diff --git a/modules/automation/cron.py b/modules/automation/cron.py index e954fd6..fbe68bd 100644 --- a/modules/automation/cron.py +++ b/modules/automation/cron.py @@ -2,11 +2,12 @@ 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.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): @@ -16,7 +17,8 @@ class Cron(metaclass=PoolMeta): def __setup__(cls): super().__setup__() cls.method.selection.append( - ('automation.cron|update_shipment', "Update Shipment from freight booking info")) + ('automation.cron|update_shipment', "Update Shipment from freight booking info") + ) class AutomationCron(ModelSQL, ModelView): "Automation Cron" @@ -37,7 +39,6 @@ class AutomationCron(ModelSQL, ModelView): @classmethod def update_shipment(cls): - # Objets Tryton PoolObj = Pool() ShipmentIn = PoolObj.get('stock.shipment.in') Party = PoolObj.get('party.party') @@ -47,7 +48,6 @@ class AutomationCron(ModelSQL, ModelView): # Table externe t = Table('freight_booking_info') cursor = Transaction().connection.cursor() - cursor.execute(*t.select( t.ShippingInstructionNumber, t.ShippingInstructionDate, @@ -68,77 +68,125 @@ class AutomationCron(ModelSQL, ModelView): t.FintradeBookingKey, )) - for row in cursor.fetchall(): + # On prépare deux listes pour la sauvegarde en batch + parties_to_save = [] + vessels_to_save = [] + locations_to_save = [] + + # Dictionnaires pour éviter de recréer plusieurs fois le même objet + 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, + 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) - # ----- Récupération / création des recordsets ----- + # ----- Fonctions pour créer ou récupérer les objets en mémoire ----- def get_or_create_party(name): - name = name.upper() - p = Party.search([('name', '=', name)], limit=1) - if p: - return p[0] + 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] new_p = Party() - new_p.name = name - Party.save([new_p]) + 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 = name.upper() - v = Vessel.search([('vessel_name', '=', name)], limit=1) - if v: - return v[0] + 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] new_v = Vessel() - new_v.vessel_name = name + new_v.vessel_name = name_upper new_v.vessel_imo = imo - Vessel.save([new_v]) + vessels_cache[name_upper] = new_v + vessels_to_save.append(new_v) return new_v def get_or_create_location(name, type_): - name = name.upper() - loc = Location.search([('name', '=', name), ('type', '=', type_)], limit=1) - if loc: - return loc[0] + 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] new_loc = Location() - new_loc.name = name + new_loc.name = name.upper() new_loc.type = type_ - Location.save([new_loc]) + locations_cache[key] = new_loc + locations_to_save.append(new_loc) return new_loc - # ----- Vérification si le Shipment existe ----- - shipment = ShipmentIn.search([('reference','=',si_number)], limit=1) + # ----- 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') + + # Stocke toutes les infos du shipment pour la deuxième étape + row_dict = { + '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 + } + row._shipment_data = row_dict # on attache les infos au row temporairement + + # ----- É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 row in rows: + data = row._shipment_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 = get_or_create_location(loading_name, 'supplier') - sh.to_location = get_or_create_location(destination_name, 'customer') - sh.carrier = get_or_create_party(carrier_name) - sh.supplier = get_or_create_party(agent_name) - sh.vessel = get_or_create_vessel(vessel_name) + 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 = bl_number - sh.bl_date = bl_date - sh.etd = etd_date + 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)