🎉 Initial commit - Hazard Odoo 16 project
- Custom modules: hazard_shopify, hazard_inventory_report, hazard_website - Third-party modules: bi_sql_editor, query_deluxe, sql_request_abstract, l10n_mx_sat_sync_itadmin_ee - Docker setup: Odoo 16 + PostgreSQL 17 - Utility scripts: backup_hazard.sh, update_module.py - Agent configuration: .agents/AGENTS.md - Security: Enterprise modules, credentials, backups and production data excluded via .gitignore
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import csv
|
||||
from collections import defaultdict
|
||||
import xmlrpc.client
|
||||
import requests
|
||||
|
||||
ODOO_URL = 'http://localhost:16001'
|
||||
ODOO_DB = 'hazard_new'
|
||||
ODOO_USER = 'admin'
|
||||
ODOO_PASS = 'admin'
|
||||
|
||||
def get_shopify_credentials():
|
||||
common = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/common')
|
||||
uid = common.authenticate(ODOO_DB, ODOO_USER, ODOO_PASS, {})
|
||||
models = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/object')
|
||||
config_ids = models.execute_kw(ODOO_DB, uid, ODOO_PASS, 'shopify.config', 'search', [[]])
|
||||
config = models.execute_kw(ODOO_DB, uid, ODOO_PASS, 'shopify.config', 'read', [config_ids[0]], {'fields': ['shop_url', 'access_token']})[0]
|
||||
return config.get('shop_url'), config.get('access_token')
|
||||
|
||||
def get_padel_skus():
|
||||
shop_url, access_token = get_shopify_credentials()
|
||||
query = """
|
||||
{
|
||||
collection(id: "gid://shopify/Collection/487990952129") {
|
||||
products(first: 250) {
|
||||
edges { node { legacyResourceId } }
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
url = f"https://{shop_url}/admin/api/2023-10/graphql.json"
|
||||
headers = {'X-Shopify-Access-Token': access_token, 'Content-Type': 'application/json'}
|
||||
resp = requests.post(url, headers=headers, json={'query': query})
|
||||
product_ids = [str(edge['node']['legacyResourceId']) for edge in resp.json()['data']['collection']['products']['edges']]
|
||||
|
||||
skus = set()
|
||||
url_rest = f"https://{shop_url}/admin/api/2023-10/products.json"
|
||||
for pid in product_ids:
|
||||
r = requests.get(f"{url_rest}?ids={pid}", headers={'X-Shopify-Access-Token': access_token})
|
||||
for p in r.json().get('products', []):
|
||||
for v in p.get('variants', []):
|
||||
skus.add(v.get('sku'))
|
||||
return skus
|
||||
|
||||
padel_skus = get_padel_skus()
|
||||
filename = 'orders_export_1 (8)(1).csv'
|
||||
|
||||
total_gross = 0
|
||||
total_net = 0
|
||||
channels = defaultdict(float)
|
||||
draft_count = 0
|
||||
web_count = 0
|
||||
pos_count = 0
|
||||
|
||||
with open(filename, 'r', encoding='utf-8-sig') as f:
|
||||
reader = csv.DictReader(f)
|
||||
for row in reader:
|
||||
sku = row.get('Lineitem sku', '')
|
||||
if sku in padel_skus:
|
||||
# count channels
|
||||
source = row.get('Source', 'unknown')
|
||||
if 'draft' in source: draft_count += 1
|
||||
elif 'web' in source: web_count += 1
|
||||
elif 'pos' in source: pos_count += 1
|
||||
|
||||
if row.get('Financial Status') in ['paid', 'partially_refunded', 'refunded']:
|
||||
price = float(row.get('Lineitem price') or 0)
|
||||
qty = int(row.get('Lineitem quantity') or 0)
|
||||
discount = float(row.get('Lineitem discount') or 0)
|
||||
|
||||
gross = price * qty
|
||||
net = gross - discount # CSV doesn't clearly show line-item refunds
|
||||
|
||||
total_gross += gross
|
||||
total_net += net
|
||||
channels[source] += net
|
||||
|
||||
print(f"--- ANALISIS DEL CSV (Pedidos Exportados) ---")
|
||||
print(f"Total Gross (sin descuento): {total_gross}")
|
||||
print(f"Total Net (con descuento, sin reembolso real): {total_net}")
|
||||
print("Por canal en el CSV:")
|
||||
for c, v in channels.items():
|
||||
print(f" {c}: {v}")
|
||||
print(f"Apariciones por canal: Web={web_count}, POS={pos_count}, Draft={draft_count}")
|
||||
Reference in New Issue
Block a user