Files
tradon/modules/automation/booking_report.py
2026-07-19 17:32:54 +02:00

129 lines
4.2 KiB
Python

import json
from sql import Literal, Null
from sql.functions import CurrentTimestamp
from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
class FreightBookingShipmentReport(ModelSQL, ModelView):
"Freight Booking Shipment Report"
__name__ = 'freight.booking.shipment.report'
automation_document = fields.Many2One(
'automation.document', "Automation Document")
bl_number = fields.Function(fields.Char("BL Number"), 'get_bl_number')
shipment = fields.Function(fields.Many2One(
'stock.shipment.in', "Shipment"), 'get_shipment')
status = fields.Function(fields.Selection([
('found', "Found"),
('error', "Error"),
], "Status"), 'get_status')
@classmethod
def __setup__(cls):
super().__setup__()
cls._order = [
('id', 'DESC'),
]
@classmethod
def table_query(cls):
AutomationDocument = Pool().get('automation.document')
document = AutomationDocument.__table__()
return document.select(
Literal(None).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
document.id.as_('id'),
document.id.as_('automation_document'),
where=(
(document.type == 'weight_report')
& (document.metadata_json != Null)))
@classmethod
def _extract_bl_number(cls, metadata_json):
if not metadata_json:
return None
try:
metadata = json.loads(str(metadata_json))
except (TypeError, ValueError):
return None
def find_value(value):
if isinstance(value, dict):
for key in (
'bl_no', 'bl_number', 'bl', 'BL_Number',
'BL number', 'B/L No'):
bl_number = value.get(key)
if bl_number:
return str(bl_number).strip()
for item in value.values():
bl_number = find_value(item)
if bl_number:
return bl_number
elif isinstance(value, list):
for item in value:
bl_number = find_value(item)
if bl_number:
return bl_number
return None
return find_value(metadata)
@classmethod
def _get_report_data(cls, reports):
ShipmentIn = Pool().get('stock.shipment.in')
bl_numbers = {}
for report in reports:
document = report.automation_document
bl_number = cls._extract_bl_number(
document.metadata_json if document else None)
bl_numbers[report.id] = bl_number
shipments_by_bl = {}
for bl_number in {b for b in bl_numbers.values() if b}:
shipments = ShipmentIn.search([
('bl_number', '=', bl_number),
], limit=1)
if not shipments:
shipments = ShipmentIn.search([
('bl_number', 'ilike', bl_number),
], limit=1)
shipments_by_bl[bl_number] = shipments[0] if shipments else None
return bl_numbers, shipments_by_bl
@classmethod
def get_bl_number(cls, reports, name):
bl_numbers, _ = cls._get_report_data(reports)
return bl_numbers
@classmethod
def get_shipment(cls, reports, name):
bl_numbers, shipments_by_bl = cls._get_report_data(reports)
return {
report.id: (
shipments_by_bl[bl_numbers[report.id]].id
if bl_numbers[report.id]
and shipments_by_bl.get(bl_numbers[report.id])
else None)
for report in reports
}
@classmethod
def get_status(cls, reports, name):
bl_numbers, shipments_by_bl = cls._get_report_data(reports)
return {
report.id: (
'found'
if bl_numbers[report.id]
and shipments_by_bl.get(bl_numbers[report.id])
else 'error')
for report in reports
}