This commit is contained in:
2026-01-20 15:25:15 +01:00
parent c5fbd3e528
commit c5053638df

View File

@@ -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)