Files
Autoparts-DB/scripts/scrape_rached_client_details.py
consultoria-as f42910f4f6
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled
feat: cashier/counter reports, service-order & remission flows, Rached migration utils
- Add "Mis cortes de caja" report for cashiers/counters with sales detail.
- Cash register history scoped to own cuts for non-admin roles; new /register/<id>/sales endpoint.
- Remove dashboard from cashier menu; add Reports to cashier/counter.
- Service orders: assign mechanic, budget field, invoice flag, counter/cashier can add items/remissions, convert to remission.
- Remission notes module (UI, CSS, courier, counter remissions).
- Customer hard-delete and vehicle/customer linkage in workshop.
- POS: always show search results, compact payment grid, credit validation, tier pricing (5%/10%), ticket with customer/folio.
- Inventory: CSV template with sku_secondary, alias import.
- Rached migration scripts and DB migrations.
- Version-bump cached JS/CSS query strings.

Excludes local Rached session tokens/captures (rached_*.json / rached_*.txt).
2026-07-02 12:51:56 +00:00

86 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Fetch full client details for clients referenced in Rached service orders."""
import json
import os
import time
import requests
from pathlib import Path
BASE_API = 'http://appapi.flechasyventiladores-rached.com'
OUT_DIR = Path(os.environ.get('OUT_DIR', Path(__file__).resolve().parent.parent / 'data' / 'rached_import'))
PASS = 'Nexus01'
HEADERS = {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'Origin': 'http://app.flechasyventiladores-rached.com',
'Referer': 'http://app.flechasyventiladores-rached.com/',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
}
def login():
url = f'{BASE_API}/api/seguridad/login'
payload = {
'grant_type': 'password',
'client_secret': 'JiRE9iL3pqRnqcFp6wDeYH0tYu97QSpkrwVKAvEP',
'client_id': 2,
'username': 'IVAN@flechasyventiladores-rached.com',
'password': PASS,
}
resp = requests.post(url, headers=HEADERS, json=payload)
resp.raise_for_status()
data = resp.json()
if data.get('mensaje'):
raise RuntimeError(f'Login failed: {data["mensaje"]}')
return data['datos']['token']
def fetch_client(token, cid):
url = f'{BASE_API}/api/catalogos/clientes/{cid}'
resp = requests.get(url, headers={**HEADERS, 'Authorization': f'Bearer {token}'}, timeout=30)
resp.raise_for_status()
return resp.json()
def main():
OUT_DIR.mkdir(parents=True, exist_ok=True)
detail_dir = OUT_DIR / 'client_details'
detail_dir.mkdir(exist_ok=True)
# collect unique client ids from order details
client_ids = set()
for f in OUT_DIR.glob('details/order_*.json'):
d = json.loads(f.read_text(encoding='utf-8')).get('datos', {})
cid = d.get('idCliente')
if cid:
client_ids.add(cid)
print(f'Found {len(client_ids)} unique clients from order details')
token = login()
print('Logged in')
results = {}
for idx, cid in enumerate(sorted(client_ids), 1):
out_path = detail_dir / f'client_{cid}.json'
if out_path.exists():
data = json.loads(out_path.read_text(encoding='utf-8'))
else:
try:
data = fetch_client(token, cid)
except Exception as e:
print(f'[{idx}/{len(client_ids)}] client {cid} error: {e}')
continue
out_path.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding='utf-8')
results[cid] = data.get('datos')
print(f'[{idx}/{len(client_ids)}] client {cid} saved')
time.sleep(0.4 if idx % 30 else 1.5)
summary_path = OUT_DIR / 'catalog_client_details.json'
summary_path.write_text(json.dumps(results, indent=2, ensure_ascii=False), encoding='utf-8')
print(f'Saved {len(results)} client details to {summary_path}')
if __name__ == '__main__':
main()