Files
tradon/modules/automation/cron.py
2026-01-20 16:13:52 +01:00

269 lines
11 KiB
Python

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,
))
# ---- PREMIÈRE TRANSACTION : Création des objets de référence ----
with Transaction().new_transaction() as trans1:
try:
parties_to_save = []
vessels_to_save = []
locations_to_save = []
parties_cache = {}
vessels_cache = {}
locations_cache = {}
# Collecter les données des objets de référence
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
# Fonction pour obtenir ou créer un Party
def get_or_create_party(name):
if not name:
return None
name_upper = name.upper()
if name_upper in parties_cache:
return parties_cache[name_upper]
# Chercher d'abord dans la base
existing = Party.search([('name', '=', name_upper)], limit=1)
if existing:
parties_cache[name_upper] = existing[0]
return existing[0]
# Créer un nouveau
new_p = Party()
new_p.name = name_upper
parties_cache[name_upper] = new_p
parties_to_save.append(new_p)
return new_p
# Fonction pour obtenir ou créer un Vessel
def get_or_create_vessel(name):
if not name:
return 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]
new_v = Vessel()
new_v.vessel_name = name_upper
vessels_cache[name_upper] = new_v
vessels_to_save.append(new_v)
return new_v
# Fonction pour obtenir ou créer une Location
def get_or_create_location(name, type_):
if not name:
return None
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.upper()
new_loc.type = type_
locations_cache[key] = new_loc
locations_to_save.append(new_loc)
return new_loc
# Collecter les objets à créer
_ = get_or_create_party(carrier_name)
_ = get_or_create_party(agent_name)
_ = get_or_create_vessel(vessel_name)
_ = get_or_create_location(loading_name, 'supplier')
_ = get_or_create_location(destination_name, 'customer')
# Sauvegarder tous les 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)
trans1.commit()
logger.info("Première transaction commitée : objets de référence créés")
except Exception as e:
trans1.rollback()
logger.error(f"Erreur dans la première transaction : {e}")
raise
# ---- DEUXIÈME TRANSACTION : Création des shipments ----
with Transaction().new_transaction() as trans2:
try:
# Recréer les curseurs après la nouvelle transaction
cursor2 = Transaction().connection.cursor()
cursor2.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,
))
rows2 = cursor2.fetchall()
shipments_to_save = []
for row in rows2:
(
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
# Vérifier si le shipment existe déjà
existing_shipment = ShipmentIn.search([
('reference', '=', si_number)
], limit=1)
if existing_shipment:
logger.info(f"Shipment existe déjà : {si_number}")
continue
# Récupérer les objets (maintenant ils existent dans la base)
carrier = Party.search([('name', '=', carrier_name.upper())], limit=1) if carrier_name else None
agent = Party.search([('name', '=', agent_name.upper())], limit=1) if agent_name else None
vessel = Vessel.search([('vessel_name', '=', vessel_name.upper())], limit=1) if vessel_name else None
loc_from = Location.search([
('name', '=', loading_name.upper()),
('type', '=', 'supplier')
], limit=1) if loading_name else None
loc_to = Location.search([
('name', '=', destination_name.upper()),
('type', '=', 'customer')
], limit=1) if destination_name else None
# Créer le shipment
shipment = ShipmentIn()
shipment.reference = si_number
shipment.from_location = loc_from[0] if loc_from else None
shipment.to_location = loc_to[0] if loc_to else None
shipment.carrier = carrier[0] if carrier else None
shipment.supplier = agent[0] if agent else None
shipment.vessel = vessel[0] if vessel else None
shipment.cargo_mode = 'bulk'
shipment.bl_number = bl_number
shipment.bl_date = bl_date
shipment.etd = etd_date
shipments_to_save.append(shipment)
logger.info(f"Shipment préparé : {si_number}")
# Sauvegarder tous les shipments
if shipments_to_save:
ShipmentIn.save(shipments_to_save)
logger.info(f"{len(shipments_to_save)} shipments créés")
trans2.commit()
except Exception as e:
trans2.rollback()
logger.error(f"Erreur dans la deuxième transaction : {e}")
raise