All checks were successful
Build and deploy / Validate source (push) Successful in 1m18s
Build and deploy / Integration suite on a real stack (push) Successful in 2m33s
Build and deploy / Secret scan and release gate (push) Successful in 9s
Build and deploy / Publish images (push) Successful in 1m42s
FREIGHT_ADAPTER=jadlog prices "Receber em casa" through Jadlog's Simulador de Frete from the order's billed metres and value, adding production days to Jadlog's delivery time. The package weight is a base plus a weight per metre from the client, with no default: the adapter refuses to start without it and without the credentials. The cart re-quotes when the package changes, and approval quotes again from the server-priced items. The production stack takes the Jadlog settings, so the read-only probe runs from the worker's console. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
81 lines
3.4 KiB
Python
81 lines
3.4 KiB
Python
"""Read-only price check against the client's real Jadlog account, run by hand.
|
|
A quote creates no shipment and costs nothing.
|
|
|
|
python -m app.jadlog_probe [--cep 01310100 ...] [--peso 0.5 ...] [--valor 100]
|
|
|
|
Without --cep and --peso it prices a few test weights to a few regions. It
|
|
answers whether the token, CNPJ and account are accepted, whether a contract
|
|
number is required (Jadlog names it in the error), and what the contract
|
|
prices and delivery times are. The first failure stops the run: an account
|
|
problem would repeat on every line.
|
|
|
|
In production, from the worker's console (Portainer > Containers > worker >
|
|
Console), with JADLOG_TOKEN, JADLOG_CNPJ and JADLOG_CONTA in the stack:
|
|
|
|
python -m app.jadlog_probe
|
|
|
|
Locally, with the credentials in jadlog.env (ignored by git):
|
|
|
|
docker compose -f compose.local.yaml -f compose.providers.yaml run --rm --no-deps --build \\
|
|
--env-from-file jadlog.env worker python -m app.jadlog_probe
|
|
"""
|
|
import argparse
|
|
import sys
|
|
from decimal import Decimal
|
|
|
|
from .core.secrets import load as load_secret_files
|
|
from .jadlog import JadlogError, JadlogQuotes
|
|
|
|
DESTINATIONS = {'14402310': 'Franca (origem)', '01310100': 'São Paulo', '20040002': 'Rio de Janeiro',
|
|
'80010000': 'Curitiba', '50030230': 'Recife', '69005010': 'Manaus'}
|
|
WEIGHTS = ['0.3', '0.5', '1', '2', '5']
|
|
|
|
|
|
def money(cents):
|
|
return f'R$ {cents / 100:.2f}'.replace('.', ',')
|
|
|
|
|
|
def run(quotes, ceps, weights, declared_cents, out):
|
|
header = quotes.token
|
|
for weight in weights:
|
|
for cep in ceps:
|
|
try:
|
|
result = quotes.quote(cep, Decimal(weight), declared_cents)
|
|
except JadlogError as error:
|
|
# The manual shows the header as the bare token; some accounts
|
|
# are issued one that expects the Bearer scheme.
|
|
if '401' in str(error) and not header.lower().startswith('bearer '):
|
|
quotes.token = 'Bearer ' + header
|
|
header = quotes.token
|
|
try:
|
|
result = quotes.quote(cep, Decimal(weight), declared_cents)
|
|
except JadlogError as retry:
|
|
out(f'ERRO {cep} {weight} kg: {retry} (also with "Bearer ")')
|
|
return 1
|
|
out('Note: the token only works with the "Bearer " prefix.')
|
|
else:
|
|
out(f'ERRO {cep} {weight} kg: {error}')
|
|
return 1
|
|
days = result['days']
|
|
out(f"{weight} kg\t{cep}\t{DESTINATIONS.get(cep, '')}\t{money(result['total_cents'])}\t"
|
|
f"{days if days is not None else '?'} dia(s)")
|
|
return 0
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(prog='python -m app.jadlog_probe')
|
|
parser.add_argument('--cep', action='append', help='destination CEP (repeatable)')
|
|
parser.add_argument('--peso', action='append', help='weight in kg (repeatable)')
|
|
parser.add_argument('--valor', default='100', help='declared value in reais (default 100)')
|
|
args = parser.parse_args(argv)
|
|
load_secret_files()
|
|
quotes = JadlogQuotes()
|
|
declared = int(Decimal(args.valor) * 100)
|
|
print(f'Origem {quotes.origin}, modalidade {quotes.modalidade}, contrato {quotes.contrato or "-"}, '
|
|
f'valor declarado {money(declared)}')
|
|
return run(quotes, args.cep or list(DESTINATIONS), args.peso or WEIGHTS, declared, print)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|