mirror of
https://bitbucket.org/presik/trytonpsk-account_col.git
synced 2023-12-14 05:53:00 +01:00
343 lines
12 KiB
Python
343 lines
12 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 decimal import Decimal
|
|
from collections import OrderedDict
|
|
|
|
from trytond.model import fields, ModelView
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.pyson import Eval
|
|
from trytond.wizard import Wizard, StateView, Button, StateReport
|
|
from trytond.transaction import Transaction
|
|
from trytond.report import Report
|
|
|
|
|
|
_ZERO = Decimal('0.0')
|
|
|
|
|
|
class Tax(metaclass=PoolMeta):
|
|
__name__ = 'account.tax'
|
|
certificate_type = fields.Selection([
|
|
('', ''),
|
|
('renta', 'Renta'),
|
|
('ret', 'ReteFuente'),
|
|
('iva', 'IVA'),
|
|
('ica', 'ICA'),
|
|
('cree', 'Cree'),
|
|
('ic', 'Impuesto al Consumo'),
|
|
('bomberil', 'Impuesto Bomberil'),
|
|
('avtableros', 'Impuesto Avisos y Tableros'),
|
|
], 'Certificate Type')
|
|
classification = fields.Selection([
|
|
('', ''),
|
|
('renta', 'Renta'),
|
|
('ret', 'ReteFuente'),
|
|
('iva', 'IVA'),
|
|
('ica', 'ICA'),
|
|
('cree', 'Cree'),
|
|
('ic', 'Impuesto al Consumo'),
|
|
], 'Classification For Reports')
|
|
|
|
classification_tax = fields.Selection([
|
|
('', ''),
|
|
('01', 'IVA'),
|
|
('02', 'IC'),
|
|
('03', 'ICA'),
|
|
('04', 'INC'),
|
|
('05', 'ReteIVA'),
|
|
('06', 'ReteFuente'),
|
|
('07', 'ReteICA'),
|
|
('20', 'FtoHorticultura'),
|
|
('21', 'Timbre'),
|
|
('22', 'Bolsas'),
|
|
('23', 'INCarbono'),
|
|
('24', 'INCombustibles'),
|
|
('25', 'Sobretasa Combustibles'),
|
|
('26', 'Sordicom'),
|
|
('ZZ', 'Otro'),
|
|
('NA', 'No Aceptada'),
|
|
('renta', 'renta'),
|
|
('autorenta', 'autorenta'),
|
|
], 'Classification Tax Electronic Invoice')
|
|
not_printable = fields.Boolean('Not Printable')
|
|
base = fields.Numeric('Base', digits=(16, 2))
|
|
|
|
|
|
class TaxLine(metaclass=PoolMeta):
|
|
__name__ = 'account.tax.line'
|
|
|
|
@fields.depends('_parent_move_line.account', 'move_line')
|
|
def on_change_with_company(self, name=None):
|
|
if self.move_line:
|
|
return self.move_line.account.company.id
|
|
|
|
@fields.depends('tax', 'move_line')
|
|
def on_change_with_amount(self, name=None):
|
|
if hasattr(self.move_line, 'credit') and hasattr(self.move_line, 'debit'):
|
|
return (self.move_line.credit - self.move_line.debit)
|
|
|
|
|
|
class TaxesByInvoiceStart(ModelView):
|
|
'Taxes By Invoice Start'
|
|
__name__ = 'account_col.print_taxes_by_invoice.start'
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True)
|
|
start_period = fields.Many2One('account.period', 'Start Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '<=', (Eval('end_period'), 'start_date')),
|
|
], depends=['fiscalyear', 'end_period'], required=True)
|
|
end_period = fields.Many2One('account.period', 'End Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '>=', (Eval('start_period'), 'start_date'))
|
|
],
|
|
depends=['fiscalyear', 'start_period'], required=True)
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
|
|
@staticmethod
|
|
def default_fiscalyear():
|
|
FiscalYear = Pool().get('account.fiscalyear')
|
|
return FiscalYear.find(
|
|
Transaction().context.get('company'), exception=False)
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@fields.depends('fiscalyear')
|
|
def on_change_fiscalyear(self):
|
|
self.start_period = None
|
|
self.end_period = None
|
|
|
|
|
|
class PrintTaxesByInvoice(Wizard):
|
|
'Print Taxes By Invoice'
|
|
__name__ = 'account_col.print_taxes_by_invoice'
|
|
start = StateView('account_col.print_taxes_by_invoice.start',
|
|
'account_col.print_taxes_by_invoice_start_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Print', 'print_', 'tryton-print', default=True),
|
|
])
|
|
print_ = StateReport('account_col.taxes_by_invoice_report')
|
|
|
|
def do_print_(self, action):
|
|
start_period = self.start.start_period.id
|
|
end_period = self.start.end_period.id
|
|
|
|
data = {
|
|
'company': self.start.company.id,
|
|
'fiscalyear': self.start.fiscalyear.id,
|
|
'start_period': start_period,
|
|
'end_period': end_period,
|
|
}
|
|
return action, data
|
|
|
|
def transition_print_(self):
|
|
return 'end'
|
|
|
|
|
|
class TaxesByInvoice(Report):
|
|
__name__ = 'account_col.taxes_by_invoice_report'
|
|
|
|
@classmethod
|
|
def get_context(cls, records, header, data):
|
|
report_context = super().get_context(records, header, data)
|
|
pool = Pool()
|
|
Period = pool.get('account.period')
|
|
Company = pool.get('company.company')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Invoice = pool.get('account.invoice')
|
|
company = Company(data['company'])
|
|
|
|
start_period = Period(data['start_period'])
|
|
end_period = Period(data['end_period'])
|
|
|
|
dom_invoices = []
|
|
dom_invoices.append([
|
|
('invoice_date', '>=', start_period.start_date),
|
|
('invoice_date', '<=', end_period.end_date),
|
|
('state', 'in', ['posted', 'paid']),
|
|
])
|
|
|
|
invoices = Invoice.search(dom_invoices, order=[('number', 'ASC')])
|
|
|
|
taxes = {}
|
|
for invoice in invoices:
|
|
for itax in invoice.taxes:
|
|
if not itax.tax:
|
|
msg = f'Falta impuestos en la factura {invoice.number}'
|
|
raise UserError(msg)
|
|
tax_id = itax.tax.id
|
|
if tax_id not in taxes.keys():
|
|
taxes[tax_id] = {
|
|
'name': (itax.account.code or '') + ' - ' + itax.account.name,
|
|
'lines': [],
|
|
'sum_base': [],
|
|
'sum_amount': [],
|
|
}
|
|
taxes[tax_id]['lines'].append(itax)
|
|
taxes[tax_id]['sum_base'].append(itax.base)
|
|
taxes[tax_id]['sum_amount'].append(itax.amount)
|
|
|
|
report_context['records'] = taxes.values()
|
|
report_context['start_period'] = start_period.name
|
|
report_context['end_period'] = end_period.name
|
|
report_context['company'] = company
|
|
report_context['fiscalyear'] = FiscalYear(data['fiscalyear']).name
|
|
return report_context
|
|
|
|
|
|
class TaxesPostedStart(ModelView):
|
|
'Taxes Posted Start'
|
|
__name__ = 'account_col.print_taxes_posted.start'
|
|
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
|
required=True)
|
|
start_period = fields.Many2One('account.period', 'Start Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '<=', (Eval('end_period'), 'start_date')),
|
|
], depends=['fiscalyear', 'end_period'], required=True)
|
|
end_period = fields.Many2One('account.period', 'End Period',
|
|
domain=[
|
|
('fiscalyear', '=', Eval('fiscalyear')),
|
|
('start_date', '>=', (Eval('start_period'), 'start_date'))
|
|
],
|
|
depends=['fiscalyear', 'start_period'], required=True)
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
taxes = fields.Many2Many('account.tax', None, None, 'Tax')
|
|
# tax = fields.Many2One('account.tax', 'Tax')
|
|
|
|
@staticmethod
|
|
def default_fiscalyear():
|
|
FiscalYear = Pool().get('account.fiscalyear')
|
|
return FiscalYear.find(
|
|
Transaction().context.get('company'), exception=False)
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@fields.depends('fiscalyear')
|
|
def on_change_fiscalyear(self):
|
|
self.start_period = None
|
|
self.end_period = None
|
|
|
|
|
|
class PrintTaxesPosted(Wizard):
|
|
'Print Taxes Posted'
|
|
__name__ = 'account_col.print_taxes_posted'
|
|
start = StateView('account_col.print_taxes_posted.start',
|
|
'account_col.print_taxes_posted_start_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Print', 'print_', 'tryton-print', default=True),
|
|
])
|
|
print_ = StateReport('account_col.taxes_posted_report')
|
|
|
|
def do_print_(self, action):
|
|
taxes = None
|
|
if self.start.taxes:
|
|
taxes = [tax.id for tax in self.start.taxes]
|
|
data = {
|
|
'company': self.start.company.id,
|
|
'fiscalyear': self.start.fiscalyear.id,
|
|
'start_period': self.start.start_period.id,
|
|
'end_period': self.start.end_period.id,
|
|
'taxes': taxes,
|
|
|
|
}
|
|
return action, data
|
|
|
|
def transition_print_(self):
|
|
return 'end'
|
|
|
|
|
|
class TaxesPosted(Report):
|
|
__name__ = 'account_col.taxes_posted_report'
|
|
|
|
@classmethod
|
|
def get_context(cls, records, header, data):
|
|
report_context = super().get_context(records, header, data)
|
|
pool = Pool()
|
|
Period = pool.get('account.period')
|
|
Company = pool.get('company.company')
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
Tax = pool.get('account.tax')
|
|
MoveLine = pool.get('account.move.line')
|
|
company = Company(data['company'])
|
|
|
|
start_period = Period(data['start_period'])
|
|
end_period = Period(data['end_period'])
|
|
|
|
dom = []
|
|
if data['taxes']:
|
|
dom.append(('id', 'in', data['taxes']))
|
|
|
|
taxes = Tax.search(dom, order=[('invoice_account.code', 'ASC')])
|
|
taxes_accounts = {}
|
|
|
|
def _get_data_tax(acc):
|
|
val = {
|
|
'code': acc.code,
|
|
'name': acc.rec_name,
|
|
'rate': '',
|
|
'lines': [],
|
|
'sum_base': [],
|
|
'sum_amount': [],
|
|
}
|
|
return val
|
|
|
|
for t in taxes:
|
|
for tax_i_acc in (t.invoice_account, t.credit_note_account):
|
|
if tax_i_acc and tax_i_acc.id not in taxes_accounts.keys():
|
|
taxes_accounts[tax_i_acc.id] = _get_data_tax(tax_i_acc)
|
|
|
|
periods = Period.search([
|
|
('fiscalyear', '=', data['fiscalyear']),
|
|
('start_date', '>=', start_period.start_date),
|
|
('end_date', '<=', end_period.end_date),
|
|
])
|
|
period_ids = [p.id for p in periods]
|
|
|
|
lines = MoveLine.search([
|
|
('account', 'in', set(taxes_accounts.keys())),
|
|
('move.period', 'in', period_ids),
|
|
], order=[('date', 'ASC')])
|
|
|
|
targets = {}
|
|
for line in lines:
|
|
line_id = line.account.id
|
|
if line_id not in targets.keys():
|
|
targets[line_id] = taxes_accounts[line_id]
|
|
line_ = cls.get_tax_reversed(line)
|
|
targets[line_id]['lines'].append(line_)
|
|
targets[line_id]['sum_base'].append(line_['base'])
|
|
targets[line_id]['sum_amount'].append(line_['tax_amount'])
|
|
|
|
ordered_targets = sorted(((v['code'], v) for v in targets.values()), key = lambda tup: tup[0])
|
|
ordered_targets = OrderedDict(ordered_targets)
|
|
|
|
report_context['records'] = ordered_targets.values()
|
|
report_context['start_period'] = start_period.name
|
|
report_context['end_period'] = end_period.name
|
|
report_context['company'] = company
|
|
report_context['fiscalyear'] = FiscalYear(data['fiscalyear']).name
|
|
return report_context
|
|
|
|
@classmethod
|
|
def get_tax_reversed(cls, line):
|
|
line2 = {'line': line}
|
|
rate = None
|
|
base = _ZERO
|
|
amount = line.debit - line.credit
|
|
if line.tax_lines:
|
|
for tax_line in line.tax_lines:
|
|
if tax_line.tax:
|
|
rate = tax_line.tax.rate
|
|
if rate:
|
|
base = amount / abs(rate)
|
|
rate = rate * 100
|
|
|
|
|
|
#TODO: Add smart compute deduced from taxes model
|
|
line2.update({'base': base, 'tax_amount': amount, 'rate': rate})
|
|
return line2
|