import requests from decimal import getcontext, Decimal, ROUND_HALF_UP from datetime import datetime from trytond.model import fields from trytond.model import ModelSQL, ModelView from trytond.pool import Pool, PoolMeta from trytond.transaction import Transaction import logging from sql import Table logger = logging.getLogger(__name__) class Cron(metaclass=PoolMeta): __name__ = 'ir.cron' @classmethod def __setup__(cls): super().__setup__() cls.method.selection.append( ('automation.cron|update_shipment', "Update Shipment from freight booking info") ) class AutomationCron(ModelSQL, ModelView): "Automation Cron" __name__ = 'automation.cron' frequency = fields.Selection([ ('daily', "Daily"), ('weekly', "Weekly"), ('monthly', "Monthly"), ], "Frequency", required=True, help="How frequently rates must be updated.") last_update = fields.Date("Last Update", required=True) @classmethod def run(cls, crons): cls.update_shipment() @classmethod def update_shipment(cls): PoolObj = Pool() ShipmentIn = PoolObj.get('stock.shipment.in') Party = PoolObj.get('party.party') Vessel = PoolObj.get('trade.vessel') Location = PoolObj.get('stock.location') # Table externe t = Table('freight_booking_info') cursor = Transaction().connection.cursor() cursor.execute(*t.select( t.ShippingInstructionNumber, t.ShippingInstructionDate, t.ShippingInstructionQuantity, t.ShippingInstructionQuantityUnit, t.NumberOfContainers, t.ContainerType, t.Loading, t.Destination, t.BookingAgent, t.Carrier, t.Vessel, t.BL_Number, t.ETD_Date, t.BL_Date, t.ExpectedController, t.Comments, t.FintradeBookingKey, )) # Préparer les listes pour la sauvegarde et les données du shipment parties_to_save = [] vessels_to_save = [] locations_to_save = [] shipments_data = [] # <-- nouvelle liste parties_cache = {} vessels_cache = {} locations_cache = {} rows = cursor.fetchall() for row in rows: ( si_number, si_date, si_quantity, si_unit, container_number, container_type, loading_name, destination_name, agent_name, carrier_name, vessel_name, bl_number, etd_date, bl_date, controller, comments, fintrade_booking_key ) = row logger.info("ROW_FROM_CRON: %s", row) # ----- Fonctions pour créer ou récupérer les objets ----- def get_or_create_party(name): name_upper = name.upper() if name_upper in parties_cache: return parties_cache[name_upper] existing = Party.search([('name', '=', name_upper)], limit=1) if existing: parties_cache[name_upper] = existing[0] return existing[0] if name: new_p = Party() new_p.name = name_upper parties_cache[name_upper] = new_p parties_to_save.append(new_p) return new_p def get_or_create_vessel(name, imo=None): name_upper = name.upper() if name_upper in vessels_cache: return vessels_cache[name_upper] existing = Vessel.search([('vessel_name', '=', name_upper)], limit=1) if existing: vessels_cache[name_upper] = existing[0] return existing[0] if name: new_v = Vessel() new_v.vessel_name = name_upper new_v.vessel_imo = imo vessels_cache[name_upper] = new_v vessels_to_save.append(new_v) return new_v def get_or_create_location(name, type_): key = f"{name.upper()}_{type_}" if key in locations_cache: return locations_cache[key] existing = Location.search([('name', '=', name.upper()), ('type', '=', type_)], limit=1) if existing: locations_cache[key] = existing[0] return existing[0] if name: new_loc = Location() new_loc.name = name.upper() new_loc.type = type_ locations_cache[key] = new_loc locations_to_save.append(new_loc) return new_loc # ----- Récupération ou création des objets ----- carrier = get_or_create_party(carrier_name) agent = get_or_create_party(agent_name) vessel = get_or_create_vessel(vessel_name) loc_from = get_or_create_location(loading_name, 'supplier') loc_to = get_or_create_location(destination_name, 'customer') # Stocker les données pour la deuxième étape shipments_data.append({ 'si_number': si_number, 'bl_number': bl_number, 'bl_date': bl_date, 'etd_date': etd_date, 'carrier': carrier, 'agent': agent, 'vessel': vessel, 'from_location': loc_from, 'to_location': loc_to, }) # ----- Étape 1 : sauvegarde des objets de référence ----- if parties_to_save: Party.save(parties_to_save) if vessels_to_save: Vessel.save(vessels_to_save) if locations_to_save: Location.save(locations_to_save) # Commit pour garantir que tous les IDs sont corrects Transaction().commit() # ----- Étape 2 : création des shipments ----- for data in shipments_data: si_number = data['si_number'] shipment = ShipmentIn.search([('reference', '=', si_number)], limit=1) if shipment: sh = shipment[0] else: sh = ShipmentIn() sh.reference = si_number sh.from_location = data['from_location'] sh.to_location = data['to_location'] sh.carrier = data['carrier'] sh.supplier = data['agent'] sh.vessel = data['vessel'] sh.cargo_mode = 'bulk' sh.bl_number = data['bl_number'] sh.bl_date = data['bl_date'] sh.etd = data['etd_date'] ShipmentIn.save([sh]) logger.info("SHIPMENT_CREATED: %s", sh)