Add WR draft management
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.exceptions import UserError
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
from datetime import datetime as dt
|
||||
import datetime
|
||||
import requests
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -49,21 +52,127 @@ class WeightReport(ModelSQL, ModelView):
|
||||
invoice_net_kg = fields.Numeric('Invoice Net (kg)', digits=(16, 2))
|
||||
gain_loss_kg = fields.Numeric('Gain/Loss (kg)', digits=(16, 2))
|
||||
gain_loss_percent = fields.Numeric('Gain/Loss (%)', digits=(16, 2))
|
||||
remote_weight_report_keys = fields.Text('Remote WR Keys', readonly=True)
|
||||
remote_weight_report_sent_at = fields.DateTime(
|
||||
'Remote WR Sent At', readonly=True)
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order = [('report_date', 'DESC')]
|
||||
# cls._buttons.update({
|
||||
# 'import_json': {},
|
||||
# 'export_json': {},
|
||||
# })
|
||||
cls._buttons.update({
|
||||
'create_remote_weight_reports': {},
|
||||
})
|
||||
|
||||
def get_rec_name(self, name):
|
||||
items = [self.lab]
|
||||
if self.reference:
|
||||
items.append('[%s]' % self.reference)
|
||||
return ' '.join(items)
|
||||
|
||||
def create_remote_weight_report(self, wr_payload):
|
||||
response = requests.post(
|
||||
"http://automation-service:8006/weight-report",
|
||||
json=wr_payload,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
def get_related_shipments(self):
|
||||
ShipmentWR = Pool().get('shipment.wr')
|
||||
links = ShipmentWR.search([('wr', '=', self.id)])
|
||||
return [link.shipment_in for link in links if link.shipment_in]
|
||||
|
||||
def get_source_shipment(self):
|
||||
shipments = self.get_related_shipments()
|
||||
if not shipments:
|
||||
raise UserError('No shipment is linked to this weight report.')
|
||||
unique_shipments = {shipment.id: shipment for shipment in shipments}
|
||||
if len(unique_shipments) > 1:
|
||||
raise UserError(
|
||||
'This weight report is linked to multiple shipments.')
|
||||
return next(iter(unique_shipments.values()))
|
||||
|
||||
def get_remote_weight_report_lots(self, shipment):
|
||||
lots = []
|
||||
seen = set()
|
||||
for move in shipment.incoming_moves or []:
|
||||
lot = getattr(move, 'lot', None)
|
||||
if (not lot or lot.lot_type != 'physic'
|
||||
or lot.id in seen):
|
||||
continue
|
||||
seen.add(lot.id)
|
||||
lots.append(lot)
|
||||
if not lots:
|
||||
raise UserError(
|
||||
'No physical lot was found on the incoming moves.')
|
||||
return lots
|
||||
|
||||
def validate_remote_weight_report_context(self, shipment):
|
||||
if not shipment.controller:
|
||||
raise UserError(
|
||||
'A controller is required before creating remote weight reports.')
|
||||
if not shipment.returned_id:
|
||||
raise UserError(
|
||||
'A returned ID is required before creating remote weight reports.')
|
||||
if not shipment.agent:
|
||||
raise UserError(
|
||||
'A booking agent is required before creating remote weight reports.')
|
||||
if not shipment.to_location:
|
||||
raise UserError(
|
||||
'A destination location is required before creating remote weight reports.')
|
||||
if not self.bales:
|
||||
raise UserError(
|
||||
'The global weight report must define the number of bales.')
|
||||
if not self.report_date or not self.weight_date:
|
||||
raise UserError(
|
||||
'Report date and weight date are required.')
|
||||
|
||||
def build_remote_weight_report_payload(self, shipment, lot):
|
||||
if not lot.lot_chunk_key:
|
||||
raise UserError(
|
||||
'Each physical lot must have a chunk key before export.')
|
||||
factor_net = self.net_landed_kg / self.bales
|
||||
factor_gross = self.gross_landed_kg / self.bales
|
||||
lot_ratio = Decimal(lot.lot_qt) / self.bales
|
||||
return {
|
||||
"chunk_key": lot.lot_chunk_key,
|
||||
"gross_weight": float(round(
|
||||
Decimal(lot.lot_qt) * factor_gross, 5)),
|
||||
"net_weight": float(round(
|
||||
Decimal(lot.lot_qt) * factor_net, 5)),
|
||||
"tare_total": float(round(self.tare_kg * lot_ratio, 5)),
|
||||
"bags": int(lot.lot_qt),
|
||||
"surveyor_code": shipment.controller.get_alf(),
|
||||
"place_key": shipment.to_location.get_places(),
|
||||
"report_date": int(self.report_date.strftime("%Y%m%d")),
|
||||
"weight_date": int(self.weight_date.strftime("%Y%m%d")),
|
||||
"agent": shipment.agent.get_alf(),
|
||||
"forwarder_ref": shipment.returned_id,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def create_remote_weight_reports(cls, reports):
|
||||
to_save = []
|
||||
for report in reports:
|
||||
shipment = report.get_source_shipment()
|
||||
report.validate_remote_weight_report_context(shipment)
|
||||
lots = report.get_remote_weight_report_lots(shipment)
|
||||
created = []
|
||||
for lot in lots:
|
||||
payload = report.build_remote_weight_report_payload(
|
||||
shipment, lot)
|
||||
logger.info("REMOTE_WR_PAYLOAD:%s", payload)
|
||||
data = report.create_remote_weight_report(payload)
|
||||
created.append(
|
||||
f"{lot.rec_name}: {data.get('weight_report_key')}")
|
||||
report.remote_weight_report_keys = '\n'.join(created)
|
||||
report.remote_weight_report_sent_at = datetime.datetime.now()
|
||||
to_save.append(report)
|
||||
if to_save:
|
||||
cls.save(to_save)
|
||||
# @classmethod
|
||||
# @ModelView.button_action('weight_report.act_import_json')
|
||||
# def import_json(cls, reports):
|
||||
@@ -200,4 +309,4 @@ class WeightReport(ModelSQL, ModelView):
|
||||
report['gain_loss_percent'] = gain_loss_percent.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
|
||||
|
||||
# 7. Création du rapport
|
||||
return cls.create([report])[0]
|
||||
return cls.create([report])[0]
|
||||
|
||||
Reference in New Issue
Block a user