created project
This commit is contained in:
commit
2eb19bc82c
|
@ -0,0 +1,13 @@
|
|||
LOGIN=LOGIN
|
||||
EPIC_PASSWORD=EPIC_PASSWORD
|
||||
|
||||
TGAPI_KEY=TGAPI_KEY
|
||||
TGCHAT_ID=TGCHAT_ID
|
||||
|
||||
DATABASE=DATABASE
|
||||
DB_HOST=DB_HOST
|
||||
USERS=USERS
|
||||
PASSW=PASSW
|
||||
|
||||
CRM_API_KEY=CRM_API_KEY
|
||||
PAYMENT_METHOD_ID=PAYMENT_METHOD_ID
|
|
@ -0,0 +1,160 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
|
@ -0,0 +1,148 @@
|
|||
import requests
|
||||
from create_order_in_crm import BASE_URL, CRM_API_KEY
|
||||
from get_order_number_from_crm_by_id import get_order_number
|
||||
from get_orders import get_auth_token, LOGIN, PASSWORD
|
||||
from models import EpicenterOrder, CancelReason, db
|
||||
|
||||
|
||||
def get_cancel_reason_name(reason_ukr: str):
|
||||
try:
|
||||
# Connect to the database
|
||||
db.connect()
|
||||
|
||||
# Query the CancelReason table
|
||||
cancel_reason = (
|
||||
CancelReason.select()
|
||||
.where(CancelReason.ukr_description.contains(reason_ukr))
|
||||
.first()
|
||||
)
|
||||
|
||||
# Close the database connection
|
||||
db.close()
|
||||
|
||||
if cancel_reason:
|
||||
return cancel_reason.name
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_cancel_reason_from_crm(order_id: int):
|
||||
|
||||
order_url = BASE_URL + f"order/{order_id}"
|
||||
|
||||
headers = {
|
||||
"accept": "application/json",
|
||||
"Authorization": f"Bearer {CRM_API_KEY}",
|
||||
}
|
||||
|
||||
order_info_response = requests.get(
|
||||
order_url, headers=headers, params={"include": "custom_fields"}
|
||||
)
|
||||
|
||||
# Check if request was successful
|
||||
if order_info_response.status_code == 200:
|
||||
order_info = order_info_response.json() # Convert response to JSON
|
||||
custom_fields = order_info.get("custom_fields", []) # Get custom_fields
|
||||
|
||||
target_uuid = "OR_1002"
|
||||
|
||||
# Используем list comprehension для поиска нужного словаря
|
||||
matching_dict = next(
|
||||
(item for item in custom_fields if item.get("uuid") == target_uuid), None
|
||||
)
|
||||
|
||||
# Если словарь найден, выводим значение 'value'
|
||||
if matching_dict:
|
||||
methodpay = matching_dict.get("value")
|
||||
return methodpay[0]
|
||||
else:
|
||||
print(f"Не найден словарь с uuid")
|
||||
else:
|
||||
print(
|
||||
f"Failed to retrieve order information. Status code: {order_info_response.status_code}"
|
||||
)
|
||||
|
||||
|
||||
def cancel_order(order_number: int, reason: str):
|
||||
|
||||
order = EpicenterOrder.get(EpicenterOrder.order_number == order_number)
|
||||
order_id = order.order_id
|
||||
auth_token = get_auth_token(LOGIN, PASSWORD)
|
||||
reason_to_cancel = get_cancel_reason_name(reason)
|
||||
|
||||
first_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"access-control-request-headers": "authorization,content-type",
|
||||
"access-control-request-method": "POST",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
first_response = requests.options(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/canceled",
|
||||
headers=first_headers,
|
||||
)
|
||||
|
||||
second_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
"content-type": "application/json",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
json_data = {
|
||||
"reason_code": reason_to_cancel,
|
||||
"comment": None,
|
||||
"translationKey": f"order.{reason_to_cancel}",
|
||||
"number": "",
|
||||
"provider": "",
|
||||
}
|
||||
|
||||
second_response = requests.post(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/canceled",
|
||||
headers=second_headers,
|
||||
json=json_data,
|
||||
)
|
||||
|
||||
|
||||
def change_status_in_db(order_number: int):
|
||||
|
||||
with db.atomic():
|
||||
order = EpicenterOrder.get(EpicenterOrder.order_number == order_number)
|
||||
order.order_status = "canceled"
|
||||
order.save()
|
||||
print(f"Status for order {order_number} changed to canceled.")
|
||||
|
||||
|
||||
def cancel_order_and_change_status(order_id: int):
|
||||
|
||||
order_number = get_order_number(order_id)
|
||||
reason = get_cancel_reason_from_crm(order_id)
|
||||
|
||||
print(order_number)
|
||||
print(reason)
|
||||
|
||||
cancel_order(order_number, reason=reason)
|
||||
change_status_in_db(order_number)
|
||||
|
||||
|
||||
# cancel_order_and_change_status(171)
|
|
@ -0,0 +1,121 @@
|
|||
import requests
|
||||
import os
|
||||
from models import EpicenterOrder, EpicenterOrderProduct
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
BASE_URL = "https://openapi.keycrm.app/v1/"
|
||||
CRM_API_KEY = os.getenv("CRM_API_KEY")
|
||||
PAYMENT_METHOD_ID = os.getenv("PAYMENT_METHOD_ID")
|
||||
|
||||
|
||||
def create_order(
|
||||
order_number: str,
|
||||
order_creation_date: str,
|
||||
full_name: str,
|
||||
email: str,
|
||||
phone_number: str,
|
||||
city: str,
|
||||
delivery_address: str,
|
||||
delivery_post_number: str,
|
||||
delivery_ref: str,
|
||||
products: list,
|
||||
amount: float,
|
||||
):
|
||||
create_order_url = BASE_URL + "order/"
|
||||
|
||||
headers = {
|
||||
"accept": "application/json",
|
||||
"Authorization": f"Bearer {CRM_API_KEY}",
|
||||
}
|
||||
|
||||
json_data = {
|
||||
"source_id": 1,
|
||||
"source_uuid": order_number,
|
||||
"ordered_at": order_creation_date,
|
||||
"buyer": {
|
||||
"full_name": full_name,
|
||||
"email": email,
|
||||
"phone": phone_number,
|
||||
},
|
||||
"shipping": {
|
||||
"delivery_service_id": 1,
|
||||
"shipping_service": "Нова Пошта",
|
||||
"shipping_address_city": city,
|
||||
"shipping_address_country": "Ukraine",
|
||||
"shipping_secondary_line": delivery_address,
|
||||
"shipping_receive_point": delivery_post_number,
|
||||
"recipient_full_name": full_name,
|
||||
"recipient_phone": phone_number,
|
||||
"warehouse_ref": delivery_ref,
|
||||
},
|
||||
"products": products,
|
||||
"payments": [
|
||||
{
|
||||
"status": "not_paid",
|
||||
"payment_method_id": PAYMENT_METHOD_ID,
|
||||
"amount": amount,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
response = requests.post(create_order_url, headers=headers, json=json_data)
|
||||
print(response.text)
|
||||
|
||||
|
||||
def create_from_db(order_number: int):
|
||||
|
||||
orders_query = EpicenterOrder.select().where(
|
||||
EpicenterOrder.order_number == order_number
|
||||
)
|
||||
|
||||
# print(orders_query)
|
||||
|
||||
for order_info in orders_query:
|
||||
# extract order information
|
||||
order_number = order_info.order_number
|
||||
order_creation_date = order_info.order_creation_date.strftime(
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
full_name = order_info.full_name
|
||||
email = order_info.email
|
||||
phone_number = order_info.phone_number
|
||||
delivery_address = order_info.delivery_address
|
||||
delivery_post_number = order_info.delivery_post_number
|
||||
delivery_ref = order_info.delivery_ref
|
||||
settlement = order_info.settlement
|
||||
amount = float(order_info.amount)
|
||||
|
||||
# print(amount)
|
||||
|
||||
# extract products associated with the order
|
||||
products = []
|
||||
for order_product in EpicenterOrderProduct.select().where(
|
||||
EpicenterOrderProduct.epicenter_order == order_info
|
||||
):
|
||||
product_info = {
|
||||
"name": order_product.product.name,
|
||||
"sku": order_product.product.sku,
|
||||
"price": float(order_product.product.price),
|
||||
"quantity": order_product.quantity,
|
||||
}
|
||||
products.append(product_info)
|
||||
print(product_info)
|
||||
|
||||
create_order(
|
||||
order_number=order_number,
|
||||
order_creation_date=order_creation_date,
|
||||
full_name=full_name,
|
||||
email=email,
|
||||
phone_number=phone_number,
|
||||
delivery_post_number=delivery_post_number,
|
||||
delivery_ref=delivery_ref,
|
||||
delivery_address=delivery_address,
|
||||
city=settlement,
|
||||
products=products,
|
||||
amount=amount,
|
||||
)
|
||||
|
||||
|
||||
# create_from_db(32078457)
|
|
@ -0,0 +1,20 @@
|
|||
import requests
|
||||
|
||||
from create_order_in_crm import BASE_URL, CRM_API_KEY
|
||||
|
||||
|
||||
def get_order_number(order_id: int):
|
||||
order_url = BASE_URL + f"order/{order_id}"
|
||||
|
||||
headers = {
|
||||
"accept": "application/json",
|
||||
"Authorization": f"Bearer {CRM_API_KEY}",
|
||||
}
|
||||
|
||||
order_info_response = requests.get(
|
||||
order_url, headers=headers, params={"include": "custom_fields"}
|
||||
)
|
||||
|
||||
order_info = order_info_response.json()
|
||||
order_number = order_info.get("source_uuid")
|
||||
return order_number
|
|
@ -0,0 +1,370 @@
|
|||
import time
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from datetime import datetime
|
||||
from telegram_bot import order_epicenter_error
|
||||
from models import db, EpicenterOrder, Product, EpicenterOrderProduct
|
||||
|
||||
|
||||
load_dotenv()
|
||||
|
||||
LOGIN = os.getenv("LOGIN")
|
||||
PASSWORD = os.getenv("EPIC_PASSWORD")
|
||||
|
||||
|
||||
def get_auth_token(login: str, password: str) -> str:
|
||||
|
||||
headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "application/json",
|
||||
"accept-language": "ru",
|
||||
"content-type": "application/json",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Linux"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
json_data = {
|
||||
"login": login,
|
||||
"password": password,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
"https://core-api.epicentrm.cloud/v1/users/login",
|
||||
headers=headers,
|
||||
json=json_data,
|
||||
)
|
||||
|
||||
auth_token = response.json()["token"]["auth"]
|
||||
|
||||
return auth_token
|
||||
|
||||
|
||||
def is_new_order(order_id: str, auth_token: str) -> bool:
|
||||
headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "application/json",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
response = requests.get(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
data = json.loads(response.text)
|
||||
|
||||
if (
|
||||
data["statusCode"] == "new"
|
||||
and data["statusCode"] != "canceled"
|
||||
and data["statusCode"] != "sent"
|
||||
) and data["statusCode"] != "confirmed":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def activate_order(order_id: str, auth_token: str):
|
||||
|
||||
first_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"access-control-request-headers": "authorization,content-type",
|
||||
"access-control-request-method": "POST",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
requests.options(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/confirmed_by_merchant",
|
||||
headers=first_headers,
|
||||
)
|
||||
|
||||
second_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
# 'content-length': '0',
|
||||
"content-type": "application/json",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
requests.post(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}"
|
||||
f"/change-status/to/confirmed_by_merchant",
|
||||
headers=second_headers,
|
||||
)
|
||||
|
||||
|
||||
def get_delivery_info(
|
||||
shipment_settlementId: str, shipment_officeId: str, auth_token: str
|
||||
):
|
||||
|
||||
headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "application/json",
|
||||
"accept-language": "ru",
|
||||
"authorization": f"Bearer " f"{auth_token}",
|
||||
"if-none-match": 'W/"196-wqlAXM70iFf1sVnvW/hGnongIL0"',
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
response = requests.get(
|
||||
f"https://core-api.epicentrm.cloud/v2/deliveries/nova_poshta/settlements/{shipment_settlementId}"
|
||||
f"/offices/{shipment_officeId}",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
shipment_data = json.loads(response.text)
|
||||
|
||||
return shipment_data["title"]
|
||||
|
||||
|
||||
def get_first_page_order_ids(auth_token: str):
|
||||
headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "application/json",
|
||||
"accept-language": "ru",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
"if-none-match": 'W/"6e25-Lp/88DlhwX6wEIzxPDq/6WiYQf8"',
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Linux"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
params = {
|
||||
"offset": "0",
|
||||
"limit": "10",
|
||||
}
|
||||
|
||||
response = requests.get(
|
||||
"https://core-api.epicentrm.cloud/v2/oms/orders", params=params, headers=headers
|
||||
)
|
||||
|
||||
data = json.loads(response.text)
|
||||
|
||||
order_ids = [order["id"] for order in data["items"]]
|
||||
|
||||
return order_ids
|
||||
|
||||
|
||||
def get_order_info(order_id: str, auth_token: str):
|
||||
headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "application/json",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
"if-none-match": 'W/"4ced-XZFKegDeJ8gOKv2D+e5bORHnOoM"',
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
response = requests.get(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
order = json.loads(response.text)
|
||||
products = []
|
||||
|
||||
if is_new_order(order_id, auth_token):
|
||||
activate_order(order_id, auth_token)
|
||||
time.sleep(10)
|
||||
return get_order_info(order_id, auth_token)
|
||||
else:
|
||||
# get product info
|
||||
for item in range(len(order["items"])):
|
||||
title = order["items"][item]["title"]
|
||||
sku = order["items"][item]["sku"]
|
||||
product_price = order["items"][item]["price"]
|
||||
quantity = order["items"][item]["quantity"]
|
||||
products.append(
|
||||
{
|
||||
"name": title,
|
||||
"sku": sku,
|
||||
"price": product_price,
|
||||
"quantity": quantity,
|
||||
}
|
||||
)
|
||||
|
||||
# User info
|
||||
first_name = order["address"]["firstName"]
|
||||
last_name = order["address"]["lastName"]
|
||||
patronymic = order["address"]["patronymic"]
|
||||
email = order["address"]["email"]
|
||||
phone_number = order["address"]["phone"]
|
||||
|
||||
# Delivery info
|
||||
delivery_info = get_delivery_info(
|
||||
order["address"]["shipment"]["settlementId"],
|
||||
order["address"]["shipment"]["officeId"],
|
||||
auth_token,
|
||||
)
|
||||
delivery_ref = order["address"]["shipment"]["officeId"]
|
||||
settlement = order["settlement"]["title"]
|
||||
|
||||
# Order info
|
||||
order_number = order["number"]
|
||||
order_status = order["statusCode"]
|
||||
created_at = order["createdAt"]
|
||||
subtotal = order["subtotal"]
|
||||
|
||||
order_data = {
|
||||
"first_name": first_name,
|
||||
"last_name": last_name,
|
||||
"patronymic": patronymic,
|
||||
"email": email,
|
||||
"phone_number": phone_number,
|
||||
"delivery_info": delivery_info,
|
||||
"delivery_ref": delivery_ref,
|
||||
"settlement": settlement,
|
||||
"order_number": order_number,
|
||||
"order_id": order_id,
|
||||
"products": products,
|
||||
"order_status": order_status,
|
||||
"created_at": created_at,
|
||||
"subtotal": subtotal,
|
||||
}
|
||||
|
||||
return order_data
|
||||
|
||||
|
||||
def insert_order_info(order_info):
|
||||
with db.atomic():
|
||||
# Insert EpicenterOrder
|
||||
epicenter_model = EpicenterOrder.create(
|
||||
order_number=order_info["order_number"],
|
||||
order_id=order_info["order_id"],
|
||||
order_status=order_info["order_status"],
|
||||
order_creation_date=datetime.strptime(
|
||||
order_info["created_at"], "%Y-%m-%dT%H:%M:%S%z"
|
||||
).strftime("%Y-%m-%d %H:%M:%S"),
|
||||
full_name=(
|
||||
f"{order_info['first_name']} {order_info['last_name']} "
|
||||
f"{order_info['patronymic'] if order_info['patronymic'] else ''}"
|
||||
),
|
||||
email=order_info["email"],
|
||||
phone_number=order_info["phone_number"],
|
||||
delivery_address=", ".join(order_info["delivery_info"].split(",")[1:]),
|
||||
delivery_post_number=f"Склад {order_info['delivery_info'].split(',')[0]}".replace(
|
||||
"№", "#"
|
||||
).rstrip(),
|
||||
delivery_ref=order_info["delivery_ref"],
|
||||
settlement=order_info["settlement"],
|
||||
amount=order_info["subtotal"],
|
||||
)
|
||||
|
||||
# Insert or update products and associate them with the order
|
||||
product_records = []
|
||||
for product_data in order_info["products"]:
|
||||
sku = product_data["sku"]
|
||||
existing_product = Product.select().where(Product.sku == sku).first()
|
||||
if existing_product:
|
||||
# Update existing product
|
||||
existing_product.price = product_data["price"]
|
||||
existing_product.save()
|
||||
else:
|
||||
# Create new product
|
||||
existing_product = Product.create(
|
||||
name=product_data["name"], sku=sku, price=product_data["price"]
|
||||
)
|
||||
product_records.append(existing_product)
|
||||
# Associate product with the order and specify quantity
|
||||
EpicenterOrderProduct.create(
|
||||
epicenter_order=epicenter_model,
|
||||
product=existing_product,
|
||||
quantity=product_data["quantity"],
|
||||
)
|
||||
|
||||
|
||||
def write_orders(auth_token: str):
|
||||
|
||||
# get order_ids from first 10 orders
|
||||
order_ids = get_first_page_order_ids(auth_token)
|
||||
|
||||
for order_id in order_ids:
|
||||
print(order_id)
|
||||
|
||||
existing_order = (
|
||||
EpicenterOrder.select().where(EpicenterOrder.order_id == order_id).first()
|
||||
)
|
||||
|
||||
if existing_order:
|
||||
continue
|
||||
|
||||
order_info = get_order_info(order_id=order_id, auth_token=auth_token)
|
||||
insert_order_info(order_info=order_info)
|
||||
|
||||
db.close()
|
||||
# request.get()url Alex send order_number
|
||||
|
||||
print("DONE")
|
||||
|
||||
|
||||
def run_all():
|
||||
try:
|
||||
while True:
|
||||
auth_token = get_auth_token(LOGIN, PASSWORD)
|
||||
write_orders(auth_token=auth_token)
|
||||
time.sleep(1800)
|
||||
except Exception as e:
|
||||
# print(e.with_traceback())
|
||||
exception_text = f"🆘An error in epicenter orders script. Please change something!🆘\n Exception: {e}"
|
||||
order_epicenter_error(exception_text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_all()
|
|
@ -0,0 +1,169 @@
|
|||
import requests
|
||||
|
||||
from get_order_number_from_crm_by_id import get_order_number
|
||||
from create_order_in_crm import BASE_URL, CRM_API_KEY
|
||||
from get_orders import get_auth_token, LOGIN, PASSWORD
|
||||
from models import EpicenterOrder, db
|
||||
|
||||
|
||||
def get_ttn_number_from_order(order_id: int):
|
||||
order_number = get_order_number(order_id)
|
||||
|
||||
order = (
|
||||
EpicenterOrder.select()
|
||||
.where(EpicenterOrder.order_number == order_number)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not order:
|
||||
print(f"Order with order number {order_number} not found.")
|
||||
|
||||
order_url = BASE_URL + f"order/{order_id}/"
|
||||
|
||||
print(order_id, order_url)
|
||||
|
||||
headers = {
|
||||
"accept": "application/json",
|
||||
"Authorization": f"Bearer {CRM_API_KEY}",
|
||||
}
|
||||
|
||||
params = {
|
||||
"include": "shipping",
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(order_url, headers=headers, params=params)
|
||||
|
||||
data = response.json()
|
||||
tracking_code = data["shipping"].get("tracking_code")
|
||||
return tracking_code
|
||||
|
||||
except Exception as e:
|
||||
print(f"An unexpected error occurred: {e}")
|
||||
|
||||
|
||||
|
||||
def change_status_to_confirmed(order_number: int, auth_token: str):
|
||||
order = (
|
||||
EpicenterOrder.select()
|
||||
.where(EpicenterOrder.order_number == order_number)
|
||||
.first()
|
||||
)
|
||||
order_id = order.order_id
|
||||
order.status = "confirmed"
|
||||
|
||||
first_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"access-control-request-headers": "authorization,content-type",
|
||||
"access-control-request-method": "POST",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
first_response = requests.options(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/confirmed",
|
||||
headers=first_headers,
|
||||
)
|
||||
|
||||
second_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
# 'content-length': '0',
|
||||
"content-type": "application/json",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
second_response = requests.post(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/confirmed",
|
||||
headers=second_headers,
|
||||
)
|
||||
|
||||
|
||||
def update_status_to_sent(order_number: int, order_id_crm: int):
|
||||
|
||||
auth_token = get_auth_token(LOGIN, PASSWORD)
|
||||
|
||||
with db.transaction():
|
||||
change_status_to_confirmed(order_number, auth_token)
|
||||
order = (
|
||||
EpicenterOrder.select()
|
||||
.where(EpicenterOrder.order_number == order_number)
|
||||
.first()
|
||||
)
|
||||
order_id = order.order_id
|
||||
order.order_status = "sent"
|
||||
|
||||
ttn_number = get_ttn_number_from_order(order_id_crm)
|
||||
order.ttn = ttn_number
|
||||
order.save()
|
||||
|
||||
first_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"access-control-request-headers": "authorization,content-type",
|
||||
"access-control-request-method": "POST",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
first_response = requests.options(
|
||||
"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/sent",
|
||||
headers=first_headers,
|
||||
)
|
||||
|
||||
second_headers = {
|
||||
"authority": "core-api.epicentrm.cloud",
|
||||
"accept": "*/*",
|
||||
"accept-language": "en-US,en;q=0.9,ru;q=0.8,ru-RU;q=0.7",
|
||||
"authorization": f"Bearer {auth_token}",
|
||||
"content-type": "application/json",
|
||||
"origin": "https://admin.epicentrm.com.ua",
|
||||
"referer": "https://admin.epicentrm.com.ua/",
|
||||
"sec-ch-ua": '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"',
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
json_data = {
|
||||
"reason_code": "",
|
||||
"comment": None,
|
||||
"translationKey": "",
|
||||
"number": ttn_number,
|
||||
"provider": "nova_poshta",
|
||||
}
|
||||
|
||||
second_response = requests.post(
|
||||
f"https://core-api.epicentrm.cloud/v2/oms/orders/{order_id}/change-status/to/sent",
|
||||
headers=second_headers,
|
||||
json=json_data,
|
||||
)
|
||||
|
||||
|
||||
def get_and_write_ttn_number(order_id_crm: int):
|
||||
order_number = get_order_number(order_id=order_id_crm)
|
||||
update_status_to_sent(order_number, order_id_crm)
|
|
@ -0,0 +1,117 @@
|
|||
import os
|
||||
from dotenv import load_dotenv
|
||||
from peewee import *
|
||||
|
||||
|
||||
load_dotenv()
|
||||
|
||||
DATABASE = os.getenv("DATABASE")
|
||||
DB_HOST = os.getenv("DB_HOST")
|
||||
USERS = os.getenv("USERS")
|
||||
PASSW = os.getenv("PASSW")
|
||||
|
||||
|
||||
db = MySQLDatabase(
|
||||
database=DATABASE, user=USERS, password=PASSW, host=DB_HOST, port=3306
|
||||
)
|
||||
|
||||
|
||||
class Product(Model):
|
||||
product_id = AutoField(primary_key=True)
|
||||
name = CharField()
|
||||
sku = CharField(unique=True)
|
||||
price = DecimalField()
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class EpicenterOrder(Model):
|
||||
order_number = CharField(unique=True)
|
||||
order_id = CharField(unique=True)
|
||||
products = ManyToManyField(Product, backref="epicenter_orders")
|
||||
order_status = CharField()
|
||||
order_creation_date = DateTimeField()
|
||||
full_name = CharField()
|
||||
email = CharField()
|
||||
phone_number = CharField()
|
||||
delivery_address = CharField()
|
||||
delivery_post_number = CharField()
|
||||
delivery_ref = CharField()
|
||||
settlement = CharField()
|
||||
amount = DecimalField()
|
||||
ttn = CharField(null=True)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class EpicenterOrderProduct(Model):
|
||||
epicenter_order = ForeignKeyField(EpicenterOrder)
|
||||
product = ForeignKeyField(Product)
|
||||
quantity = IntegerField()
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class CancelReason(Model):
|
||||
name = CharField()
|
||||
ukr_description = CharField()
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
# db.create_tables([EpicenterOrder, Product, EpicenterOrderProduct, CancelReason])
|
||||
# db.close()
|
||||
|
||||
|
||||
# run when you lost cancelreason table
|
||||
def insert_cancel_reasons(reasons_dict):
|
||||
try:
|
||||
# Connect to the database
|
||||
db.connect()
|
||||
|
||||
# Create the table if it doesn't exist
|
||||
db.create_tables([CancelReason])
|
||||
|
||||
# Insert data into the table
|
||||
with db.atomic():
|
||||
for key, value in reasons_dict.items():
|
||||
CancelReason.create(name=key, ukr_description=value)
|
||||
|
||||
# Close the database connection
|
||||
db.close()
|
||||
print("Data insertion successful.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
|
||||
# customer_cancel_reasons = {
|
||||
# "customer_account_payment_with_vat_is_preferred": "Хотів сплатити на Р/Р (з ПДВ)",
|
||||
# "customer_account_payment_without_vat_is_preferred": "Хотів сплатити на Р/Р (без ПДВ)",
|
||||
# "customer_bought_elsewhere_as_a_gift": "Купив в іншому місці/подарували",
|
||||
# "customer_canceled_at_delivery_office": "Відмова у відділенні",
|
||||
# "customer_changed_mind": "Потрібна була консультація",
|
||||
# "customer_credit_card_payment_is_preferred": "Хотів сплатити карткою",
|
||||
# "customer_delivery_speed_too_slow": "Не влаштували терміни доставки",
|
||||
# "customer_dissatisfied_with_the_shipping_cost": "Не влаштувала ціна доставки",
|
||||
# "customer_epic_warranty_is_preferred": "Вже купив в Епіцентрі",
|
||||
# "customer_found_cheaper": "Не влаштувала ціна товару",
|
||||
# "customer_get_loan_is_preferred_payment_type": "Хотів оформити розтермінування/кредит",
|
||||
# "customer_long_merchant_confirmation": "Тривале підтвердження",
|
||||
# "customer_no_payment": "Не вдалося оплатити на сайті",
|
||||
# "customer_not_timely_confirmation_of_the_availability_of_goods": "Немає в наявності",
|
||||
# "customer_order_duplicate": "Помилково оформив кілька замовлень",
|
||||
# "customer_prepayment_required": "Потрібна передоплата",
|
||||
# "customer_price_obsoleted": "Ціна неактуальна",
|
||||
# "customer_product_characteristics_are_not_suitable": "Товар не підходить за характеристиками",
|
||||
# "customer_requires_advance_payment_which_is_not_indicated_on_the_website": "Вимагають передоплату, про яку не інформує сайт",
|
||||
# "customer_several_packages_delivery_payment_is_not_suitable": "Хотів доставку одним замовленням",
|
||||
# "customer_shop_pickup_preferred_delivery_price_too_high": "Хотів забрати з пунктів самовивозу",
|
||||
# "customer_test": "Тест",
|
||||
# }
|
||||
|
||||
# insert_cancel_reasons(customer_cancel_reasons)
|
|
@ -0,0 +1,18 @@
|
|||
black==24.1.1
|
||||
certifi==2024.2.2
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
colorama==0.4.6
|
||||
idna==3.6
|
||||
mypy-extensions==1.0.0
|
||||
mysql-connector-python==8.3.0
|
||||
packaging==23.2
|
||||
pathspec==0.12.1
|
||||
peewee==3.17.0
|
||||
platformdirs==4.2.0
|
||||
PyMySQL==1.1.0
|
||||
python-dotenv==1.0.1
|
||||
requests==2.31.0
|
||||
tomli==2.0.1
|
||||
typing_extensions==4.9.0
|
||||
urllib3==2.2.0
|
|
@ -0,0 +1,16 @@
|
|||
import os
|
||||
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
api_key = os.getenv("TGAPI_KEY")
|
||||
chat = os.getenv("TGCHAT_ID")
|
||||
|
||||
|
||||
def order_epicenter_error(text):
|
||||
answer = requests.get(
|
||||
"https://api.telegram.org/bot{}/sendMessage".format(api_key),
|
||||
params=dict(chat_id=chat, text=str(text), parse_mode="HTML"),
|
||||
)
|
Loading…
Reference in New Issue