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)