Files
tradon/modules/purchase_trade/weight_report.py
2026-02-11 08:20:23 +01:00

204 lines
8.2 KiB
Python

from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
from decimal import Decimal, ROUND_HALF_UP
from datetime import datetime as dt
import logging
logger = logging.getLogger(__name__)
class WeightReport(ModelSQL, ModelView):
'Weight Report'
__name__ = 'weight.report'
_rec_name = 'reference'
# Identification
lab = fields.Char('Laboratory', required=True)
# Report Information
reference = fields.Char('Reference')
file_no = fields.Char('File Number')
report_date = fields.Date('Report Date')
# Contract Information
contract_no = fields.Char('Contract Number')
invoice_no = fields.Char('Invoice Number')
lc_no = fields.Char('LC Number')
origin = fields.Char('Origin')
commodity = fields.Char('Commodity')
# Parties Information
seller = fields.Many2One('party.party','Seller', required=True)
buyer = fields.Many2One('party.party','Buyer', required=True)
carrier = fields.Many2One('party.party','Carrier')
# Shipment Information
vessel = fields.Many2One('trade.vessel','Vessel')
bl_no = fields.Char('B/L Number')
bl_date = fields.Date('B/L Date')
port_loading = fields.Many2One('stock.location','Port of Loading')
port_destination = fields.Many2One('stock.location','Port of Destination')
arrival_date = fields.Date('Arrival Date')
weighing_place = fields.Char('Weighing Place')
weighing_method = fields.Char('Weighing Method')
weight_date = fields.Date('Weight Date')
bales = fields.Integer('Number of Bales')
# Weights Information
gross_landed_kg = fields.Numeric('Gross Landed (kg)', digits=(16, 2))
tare_kg = fields.Numeric('Tare Weight (kg)', digits=(16, 2))
net_landed_kg = fields.Numeric('Net Landed (kg)', digits=(16, 2))
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))
@classmethod
def __setup__(cls):
super().__setup__()
cls._order = [('report_date', 'DESC')]
# cls._buttons.update({
# 'import_json': {},
# 'export_json': {},
# })
def get_rec_name(self, name):
items = [self.lab]
if self.reference:
items.append('[%s]' % self.reference)
return ' '.join(items)
# @classmethod
# @ModelView.button_action('weight_report.act_import_json')
# def import_json(cls, reports):
# pass
# @classmethod
# @ModelView.button_action('weight_report.act_export_json')
# def export_json(cls, reports):
# pass
@classmethod
def create_from_json(cls, json_data):
"""Crée un rapport à partir de données JSON"""
pool = Pool()
Party = pool.get('party.party')
Vessel = pool.get('trade.vessel')
Location = pool.get('stock.location')
# Préparer les données
report = {}
# 1. Identification (champs simples)
report['lab'] = json_data.get('lab', '')
# 2. Report Information
report_data = json_data.get('report', {})
report['reference'] = report_data.get('reference', '')
report['file_no'] = report_data.get('file_no', '')
# Conversion de la date (format: "28 October 2025")
def parse_date(date_str):
logger.info("TRY_TO_PARSE:%s",date_str)
for fmt in ('%d %B %Y', '%d %b %Y'):
try:
return dt.strptime(date_str, fmt).date()
except ValueError:
pass
return None
report['report_date'] = parse_date(report_data.get('date', ''))
logger.info("RETRUN_DATE:%s",report['weight_date'])
# 3. Contract Information
contract_data = json_data.get('contract', {})
report['contract_no'] = contract_data.get('contract_no', '')
report['invoice_no'] = contract_data.get('invoice_no', '')
report['lc_no'] = contract_data.get('lc_no', '')
report['origin'] = contract_data.get('origin', '')
report['commodity'] = contract_data.get('commodity', '')
# 4. Parties Information (Many2One)
parties_data = json_data.get('parties', {})
# Recherche ou création des parties
seller_name = parties_data.get('seller', '')
if seller_name:
seller = Party.getPartyByName(seller_name)
report['seller'] = seller.id if seller else None
buyer_name = parties_data.get('buyer', '')
if buyer_name:
buyer = Party.getPartyByName(buyer_name)
report['buyer'] = buyer.id if buyer else None
carrier_name = parties_data.get('carrier', '')
if carrier_name:
carrier = Party.getPartyByName(carrier_name)
report['carrier'] = carrier.id if carrier else None
# 5. Shipment Information
shipment_data = json_data.get('shipment', {})
# Recherche du navire par nom
vessel_name = shipment_data.get('vessel', '')
if vessel_name:
vessel = Vessel.search([('vessel_name', '=', vessel_name)], limit=1)
report['vessel'] = vessel[0].id if vessel else None
report['bl_no'] = shipment_data.get('bl_no', '')
# Conversion de la date B/L (format: "16-Aug-2025")
bl_date_str = shipment_data.get('bl_date', '')
if bl_date_str:
try:
report['bl_date'] = dt.strptime(bl_date_str, '%d-%b-%Y').date()
except:
report['bl_date'] = None
# Ports (Many2One - nécessite recherche par nom)
port_loading_name = shipment_data.get('port_loading', '')
if port_loading_name:
port_loading = Location.search([
('name', '=', port_loading_name),
('type', '=', 'supplier')
], limit=1)
report['port_loading'] = port_loading[0].id if port_loading else None
port_destination_name = shipment_data.get('port_destination', '')
if port_destination_name:
port_destination = Location.search([
('name', '=', port_destination_name),
('type', '=', 'customer')
], limit=1)
report['port_destination'] = port_destination[0].id if port_destination else None
# Conversion de la date d'arrivée (format: "20-Oct-2025")
arrival_date_str = shipment_data.get('arrival_date', '')
if arrival_date_str:
try:
report['arrival_date'] = dt.strptime(arrival_date_str, '%d-%b-%Y').date()
except:
report['arrival_date'] = None
report['weighing_place'] = shipment_data.get('weighing_place', '')
report['weighing_method'] = shipment_data.get('weighing_method', '')
report['bales'] = int(shipment_data.get('bales', 0) or 0)
# 6. Weights Information
weights_data = json_data.get('weights', {})
gross = Decimal(str(weights_data.get('gross_landed_kg', 0) or 0))
tare = Decimal(str(weights_data.get('tare_kg', 0) or 0))
net = Decimal(str(weights_data.get('net_landed_kg', 0) or 0))
invoice = Decimal(str(weights_data.get('invoice_net_kg', 0) or 0))
gain_loss = Decimal(str(weights_data.get('gain_loss_kg', 0) or 0))
gain_loss_percent = Decimal(str(weights_data.get('gain_loss_percent', 0) or 0))
# Arrondir à 2 décimales
report['weight_date'] = parse_date(weights_data.get('weight_date', ''))
report['gross_landed_kg'] = gross.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
report['tare_kg'] = tare.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
report['net_landed_kg'] = net.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
report['invoice_net_kg'] = invoice.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
report['gain_loss_kg'] = gain_loss.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
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]