export script

This commit is contained in:
2026-04-13 21:10:37 -03:00
parent 9ecc341da8
commit 236ab941a5
16 changed files with 2410 additions and 158 deletions

View File

@@ -2,15 +2,81 @@ import logging as log
from typing import Type
import requests
from sqlalchemy.orm import Session
from sqlalchemy import select, desc
from sqlalchemy import select, desc, delete
import constants
from db.helpers import get_engine
from db.models import ApiToken
from constants import *
import logging
import datetime
logger = logging.getLogger(__name__)
def get_auth_token() -> str:
delete_old_tokens()
all_tokens: list[ApiToken] = get_all_tokens()
if len(all_tokens) == 0:
return generate_token().access_token
# check if there is at least one active
active_tokens: list[ApiToken] = []
tokens_to_refresh: list[ApiToken] = []
for token in all_tokens:
if token.date_expiration_access_token > datetime.datetime.now():
active_tokens.append(token)
else:
tokens_to_refresh.append(token)
with Session(get_engine()) as session:
if len(active_tokens) > 0:
logger.info("There are active tokens. Returning first and deleting the rest")
for idx, active_token in enumerate(active_tokens):
if idx > 0:
logger.info(f"More than 1 active token. Deleting auth token.")
session.delete(active_token)
return active_tokens[0].access_token
for idx, ref_token in enumerate(tokens_to_refresh):
if idx > 0:
logger.info(f"More than 1 token to refresh. Deleting token expired in {ref_token.date_expiration_refresh_token}")
session.delete(ref_token)
session.commit()
return refresh_token(tokens_to_refresh[0]).access_token
def delete_old_tokens():
with Session(get_engine()) as session:
logger.info("Deleting old tokens.")
delete(ApiToken).where(ApiToken.date_expiration_refresh_token > (datetime.datetime.now() - datetime.timedelta(1)))
session.commit()
def refresh_token(token: ApiToken) -> ApiToken:
response = requests.get(f"{constants.api_url}/auth?refresh_token={token.refresh_token}")
refreshed_token = persist_auth_token(response.json())
with Session(get_engine()) as session:
session.delete(token)
session.commit()
return refresh_token
def generate_token(persist=False):
def get_all_tokens():
with Session(get_engine()) as session:
return session.query(ApiToken).all()
def generate_token() -> ApiToken:
body = {
"consumer_key": api_consumer_key,
"consumer_secret": api_consumer_secret,
@@ -21,30 +87,9 @@ def generate_token(persist=False):
if response.status_code in [201, 200]:
log.info('Generated tray access token: %s', response.json())
if persist:
log.info('Persisting token')
persist_auth_token(response.json())
return persist_auth_token(response.json())
return response
def refresh_access_token():
generate_token(persist=True)
token = get_last_api_token()
log.info('Refreshing token')
response = requests.get(f"{api_url}/auth?refresh_token={token.refresh_token}").json()
try:
persist_auth_token(response)
return response['access_token']
except Exception as e:
log.error(e)
return None
def persist_auth_token(api_token):
def persist_auth_token(api_token) -> ApiToken:
with Session(get_engine()) as session:
token = ApiToken(message=api_token["message"],
code=api_token["code"],
@@ -58,6 +103,8 @@ def persist_auth_token(api_token):
session.add(token)
session.commit()
return token
def delete_token(token):

View File

View File

@@ -1,109 +0,0 @@
from datetime import datetime
from sqlalchemy.orm import sessionmaker
from db.helpers import get_engine
from db.models import Order, OrderStatus, OrderProductsSold # , ProductsSold
from service.helper import parse_date, get_paged_data
class OrderService:
session = None
access_token = None
limiter = None
def __init__(self, access_token, limiter):
self.access_token = access_token
Session = sessionmaker(bind=get_engine())
self.session = Session()
self.limiter = limiter
def save_all_orders(self):
params = {
'access_token': self.access_token
}
json_orders = get_paged_data('orders', 'Orders', self.limiter, max_pages=None, params=params)
self.save_orders(json_orders)
def parse_order(self, json_order):
return Order(
id=int(json_order['id']),
status=json_order['status'],
date=parse_date(json_order['date']),
customer_id=int(json_order['customer_id']),
partial_total=float(json_order['partial_total']),
taxes=float(json_order['taxes']),
discount=float(json_order['discount']),
point_sale=json_order['point_sale'],
shipment=json_order['shipment'],
shipment_value=float(json_order['shipment_value']),
shipment_date=parse_date(json_order['shipment_date']),
store_note=json_order['store_note'],
discount_coupon=json_order['discount_coupon'],
payment_method_rate=float(json_order['payment_method_rate']),
value_1=float(json_order['value_1']),
payment_form=json_order['payment_form'],
sending_code=json_order['sending_code'],
session_id=json_order['session_id'],
total=float(json_order['total']),
payment_date=parse_date(json_order['payment_date']),
access_code=json_order['access_code'],
progressive_discount=float(json_order['progressive_discount']),
shipping_progressive_discount=float(json_order['shipping_progressive_discount']),
shipment_integrator=json_order['shipment_integrator'],
modified=datetime.strptime(json_order['modified'], '%Y-%m-%d %H:%M:%S'),
printed=bool(json_order['printed']),
interest=float(json_order['interest']),
cart_additional_values_discount=float(json_order['cart_additional_values_discount']),
cart_additional_values_increase=float(json_order['cart_additional_values_increase']),
id_quotation=json_order['id_quotation'],
estimated_delivery_date=parse_date(json_order['estimated_delivery_date']),
external_code=json_order['external_code'],
tracking_url=json_order['tracking_url'],
has_payment=bool(int(json_order['has_payment'])),
has_shipment=bool(int(json_order['has_shipment'])),
has_invoice=bool(int(json_order['has_invoice'])),
total_comission_user=float(json_order['total_comission_user']),
total_comission=float(json_order['total_comission']),
is_traceable=bool(json_order['is_traceable']),
order_status_id=int(json_order['OrderStatus']['id'])
)
def parse_order_status(self, json_order_status):
return OrderStatus(
id=int(json_order_status['id']),
default=bool(int(json_order_status['default'])),
type=json_order_status['type'],
show_backoffice=bool(int(json_order_status['show_backoffice'])),
allow_edit_order=bool(int(json_order_status['allow_edit_order'])),
status=json_order_status['status'],
description=json_order_status['description'],
background=json_order_status['background']
)
def parse_order_products_sold(self, json_order_ps, order_id):
return OrderProductsSold(
order_id=order_id,
products_sold_id=json_order_ps['id']
)
def save_orders(self, orders):
for json_order in orders:
json_order = json_order['Order']
order = self.parse_order(json_order)
if 'OrderStatus' in json_order:
json_order_status = json_order['OrderStatus']
order_status = self.parse_order_status(json_order_status)
self.session.merge(order_status)
if 'ProductsSold' in json_order:
for json_ps in json_order['ProductsSold']:
order_products_sold = self.parse_order_products_sold(json_ps, order.id)
self.session.merge(order_products_sold)
self.session.merge(order)
self.session.commit()

View File

@@ -0,0 +1,122 @@
from datetime import datetime
from sqlalchemy.orm import sessionmaker
from db.helpers import get_engine
from db.models import Order, OrderStatus, OrderProductsSold # , ProductsSold
from service.helper import parse_date, get_paged_data
from constants import api_url
import logging
import requests
from service.auth_service import get_auth_token
from pyrate_limiter import Rate, Limiter, Duration
class TrayOrderService:
access_token = None
limiter = None
logger = logging.getLogger(__name__)
def __init__(self):
self.limiter = Limiter(Rate(100, Duration.SECOND * 60), max_delay=50000)
self.access_token = get_auth_token()
def get_complete_order(self, order_id: int):
url = f"{api_url}/orders/{order_id}/complete?access_token={self.access_token}"
response = requests.get(url)
return self.parse_complete_order(response.json()['Order'])
def save_all_orders(self):
params = {
'access_token': self.access_token
}
json_orders = get_paged_data('orders', 'Orders', self.limiter, max_pages=None, params=params)
self.save_orders(json_orders)
def parse_complete_order(self, json):
order = json.get('Order')
def parse_order(self, json_order):
return Order(
id=int(json_order.get('id')),
status=json_order.get('status'),
date=parse_date(json_order.get('date')),
customer_id=int(json_order.get('customer_id')),
partial_total=float(json_order.get('partial_total')),
taxes=float(json_order.get('taxes')),
discount=float(json_order.get('discount')),
point_sale=json_order.get('point_sale'),
shipment=json_order.get('shipment'),
shipment_value=float(json_order.get('shipment_value')),
shipment_date=parse_date(json_order.get('shipment_date')),
store_note=json_order.get('store_note'),
discount_coupon=json_order.get('discount_coupon'),
payment_method_rate=float(json_order.get('payment_method_rate')),
value_1=float(json_order.get('value_1')),
payment_form=json_order.get('payment_form'),
sending_code=json_order.get('sending_code'),
session_id=json_order.get('session_id'),
total=float(json_order.get('total')),
payment_date=parse_date(json_order.get('payment_date')),
access_code=json_order.get('access_code'),
#progressive_discount=float(json_order.get('progressive_discount')),
#shipping_progressive_discount=float(json_order.get('shipping_progressive_discount')),
shipment_integrator=json_order.get('shipment_integrator'),
modified=datetime.strptime(json_order.get('modified'), '%Y-%m-%d %H:%M:%S'),
printed=bool(json_order.get('printed')),
#interest=float(json_order.get('interest')),
#cart_additional_values_discount=float(json_order.get('cart_additional_values_discount')),
#cart_additional_values_increase=float(json_order.get('cart_additional_values_increase')),
id_quotation=json_order.get('id_quotation'),
estimated_delivery_date=parse_date(json_order.get('estimated_delivery_date')),
external_code=json_order.get('external_code'),
tracking_url=json_order.get('tracking_url'),
has_payment=bool(int(json_order.get('has_payment'))),
has_shipment=bool(int(json_order.get('has_shipment'))),
has_invoice=bool(int(json_order.get('has_invoice'))),
#total_comission_user=float(json_order.get('total_comission_user')),
#total_comission=float(json_order.get('total_comission')),
is_traceable=bool(json_order.get('is_traceable')),
#order_status_id=int(json_order.get('OrderStatus')['id'])
)
def parse_order_status(self, json_order_status):
return OrderStatus(
id=int(json_order_status['id']),
default=bool(int(json_order_status['default'])),
type=json_order_status['type'],
show_backoffice=bool(int(json_order_status['show_backoffice'])),
allow_edit_order=bool(int(json_order_status['allow_edit_order'])),
status=json_order_status['status'],
description=json_order_status['description'],
background=json_order_status['background']
)
def parse_order_products_sold(self, json_order_ps, order_id):
return OrderProductsSold(
order_id=order_id,
products_sold_id=json_order_ps['id']
)
def save_orders(self, orders):
for json_order in orders:
json_order = json_order['Order']
order = self.parse_order(json_order)
if 'OrderStatus' in json_order:
json_order_status = json_order['OrderStatus']
order_status = self.parse_order_status(json_order_status)
self.session.merge(order_status)
if 'ProductsSold' in json_order:
for json_ps in json_order['ProductsSold']:
order_products_sold = self.parse_order_products_sold(json_ps, order.id)
self.session.merge(order_products_sold)
self.session.merge(order)
self.session.commit()

View File

@@ -0,0 +1,37 @@
from db.helpers import get_engine
from sqlalchemy.orm import Session
from db.models import TrayWebhook
import json
import logging
from service.tray_order_service import TrayOrderService
logger = logging.getLogger(__name__)
def process_webhook(body: dict):
save_webhook(body)
act = body['act']
order_id = body['scope_id']
seller_id = body['seller_id']
if seller_id != "1018776":
logger.info(f"seller_id: {seller_id}. Exiting.")
return 400
order_service = TrayOrderService()
if act == 'insert' or act == 'update':
order = order_service.get_complete_order(order_id)
logger.info(order)
return order
return 400
def save_webhook(body: dict):
with Session(get_engine()) as session:
webhook = TrayWebhook(json.dumps(body))
session.add(webhook)
session.commit()