708 lines
25 KiB
Python
708 lines
25 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from datetime import timedelta, date
|
|
from itertools import chain
|
|
from sql import Table
|
|
from decimal import Decimal
|
|
|
|
from trytond.model import fields, ModelSQL, ModelView
|
|
from trytond.wizard import (
|
|
Wizard, StateView, Button, StateTransition, StateReport)
|
|
from trytond.pool import PoolMeta, Pool
|
|
from trytond.pyson import Eval
|
|
from trytond.transaction import Transaction
|
|
from trytond.exceptions import UserError
|
|
from trytond.report import Report
|
|
|
|
STATES = {
|
|
'readonly': Eval('state') == 'done'
|
|
}
|
|
|
|
|
|
class Sale(metaclass=PoolMeta):
|
|
__name__ = 'sale.sale'
|
|
carrier = fields.Many2One('party.party', 'Carrier', states=STATES)
|
|
freight_forwader = fields.Many2One('party.party', 'Freight Forwader',
|
|
states=STATES, help="The agent")
|
|
mawb = fields.Char('MAWB', states=STATES)
|
|
hawb = fields.Char('HAWB', states=STATES)
|
|
charge = fields.Many2One('exportation.charge', 'Charge', states={
|
|
'readonly': False,
|
|
})
|
|
export_target_city = fields.Many2One('party.city_code',
|
|
'Export Target City', required=True, select=True)
|
|
export_route = fields.Char('Export Route', select=True)
|
|
boxes = fields.Function(fields.Float('Boxes', digits=(6, 2)),
|
|
'get_lines_totals')
|
|
unit_qty = fields.Function(fields.Float('Unit Qty', digits=(6, 0)),
|
|
'get_lines_totals')
|
|
packing_qty = fields.Function(fields.Float('Packing Qty', digits=(6, 0)),
|
|
'get_lines_totals')
|
|
quantity = fields.Function(fields.Float('Quantity', digits=(6, 0)),
|
|
'get_lines_totals')
|
|
aged = fields.Function(fields.Integer('Aged'), 'get_aged')
|
|
total_amount_ref = fields.Function(fields.Numeric('Total Amount Ref.',
|
|
digits=(6, 2)), 'get_total_amount_ref')
|
|
custom_global = fields.Many2One('party.customs_global', 'Global',
|
|
domain=[('party', '=', Eval('party'))])
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(Sale, cls).__setup__()
|
|
cls.shipping_date.states = {
|
|
'readonly': Eval('state') == 'done',
|
|
}
|
|
cls.lines.states = {
|
|
'readonly': Eval('state') == 'done',
|
|
}
|
|
|
|
@fields.depends('party', 'invoice_party', 'shipment_party',
|
|
'payment_term', 'currency', 'carrier', 'freight_forwader')
|
|
def on_change_party(self):
|
|
super(Sale, self).on_change_party()
|
|
if self.party:
|
|
if self.party.currency:
|
|
self.currency = self.party.currency.id
|
|
if self.party.carrier:
|
|
self.carrier = self.party.carrier.id
|
|
if self.party.freight_forwader:
|
|
self.freight_forwader = self.party.freight_forwader.id
|
|
if self.party.addresses:
|
|
city_code = self.party.addresses[0].city_code
|
|
self.export_target_city = city_code.id if city_code else None
|
|
if self.party.export_route:
|
|
self.export_route = self.party.export_route
|
|
|
|
@classmethod
|
|
def _get_untaxed_amount(cls, sale):
|
|
return sum(
|
|
(line.amount for line in sale.lines
|
|
if line.type == 'line'), Decimal(0)
|
|
)
|
|
|
|
def get_total_amount_ref(self, name=None):
|
|
res = []
|
|
for line in self.lines:
|
|
if line.unit_price_ref:
|
|
res.append(Decimal(line.quantity) * line.unit_price_ref)
|
|
return sum(res)
|
|
|
|
@classmethod
|
|
def process(cls, sales):
|
|
sale = sales[0]
|
|
sale.untaxed_amount_cache = cls._get_untaxed_amount(sale)
|
|
sale.tax_amount_cache = sale.get_tax_amount()
|
|
sale.total_amount_cache = sale.tax_amount_cache + sale.untaxed_amount_cache
|
|
sale.save()
|
|
super(Sale, cls).process(sales)
|
|
for sale in sales:
|
|
for line in sale.lines:
|
|
if not line.production and line.product.template.producible:
|
|
production_id = cls.create_production(line)
|
|
if production_id:
|
|
line.production = production_id
|
|
line.save()
|
|
|
|
@classmethod
|
|
def copy(cls, sales, default=None):
|
|
if default is None:
|
|
default = {}
|
|
else:
|
|
default = default.copy()
|
|
default.setdefault('shipping_date', None)
|
|
return super(Sale, cls).copy(sales, default)
|
|
|
|
@classmethod
|
|
def create_production(cls, line):
|
|
pool = Pool()
|
|
Production = pool.get('production')
|
|
sale = line.sale
|
|
planned_date = sale.shipping_date - timedelta(days=1)
|
|
if planned_date < sale.sale_date:
|
|
planned_date = sale.sale_date
|
|
data = {
|
|
'reference': sale.reference or sale.number,
|
|
'customer': sale.party.id,
|
|
'delivery_date': sale.shipping_date,
|
|
'planned_date': sale.shipping_date,
|
|
'planned_start_date': sale.shipping_date,
|
|
'effective_date': sale.shipping_date,
|
|
'effective_start_date': sale.shipping_date,
|
|
'company': sale.company.id,
|
|
'warehouse': sale.warehouse.id,
|
|
'location': sale.warehouse.production_location.id,
|
|
'product': line.product.id,
|
|
'uom': line.packing_uom.id,
|
|
'quantity': line.packing_qty,
|
|
'state': 'request',
|
|
'primary': True,
|
|
'origin': str(line),
|
|
'factor_packing': line.factor_packing,
|
|
'outputs': [('create', [{
|
|
'product': line.product.id,
|
|
'quantity': line.packing_qty,
|
|
'uom': line.packing_uom.id,
|
|
'unit_price': line.product.cost_price,
|
|
'from_location': sale.warehouse.production_location.id,
|
|
'to_location': sale.warehouse.storage_location.id,
|
|
}])],
|
|
}
|
|
_inputs = []
|
|
subproductions = []
|
|
for kit in line.kits:
|
|
input = {
|
|
'product': kit.product.id,
|
|
'quantity': kit.quantity * line.packing_qty,
|
|
'uom': kit.product.default_uom.id,
|
|
'from_location': sale.warehouse.storage_location.id,
|
|
'to_location': sale.warehouse.production_location.id,
|
|
'style': kit.style.id if kit.style else None,
|
|
}
|
|
if kit.product.producible:
|
|
_production = cls._get_production(kit, sale, line)
|
|
input['production'] = _production
|
|
subproductions.append(_production)
|
|
_inputs.append(input)
|
|
data['inputs'] = [('create', _inputs)]
|
|
data['subproductions'] = [('add', subproductions)]
|
|
if data:
|
|
data['state'] = 'waiting'
|
|
productions = Production.create([data])
|
|
if productions:
|
|
return productions[0].id
|
|
|
|
@classmethod
|
|
def _get_production(cls, kit, sale, line):
|
|
pool = Pool()
|
|
Production = pool.get('production')
|
|
data = {
|
|
'reference': sale.number + ' | ' + line.summary,
|
|
'company': sale.company.id,
|
|
'customer': sale.party.id,
|
|
'warehouse': sale.warehouse.id,
|
|
'delivery_date': sale.shipping_date,
|
|
'location': sale.warehouse.production_location.id,
|
|
'planned_date': sale.shipping_date,
|
|
'planned_start_date': sale.shipping_date,
|
|
'effective_date': sale.shipping_date,
|
|
'effective_start_date': sale.shipping_date,
|
|
'product': kit.product.id,
|
|
'uom': kit.product.default_uom.id,
|
|
'quantity': kit.quantity * line.packing_qty,
|
|
'state': 'waiting',
|
|
'origin': str(line),
|
|
'outputs': [('create', [{
|
|
'product': kit.product.id,
|
|
'quantity': kit.quantity * line.packing_qty,
|
|
'uom': kit.uom.id,
|
|
'unit_price': kit.product.cost_price,
|
|
'from_location': sale.warehouse.production_location.id,
|
|
'to_location': sale.warehouse.storage_location.id,
|
|
}])],
|
|
}
|
|
inputs = []
|
|
for com in kit.components:
|
|
inputs.append({
|
|
'product': com.product.id,
|
|
'quantity': com.quantity * kit.quantity * line.packing_qty * com.product.default_uom.rate,
|
|
'uom': com.product.default_uom.id,
|
|
'from_location': sale.warehouse.storage_location.id,
|
|
'to_location': sale.warehouse.production_location.id,
|
|
'style': com.style.id if com.style else None,
|
|
})
|
|
data['inputs'] = [('create', inputs)]
|
|
data['state'] = 'waiting'
|
|
pruduction, = Production.create([data])
|
|
return pruduction.id
|
|
|
|
def get_aged(self, name=None):
|
|
if self.sale_date:
|
|
aged = (date.today() - self.shipping_date).days
|
|
return aged
|
|
|
|
def get_lines_totals(self, name=None):
|
|
return sum(getattr(line, name) or 0 for line in self.lines)
|
|
|
|
|
|
class SaleLine(metaclass=PoolMeta):
|
|
__name__ = 'sale.line'
|
|
factor_packing = fields.Float('Factor Packing')
|
|
reference = fields.Function(fields.Char('Reference'), 'get_reference')
|
|
customer = fields.Function(fields.Many2One('party.party',
|
|
'Customer'), 'get_customer')
|
|
boxes = fields.Function(fields.Float('Boxes', digits=(6, 2)),
|
|
'on_change_with_boxes')
|
|
unit_qty = fields.Function(fields.Float('Unit Qty', digits=(10, 0)),
|
|
'on_change_with_unit_qty')
|
|
packing_uom = fields.Many2One('product.uom', 'Packing UoM')
|
|
packing_qty = fields.Float('Packing Qty')
|
|
kits = fields.One2Many('sale.line.kit', 'line', 'Line Kit')
|
|
productions = fields.One2Many('production', 'origin', 'Productions')
|
|
charge_line = fields.Many2One('exportation.charge.line', 'Charge Line')
|
|
production = fields.Many2One('production', 'Production')
|
|
quality_analysis = fields.One2Many('farming.quality.analysis', 'origin',
|
|
'Quality Analysis', states=STATES)
|
|
unit_price_ref = fields.Numeric('Price Ref.', digits=(6, 2))
|
|
amount_ref = fields.Function(fields.Numeric('Amount Ref.',
|
|
digits=(6, 2)), 'get_amount_ref')
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(SaleLine, cls).__setup__()
|
|
cls.unit_price.states = {
|
|
'invisible': Eval('type') != 'line',
|
|
'required': Eval('type') == 'line',
|
|
'readonly': Eval('sale_state') == 'done'
|
|
}
|
|
|
|
@classmethod
|
|
def copy(cls, lines, default=None):
|
|
if default is None:
|
|
default = {}
|
|
else:
|
|
default = default.copy()
|
|
default.setdefault('production', None)
|
|
default.setdefault('charge_line', None)
|
|
return super(SaleLine, cls).copy(lines, default)
|
|
|
|
@fields.depends('quantity', 'unit')
|
|
def on_change_with_unit_qty(self, name=None):
|
|
if self.quantity and self.unit:
|
|
res = self.quantity * self.unit.factor
|
|
return res
|
|
|
|
@fields.depends('packing_qty', 'factor_packing')
|
|
def on_change_with_quantity(self):
|
|
if self.packing_qty and self.factor_packing:
|
|
return self.packing_qty * self.factor_packing
|
|
|
|
@fields.depends('packing_qty', 'packing_uom')
|
|
def on_change_with_boxes(self, name=None):
|
|
if self.packing_qty and self.packing_uom:
|
|
return self.packing_qty * self.packing_uom.factor
|
|
|
|
@fields.depends('kits', 'product', 'description')
|
|
def on_change_kits(self, name=None):
|
|
if self.product and self.kits:
|
|
string_ = [
|
|
ki.product.template.name
|
|
for ki in self.kits if ki.product and ki.product.template.farming]
|
|
if not string_:
|
|
return
|
|
desc_full = ' | '.join([self.product.rec_name] + string_)
|
|
self.description = desc_full
|
|
|
|
def get_amount_ref(self, name=None):
|
|
if self.unit_price_ref and self.quantity:
|
|
return Decimal(self.quantity) * self.unit_price_ref
|
|
|
|
def get_customer(self, name=None):
|
|
if self.sale:
|
|
return self.sale.party.id
|
|
|
|
def get_reference(self, name=None):
|
|
if self.sale:
|
|
return self.sale.reference
|
|
|
|
def _get_invoice_line_quantity(self):
|
|
qty = self.quantity
|
|
if self.sale.invoice_method != 'manual':
|
|
qty = super(SaleLine, self)._get_invoice_line_quantity()
|
|
return qty
|
|
|
|
|
|
class SaleLineKit(ModelSQL, ModelView):
|
|
"Sale Line Kit"
|
|
__name__ = "sale.line.kit"
|
|
line = fields.Many2One('sale.line', 'Line', required=True,
|
|
ondelete='CASCADE')
|
|
product = fields.Many2One('product.product', 'Product', required=True,
|
|
domain=[('type', '=', 'goods')])
|
|
uom = fields.Many2One('product.uom', 'UoM')
|
|
quantity = fields.Integer('Quantity', required=True)
|
|
notes = fields.Char('Notes')
|
|
components = fields.One2Many('sale.line.kit.component', 'kit', 'Components')
|
|
style = fields.Many2One('product.style', 'Style')
|
|
|
|
@fields.depends('product', 'uom')
|
|
def on_change_with_uom(self, name=None):
|
|
if self.product:
|
|
return self.product.default_uom.id
|
|
|
|
@staticmethod
|
|
def default_quantity():
|
|
return 1
|
|
|
|
|
|
class SaleLineKitComponent(ModelSQL, ModelView):
|
|
"Sale Line Component"
|
|
__name__ = "sale.line.kit.component"
|
|
kit = fields.Many2One('sale.line.kit', 'Kit', ondelete='CASCADE',
|
|
required=True)
|
|
product = fields.Many2One('product.product', 'Product', required=True,
|
|
domain=[('type', '=', 'goods')])
|
|
quantity = fields.Float('Quantity', digits=(2, 2))
|
|
notes = fields.Char('Notes')
|
|
style = fields.Many2One('product.style', 'Style')
|
|
|
|
@staticmethod
|
|
def default_quantity():
|
|
return 1
|
|
|
|
|
|
class SaleForceDraft(Wizard):
|
|
__name__ = 'sale_co.force_draft'
|
|
|
|
def transition_force_draft(self):
|
|
Sale = Pool().get('sale.sale')
|
|
Production = Pool().get('production')
|
|
ids = Transaction().context['active_ids']
|
|
if not ids:
|
|
return 'end'
|
|
sales = Sale.browse(ids)
|
|
for sale in sales:
|
|
for line in sale.lines:
|
|
productions = Production.search([
|
|
('origin', '=', str(line)),
|
|
])
|
|
for pd in productions:
|
|
if pd.state in ['assigned', 'running', 'done']:
|
|
raise UserError(
|
|
'No se puede borrar la produccion porque esta en proceso'
|
|
)
|
|
else:
|
|
Production.delete([pd])
|
|
|
|
super(SaleForceDraft, self).transition_force_draft()
|
|
return 'end'
|
|
|
|
|
|
class GroupingSalesStart(ModelView):
|
|
'Grouping Sales Start'
|
|
__name__ = 'sale.grouping_sales.start'
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
customer = fields.Many2One('party.party', 'Customer', required=True)
|
|
currency = fields.Many2One('currency.currency', 'Currency', required=True)
|
|
start_date = fields.Date("Start Date", required=True)
|
|
end_date = fields.Date("End Date", required=True)
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
|
|
class GroupingSales(Wizard):
|
|
'Grouping Sales'
|
|
__name__ = 'sale.grouping_sales'
|
|
start = StateView(
|
|
'sale.grouping_sales.start',
|
|
'farming.grouping_sales_start_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Ok', 'accept', 'tryton-ok', default=True),
|
|
])
|
|
accept = StateTransition()
|
|
|
|
def _create_invoice(self, lines, sale):
|
|
invoice_lines = []
|
|
for line in lines:
|
|
invoice_lines.append(line.get_invoice_line())
|
|
invoice_lines = list(chain(*invoice_lines))
|
|
if not invoice_lines:
|
|
return
|
|
|
|
invoice = sale._get_invoice_sale()
|
|
if getattr(invoice, 'lines', None):
|
|
invoice_lines = list(invoice.lines) + invoice_lines
|
|
invoice.lines = invoice_lines
|
|
invoice.save()
|
|
|
|
invoice.update_taxes()
|
|
sale.copy_resources_to(invoice)
|
|
return invoice
|
|
|
|
def transition_accept(self):
|
|
pool = Pool()
|
|
Sale = pool.get('sale.sale')
|
|
dom = ['OR', [
|
|
('state', 'in', ['confirmed', 'processing', 'done']),
|
|
('invoice_state', '=', 'none'),
|
|
('party', '=', self.start.customer.id),
|
|
('invoice_party', '=', None),
|
|
('currency', '=', self.start.currency.id),
|
|
('shipping_date', '>=', self.start.start_date),
|
|
('shipping_date', '<=', self.start.end_date),
|
|
], [
|
|
('state', 'in', ['confirmed', 'processing', 'done']),
|
|
('invoice_state', '=', 'none'),
|
|
('invoice_party', '=', self.start.customer.id),
|
|
('currency', '=', self.start.currency.id),
|
|
('shipping_date', '>=', self.start.start_date),
|
|
('shipping_date', '<=', self.start.end_date),
|
|
]]
|
|
|
|
sales = Sale.search(dom, order=[('shipping_date', 'ASC')])
|
|
if not sales:
|
|
return 'end'
|
|
|
|
lines_to_bill = []
|
|
for sale in sales:
|
|
if sale.invoices:
|
|
continue
|
|
for line in sale.lines:
|
|
lines_to_bill.append(line)
|
|
|
|
if lines_to_bill:
|
|
self._create_invoice(lines_to_bill, sales[0])
|
|
return 'end'
|
|
|
|
|
|
class ReturnSale(metaclass=PoolMeta):
|
|
__name__ = 'sale.return_sale'
|
|
|
|
def do_return_(self, action):
|
|
sales = self.records
|
|
return_sales = self.model.copy(sales)
|
|
for return_sale, sale in zip(return_sales, sales):
|
|
return_sale.origin = sale
|
|
for line in return_sale.lines:
|
|
line.production = None
|
|
if line.type == 'line':
|
|
line.quantity *= -1
|
|
return_sale.lines = return_sale.lines # Force saving
|
|
|
|
self.model.save(return_sales)
|
|
|
|
data = {'res_id': [s.id for s in return_sales]}
|
|
if len(return_sales) == 1:
|
|
action['views'].reverse()
|
|
return action, data
|
|
|
|
|
|
class SaleChangeProcessing(Wizard):
|
|
__name__ = 'sale.change_processing'
|
|
start_state = 'change_processing'
|
|
change_processing = StateTransition()
|
|
|
|
def transition_change_processing(self):
|
|
Sale = Pool().get('sale.sale')
|
|
sale_table = Table('sale_sale')
|
|
cursor = Transaction().connection.cursor()
|
|
sale_id = Transaction().context['active_id']
|
|
if not sale_id:
|
|
return 'end'
|
|
|
|
sale, = Sale.browse([sale_id])
|
|
if sale.state in ['done', 'processing'] and sale.id:
|
|
cursor.execute(*sale_table.update(
|
|
columns=[
|
|
sale_table.state,
|
|
sale_table.untaxed_amount_cache,
|
|
sale_table.tax_amount_cache,
|
|
sale_table.total_amount_cache],
|
|
values=['processing', 0, 0, 0],
|
|
where=sale_table.id == sale.id)
|
|
)
|
|
return 'end'
|
|
|
|
|
|
class PortfolioDetailedStart(ModelView):
|
|
'Portfolio Detailed Start'
|
|
__name__ = 'farming.portfolio_detailed.start'
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
to_date = fields.Date('To Date')
|
|
parties = fields.Many2Many('party.party', None, None, 'Parties')
|
|
type = fields.Selection([
|
|
('out', 'Customer'),
|
|
], 'Type', required=True)
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@staticmethod
|
|
def default_type():
|
|
return 'out'
|
|
|
|
|
|
class PortfolioDetailed(Wizard):
|
|
'Portfolio Detailed'
|
|
__name__ = 'farming.portfolio_detailed'
|
|
start = StateView(
|
|
'farming.portfolio_detailed.start',
|
|
'farming.print_sale_portfolio_detailed_start_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Print', 'print_', 'tryton-ok', default=True),
|
|
])
|
|
print_ = StateReport('farming.portfolio_detailed.report')
|
|
|
|
def do_print_(self, action):
|
|
parties_ids = [p.id for p in self.start.parties]
|
|
data = {
|
|
'company': self.start.company.id,
|
|
'type': self.start.type,
|
|
'to_date': self.start.to_date,
|
|
'parties': parties_ids,
|
|
}
|
|
return action, data
|
|
|
|
def transition_print_(self):
|
|
return 'end'
|
|
|
|
|
|
class PortfolioDetailedReport(Report):
|
|
__name__ = 'farming.portfolio_detailed.report'
|
|
|
|
@classmethod
|
|
def get_domain_inv(cls, dom_sales, data):
|
|
dom_sales.append([
|
|
('company', '=', data['company']),
|
|
])
|
|
|
|
if data['parties']:
|
|
dom_sales.append(
|
|
('party', 'in', data['parties'])
|
|
)
|
|
|
|
if data['to_date']:
|
|
dom_sales.append(
|
|
('shipping_date', '<=', data['to_date']),
|
|
)
|
|
return dom_sales
|
|
|
|
@classmethod
|
|
def get_context(cls, records, header, data):
|
|
report_context = super().get_context(records, header, data)
|
|
|
|
pool = Pool()
|
|
Sale = pool.get('sale.sale')
|
|
dom_sales = []
|
|
dom_sales = cls.get_domain_inv(dom_sales, data)
|
|
sales = Sale.search(
|
|
dom_sales,
|
|
order=[('party.name', 'ASC'), ('shipping_date', 'ASC')]
|
|
)
|
|
salesmans = {}
|
|
for sale in sales:
|
|
pay_to_date = []
|
|
if data['to_date']:
|
|
for line in sale.payments:
|
|
if line.date <= data['to_date']:
|
|
pay_to_date.append(line.amount)
|
|
|
|
amount_to_pay = sale.total_amount - sum(pay_to_date)
|
|
else:
|
|
amount_to_pay = sale.residual_amount
|
|
pay_to_date = [
|
|
pay.amount for pay in sale.payments if pay.amount]
|
|
|
|
if sale.total_amount == sum(pay_to_date):
|
|
continue
|
|
|
|
if 'field_salesman' in data.keys() and \
|
|
data['field_salesman'] and sale.salesman:
|
|
if sale.salesman.id not in salesmans.keys():
|
|
salesmans[sale.salesman.id] = {
|
|
'salesman': sale.salesman.party.full_name,
|
|
'parties': {},
|
|
'total_invoices': [],
|
|
'total_amount_to_pay': [],
|
|
}
|
|
|
|
salesman = sale.salesman.id
|
|
elif 'without_seller' not in salesmans:
|
|
salesmans['without_seller'] = {
|
|
'salesman': 'without_seller',
|
|
'parties': {},
|
|
'total_invoices': [],
|
|
'total_amount_to_pay': [],
|
|
}
|
|
salesman = 'without_seller'
|
|
else:
|
|
salesman = 'without_seller'
|
|
if sale.party.id not in salesmans[salesman]['parties'].keys():
|
|
salesmans[salesman]['parties'][sale.party.id] = {
|
|
'party': sale.party,
|
|
'invoices': [],
|
|
'total_invoices': [],
|
|
'total_amount_to_pay': [],
|
|
}
|
|
|
|
party_key = salesmans[salesman]['parties'][sale.party.id]
|
|
salesmans[salesman]['total_invoices'].append(sale.total_amount)
|
|
salesmans[salesman]['total_amount_to_pay'].append(amount_to_pay)
|
|
party_key['invoices'].append(sale)
|
|
party_key['total_invoices'].append(sale.total_amount)
|
|
party_key['total_amount_to_pay'].append(amount_to_pay)
|
|
|
|
report_context['records'] = salesmans
|
|
report_context['data'] = data
|
|
return report_context
|
|
|
|
|
|
class AduanaDetailedStart(ModelView):
|
|
'Portfolio Detailed Start'
|
|
__name__ = 'farming.aduana_detailed.start'
|
|
|
|
date = fields.Date('date')
|
|
|
|
|
|
class AduanaDetailed(Wizard):
|
|
'Aduana Detailed'
|
|
__name__ = 'farming.aduana_detailed'
|
|
start = StateView(
|
|
'farming.aduana_detailed.start',
|
|
'farming.aduana_detailed_start_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Print', 'print_', 'tryton-ok', default=True),
|
|
])
|
|
print_ = StateReport('farming.aduana_detailed.report')
|
|
|
|
def do_print_(self, action):
|
|
data = {
|
|
'date': self.start.date,
|
|
}
|
|
return action, data
|
|
|
|
def transition_print_(self):
|
|
return 'end'
|
|
|
|
|
|
class AduanaDetailedReport(Report):
|
|
__name__ = 'farming.aduana_detailed.report'
|
|
|
|
@classmethod
|
|
def get_context(cls, records, header, data):
|
|
report_context = super().get_context(records, header, data)
|
|
pool = Pool()
|
|
Sale = pool.get('sale.sale')
|
|
sales = Sale.search(('shipping_date', '=', data['date']))
|
|
report_sales = {}
|
|
for sale in sales:
|
|
if sale.number:
|
|
total_weight = 0
|
|
for line in sale.lines:
|
|
if line.packing_uom.symbol == 'EB':
|
|
total_weight = total_weight + (line.packing_qty * 3.1)
|
|
elif line.packing_uom.symbol == 'QB':
|
|
total_weight = total_weight + (line.packing_qty * 7)
|
|
elif line.packing_uom.symbol == 'HB':
|
|
total_weight = total_weight + (line.packing_qty * 8.5)
|
|
|
|
report_sales[sale.number] = {
|
|
'client': sale.party.name,
|
|
'nit': sale.carrier.id_number,
|
|
'guia': sale.mawb,
|
|
'global': sale.custom_global and sale.custom_global.global_custom,
|
|
'invoice': sale.number,
|
|
'code': '0001',
|
|
'product': 'Hidrangea',
|
|
'units': sale.unit_qty,
|
|
'pieces': sale.packing_qty,
|
|
'weight': total_weight,
|
|
'total': sale.total_amount,
|
|
'license_plate': 'WHO-265',
|
|
}
|
|
report_context['records'] = report_sales.values()
|
|
|
|
return report_context
|