257 lines
11 KiB
Python
257 lines
11 KiB
Python
from trytond.model import fields, ModelSQL, ModelView, Unique, Workflow
|
|
from trytond.pool import Pool
|
|
# from trytond.transaction import Transaction
|
|
# from trytond.wizard import Button, StateTransition, StateView, Wizard
|
|
from trytond.pyson import Eval
|
|
from decimal import Decimal
|
|
from trytond.exceptions import UserError
|
|
from lxml import etree
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
class SupplierCertificate(Workflow, ModelSQL, ModelView):
|
|
"""Supplier Certificate"""
|
|
__name__ = 'farming.supplier_certificate'
|
|
|
|
number = fields.Char('Number', states={
|
|
'readonly': True
|
|
})
|
|
# supplier = fields.Many2Many('party.party', 'Supplier')
|
|
suppliers = fields.Many2Many('farming.supplier_certificate-party.party', 'supplier_certificate',
|
|
'party', 'Party')
|
|
provider_link = fields.Char('Link Mail')
|
|
start_date = fields.Date('Start Date')
|
|
end_date = fields.Date('End Date')
|
|
invoice_lines = fields.Many2Many('farming.supplier_certificate-account_invoice_line', 'supplier_certificate',
|
|
'invoice_line', 'Invoice Lines', domain=[
|
|
('invoice.type', '=', 'in'),
|
|
('invoice.party', 'in', Eval('suppliers')),
|
|
('product.exportable', '=', True),
|
|
('invoice.invoice_date', '>=', Eval('start_date')),
|
|
('invoice.invoice_date', '<=', Eval('end_date')),
|
|
], depends=['suppliers', 'start_date', 'end_date'])
|
|
# ('invoice', '=', Eval('invoice')),
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('cancelled', 'Cancelled'),
|
|
('done', 'Done'),
|
|
('processed', 'Processed'),
|
|
], 'State', readonly=True, select=True)
|
|
total_amount = fields.Function(fields.Numeric('Total_amount'), 'get_total_amount')
|
|
vat_amount = fields.Function(fields.Numeric('Vat Amount'), 'get_vat_amount')
|
|
xml_certificate = fields.Text('XML Certificate')
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(SupplierCertificate, cls).__setup__()
|
|
cls._transitions |= set((
|
|
('draft', 'processed'),
|
|
('processed', 'done'),
|
|
('processed', 'cancelled'),
|
|
))
|
|
cls._buttons.update({
|
|
'draft': {
|
|
'invisible': Eval('state').in_(['draft', 'processed', 'done'])
|
|
},
|
|
'cancel': {
|
|
'invisible': Eval('state').in_(['cancelled', 'draft', 'done']),
|
|
},
|
|
'process': {
|
|
'invisible': Eval('state') != 'draft',
|
|
},
|
|
'done': {
|
|
'invisible': Eval('state').in_(['draft', 'cancelled', 'done']),
|
|
},
|
|
'create_certificate': {
|
|
|
|
}
|
|
|
|
})
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('draft')
|
|
def draft(cls, records):
|
|
pass
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('cancelled')
|
|
def cancel(cls, records):
|
|
pass
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('processed')
|
|
def process(cls, records):
|
|
for record in records:
|
|
record.set_number()
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('done')
|
|
def done(cls, records):
|
|
pass
|
|
|
|
@staticmethod
|
|
def default_state():
|
|
return 'draft'
|
|
|
|
def get_total_amount(self, name):
|
|
total_amount = 0
|
|
if self.invoice_lines:
|
|
for invoice_line in self.invoice_lines:
|
|
total_amount += invoice_line.amount
|
|
return Decimal(total_amount)
|
|
|
|
def get_vat_amount(self, name):
|
|
total_amount_taxes = 0
|
|
TAX = Pool().get('account.tax')
|
|
iva = TAX(2)
|
|
if self.invoice_lines:
|
|
for invoice_line in self.invoice_lines:
|
|
# total_amount_taxes += invoice_line.amount * iva.rate * Decimal(invoice_line.quantity)
|
|
total_amount_taxes += invoice_line.amount * iva.rate
|
|
return Decimal(total_amount_taxes)
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
def create_certificate(cls, certificates):
|
|
for record in certificates:
|
|
date_exp = record.start_date + timedelta(days=180)
|
|
flimexp = date_exp.strftime("%Y-%m-%d")
|
|
root = etree.Element("mas", nsmap={"xsi": "http://www.w3.org/2001/XMLSchema-instance"})
|
|
root.set("{http://www.w3.org/2001/XMLSchema-instance}noNamespaceSchemaLocation", "../xsd/640.xsd")
|
|
cab = etree.SubElement(root, "Cab")
|
|
elements_to_add = {
|
|
"Ano": str(record.start_date.year),
|
|
"CodCpt": "1",
|
|
"Formato": "640",
|
|
"Version": "1",
|
|
"NumEnvio": record.number,
|
|
"FecEnvio": str(datetime.today().isoformat()).split('.')[0],
|
|
"FecInicial": str(record.start_date),
|
|
"FecFinal": str(record.start_date),
|
|
"ValorTotal": "31",
|
|
"CantReg": str(len(record.suppliers))
|
|
}
|
|
for tag, text in elements_to_add.items():
|
|
element = etree.Element(tag)
|
|
element.text = text
|
|
cab.append(element)
|
|
pool = Pool()
|
|
Authorization = pool.get('account.invoice.authorization')
|
|
for supplier in record.suppliers:
|
|
resolution_number = supplier.invoice_authorization.number
|
|
start_date_auth = supplier.invoice_authorization.start_date_auth
|
|
invoice_lines = []
|
|
vtcons = 0
|
|
vtexen = 0
|
|
for line in record.invoice_lines:
|
|
try:
|
|
autorization, = Authorization.search([('id', '=', line.invoice.authorization)])
|
|
except:
|
|
autorization = '9999'
|
|
if line.invoice.party == supplier:
|
|
harmonized_tariff_schedule = line.product.harmonized_tariff_schedule
|
|
invoice_line_dict = {
|
|
'nfact': line.invoice.reference,
|
|
'ffac': str(line.invoice.invoice_date),
|
|
'resfac': resolution_number,
|
|
'fres': str(start_date_auth),
|
|
'tipo': '1',
|
|
'subp': harmonized_tariff_schedule.code,
|
|
'desc': line.product.description if line.product.description else line.product.name,
|
|
'cunfi': f"{line.quantity:.6f}",
|
|
'unfi': harmonized_tariff_schedule.uom.symbol,
|
|
'cunco': f"{line.quantity:.6f}",
|
|
'unco': 'NAR',
|
|
'vuni': line.unit_price,
|
|
'amount': round(float(line.unit_price) * line.quantity, 6),
|
|
'tiva': '19.00',
|
|
'vexen': round((float(line.unit_price) * line.quantity) * 0.19, 6),
|
|
'codins': line.product.code,
|
|
}
|
|
vtcons += invoice_line_dict['amount']
|
|
vtexen += invoice_line_dict['vexen']
|
|
invoice_lines.append(invoice_line_dict)
|
|
cp = etree.SubElement(root, "cp")
|
|
cp.set("cpto", "1")
|
|
cp.set("tdoc", supplier.type_document)
|
|
cp.set("ndoc", supplier.id_number)
|
|
if supplier.type_document == '31':
|
|
cp.set("razsoc", supplier.name)
|
|
else:
|
|
cp.set("apl1", supplier.patient.first_family_name)
|
|
cp.set("apl2", supplier.patient.second_family_name)
|
|
cp.set("nom1", supplier.first_name)
|
|
cp.set("nom2", supplier.second_name)
|
|
cp.set("cantfac", "1")
|
|
cp.set("vtcons", f"{vtcons:.6f}")
|
|
cp.set("vtexen", f"{vtexen:.6f}")
|
|
cp.set("flimexp", flimexp)
|
|
cp.set("nitems", str(len(invoice_lines)))
|
|
for line in invoice_lines:
|
|
cphoja2 = etree.SubElement(cp, "cphoja2")
|
|
cphoja2.set("nfact", line['nfact'])
|
|
cphoja2.set("ffac", line['ffac'])
|
|
cphoja2.set("resfac", line['resfac'])
|
|
cphoja2.set("fres", line['fres'])
|
|
cphoja2.set("tipo", '1')
|
|
cphoja2.set("subp", line['subp'])
|
|
cphoja2.set("desc", line['desc'])
|
|
cphoja2.set("cunfi", line['cunfi'])
|
|
cphoja2.set("unfi", line['unfi'])
|
|
cphoja2.set("cunco", line['cunco'])
|
|
cphoja2.set("unco", 'NAR')
|
|
cphoja2.set("vuni", f"{line['vuni']:.6f}")
|
|
cphoja2.set("vtotal", f"{line['amount']:.6f}")
|
|
cphoja2.set("tiva", '19.00')
|
|
cphoja2.set("vexen", f"{line['vexen']:.6f}")
|
|
cphoja2.set("codins", line['codins'])
|
|
|
|
tree = etree.ElementTree(root)
|
|
record.xml_certificate = etree.tostring(tree, xml_declaration=True, pretty_print=True, encoding="ISO-8859-1").decode("ISO-8859-1")
|
|
record.save()
|
|
|
|
def set_number(self):
|
|
pool = Pool()
|
|
Config = pool.get('account.configuration')
|
|
config = Config(1)
|
|
if self.number:
|
|
return
|
|
if not config.sequence_supplier_certificate:
|
|
raise UserError('No existe secuencia de certificado de proveedor')
|
|
number = config.certificate_sequence.get()
|
|
self.write([self], {'number': number})
|
|
|
|
|
|
class SupplierCetificateInvoiceLine(ModelSQL):
|
|
'Supplier certificate - invoice Line'
|
|
__name__ = 'farming.supplier_certificate-account_invoice_line'
|
|
_table = 'supplier_certificate-account_invoice_line'
|
|
supplier_certificate = fields.Many2One('farming.supplier_certificate',
|
|
'Supplier Certificate', select=True, required=True, ondelete='CASCADE')
|
|
invoice_line = fields.Many2One('account.invoice.line', 'Invoice Line',
|
|
ondelete='CASCADE', select=True, required=True)
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(SupplierCetificateInvoiceLine, cls).__setup__()
|
|
table = cls.__table__()
|
|
|
|
cls._sql_constraints += [
|
|
('invoice_line_uniq', Unique(table, table.invoice_line),
|
|
'invoice line already exists!'),
|
|
]
|
|
|
|
|
|
class SupplierCetificateParty(ModelSQL):
|
|
'Supplier certificate - invoice Line'
|
|
__name__ = 'farming.supplier_certificate-party.party'
|
|
_table = 'supplier_certificate-party_party'
|
|
supplier_certificate = fields.Many2One('farming.supplier_certificate',
|
|
'Supplier Certificate', select=True, required=True, ondelete='CASCADE')
|
|
party = fields.Many2One('party.party', 'Party',
|
|
ondelete='CASCADE', select=True, required=True)
|