[FIX] l10n_de: review DIN5008 format

closes odoo/odoo#72548

X-original-commit: bfa7c9e78037cd0abda3e8f0a9a519a600988e9c
Signed-off-by: Quentin De Paoli (qdp) <qdp@openerp.com>
Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
wan
2021-06-23 14:12:41 +00:00
parent 16595e8af2
commit 68e0a2c83d
23 changed files with 537 additions and 79 deletions
+3
View File
@@ -2,5 +2,8 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import datev
from . import base_document_layout
from . import chart_template
from . import ir_actions_report
from . import account_move
from . import res_company
+40
View File
@@ -0,0 +1,40 @@
from odoo import models, fields, _
from odoo.tools import format_date
class AccountMove(models.Model):
_inherit = 'account.move'
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
l10n_de_document_title = fields.Char(compute='_compute_l10n_de_document_title')
def _compute_l10n_de_template_data(self):
for record in self:
record.l10n_de_template_data = data = []
if record.name:
data.append((_("Invoice No."), record.name))
if record.invoice_date:
data.append((_("Invoice Date"), format_date(self.env, record.invoice_date)))
if record.invoice_date_due:
data.append((_("Due Date"), format_date(self.env, record.invoice_date_due)))
if record.invoice_origin:
data.append((_("Source"), record.invoice_origin))
if record.ref:
data.append((_("Reference"), record.ref))
def _compute_l10n_de_document_title(self):
for record in self:
record.l10n_de_document_title = ''
if record.move_type == 'out_invoice':
if record.state == 'posted':
record.l10n_de_document_title = _('Invoice')
elif record.state == 'draft':
record.l10n_de_document_title = _('Draft Invoice')
elif record.state == 'cancel':
record.l10n_de_document_title = _('Cancelled Invoice')
elif record.move_type == 'out_refund':
record.l10n_de_document_title = _('Credit Note')
elif record.move_type == 'in_refund':
record.l10n_de_document_title = _('Vendor Credit Note')
elif record.move_type == 'in_invoice':
record.l10n_de_document_title = _('Vendor Bill')
@@ -0,0 +1,27 @@
from odoo import models, fields, _
from odoo.tools import format_date
class BaseDocumentLayout(models.TransientModel):
_inherit = 'base.document.layout'
street = fields.Char(related='company_id.street', readonly=True)
street2 = fields.Char(related='company_id.street2', readonly=True)
zip = fields.Char(related='company_id.zip', readonly=True)
city = fields.Char(related='company_id.city', readonly=True)
company_registry = fields.Char(related='company_id.company_registry', readonly=True)
bank_ids = fields.One2many(related='company_id.bank_ids', readonly=True)
account_fiscal_country_id = fields.Many2one(related='company_id.account_fiscal_country_id', readonly=True)
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
l10n_de_document_title = fields.Char(compute='_compute_l10n_de_document_title')
def _compute_l10n_de_template_data(self):
self.l10n_de_template_data = [
(_("Invoice No."), 'INV/2021/12345'),
(_("Invoice Date"), format_date(self.env, fields.Date.today())),
(_("Due Date"), format_date(self.env, fields.Date.add(fields.Date.today(), days=7))),
(_("Reference"), 'SO/2021/45678'),
]
def _compute_l10n_de_document_title(self):
self.l10n_de_document_title = 'Invoice'
@@ -0,0 +1,10 @@
from odoo import models
class IrActionsReport(models.Model):
_inherit = 'ir.actions.report'
def _get_rendering_context(self, docids, data):
data = super()._get_rendering_context(docids, data)
data['din_header_spacing'] = self.get_paperformat().header_spacing
return data
+158 -75
View File
@@ -3,108 +3,191 @@
<data>
<!-- New report paperformat for din5008 format -->
<record id="paperformat_euro_din_a" model="report.paperformat">
<field name="name">European A4 for DIN5008 Type A</field>
<field name="default" eval="False" />
<field name="format">A4</field>
<field name="orientation">Portrait</field>
<field name="margin_top">27</field>
<field name="margin_bottom">40</field>
<field name="margin_left">20</field>
<field name="margin_right">10</field>
<field name="dpi">70</field>
<field name="header_line" eval="False" />
<field name="header_spacing">27</field>
</record>
<record id="paperformat_euro_din" model="report.paperformat">
<field name="name">European A4 for DIN</field>
<field name="name">European A4 for DIN5008 Type B</field>
<field name="default" eval="False" />
<field name="format">A4</field>
<field name="orientation">Portrait</field>
<field name="margin_top">45</field>
<field name="margin_bottom">28</field>
<field name="margin_left">0</field>
<field name="margin_right">0</field>
<field name="margin_bottom">40</field>
<field name="margin_left">20</field>
<field name="margin_right">10</field>
<field name="dpi">70</field>
<field name="header_line" eval="False" />
<field name="header_spacing">45</field>
</record>
<!-- New report layout for din5008 format -->
<template id="external_layout_din5008">
<t t-if="not o and doc">
<t t-set="o" t-value="doc"/>
</t>
<t t-if="o and 'company_id' in o">
<t t-set="company" t-value="o.company_id.sudo()"/>
</t>
<t t-if="not o or not 'company_id' in o">
<t t-set="company" t-value="res_company"/>
</t>
<div>
<div class="header din">
<div class="float-right">
<h3 class="mt0 text-right" t-field="company.report_header"/>
</div>
<img t-if="company.logo" t-att-src="image_data_uri(company.logo)" class="float-left"/>
<div t-attf-class="header din_page o_company_#{company.id}_layout">
<table class="company_header" t-att-style="'height: %dmm;' % (din_header_spacing or 27)">
<tr>
<td><h3 class="mt0" t-field="company.report_header"/></td>
<td><img t-if="company.logo" t-att-src="image_data_uri(company.logo)" t-att-style="'max-height: %dmm;' % (din_header_spacing or 27)"/></td>
</tr>
</table>
</div>
<div class="article din" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
<div class="header_address">
<t t-if="address">
<div class="company_invoice_address">
<t t-if="company.name">
<span t-field="company.name"/> &#8226;
</t>
<t t-if="company.street">
<span t-field="company.street"/> &#8226;
</t>
<t t-if="company.street2">
<span t-field="company.street2"/> &#8226;
</t>
<t t-if="company.zip">
<span t-field="company.zip"/> &#8226;
</t>
<t t-if="company.city">
<span t-field="company.city"/> &#8226;
</t>
<t t-if="company.country_id">
<span t-field="company.country_id.name"/>
</t>
<hr class="company_invoice_line" />
</div>
<div name="invoice_address" class="invoice_address">
<t t-out="address"/>
</div>
</t>
<t t-else="fallback_address">
<div name="invoice_address" class="invoice_address" t-out="fallback_address" t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True}' />
</t>
<div class="company_address">
<div>
<strong t-field="company.partner_id.name"/>
</div>
<span t-field="company.partner_id"
t-options='{"widget": "contact", "fields": ["address"], "no_marker": true}'/>
<t t-if="information_block">
<div t-attf-class="din_page invoice_note article o_company_#{company.id}_layout" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
<table>
<tr>
<td>
<div class="address">
<t t-out="information_block"/>
<t t-if="company.name">
<span t-field="company.name"/>
</t>
<t t-if="company.street">
<span>|</span> <span t-field="company.street"/>
</t>
<t t-if="company.street2">
<span>|</span> <span t-field="company.street2"/>
</t>
<t t-if="company.zip">
<span>|</span> <span t-field="company.zip"/>
</t>
<t t-if="company.city">
<span t-if="not company.zip">|</span> <span t-field="company.city"/>
</t>
<t t-if="company.country_id">
<span>|</span> <span t-field="company.country_id.name"/>
</t>
<hr class="company_invoice_line" />
<div t-if="address">
<t t-out="address"/>
</div>
<div t-else="fallback_address">
<t t-esc="fallback_address"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True}' />
</div>
</div>
</td>
<td>
<div class="information_block">
<t t-if="'l10n_de_template_data' in company" t-set="template_data" t-value="company.l10n_de_template_data"/>
<t t-if="o and 'l10n_de_template_data' in o" t-set="template_data" t-value="o.l10n_de_template_data"/>
<table>
<t t-foreach="template_data" t-as="row">
<tr><td><t t-esc="row[0]"/></td><td><t t-esc="row[1]"/></td></tr>
</t>
</table>
</div>
</td>
</tr>
<tr t-if="o and 'l10n_de_addresses' in o">
<t t-foreach="o.l10n_de_addresses" t-as="doc_address">
<td>
<div class="shipping_address">
<strong><t t-esc="doc_address[0]"/></strong>
<div t-esc="doc_address[1]" t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True}'/>
</div>
</td>
</t>
</div>
</div>
<t t-out="0" />
</tr>
</table>
<h2>
<span t-if="not o"><t t-esc="company.l10n_de_document_title"/></span>
<span t-elif="'l10n_de_document_title' in o"><t t-esc="o.l10n_de_document_title"/></span>
<span t-else="" t-field="o.name"/>
</h2>
<t t-out="0"/>
</div>
<div class="footer o_background_footer din">
<div t-attf-class="din_page footer o_company_#{company.id}_layout">
<div class="text-right page_number">
<div class="text-muted">
Page:
<span class="page"/>
of
<span class="topage"/>
Page: <span class="page"/> of <span class="topage"/>
</div>
</div>
<div class="text-center">
<ul class="list-inline">
<li t-if="company.phone"><i class="fa fa-phone"/> <span t-field="company.phone"/></li>
<li t-if="company.email"><i class="fa fa-at"/> <span t-field="company.email"/></li>
<li t-if="company.website"><i class="fa fa-globe"/> <span t-field="company.website"/></li>
<li t-if="company.vat"><i class="fa fa-building-o"/><t t-esc="company.account_fiscal_country_id.vat_label or 'Tax ID'"/>: <span t-field="company.vat"/></li>
</ul>
<div t-field="company.report_footer"/>
<div class="company_details">
<table>
<tr>
<td>
<ul class="list-inline">
<li t-if="company.name"><span t-field="company.name"/></li>
<li t-if="company.street"><span t-field="company.street"/></li>
<li t-if="company.street2"><span t-field="company.street2"/></li>
<li><span t-if="company.zip" t-field="company.zip"/> <span t-if="company.city" t-field="company.city"/></li>
<li t-if="company.country_id"><span t-field="company.country_id.name"/></li>
</ul>
</td>
<td>
<ul class="list-inline">
<li t-if="company.phone"><span t-field="company.phone"/></li>
<li t-if="company.email"><span t-field="company.email"/></li>
<li t-if="company.website"><span t-field="company.website"/></li>
</ul>
</td>
<td>
<ul class="list-inline">
<li t-if="company.vat"><t t-esc="company.account_fiscal_country_id.vat_label or 'Tax ID'"/>: <span t-field="company.vat"/></li>
<li>HRB Nr: <span t-field="company.company_registry"/></li>
<div t-field="company.report_footer"/>
</ul>
</td>
<td>
<ul class="list-inline" t-if="company.bank_ids">
<t t-foreach="company.bank_ids[:2]" t-as="bank">
<li><span t-field="bank.bank_id.name"/></li>
<li>IBAN: <span t-field="bank.acc_number"/></li>
<li>BIC: <span t-field="bank.bank_id.bic"/></li>
</t>
</ul>
</td>
</tr>
</table>
</div>
</div>
</div>
</template>
<template id="din5008_css" inherit_id="web.styles_company_report">
<xpath expr="//t[@t-elif]" position="before">
<t t-elif="layout == 'l10n_de.external_layout_din5008'">
&amp;.din_page {
&amp;.header {
.company_header {
.name_container {
color: <t t-esc='primary'/>;
}
}
}
&amp;.invoice_note {
td {
.address {
> span {
color: <t t-esc='secondary'/>;
}
}
}
h2 {
color: <t t-esc='primary'/>;
}
.page {
[name=invoice_line_table], [name=stock_move_table], .o_main_table {
th {
color: <t t-esc='secondary'/>;
}
}
}
}
}
</t>
</xpath>
</template>
</data>
</odoo>
@@ -1,3 +1,110 @@
.din_page {
width: 180mm;
margin-left: -1rem;
font-size: 9pt;
&.header {
table {
width: 100%;
img, h3, td, tr {
padding: 0;
margin: 0;
}
h3 {
color: $o-default-report-primary-color;
position: relative;
top: -10mm;
margin-bottom: -10mm;
}
img {
float: right;
}
}
}
&.invoice_note {
tr {
td {
vertical-align: bottom;
}
&:nth-child(2) td {
vertical-align: top;
}
.address, .information_block, .shipping_address, .invoice_address {
margin: 0;
}
.address {
height: 45mm;
}
.address, .shipping_address {
width: 85mm;
padding-left: 5mm;
.company_invoice_line {
margin-top: 1mm;
}
> span {
color: $o-default-report-secondary-color;
}
}
.information_block, .invoice_address {
width: 75mm;
min-height: 40mm;
margin-left: 20mm;
table {
width: 100%;
}
}
}
h2 {
margin-left: 5mm;
margin-right: 10mm;
margin-top: 8.46mm;
color: $o-default-report-primary-color;
}
> .pt-5 { // hide hardcoded address from base.template.layout
display: none;
}
.page {
margin-left: 5mm;
margin-right: 10mm;
> h2, h1, #informations {
display: none;
}
[name=invoice_line_table], [name=stock_move_table], .o_main_table {
margin-top: 8.46mm;
th {
color: $o-default-report-secondary-color;
}
}
}
}
&.footer {
padding-left: 5mm;
padding-right: 10mm;
.page_number {
margin-top: 4.23mm;
width: 100%;
height: 4.23mm;
}
.company_details {
margin-top: 4.23mm;
width: 100%;
table {
border-top: solid 1px;
width: 100%;
td {
vertical-align: baseline;
padding-right: 3mm;
&:last-child {
padding-right: initial;
}
}
}
}
}
}
// TODO WAN remove in master
.din {
&.header {
min-height: 45mm;
@@ -40,7 +147,7 @@
word-break: break-word;
float: left;
}
.header_address {
.header_address {
min-height: 45mm;
}
.page_number {
+1
View File
@@ -0,0 +1 @@
from . import models
+12
View File
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Germany - Purchase',
'category': 'Accounting/Localizations',
'depends': [
'l10n_de',
'purchase',
],
'auto_install': True,
}
@@ -0,0 +1 @@
from . import purchase
@@ -0,0 +1,48 @@
from odoo import models, fields, _
from odoo.tools import format_date
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
l10n_de_document_title = fields.Char(compute='_compute_l10n_de_document_title')
l10n_de_addresses = fields.Binary(compute='_compute_l10n_de_addresses')
def _compute_l10n_de_template_data(self):
for record in self:
record.l10n_de_template_data = data = []
if record.state == 'draft':
data.append((_("Request for Quotation No."), record.name))
elif record.state in ['sent', 'to approve', 'purchase', 'done']:
data.append((_("Purchase Order No."), record.name))
elif record.state == 'cancel':
data.append((_("Cancelled Purchase Order No."), record.name))
if record.user_id:
data.append((_("Purchase Representative"), record.user_id.name))
if record.partner_ref:
data.append((_("Order Reference"), record.partner_ref))
if record.date_order:
data.append((_("Order Date"), format_date(self.env, record.date_order)))
if record.incoterm_id:
data.append((_("Incoterm"), record.incoterm_id.code))
def _compute_l10n_de_document_title(self):
for record in self:
if record.state == 'draft':
record.l10n_de_document_title = _("Request for Quotation")
elif record.state in ['sent', 'to approve', 'purchase', 'done']:
record.l10n_de_document_title = _("Purchase Order")
elif record.state == 'cancel':
record.l10n_de_document_title = _("Cancelled Purchase Order")
def _compute_l10n_de_addresses(self):
for record in self:
record.l10n_de_addresses = data = []
if record.dest_address_id:
data.append((_("Shipping Address:"), record.dest_address_id))
elif 'picking_type_id' in record._fields and record.picking_type_id.warehouse_id:
data.append((_("Shipping Address:"), record.picking_type_id.warehouse_id.partner_id))
+1
View File
@@ -0,0 +1 @@
from . import models
+12
View File
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Germany - Repair',
'category': 'Accounting/Localizations',
'depends': [
'l10n_de',
'repair',
],
'auto_install': True,
}
+1
View File
@@ -0,0 +1 @@
from . import repair
+27
View File
@@ -0,0 +1,27 @@
from odoo import models, fields, _
from odoo.tools import format_date
class RepairOrder(models.Model):
_inherit = 'repair.order'
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
l10n_de_document_title = fields.Char(compute='_compute_l10n_de_document_title')
def _compute_l10n_de_template_data(self):
for record in self:
record.l10n_de_template_data = data = []
if record.product_id:
data.append((_("Product to Repair"), record.product_id.name))
if record.lot_id:
data.append((_("Lot/Serial Number"), record.lot_id.name))
if record.guarantee_limit:
data.append((_("Warranty"), format_date(self.env, record.guarantee_limit)))
data.append((_("Printing Date"), format_date(self.env, fields.Date.today())))
def _compute_l10n_de_document_title(self):
for record in self:
if record.state == 'draft':
record.l10n_de_document_title = _("Repair Order")
else:
record.l10n_de_document_title = _("Repair Quotation")
+1
View File
@@ -0,0 +1 @@
from . import models
+12
View File
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Germany - Sale',
'category': 'Accounting/Localizations',
'depends': [
'l10n_de',
'sale',
],
'auto_install': True,
}
+1
View File
@@ -0,0 +1 @@
from . import sale
+46
View File
@@ -0,0 +1,46 @@
from odoo import models, fields, _
from odoo.tools import format_date
class SaleOrder(models.Model):
_inherit = 'sale.order'
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
l10n_de_document_title = fields.Char(compute='_compute_l10n_de_document_title')
l10n_de_addresses = fields.Binary(compute='_compute_l10n_de_addresses')
def _compute_l10n_de_template_data(self):
for record in self:
record.l10n_de_template_data = data = []
if record.state in ('draft', 'sent'):
if record.name:
data.append((_("Quotation No."), record.name))
if record.date_order:
data.append((_("Quotation Date"), format_date(self.env, record.date_order)))
if record.validity_date:
data.append((_("Expiration"), format_date(self.env, record.validity_date)))
else:
if record.name:
data.append((_("Order No."), record.name))
if record.date_order:
data.append((_("Order Date"), format_date(self.env, record.date_order)))
if record.client_order_ref:
data.append((_('Customer Reference'), record.client_order_ref))
if record.user_id:
data.append((_("Salesperson"), record.user_id.name))
def _compute_l10n_de_document_title(self):
for record in self:
if record.state in ('draft', 'sent'):
record.l10n_de_document_title = _('Quotation')
else:
record.l10n_de_document_title = _('Sales Order')
def _compute_l10n_de_addresses(self):
for record in self:
record.l10n_de_addresses = data = []
if record.partner_shipping_id == record.partner_invoice_id:
data.append((_("Invoicing and Shipping Address:"), record.partner_shipping_id))
else:
data.append((_("Shipping Address:"), record.partner_shipping_id))
data.append((_("Invoicing Address:"), record.partner_invoice_id))
+1
View File
@@ -0,0 +1 @@
from . import models
+12
View File
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Germany - Stock',
'category': 'Accounting/Localizations',
'depends': [
'l10n_de',
'stock',
],
'auto_install': True,
}
+1
View File
@@ -0,0 +1 @@
from . import stock
+14
View File
@@ -0,0 +1,14 @@
from odoo import models, fields, _
from odoo.tools import format_date
class StockInventory(models.Model):
_inherit = 'stock.inventory'
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
def _compute_l10n_de_template_data(self):
for record in self:
record.l10n_de_template_data = data = []
if record.date:
data.append((_("Date"), format_date(self.env, record.date)))
@@ -250,7 +250,6 @@ class IrActionsReport(models.Model):
'''
return wkhtmltopdf_state
@api.model
def get_paperformat(self):
return self.paperformat_id or self.env.company.paperformat_id
@@ -861,12 +860,10 @@ class IrActionsReport(models.Model):
data = self._get_rendering_context(docids, data)
return self._render_template(self.sudo().report_name, data), 'html'
@api.model
def _get_rendering_context_model(self):
report_model_name = 'report.%s' % self.report_name
return self.env.get(report_model_name)
@api.model
def _get_rendering_context(self, docids, data):
# access the report details with sudo() but evaluation context as current user
self_sudo = self.sudo()