+# Copyright 2019 Tecnativa - Carlos Dauden
# License AGPL-3 - See https://www.gnu.org/licenses/agpl-3.0
from odoo import api, fields, models
@@ -10,9 +11,12 @@
class L10nEsVatBookLineTax(models.Model):
_name = 'l10n.es.vat.book.line.tax'
- vat_book_line_id = fields.Many2one(comodel_name='l10n.es.vat.book.line',
- required=True, ondelete='cascade')
-
+ vat_book_line_id = fields.Many2one(
+ comodel_name='l10n.es.vat.book.line',
+ required=True,
+ ondelete='cascade',
+ index=True,
+ )
base_amount = fields.Float(
string='Base')
@@ -28,6 +32,20 @@ class L10nEsVatBookLineTax(models.Model):
move_line_ids = fields.Many2many(
comodel_name='account.move.line', string='Move Lines')
+ is_req = fields.Boolean(
+ string='R.Eq.',
+ help='Is Recargo de Equivalencia',
+ )
+ req_tax_id = fields.Many2one(
+ comodel_name='account.tax',
+ string='R.Eq. Tax',
+ )
+ req_tax_amount = fields.Float(
+ string='R.Eq. Tax fee',
+ )
+ total_amount_req_include = fields.Float(
+ string='Total w/REq',
+ )
@api.multi
@api.depends('tax_id')
diff --git a/l10n_es_vat_book/report/common_templates.xml b/l10n_es_vat_book/report/common_templates.xml
index df1ec89c753..081093bd983 100644
--- a/l10n_es_vat_book/report/common_templates.xml
+++ b/l10n_es_vat_book/report/common_templates.xml
@@ -200,7 +200,10 @@
Total
|
- |
+
+
+ |
|
+# Copyright 2019 Tecnativa - Carlos Dauden
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
-from odoo import _, models
+from odoo import _, fields, models
class VatNumberXlsx(models.AbstractModel):
_name = 'report.l10n_es_vat_book.l10n_es_vat_book_xlsx'
_inherit = 'report.report_xlsx.abstract'
+ def parse_vat_info(self, line, europe_codes):
+ identifier_type = ''
+ vat_number = line.vat_number and line.vat_number or ''
+ if vat_number[:2] in europe_codes:
+ country_code = vat_number[:2]
+ vat_number = vat_number[2:]
+ if country_code != 'ES':
+ identifier_type = '02'
+ return country_code, identifier_type, vat_number
+ country_code = line.partner_id.country_id.code
+ if country_code in europe_codes:
+ if country_code != 'ES':
+ identifier_type = '02'
+ else:
+ identifier_type = '04'
+ return country_code, identifier_type, vat_number
+
+ def format_boe_date(self, date):
+ return fields.Datetime.from_string(date).strftime('%d/%m/%Y')
+
+ def create_issued_sheet(self, workbook, book):
+ title_format = workbook.add_format({
+ 'bold': 1,
+ 'border': 1,
+ 'align': 'center',
+ 'valign': 'vjustify',
+ })
+ header_format = workbook.add_format({
+ 'bold': 1,
+ 'border': 1,
+ 'align': 'center',
+ 'valign': 'vjustify',
+ 'fg_color': '#F2F2F2'})
+ subheader_format = workbook.add_format({
+ 'bold': 1,
+ 'border': 1,
+ 'align': 'center',
+ 'valign': 'vjustify'})
+ number_format = workbook.add_format()
+ number_format.set_num_format('0.00')
+
+ sheet = workbook.add_worksheet(_('ISSUED'))
+
+ sheet.merge_range('B1:Q1', _('LIBRO REGISTRO FACTURAS EXPEDIDAS'),
+ title_format)
+ sheet.write('A2', _('Year: %s' % book.year))
+ sheet.write('A3', _('VAT: %s' % book.company_vat))
+ sheet.merge_range('A4:D4', _('Name: %s' % book.company_id.name))
+
+ sheet.merge_range('C6:E6', _('Invoice Identification'), header_format)
+ sheet.merge_range('F6:H6', _('Receiver VAT'), header_format)
+ sheet.merge_range('R6:U6', _('Collection (Cash Criteria Operation)'),
+ header_format)
+
+ sheet.merge_range('A6:A7', _('Expedition Date'), header_format)
+ sheet.merge_range('B6:B7', _('Operation Date'), header_format)
+ sheet.write('C7', _('Serial'), subheader_format)
+ sheet.write('D7', _('Number'), subheader_format)
+ sheet.write('E7', _('Final Number'), subheader_format)
+ sheet.write('F7', _('Type'), subheader_format)
+ sheet.write('G7', _('Country Code'), subheader_format)
+ sheet.write('H7', _('Identification'), subheader_format)
+ sheet.merge_range('I6:I7', _('Receiver Name'), header_format)
+ sheet.merge_range('J6:J7', _('Substitute Invoice'), header_format)
+ sheet.merge_range('K6:K7', _('Operation Key'), header_format)
+ sheet.merge_range('L6:L7', _('Total Invoice'), header_format)
+ sheet.merge_range('M6:M7', _('Untaxed Amount'), header_format)
+ sheet.merge_range('N6:N7', _('Tax Type'), header_format)
+ sheet.merge_range('O6:O7', _('Affected Tax Amount'), header_format)
+ sheet.merge_range('P6:P7', _('Surcharge Type'), header_format)
+ sheet.merge_range('Q6:Q7', _('Surcharge Amount'), header_format)
+ sheet.write('R7', _('Date'), subheader_format)
+ sheet.write('S7', _('Amount'), subheader_format)
+ sheet.write('T7', _('Payment Mode'), subheader_format)
+ sheet.write('U7', _('Payment Mode Identification'), subheader_format)
+
+ sheet.set_column('A:A', 16)
+ sheet.set_column('B:B', 16)
+ sheet.set_column('C:C', 14)
+ sheet.set_column('D:D', 17)
+ sheet.set_column('E:E', 17)
+ sheet.set_column('F:F', 8)
+ sheet.set_column('G:G', 12)
+ sheet.set_column('H:H', 14)
+ sheet.set_column('I:I', 40)
+ sheet.set_column('J:J', 16)
+ sheet.set_column('K:K', 16)
+ sheet.set_column('L:L', 14)
+ sheet.set_column('M:M', 14)
+ sheet.set_column('N:N', 14)
+ sheet.set_column('O:O', 14)
+ sheet.set_column('P:P', 14)
+ sheet.set_column('Q:Q', 14)
+ sheet.set_column('R:R', 14)
+ sheet.set_column('S:S', 14)
+ sheet.set_column('T:T', 14)
+ sheet.set_column('U:U', 30)
+
+ return sheet
+
+ def fill_issued_row_data(self, sheet, row, line, tax_line, europe_codes,
+ tax_index):
+ """ Fill issued data """
+
+ invoice_date = self.format_boe_date(line.invoice_date)
+ country_code, identifier_type, vat_number = self.parse_vat_info(
+ line, europe_codes)
+ sheet.write('A' + str(row), invoice_date)
+ sheet.write('B' + str(row), invoice_date)
+ sheet.write('C' + str(row), line.ref[:-20])
+ sheet.write('D' + str(row), line.ref[-20:])
+ sheet.write('E' + str(row), '') # Final number
+ sheet.write('F' + str(row), identifier_type)
+ if country_code != 'ES':
+ sheet.write('G' + str(row), country_code)
+ sheet.write('H' + str(row), vat_number)
+ sheet.write('I' + str(row), line.partner_id.name[:40])
+ # TODO: Substitute Invoice
+ # sheet.write('J' + str(row),
+ # line.invoice_id.refund_invoice_id.number or '')
+ sheet.write('K' + str(row), '') # Operation Key
+ if tax_index == 0:
+ sheet.write('L' + str(row), line.total_amount)
+ sheet.write('M' + str(row), tax_line.base_amount)
+ sheet.write('N' + str(row), tax_line.tax_id.amount)
+ sheet.write('O' + str(row), tax_line.tax_amount)
+ if tax_line.req_tax_amount:
+ sheet.write('P' + str(row), tax_line.req_tax_id.amount)
+ sheet.write('Q' + str(row), tax_line.req_tax_amount)
+
+ def create_received_sheet(self, workbook, book):
+ title_format = workbook.add_format({
+ 'bold': 1,
+ 'border': 1,
+ 'align': 'center',
+ 'valign': 'vjustify',
+ })
+ header_format = workbook.add_format({
+ 'bold': 1,
+ 'border': 1,
+ 'align': 'center',
+ 'valign': 'vjustify',
+ 'fg_color': '#F2F2F2'})
+ subheader_format = workbook.add_format({
+ 'bold': 1,
+ 'border': 1,
+ 'align': 'center',
+ 'valign': 'vjustify'})
+ number_format = workbook.add_format()
+ number_format.set_num_format('0.00')
+
+ sheet = workbook.add_worksheet(_('RECEIVED'))
+
+ sheet.merge_range('B1:S1', _('LIBRO REGISTRO FACTURAS RECIBIDAS'),
+ title_format)
+ sheet.write('A2', _('Year: %s' % book.year))
+ sheet.write('A3', _('VAT: %s' % book.company_vat))
+ sheet.merge_range('A4:D4', _('Name: %s' % book.company_id.name))
+
+ sheet.merge_range('C6:D6', _('Expediter Invoice Identification'),
+ header_format)
+ sheet.merge_range('G6:I6', _('Expediter VAT'), header_format)
+ sheet.merge_range('T6:W6', _('Payment (Cash Criteria Operation)'),
+ header_format)
+
+ sheet.merge_range('A6:A7', _('Expedition Date'), header_format)
+ sheet.merge_range('B6:B7', _('Operation Date'), header_format)
+ sheet.write('C7', _('Serial-Number'), subheader_format)
+ sheet.write('D7', _('Final-Number'), subheader_format)
+ sheet.merge_range('E6:E7', _('Reception Number'), header_format)
+ sheet.merge_range('F6:F7', _('Final Reception Number'), header_format)
+ sheet.write('G7', _('Type'), subheader_format)
+ sheet.write('H7', _('Country Code'), subheader_format)
+ sheet.write('I7', _('Identification'), subheader_format)
+ sheet.merge_range('J6:J7', _('Expediter Name'), header_format)
+ sheet.merge_range('K6:K7', _('Substitute Invoice'), header_format)
+ sheet.merge_range('L6:L7', _('Operation Key'), header_format)
+ sheet.merge_range('M6:M7', _('Total Invoice'), header_format)
+ sheet.merge_range('N6:N7', _('Untaxed Amount'), header_format)
+ sheet.merge_range('O6:O7', _('Tax Type'), header_format)
+ sheet.merge_range('P6:P7', _('Supported Tax Amount'), header_format)
+ sheet.merge_range('Q6:Q7', _('Deductible Tax Amount'), header_format)
+ sheet.merge_range('R6:R7', _('Surcharge Type'), header_format)
+ sheet.merge_range('S6:S7', _('Surcharge Amount'), header_format)
+ sheet.write('T7', _('Date'), subheader_format)
+ sheet.write('U7', _('Amount'), subheader_format)
+ sheet.write('V7', _('Payment Mode'), subheader_format)
+ sheet.write('W7', _('Payment Mode Identification'), subheader_format)
+
+ sheet.set_column('A:A', 16)
+ sheet.set_column('B:B', 16)
+ sheet.set_column('C:C', 17)
+ sheet.set_column('D:D', 17)
+ sheet.set_column('E:E', 17)
+ sheet.set_column('F:F', 17)
+ sheet.set_column('G:G', 8)
+ sheet.set_column('H:H', 12)
+ sheet.set_column('I:I', 14)
+ sheet.set_column('J:J', 40)
+ sheet.set_column('K:K', 16)
+ sheet.set_column('L:L', 14)
+ sheet.set_column('M:M', 14)
+ sheet.set_column('N:N', 14)
+ sheet.set_column('O:O', 14)
+ sheet.set_column('P:P', 14)
+ sheet.set_column('Q:Q', 14)
+ sheet.set_column('R:R', 14)
+ sheet.set_column('S:S', 14)
+ sheet.set_column('T:T', 14)
+ sheet.set_column('U:U', 14)
+ sheet.set_column('V:V', 14)
+ sheet.set_column('W:W', 30)
+
+ return sheet
+
+ def fill_received_row_data(self, sheet, row, line, tax_line, europe_codes,
+ tax_index):
+ """ Fill received data """
+
+ invoice_date = self.format_boe_date(line.invoice_date)
+ country_code, identifier_type, vat_number = self.parse_vat_info(
+ line, europe_codes)
+ sheet.write('A' + str(row), invoice_date)
+ sheet.write('B' + str(row), invoice_date)
+ sheet.write('C' + str(row),
+ line.external_ref and line.external_ref[:40] or '')
+ sheet.write('D' + str(row), '')
+ sheet.write('E' + str(row), line.ref[:20])
+ sheet.write('F' + str(row), '')
+ sheet.write('G' + str(row), identifier_type)
+ if country_code != 'ES':
+ sheet.write('H' + str(row), country_code)
+ sheet.write('I' + str(row), vat_number)
+ sheet.write('J' + str(row), line.partner_id.name[:40])
+ # TODO: Substitute Invoice
+ # sheet.write('K' + str(row),
+ # line.invoice_id.refund_invoice_id.number or '')
+ sheet.write('L' + str(row), '') # Operation Key
+ if tax_index == 0:
+ sheet.write('M' + str(row), line.total_amount)
+ sheet.write('N' + str(row), tax_line.base_amount)
+ sheet.write('O' + str(row), tax_line.tax_id.amount)
+ sheet.write('P' + str(row), tax_line.tax_amount)
+ sheet.write('Q' + str(row), tax_line.tax_amount)
+ if tax_line.req_tax_amount:
+ sheet.write('R' + str(row), tax_line.req_tax_id.amount)
+ sheet.write('S' + str(row), tax_line.req_tax_amount)
+
def generate_xlsx_report(self, workbook, data, objects):
+ """ Create vat book xlsx in BOE format """
+
+ europe = self.env.ref('base.europe', raise_if_not_found=False)
+ if not europe:
+ europe = self.env["res.country.group"].search(
+ [('name', '=', 'Europe')], limit=1)
+ europe_codes = europe.country_ids.mapped('code')
+
book = objects[0]
- bold = workbook.add_format({'bold': True})
-
- def fill_table(sheet_name, lines, received_lines=False):
- sheet = workbook.add_worksheet(sheet_name[:31])
- row = col = 0
- xlsx_header = [
- _('Invoice'),
- _('Date'),
- _('Partner'),
- _('VAT'),
- _('Base'),
- _('Tax'),
- _('Fee'),
- _('Total'),
- ]
- if received_lines:
- xlsx_header.insert(0, _('Reference'))
- for col_header in xlsx_header:
- sheet.write(row, col, col_header, bold)
- col += 1
-
- row = 1
- for line in lines:
- for tax_line in line.tax_line_ids:
- col = 0
- if received_lines:
- sheet.write(row, col, line.invoice_id.reference)
- col += 1
- sheet.write(row, col, line.invoice_id.number)
- col += 1
- sheet.write(row, col, line.invoice_date)
- col += 1
- sheet.write(row, col, line.partner_id.name)
- col += 1
- sheet.write(row, col, line.vat_number)
- col += 1
- sheet.write(row, col, tax_line.base_amount)
- col += 1
- sheet.write(row, col, tax_line.tax_id.name)
- col += 1
- sheet.write(row, col, tax_line.tax_amount)
- col += 1
- sheet.write(row, col, tax_line.total_amount)
+
+ # Issued
+ issued_sheet = self.create_issued_sheet(workbook, book)
+ lines = book.issued_line_ids + book.rectification_issued_line_ids
+ lines = lines.sorted(key=lambda l: (l.invoice_date, l.ref))
+ row = 8
+ for line in lines:
+ for i, tax_line in enumerate(line.tax_line_ids):
+ if not tax_line.is_req:
+ # TODO: Payments bucle
+ self.fill_issued_row_data(
+ issued_sheet, row, line, tax_line, europe_codes, i)
row += 1
- if book.issued_line_ids:
- report_name = _('Issued Invoices')
- lines = book.issued_line_ids
- fill_table(report_name, lines)
- if book.rectification_issued_line_ids:
- report_name = _('Issued Refund Invoices')
- lines = book.rectification_issued_line_ids
- fill_table(report_name, lines)
- if book.received_line_ids:
- report_name = _('Received Invoices')
- lines = book.received_line_ids
- fill_table(report_name, lines, received_lines=True)
- if book.rectification_received_line_ids:
- report_name = _('Received Refund Invoices')
- lines = book.rectification_received_line_ids
- fill_table(report_name, lines, received_lines=True)
+ # Received
+ received_sheet = self.create_received_sheet(workbook, book)
+ lines = book.received_line_ids + book.rectification_received_line_ids
+ lines = lines.sorted(key=lambda l: (l.invoice_date, l.ref))
+ row = 8
+ for line in lines:
+ for i, tax_line in enumerate(line.tax_line_ids):
+ # TODO: Payments bucle
+ self.fill_received_row_data(
+ received_sheet, row, line, tax_line, europe_codes, i)
+ row += 1
diff --git a/l10n_es_vat_book/report/vat_book_xlsx.xml b/l10n_es_vat_book/report/vat_book_xlsx.xml
index c272a982127..7d9ac24e7f8 100644
--- a/l10n_es_vat_book/report/vat_book_xlsx.xml
+++ b/l10n_es_vat_book/report/vat_book_xlsx.xml
@@ -1,13 +1,11 @@
-
- VAT book XLSX report
- l10n.es.vat.book
- ir.actions.report
- l10n_es_vat_book.l10n_es_vat_book_xlsx
- xlsx
- l10n_es_vat_book
-
+
diff --git a/l10n_es_vat_book/views/l10n_es_vat_book_line.xml b/l10n_es_vat_book/views/l10n_es_vat_book_line.xml
index c36750db607..23dc3532372 100644
--- a/l10n_es_vat_book/views/l10n_es_vat_book_line.xml
+++ b/l10n_es_vat_book/views/l10n_es_vat_book_line.xml
@@ -13,6 +13,9 @@
+
+
+
@@ -25,13 +28,29 @@
+
+
+
+
|