feat(pricing): kit/pachet pricing with price list lookup, replace procent_pret
- Oracle PL/SQL: kit pricing logic with Mode A (distributed discount) and
Mode B (separate discount line), dual policy support, PRETURI_CU_TVA flag
- Eliminate procent_pret from entire stack (Oracle, Python, JS, HTML)
- New settings: kit_pricing_mode, kit_discount_codmat, price_sync_enabled
- Settings UI: cards for Kit Pricing and Price Sync configuration
- Mappings UI: kit badges with lazy-loaded component prices from price list
- Price sync from orders: auto-update ROA prices when web prices differ
- Catalog price sync: new service to sync all GoMag product prices to ROA
- Kit component price validation: pre-check prices before import
- New endpoint GET /api/mappings/{sku}/prices for component price display
- New endpoints POST /api/price-sync/start, GET status, GET history
- DDL script 07_drop_procent_pret.sql (run after deploy confirmation)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -101,3 +101,77 @@ async def download_orders(
|
||||
await asyncio.sleep(1)
|
||||
|
||||
return {"pages": total_pages, "total": total_orders, "files": saved_files}
|
||||
|
||||
|
||||
async def download_products(
|
||||
api_key: str = None,
|
||||
api_shop: str = None,
|
||||
products_url: str = None,
|
||||
log_fn: Callable[[str], None] = None,
|
||||
) -> list[dict]:
|
||||
"""Download all products from GoMag Products API.
|
||||
Returns list of product dicts with: sku, price, vat, vat_included, bundleItems.
|
||||
"""
|
||||
def _log(msg: str):
|
||||
logger.info(msg)
|
||||
if log_fn:
|
||||
log_fn(msg)
|
||||
|
||||
effective_key = api_key or settings.GOMAG_API_KEY
|
||||
effective_shop = api_shop or settings.GOMAG_API_SHOP
|
||||
default_url = "https://api.gomag.ro/api/v1/product/read/json"
|
||||
effective_url = products_url or default_url
|
||||
|
||||
if not effective_key or not effective_shop:
|
||||
_log("GoMag API keys neconfigurați, skip product download")
|
||||
return []
|
||||
|
||||
headers = {
|
||||
"Apikey": effective_key,
|
||||
"ApiShop": effective_shop,
|
||||
"User-Agent": "Mozilla/5.0",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
all_products = []
|
||||
total_pages = 1
|
||||
|
||||
async with httpx.AsyncClient(timeout=30) as client:
|
||||
page = 1
|
||||
while page <= total_pages:
|
||||
params = {"page": page, "limit": 100}
|
||||
try:
|
||||
response = await client.get(effective_url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
except httpx.HTTPError as e:
|
||||
_log(f"GoMag Products API eroare pagina {page}: {e}")
|
||||
break
|
||||
except Exception as e:
|
||||
_log(f"GoMag Products eroare neașteptată pagina {page}: {e}")
|
||||
break
|
||||
|
||||
if page == 1:
|
||||
total_pages = int(data.get("pages", 1))
|
||||
_log(f"GoMag Products: {data.get('total', '?')} produse în {total_pages} pagini")
|
||||
|
||||
products = data.get("products", [])
|
||||
if isinstance(products, dict):
|
||||
products = [products]
|
||||
if isinstance(products, list):
|
||||
for p in products:
|
||||
if isinstance(p, dict) and p.get("sku"):
|
||||
all_products.append({
|
||||
"sku": p["sku"],
|
||||
"price": p.get("price", "0"),
|
||||
"vat": p.get("vat", "19"),
|
||||
"vat_included": p.get("vat_included", "1"),
|
||||
"bundleItems": p.get("bundleItems", []),
|
||||
})
|
||||
|
||||
page += 1
|
||||
if page <= total_pages:
|
||||
await asyncio.sleep(1)
|
||||
|
||||
_log(f"GoMag Products: {len(all_products)} produse cu SKU descărcate")
|
||||
return all_products
|
||||
|
||||
Reference in New Issue
Block a user