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]) ShipmentWR.save([swr])
doc.notes = (doc.notes or "") + f"Shipment found: {sh[0].number}\n" doc.notes = (doc.notes or "") + f"Shipment found: {sh[0].number}\n"
logger.info("BL_NUMBER:%s",sh[0].bl_number) logger.info("BL_NUMBER:%s",sh[0].bl_number)
t = Table('freight_booking_lots') sale_line = sh[0]._create_lots_from_fintrade()
cursor = Transaction().connection.cursor() if sale_line:
query = t.select( logger.info("CREATE_FINTRADE_WR_FOR_SL:%s",sale_line)
t.BOOKING_NUMBER, weight_total = sum([l.lot_quantity for l in sale_line.lots if l.lot_type == 'physic'])
t.LOT_NUMBER, factor = weight_total / wr.net_landed_kg if wr.net_landed_kg else 1
t.LOT_NBR_BALES, for lot in sale_line.lots:
t.LOT_GROSS_WEIGHT, if lot.lot_type == 'physic':
t.LOT_NET_WEIGHT, wr_payload = {
t.LOT_UOM, "chunk_key": lot.lot_chunk_key,
t.LOT_QUALITY, "gross_weight": float(round(lot.lot_gross_quantity / factor,5)),
t.CUSTOMER, "net_weight": float(round(lot.lot_quantity / factor,5)),
t.SELL_PRICE_CURRENCY, "tare_total": float(round(wr.tare_kg * (lot.lot_quantity / weight_total),5)) ,
t.SELL_PRICE_UNIT, "bags": int(wr.bales * (lot.lot_quantity / weight_total)),
t.SELL_PRICE, "surveyor_code": 231,
t.SALE_INVOICE, "place_key": 0,
t.SELL_INV_AMOUNT, "report_date": 20260127
t.SALE_INVOICE_DATE, }
t.SELL_PREMIUM, logger.info("PAYLOAD:%s",wr_payload)
t.SALE_CONTRACT_NUMBER, data = doc.create_weight_report(wr_payload)
t.SALE_DECLARATION_KEY, doc.notes = (doc.notes or "") + f"WR created in Fintrade: {data.get('success')}\n"
t.SHIPMENT_CHUNK_KEY, doc.notes = (doc.notes or "") + f"WR key: {data.get('weight_report_key')}\n"
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"
# if cls.rule_set.ocr_required:[] # if cls.rule_set.ocr_required:[]
# cls.run_ocr([doc]) # cls.run_ocr([doc])

View File

@@ -308,7 +308,8 @@ class AutomationCron(ModelSQL, ModelView):
# Sauvegarder ce shipment uniquement # Sauvegarder ce shipment uniquement
ShipmentIn.save([shipment]) ShipmentIn.save([shipment])
shipment._create_lots_from_fintrade()
shipment.get_controller()
trans_shipment.commit() trans_shipment.commit()
successful_shipments += 1 successful_shipments += 1
logger.info(f"✓ Shipment {si_number} créé avec succès") 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) children.append(child)
else: else:
child = cls( child = cls(
name='mail.txt', name='mail_' + message.get('subject', 'No Subject') + '.txt',
company=rule.document_incoming_company, company=rule.document_incoming_company,
data=body_bytes, data=body_bytes,
type=rule.document_incoming_type, type=rule.document_incoming_type,

View File

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

View File

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

View File

@@ -16,6 +16,7 @@ from itertools import chain, groupby
from operator import itemgetter from operator import itemgetter
import datetime import datetime
from collections import defaultdict from collections import defaultdict
from sql import Table
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -444,6 +445,183 @@ class ShipmentIn(metaclass=PoolMeta):
else: else:
return str(self.id) 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 @classmethod
@ModelView.button @ModelView.button
def compute(cls, shipments): def compute(cls, shipments):

View File

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