sligro: Return substitute products when available
This commit is contained in:
parent
d9fc9ac084
commit
7a8997835d
1 changed files with 38 additions and 12 deletions
|
@ -8,7 +8,7 @@ import os
|
||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
from supermarktconnector.ah import AHConnector
|
from supermarktconnector.ah import AHConnector
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
|
|
||||||
vat = Decimal('1.09')
|
vat = Decimal('1.09')
|
||||||
|
@ -26,6 +26,7 @@ class Product:
|
||||||
gtin: str
|
gtin: str
|
||||||
units: int
|
units: int
|
||||||
aliases: List[str]
|
aliases: List[str]
|
||||||
|
replacement: Optional["Product"] = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -84,25 +85,46 @@ def sligro_client():
|
||||||
return _sess
|
return _sess
|
||||||
|
|
||||||
|
|
||||||
def sligro_get_by_gtin(gtin13):
|
def sligro_get_by_sku(sku, _recurse=0):
|
||||||
|
assert re.match(r'^\d{4,12}$', sku)
|
||||||
|
return _sligro_get(sku, _recurse=_recurse)
|
||||||
|
|
||||||
|
|
||||||
|
def sligro_get_by_gtin(gtin13, _recurse=0):
|
||||||
assert re.match(r'^\d{13}$', gtin13)
|
assert re.match(r'^\d{13}$', gtin13)
|
||||||
gtin14 = f'{gtin13:0>14}'
|
gtin14 = f'{gtin13:0>14}'
|
||||||
|
|
||||||
# The search feature of the website returns results in JSON and handles GTIN formats. Neat!
|
# The search feature of the website returns results in JSON and handles GTIN formats. Neat!
|
||||||
# However, it can be a bit picky about leading zeros, so we try to query with GTIN14 as that is
|
# However, it can be a bit picky about leading zeros, so we try to query with GTIN14 as that is
|
||||||
# what works in the most cases. Sometimes GTIN13 is still required though
|
# what works in the most cases. Sometimes GTIN13 is still required though
|
||||||
for gtin_whatever in [gtin14, gtin13]:
|
for gtin_whatever in [gtin14, gtin13]:
|
||||||
response = requests.get(f'https://www.sligro.nl/api/product-overview/sligro-nl/nl/query/3?term={gtin_whatever}')
|
try:
|
||||||
response.raise_for_status()
|
return _sligro_get(gtin_whatever, _recurse=_recurse)
|
||||||
body = response.json()
|
except ProductNotFoundError:
|
||||||
if 'products' in body:
|
continue
|
||||||
break
|
raise ProductNotFoundError()
|
||||||
else:
|
|
||||||
|
|
||||||
|
def _sligro_get(query, *, _recurse=0):
|
||||||
|
# A runaway recursion could DoS the sligro API, which is impolite :)
|
||||||
|
assert _recurse <= 1
|
||||||
|
|
||||||
|
response = requests.get(f'https://www.sligro.nl/api/product-overview/sligro-nl/nl/query/3?term={query}')
|
||||||
|
response.raise_for_status()
|
||||||
|
body = response.json()
|
||||||
|
if 'products' not in body:
|
||||||
raise ProductNotFoundError()
|
raise ProductNotFoundError()
|
||||||
|
|
||||||
product = body['products'][0]
|
if len(body['products']) > 1:
|
||||||
|
product = next(filter(lambda p: 'productReferenceReplace' not in p, body['products']))
|
||||||
|
else:
|
||||||
|
product = body['products'][0]
|
||||||
|
|
||||||
sku = product["code"]
|
sku = product["code"]
|
||||||
|
|
||||||
|
replacement = None
|
||||||
|
if 'productReferenceReplace' in product:
|
||||||
|
replacement = sligro_get_by_sku(product['productReferenceReplace'][0], _recurse=_recurse+1)
|
||||||
|
|
||||||
# Query the product page itself, there is more info that we need on there. In the website, the
|
# Query the product page itself, there is more info that we need on there. In the website, the
|
||||||
# final path element is a derivation of the contentDescription field. It must be present, but
|
# final path element is a derivation of the contentDescription field. It must be present, but
|
||||||
# matches anything.
|
# matches anything.
|
||||||
|
@ -132,12 +154,16 @@ def sligro_get_by_gtin(gtin13):
|
||||||
else:
|
else:
|
||||||
price_obj = pricing['price']
|
price_obj = pricing['price']
|
||||||
|
|
||||||
|
name = product["name"]
|
||||||
|
name = re.sub(' - Wordt binnenkort vervangen door.+$', '', name)
|
||||||
|
|
||||||
return Product(
|
return Product(
|
||||||
name=f'{product["brandName"]} {product["name"]} ({volume})',
|
name=f'{product["brandName"]} {name} ({volume})',
|
||||||
price=Decimal(price_obj['value']) * vat,
|
price=Decimal(price_obj['value']) * vat,
|
||||||
gtin=gtin13,
|
gtin=product['gtin'].lstrip('0'),
|
||||||
units=units,
|
units=units,
|
||||||
aliases=[sub_gtin] if sub_gtin else [],
|
aliases=[sub_gtin] if sub_gtin else [],
|
||||||
|
replacement=replacement,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue