# -*- coding: utf-8 -*- # This file is part of the edocument-module for Tryton from m-ds.de. # The COPYRIGHT file at the top level of this repository contains the # full copyright notices and license terms. from decimal import Decimal, ROUND_HALF_EVEN import html from trytond.exceptions import UserError from trytond.i18n import gettext from trytond.tools import cached_property from trytond.pool import Pool from trytond.modules.product import price_digits class EdocumentMixin(object): """ functions to get field values for xml """ __slots__ = () def company_bank_accounts(self): """ get leist of bank account numbers, defined in config Returns: list: records of model bank.account.number """ Configuration = Pool().get('account.configuration') result = [] cfg1 = Configuration.get_singleton() if cfg1 and cfg1.edocument_bank: result.extend(list(cfg1.edocument_bank)) else: result.extend([ y for x in self.invoice.company.party.bank_accounts for y in x.numbers]) return result @cached_property def seller_trade_address(self): """ get address of seller, throw exception if incomplete Raises: UserError: if no address UserError: if no country on address Returns: record : model party.address """ result = super().seller_trade_address if not result: raise UserError(gettext( 'edocument_xrechnung.msg_no_seller_address', sellerparty=self.invoice.company.rec_name if self.invoice and self.invoice.company else '-')) if not result.country: raise UserError(gettext( 'edocument_xrechnung.msg_no_address_country', party=result.party.rec_name if result.party else '-')) return result @cached_property def buyer_trade_address(self): """ exception if no address Returns: record: model party.address """ if (self.invoice.type == 'out') and ( not self.invoice.invoice_address): raise UserError(gettext( 'edocument_xrechnung.msg_no_buyer_address', buyerparty=self.invoice.party.rec_name if self.invoice and self.invoice.party else '-')) result = super().buyer_trade_address if result and not result.country: raise UserError(gettext( 'edocument_xrechnung.msg_no_address_country', party=result.party.rec_name if result.party else '-')) return result def get_list_of_comments(self): """ comment, to export in Returns: _type_: _description_ """ result = [] if self.invoice.comment: result.append({ 'content': self.invoice.comment, 'subject_code': '', 'content_code': ''}) return result def invoice_line_tax(self, line): """ get tax of invoice-line, fire exception if no/multiple taxes exists """ Tax = Pool().get('account.tax') if len(line.taxes) != 1: raise UserError(gettext( 'edocument_xrechnung.msg_linetax_invalid_number', linename=line.rec_name, numtax=len(line.taxes))) taxlines = Tax.compute( line.taxes, Decimal('1'), 1.0, line.invoice.accounting_date or line.invoice.invoice_date) assert len(taxlines) == 1 tax = taxlines[0]['tax'] allowed_cat = ['AE', 'L', 'M', 'E', 'S', 'Z', 'G', 'O', 'K', 'B'] unece_category_code = self.get_category_code(tax) if unece_category_code not in allowed_cat: raise UserError(gettext( 'edocument_xrechnung.msg_linetax_invalid_catcode', taxname=tax.rec_name, allowed=', '.join(allowed_cat))) return tax def taxident_data(self, tax_identifier): """ get tax-scheme-id and codes """ result = {'code': None, 'id': None} if tax_identifier: if tax_identifier.type == 'de_vat': result['code'] = 'DE%s' % tax_identifier.code result['id'] = 'VAT' return result def tax_rate(self, tax): """ get tax-rate in procent """ return (tax.rate * Decimal('100.0')).quantize(Decimal('0.01')) def uom_unece_code(self, line): """ 'line': invoice.line """ if len(line.unit.unece_code or '') == 0: raise UserError(gettext( 'edocument_xrechnung.msg_uom_code_missing', uomname=line.unit.rec_name)) return line.unit.unece_code def tax_unece_code(self, tax): """ 'tax': invoice.line """ unece_code = self.get_tax_unece_code(tax) if not unece_code: raise UserError(gettext( 'edocument_xrechnung.msg_tax_code_missing', taxname=tax.rec_name)) return tax.unece_code def get_tax_unece_code(self, tax): while tax: if tax.unece_code: return tax.unece_code break tax = tax.parent def get_category_code(self, tax): while tax: if tax.unece_category_code: return tax.unece_category_code break tax = tax.parent def tax_category_code(self, tax): """ read tax-category, fire exception if missing """ unece_category_code = self.get_category_code(tax) if not unece_category_code: raise UserError(gettext( 'edocument_xrechnung.mds_tax_category_missing', taxname=tax.rec_name)) return unece_category_code def round_unitprice(self, value): """ round value by digits in unit_price of account.invoice.line Args: value (Decimal): unit-price Returns: Decimal: rounded value """ if isinstance(value, Decimal): return value.quantize( Decimal(str(1/10 ** price_digits[1])), ROUND_HALF_EVEN) return value def quote_text(self, text): """ replace critical chars """ if text: return html.escape(text) # end EdocumentMixin