from decimal import Decimal from trytond.pool import Pool, PoolMeta class Invoice(metaclass=PoolMeta): __name__ = 'account.invoice' def _get_report_invoice_line(self): for line in self.lines or []: if getattr(line, 'type', None) == 'line': return line return self.lines[0] if self.lines else None def _get_report_purchase(self): purchases = list(self.purchases or []) return purchases[0] if purchases else None def _get_report_sale(self): # Bridge invoice templates to the originating sale so FODT files can # reuse stable sale.report_* properties instead of complex expressions. sales = list(self.sales or []) return sales[0] if sales else None def _get_report_trade(self): return self._get_report_sale() or self._get_report_purchase() def _get_report_purchase_line(self): purchase = self._get_report_purchase() if purchase and purchase.lines: return purchase.lines[0] def _get_report_sale_line(self): sale = self._get_report_sale() if sale and sale.lines: return sale.lines[0] def _get_report_trade_line(self): return self._get_report_sale_line() or self._get_report_purchase_line() def _get_report_lot(self): line = self._get_report_trade_line() if line and line.lots: for lot in line.lots: if lot.lot_type == 'physic': return lot return line.lots[0] def _get_report_freight_fee(self): pool = Pool() Fee = pool.get('fee.fee') shipment = self._get_report_shipment() if not shipment: return None fees = Fee.search([ ('shipment_in', '=', shipment.id), ('product.name', '=', 'Maritime freight'), ], limit=1) return fees[0] if fees else None def _get_report_shipment(self): lot = self._get_report_lot() if not lot: return None return ( getattr(lot, 'lot_shipment_in', None) or getattr(lot, 'lot_shipment_out', None) or getattr(lot, 'lot_shipment_internal', None) ) @property def report_address(self): trade = self._get_report_trade() if trade and trade.report_address: return trade.report_address if self.invoice_address and self.invoice_address.full_address: return self.invoice_address.full_address return '' @property def report_contract_number(self): trade = self._get_report_trade() if trade and trade.full_number: return trade.full_number return self.origins or '' @property def report_shipment(self): trade = self._get_report_trade() if trade and trade.report_shipment: return trade.report_shipment return self.description or '' @property def report_trader_initial(self): trade = self._get_report_trade() if trade and getattr(trade, 'trader', None): return trade.trader.initial or '' return '' @property def report_origin(self): trade = self._get_report_trade() if trade and getattr(trade, 'product_origin', None): return trade.product_origin or '' return '' @property def report_operator_initial(self): trade = self._get_report_trade() if trade and getattr(trade, 'operator', None): return trade.operator.initial or '' return '' @property def report_product_description(self): line = self._get_report_trade_line() if line and line.product: return line.product.description or '' return '' @property def report_description_upper(self): if self.lines: return (self.lines[0].description or '').upper() return '' @property def report_crop_name(self): trade = self._get_report_trade() if trade and getattr(trade, 'crop', None): return trade.crop.name or '' return '' @property def report_attributes_name(self): line = self._get_report_trade_line() if line: return getattr(line, 'attributes_name', '') or '' return '' @property def report_price(self): trade = self._get_report_trade() if trade and trade.report_price: return trade.report_price return '' @property def report_rate_currency_upper(self): line = self._get_report_invoice_line() if line: return line.report_rate_currency_upper return '' @property def report_rate_value(self): line = self._get_report_invoice_line() if line: return line.report_rate_value return '' @property def report_rate_unit_upper(self): line = self._get_report_invoice_line() if line: return line.report_rate_unit_upper return '' @property def report_rate_price_words(self): line = self._get_report_invoice_line() if line: return line.report_rate_price_words return self.report_price or '' @property def report_rate_pricing_text(self): line = self._get_report_invoice_line() if line: return line.report_rate_pricing_text return '' @property def report_payment_date(self): trade = self._get_report_trade() if trade and trade.report_payment_date: return trade.report_payment_date return '' @property def report_payment_description(self): trade = self._get_report_trade() if trade and trade.payment_term: return trade.payment_term.description or '' if self.payment_term: return self.payment_term.description or '' return '' @property def report_nb_bale(self): sale = self._get_report_sale() if sale and sale.report_nb_bale: return sale.report_nb_bale line = self._get_report_trade_line() if line and line.lots: nb_bale = sum( lot.lot_qt for lot in line.lots if lot.lot_type == 'physic' ) return 'NB BALES: ' + str(int(nb_bale)) return '' @property def report_gross(self): sale = self._get_report_sale() if sale and sale.report_gross != '': return sale.report_gross line = self._get_report_trade_line() if line and line.lots: return sum( lot.get_current_gross_quantity() for lot in line.lots if lot.lot_type == 'physic' ) return '' @property def report_net(self): trade = self._get_report_trade() if trade and getattr(trade, 'report_net', '') != '': return trade.report_net line = self._get_report_trade_line() if line and line.lots: return sum( lot.get_current_quantity() for lot in line.lots if lot.lot_type == 'physic' ) if self.lines: return self.lines[0].quantity return '' @property def report_lbs(self): net = self.report_net if net == '': return '' return round(Decimal(net) * Decimal('2204.62'),2) @property def report_bl_date(self): shipment = self._get_report_shipment() if shipment: return shipment.bl_date @property def report_bl_nb(self): shipment = self._get_report_shipment() if shipment: return shipment.bl_number @property def report_vessel(self): shipment = self._get_report_shipment() if shipment and shipment.vessel: return shipment.vessel.vessel_name @property def report_loading_port(self): shipment = self._get_report_shipment() if shipment and shipment.from_location: return shipment.from_location.rec_name return '' @property def report_discharge_port(self): shipment = self._get_report_shipment() if shipment and shipment.to_location: return shipment.to_location.rec_name return '' @property def report_incoterm(self): trade = self._get_report_trade() if not trade: return '' incoterm = trade.incoterm.code if getattr(trade, 'incoterm', None) else '' location = ( trade.incoterm_location.party_name if getattr(trade, 'incoterm_location', None) else '' ) if incoterm and location: return f"{incoterm} {location}" return incoterm or location @property def report_proforma_invoice_number(self): lot = self._get_report_lot() if lot: line = ( getattr(lot, 'sale_invoice_line_prov', None) or getattr(lot, 'invoice_line_prov', None) ) if line and line.invoice: return line.invoice.number or '' return '' @property def report_proforma_invoice_date(self): lot = self._get_report_lot() if lot: line = ( getattr(lot, 'sale_invoice_line_prov', None) or getattr(lot, 'invoice_line_prov', None) ) if line and line.invoice: return line.invoice.invoice_date @property def report_controller_name(self): shipment = self._get_report_shipment() if shipment and shipment.controller: return shipment.controller.rec_name return '' @property def report_si_number(self): shipment = self._get_report_shipment() if shipment: return shipment.number or '' return '' @property def report_freight_amount(self): fee = self._get_report_freight_fee() if fee: return fee.get_amount() return '' @property def report_freight_currency_symbol(self): fee = self._get_report_freight_fee() if fee and fee.currency: return fee.currency.symbol or '' if self.currency: return self.currency.symbol or '' return 'USD' class InvoiceLine(metaclass=PoolMeta): __name__ = 'account.invoice.line' def _get_report_trade(self): origin = getattr(self, 'origin', None) if not origin: return None return getattr(origin, 'sale', None) or getattr(origin, 'purchase', None) def _get_report_trade_line(self): return getattr(self, 'origin', None) @property def report_product_description(self): if self.product: return self.product.description or '' origin = getattr(self, 'origin', None) if origin and getattr(origin, 'product', None): return origin.product.description or '' return '' @property def report_description_upper(self): return (self.description or '').upper() @property def report_rate_currency_upper(self): origin = self._get_report_trade_line() currency = getattr(origin, 'linked_currency', None) or self.currency if currency and currency.rec_name: return currency.rec_name.upper() return '' @property def report_rate_value(self): return self.unit_price if self.unit_price is not None else '' @property def report_rate_unit_upper(self): origin = self._get_report_trade_line() unit = getattr(origin, 'linked_unit', None) or self.unit if unit and unit.rec_name: return unit.rec_name.upper() return '' @property def report_rate_price_words(self): trade = self._get_report_trade() if trade and getattr(trade, 'report_price', None): return trade.report_price return '' @property def report_rate_pricing_text(self): origin = self._get_report_trade_line() return getattr(origin, 'get_pricing_text', '') or '' @property def report_crop_name(self): trade = self._get_report_trade() if trade and getattr(trade, 'crop', None): return trade.crop.name or '' return '' @property def report_attributes_name(self): origin = getattr(self, 'origin', None) if origin: return getattr(origin, 'attributes_name', '') or '' return '' @property def report_net(self): if self.type == 'line': return self.quantity return '' @property def report_lbs(self): net = self.report_net if net == '': return '' return round(Decimal(net) * Decimal('2204.62'),2)