This commit is contained in:
2026-02-02 10:42:08 +01:00
parent 64806b143b
commit 7d89418874
7 changed files with 213 additions and 185 deletions

View File

@@ -220,189 +220,27 @@ class AutomationDocument(ModelSQL, ModelView, Workflow):
ShipmentWR.save([swr])
doc.notes = (doc.notes or "") + f"Shipment found: {sh[0].number}\n"
logger.info("BL_NUMBER:%s",sh[0].bl_number)
t = Table('freight_booking_lots')
cursor = Transaction().connection.cursor()
query = t.select(
t.BOOKING_NUMBER,
t.LOT_NUMBER,
t.LOT_NBR_BALES,
t.LOT_GROSS_WEIGHT,
t.LOT_NET_WEIGHT,
t.LOT_UOM,
t.LOT_QUALITY,
t.CUSTOMER,
t.SELL_PRICE_CURRENCY,
t.SELL_PRICE_UNIT,
t.SELL_PRICE,
t.SALE_INVOICE,
t.SELL_INV_AMOUNT,
t.SALE_INVOICE_DATE,
t.SELL_PREMIUM,
t.SALE_CONTRACT_NUMBER,
t.SALE_DECLARATION_KEY,
t.SHIPMENT_CHUNK_KEY,
where=(t.BOOKING_NUMBER == int(sh[0].reference))
)
cursor.execute(*query)
rows = cursor.fetchall()
logger.info("ROWS:%s",rows)
if rows:
sale_line = None
for row in rows:
logger.info("ROW:%s",row)
#Purchase & Sale creation
LotQt = Pool().get('lot.qt')
Lot = Pool().get('lot.lot')
LotAdd = Pool().get('lot.add.line')
Currency = Pool().get('currency.currency')
Product = Pool().get('product.product')
Party = Pool().get('party.party')
Uom = Pool().get('product.uom')
Sale = Pool().get('sale.sale')
SaleLine = Pool().get('sale.line')
dec_key = str(row[16]).strip()
chunk_key = str(row[17]).strip()
doc.notes = (doc.notes or "") + f"Lots found: {chunk_key}\n"
lot_unit = str(row[5]).strip().lower()
product = str(row[6]).strip().upper()
lot_net_weight = Decimal(row[4])
logger.info("LOT_NET_WEIGHT:%s",lot_net_weight)
lot_gross_weight = Decimal(row[3])
lot_bales = Decimal(row[2])
lot_number = row[1]
customer = str(row[7]).strip().upper()
sell_price_currency = str(row[8]).strip().upper()
sell_price_unit = str(row[9]).strip().lower()
sell_price = Decimal(row[10])
premium = Decimal(row[14])
reference = Decimal(row[15])
logger.info("DECLARATION_KEY:%s",dec_key)
declaration = SaleLine.search(['note','=',dec_key])
if declaration:
sale_line = declaration[0]
logger.info("WITH_DEC:%s",sale_line)
vlot = sale_line.lots[0]
lqt = LotQt.search([('lot_s','=',vlot.id)])
if lqt:
for lq in lqt:
if lq.lot_p:
logger.info("VLOT_P:%s",lq.lot_p)
sale_line.quantity_theorical += round(lot_net_weight,2)
SaleLine.save([sale_line])
lq.lot_p.updateVirtualPart(round(lot_net_weight,2),sh[0],lq.lot_s)
vlot.set_current_quantity(round(lot_net_weight,2),round(lot_gross_weight,2),1)
Lot.save([vlot])
else:
sale = Sale()
sale_line = SaleLine()
sale.party = Party.getPartyByName(customer,'CLIENT')
logger.info("SALE_PARTY:%s",sale.party)
sale.reference = reference
sale.company = 6
if sale.party.addresses:
sale.invoice_address = sale.party.addresses[0]
sale.shipment_address = sale.party.addresses[0]
if sell_price_currency == 'USC':
sale.currency = Currency.get_by_name('USD')
sale_line.enable_linked_currency = True
sale_line.linked_currency = 1
sale_line.linked_unit = Uom.get_by_name(sell_price_unit)
sale_line.linked_price = round(sell_price,4)
sale_line.unit_price = sale_line.get_price_linked_currency()
else:
sale.currency = Currency.get_by_name(sell_price_currency)
sale_line.unit_price = round(sell_price,4)
sale_line.unit = Uom.get_by_name(sell_price_unit)
sale_line.premium = premium
Sale.save([sale])
sale_line.sale = sale.id
sale_line.quantity = round(lot_net_weight,2)
sale_line.quantity_theorical = round(lot_net_weight,2)
sale_line.product = Product.get_by_name('BRAZIL COTTON')
logger.info("PRODUCT:%s",sale_line.product)
sale_line.unit = Uom.get_by_name(lot_unit)
sale_line.price_type = 'priced'
sale_line.created_by_code = False
sale_line.note = dec_key
SaleLine.save([sale_line])
#need to link the virtual part to the shipment
lqt = LotQt.search([('lot_s','=',sale_line.lots[0])])
if lqt:
lqt[0].lot_shipment_in = sh[0]
LotQt.save(lqt)
logger.info("SALE_LINKED_TO_SHIPMENT:%s",sh[0])
ContractStart = Pool().get('contracts.start')
ContractDetail = Pool().get('contract.detail')
ct = ContractStart()
d = ContractDetail()
ct.type = 'Purchase'
ct.matched = True
ct.shipment_in = sh[0]
ct.lot = sale_line.lots[0]
ct.product = sale_line.product
ct.unit = sale_line.unit
d.party = Party.getPartyByName('FAIRCOT')
if sale_line.enable_linked_currency:
d.currency_unit = str(sale_line.linked_currency.id) + '_' + str(sale_line.linked_unit.id)
else:
d.currency_unit = str(sale.currency.id) + '_' + str(sale_line.unit.id)
d.quantity = sale_line.quantity
d.unit = sale_line.unit
d.price = sale_line.unit_price
d.price_type = 'priced'
d.crop = None
d.tol_min = 0
d.tol_max = 0
d.incoterm = None
d.reference = str(sale.id)
d.del_period = None
d.from_del = None
d.to_del = None
ct.contracts = [d]
ContractFactory.create_contracts(
ct.contracts,
type_=ct.type,
ct=ct,
)
#Lots creation
vlot = sale_line.lots[0]
lqt = LotQt.search([('lot_s','=',vlot.id),('lot_p','>',0)])
if lqt and vlot.lot_quantity > 0:
lqt = lqt[0]
l = LotAdd()
l.lot_qt = lot_bales
l.lot_unit = Uom.get_by_name('bale')
l.lot_unit_line = Uom.get_by_name(lot_unit)
l.lot_quantity = round(lot_net_weight,2)
l.lot_gross_quantity = round(lot_gross_weight,2)
l.lot_premium = premium
l.lot_chunk_key = int(chunk_key)
logger.info("ADD_LOT:%s",int(chunk_key))
LotQt.add_physical_lots(lqt,[l])
if sale_line:
logger.info("CREATE_FINTRADE_WR_FOR_SL:%s",sale_line)
weight_total = sum([l.lot_quantity for l in sale_line.lots if l.lot_type == 'physic'])
factor = weight_total / wr.net_landed_kg if wr.net_landed_kg else 1
for lot in sale_line.lots:
if lot.lot_type == 'physic':
wr_payload = {
"chunk_key": lot.lot_chunk_key,
"gross_weight": float(round(lot.lot_gross_quantity / factor,5)),
"net_weight": float(round(lot.lot_quantity / factor,5)),
"tare_total": float(round(wr.tare_kg * (lot.lot_quantity / weight_total),5)) ,
"bags": int(wr.bales * (lot.lot_quantity / weight_total)),
"surveyor_code": 231,
"place_key": 0,
"report_date": 20260127
}
logger.info("PAYLOAD:%s",wr_payload)
data = doc.create_weight_report(wr_payload)
doc.notes = (doc.notes or "") + f"WR created in Fintrade: {data.get('success')}\n"
doc.notes = (doc.notes or "") + f"WR key: {data.get('weight_report_key')}\n"
sale_line = sh[0]._create_lots_from_fintrade()
if sale_line:
logger.info("CREATE_FINTRADE_WR_FOR_SL:%s",sale_line)
weight_total = sum([l.lot_quantity for l in sale_line.lots if l.lot_type == 'physic'])
factor = weight_total / wr.net_landed_kg if wr.net_landed_kg else 1
for lot in sale_line.lots:
if lot.lot_type == 'physic':
wr_payload = {
"chunk_key": lot.lot_chunk_key,
"gross_weight": float(round(lot.lot_gross_quantity / factor,5)),
"net_weight": float(round(lot.lot_quantity / factor,5)),
"tare_total": float(round(wr.tare_kg * (lot.lot_quantity / weight_total),5)) ,
"bags": int(wr.bales * (lot.lot_quantity / weight_total)),
"surveyor_code": 231,
"place_key": 0,
"report_date": 20260127
}
logger.info("PAYLOAD:%s",wr_payload)
data = doc.create_weight_report(wr_payload)
doc.notes = (doc.notes or "") + f"WR created in Fintrade: {data.get('success')}\n"
doc.notes = (doc.notes or "") + f"WR key: {data.get('weight_report_key')}\n"
# if cls.rule_set.ocr_required:[]
# cls.run_ocr([doc])

View File

@@ -308,7 +308,8 @@ class AutomationCron(ModelSQL, ModelView):
# Sauvegarder ce shipment uniquement
ShipmentIn.save([shipment])
shipment._create_lots_from_fintrade()
shipment.get_controller()
trans_shipment.commit()
successful_shipments += 1
logger.info(f"✓ Shipment {si_number} créé avec succès")

View File

@@ -215,7 +215,7 @@ class Incoming(DeactivableMixin, Workflow, ModelSQL, ModelView):
children.append(child)
else:
child = cls(
name='mail.txt',
name='mail_' + message.get('subject', 'No Subject') + '.txt',
company=rule.document_incoming_company,
data=body_bytes,
type=rule.document_incoming_type,

View File

@@ -49,6 +49,9 @@ class Incoming(metaclass=PoolMeta):
wr.type = 'controller'
wr.state = 'draft'
WR.save([wr])
WR.run_ocr([wr])
WR.run_metadata([wr])
return wr
# @property

View File

@@ -11,6 +11,10 @@ class PartyExecution(ModelSQL,ModelView):
party = fields.Many2One('party.party',"Party")
area = fields.Many2One('country.region',"Area")
percent = fields.Numeric("% targeted")
achieved_percent = fields.Function(fields.Numeric("% achieved"),'get_percent')
def get_percent(self,name):
return 2
class Party(metaclass=PoolMeta):
__name__ = 'party.party'
@@ -21,6 +25,9 @@ class Party(metaclass=PoolMeta):
association = fields.Many2One('purchase.association',"Association")
execution = fields.One2Many('party.execution','party',"")
def IsAvailableForControl(self,sh):
return True
@classmethod
def getPartyByName(cls, party, category=None):
party = party.upper()

View File

@@ -16,6 +16,7 @@ from itertools import chain, groupby
from operator import itemgetter
import datetime
from collections import defaultdict
from sql import Table
import logging
logger = logging.getLogger(__name__)
@@ -444,6 +445,183 @@ class ShipmentIn(metaclass=PoolMeta):
else:
return str(self.id)
def get_controller(self):
ControllerCategory = Pool().get('party.category')
PartyCategory = Pool().get('party.party-party.category')
cc = ControllerCategory.search(['name','=','CONTROLLER'])
if cc:
cc = cc[0]
controllers = PartyCategory.search(['category','=',cc.id])
for c in controllers:
if c.party.IsAvailableForControl(self):
return c.party
def _create_lots_from_fintrade(self):
t = Table('freight_booking_lots')
cursor = Transaction().connection.cursor()
query = t.select(
t.BOOKING_NUMBER,
t.LOT_NUMBER,
t.LOT_NBR_BALES,
t.LOT_GROSS_WEIGHT,
t.LOT_NET_WEIGHT,
t.LOT_UOM,
t.LOT_QUALITY,
t.CUSTOMER,
t.SELL_PRICE_CURRENCY,
t.SELL_PRICE_UNIT,
t.SELL_PRICE,
t.SALE_INVOICE,
t.SELL_INV_AMOUNT,
t.SALE_INVOICE_DATE,
t.SELL_PREMIUM,
t.SALE_CONTRACT_NUMBER,
t.SALE_DECLARATION_KEY,
t.SHIPMENT_CHUNK_KEY,
where=(t.BOOKING_NUMBER == int(self.reference))
)
cursor.execute(*query)
rows = cursor.fetchall()
logger.info("ROWS:%s",rows)
if rows:
sale_line = None
for row in rows:
logger.info("ROW:%s",row)
#Purchase & Sale creation
LotQt = Pool().get('lot.qt')
Lot = Pool().get('lot.lot')
LotAdd = Pool().get('lot.add.line')
Currency = Pool().get('currency.currency')
Product = Pool().get('product.product')
Party = Pool().get('party.party')
Uom = Pool().get('product.uom')
Sale = Pool().get('sale.sale')
SaleLine = Pool().get('sale.line')
dec_key = str(row[16]).strip()
chunk_key = str(row[17]).strip()
lot_unit = str(row[5]).strip().lower()
product = str(row[6]).strip().upper()
lot_net_weight = Decimal(row[4])
logger.info("LOT_NET_WEIGHT:%s",lot_net_weight)
lot_gross_weight = Decimal(row[3])
lot_bales = Decimal(row[2])
lot_number = row[1]
customer = str(row[7]).strip().upper()
sell_price_currency = str(row[8]).strip().upper()
sell_price_unit = str(row[9]).strip().lower()
sell_price = Decimal(row[10])
premium = Decimal(row[14])
reference = Decimal(row[15])
logger.info("DECLARATION_KEY:%s",dec_key)
declaration = SaleLine.search(['note','=',dec_key])
if declaration:
sale_line = declaration[0]
logger.info("WITH_DEC:%s",sale_line)
vlot = sale_line.lots[0]
lqt = LotQt.search([('lot_s','=',vlot.id)])
if lqt:
for lq in lqt:
if lq.lot_p:
logger.info("VLOT_P:%s",lq.lot_p)
sale_line.quantity_theorical += round(lot_net_weight,2)
SaleLine.save([sale_line])
lq.lot_p.updateVirtualPart(round(lot_net_weight,2),self,lq.lot_s)
vlot.set_current_quantity(round(lot_net_weight,2),round(lot_gross_weight,2),1)
Lot.save([vlot])
else:
sale = Sale()
sale_line = SaleLine()
sale.party = Party.getPartyByName(customer,'CLIENT')
logger.info("SALE_PARTY:%s",sale.party)
sale.reference = reference
sale.company = 6
if sale.party.addresses:
sale.invoice_address = sale.party.addresses[0]
sale.shipment_address = sale.party.addresses[0]
if sell_price_currency == 'USC':
sale.currency = Currency.get_by_name('USD')
sale_line.enable_linked_currency = True
sale_line.linked_currency = 1
sale_line.linked_unit = Uom.get_by_name(sell_price_unit)
sale_line.linked_price = round(sell_price,4)
sale_line.unit_price = sale_line.get_price_linked_currency()
else:
sale.currency = Currency.get_by_name(sell_price_currency)
sale_line.unit_price = round(sell_price,4)
sale_line.unit = Uom.get_by_name(sell_price_unit)
sale_line.premium = premium
Sale.save([sale])
sale_line.sale = sale.id
sale_line.quantity = round(lot_net_weight,2)
sale_line.quantity_theorical = round(lot_net_weight,2)
sale_line.product = Product.get_by_name('BRAZIL COTTON')
logger.info("PRODUCT:%s",sale_line.product)
sale_line.unit = Uom.get_by_name(lot_unit)
sale_line.price_type = 'priced'
sale_line.created_by_code = False
sale_line.note = dec_key
SaleLine.save([sale_line])
#need to link the virtual part to the shipment
lqt = LotQt.search([('lot_s','=',sale_line.lots[0])])
if lqt:
lqt[0].lot_shipment_in = self
LotQt.save(lqt)
logger.info("SALE_LINKED_TO_SHIPMENT:%s",self)
ContractStart = Pool().get('contracts.start')
ContractDetail = Pool().get('contract.detail')
ct = ContractStart()
d = ContractDetail()
ct.type = 'Purchase'
ct.matched = True
ct.shipment_in = self
ct.lot = sale_line.lots[0]
ct.product = sale_line.product
ct.unit = sale_line.unit
d.party = Party.getPartyByName('FAIRCOT')
if sale_line.enable_linked_currency:
d.currency_unit = str(sale_line.linked_currency.id) + '_' + str(sale_line.linked_unit.id)
else:
d.currency_unit = str(sale.currency.id) + '_' + str(sale_line.unit.id)
d.quantity = sale_line.quantity
d.unit = sale_line.unit
d.price = sale_line.unit_price
d.price_type = 'priced'
d.crop = None
d.tol_min = 0
d.tol_max = 0
d.incoterm = None
d.reference = str(sale.id)
d.del_period = None
d.from_del = None
d.to_del = None
ct.contracts = [d]
ContractFactory.create_contracts(
ct.contracts,
type_=ct.type,
ct=ct,
)
#Lots creation
vlot = sale_line.lots[0]
lqt = LotQt.search([('lot_s','=',vlot.id),('lot_p','>',0)])
if lqt and vlot.lot_quantity > 0:
lqt = lqt[0]
l = LotAdd()
l.lot_qt = lot_bales
l.lot_unit = Uom.get_by_name('bale')
l.lot_unit_line = Uom.get_by_name(lot_unit)
l.lot_quantity = round(lot_net_weight,2)
l.lot_gross_quantity = round(lot_gross_weight,2)
l.lot_premium = premium
l.lot_chunk_key = int(chunk_key)
logger.info("ADD_LOT:%s",int(chunk_key))
LotQt.add_physical_lots(lqt,[l])
return sale_line
@classmethod
@ModelView.button
def compute(cls, shipments):

View File

@@ -1,4 +1,5 @@
<tree>
<field name="area"/>
<field name="percent"/>
<field name="achieved_percent"/>
</tree>