def _document_lines(self): line_number = 1 picking_lines = [] MntExe = 0 for line in self.move_lines: if line.name.startswith('>') and self.hide_kit_components: continue no_product = False if line.product_id.default_code == 'NO_PRODUCT': no_product = True lines = collections.OrderedDict() lines['NroLinDet'] = line_number if line.product_id.default_code and not no_product: lines['CdgItem'] = collections.OrderedDict() lines['CdgItem']['TpoCodigo'] = 'INT1' lines['CdgItem']['VlrCodigo'] = line.product_id.default_code tax_include = False if line.move_line_tax_ids: for t in line.move_line_tax_ids: tax_include = t.price_include if t.amount == 0 or t.sii_code in [0]: # mejor manera de identificar exento de afecto lines['IndExe'] = 1 MntExe += int(round(line.subtotal, 0)) lines['NmbItem'] = pysiidte.str_shorten(line.product_id.name, 80) lines['DscItem'] = pysiidte.str_shorten(line.name, 1000) # descripción más extenza if line.product_id.default_code: lines['NmbItem'] = pysiidte.str_shorten( line.product_id.name.replace('['+line.product_id.default_code+'] ', ''), 80) qty = round(line.quantity_done, 4) if qty <= 0: qty = round(line.product_uom_qty, 4) if qty <=0: raise UserError("¡No puede ser menor o igual que 0!, tiene líneas con cantidad realiada 0") if not no_product: lines['QtyItem'] = qty if self.move_reason in ['5']: no_product = True if not no_product: lines['UnmdItem'] = line.product_uom.name[:4] if line.delivery_price_unit > 0: lines['PrcItem'] = round(line.delivery_price_unit, 4) if line.discount > 0: lines['DescuentoPct'] = line.discount lines['DescuentoMonto'] = int(round((((line.discount / 100) * lines['PrcItem']) * qty))) if not no_product: lines['MontoItem'] = int(round(line.subtotal, 0)) if no_product: lines['MontoItem'] = 0 line_number += 1 picking_lines.extend([{'Detalle': lines}]) if 'IndExe' in lines: tax_include = False if len(picking_lines) == 0: raise UserError(_('No se puede emitir una guía sin líneas')) return { 'picking_lines': picking_lines, 'MntExe': MntExe, 'no_product': no_product, 'tax_include': tax_include, }
def get_barcode(self, no_product=False): partner_id = self.partner_id or self.company_id.partner_id ted = False RutEmisor = self.format_rut(self.company_id.main_id_number) result['TED']['DD']['RE'] = RutEmisor result['TED']['DD']['TD'] = self.location_id.document_type_id.code result['TED']['DD']['F'] = self.get_folio() result['TED']['DD']['FE'] = datetime.strftime(datetime.now(), '%Y-%m-%d') if not partner_id.commercial_partner_id.main_id_number: raise UserError(_("Fill Partner VAT")) result['TED']['DD']['RR'] = self.format_rut(partner_id.commercial_partner_id.main_id_number) result['TED']['DD']['RSR'] = pysiidte.str_shorten(partner_id.commercial_partner_id.name, 40) result['TED']['DD']['MNT'] = int(round(self.amount_total)) if no_product: result['TED']['DD']['MNT'] = 0 for line in self.move_lines: result['TED']['DD']['IT1'] = pysiidte.str_shorten(line.product_id.name,40) if line.product_id.default_code: result['TED']['DD']['IT1'] = pysiidte.str_shorten(line.product_id.name.replace( '['+line.product_id.default_code+'] ', ''), 40) break resultcaf = self.location_id.sequence_id.get_caf_file() result['TED']['DD']['CAF'] = resultcaf['AUTORIZACION']['CAF'] if RutEmisor != result['TED']['DD']['CAF']['DA']['RE']: raise UserError(_('NO coincide el Dueño del CAF : %s con el emisor Seleccionado: %s' % ( result['TED']['DD']['CAF']['DA']['RE'], RutEmisor))) dte = result['TED']['DD'] timestamp = pysiidte.time_stamp() if date(int(timestamp[:4]), int(timestamp[5:7]), int(timestamp[8:10])) < date( int(self.date[:4]), int(self.date[5:7]), int(self.date[8:10])): raise UserError("La fecha de timbraje no puede ser menor a la fecha de emisión del documento") dte['TSTED'] = timestamp ddxml = '<DD>'+dicttoxml.dicttoxml( dte, root=False, attr_type=False).decode().replace( '<key name="@version">1.0</key>', '', 1).replace( '><key name="@version">1.0</key>', ' version="1.0">', 1).replace( '><key name="@algoritmo">SHA1withRSA</key>', ' algoritmo="SHA1withRSA">').replace( '<key name="#text">', '').replace( '</key>', '').replace('<CAF>', '<CAF version="1.0">')+'</DD>' keypriv = resultcaf['AUTORIZACION']['RSASK'].replace('\t', '') # parser = etree.XMLParser(remove_blank_text=True) root = etree.XML(ddxml) # Daniel Blanco: se instancia el parser # root = etree.fromstring(ddxml, parser=parser) # Daniel Blanco: se instancia el parser ddxml = etree.tostring(root) # Daniel Blanco: test pretty_print: la mayoría no lo formatea frmt = self.signmessage(ddxml, keypriv) ted = '<TED version="1.0">{}<FRMT algoritmo="SHA1withRSA">{}</FRMT></TED>'.format(ddxml.decode(), frmt) self.sii_barcode = ted image = False if ted: barcodefile = BytesIO() image = self.pdf417bc(ted) image.save(barcodefile, 'PNG') data = barcodefile.getvalue() self.sii_barcode_img = base64.b64encode(data) ted += ''' <TmstFirma>{}</TmstFirma>'''.format(timestamp) return ted
def _emisor(self): issuer = collections.OrderedDict() issuer['RUTEmisor'] = self.format_rut(self.company_id.main_id_number) issuer['RznSoc'] = self.company_id.partner_id.name issuer['GiroEmis'] = pysiidte.str_shorten(self.company_id.activity_description.name, 80) issuer['Telefono'] = pysiidte.str_shorten(self.company_id.phone or '', 20) issuer['CorreoEmisor'] = self.company_id.dte_email issuer['item'] = self._giros_emisor() if self.location_id.sii_code: issuer['CdgSIISucur'] = self.location_id.sii_code issuer['DirOrigen'] = self.company_id.street + ' ' + (self.company_id.street2 or '') issuer['CmnaOrigen'] = self.company_id.city_id.name or '' issuer['CiudadOrigen'] = self.company_id.city or '' return issuer
def _totals_otra_moneda(self, currency_id, MntExe, MntNeto, IVA, TasaIVA, ImptoReten, MntTotal=0): if not self._check_doc_type('E'): return super(Exportacion, self)._totals_otra_moneda(currency_id, MntExe, MntNeto, IVA, TasaIVA, ImptoReten, MntTotal) total_amounts = collections.OrderedDict() total_amounts['TpoMoneda'] = pysiidte.str_shorten( self.company_id.currency_id.short_name, 15) # PESO CL total_amounts['TpoCambio'] = round( self.currency_id.rate, 4) # currency_id.rate del euro 0,00127323656735 if MntExe: if self.currency_id: MntExe = self.currency_id.compute(MntExe, self.company_currency_id) total_amounts['MntExeOtrMnda'] = MntExe if self.currency_id: MntTotal = self.currency_id.compute(MntTotal, self.company_currency_id) total_amounts['MntTotOtrMnda'] = MntTotal return total_amounts
def _receptor(self): recipient = collections.OrderedDict() partner_id = self.partner_id or self.company_id.partner_id if not partner_id.commercial_partner_id.main_id_number: raise UserError("Must include recipient RUT (VAT)") recipient['RUTRecep'] = self.format_rut(partner_id.commercial_partner_id.main_id_number) recipient['RznSocRecep'] = pysiidte.str_shorten(partner_id.commercial_partner_id.name, 100) activity_description = self.activity_description or partner_id.activity_description if not activity_description: raise UserError(_('Seleccione giro del partner')) recipient['GiroRecep'] = pysiidte.str_shorten(activity_description.name, 40) if partner_id.commercial_partner_id.phone: recipient['Contacto'] = partner_id.commercial_partner_id.phone if partner_id.commercial_partner_id.dte_email: recipient['CorreoRecep'] = partner_id.commercial_partner_id.dte_email recipient['DirRecep'] = pysiidte.str_shorten( partner_id.commercial_partner_id.street + ' ' + (partner_id.commercial_partner_id.street2 or ''), 70) recipient['CmnaRecep'] = partner_id.commercial_partner_id.city_id.name recipient['CiudadRecep'] = partner_id.commercial_partner_id.city return recipient