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>
This commit is contained in:
179
scripts/analyze_billing.py
Normal file
179
scripts/analyze_billing.py
Normal file
@@ -0,0 +1,179 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user