146 lines
5.0 KiB
Python
146 lines
5.0 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 __future__ import with_statement
|
|
from decimal import Decimal
|
|
import datetime
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.pyson import Eval
|
|
from trytond.report import Report
|
|
from trytond.transaction import Transaction
|
|
from trytond.model import ModelView, fields
|
|
from trytond.wizard import Wizard, StateView, Button, StateReport
|
|
|
|
_ZERO = Decimal('0.0')
|
|
|
|
|
|
class Invoice(metaclass=PoolMeta):
|
|
__name__ = 'account.invoice'
|
|
salesman = fields.Many2One('company.employee', 'Salesman', states={
|
|
'readonly': Eval('state') != 'draft',
|
|
'invisible': Eval('type') != 'out',
|
|
})
|
|
|
|
|
|
class PortfolioBySalesmanStart(ModelView):
|
|
'Portfolio Detailed Start'
|
|
__name__ = 'sale_salesman.portfolio_by_salesman.start'
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
to_date = fields.Date('To Date')
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
|
|
class PortfolioBySalesman(Wizard):
|
|
'Portfolio Detailed'
|
|
__name__ = 'sale_salesman.portfolio_by_salesman'
|
|
start = StateView('sale_salesman.portfolio_by_salesman.start',
|
|
'sale_salesman.print_portfolio_by_salesman_start_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Print', 'print_', 'tryton-ok', default=True),
|
|
])
|
|
print_ = StateReport('sale_salesman.portfolio_by_salesman.report')
|
|
|
|
def do_print_(self, action):
|
|
data = {
|
|
'ids': [],
|
|
'company': self.start.company.id,
|
|
'to_date': self.start.to_date,
|
|
}
|
|
return action, data
|
|
|
|
def transition_print_(self):
|
|
return 'end'
|
|
|
|
|
|
class PortfolioBySalesmanReport(Report):
|
|
__name__ = 'sale_salesman.portfolio_by_salesman.report'
|
|
|
|
@classmethod
|
|
def get_domain_invoice(cls, domain, data):
|
|
return domain, data
|
|
|
|
@classmethod
|
|
def get_context(cls, records, header, data):
|
|
report_context = super().get_context(records, header, data)
|
|
|
|
pool = Pool()
|
|
Invoice = pool.get('account.invoice')
|
|
today = pool.get('ir.date').today()
|
|
|
|
dom_invoices = [
|
|
('company', '=', data['company']),
|
|
('salesman', '!=', None),
|
|
('type', '=', 'out'),
|
|
]
|
|
|
|
states = ['posted']
|
|
|
|
if data['to_date']:
|
|
dif_date = today - data['to_date']
|
|
if dif_date and abs(dif_date) > datetime.timedelta(days=5):
|
|
states.append('paid')
|
|
dom_invoices.append(
|
|
('invoice_date', '<=', data['to_date']),
|
|
)
|
|
dom_invoices.append(
|
|
('state', 'in', states),
|
|
)
|
|
|
|
dom_invoices, data = cls.get_domain_invoice(dom_invoices, data)
|
|
invoices = Invoice.search(dom_invoices,
|
|
order=[('party.name', 'ASC'), ('invoice_date', 'ASC')]
|
|
)
|
|
|
|
salesmans = {}
|
|
|
|
for invoice in invoices:
|
|
pay_to_date = []
|
|
if data['to_date']:
|
|
if not invoice.move:
|
|
continue
|
|
|
|
move_lines_paid = []
|
|
for line in invoice.payment_lines:
|
|
if line.move.date <= data['to_date']:
|
|
pay_to_date.append(line.debit - line.credit)
|
|
move_lines_paid.append(line.id)
|
|
for line in invoice.move.lines:
|
|
if not line.reconciliation:
|
|
continue
|
|
for recline in line.reconciliation.lines:
|
|
if recline.id == line.id or line.id in move_lines_paid:
|
|
continue
|
|
if recline.move.date <= data['to_date']:
|
|
pay_to_date.append(recline.debit - recline.credit)
|
|
|
|
amount = sum(pay_to_date)
|
|
if invoice.type == 'out':
|
|
amount *= -1
|
|
if amount >= invoice.total_amount:
|
|
continue
|
|
amount_to_pay = invoice.total_amount - amount
|
|
invoice.amount_to_pay = amount_to_pay
|
|
else:
|
|
amount_to_pay = invoice.amount_to_pay
|
|
if invoice.salesman.id not in salesmans.keys():
|
|
salesmans[invoice.salesman.id] = {
|
|
'salesman': invoice.salesman.party.name,
|
|
'invoices': [],
|
|
'total_invoices': [],
|
|
'total_amount_to_pay': [],
|
|
}
|
|
|
|
aged = (today - invoice.invoice_date).days
|
|
setattr(invoice, 'aged', aged)
|
|
|
|
salesmans[invoice.salesman.id]['invoices'].append(invoice)
|
|
salesmans[invoice.salesman.id]['total_invoices'].append(
|
|
invoice.total_amount)
|
|
salesmans[invoice.salesman.id]['total_amount_to_pay'].append(
|
|
amount_to_pay)
|
|
|
|
report_context['records'] = list(salesmans.values())
|
|
return report_context
|