Files
gomag-vending/scripts/analyze_billing.py
Claude Agent 3d73d9e422 add: scripts for invoice-order matching and SKU discovery
Analysis scripts to match GoMag orders with Oracle invoices by
date/client/total, then compare line items by price to discover
SKU → id_articol mappings. Generates SQL for nom_articole codmat
updates and CSV for ARTICOLE_TERTI repackaging/set mappings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:01:51 +00:00

180 lines
6.9 KiB
Python

"""Analyze billing vs shipping patterns across all GoMag orders"""
import sys, json, httpx
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
API_KEY = '4c5e46df8f6c4f054fe2787de7a13d4a'
API_SHOP = 'https://coffeepoint.ro'
API_URL = 'https://api.gomag.ro/api/v1/order/read/json'
headers = {
'Apikey': API_KEY,
'ApiShop': API_SHOP,
'User-Agent': 'Mozilla/5.0',
'Content-Type': 'application/json',
}
params = {'startDate': '2026-03-08', 'page': 1, 'limit': 250}
all_orders = []
for page in range(1, 20):
params['page'] = page
resp = httpx.get(API_URL, headers=headers, params=params, timeout=60)
data = resp.json()
pages = data.get('pages', 1)
orders_raw = data.get('orders', {})
if isinstance(orders_raw, dict):
for key, order in orders_raw.items():
if isinstance(order, dict):
all_orders.append(order)
print(f"Page {page}/{pages}: {len(orders_raw)} orders")
if page >= pages:
break
print(f"\nTotal orders: {len(all_orders)}")
# Analyze patterns
company_orders = []
person_orders = []
diff_person_orders = [] # shipping != billing person
for order in all_orders:
billing = order.get('billing', {}) or {}
shipping = order.get('shipping', {}) or {}
company = billing.get('company', {})
is_company = isinstance(company, dict) and bool(company.get('name'))
b_first = billing.get('firstname', '') or ''
b_last = billing.get('lastname', '') or ''
s_first = shipping.get('firstname', '') or ''
s_last = shipping.get('lastname', '') or ''
billing_person = f"{b_first} {b_last}".strip()
shipping_person = f"{s_first} {s_last}".strip()
entry = {
'number': order.get('number', ''),
'total': order.get('total', ''),
'billing_person': billing_person,
'shipping_person': shipping_person,
'company_name': company.get('name', '') if is_company else '',
'company_code': company.get('code', '') if is_company else '',
'is_company': is_company,
'same_person': billing_person.upper() == shipping_person.upper(),
}
if is_company:
company_orders.append(entry)
else:
person_orders.append(entry)
if not entry['same_person'] and shipping_person and billing_person:
diff_person_orders.append(entry)
print(f"\n{'='*80}")
print(f"COMPANY orders (billing has company): {len(company_orders)}")
print(f"PERSON orders (no company): {len(person_orders)}")
print(f" - same billing/shipping person: {len(person_orders) - len(diff_person_orders)}")
print(f" - DIFFERENT billing/shipping person: {len(diff_person_orders)}")
# Show company examples
print(f"\n{'='*80}")
print(f"COMPANY ORDERS — first 20 examples")
print(f"{'ORDER':>12s} {'COMPANY':35s} {'CUI':20s} {'BILLING_PERSON':25s} {'SHIPPING_PERSON':25s} {'SAME':5s}")
for e in company_orders[:20]:
same = 'DA' if e['same_person'] else 'NU'
print(f"{e['number']:>12s} {e['company_name'][:35]:35s} {e['company_code'][:20]:20s} {e['billing_person'][:25]:25s} {e['shipping_person'][:25]:25s} {same:5s}")
# Show different person examples
print(f"\n{'='*80}")
print(f"DIFFERENT PERSON (no company, billing != shipping) — ALL {len(diff_person_orders)} examples")
print(f"{'ORDER':>12s} {'BILLING_PERSON':30s} {'SHIPPING_PERSON':30s}")
for e in diff_person_orders:
print(f"{e['number']:>12s} {e['billing_person'][:30]:30s} {e['shipping_person'][:30]:30s}")
# Show person orders with same name
print(f"\n{'='*80}")
print(f"PERSON ORDERS (same billing/shipping) — first 10 examples")
print(f"{'ORDER':>12s} {'BILLING_PERSON':30s} {'SHIPPING_PERSON':30s} {'TOTAL':>10s}")
same_person = [e for e in person_orders if e['same_person']]
for e in same_person[:10]:
print(f"{e['number']:>12s} {e['billing_person'][:30]:30s} {e['shipping_person'][:30]:30s} {e['total']:>10s}")
# Now cross-reference with Oracle to verify import logic
# For company orders, check what partner name was created in ROA
import oracledb, os, sqlite3
os.environ['PATH'] = r'C:\app\Server\product\18.0.0\dbhomeXE\bin' + ';' + os.environ.get('PATH','')
oracledb.init_oracle_client()
db = sqlite3.connect(r'C:\gomag-vending\api\data\import.db')
db.row_factory = sqlite3.Row
c = db.cursor()
conn = oracledb.connect(user='VENDING', password='ROMFASTSOFT', dsn='ROA')
cur = conn.cursor()
print(f"\n{'='*80}")
print(f"VERIFICATION: Company orders — GoMag vs SQLite vs Oracle ROA")
print(f"{'ORDER':>12s} | {'GOMAG_COMPANY':30s} | {'SQLITE_CUSTOMER':30s} | {'ROA_PARTNER':30s} | MATCH?")
# Build lookup from GoMag orders
gomag_lookup = {}
for order in all_orders:
num = order.get('number', '')
gomag_lookup[num] = order
# Get all imported orders from SQLite with id_partener
c.execute("""
SELECT order_number, customer_name, id_partener, billing_name, shipping_name
FROM orders WHERE id_partener IS NOT NULL
""")
for row in c.fetchall():
on = row['order_number']
gomag = gomag_lookup.get(on)
if not gomag:
continue
billing = gomag.get('billing', {}) or {}
company = billing.get('company', {})
is_company = isinstance(company, dict) and bool(company.get('name'))
company_name = company.get('name', '') if is_company else ''
# Get ROA partner name
roa_partner = ''
if row['id_partener']:
cur.execute("SELECT denumire, prenume FROM nom_parteneri WHERE id_part = :1", [row['id_partener']])
r = cur.fetchone()
if r:
roa_partner = ((r[0] or '') + ' ' + (r[1] or '')).strip()
gomag_label = company_name if is_company else f"{billing.get('firstname','')} {billing.get('lastname','')}"
match = 'OK' if company_name and company_name.upper()[:15] in roa_partner.upper() else ('OK' if not company_name else 'DIFF')
print(f"{on:>12s} | {gomag_label[:30]:30s} | {(row['customer_name'] or '')[:30]:30s} | {roa_partner[:30]:30s} | {match}")
# Also show some SKIPPED company orders to see what customer_name we stored
print(f"\n{'='*80}")
print(f"SKIPPED company orders — GoMag company vs SQLite customer_name")
print(f"{'ORDER':>12s} | {'GOMAG_COMPANY':30s} | {'SQLITE_CUSTOMER':30s} | {'BILLING_PERSON':25s} | {'SHIPPING_PERSON':25s}")
c.execute("SELECT order_number, customer_name, billing_name, shipping_name FROM orders WHERE status = 'SKIPPED' LIMIT 200")
for row in c.fetchall():
on = row['order_number']
gomag = gomag_lookup.get(on)
if not gomag:
continue
billing = gomag.get('billing', {}) or {}
company = billing.get('company', {})
is_company = isinstance(company, dict) and bool(company.get('name'))
if not is_company:
continue
company_name = company.get('name', '')
b_person = f"{billing.get('firstname','')} {billing.get('lastname','')}".strip()
shipping = gomag.get('shipping', {}) or {}
s_person = f"{shipping.get('firstname','')} {shipping.get('lastname','')}".strip()
print(f"{on:>12s} | {company_name[:30]:30s} | {(row['customer_name'] or '')[:30]:30s} | {b_person[:25]:25s} | {s_person[:25]:25s}")
db.close()
conn.close()