created project

This commit is contained in:
Vladyslav Shatrovskyi 2024-02-10 11:05:21 +02:00
commit 2eb19bc82c
10 changed files with 1152 additions and 0 deletions

13
.env.sample Normal file
View File

@ -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

160
.gitignore vendored Normal file
View File

@ -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/

148
cancel_order.py Normal file
View File

@ -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)

121
create_order_in_crm.py Normal file
View File

@ -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)

View File

@ -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

370
get_orders.py Normal file
View File

@ -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()

169
get_ttn_number.py Normal file
View File

@ -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)

117
models.py Normal file
View File

@ -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)

18
requirements.txt Normal file
View File

@ -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

16
telegram_bot.py Normal file
View File

@ -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"),
)