[MERGE] forward port branch saas-12.3 up to 60e71302a3

This commit is contained in:
Christophe Simonis
2019-05-13 15:26:12 +02:00
583 changed files with 57564 additions and 27122 deletions
+2
View File
@@ -45,6 +45,8 @@ def _auto_install_l10n(cr, registry):
'PL', 'PT', 'RO', 'SI', 'TR', 'UK', 'VE', 'VN'
]:
module_list.append('base_vat')
if country_code == 'MX':
module_list.append('l10n_mx_edi')
# European countries will be using SEPA
europe = env.ref('base.europe', raise_if_not_found=False)
+4 -2
View File
@@ -28,6 +28,7 @@ You could use this simplified accounting in case you work with an (external) acc
'wizard/account_unreconcile_view.xml',
'wizard/account_move_reversal_view.xml',
'views/account_move_views.xml',
'wizard/setup_wizards_view.xml',
'views/account_view.xml',
'views/account_report.xml',
'data/mail_template_data.xml',
@@ -54,14 +55,14 @@ You could use this simplified accounting in case you work with an (external) acc
'views/account_portal_templates.xml',
'views/report_payment_receipt_templates.xml',
'data/payment_receipt_data.xml',
'wizard/setup_wizards_view.xml',
'views/account_onboarding_templates.xml',
'data/service_cron_reverse.xml',
'data/service_cron.xml',
'views/account_fiscal_year_view.xml',
'views/account_incoterms_view.xml',
'data/account_incoterms_data.xml',
'views/digest_views.xml',
'wizard/account_invoice_send_views.xml',
'views/account_tax_report_views.xml',
],
'demo': [
'demo/account_demo.xml',
@@ -71,6 +72,7 @@ You could use this simplified accounting in case you work with an (external) acc
"static/src/xml/account_payment.xml",
"static/src/xml/account_report_backend.xml",
"static/src/xml/bills_tree_upload_views.xml",
'static/src/xml/account_journal_activity.xml',
],
'installable': True,
'application': True,
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="ir_cron_auto_post_draft_entry" model="ir.cron">
<field name="name">Account; Post draft entries with auto_post set to True up to today</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="nextcall" eval="(DateTime.now().replace(hour=2, minute=0) + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')" />
<field name="doall" eval="False"/>
<field name="model_id" ref="model_account_move"/>
<field name="code">model._run_post_draft_to_post()</field>
<field name="state">code</field>
</record>
</odoo>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="ir_cron_reverse_entry" model="ir.cron">
<field name="name">Account; Reverse entries</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model_id" ref="model_account_move"/>
<field name="code">model._run_reverses_entries()</field>
<field name="state">code</field>
</record>
</odoo>
+378 -86
View File
@@ -5,7 +5,7 @@ import math
import re
from odoo.osv import expression
from odoo.tools.float_utils import float_round as round
from odoo.tools.float_utils import float_round as round, float_compare
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.exceptions import UserError, ValidationError
from odoo import api, fields, models, _
@@ -45,6 +45,123 @@ class AccountAccountTag(models.Model):
applicability = fields.Selection([('accounts', 'Accounts'), ('taxes', 'Taxes')], required=True, default='accounts')
color = fields.Integer('Color Index')
active = fields.Boolean(default=True, help="Set active to false to hide the Account Tag without removing it.")
tax_report_line_ids = fields.Many2many(string="Tax Report Lines", comodel_name='account.tax.report.line', relation='account_tax_report_line_tags_rel', help="The tax report lines using this tag")
tax_negate = fields.Boolean(string="Negate Tax Balance", help="Check this boox to negate the absolute value of the balance of the lines associated with this tag in tax report computation.")
country_id = fields.Many2one(string="Country", comodel_name='res.country', help="Country for which this tag is available, when applied on taxes.")
class AccountTaxReportLine(models.Model):
_name = "account.tax.report.line"
_description = 'Account Tax Report Line'
_order = 'sequence'
_parent_store = True
name = fields.Char(string="Name", required=True, help="Complete name for this report line, to be used in report.")
tag_ids = fields.Many2many(string="Tags", comodel_name='account.account.tag', relation='account_tax_report_line_tags_rel', help="Tax tags populating this line")
country_id = fields.Many2one(string="Country", comodel_name='res.country', required=True, default=lambda x: x.env.user.company_id.country_id.id, help="Country for which this line is available.")
report_action_id = fields.Many2one(string="Report Action", comodel_name='ir.actions.act_window', help="The optional action to call when clicking on this line in accounting reports.")
children_line_ids = fields.One2many(string="Children Lines", comodel_name='account.tax.report.line', inverse_name='parent_id', help="Lines that should be rendered as children of this one")
parent_id = fields.Many2one(string="Parent Line", comodel_name='account.tax.report.line')
sequence = fields.Integer(string='Sequence', required=True, help="Sequence determining the order of the lines in the report (smaller ones come first). This order is applied locally per section (so, chilldren of the same line are always rendered one after the other).")
parent_path = fields.Char(index=True)
#helper to create tags (positive and negative) on report line creation
tag_name = fields.Char(string="Tag Name", help="Short name for the tax grid corresponding to this report line. Leave empty if this report line should not correspond to any such grid.")
#fields used in specific localization reports, where a report line isn't simply the given by the sum of account.move.line with selected tags
code = fields.Char(string="Code", help="Optional unique code to refer to this line in total formulas")
formula = fields.Char(string="Formula", help="Python expression used to compute the value of a total line. This field is mutually exclusive with tag_name, setting it turns the line to a total line. Tax report line codes can be used as variables in this expression to refer to the balance of the corresponding lines in the report. A formula cannot refer to another line using a formula.")
@api.model
def create(self, vals):
tag_name = vals.get('tag_name', '')
if tag_name:
vals['tag_ids'] = self._get_tags_create_vals(tag_name, vals.get('country_id'))
return super(AccountTaxReportLine, self).create(vals)
@api.model
def _get_tags_create_vals(self, tag_name, country_id):
minus_tag_vals = {
'name': '-' + tag_name,
'applicability': 'taxes',
'tax_negate': True,
'country_id': country_id,
}
plus_tag_vals = {
'name': '+' + tag_name,
'applicability': 'taxes',
'tax_negate': False,
'country_id': country_id,
}
return [(0, 0, minus_tag_vals), (0, 0, plus_tag_vals)]
def write(self, vals):
rslt = super(AccountTaxReportLine, self).write(vals)
if 'tag_name' in vals:
# Constraint _validate_tags ensures that tag_ids always contains two
# tags if not empty: + and -.
# So, we can impact the whole tag_ids set if tag_name is modified.
if vals['tag_name']:
# If some lines in the set did not have tags yet, we create them
without_tags = self.filtered(lambda x: not x.tag_ids)
for record in without_tags:
record.write({'tag_ids': self._get_tags_create_vals(record.tag_name, record.country_id.id)})
# We update the name of every tag linked to other lines
to_update = self - without_tags
tags_to_update = to_update.mapped('tag_ids')
minus_child_tags = tags_to_update.filtered(lambda x: x.tax_negate)
minus_child_tags.write({'name': '-' + vals['tag_name']})
plus_child_tags = tags_to_update.filtered(lambda x: not x.tax_negate)
plus_child_tags.write({'name': '+' + vals['tag_name']})
else:
# tag_name was set empty, so we remove the tags
self._delete_tags_from_taxes(self.mapped('tag_ids.id'))
self.write({'tag_ids': [(2, tag.id, 0) for tag in self.mapped('tag_ids')]})
return rslt
def unlink(self):
self._delete_tags_from_taxes(self.mapped('tag_ids.id'))
children = self.mapped('children_line_ids')
if children:
children.unlink()
return super(AccountTaxReportLine, self).unlink()
def _delete_tags_from_taxes(self, tag_ids_to_delete):
""" Based on a list of tag ids, delete them all from database, removing them
first from the repartition lines they are linked to.
"""
repartition_lines = self.env['account.tax.repartition.line'].search([('tag_ids', 'in', tag_ids_to_delete)])
repartition_lines.write({'tag_ids': [(3, tag_id, 0) for tag_id in tag_ids_to_delete]})
@api.constrains('formula', 'tag_name')
def _validate_formula(self):
if self.formula and self.tag_name:
raise ValidationError(_("Tag name and formula are mutually exclusive, they should not be set together on the same tax report line."))
@api.constrains('tag_name', 'tag_ids')
def _validate_tags(self):
neg_tags = self.tag_ids.filtered(lambda x: x.tax_negate)
pos_tags = self.tag_ids.filtered(lambda x: not x.tax_negate)
if self.tag_ids and (len(neg_tags) !=1 or len(pos_tags) != 1):
raise ValidationError(_("If tags are defined for a tax report line, only two are allowed on it: a positive and a negative one."))
@api.onchange('parent_id')
def _onchange_parent_id(self):
""" If the parent of a report line is changed, the sequence of this line
must be updated, in order for it to match the sequence numbering of its
parent. By default, we add it as the last line of this section.
"""
if self.country_id:
lines_domain = [('country_id', '=', self.country_id.id)]
if self.parent_id:
lines_domain.append(('parent_id', '=', self.parent_id.id))
last_line = self.env['account.tax.report.line'].search(lines_domain, order="sequence desc", limit=1)
self.sequence = last_line.sequence + 1
#----------------------------------------------------------
# Accounts
@@ -88,7 +205,7 @@ class AccountAccount(models.Model):
reconcile = fields.Boolean(string='Allow Reconciliation', default=False,
help="Check this box if this account allows invoices & payments matching of journal items.")
tax_ids = fields.Many2many('account.tax', 'account_account_tax_default_rel',
'account_id', 'tax_id', string='Default Taxes')
'account_id', 'tax_id', string='Default Taxes', context={'append_type_to_tax_name': True})
note = fields.Text('Internal Notes')
company_id = fields.Many2one('res.company', string='Company', required=True,
default=lambda self: self.env.company_id)
@@ -883,6 +1000,10 @@ class AccountTaxGroup(models.Model):
name = fields.Char(required=True, translate=True)
sequence = fields.Integer(default=10)
property_tax_payable_account_id = fields.Many2one('account.account', company_dependent=True, string='Tax current account (payable)')
property_tax_receivable_account_id = fields.Many2one('account.account', company_dependent=True, string='Tax current account (receivable)')
property_advance_tax_payment_account_id = fields.Many2one('account.account', company_dependent=True, string='Advance Tax payment account')
class AccountTax(models.Model):
_name = 'account.tax'
@@ -897,24 +1018,29 @@ class AccountTax(models.Model):
type_tax_use = fields.Selection([('sale', 'Sales'), ('purchase', 'Purchases'), ('none', 'None'), ('adjustment', 'Adjustment')], string='Tax Scope', required=True, default="sale",
help="Determines where the tax is selectable. Note : 'None' means a tax can't be used by itself, however it can still be used in a group. 'adjustment' is used to perform tax adjustment.")
amount_type = fields.Selection(default='percent', string="Tax Computation", required=True, oldname='type',
selection=[('group', 'Group of Taxes'), ('fixed', 'Fixed'), ('percent', 'Percentage of Price'), ('division', 'Percentage of Price Tax Included')])
selection=[('group', 'Group of Taxes'), ('fixed', 'Fixed'), ('percent', 'Percentage of Price'), ('division', 'Percentage of Price Tax Included')],
help="""
- Group of Taxes: The tax is a set of sub taxes.
- Fixed: The tax amount stays the same whatever the price.
- Percentage of Price: The tax amount is a % of the price:
e.g 100 * 10% = 110 (not price included)
e.g 110 / (1 + 10%) = 100 (price included)
- Percentage of Price Tax Included: The tax amount is a division of the price:
e.g 180 / (1 - 10%) = 200 (not price included)
e.g 200 * (1 - 10%) = 180 (price included)
""")
active = fields.Boolean(default=True, help="Set active to false to hide the tax without removing it.")
company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company_id)
children_tax_ids = fields.Many2many('account.tax', 'account_tax_filiation_rel', 'parent_tax', 'child_tax', string='Children Taxes')
sequence = fields.Integer(required=True, default=1,
help="The sequence field is used to define order in which the tax lines are applied.")
amount = fields.Float(required=True, digits=(16, 4))
account_id = fields.Many2one('account.account', domain=[('deprecated', '=', False)], string='Tax Account', ondelete='restrict',
help="Account that will be set on invoice tax lines for invoices. Leave empty to use the expense account.", oldname='account_collected_id')
refund_account_id = fields.Many2one('account.account', domain=[('deprecated', '=', False)], string='Tax Account on Credit Notes', ondelete='restrict',
help="Account that will be set on invoice tax lines for credit notes. Leave empty to use the expense account.", oldname='account_paid_id')
description = fields.Char(string='Label on Invoices')
price_include = fields.Boolean(string='Included in Price', default=False,
help="Check this if the price you use on the product and invoices includes this tax.")
include_base_amount = fields.Boolean(string='Affect Base of Subsequent Taxes', default=False,
help="If set, taxes which are computed after this one will be computed based on the price tax included.")
analytic = fields.Boolean(string="Include in Analytic Cost", help="If set, the amount computed by this tax will be assigned to the same analytic account as the invoice line (if any)")
tag_ids = fields.Many2many('account.account.tag', 'account_tax_account_tag', string='Tags', help="Optional tags you may want to assign for custom reporting")
tax_group_id = fields.Many2one('account.tax.group', string="Tax Group", default=_default_tax_group, required=True)
# Technical field to make the 'tax_exigibility' field invisible if the same named field is set to false in 'res.company' model
hide_tax_exigibility = fields.Boolean(string='Hide Use Cash Basis Option', related='company_id.tax_exigibility', readonly=True)
@@ -925,22 +1051,55 @@ class AccountTax(models.Model):
oldname='use_cash_basis',
help="Based on Invoice: the tax is due as soon as the invoice is validated.\n"
"Based on Payment: the tax is due as soon as the payment of the invoice is received.")
cash_basis_account_id = fields.Many2one(
'account.account',
string='Tax Received Account',
domain=[('deprecated', '=', False)],
oldname='cash_basis_account',
help='Account used as counterpart for the journal entry, for taxes eligible based on payments.')
cash_basis_transition_account_id = fields.Many2one(string="Cash Basis Transition Account", domain=[('deprecated', '=', False)], comodel_name='account.account', help="Account used to transition the tax amount for cash basis taxes. It will contain the tax amount as long as the original invoice has not been reconciled ; at reconciliation, this amount cancelled on this account and put on the regular tax account.")
cash_basis_base_account_id = fields.Many2one(
'account.account',
domain=[('deprecated', '=', False)],
string='Base Tax Received Account',
help='Account that will be set on lines created in cash basis journal entry and used to keep track of the tax base amount.')
invoice_repartition_line_ids = fields.One2many(string="Repartition for Invoices", comodel_name="account.tax.repartition.line", inverse_name="invoice_tax_id", copy=True, help="Repartition when the tax is used on an invoice")
refund_repartition_line_ids = fields.One2many(string="Repartition for Refund Invoices", comodel_name="account.tax.repartition.line", inverse_name="refund_tax_id", copy=True, help="Repartition when the tax is used on a refund")
country_id = fields.Many2one(string='Country', comodel_name='res.country', related='company_id.country_id', help="Technical field used to restrict the domain of account tags for tax repartition lines created for this tax.")
_sql_constraints = [
('name_company_uniq', 'unique(name, company_id, type_tax_use)', 'Tax names must be unique !'),
]
@api.model
def default_get(self, vals):
rslt = super(AccountTax, self).default_get(vals)
if 'refund_repartition_line_ids' in vals:
rslt['refund_repartition_line_ids'] = [
(0, 0, { 'repartition_type': 'base', 'factor_percent': 100.0, 'tag_ids': [], 'company_id': rslt.get('company_id')}),
(0, 0, { 'repartition_type': 'tax', 'factor_percent': 100.0, 'tag_ids': [], 'company_id': rslt.get('company_id')}),
]
if 'invoice_repartition_line_ids' in vals:
rslt['invoice_repartition_line_ids'] = [
(0, 0, { 'repartition_type': 'base', 'factor_percent': 100.0, 'tag_ids': [], 'company_id': rslt.get('company_id')}),
(0, 0, { 'repartition_type': 'tax', 'factor_percent': 100.0, 'tag_ids': [], 'company_id': rslt.get('company_id')}),
]
return rslt
def _check_repartition_lines(self, lines):
self.ensure_one()
base_line = lines.filtered(lambda x: x.repartition_type == 'base')
if len(base_line) != 1:
raise ValidationError(_("Invoice and credit note repartition should each contain exactly one line for the base."))
@api.constrains('invoice_repartition_line_ids', 'refund_repartition_line_ids')
def _validate_repartition_lines(self):
for record in self:
record._check_repartition_lines(record.invoice_repartition_line_ids)
record._check_repartition_lines(record.refund_repartition_line_ids)
sum_inv_tax = sum(record.mapped('invoice_repartition_line_ids.factor_percent'))
sum_refund_tax = sum(record.mapped('refund_repartition_line_ids.factor_percent'))
if float_compare(sum_inv_tax, sum_refund_tax, precision_digits=4) != 0:
raise ValidationError(_("You should impact the same total percentage of the tax amount for invoices and refunds."))
@api.one
@api.constrains('children_tax_ids', 'type_tax_use')
def _check_children_scope(self):
@@ -1002,10 +1161,6 @@ class AccountTax(models.Model):
if self.amount_type is not 'group':
self.children_tax_ids = [(5,)]
@api.onchange('account_id')
def onchange_account_id(self):
self.refund_account_id = self.account_id
@api.onchange('price_include')
def onchange_price_include(self):
if self.price_include:
@@ -1015,15 +1170,18 @@ class AccountTax(models.Model):
""" Returns a string that will be used to group account.invoice.tax sharing the same properties"""
self.ensure_one()
return str(invoice_tax_val['tax_id']) + '-' + \
str(invoice_tax_val.get('tax_repartition_line_id')) + '-' + \
str(invoice_tax_val['account_id']) + '-' + \
str(invoice_tax_val['account_analytic_id']) + '-' + \
str(invoice_tax_val.get('analytic_tag_ids', []))
str(invoice_tax_val.get('analytic_tag_ids', [])) + '-' + \
str(invoice_tax_val.get('tax_ids') or [])
def _compute_amount(self, base_amount, price_unit, quantity=1.0, product=None, partner=None):
""" Returns the amount of a single tax. base_amount is the actual amount on which the tax is applied, which is
price_unit * quantity eventually affected by previous taxes (if tax is include_base_amount XOR price_include)
"""
self.ensure_one()
if self.amount_type == 'fixed':
# Use copysign to take into account the sign of the base amount which includes the sign
# of the quantity and the sign of the price_unit
@@ -1038,17 +1196,23 @@ class AccountTax(models.Model):
else:
return quantity * self.amount
price_include = self.price_include or self._context.get('force_price_include')
price_include = self._context['force_price_include'] if 'force_price_include' in self._context else self.price_include
if (self.amount_type == 'percent' and not price_include) or (self.amount_type == 'division' and price_include):
# base * (1 + tax_amount) = new_base
if self.amount_type == 'percent' and not price_include:
return base_amount * self.amount / 100
# <=> new_base = base / (1 + tax_amount)
if self.amount_type == 'percent' and price_include:
return base_amount - (base_amount / (1 + self.amount / 100))
# base / (1 - tax_amount) = new_base
if self.amount_type == 'division' and not price_include:
return base_amount / (1 - self.amount / 100) - base_amount
# <=> new_base * (1 - tax_amount) = base
if self.amount_type == 'division' and price_include:
return base_amount - (base_amount * (self.amount / 100))
@api.multi
def json_friendly_compute_all(self, price_unit, currency_id=None, quantity=1.0, product_id=None, partner_id=None):
def json_friendly_compute_all(self, price_unit, currency_id=None, quantity=1.0, product_id=None, partner_id=None, is_refund=False):
""" Just converts parameters in browse records and calls for compute_all, because js widgets can't serialize browse records """
if currency_id:
currency_id = self.env['res.currency'].browse(currency_id)
@@ -1056,10 +1220,23 @@ class AccountTax(models.Model):
product_id = self.env['product.product'].browse(product_id)
if partner_id:
partner_id = self.env['res.partner'].browse(partner_id)
return self.compute_all(price_unit, currency=currency_id, quantity=quantity, product=product_id, partner=partner_id)
return self.compute_all(price_unit, currency=currency_id, quantity=quantity, product=product_id, partner=partner_id, is_refund=is_refund)
def flatten_taxes_hierarchy(self):
# Flattens the taxes contained in this recordset, returning all the
# children at the bottom of the hierarchy, in a recordset, ordered by sequence.
# Eg. considering letters as taxes and alphabetic order as sequence :
# [G, B([A, D, F]), E, C] will be computed as [A, D, F, C, E, G]
all_taxes = self.env['account.tax']
for tax in self.sorted(key=lambda r: r.sequence):
if tax.amount_type == 'group':
all_taxes += tax.children_tax_ids.flatten_taxes_hierarchy()
else:
all_taxes += tax
return all_taxes
@api.multi
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None):
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None, is_refund=False):
""" Returns all information required to apply taxes (in self + their children in case of a tax group).
We consider the sequence of the parent for group of taxes.
Eg. considering letters as taxes and alphabetic order as sequence :
@@ -1077,15 +1254,32 @@ class AccountTax(models.Model):
'account_id': int,
'refund_account_id': int,
'analytic': boolean,
}]
}],
} """
if len(self) == 0:
company_id = self.env.company_id
if not self:
company = self.env.company_id
else:
company_id = self[0].company_id
company = self[0].company_id
# 1) Flatten the taxes.
taxes = self.flatten_taxes_hierarchy()
# 2) Avoid mixing taxes having price_include=False && include_base_amount=True
# with taxes having price_include=True. This use case is not supported as the
# computation of the total_excluded would be impossible.
base_excluded_flag = False # price_include=False && include_base_amount=True
included_flag = False # price_include=True
for tax in taxes:
if tax.price_include:
included_flag = True
elif tax.include_base_amount:
base_excluded_flag = True
if base_excluded_flag and included_flag:
raise UserError(_('Unable to mix any taxes being price included with taxes affecting the base amount but not included in price.'))
# 3) Deal with the rounding methods
if not currency:
currency = company_id.currency_id
taxes = []
currency = company.currency_id
# By default, for each tax, tax amount will first be computed
# and rounded at the 'Account' decimal precision for each
# PO/SO/invoice line and then these rounded amounts will be
@@ -1101,7 +1295,7 @@ class AccountTax(models.Model):
# amounts. For example, in SO/PO line, we don't want to round the price unit at the
# precision of the currency.
# The context key 'round' allows to force the standard behavior.
round_tax = False if company_id.tax_calculation_rounding_method == 'round_globally' else True
round_tax = False if company.tax_calculation_rounding_method == 'round_globally' else True
round_total = True
if 'round' in self.env.context:
round_tax = bool(self.env.context['round'])
@@ -1110,73 +1304,132 @@ class AccountTax(models.Model):
if not round_tax:
prec += 5
base_values = self.env.context.get('base_values')
if not base_values:
total_excluded = total_included = total_void = base = round(price_unit * quantity, prec)
else:
total_excluded, total_included, total_void, base = base_values
# 4) Iterate the taxes in the reversed sequence order to retrieve the initial base of the computation.
# tax | base | amount |
# /\ ----------------------------
# || tax_1 | XXXX | | <- we are looking for that, it's the total_excluded
# || tax_2 | .. | |
# || tax_3 | .. | |
# || ... | .. | .. |
# ----------------------------
def recompute_base(base_amount, fixed_amount, percent_amount, division_amount):
# Recompute the new base amount based on included fixed/percent amounts and the current base amount.
# Example:
# tax | amount | type | price_include |
# -----------------------------------------------
# tax_1 | 10% | percent | t
# tax_2 | 15 | fix | t
# tax_3 | 20% | percent | t
# tax_4 | 10% | division | t
# -----------------------------------------------
# Sorting key is mandatory in this case. When no key is provided, sorted() will perform a
# search. However, the search method is overridden in account.tax in order to add a domain
# depending on the context. This domain might filter out some taxes from self, e.g. in the
# case of group taxes.
for tax in self.sorted(key=lambda r: r.sequence):
# Allow forcing price_include/include_base_amount through the context for the reconciliation widget.
# See task 24014.
price_include = self._context.get('force_price_include', tax.price_include)
# if base_amount = 145, the new base is computed as:
# (145 - 15) / (1.0 + 30%) * 90% = 130 / 1.3 * 90% = 90
return (base_amount - fixed_amount) / (1.0 + percent_amount / 100.0) * (100 - division_amount) / 100
if tax.amount_type == 'group':
children = tax.children_tax_ids.with_context(base_values=(total_excluded, total_included, total_void, base))
ret = children.compute_all(price_unit, currency, quantity, product, partner)
total_excluded = ret['total_excluded']
base = ret['base'] if tax.include_base_amount else base
total_included = ret['total_included']
total_void = ret['total_void']
tax_amount = total_included - total_excluded
taxes += ret['taxes']
continue
base = round(price_unit * quantity, prec)
tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner)
if not round_tax:
tax_amount = round(tax_amount, prec)
# For the computation of move lines, we could have a negative base value.
# In this case, compute all with positive values and negate them at the end.
sign = 1
if base < 0:
base = -base
sign = -1
# Store the totals to reach when using price_include taxes (only the last price included in row)
total_included_checkpoints = {}
i = len(taxes) - 1
store_included_tax_total = True
# Keep track of the accumulated included fixed/percent amount.
incl_fixed_amount = incl_percent_amount = incl_division_amount = 0
# Store the tax amounts we compute while searching for the total_excluded
cached_tax_amounts = {}
for tax in reversed(taxes):
if tax.include_base_amount:
base = recompute_base(base, incl_fixed_amount, incl_percent_amount, incl_division_amount)
incl_fixed_amount = incl_percent_amount = incl_division_amount = 0
store_included_tax_total = True
if tax.price_include:
if tax.amount_type == 'percent':
incl_percent_amount += tax.amount
elif tax.amount_type == 'division':
incl_division_amount += tax.amount
elif tax.amount_type == 'fixed':
incl_fixed_amount += quantity * tax.amount
else:
# tax.amount_type == other (python)
tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner)
incl_fixed_amount += tax_amount
# Avoid unecessary re-computation
cached_tax_amounts[i] = tax_amount
if store_included_tax_total:
total_included_checkpoints[i] = base
store_included_tax_total = False
i -= 1
total_excluded = recompute_base(base, incl_fixed_amount, incl_percent_amount, incl_division_amount)
# 5) Iterate the taxes in the sequence order to compute missing tax amounts.
# Start the computation of accumulated amounts at the total_excluded value.
base = total_included = total_void = total_excluded
taxes_vals = []
i = 0
cumulated_tax_included_amount = 0
for tax in taxes:
#compute the tax_amount
if tax.price_include and total_included_checkpoints.get(i):
# We know the total to reach for that tax, so we make a substraction to avoid any rounding issues
tax_amount = total_included_checkpoints[i] - (base + cumulated_tax_included_amount)
cumulated_tax_included_amount = 0
else:
tax_amount = currency.round(tax_amount)
tax_amount = tax.with_context(force_price_include=False)._compute_amount(
base, price_unit, quantity, product, partner)
if price_include:
total_excluded -= tax_amount
base -= tax_amount
else:
total_included += tax_amount
# The total_void amount is computed as the sum of total_excluded
# with all tax_amount, where tax has an account set
if not tax.account_id:
total_void += tax_amount
# Round the tax_amount
tax_amount = round(tax_amount, prec)
# Keep base amount used for the current tax
tax_base = base
if tax.price_include and not total_included_checkpoints.get(i):
cumulated_tax_included_amount += tax_amount
tax_repartition_lines = is_refund and tax.refund_repartition_line_ids or tax.invoice_repartition_line_ids
repartition_lines_to_treat = len(tax_repartition_lines)
total_amount = 0
for repartition_line in tax_repartition_lines.filtered(lambda x: x.repartition_type == 'tax'):
# In case some rounding error occurs, we compensate for it on the last line
line_amount = round(sign * tax_amount * repartition_line.factor if repartition_lines_to_treat != 1 else tax_amount - total_amount, prec)
taxes_vals.append({
'id': tax.id,
'name': partner and tax.with_context(lang=partner.lang).name or tax.name,
'amount': line_amount,
'base': round(sign * base, prec),
'sequence': tax.sequence,
'account_id': tax.cash_basis_transition_account_id.id if tax.tax_exigibility == 'on_payment' else repartition_line.account_id.id,
'analytic': tax.analytic,
'price_include': tax.price_include,
'tax_exigibility': tax.tax_exigibility,
'tax_repartition_line_id': repartition_line.id,
'tag_ids': [(6, False, repartition_line.tag_ids.ids)],
})
total_amount += line_amount
if not repartition_line.account_id:
total_void += line_amount
repartition_lines_to_treat -= 1
# Affect subsequent taxes
if tax.include_base_amount:
base += tax_amount
taxes.append({
'id': tax.id,
'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
'amount': tax_amount,
'base': tax_base,
'sequence': tax.sequence,
'account_id': tax.account_id.id,
'refund_account_id': tax.refund_account_id.id,
'analytic': tax.analytic,
'price_include': tax.price_include,
'tax_exigibility': tax.tax_exigibility,
})
total_included += tax_amount
i += 1
return {
'taxes': sorted(taxes, key=lambda k: k['sequence']),
'total_excluded': currency.round(total_excluded) if round_total else total_excluded,
'total_included': currency.round(total_included) if round_total else total_included,
'total_void': currency.round(total_void) if round_total else total_void,
'base': base,
'base_tags': taxes.mapped(is_refund and 'refund_repartition_line_ids' or 'invoice_repartition_line_ids').filtered(lambda x: x.repartition_type == 'base').mapped('tag_ids').ids,
'taxes': taxes_vals,
'total_excluded': sign * (currency.round(total_excluded) if round_total else total_excluded),
'total_included': sign * (currency.round(total_included) if round_total else total_included),
'total_void': sign * (currency.round(total_void) if round_total else total_void),
}
@api.model
@@ -1195,3 +1448,42 @@ class AccountTax(models.Model):
prod_taxes = prod_taxes.filtered(lambda tax: tax.company_id == company_id)
line_taxes = line_taxes.filtered(lambda tax: tax.company_id == company_id)
return self._fix_tax_included_price(price, prod_taxes, line_taxes)
class AccountTaxRepartitionLine(models.Model):
_name = "account.tax.repartition.line"
_description = "Tax Repartition Line"
_order = 'sequence, repartition_type, id'
factor_percent = fields.Float(string="%", required=True, help="Factor to apply on the account move lines generated from this repartition line, in percents")
factor = fields.Float(string="Factor Ratio", compute="_compute_factor", help="Factor to apply on the account move lines generated from this repartition line")
repartition_type = fields.Selection(string="Based On", selection=[('base', 'Base'), ('tax', 'of tax')], required=True, default='tax', help="Base on which the factor will be applied.")
account_id = fields.Many2one(string="Account", comodel_name='account.account', help="Account on which to post the tax amount")
tag_ids = fields.Many2many(string="Tax Grid", comodel_name='account.account.tag', domain=[('applicability', '=', 'taxes')], copy=True)
invoice_tax_id = fields.Many2one(comodel_name='account.tax', help="The tax set to apply this repartition on invoices. Mutually exclusive with refund_tax_id")
refund_tax_id = fields.Many2one(comodel_name='account.tax', help="The tax set to apply this repartition on refund invoices. Mutually exclusive with invoice_tax_id")
tax_id = fields.Many2one(comodel_name='account.tax', compute='_compute_tax_id')
country_id = fields.Many2one(string="Country", comodel_name='res.country', related='company_id.country_id', help="Technical field used to restrict tags domain in form view.")
company_id = fields.Many2one(string="Company", comodel_name='res.company', required=True, default=lambda x: x.env.user.company_id, help="The company this repartition line belongs to.")
sequence = fields.Integer(string="Sequence", default=1, help="The order in which display and match repartition lines. For refunds to work properly, invoice repartition lines should be arranged in the same order as the credit note repartition lines they correspond to.")
@api.constrains('invoice_tax_id', 'refund_tax_id')
def validate_tax_template_link(self):
for record in self:
if record.invoice_tax_id and record.refund_tax_id:
raise ValidationError(_("Tax repartition lines should apply to either invoices or refunds, not both at the same time. invoice_tax_id and refund_tax_id should not be set together."))
@api.depends('factor_percent')
def _compute_factor(self):
for record in self:
record.factor = record.factor_percent / 100.0
@api.depends('invoice_tax_id', 'refund_tax_id')
def _compute_tax_id(self):
for record in self:
record.tax_id = record.invoice_tax_id or record.refund_tax_id
@api.onchange('repartition_type')
def _onchange_repartition_type(self):
if self.repartition_type == 'base':
self.account_id = None
+92 -31
View File
@@ -446,6 +446,7 @@ class AccountBankStatementLine(models.Model):
""" Prepare the dict of values to balance the move.
:param recordset move: the account.move to link the move line
:param dict move: a dict of vals of a account.move which will be created later
:param float amount: the amount of transaction that wasn't already reconciled
"""
company_currency = self.journal_id.company_id.currency_id
@@ -453,19 +454,23 @@ class AccountBankStatementLine(models.Model):
st_line_currency = self.currency_id or statement_currency
amount_currency = False
st_line_currency_rate = self.currency_id and (self.amount_currency / self.amount) or False
if isinstance(move, dict):
amount_sum = sum(x[2].get('amount_currency', 0) for x in move['line_ids'])
else:
amount_sum = sum(x.amount_currency for x in move.line_ids)
# We have several use case here to compare the currency and amount currency of counterpart line to balance the move:
if st_line_currency != company_currency and st_line_currency == statement_currency:
# company in currency A, statement in currency B and transaction in currency B
# counterpart line must have currency B and correct amount is inverse of already existing lines
amount_currency = -sum([x.amount_currency for x in move.line_ids])
amount_currency = -amount_sum
elif st_line_currency != company_currency and statement_currency == company_currency:
# company in currency A, statement in currency A and transaction in currency B
# counterpart line must have currency B and correct amount is inverse of already existing lines
amount_currency = -sum([x.amount_currency for x in move.line_ids])
amount_currency = -amount_sum
elif st_line_currency != company_currency and st_line_currency != statement_currency:
# company in currency A, statement in currency B and transaction in currency C
# counterpart line must have currency B and use rate between B and C to compute correct amount
amount_currency = -sum([x.amount_currency for x in move.line_ids])/st_line_currency_rate
amount_currency = -amount_sum/st_line_currency_rate
elif st_line_currency == company_currency and statement_currency != company_currency:
# company in currency A, statement in currency B and transaction in currency A
# counterpart line must have currency B and amount is computed using the rate between A and B
@@ -474,9 +479,8 @@ class AccountBankStatementLine(models.Model):
# last case is company in currency A, statement in currency A and transaction in currency A
# and in this case counterpart line does not need any second currency nor amount_currency
return {
aml_dict = {
'name': self.name,
'move_id': move.id,
'partner_id': self.partner_id and self.partner_id.id or False,
'account_id': amount >= 0 \
and self.statement_id.journal_id.default_credit_account_id.id \
@@ -487,22 +491,71 @@ class AccountBankStatementLine(models.Model):
'currency_id': statement_currency != company_currency and statement_currency.id or (st_line_currency != company_currency and st_line_currency.id or False),
'amount_currency': amount_currency,
}
if isinstance(move, self.env['account.move'].__class__):
aml_dict['move_id'] = move.id
return aml_dict
@api.multi
def fast_counterpart_creation(self):
"""This function is called when confirming a bank statement and will allow to automatically process lines without
going in the bank reconciliation widget. By setting an account_id on bank statement lines, it will create a journal
entry using that account to counterpart the bank account
"""
payment_list = []
move_list = []
account_type_receivable = self.env.ref('account.data_account_type_receivable')
already_done_stmt_line_ids = [a['statement_line_id'][0] for a in self.env['account.move.line'].read_group([('statement_line_id', 'in', self.ids)], ['statement_line_id'], ['statement_line_id'])]
managed_st_line = []
for st_line in self:
# Technical functionality to automatically reconcile by creating a new move line
if st_line.account_id and not st_line.journal_entry_ids.ids:
vals = {
if st_line.account_id and not st_line.id in already_done_stmt_line_ids:
managed_st_line.append(st_line.id)
# Create payment vals
total = st_line.amount
payment_methods = (total > 0) and st_line.journal_id.inbound_payment_method_ids or st_line.journal_id.outbound_payment_method_ids
currency = st_line.journal_id.currency_id or st_line.company_id.currency_id
partner_type = 'customer' if st_line.account_id.user_type_id == account_type_receivable else 'supplier'
payment_list.append({
'payment_method_id': payment_methods and payment_methods[0].id or False,
'payment_type': total > 0 and 'inbound' or 'outbound',
'partner_id': st_line.partner_id.id,
'partner_type': partner_type,
'journal_id': st_line.statement_id.journal_id.id,
'payment_date': st_line.date,
'state': 'reconciled',
'currency_id': currency.id,
'amount': abs(total),
'communication': st_line._get_communication(payment_methods[0] if payment_methods else False),
'name': st_line.statement_id.name or _("Bank Statement %s") % st_line.date,
})
# Create move and move line vals
move_vals = st_line._prepare_reconciliation_move(st_line.statement_id.name)
aml_dict = {
'name': st_line.name,
'debit': st_line.amount < 0 and -st_line.amount or 0.0,
'credit': st_line.amount > 0 and st_line.amount or 0.0,
'account_id': st_line.account_id.id,
'partner_id': st_line.partner_id.id,
'statement_line_id': st_line.id,
}
st_line.process_reconciliation(new_aml_dicts=[vals])
st_line._prepare_move_line_for_currency(aml_dict, st_line.date or fields.Date.context_today())
move_vals['line_ids'] = [(0, 0, aml_dict)]
balance_line = self._prepare_reconciliation_move_line(move_vals, st_line.amount)
move_vals['line_ids'].append((0, 0, balance_line))
move_list.append(move_vals)
# Creates
payment_ids = self.env['account.payment'].create(payment_list)
for payment_id, move_vals in zip(payment_ids, move_list):
for line in move_vals['line_ids']:
line[2]['payment_id'] = payment_id.id
move_ids = self.env['account.move'].create(move_list)
move_ids.post()
for move, st_line, payment in zip(move_ids, self.browse(managed_st_line), payment_ids):
st_line.write({'move_name': move.name})
payment.write({'payment_reference': move.name})
def _get_communication(self, payment_method_id):
return self.name or ''
@@ -630,8 +683,6 @@ class AccountBankStatementLine(models.Model):
# Create move line(s). Either matching an existing journal entry (eg. invoice), in which
# case we reconcile the existing and the new move lines together, or being a write-off.
if counterpart_aml_dicts or new_aml_dicts:
st_line_currency = self.currency_id or statement_currency
st_line_currency_rate = self.currency_id and (self.amount_currency / self.amount) or False
# Create the move
self.sequence = self.statement_id.line_ids.ids.index(self.id) + 1
@@ -654,32 +705,12 @@ class AccountBankStatementLine(models.Model):
# Complete dicts to create both counterpart move lines and write-offs
to_create = (counterpart_aml_dicts + new_aml_dicts)
company = self.company_id
date = self.date or fields.Date.today()
for aml_dict in to_create:
aml_dict['move_id'] = move.id
aml_dict['partner_id'] = self.partner_id.id
aml_dict['statement_line_id'] = self.id
if st_line_currency.id != company_currency.id:
aml_dict['amount_currency'] = aml_dict['debit'] - aml_dict['credit']
aml_dict['currency_id'] = st_line_currency.id
if self.currency_id and statement_currency.id == company_currency.id and st_line_currency_rate:
# Statement is in company currency but the transaction is in foreign currency
aml_dict['debit'] = company_currency.round(aml_dict['debit'] / st_line_currency_rate)
aml_dict['credit'] = company_currency.round(aml_dict['credit'] / st_line_currency_rate)
elif self.currency_id and st_line_currency_rate:
# Statement is in foreign currency and the transaction is in another one
aml_dict['debit'] = statement_currency._convert(aml_dict['debit'] / st_line_currency_rate, company_currency, company, date)
aml_dict['credit'] = statement_currency._convert(aml_dict['credit'] / st_line_currency_rate, company_currency, company, date)
else:
# Statement is in foreign currency and no extra currency is given for the transaction
aml_dict['debit'] = st_line_currency._convert(aml_dict['debit'], company_currency, company, date)
aml_dict['credit'] = st_line_currency._convert(aml_dict['credit'], company_currency, company, date)
elif statement_currency.id != company_currency.id:
# Statement is in foreign currency but the transaction is in company currency
prorata_factor = (aml_dict['debit'] - aml_dict['credit']) / self.amount_currency
aml_dict['amount_currency'] = prorata_factor * self.amount
aml_dict['currency_id'] = statement_currency.id
self._prepare_move_line_for_currency(aml_dict, date)
# Create write-offs
for aml_dict in new_aml_dicts:
@@ -729,6 +760,36 @@ class AccountBankStatementLine(models.Model):
counterpart_moves.assert_balanced()
return counterpart_moves
@api.multi
def _prepare_move_line_for_currency(self, aml_dict, date):
self.ensure_one()
company_currency = self.journal_id.company_id.currency_id
statement_currency = self.journal_id.currency_id or company_currency
st_line_currency = self.currency_id or statement_currency
st_line_currency_rate = self.currency_id and (self.amount_currency / self.amount) or False
company = self.company_id
if st_line_currency.id != company_currency.id:
aml_dict['amount_currency'] = aml_dict['debit'] - aml_dict['credit']
aml_dict['currency_id'] = st_line_currency.id
if self.currency_id and statement_currency.id == company_currency.id and st_line_currency_rate:
# Statement is in company currency but the transaction is in foreign currency
aml_dict['debit'] = company_currency.round(aml_dict['debit'] / st_line_currency_rate)
aml_dict['credit'] = company_currency.round(aml_dict['credit'] / st_line_currency_rate)
elif self.currency_id and st_line_currency_rate:
# Statement is in foreign currency and the transaction is in another one
aml_dict['debit'] = statement_currency._convert(aml_dict['debit'] / st_line_currency_rate, company_currency, company, date)
aml_dict['credit'] = statement_currency._convert(aml_dict['credit'] / st_line_currency_rate, company_currency, company, date)
else:
# Statement is in foreign currency and no extra currency is given for the transaction
aml_dict['debit'] = st_line_currency._convert(aml_dict['debit'], company_currency, company, date)
aml_dict['credit'] = st_line_currency._convert(aml_dict['credit'], company_currency, company, date)
elif statement_currency.id != company_currency.id:
# Statement is in foreign currency but the transaction is in company currency
prorata_factor = (aml_dict['debit'] - aml_dict['credit']) / self.amount_currency
aml_dict['amount_currency'] = prorata_factor * self.amount
aml_dict['currency_id'] = statement_currency.id
def _check_invoice_state(self, invoice):
if invoice.state == 'in_payment' and all([payment.state == 'reconciled' for payment in invoice.mapped('payment_move_line_ids.payment_id')]):
invoice.write({'state': 'paid'})
+161 -76
View File
@@ -70,6 +70,12 @@ class AccountInvoice(models.Model):
self.amount_total_signed = self.amount_total * sign
self.amount_untaxed_signed = amount_untaxed_signed * sign
def _compute_sign_taxes(self):
for invoice in self:
sign = invoice.type in ['in_refund', 'out_refund'] and -1 or 1
invoice.amount_untaxed_invoice_signed = invoice.amount_untaxed * sign
invoice.amount_tax_signed = invoice.amount_tax * sign
@api.onchange('amount_total')
def _onchange_amount_total(self):
for inv in self:
@@ -347,8 +353,12 @@ class AccountInvoice(models.Model):
store=True, readonly=True, compute='_compute_amount', tracking=True)
amount_untaxed_signed = fields.Monetary(string='Untaxed Amount in Company Currency', currency_field='company_currency_id',
store=True, readonly=True, compute='_compute_amount')
amount_untaxed_invoice_signed = fields.Monetary(string='Untaxed Amount in Invoice Currency', currency_field='currency_id',
readonly=True, compute='_compute_sign_taxes')
amount_tax = fields.Monetary(string='Tax',
store=True, readonly=True, compute='_compute_amount')
amount_tax_signed = fields.Monetary(string='Tax in Invoice Currency', currency_field='currency_id',
readonly=True, compute='_compute_sign_taxes')
amount_total = fields.Monetary(string='Total',
store=True, readonly=True, compute='_compute_amount')
amount_total_signed = fields.Monetary(string='Total in Invoice Currency', currency_field='currency_id',
@@ -684,7 +694,7 @@ class AccountInvoice(models.Model):
return self.env.ref('account.account_invoices_without_payment').report_action(self)
@api.multi
def action_reconcile_to_check(self, params):
def action_reconcile_to_check(self):
self.ensure_one()
domain = self._get_domain_edition_mode_available()
ids = self.env['account.move.line'].search(domain).mapped('statement_line_id').ids
@@ -787,7 +797,7 @@ class AccountInvoice(models.Model):
# Subscribe internal users on the newly created bill
partners = self.env['res.partner'].browse(seen_partner_ids)
is_internal = lambda p: (p.user_ids and
all(p.user_ids.mapped(lambda u: u.user_has_groups('base.group_user'))))
all(p.user_ids.mapped(lambda u: u.has_group('base.group_user'))))
partners_to_subscribe = partners.filtered(is_internal)
if partners_to_subscribe:
invoice.message_subscribe([p.id for p in partners_to_subscribe])
@@ -852,6 +862,7 @@ class AccountInvoice(models.Model):
taxes_grouped = self.get_taxes_values()
tax_lines = self.tax_line_ids.filtered('manual')
for tax in taxes_grouped.values():
# ATTENTION: due to this, fields in tax have to be in the view (possibly invisible), as they won't be saved otherwise (when hitting "save")
tax_lines += tax_lines.new(tax)
self.tax_line_ids = tax_lines
return
@@ -1069,12 +1080,13 @@ class AccountInvoice(models.Model):
else:
return self.env.ref('account.invoice_form').id
def _prepare_tax_line_vals(self, line, tax):
""" Prepare values to create an account.invoice.tax line
The line parameter is an account.invoice.line, and the
tax parameter is the output of account.tax.compute_all().
"""
def _prepare_tax_line_vals(self, line, tax, tax_ids):
''' Prepare values to create an account.invoice.tax line.
:param line: An account.invoice.line record.
:param tax: Tax values outputted by compute_all() in account.tax.
:param taxes: A list of account.tax ids affecting the tax base amount.
:return: The account.invoice.tax values to create a new record.
'''
vals = {
'invoice_id': self.id,
'name': tax['name'],
@@ -1084,8 +1096,10 @@ class AccountInvoice(models.Model):
'manual': False,
'sequence': tax['sequence'],
'account_analytic_id': tax['analytic'] and line.account_analytic_id.id or False,
'account_id': self.type in ('out_invoice', 'in_invoice') and (tax['account_id'] or line.account_id.id) or (tax['refund_account_id'] or line.account_id.id),
'account_id': tax['account_id'] or line.account_id.id,
'analytic_tag_ids': tax['analytic'] and line.analytic_tag_ids.ids or False,
'tax_ids': tax_ids and [(6, None, tax_ids)] or False,
'tax_repartition_line_id': tax.get('tax_repartition_line_id'), # For base amount, we let this field empty
}
# If the taxes generate moves on the same financial account as the invoice line,
@@ -1098,6 +1112,11 @@ class AccountInvoice(models.Model):
@api.multi
def get_taxes_values(self, tax_group_fields=False):
def is_tax_affecting_base_amount(tax):
return (tax.amount_type not in ('group', 'division') and tax.include_base_amount and tax.price_include)\
or (tax.amount_type == 'division' and tax.include_base_amount and not tax.price_include)
# Avoid redundant browsing.
tax_map = dict((t.id, t) for t in self.invoice_line_ids.mapped('invoice_line_tax_ids'))
default_tax_group_fields = set(['amount', 'base'])
if tax_group_fields:
default_tax_group_fields |= set(tax_group_fields)
@@ -1106,18 +1125,33 @@ class AccountInvoice(models.Model):
for line in self.invoice_line_ids:
if not line.account_id:
continue
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
taxes = line.invoice_line_tax_ids.compute_all(price_unit, self.currency_id, line.quantity, line.product_id, self.partner_id)['taxes']
for tax in taxes:
val = self._prepare_tax_line_vals(line, tax)
key = self.env['account.tax'].browse(tax['id']).get_grouping_key(val)
taxes = line.invoice_line_tax_ids.compute_all(price_unit, self.currency_id, line.quantity, line.product_id, self.partner_id, is_refund=self.type in ('in_refund', 'out_refund'))['taxes']
affecting_base_tax_ids = []
for tax_vals in taxes:
# Retrieve the tax record (not in tax_vals when dealing with group of taxes).
if tax_map.get(tax_vals['id']):
tax = tax_map[tax_vals['id']]
else:
tax = tax_map[tax_vals['id']] = self.env['account.tax'].browse(tax_vals['id'])
val = self._prepare_tax_line_vals(line, tax_vals, affecting_base_tax_ids)
key = tax.get_grouping_key(val)
if key not in tax_grouped:
tax_grouped[key] = val
tax_grouped[key]['base'] = round_curr(val['base'])
else:
for field in default_tax_group_fields:
tax_grouped[key][field] += round_curr(val.get(field) or 0)
tax_grouped[key][field] += round_curr(val.get(field)) or 0
if tax.amount_type == "group":
affecting_base_tax_ids += tax.children_tax_ids.filtered(lambda t: is_tax_affecting_base_amount(t)).ids
elif is_tax_affecting_base_amount(tax):
affecting_base_tax_ids.append(tax.id)
return tax_grouped
@api.multi
@@ -1199,13 +1233,19 @@ class AccountInvoice(models.Model):
continue
if line.quantity==0:
continue
tax_ids = []
for tax in line.invoice_line_tax_ids:
tax_ids.append((4, tax.id, None))
for child in tax.children_tax_ids:
tax_ids.append((4, child.id, None))
taxes_to_flatten = line.invoice_line_tax_ids
flattened_taxes = self.env['account.tax']
while taxes_to_flatten:
tax = taxes_to_flatten[0]
taxes_to_flatten -= tax
flattened_taxes += tax
taxes_to_flatten += tax.children_tax_ids
analytic_tag_ids = [(4, analytic_tag.id, None) for analytic_tag in line.analytic_tag_ids]
tax_repartition_field_name = 'invoice_repartition_line_ids' if line.invoice_type in ('in_invoice', 'out_invoice') else 'refund_repartition_line_ids'
tag_ids = flattened_taxes.mapped(tax_repartition_field_name).filtered(lambda x: x.repartition_type == 'base').mapped('tag_ids.id')
move_line_dict = {
'invl_id': line.id,
'type': 'src',
@@ -1218,25 +1258,20 @@ class AccountInvoice(models.Model):
'uom_id': line.uom_id.id,
'account_analytic_id': line.account_analytic_id.id,
'analytic_tag_ids': analytic_tag_ids,
'tax_ids': tax_ids,
'tax_ids': [(6, 0, flattened_taxes.ids)],
'invoice_id': self.id,
'tag_ids': [(6, 0, tag_ids)],
}
res.append(move_line_dict)
return res
@api.model
def tax_line_move_line_get(self):
self.ensure_one()
res = []
# keep track of taxes already processed
done_taxes = []
# loop the invoice.tax.line in reversal sequence
for tax_line in sorted(self.tax_line_ids, key=lambda x: -x.sequence):
if tax_line.amount_total:
tax = tax_line.tax_id
if tax.amount_type == "group":
for child_tax in tax.children_tax_ids:
done_taxes.append(child_tax.id)
analytic_tag_ids = [(4, analytic_tag.id, None) for analytic_tag in tax_line.analytic_tag_ids]
res.append({
'invoice_tax_line_id': tax_line.id,
@@ -1250,9 +1285,10 @@ class AccountInvoice(models.Model):
'account_analytic_id': tax_line.account_analytic_id.id,
'analytic_tag_ids': analytic_tag_ids,
'invoice_id': self.id,
'tax_ids': [(6, 0, list(done_taxes))] if tax_line.tax_id.include_base_amount else []
'tax_ids': tax_line.tax_ids and [(6, 0, tax_line.tax_ids.ids)] or False, # We don't pass an empty recordset here, as it would reset the tax_exibility of the line, due to the condition in account.move.line's create
'tax_repartition_line_id': tax_line.tax_repartition_line_id.id,
'tag_ids': [(6, 0, tax_line.tax_repartition_line_id.tag_ids.ids)],
})
done_taxes.append(tax.id)
return res
def inv_line_characteristic_hashcode(self, invoice_line):
@@ -1514,21 +1550,6 @@ class AccountInvoice(models.Model):
result.append((0, 0, values))
return result
@api.model
def _refund_tax_lines_account_change(self, lines, taxes_to_change):
# Let's change the account on tax lines when
# @param {list} lines: a list of orm commands
# @param {dict} taxes_to_change
# key: tax ID, value: refund account
if not taxes_to_change:
return lines
for line in lines:
if isinstance(line[2], dict) and line[2]['tax_id'] in taxes_to_change:
line[2]['account_id'] = taxes_to_change[line[2]['tax_id']]
return lines
def _get_refund_common_fields(self):
return ['partner_id', 'payment_term_id', 'account_id', 'currency_id', 'journal_id']
@@ -1550,6 +1571,87 @@ class AccountInvoice(models.Model):
def _get_currency_rate_date(self):
return self.date or self.date_invoice
@api.model
def _create_refund_repartition_mapping(self, taxes):
""" Creates a mapping between tax and refund repartition lines of the
provided taxes, using the sequence of repartition lines to match them.
This function is used in order to fix account.invoice.tax objects generated
for refunds when tax amounts have been modified manually.
For example, a tax with the following tax repartition...
- INVOICE:
1) 30%
2) 70%
- REFUND
3) 40%
4) 60%
... will group line 1) with line 3), and line 2) with lines 3) and 4).
:return: A dictionnary, with invoice repartition line ids as keys, and lists
of corresponding refund repartition line ids as values.
"""
rslt = {}
for tax in taxes:
inv_index = 0
ref_index = 0
tax_inv_lines = tax.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax')
tax_ref_lines = tax.refund_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax')
amount_to_match = tax_inv_lines[inv_index].factor_percent
while inv_index < len(tax_inv_lines) or ref_index < len(tax_ref_lines):
inv_rep_line = inv_index < len(tax_inv_lines) and tax_inv_lines[inv_index] or tax_inv_lines[-1]
ref_rep_line = ref_index < len(tax_ref_lines) and tax_ref_lines[ref_index] or tax_ref_lines[-1]
rslt_list = rslt.get(inv_rep_line.id, [])
if ref_rep_line.id not in rslt_list:
rslt_list.append(ref_rep_line.id)
rslt[inv_rep_line.id] = rslt_list
if amount_to_match > 0:
amount_to_match -= ref_rep_line.factor_percent
ref_index += 1
elif amount_to_match < 0:
amount_to_match += inv_rep_line.factor_percent
inv_index +=1
else:
inv_index += 1
if inv_index < len(tax_inv_lines):
amount_to_match = tax_inv_lines[inv_index].factor_percent
return rslt
def _group_tax_lines_by_repartition(self):
self.ensure_one()
rslt = {}
for tax_line in self.tax_line_ids:
rslt[tax_line.tax_repartition_line_id.id] = tax_line
return rslt
@api.model
def _fix_refund_tax_lines(self, invoice, refund):
""" Modifies the tax_line_ids of a draft refund invoice in order to make it
match the manual tax modifications that were made on its original invoice.
"""
invoice_tax_lines_map = invoice._group_tax_lines_by_repartition()
refund_tax_lines_map = refund._group_tax_lines_by_repartition()
refund_repartition_map = self._create_refund_repartition_mapping(invoice.mapped('invoice_line_ids.invoice_line_tax_ids'))
computed_tax_values = invoice.get_taxes_values()
for tax_data in computed_tax_values.values():
rep_line_id = tax_data['tax_repartition_line_id']
matching_invoice_tax = invoice_tax_lines_map.get(rep_line_id)
if matching_invoice_tax:
ref_rep_line_id = refund_repartition_map[rep_line_id][0]
refund_tax_line = refund_tax_lines_map.get(ref_rep_line_id)
manual_difference = matching_invoice_tax.amount - tax_data['amount']
if not invoice.currency_id.is_zero(manual_difference):
refund_tax_line.amount += manual_difference
@api.model
def _prepare_refund(self, invoice, date_invoice=None, date=None, description=None, journal_id=None):
""" Prepare the dict of values to create the new credit note from the invoice.
@@ -1573,14 +1675,6 @@ class AccountInvoice(models.Model):
values['invoice_line_ids'] = self._refund_cleanup_lines(invoice.invoice_line_ids)
tax_lines = invoice.tax_line_ids
taxes_to_change = {
line.tax_id.id: line.tax_id.refund_account_id.id
for line in tax_lines.filtered(lambda l: l.tax_id.refund_account_id != l.tax_id.account_id)
}
cleaned_tax_lines = self._refund_cleanup_lines(tax_lines)
values['tax_line_ids'] = self._refund_tax_lines_account_change(cleaned_tax_lines, taxes_to_change)
if journal_id:
journal = self.env['account.journal'].browse(journal_id)
elif invoice['type'] == 'in_invoice':
@@ -1621,6 +1715,7 @@ class AccountInvoice(models.Model):
message = _("This customer invoice credit note has been created from: <a href=# data-oe-model=account.invoice data-oe-id=%d>%s</a><br>Reason: %s") % (invoice.id, invoice.number, description)
else:
message = _("This vendor bill credit note has been created from: <a href=# data-oe-model=account.invoice data-oe-id=%d>%s</a><br>Reason: %s") % (invoice.id, invoice.number, description)
self._fix_refund_tax_lines(invoice, refund_invoice)
refund_invoice.message_post(body=message)
new_invoices += refund_invoice
@@ -1740,7 +1835,7 @@ class AccountInvoiceLine(models.Model):
price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
taxes = False
if self.invoice_line_tax_ids:
taxes = self.invoice_line_tax_ids.compute_all(price, currency, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id)
taxes = self.invoice_line_tax_ids.compute_all(price, currency, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id, is_refund=self.invoice_id.type in ('in_refund', 'out_refund'))
self.price_subtotal = price_subtotal_signed = taxes['total_excluded'] if taxes else self.quantity * price
self.price_total = taxes['total_included'] if taxes else self.price_subtotal
if self.invoice_id.currency_id and self.invoice_id.currency_id != self.invoice_id.company_id.currency_id:
@@ -1842,14 +1937,14 @@ class AccountInvoiceLine(models.Model):
def _set_taxes(self):
""" Used in on_change to set taxes and price"""
self.ensure_one()
if self.invoice_id.type in ('out_invoice', 'out_refund'):
taxes = self.product_id.taxes_id or self.account_id.tax_ids or self.invoice_id.company_id.account_sale_tax_id
else:
taxes = self.product_id.supplier_taxes_id or self.account_id.tax_ids or self.invoice_id.company_id.account_purchase_tax_id
# Keep only taxes of the company
company_id = self.company_id or self.env.company_id
taxes = taxes.filtered(lambda r: r.company_id == company_id)
if self.invoice_id.type in ('out_invoice', 'out_refund'):
taxes = self.product_id.taxes_id.filtered(lambda r: r.company_id == company_id) or self.account_id.tax_ids or self.invoice_id.company_id.account_sale_tax_id
else:
taxes = self.product_id.supplier_taxes_id.filtered(lambda r: r.company_id == company_id) or self.account_id.tax_ids or self.invoice_id.company_id.account_purchase_tax_id
self.invoice_line_tax_ids = fp_taxes = self.invoice_id.fiscal_position_id.map_tax(taxes, self.product_id, self.invoice_id.partner_id)
@@ -2026,7 +2121,7 @@ class AccountInvoiceLine(models.Model):
class AccountInvoiceTax(models.Model):
_name = "account.invoice.tax"
_description = "Invoice Tax"
_order = 'sequence'
_order = 'sequence, id desc'
def _prepare_invoice_tax_val(self):
self.ensure_one()
@@ -2034,25 +2129,13 @@ class AccountInvoiceTax(models.Model):
'tax_id': self.tax_id.id,
'account_id': self.account_id.id,
'account_analytic_id': self.account_analytic_id.id,
'analytic_tag_ids': self.analytic_tag_ids.ids or False}
@api.depends('invoice_id.invoice_line_ids')
def _compute_base_amount(self):
tax_grouped = {}
for invoice in self.mapped('invoice_id'):
tax_grouped[invoice.id] = invoice.get_taxes_values()
for tax in self:
tax.base = 0.0
if tax.tax_id:
key = tax.tax_id.get_grouping_key(tax._prepare_invoice_tax_val())
if tax.invoice_id and key in tax_grouped[tax.invoice_id.id]:
tax.base = tax_grouped[tax.invoice_id.id][key]['base']
else:
_logger.warning('Tax Base Amount not computable probably due to a change in an underlying tax (%s).', tax.tax_id.name)
'analytic_tag_ids': self.analytic_tag_ids.ids or False,
}
invoice_id = fields.Many2one('account.invoice', string='Invoice', ondelete='cascade', index=True)
name = fields.Char(string='Tax Description', required=True)
tax_id = fields.Many2one('account.tax', string='Tax', ondelete='restrict')
tax_repartition_line_id = fields.Many2one(string="Originating Repartition Line", comodel_name='account.tax.repartition.line')
account_id = fields.Many2one('account.account', string='Tax Account', required=True, domain=[('deprecated', '=', False)])
account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic account')
analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
@@ -2063,7 +2146,9 @@ class AccountInvoiceTax(models.Model):
sequence = fields.Integer(help="Gives the sequence order when displaying a list of invoice tax.")
company_id = fields.Many2one('res.company', string='Company', related='account_id.company_id', store=True, readonly=True)
currency_id = fields.Many2one('res.currency', related='invoice_id.currency_id', store=True, readonly=True)
base = fields.Monetary(string='Base', compute='_compute_base_amount', store=True)
base = fields.Monetary(string='Base')
tax_ids = fields.Many2many('account.tax', string='Affecting Base Taxes',
help='Taxes affecting the tax base amount applied before this one.')
@api.depends('amount', 'amount_rounding')
def _compute_amount_total(self):
@@ -2,11 +2,10 @@ import json
from datetime import datetime, timedelta
from babel.dates import format_datetime, format_date
from odoo import models, api, _, fields
from odoo.release import version
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF, safe_eval
from odoo.tools.misc import formatLang
from odoo.tools.misc import formatLang, format_date as odoo_format_date
import random
class account_journal(models.Model):
@@ -23,8 +22,41 @@ class account_journal(models.Model):
elif (self.type in ['cash', 'bank']):
self.kanban_dashboard_graph = json.dumps(self.get_line_graph_datas())
def _get_json_activity_data(self):
for journal in self:
activities = []
# search activity on move on the journal
sql_query = '''
SELECT act.id,
act.res_id,
act.res_model,
act.summary,
act_type.name as act_type_name,
act_type.category as activity_category,
act.date_deadline,
CASE WHEN act.date_deadline < CURRENT_DATE THEN 'late' ELSE 'future' END as status
FROM account_move m
LEFT JOIN mail_activity act ON act.res_id = m.id
LEFT JOIN mail_activity_type act_type ON act.activity_type_id = act_type.id
WHERE act.res_model = 'account.move'
AND m.journal_id = %s
'''
self.env.cr.execute(sql_query, (journal.id,))
for activity in self.env.cr.dictfetchall():
activities.append({
'id': activity.get('id'),
'res_id': activity.get('res_id'),
'res_model': activity.get('res_model'),
'status': activity.get('status'),
'name': activity.get('summary') or activity.get('act_type_name'),
'activity_category': activity.get('activity_category'),
'date': odoo_format_date(self.env, activity.get('date_deadline'))
})
journal.json_activity_data = json.dumps({'activities': activities})
kanban_dashboard = fields.Text(compute='_kanban_dashboard')
kanban_dashboard_graph = fields.Text(compute='_kanban_dashboard_graph')
json_activity_data = fields.Text(compute='_get_json_activity_data')
show_on_dashboard = fields.Boolean(string='Show journal on dashboard', help="Whether this journal should be displayed on the dashboard or not", default=True)
color = fields.Integer("Color Index", default=0)
@@ -215,6 +247,10 @@ class account_journal(models.Model):
(number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay, currency, curr_cache=curr_cache)
(number_draft, sum_draft) = self._count_results_and_sum_amounts(query_results_drafts, currency, curr_cache=curr_cache)
(number_late, sum_late) = self._count_results_and_sum_amounts(late_query_results, currency, curr_cache=curr_cache)
read = self.env['account.move'].read_group([('journal_id', '=', self.id), ('to_check', '=', True)], ['amount'], 'journal_id', lazy=False)
if read:
number_to_check = read[0]['__count']
to_check_balance = read[0]['amount']
difference = currency.round(last_balance-account_sum) + 0.0
+155 -105
View File
@@ -42,13 +42,38 @@ class AccountMove(models.Model):
return result
@api.multi
@api.depends('line_ids.debit', 'line_ids.credit')
@api.depends('line_ids.debit', 'line_ids.credit', 'line_ids.amount_currency', 'line_ids.currency_id')
def _amount_compute(self):
for move in self:
total = 0.0
for line in move.line_ids:
total_currency = 0.0
currency_id = move.line_ids and move.line_ids[0].currency_id.id or False
for line in move.line_ids.filtered(lambda l: l.debit):
total += line.debit
move.amount = total
if currency_id and line.currency_id.id == currency_id:
total_currency += line.amount_currency
elif currency_id:
currency_id = False
if currency_id and total_currency:
move.amount = total_currency
move.currency_id = currency_id
else:
move.currency_id = move.company_id.currency_id or self.env.user.company_id.currency_id
move.amount = total
@api.multi
def _set_amount(self):
for move in self:
if len(move.line_ids) == 2 and move.amount != 0:
amount_in_company_currency = move.amount
if move.currency_id and move.currency_id != move.company_id.currency_id:
amount_in_company_currency = move.currency_id._convert(move.amount, move.company_id.currency_id, move.company_id, move.date)
for line in move.line_ids:
line.amount_currency = line.debit and move.amount or -move.amount
for line in move.with_context(check_move_validity=False).line_ids:
line.debit = line.debit and amount_in_company_currency or 0.0
line.credit = line.credit and amount_in_company_currency or 0.0
@api.depends('line_ids.debit', 'line_ids.credit', 'line_ids.matched_debit_ids.amount', 'line_ids.matched_credit_ids.amount', 'line_ids.account_id.user_type_id.type')
def _compute_matched_percentage(self):
@@ -62,12 +87,14 @@ class AccountMove(models.Model):
if line.account_id.user_type_id.type in ('receivable', 'payable'):
amount = abs(line.debit - line.credit)
total_amount += amount
for partial_line in (line.matched_debit_ids + line.matched_credit_ids):
total_reconciled += partial_line.amount
precision_currency = move.currency_id or move.company_id.currency_id
if float_is_zero(total_amount, precision_rounding=precision_currency.rounding):
move.matched_percentage = 1.0
else:
for line in move.line_ids:
if line.account_id.user_type_id.type in ('receivable', 'payable'):
for partial_line in (line.matched_debit_ids + line.matched_credit_ids):
total_reconciled += partial_line.amount
move.matched_percentage = total_reconciled / total_amount
@api.multi
@@ -87,11 +114,6 @@ class AccountMove(models.Model):
return [('id', 'in', rmi.ids)]
return [('id', '=', False)]
@api.one
@api.depends('company_id')
def _compute_currency(self):
self.currency_id = self.company_id.currency_id or self.env.company_id.currency_id
@api.multi
def _get_default_journal(self):
if self.env.context.get('default_journal_type'):
@@ -116,7 +138,6 @@ class AccountMove(models.Model):
ref = fields.Char(string='Reference', copy=False)
date = fields.Date(required=True, states={'posted': [('readonly', True)]}, index=True, default=fields.Date.context_today)
journal_id = fields.Many2one('account.journal', string='Journal', required=True, states={'posted': [('readonly', True)]}, default=_get_default_journal)
currency_id = fields.Many2one('res.currency', compute='_compute_currency', store=True, string="Currency")
state = fields.Selection([('draft', 'Unposted'), ('posted', 'Posted')], string='Status',
required=True, readonly=True, copy=False, default='draft',
help='All manually created new journal entries are usually in the status \'Unposted\', '
@@ -127,7 +148,8 @@ class AccountMove(models.Model):
line_ids = fields.One2many('account.move.line', 'move_id', string='Journal Items',
states={'posted': [('readonly', True)]}, copy=True)
partner_id = fields.Many2one('res.partner', compute='_compute_partner_id', string="Partner", store=True, readonly=True)
amount = fields.Monetary(compute='_amount_compute', store=True)
amount = fields.Monetary(compute='_amount_compute', inverse="_set_amount", store=True)
currency_id = fields.Many2one('res.currency', compute='_amount_compute', store=True, string="Currency")
narration = fields.Text(string='Internal Note')
company_id = fields.Many2one('res.company', related='journal_id.company_id', string='Company', store=True, readonly=True)
matched_percentage = fields.Float('Percentage Matched', compute='_compute_matched_percentage', digits=0, store=True, readonly=True, help="Technical field used in cash basis method")
@@ -139,13 +161,12 @@ class AccountMove(models.Model):
string='Tax Cash Basis Entry of',
help="Technical field used to keep track of the tax cash basis reconciliation. "
"This is needed when cancelling the source: it will post the inverse journal entry to cancel that part too.")
auto_reverse = fields.Boolean(string='Reverse Automatically', default=False, help='If this checkbox is ticked, this entry will be automatically reversed at the reversal date you defined.')
reverse_date = fields.Date(string='Reversal Date', help='Date of the reverse accounting entry.')
auto_post = fields.Boolean(string='Post Automatically', default=False, help='If this checkbox is ticked, this entry will be automatically posted at its date.')
reverse_entry_id = fields.Many2one('account.move', String="Reverse entry", store=True, readonly=True)
to_check = fields.Boolean(string='To Check', default=False, help='If this checkbox is ticked, it means that the user was not sure of all the related informations at the time of the creation of the move and that the move needs to be checked again.')
tax_type_domain = fields.Char(store=False, help='Technical field used to have a dynamic taxes domain on the form view.')
@api.constrains('line_ids', 'journal_id', 'auto_reverse', 'reverse_date')
@api.constrains('line_ids', 'journal_id')
def _validate_move_modification(self):
if 'posted' in self.mapped('line_ids.payment_id.state'):
raise ValidationError(_("You cannot modify a journal entry linked to a posted payment."))
@@ -183,23 +204,16 @@ class AccountMove(models.Model):
'analytic_account_id': analytic_account_str and int(analytic_account_str) or False,
}
def _find_existing_tax_line(line_ids, tax, tag_ids, analytic_account_id):
def _find_existing_tax_line(line_ids, tax_repartition_line_id, analytic_tag_ids, analytic_account_id):
if tax.analytic:
return line_ids.filtered(lambda x: x.tax_line_id == tax and x.analytic_tag_ids.ids == tag_ids and x.analytic_account_id.id == analytic_account_id)
return line_ids.filtered(lambda x: x.tax_line_id == tax)
return line_ids.filtered(lambda x: x.tax_repartition_line_id.id == tax_repartition_line_id and x.analytic_tag_ids.ids == analytic_tag_ids and x.analytic_account_id.id == analytic_account_id)
return line_ids.filtered(lambda x: x.tax_repartition_line_id.id == tax_repartition_line_id)
def _get_lines_to_sum(line_ids, tax, tag_ids, analytic_account_id):
if tax.analytic:
return line_ids.filtered(lambda x: tax in x.tax_ids and x.analytic_tag_ids.ids == tag_ids and x.analytic_account_id.id == analytic_account_id)
return line_ids.filtered(lambda x: tax in x.tax_ids)
def _get_tax_account(tax, amount):
if tax.tax_exigibility == 'on_payment' and tax.cash_basis_account_id:
return tax.cash_basis_account_id
if tax.type_tax_use == 'purchase':
return tax.refund_account_id if amount < 0 else tax.account_id
return tax.refund_account_id if amount >= 0 else tax.account_id
# Cache the already computed tax to avoid useless recalculation.
processed_taxes = self.env['account.tax']
@@ -226,61 +240,59 @@ class AccountMove(models.Model):
to_process_taxes = (taxes - processed_taxes).filtered(lambda t: t.amount_type != 'group')
processed_taxes += to_process_taxes
# Apply tags on base line
line.tag_ids = taxes.mapped('invoice_repartition_line_ids').filtered(lambda x: x.repartition_type == 'base').mapped('tag_ids')
# Process taxes.
for tax in to_process_taxes:
tax_line = _find_existing_tax_line(self.line_ids, tax, parsed_key['tag_ids'], parsed_key['analytic_account_id'])
lines_to_sum = _get_lines_to_sum(self.line_ids, tax, parsed_key['tag_ids'], parsed_key['analytic_account_id'])
if not lines_to_sum:
# Drop tax line because the originator tax is no longer used.
self.line_ids -= tax_line
continue
balance = sum([l.balance for l in lines_to_sum])
# Compute the tax amount one by one.
quantity = len(lines_to_sum) if tax.amount_type == 'fixed' else 1
taxes_vals = tax.compute_all(balance,
quantity=quantity, currency=line.currency_id, product=line.product_id, partner=line.partner_id)
taxes_vals = tax.compute_all(balance, quantity=quantity, currency=line.currency_id, product=line.product_id, partner=line.partner_id)
if tax_line:
# Update the existing tax_line.
if balance:
# Update the debit/credit amount according to the new balance.
if taxes_vals.get('taxes'):
amount = taxes_vals['taxes'][0]['amount']
account = _get_tax_account(tax, amount) or line.account_id
tax_line.debit = amount > 0 and amount or 0.0
tax_line.credit = amount < 0 and -amount or 0.0
tax_line.account_id = account
else:
# Reset debit/credit in case of the originator line is temporary set to 0 in both debit/credit.
tax_line.debit = tax_line.credit = 0.0
elif taxes_vals.get('taxes'):
# Create a new tax_line.
if taxes_vals.get('taxes'):
for line_vals in taxes_vals['taxes']:
tax_line = _find_existing_tax_line(self.line_ids, line_vals['tax_repartition_line_id'], parsed_key['tag_ids'], parsed_key['analytic_account_id'])
if tax_line:
if not lines_to_sum:
# Drop tax line because the originator tax is no longer used.
self.line_ids -= tax_line
elif balance:
# Update the existing tax_line.
# Update the debit/credit amount according to the new balance.
amount = line_vals['amount']
account = line_vals['account_id'] or line.account_id
tax_line.debit = amount > 0 and amount or 0.0
tax_line.credit = amount < 0 and -amount or 0.0
tax_line.account_id = account
else:
# Reset debit/credit in case of the originator line is temporary set to 0 in both debit/credit.
tax_line.debit = tax_line.credit = 0.0
else:
# Create a new tax_line.
amount = taxes_vals['taxes'][0]['amount']
account = _get_tax_account(tax, amount) or line.account_id
tax_vals = taxes_vals['taxes'][0]
name = tax_vals['name']
line_vals = {
'account_id': account.id,
'name': name,
'tax_line_id': tax_vals['id'],
'partner_id': line.partner_id.id,
'debit': amount > 0 and amount or 0.0,
'credit': amount < 0 and -amount or 0.0,
'analytic_account_id': line.analytic_account_id.id if tax.analytic else False,
'analytic_tag_ids': line.analytic_tag_ids.ids if tax.analytic else False,
'move_id': self.id,
'tax_exigible': tax.tax_exigibility == 'on_invoice',
'company_id': self.company_id.id,
'company_currency_id': self.company_id.currency_id.id,
}
# N.B. currency_id/amount_currency are not set because if we have two lines with the same tax
# and different currencies, we have no idea which currency set on this line.
self.env['account.move.line'].new(line_vals)
amount = line_vals['amount']
to_create_vals = {
'account_id': line_vals['account_id'] or line.account_id.id,
'name': line_vals['name'],
'partner_id': line.partner_id.id,
'debit': amount > 0 and amount or 0.0,
'credit': amount < 0 and -amount or 0.0,
'analytic_account_id': line.analytic_account_id.id if tax.analytic else False,
'analytic_tag_ids': line.analytic_tag_ids.ids if tax.analytic else False,
'move_id': self.id,
'tax_exigible': tax.tax_exigibility == 'on_invoice',
'company_id': self.company_id.id,
'company_currency_id': self.company_id.currency_id.id,
'tax_repartition_line_id': line_vals['tax_repartition_line_id'],
'tag_ids': line_vals['tag_ids'],
}
# N.B. currency_id/amount_currency are not set because if we have two lines with the same tax
# and different currencies, we have no idea which currency set on this line.
self.env['account.move.line'].new(to_create_vals)
# Keep record of the values used as taxes the last time this method has been run.
line.tax_line_grouping_key = _build_grouping_key(line)
@@ -314,6 +326,9 @@ class AccountMove(models.Model):
# Create the analytic lines in batch is faster as it leads to less cache invalidation.
self.mapped('line_ids').create_analytic_lines()
for move in self:
if move.auto_post and move.date > fields.Date.today():
raise UserError(_("This move is configured to be auto-posted on {}".format(move.date.strftime(self.env['res.lang']._lang_get(self.env.user.lang).date_format))))
if move.name == '/':
new_name = False
journal = move.journal_id
@@ -416,14 +431,14 @@ class AccountMove(models.Model):
return True
@api.multi
def _reverse_move(self, date=None, journal_id=None, auto=False):
def _reverse_move(self, date=None, journal_id=None):
self.ensure_one()
with self.env.norecompute():
reversed_move = self.copy(default={
'date': date,
'journal_id': journal_id.id if journal_id else self.journal_id.id,
'ref': (_('Automatic reversal of: %s') if auto else _('Reversal of: %s')) % (self.name),
'auto_reverse': False})
'ref': _('Reversal of: %s') % (self.name),
})
for acm_line in reversed_move.line_ids.with_context(check_move_validity=False):
acm_line.write({
'debit': acm_line.credit,
@@ -435,16 +450,14 @@ class AccountMove(models.Model):
return reversed_move
@api.multi
def reverse_moves(self, date=None, journal_id=None, auto=False):
def reverse_moves(self, date=None, journal_id=None):
date = date or fields.Date.today()
reversed_moves = self.env['account.move']
for ac_move in self:
#unreconcile all lines reversed
aml = ac_move.line_ids.filtered(lambda x: x.account_id.reconcile or x.account_id.internal_type == 'liquidity')
aml.remove_move_reconcile()
reversed_move = ac_move._reverse_move(date=date,
journal_id=journal_id,
auto=auto)
reversed_move = ac_move._reverse_move(date=date, journal_id=journal_id)
reversed_moves |= reversed_move
#reconcile together the reconcilable (or the liquidity aml) and their newly created counterpart
for account in set([x.account_id for x in aml]):
@@ -475,18 +488,17 @@ class AccountMove(models.Model):
return action
@api.model
def _run_reverses_entries(self):
''' This method is called from a cron job. '''
def _run_post_draft_to_post(self):
''' This method is called from a cron job.
It is used to post entries such as those created by the module
account_asset.
'''
records = self.search([
('state', '=', 'posted'),
('auto_reverse', '=', True),
('reverse_date', '<=', fields.Date.today()),
('reverse_entry_id', '=', False)])
for move in records:
date = None
if move.reverse_date and (not self.env.company_id.period_lock_date or move.reverse_date > self.env.company_id.period_lock_date):
date = move.reverse_date
move.reverse_moves(date=date, auto=True)
('state', '=', 'draft'),
('date', '<=', fields.Date.today()),
('auto_post', '=', True),
])
records.post()
@api.multi
def action_view_reverse_entry(self):
@@ -670,7 +682,8 @@ class AccountMoveLine(models.Model):
date = fields.Date(related='move_id.date', string='Date', index=True, store=True, copy=False, readonly=False) # related is required
analytic_line_ids = fields.One2many('account.analytic.line', 'move_id', string='Analytic lines', oldname="analytic_lines")
tax_ids = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)])
tax_line_id = fields.Many2one('account.tax', string='Originator tax', ondelete='restrict')
tax_line_id = fields.Many2one('account.tax', string='Originator tax', ondelete='restrict', compute='_compute_tax_line_id', store=True)
tax_repartition_line_id = fields.Many2one(comodel_name='account.tax.repartition.line', string="Originator Tax Repartition Line", ondelete='restrict', help="Tax repartition line that caused the creation of this move line, if any")
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account', index=True)
analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags')
company_id = fields.Many2one('res.company', related='account_id.company_id', string='Company', store=True, readonly=True)
@@ -684,6 +697,8 @@ class AccountMoveLine(models.Model):
recompute_tax_line = fields.Boolean(store=False, help="Technical field used to know if the tax_ids field has been modified in the UI.")
tax_line_grouping_key = fields.Char(store=False, string='Old Taxes', help="Technical field used to store the old values of fields used to compute tax lines (in account.move form view) between the moment the user changed it and the moment the ORM reflects that change in its one2many")
tag_ids = fields.Many2many(string="Tags", comodel_name='account.account.tag', ondelete='restrict', help="Tags assigned to this line by the tax creating it, if any. It determines its impact on financial reports.")
tax_audit = fields.Char(string="Tax Audit String", compute="_compute_tax_audit", store=True, help="Computed field, listing the tax grids impacted by this line, and the amount it applies to each of them.")
_sql_constraints = [
('credit_debit1', 'CHECK (credit*debit=0)', 'Wrong credit or debit value in accounting entry !'),
@@ -753,12 +768,44 @@ class AccountMoveLine(models.Model):
if (line.amount_currency > 0.0 and line.credit > 0.0) or (line.amount_currency < 0.0 and line.debit > 0.0):
raise ValidationError(_('The amount expressed in the secondary currency must be positive when account is debited and negative when account is credited.'))
@api.depends('tax_repartition_line_id.invoice_tax_id', 'tax_repartition_line_id.refund_tax_id')
def _compute_tax_line_id(self):
""" tax_line_id is computed as the tax linked to the repartition line creating
the move.
"""
for record in self:
rep_line = record.tax_repartition_line_id
# A constraint on account.tax.repartition.line ensures both those fields are mutually exclusive
record.tax_line_id = rep_line.invoice_tax_id or rep_line.refund_tax_id
@api.depends('account_id.user_type_id')
def _compute_is_unaffected_earnings_line(self):
for record in self:
unaffected_earnings_type = self.env.ref("account.data_unaffected_earnings")
record.is_unaffected_earnings_line = unaffected_earnings_type == record.account_id.user_type_id
@api.depends('tag_ids', 'debit', 'credit', 'journal_id', 'invoice_id')
def _compute_tax_audit(self):
separator = ' '
for record in self:
currency = record.company_id.currency_id
audit_str = ''
for tag in record.tag_ids:
tag_amount = (tag.tax_negate and -1 or 1) * (record.journal_id.type == 'sale' and -1 or 1) * (record.invoice_id.type in ('in_refund', 'out_refund') and -1 or 1) * record.balance
if tag.tax_report_line_ids:
#Then, the tag comes from a report line, and hence has a + or - sign (also in its name)
for report_line in tag.tax_report_line_ids:
audit_str += separator if audit_str else ''
audit_str += report_line.tag_name + ': ' + formatLang(self.env, tag_amount, currency_obj=currency)
else:
# Then, it's a financial tag (sign is always +, and never shown in tag name)
audit_str += separator if audit_str else ''
audit_str += tag.name + ': ' + formatLang(self.env, tag_amount, currency_obj=currency)
record.tax_audit = audit_str
@api.onchange('amount_currency', 'currency_id', 'account_id')
def _onchange_amount_currency(self):
'''Recompute the debit/credit based on amount_currency/currency_id and date.
@@ -786,22 +833,21 @@ class AccountMoveLine(models.Model):
In case of full reconciliation, all moves belonging to the reconciliation will belong to the same account_full_reconcile object.
"""
# Get first all aml involved
part_recs = self.env['account.partial.reconcile'].search(['|', ('debit_move_id', 'in', self.ids), ('credit_move_id', 'in', self.ids)])
amls = self
todo = set(part_recs)
todo = self.env['account.partial.reconcile'].search_read(['|', ('debit_move_id', 'in', self.ids), ('credit_move_id', 'in', self.ids)], ['debit_move_id', 'credit_move_id'])
amls = set(self.ids)
seen = set()
while todo:
partial_rec = todo.pop()
seen.add(partial_rec)
for aml in [partial_rec.debit_move_id, partial_rec.credit_move_id]:
if aml not in amls:
amls += aml
for x in aml.matched_debit_ids | aml.matched_credit_ids:
if x not in seen:
todo.add(x)
partial_rec_ids = [x.id for x in seen]
aml_ids = [rec['debit_move_id'][0] for rec in todo if rec['debit_move_id']] + [rec['credit_move_id'][0] for rec in todo if rec['credit_move_id']]
amls |= set(aml_ids)
seen |= set([rec['id'] for rec in todo])
todo = self.env['account.partial.reconcile'].search_read(['&', '|', ('credit_move_id', 'in', aml_ids), ('debit_move_id', 'in', aml_ids), '!', ('id', 'in', list(seen))], ['debit_move_id', 'credit_move_id'])
partial_rec_ids = list(seen)
if not amls:
return
else:
amls = self.browse(list(amls))
# If we have multiple currency, we can only base ourselve on debit-credit to see if it is fully reconciled
currency = set([a.currency_id for a in amls if a.currency_id.id != False])
multiple_currency = False
@@ -1040,7 +1086,7 @@ class AccountMoveLine(models.Model):
partner_id = self.env['res.partner']._find_accounting_partner(self[0].partner_id).id
company_currency = self[0].account_id.company_id.currency_id
writeoff_currency = self[0].currency_id or company_currency
writeoff_currency = self[0].account_id.currency_id or company_currency
line_to_reconcile = self.env['account.move.line']
# Iterate and create one writeoff by journal
writeoff_moves = self.env['account.move']
@@ -1214,8 +1260,8 @@ class AccountMoveLine(models.Model):
#Toggle the 'tax_exigible' field to False in case it is not yet given and the tax in 'tax_line_id' or one of
#the 'tax_ids' is a cash based tax.
taxes = False
if vals.get('tax_line_id'):
taxes = [{'tax_exigibility': self.env['account.tax'].browse(vals['tax_line_id']).tax_exigibility}]
if vals.get('tax_repartition_line_id'):
taxes = [{'tax_exigibility': self.env['account.tax.repartition.line'].browse(vals['tax_repartition_line_id']).tax_id.tax_exigibility}]
if vals.get('tax_ids'):
taxes = self.env['account.move.line'].resolve_2many_commands('tax_ids', vals['tax_ids'])
if taxes and any([tax['tax_exigibility'] == 'on_payment' for tax in taxes]) and not vals.get('tax_exigible'):
@@ -1668,7 +1714,7 @@ class AccountPartialReconcile(models.Model):
'name': line.name,
'debit': rounded_amt if rounded_amt > 0 else 0.0,
'credit': abs(rounded_amt) if rounded_amt < 0 else 0.0,
'account_id': line.tax_line_id.cash_basis_account_id.id,
'account_id': line.tax_repartition_line_id.account_id.id,
'analytic_account_id': line.analytic_account_id.id,
'analytic_tag_ids': line.analytic_tag_ids.ids,
'tax_line_id': line.tax_line_id.id,
@@ -1677,6 +1723,8 @@ class AccountPartialReconcile(models.Model):
'currency_id': line.currency_id.id,
'move_id': newly_created_move.id,
'partner_id': line.partner_id.id,
'tax_repartition_line_id': line.tax_repartition_line_id.id,
'tag_ids': [(6, 0, line.tag_ids.ids)],
})
if line.account_id.reconcile:
#setting the account to allow reconciliation will help to fix rounding errors
@@ -1700,6 +1748,8 @@ class AccountPartialReconcile(models.Model):
'currency_id': line.currency_id.id,
'amount_currency': self.amount_currency and line.currency_id.round(line.amount_currency * amount / line.balance) or 0.0,
'partner_id': line.partner_id.id,
'tax_repartition_line_id': line.tax_repartition_line_id.id,
'tag_ids': [(6, 0, line.tag_ids.ids)],
})
self.env['account.move.line'].with_context(check_move_validity=False).create({
'name': line.name,
+24
View File
@@ -108,6 +108,16 @@ class account_payment(models.Model):
# Check all invoices are open
if any(invoice.state != 'open' for invoice in invoices):
raise UserError(_("You can only register payments for open invoices"))
# Check if, in batch payments, there are not negative invoices and positive invoices
dtype = invoices[0].type
for inv in invoices[1:]:
if inv.type != dtype:
if ((dtype == 'in_refund' and inv.type == 'in_invoice') or
(dtype == 'in_invoice' and inv.type == 'in_refund')):
raise UserError(_("You cannot register payments for vendor bills and supplier refunds at the same time."))
if ((dtype == 'out_refund' and inv.type == 'out_invoice') or
(dtype == 'out_invoice' and inv.type == 'out_refund')):
raise UserError(_("You cannot register payments for customer invoices and credit notes at the same time."))
amount = self._compute_payment_amount(invoices, invoices[0].currency_id)
rec.update({
@@ -660,6 +670,20 @@ class account_payment(models.Model):
return vals
def _get_invoice_payment_amount(self, inv):
"""
Computes the amount covered by the current payment in the given invoice.
:param inv: an invoice object
:returns: the amount covered by the payment in the invoice
"""
self.ensure_one()
return sum([
data['amount']
for data in inv._get_payments_vals()
if data['account_payment_id'] == self.id
])
class payment_register(models.TransientModel):
_name = 'account.payment.register'
+124 -28
View File
@@ -3,7 +3,7 @@
from odoo.exceptions import AccessError
from odoo import api, fields, models, _
from odoo import SUPERUSER_ID
from odoo.exceptions import UserError
from odoo.exceptions import UserError, ValidationError
from odoo.http import request
import logging
@@ -124,6 +124,9 @@ class AccountChartTemplate(models.Model):
property_stock_account_input_categ_id = fields.Many2one('account.account.template', string="Input Account for Stock Valuation", oldname="property_stock_account_input_categ")
property_stock_account_output_categ_id = fields.Many2one('account.account.template', string="Output Account for Stock Valuation", oldname="property_stock_account_output_categ")
property_stock_valuation_account_id = fields.Many2one('account.account.template', string="Account Template for Stock Valuation")
property_tax_payable_account_id = fields.Many2one('account.account.template', string="Tax current account (payable)")
property_tax_receivable_account_id = fields.Many2one('account.account.template', string="Tax current account (receivable)")
property_advance_tax_payment_account_id = fields.Many2one('account.account.template', string="Advance tax payment account")
@api.model
def _prepare_transfer_account_template(self):
@@ -413,7 +416,7 @@ class AccountChartTemplate(models.Model):
journals = [{'name': _('Customer Invoices'), 'type': 'sale', 'code': _('INV'), 'favorite': True, 'color': 11, 'sequence': 5},
{'name': _('Vendor Bills'), 'type': 'purchase', 'code': _('BILL'), 'favorite': True, 'color': 11, 'sequence': 6},
{'name': _('Miscellaneous Operations'), 'type': 'general', 'code': _('MISC'), 'favorite': False, 'sequence': 7},
{'name': _('Miscellaneous Operations'), 'type': 'general', 'code': _('MISC'), 'favorite': True, 'sequence': 7},
{'name': _('Exchange Difference'), 'type': 'general', 'code': _('EXCH'), 'favorite': False, 'sequence': 9},
{'name': _('Cash Basis Taxes'), 'type': 'general', 'code': _('CABA'), 'favorite': False, 'sequence': 10}]
if journals_dict != None:
@@ -454,6 +457,9 @@ class AccountChartTemplate(models.Model):
('property_account_income_categ_id', 'product.category', 'account.account'),
('property_account_expense_id', 'product.template', 'account.account'),
('property_account_income_id', 'product.template', 'account.account'),
('property_tax_payable_account_id', 'account.tax.group', 'account.account'),
('property_tax_receivable_account_id', 'account.tax.group', 'account.account'),
('property_advance_tax_payment_account_id', 'account.tax.group', 'account.account'),
]
for record in todo_list:
account = getattr(self, record[0])
@@ -547,15 +553,20 @@ class AccountChartTemplate(models.Model):
account_ref.update(account_template_ref)
# writing account values after creation of accounts
for key, value in generated_tax_res['account_dict'].items():
if value['refund_account_id'] or value['account_id'] or value['cash_basis_account_id'] or value['cash_basis_base_account_id']:
for key, value in generated_tax_res['account_dict']['account.tax'].items():
if value['cash_basis_transition_account_id'] or value['cash_basis_base_account_id']:
AccountTaxObj.browse(key).write({
'refund_account_id': account_ref.get(value['refund_account_id'], False),
'account_id': account_ref.get(value['account_id'], False),
'cash_basis_account_id': account_ref.get(value['cash_basis_account_id'], False),
'cash_basis_transition_account_id': account_ref.get(value['cash_basis_transition_account_id'], False),
'cash_basis_base_account_id': account_ref.get(value['cash_basis_base_account_id'], False),
})
AccountTaxRepartitionLineObj = self.env['account.tax.repartition.line']
for key, value in generated_tax_res['account_dict']['account.tax.repartition.line'].items():
if value['account_id']:
AccountTaxRepartitionLineObj.browse(key).write({
'account_id': account_ref.get(value['account_id']),
})
# Create Journals - Only done for root chart template
if not self.parent_id:
self.generate_journals(account_ref, company)
@@ -675,6 +686,7 @@ class AccountChartTemplate(models.Model):
'company_id': company.id,
'account_id': acc_template_ref[account_reconcile_model.account_id.id],
'label': account_reconcile_model.label,
'to_check': account_reconcile_model.to_check,
'amount_type': account_reconcile_model.amount_type,
'force_tax_included': account_reconcile_model.force_tax_included,
'amount': account_reconcile_model.amount,
@@ -795,18 +807,15 @@ class AccountTaxTemplate(models.Model):
children_tax_ids = fields.Many2many('account.tax.template', 'account_tax_template_filiation_rel', 'parent_tax', 'child_tax', string='Children Taxes')
sequence = fields.Integer(required=True, default=1,
help="The sequence field is used to define order in which the tax lines are applied.")
amount = fields.Float(required=True, digits=(16, 4))
account_id = fields.Many2one('account.account.template', string='Tax Account', ondelete='restrict',
help="Account that will be set on invoice tax lines for invoices. Leave empty to use the expense account.", oldname='account_collected_id')
refund_account_id = fields.Many2one('account.account.template', string='Tax Account on Refunds', ondelete='restrict',
help="Account that will be set on invoice tax lines for refunds. Leave empty to use the expense account.", oldname='account_paid_id')
amount = fields.Float(required=True, digits=(16, 4), default=0)
description = fields.Char(string='Display on Invoices')
price_include = fields.Boolean(string='Included in Price', default=False,
help="Check this if the price you use on the product and invoices includes this tax.")
include_base_amount = fields.Boolean(string='Affect Subsequent Taxes', default=False,
help="If set, taxes which are computed after this one will be computed based on the price tax included.")
analytic = fields.Boolean(string="Analytic Cost", help="If set, the amount computed by this tax will be assigned to the same analytic account as the invoice line (if any)")
tag_ids = fields.Many2many('account.account.tag', string='Account tag', help="Optional tags you may want to assign for custom reporting")
invoice_repartition_line_ids = fields.One2many(string="Repartition for Invoices", comodel_name="account.tax.repartition.line.template", inverse_name="invoice_tax_id", copy=True, help="Repartition when the tax is used on an invoice")
refund_repartition_line_ids = fields.One2many(string="Repartition for Refund Invoices", comodel_name="account.tax.repartition.line.template", inverse_name="refund_tax_id", copy=True, help="Repartition when the tax is used on a refund")
tax_group_id = fields.Many2one('account.tax.group', string="Tax Group")
tax_exigibility = fields.Selection(
[('on_invoice', 'Based on Invoice'),
@@ -815,12 +824,11 @@ class AccountTaxTemplate(models.Model):
oldname='use_cash_basis',
help="Based on Invoice: the tax is due as soon as the invoice is validated.\n"
"Based on Payment: the tax is due as soon as the payment of the invoice is received.")
cash_basis_account_id = fields.Many2one(
'account.account.template',
string='Tax Received Account',
cash_basis_transition_account_id = fields.Many2one(
comodel_name='account.account.template',
string="Cash Basis Transition Account",
domain=[('deprecated', '=', False)],
oldname='cash_basis_account',
help='Account used as counterpart for the journal entry, for taxes eligible based on payments.')
help="Account used to transition the tax amount for cash basis taxes. It will contain the tax amount as long as the original invoice has not been reconciled ; at reconciliation, this amount cancelled on this account and put on the regular tax account.")
cash_basis_base_account_id = fields.Many2one(
'account.account.template',
domain=[('deprecated', '=', False)],
@@ -861,11 +869,17 @@ class AccountTaxTemplate(models.Model):
'price_include': self.price_include,
'include_base_amount': self.include_base_amount,
'analytic': self.analytic,
'tag_ids': [(6, 0, [t.id for t in self.tag_ids])],
'children_tax_ids': [(6, 0, children_ids)],
'tax_exigibility': self.tax_exigibility,
}
# We add repartition lines if there are some, so that if there are none,
# default_get is called and creates the default ones properly.
if self.invoice_repartition_line_ids:
val['invoice_repartition_line_ids'] = self.invoice_repartition_line_ids.get_repartition_line_create_vals(company)
if self.refund_repartition_line_ids:
val['refund_repartition_line_ids'] = self.refund_repartition_line_ids.get_repartition_line_create_vals(company)
if self.tax_group_id:
val['tax_group_id'] = self.tax_group_id.id
return val
@@ -881,7 +895,7 @@ class AccountTaxTemplate(models.Model):
}
"""
ChartTemplate = self.env['account.chart.template']
todo_dict = {}
todo_dict = {'account.tax': {}, 'account.tax.repartition.line': {}}
tax_template_to_tax = {}
templates_todo = list(self)
@@ -890,27 +904,36 @@ class AccountTaxTemplate(models.Model):
templates_todo = []
# create taxes in batch
template_vals = []
tax_template_vals = []
for template in templates:
if all(child.id in tax_template_to_tax for child in template.children_tax_ids):
vals = template._get_tax_vals(company, tax_template_to_tax)
template_vals.append((template, vals))
tax_template_vals.append((template, vals))
else:
# defer the creation of this tax to the next batch
templates_todo.append(template)
taxes = ChartTemplate._create_records_with_xmlid('account.tax', template_vals, company)
taxes = ChartTemplate._create_records_with_xmlid('account.tax', tax_template_vals, company)
# fill in tax_template_to_tax and todo_dict
for tax, (template, vals) in zip(taxes, template_vals):
for tax, (template, vals) in zip(taxes, tax_template_vals):
tax_template_to_tax[template.id] = tax.id
# Since the accounts have not been created yet, we have to wait before filling these fields
todo_dict[tax.id] = {
'account_id': template.account_id.id,
'refund_account_id': template.refund_account_id.id,
'cash_basis_account_id': template.cash_basis_account_id.id,
todo_dict['account.tax'][tax.id] = {
'cash_basis_transition_account_id': template.cash_basis_transition_account_id.id,
'cash_basis_base_account_id': template.cash_basis_base_account_id.id,
}
# We also have to delay the assignation of accounts to repartition lines
all_tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
all_template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
for i in range(0, len(all_tax_rep_lines)):
# We assume template and tax repartition lines are in the same order
template_account = all_template_rep_lines[i].account_id
if template_account:
todo_dict['account.tax.repartition.line'][all_tax_rep_lines[i].id] = {
'account_id': template_account.id,
}
if any(template.tax_exigibility == 'on_payment' for template in self):
# When a CoA is being installed automatically and if it is creating account tax(es) whose field `Use Cash Basis`(tax_exigibility) is set to True by default
# (example of such CoA's are l10n_fr and l10n_mx) then in the `Accounting Settings` the option `Cash Basis` should be checked by default.
@@ -921,6 +944,79 @@ class AccountTaxTemplate(models.Model):
'account_dict': todo_dict
}
# Tax Repartition Line Template
class AccountTaxRepartitionLineTemplate(models.Model):
_name = "account.tax.repartition.line.template"
_description = "Tax Repartition Line Template"
factor_percent = fields.Float(string="%", required=True, help="Factor to apply on the account move lines generated from this repartition line, in percents")
repartition_type = fields.Selection(string="Based On", selection=[('base', 'Base'), ('tax', 'of tax')], required=True, default='tax', help="Base on which the factor will be applied.")
account_id = fields.Many2one(string="Account", comodel_name='account.account.template', help="Account on which to post the tax amount")
invoice_tax_id = fields.Many2one(comodel_name='account.tax.template', help="The tax set to apply this repartition on invoices. Mutually exclusive with refund_tax_id")
refund_tax_id = fields.Many2one(comodel_name='account.tax.template', help="The tax set to apply this repartition on refund invoices. Mutually exclusive with invoice_tax_id")
tag_ids = fields.Many2many(string="Financial Tags", relation='account_tax_repartition_financial_tags', comodel_name='account.account.tag', copy=True, help="Additional tags that will be assigned by this repartition line for use in financial reports")
# These last two fields are helpers used to ease the declaration of account.account.tag objects in XML.
# They are directly linked to account.tax.report.line objects, which create corresponding + and - tags
# at creation. This way, we avoid declaring + and - separately every time.
plus_report_line_ids = fields.Many2many(string="Plus Tax Report Lines", relation='account_tax_repartition_plus_report_line', comodel_name='account.tax.report.line', copy=True, help="Tax report lines whose '+' tag will be assigned to move lines by this repartition line")
minus_report_line_ids = fields.Many2many(string="Minus Report Lines", relation='account_tax_repartition_minus_report_line', comodel_name='account.tax.report.line', copy=True, help="Tax report lines whose '-' tag will be assigned to move lines by this repartition line")
@api.model
def create(self, vals):
if vals.get('plus_report_line_ids'):
vals['plus_report_line_ids'] = self._convert_tag_syntax_to_orm(vals['plus_report_line_ids'])
if vals.get('minus_report_line_ids'):
vals['minus_report_line_ids'] = self._convert_tag_syntax_to_orm(vals['minus_report_line_ids'])
if vals.get('tag_ids'):
vals['tag_ids'] = self._convert_tag_syntax_to_orm(vals['tag_ids'])
return super(AccountTaxRepartitionLineTemplate, self).create(vals)
@api.model
def _convert_tag_syntax_to_orm(self, tags_list):
""" Repartition lines give the possibility to directly give
a list of ids to create for tags instead of a list of ORM commands.
This function checks that tags_list uses this syntactic sugar and returns
an ORM-compliant version of it if it does.
"""
if tags_list and all(isinstance(elem, int) for elem in tags_list):
return [(6, False, tags_list)]
return tags_list
@api.constrains('invoice_tax_id', 'refund_tax_id')
def validate_tax_template_link(self):
for record in self:
if record.invoice_tax_id and record.refund_tax_id:
raise ValidationError(_("Tax repartition line templates should apply to either invoices or refunds, not both at the same time. invoice_tax_id and refund_tax_id should not be set together."))
@api.constrains('plus_report_line_ids', 'minus_report_line_ids')
def validate_tags(self):
all_tax_rep_lines = self.mapped('plus_report_line_ids') + self.mapped('minus_report_line_ids')
lines_without_tag = all_tax_rep_lines.filtered(lambda x: not x.tag_name)
if lines_without_tag:
raise ValidationError(_("The following tax report lines are used in some tax repartition template though they don't generate any tag: %s . This probably means you forgot to set a tag_name on these lines.") % str(lines_without_tag.mapped('name')))
def get_repartition_line_create_vals(self, company):
rslt = [(5, 0, 0)]
for record in self:
tags_to_add = self.env['account.account.tag']
tags_to_add += record.plus_report_line_ids.mapped('tag_ids').filtered(lambda x: not x.tax_negate)
tags_to_add += record.minus_report_line_ids.mapped('tag_ids').filtered(lambda x: x.tax_negate)
tags_to_add += record.tag_ids
rslt.append((0, 0, {
'factor_percent': record.factor_percent,
'repartition_type': record.repartition_type,
'tag_ids': [(6, 0, tags_to_add.ids)],
'company_id': company.id,
}))
return rslt
# Fiscal Position Templates
class AccountFiscalPositionTemplate(models.Model):
+2
View File
@@ -79,4 +79,6 @@ class ProductProduct(models.Model):
'tax_ids': line.get('tax_ids', False),
'tax_line_id': line.get('tax_line_id', False),
'analytic_tag_ids': line.get('analytic_tag_ids', False),
'tax_repartition_line_id': line.get('tax_repartition_line_id'),
'tag_ids': line.get('tag_ids'),
}
@@ -689,10 +689,12 @@ class AccountReconciliation(models.AbstractModel):
'company_id': st_line.company_id.id,
}
if st_line.partner_id:
if amount > 0:
if st_line.partner_id.supplier and not st_line.partner_id.customer:
data['open_balance_account_id'] = st_line.partner_id.property_account_payable_id.id
elif not st_line.partner_id.supplier and st_line.partner_id.customer:
data['open_balance_account_id'] = st_line.partner_id.property_account_receivable_id.id
else:
data['open_balance_account_id'] = st_line.partner_id.property_account_payable_id.id
data['open_balance_account_id'] = amount > 0 and st_line.partner_id.property_account_receivable_id.id or st_line.partner_id.property_account_payable_id.id
return data
+2 -2
View File
@@ -14,8 +14,8 @@ class Users(models.Model):
super(Users, self)._check_one_user_type()
users_with_both_groups = self.filtered(lambda user:
user.user_has_groups('account.group_show_line_subtotals_tax_included') and
user.user_has_groups('account.group_show_line_subtotals_tax_excluded')
user.has_group('account.group_show_line_subtotals_tax_included') and
user.has_group('account.group_show_line_subtotals_tax_excluded')
)
if users_with_both_groups:
names = ", ".join(users_with_both_groups.mapped('name'))
@@ -64,6 +64,17 @@
<field name="category_id" ref="base.module_category_hidden"/>
</record>
<record id="account_analytic_line_rule_billing_user" model="ir.rule">
<field name="name">account.analytic.line.billing.user</field>
<field name="model_id" ref="analytic.model_account_analytic_line"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('account.group_account_invoice'))]"/>
<field name="perm_create" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_unlink" eval="1"/>
<field name="perm_read" eval="0"/>
</record>
</data>
@@ -124,6 +135,13 @@
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
<record id="tax_report_comp_rule" model="ir.rule">
<field name="name">Tax report multi-company</field>
<field name="model_id" ref="model_account_tax_report_line"/>
<field name="global" eval="True"/>
<field name="domain_force">[('country_id','=',user.company_id.country_id.id)]</field>
</record>
<record id="invoice_comp_rule" model="ir.rule">
<field name="name">Invoice multi-company</field>
<field name="model_id" ref="model_account_invoice"/>
@@ -86,3 +86,9 @@ access_account_incoterms_all,account.incoterms all,model_account_incoterms,,1,0,
access_account_incoterms_manager,account.incoterms manager,model_account_incoterms,account.group_account_manager,1,1,1,1
access_account_journal_group_all,account.journal.group all,model_account_journal_group,,1,0,0,0
access_account_journal_group_manager,account.journal.group manager,model_account_journal_group,account.group_account_manager,1,1,1,1
access_account_tax_repartition_line_user,account.tax repartition.line.user,model_account_tax_repartition_line,base.group_user,1,0,0,0
access_account_tax_repartition_line_invoice,account.tax repartition.line.invoice,model_account_tax_repartition_line,account.group_account_invoice,1,0,0,0
access_account_tax_repartition_line_manager,account.tax repartition.line.manager,model_account_tax_repartition_line,account.group_account_manager,1,1,1,1
access_account_tax_repartition_line_template_manager,account.tax repartition.line.template.manager,model_account_tax_repartition_line_template,account.group_account_manager,1,1,1,1
access_account_tax_report_line_invoice,account.tax.report.line.invoice,model_account_tax_report_line,account.group_account_invoice,1,0,0,0
access_account_tax_report_line_ac_user,account.tax.report.line.ac.user,model_account_tax_report_line,account.group_account_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
86 access_account_incoterms_manager account.incoterms manager model_account_incoterms account.group_account_manager 1 1 1 1
87 access_account_journal_group_all account.journal.group all model_account_journal_group 1 0 0 0
88 access_account_journal_group_manager account.journal.group manager model_account_journal_group account.group_account_manager 1 1 1 1
89 access_account_tax_repartition_line_user account.tax repartition.line.user model_account_tax_repartition_line base.group_user 1 0 0 0
90 access_account_tax_repartition_line_invoice account.tax repartition.line.invoice model_account_tax_repartition_line account.group_account_invoice 1 0 0 0
91 access_account_tax_repartition_line_manager account.tax repartition.line.manager model_account_tax_repartition_line account.group_account_manager 1 1 1 1
92 access_account_tax_repartition_line_template_manager account.tax repartition.line.template.manager model_account_tax_repartition_line_template account.group_account_manager 1 1 1 1
93 access_account_tax_report_line_invoice account.tax.report.line.invoice model_account_tax_report_line account.group_account_invoice 1 0 0 0
94 access_account_tax_report_line_ac_user account.tax.report.line.ac.user model_account_tax_report_line account.group_account_manager 1 1 1 1
@@ -0,0 +1,69 @@
odoo.define('account.activity', function (require) {
"use strict";
var AbstractField = require('web.AbstractField');
var core = require('web.core');
var field_registry = require('web.field_registry');
var QWeb = core.qweb;
var _t = core._t;
var VatActivity = AbstractField.extend({
className: 'o_journal_activity_kanban',
events: {
'click .see_all_activities': '_onOpenAll',
'click .see_activity': '_onOpenActivity',
},
init: function () {
this.MAX_ACTIVITY_DISPLAY = 5;
this._super.apply(this, arguments);
},
//------------------------------------------------------------
// Private
//------------------------------------------------------------
_render: function () {
var self = this;
var info = JSON.parse(this.value);
if (!info) {
this.$el.html('');
return;
}
info.more_activities = false;
if (info.activities.length > this.MAX_ACTIVITY_DISPLAY) {
info.more_activities = true;
info.activities = info.activities.slice(0, this.MAX_ACTIVITY_DISPLAY);
}
this.$el.html(QWeb.render('accountJournalDashboardActivity', info));
},
_onOpenActivity: function(e) {
e.preventDefault();
var self = this;
self.do_action({
type: 'ir.actions.act_window',
name: _t('Journal Entry'),
target: 'current',
res_id: $(e.target).data('resId'),
res_model: 'account.move',
views: [[false, 'form']],
});
},
_onOpenAll: function(e) {
e.preventDefault();
var self = this;
self.do_action({
type: 'ir.actions.act_window',
name: _t('Journal Entries'),
res_model: 'account.move',
views: [[false, 'kanban'], [false, 'form']],
search_view_id: [false],
domain: [['journal_id', '=', self.res_id], ['activity_ids', '!=', false]],
});
}
})
field_registry.add('kanban_vat_activity', VatActivity);
return VatActivity;
});
@@ -837,11 +837,17 @@ var StatementModel = BasicModel.extend({
return this._rpc({
model: 'res.partner',
method: 'read',
args: [partner_id, ["property_account_receivable_id", "property_account_payable_id"]],
args: [partner_id, ["property_account_receivable_id", "property_account_payable_id", "customer", "supplier"]],
}).then(function (result) {
if (result.length > 0) {
var line = self.getLine(handle);
self.lines[handle].st_line.open_balance_account_id = line.balance.amount < 0 ? result[0]['property_account_payable_id'][0] : result[0]['property_account_receivable_id'][0];
if (result[0]['supplier'] && !result[0]['customer']) {
self.lines[handle].st_line.open_balance_account_id = result[0]['property_account_payable_id'][0];
} else if (!result[0]['supplier'] && result[0]['customer']) {
self.lines[handle].st_line.open_balance_account_id = result[0]['property_account_receivable_id'][0];
} else {
self.lines[handle].st_line.open_balance_account_id = line.balance.amount < 0 ? result[0]['property_account_payable_id'][0] : result[0]['property_account_receivable_id'][0];
}
}
});
},
@@ -277,6 +277,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
'field_changed': '_onFieldChanged',
}),
_avoidFieldUpdate: {},
MV_LINE_DEBOUNCE: 200,
/**
* create partner_id field in editable mode
@@ -289,6 +290,11 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
this.model = model;
this._initialState = state;
if (this.MV_LINE_DEBOUNCE) {
this._onSelectMoveLine = _.debounce(this._onSelectMoveLine, this.MV_LINE_DEBOUNCE, true);
} else {
this._onSelectMoveLine = this._onSelectMoveLine;
}
},
/**
* @override
@@ -0,0 +1,8 @@
.o_journal_activity_kanban {
display: block;
.align_activity_center {
width: 100%;
align-items: center;
margin-bottom: 5px;
}
}
@@ -41,6 +41,15 @@
@include o-position-absolute($bottom: 25%, $right: 0);
z-index: 1;
}
.o_kanban_group {
&:not(.o_column_folded) {
width: 450px + 2*$o-kanban-group-padding;
@include media-breakpoint-down(sm) {
width: 100%;
}
}
}
}
// Style for the widget "dashboard_graph"
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="accountJournalDashboardActivity">
<t t-foreach="activities" t-as="activity">
<div class="row">
<div class="col-6 o_mail_activity">
<a href="#" t-att-class="(activity.status == 'late' ? 'o_activity_color_overdue ' : ' ') + (activity.activity_category == 'tax_report' ? 'o_open_vat_report' : 'see_activity')" t-att-data-res-id="activity.res_id" t-att-data-id="activity.id" t-att-data-model="activity.res_model">
<t t-esc="activity.name"/>
</a>
</div>
<div class="col-6 text-right">
<span><t t-esc="activity.date"/></span>
</div>
</div>
</t>
<a t-if="more_activities" class="pull-right see_all_activities" href="#">See all activities</a>
</t>
</templates>
@@ -585,6 +585,7 @@ odoo.define('account.reconciliation_tests', function (require) {
"use strict";
var ReconciliationClientAction = require('account.ReconciliationClientAction');
var ReconciliationRenderer = require('account.ReconciliationRenderer');
var demoData = require('account.reconciliation_tests.data');
var testUtils = require('web.test_utils');
@@ -592,7 +593,13 @@ var testUtils = require('web.test_utils');
QUnit.module('account', {
beforeEach: function () {
this.params = demoData.getParams();
}
testUtils.patch(ReconciliationRenderer.LineRenderer, {
MV_LINE_DEBOUNCE: 0,
});
},
afterEach: function () {
testUtils.unpatch(ReconciliationRenderer.LineRenderer);
},
}, function () {
QUnit.module('Reconciliation');
+1
View File
@@ -16,6 +16,7 @@ from . import test_product_id_change
from . import test_reconciliation
from . import test_search
from . import test_tax
from . import test_invoice_taxes
from . import test_account_move_taxes_edition
from . import test_templates_consistency
from . import test_account_fiscal_year
@@ -166,7 +166,7 @@ class TestAccountCustomerInvoice(AccountTestUsers):
invoice_line_ids=invoice_line_data
))
self.assertEquals(invoice.amount_untaxed, sum([x.base for x in invoice.tax_line_ids]))
self.assertAlmostEquals(invoice.amount_untaxed, sum([x.base for x in invoice.tax_line_ids]))
def test_customer_invoice_tax_refund(self):
company = self.env.company_id
@@ -193,8 +193,32 @@ class TestAccountCustomerInvoice(AccountTestUsers):
'amount': 15.0,
'amount_type': 'percent',
'type_tax_use': 'sale',
'account_id': tax_account.id,
'refund_account_id': tax_refund_account.id
'invoice_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': tax_account.id,
}),
],
'refund_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': tax_refund_account.id,
}),
],
})
invoice_line_data = [
@@ -17,6 +17,7 @@ class TestTaxBlockDate(AccountingTestCase):
def setUp(self):
super(TestTaxBlockDate, self).setUp()
self.user_id = self.env.user
company_id = self.user_id.company_id.id
last_day_month = datetime.now()
last_day_month = last_day_month.replace(day=monthrange(last_day_month.year, last_day_month.month)[1])
@@ -28,10 +29,10 @@ class TestTaxBlockDate(AccountingTestCase):
middle_day_month = middle_day_month.replace(day=15)
self.middle_day_month_str = middle_day_month.strftime(DEFAULT_SERVER_DATE_FORMAT)
self.sale_journal_id = self.env['account.journal'].search([('type', '=', 'sale')], limit=1)[0]
self.account_id = self.env['account.account'].search([('internal_type', '=', 'receivable')], limit=1)[0]
self.other_account_id = self.env['account.account'].search([('internal_type', '!=', 'receivable')], limit=1)[0]
self.tax_id = self.env['account.tax'].search([], limit=1)[0]
self.sale_journal_id = self.env['account.journal'].search([('type', '=', 'sale'), ('company_id', '=', company_id)], limit=1)[0]
self.account_id = self.env['account.account'].search([('internal_type', '=', 'receivable'), ('company_id', '=', company_id)], limit=1)[0]
self.other_account_id = self.env['account.account'].search([('internal_type', '!=', 'receivable'), ('company_id', '=', company_id)], limit=1)[0]
self.tax_id = self.env['account.tax'].search([('company_id', '=', company_id)], limit=1)[0]
self.move = {
'name': '/',
+233
View File
@@ -0,0 +1,233 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
from odoo.tests.common import Form
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestInvoiceTaxes(AccountingTestCase):
def setUp(self):
super(TestInvoiceTaxes, self).setUp()
self.percent_tax_1 = self.env['account.tax'].create({
'name': '21%',
'amount_type': 'percent',
'amount': 21,
'sequence': 10,
})
self.percent_tax_1_incl = self.env['account.tax'].create({
'name': '21% incl',
'amount_type': 'percent',
'amount': 21,
'price_include': True,
'include_base_amount': True,
'sequence': 20,
})
self.percent_tax_2 = self.env['account.tax'].create({
'name': '12%',
'amount_type': 'percent',
'amount': 12,
'sequence': 30,
})
self.group_tax = self.env['account.tax'].create({
'name': 'group 12% + 21%',
'amount_type': 'group',
'amount': 21,
'children_tax_ids': [
(4, self.percent_tax_1_incl.id),
(4, self.percent_tax_2.id)
],
'sequence': 40,
})
def _create_invoice(self, taxes_per_line, inv_type='out_invoice'):
''' Create an invoice on the fly.
:param taxes_per_line: A list of tuple (price_unit, account.tax recordset)
'''
self_ctx = self.env['account.invoice'].with_context(type=inv_type)
journal_id = self_ctx._default_journal().id
self_ctx = self_ctx.with_context(journal_id=journal_id)
with Form(self_ctx, view=(inv_type in ('out_invoice', 'out_refund') and 'account.invoice_form' or 'invoice_supplier_form')) as invoice_form:
invoice_form.partner_id = self.env.ref('base.partner_demo')
for amount, taxes in taxes_per_line:
with invoice_form.invoice_line_ids.new() as invoice_line_form:
invoice_line_form.name = 'xxxx'
invoice_line_form.quantity = 1
invoice_line_form.price_unit = amount
invoice_line_form.invoice_line_tax_ids.clear()
for tax in taxes:
invoice_line_form.invoice_line_tax_ids.add(tax)
return invoice_form.save()
def test_one_tax_per_line(self):
''' Test:
price_unit | Taxes
------------------
100 | 21%
121 | 21% incl
100 | 12%
Expected:
Tax | Taxes | Base | Amount
--------------------------------------------
21% | / | 100 | 21
21% incl | / | 100 | 21
12% | / | 100 | 12
'''
invoice = self._create_invoice([
(100, self.percent_tax_1),
(121, self.percent_tax_1_incl),
(100, self.percent_tax_2),
])
invoice.action_invoice_open()
self.assertRecordValues(invoice.tax_line_ids, [
{'name': self.percent_tax_1.name, 'base': 100, 'amount': 21, 'tax_ids': []},
{'name': self.percent_tax_1_incl.name, 'base': 100, 'amount': 21, 'tax_ids': []},
{'name': self.percent_tax_2.name, 'base': 100, 'amount': 12, 'tax_ids': []},
])
def test_affecting_base_amount(self):
''' Test:
price_unit | Taxes
------------------
121 | 21% incl, 12%
100 | 12%
Expected:
Tax | Taxes | Base | Amount
--------------------------------------------
21% incl | / | 100 | 21
12% | 21% incl | 121 | 14.52
12% | / | 100 | 12
'''
invoice = self._create_invoice([
(121, self.percent_tax_1_incl + self.percent_tax_2),
(100, self.percent_tax_2),
])
invoice.action_invoice_open()
self.assertRecordValues(invoice.tax_line_ids.sorted(lambda x: x.amount), [
{'name': self.percent_tax_2.name, 'base': 100, 'amount': 12, 'tax_ids': []},
{'name': self.percent_tax_2.name, 'base': 121, 'amount': 14.52, 'tax_ids': [self.percent_tax_1_incl.id]},
{'name': self.percent_tax_1_incl.name, 'base': 100, 'amount': 21, 'tax_ids': []},
])
def test_group_of_taxes(self):
''' Test:
price_unit | Taxes
------------------
121 | 21% incl + 12%
100 | 12%
Expected:
Tax | Taxes | Base | Amount
--------------------------------------------
21% incl | / | 100 | 21
12% | 21% incl | 121 | 14.52
12% | / | 100 | 12
'''
invoice = self._create_invoice([
(121, self.group_tax),
(100, self.percent_tax_2),
])
invoice.action_invoice_open()
self.assertRecordValues(invoice.tax_line_ids.sorted(lambda x: x.amount), [
{'name': self.percent_tax_2.name, 'base': 100, 'amount': 12, 'tax_ids': []},
{'name': self.percent_tax_2.name, 'base': 121, 'amount': 14.52, 'tax_ids': [self.percent_tax_1_incl.id]},
{'name': self.percent_tax_1_incl.name, 'base': 100, 'amount': 21, 'tax_ids': []},
])
def _create_tax_tag(self, tag_name):
return self.env['account.account.tag'].create({
'name': tag_name,
'applicability': 'taxes',
})
def test_tax_repartition(self):
inv_base_tag = self._create_tax_tag('invoice_base')
inv_tax_tag_10 = self._create_tax_tag('invoice_tax_10')
inv_tax_tag_90 = self._create_tax_tag('invoice_tax_90')
ref_base_tag = self._create_tax_tag('refund_base')
ref_tax_tag = self._create_tax_tag('refund_tax')
user_type = self.env.ref('account.data_account_type_current_assets')
account_1 = self.env['account.account'].create({'name': 'test1', 'code': 'test1', 'user_type_id': user_type.id})
account_2 = self.env['account.account'].create({'name': 'test2', 'code': 'test2', 'user_type_id': user_type.id})
tax = self.env['account.tax'].create({
'name': "Tax with account",
'amount_type': 'fixed',
'type_tax_use': 'sale',
'amount': 42,
'invoice_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'tag_ids': [(4, inv_base_tag.id, 0)],
}),
(0,0, {
'factor_percent': 10,
'repartition_type': 'tax',
'account_id': account_1.id,
'tag_ids': [(4, inv_tax_tag_10.id, 0)],
}),
(0,0, {
'factor_percent': 90,
'repartition_type': 'tax',
'account_id': account_2.id,
'tag_ids': [(4, inv_tax_tag_90.id, 0)],
}),
],
'refund_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'tag_ids': [(4, ref_base_tag.id, 0)],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': account_1.id,
'tag_ids': [(4, ref_tax_tag.id, 0)],
}),
],
})
# Test invoice repartition
invoice = self._create_invoice([(100, tax)], inv_type='out_invoice')
invoice.action_invoice_open()
invoice_move = invoice.move_id
self.assertEqual(len(invoice_move.line_ids), 4, "There should be 4 account move lines created for the invoice: payable, base and 2 tax lines")
inv_base_line = invoice_move.line_ids.filtered(lambda x: not x.tax_repartition_line_id and x.account_id.user_type_id.type != 'receivable')
self.assertEqual(len(inv_base_line), 1, "There should be only one base line generated")
self.assertEqual(abs(inv_base_line.balance), 100, "Base amount should be 100")
self.assertEqual(inv_base_line.tag_ids, inv_base_tag, "Base line should have received base tag")
inv_tax_lines = invoice_move.line_ids.filtered(lambda x: x.tax_repartition_line_id.repartition_type == 'tax')
self.assertEqual(len(inv_tax_lines), 2, "There should be two tax lines, one for each repartition line.")
self.assertEqual(abs(inv_tax_lines.filtered(lambda x: x.account_id == account_1).balance), 4.2, "Tax line on account 1 should amount to 4.2 (10% of 42)")
self.assertEqual(inv_tax_lines.filtered(lambda x: x.account_id == account_1).tag_ids, inv_tax_tag_10, "Tax line on account 1 should have 10% tag")
self.assertEqual(abs(inv_tax_lines.filtered(lambda x: x.account_id == account_2).balance), 37.8, "Tax line on account 2 should amount to 37.8 (90% of 42)")
self.assertEqual(inv_tax_lines.filtered(lambda x: x.account_id == account_2).tag_ids, inv_tax_tag_90, "Tax line on account 2 should have 90% tag")
# Test refund repartition
refund = self._create_invoice([(100, tax)], inv_type='out_refund')
refund.action_invoice_open()
refund_move = refund.move_id
self.assertEqual(len(refund_move.line_ids), 3, "There should be 4 account move lines created for the refund: payable, base and tax line")
ref_base_line = refund_move.line_ids.filtered(lambda x: not x.tax_repartition_line_id and x.account_id.user_type_id.type != 'receivable')
self.assertEqual(len(ref_base_line), 1, "There should be only one base line generated")
self.assertEqual(abs(ref_base_line.balance), 100, "Base amount should be 100")
self.assertEqual(ref_base_line.tag_ids, ref_base_tag, "Base line should have received base tag")
ref_tax_line = refund_move.line_ids.filtered(lambda x: x.tax_repartition_line_id.repartition_type == 'tax')
self.assertEqual(len(ref_tax_line), 1, "There should be only one tax line")
self.assertEqual(ref_tax_line.account_id, account_1, "Tax line should have been made on account 1")
self.assertEqual(abs(ref_tax_line.balance), 42, "Tax line should have been made on account 1")
self.assertEqual(ref_tax_line.tag_ids, ref_tax_tag, "Tax line should have the right tag")
+42 -21
View File
@@ -98,10 +98,33 @@ class TestReconciliation(AccountingTestCase):
'type_tax_use': 'purchase',
'company_id': company.id,
'amount': 20,
'account_id': self.tax_waiting_account.id,
'tax_exigibility': 'on_payment',
'cash_basis_account_id': self.tax_final_account.id,
'cash_basis_transition_account_id': self.tax_waiting_account.id,
'cash_basis_base_account_id': self.tax_base_amount_account.id,
'invoice_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': self.tax_final_account.id,
}),
],
'refund_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': self.tax_final_account.id,
}),
],
})
def create_invoice(self, type='out_invoice', invoice_amount=50, currency_id=None):
@@ -227,7 +250,7 @@ class TestReconciliationExec(TestReconciliation):
{'debit': 10.74, 'credit': 0.0, 'account_id': self.diff_expense_account.id},
{'debit': 0.0, 'credit': 10.74, 'account_id': self.account_rcv.id},
])
self.assertRecordValues(supplier_move_lines, [
{'debit': 0.0, 'credit': 27.47, 'amount_currency': -42, 'currency_id': self.currency_usd_id},
{'debit': 27.47, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_swiss_id},
@@ -249,7 +272,7 @@ class TestReconciliationExec(TestReconciliation):
{'debit': 0.0, 'credit': 7.30, 'account_id': self.diff_income_account.id},
{'debit': 7.30, 'credit': 0.0, 'account_id': self.account_rcv.id},
])
self.assertRecordValues(supplier_move_lines, [
{'debit': 0.0, 'credit': 40.0, 'amount_currency': -50, 'currency_id': self.currency_usd_id},
{'debit': 40.0, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id},
@@ -643,12 +666,12 @@ class TestReconciliationExec(TestReconciliation):
'currency_id': self.currency_usd_id,
'company_id': self.env.ref('base.main_company').id})
self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '08' + '-01',
self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '08' + '-01',
'rate': 0.75,
'currency_id': self.currency_usd_id,
'company_id': self.env.ref('base.main_company').id})
self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '09' + '-01',
self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '09' + '-01',
'rate': 0.80,
'currency_id': self.currency_usd_id,
'company_id': self.env.ref('base.main_company').id})
@@ -1280,7 +1303,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': self.tax_waiting_account.id,
'debit': 16.67,
'move_id': purchase_move.id,
'tax_line_id': self.tax_cash_basis.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
})
purchase_move.post()
@@ -1398,7 +1421,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': tax_waiting_account10.id,
'debit': 5,
'move_id': purchase_move.id,
'tax_line_id': tax_cash_basis10percent.id,
'tax_repartition_line_id': tax_cash_basis10percent.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
})
AccountMoveLine.create({
'name': 'expenseTaxed 20%',
@@ -1412,7 +1435,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': self.tax_waiting_account.id,
'debit': 16.67,
'move_id': purchase_move.id,
'tax_line_id': self.tax_cash_basis.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
})
purchase_move.post()
@@ -1520,18 +1543,18 @@ class TestReconciliationExec(TestReconciliation):
expected['tax_10']
)
index += 1
def test_reconciliation_to_check(self):
partner = self.env['res.partner'].create({'name': 'UncertainPartner'})
currency = self.env.company_id.currency_id
invoice = self.create_invoice_partner(currency_id=currency.id, partner_id=partner.id)
journal = self.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'THE', 'update_posted':True})
statement = self.make_payment(invoice, journal, 50)
st_line = statement.line_ids
previous_move_lines = st_line.journal_entry_ids.ids
previous_name = st_line.move_name
with self.assertRaises(UserError): #you need edition mode to be able to change it
st_line.with_context(edition_mode=False).process_reconciliation(
counterpart_aml_dicts=[],
@@ -1542,7 +1565,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': self.diff_income_account.id
}],
)
st_line.with_context(edition_mode=True).process_reconciliation(
counterpart_aml_dicts=[],
new_aml_dicts = [{
@@ -1620,9 +1643,9 @@ class TestReconciliationExec(TestReconciliation):
'account_id': self.tax_waiting_account.id,
'debit': 17094.66,
'move_id': purchase_move.id,
'tax_line_id': self.tax_cash_basis.id,
'currency_id': self.currency_usd_id,
'amount_currency': 848.16,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
})
purchase_payable_line0 = aml_obj.create({
'name': 'Payable',
@@ -1697,8 +1720,7 @@ class TestReconciliationExec(TestReconciliation):
self.assertEqual(len(cash_basis_aml_ids), 4)
# check amounts
cash_basis_move1 = cash_basis_moves.filtered(
lambda m: m.amount == 123936.31)
cash_basis_move1 = cash_basis_moves.filtered(lambda m: m.currency_id.is_zero(sum(line.credit for line in m.line_ids) - 123936.31))
self.assertTrue(cash_basis_move1.exists())
@@ -1793,7 +1815,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': self.tax_waiting_account.id,
'debit': 17094.66,
'move_id': purchase_move.id,
'tax_line_id': self.tax_cash_basis.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
'currency_id': self.currency_usd_id,
'amount_currency': 848.16,
})
@@ -1893,8 +1915,7 @@ class TestReconciliationExec(TestReconciliation):
self.assertEqual(len(cash_basis_aml_ids), 4)
# check amounts
cash_basis_move1 = cash_basis_moves.filtered(
lambda m: m.amount == 123936.31)
cash_basis_move1 = cash_basis_moves.filtered(lambda m: m.currency_id.is_zero(sum(line.credit for line in m.line_ids) - 123936.31))
self.assertTrue(cash_basis_move1.exists())
@@ -1953,7 +1974,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': tax_waiting_account10.id,
'debit': 5,
'move_id': purchase_move.id,
'tax_line_id': tax_cash_basis10percent.id,
'tax_repartition_line_id': tax_cash_basis10percent.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
})
AccountMoveLine.create({
'name': 'expenseTaxed 20%',
@@ -1967,7 +1988,7 @@ class TestReconciliationExec(TestReconciliation):
'account_id': self.tax_waiting_account.id,
'debit': 20,
'move_id': purchase_move.id,
'tax_line_id': self.tax_cash_basis.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
})
purchase_move.post()
+284 -47
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.account_test_users import AccountTestUsers
import time
from odoo.tests import tagged
@@ -27,6 +27,12 @@ class TestTax(AccountTestUsers):
'amount': 10,
'sequence': 3,
})
self.percent_tax_bis = self.tax_model.create({
'name': "Percent tax bis",
'amount_type': 'percent',
'amount': 10,
'sequence': 4,
})
self.division_tax = self.tax_model.create({
'name': "Division tax",
'amount_type': 'division',
@@ -73,56 +79,149 @@ class TestTax(AccountTestUsers):
self.tax_with_account = self.tax_model.create({
'name': "Tax with account",
'amount_type': 'fixed',
'account_id': some_account.id,
'refund_account_id': some_account.id,
'amount': 0,
'sequence': 8,
'invoice_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': some_account.id,
}),
],
'refund_repartition_line_ids': [
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': some_account.id,
}),
],
})
self.bank_journal = self.env['account.journal'].search([('type', '=', 'bank'), ('company_id', '=', self.account_manager.company_id.id)])[0]
self.bank_account = self.bank_journal.default_debit_account_id
self.expense_account = self.env['account.account'].search([('user_type_id.type', '=', 'payable')], limit=1) #Should be done by onchange later
def _check_compute_all_results(self, total_included, total_excluded, taxes, res):
self.assertAlmostEqual(res['total_included'], total_included)
self.assertAlmostEqual(res['total_excluded'], total_excluded)
for i in range(0, len(taxes)):
self.assertAlmostEqual(res['taxes'][i]['base'], taxes[i][0])
self.assertAlmostEqual(res['taxes'][i]['amount'], taxes[i][1])
def test_tax_group_of_group_tax(self):
self.fixed_tax.include_base_amount = True
self.group_tax.include_base_amount = True
self.group_of_group_tax.include_base_amount = True
res = self.group_of_group_tax.compute_all(200.0)
self.assertEquals(res['total_excluded'], 200.0)
# After calculation of first group
# base = 210
# total_included = 231
# Base of the first grouped is passed
# Base after the second group (220) is dropped.
# Base of the group of groups is passed out,
# so we obtain base as after first group
self.assertEquals(res['base'], 210.0)
self.assertEquals(res['total_included'], 263.0)
self._check_compute_all_results(
263, # 'total_included'
200, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(200.0, 10.0), # | 1 | 10 | | t
(210.0, 21.0), # | 3 | 10% | |
(210.0, 10.0), # | 1 | 10 | | t
(220.0, 22.0), # | 3 | 10% | |
# ---------------------------------------------------
],
res
)
def test_tax_group(self):
res = self.group_tax.compute_all(200.0)
self.assertEquals(res['total_excluded'], 200.0)
self.assertEquals(res['total_included'], 230.0)
self.assertEquals(len(res['taxes']), 2)
self.assertEquals(res['taxes'][0]['amount'], 10.0)
self.assertEquals(res['taxes'][1]['amount'], 20.0)
self._check_compute_all_results(
230, # 'total_included'
200, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(200.0, 10.0), # | 1 | 10 | |
(200.0, 20.0), # | 3 | 10% | |
# ---------------------------------------------------
],
res
)
def test_tax_percent_division(self):
self.division_tax.price_include = True
self.division_tax.include_base_amount = True
res_division = self.division_tax.compute_all(200.0)
self._check_compute_all_results(
200, # 'total_included'
180, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(180.0, 20.0), # | 4 | 10/ | t | t
# ---------------------------------------------------
],
res_division
)
self.percent_tax.price_include = False
self.percent_tax.include_base_amount = False
res_division = self.division_tax.compute_all(200.0)
res_percent = self.percent_tax.compute_all(200.0)
self.assertEquals(res_division['taxes'][0]['amount'], 20.0)
self.assertEquals(res_percent['taxes'][0]['amount'], 20.0)
res_percent = self.percent_tax.compute_all(100.0)
self._check_compute_all_results(
110, # 'total_included'
100, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(100.0, 10.0), # | 3 | 10% | |
# ---------------------------------------------------
],
res_percent
)
self.division_tax.price_include = False
self.division_tax.include_base_amount = False
res_division = self.division_tax.compute_all(180.0)
self._check_compute_all_results(
200, # 'total_included'
180, # 'total_excluded'
[
# base, amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(180.0, 20.0), # | 4 | 10/ | |
# ---------------------------------------------------
],
res_division
)
self.percent_tax.price_include = True
self.percent_tax.include_base_amount = True
res_division = self.division_tax.compute_all(200.0)
res_percent = self.percent_tax.compute_all(200.0)
self.assertEquals(res_division['taxes'][0]['amount'], 22.22)
self.assertEquals(res_percent['taxes'][0]['amount'], 18.18)
res_percent = self.percent_tax.compute_all(110.0)
self._check_compute_all_results(
110, # 'total_included'
100, # 'total_excluded'
[
# base, amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(100.0, 10.0), # | 3 | 10% | t | t
# ---------------------------------------------------
],
res_percent
)
self.percent_tax_bis.price_include = True
self.percent_tax_bis.include_base_amount = True
self.percent_tax_bis.amount = 21
res_percent = self.percent_tax_bis.compute_all(7.0)
self._check_compute_all_results(
7.0, # 'total_included'
5.79, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(5.79, 1.21), # | 3 | 21% | t | t
# ---------------------------------------------------
],
res_percent
)
def test_tax_sequence_normalized_set(self):
self.division_tax.sequence = 1
@@ -130,28 +229,166 @@ class TestTax(AccountTestUsers):
self.percent_tax.sequence = 3
taxes_set = (self.group_tax | self.division_tax)
res = taxes_set.compute_all(200.0)
self.assertEquals(res['taxes'][0]['amount'], 22.22)
self.assertEquals(res['taxes'][1]['amount'], 10.0)
self.assertEquals(res['taxes'][2]['amount'], 20.0)
self._check_compute_all_results(
252.22, # 'total_included'
200, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(200.0, 22.22), # | 1 | 10/ | |
(200.0, 10.0), # | 2 | 10 | |
(200.0, 20.0), # | 3 | 10% | |
# ---------------------------------------------------
],
res
)
def test_tax_include_base_amount(self):
def test_fixed_tax_include_base_amount(self):
self.fixed_tax.include_base_amount = True
res = self.group_tax.compute_all(200.0)
self.assertEquals(res['total_included'], 231.0)
self._check_compute_all_results(
231, # 'total_included'
200, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(200.0, 10.0), # | 1 | 10 | | t
(210.0, 21.0), # | 3 | 10% | |
# ---------------------------------------------------
],
res
)
def test_tax_currency(self):
self.division_tax.amount = 15.0
res = self.division_tax.compute_all(200.0, currency=self.env.ref('base.VEF'))
self.assertAlmostEqual(res['total_included'], 235.2941)
self.fixed_tax.price_include = True
self.fixed_tax.include_base_amount = False
res = self.fixed_tax.compute_all(100.0, quantity=2.0)
self._check_compute_all_results(
200, # 'total_included'
180, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(180.0, 20.0), # | 1 | 20 | | t
# ---------------------------------------------------
],
res
)
def test_tax_with_no_account(self):
self.tax_with_no_account.amount = 10.0
res = self.tax_with_no_account.compute_all(200.0)
self.assertEquals(res['total_included'], 210)
self.assertEquals(res['total_void'], 210)
def test_percent_tax_include_base_amount(self):
self.percent_tax.price_include = True
self.percent_tax.amount = 21.0
res = self.percent_tax.compute_all(7.0)
self._check_compute_all_results(
7.0, # 'total_included'
5.79, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(5.79, 1.21), # | 3 | 21% | t |
# ---------------------------------------------------
],
res
)
def test_tax_with_account(self):
self.tax_with_account.amount = 10.0
res = self.tax_with_account.compute_all(200.0)
self.assertEquals(res['total_included'], 210)
self.assertEquals(res['total_void'], 200)
self.percent_tax.price_include = True
self.percent_tax.amount = 20.0
res = self.percent_tax.compute_all(399.99)
self._check_compute_all_results(
399.99, # 'total_included'
333.33, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(333.33, 66.66), # | 3 | 20% | t |
# ---------------------------------------------------
],
res
)
def test_tax_decimals(self):
"""Test the rounding of taxes up to 6 decimals (maximum decimals places allowed for currencies)"""
self.env.user.company_id.currency_id.rounding = 0.000001
self.percent_tax.price_include = True
self.percent_tax.amount = 21.0
res = self.percent_tax.compute_all(7.0)
self._check_compute_all_results(
7.0, # 'total_included'
5.785124, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# --------------------------------------------------------
(5.785124, 1.214876), # | 3 | 21% | t |
# --------------------------------------------------------
],
res
)
self.percent_tax.price_include = True
self.percent_tax.amount = 20.0
res = self.percent_tax.compute_all(399.999999)
self._check_compute_all_results(
399.999999, # 'total_included'
333.333333, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# -----------------------------------------------------------
(333.333333, 66.666666), # | 3 | 20% | t |
# -----------------------------------------------------------
],
res
)
def test_advanced_taxes_computation_0(self):
'''Test more advanced taxes computation (see issue 34471).'''
tax_1 = self.env['account.tax'].create({
'name': 'test_advanced_taxes_computation_0_1',
'amount_type': 'percent',
'amount': 10,
'price_include': True,
'include_base_amount': True,
'sequence': 1,
})
tax_2 = self.env['account.tax'].create({
'name': 'test_advanced_taxes_computation_0_2',
'amount_type': 'percent',
'amount': 10,
'sequence': 2,
})
tax_3 = self.env['account.tax'].create({
'name': 'test_advanced_taxes_computation_0_3',
'amount_type': 'percent',
'amount': 10,
'price_include': True,
'sequence': 3,
})
tax_4 = self.env['account.tax'].create({
'name': 'test_advanced_taxes_computation_0_4',
'amount_type': 'percent',
'amount': 10,
'sequence': 4,
})
tax_5 = self.env['account.tax'].create({
'name': 'test_advanced_taxes_computation_0_5',
'amount_type': 'percent',
'amount': 10,
'price_include': True,
'sequence': 5,
})
taxes = tax_1 + tax_2 + tax_3 + tax_4 + tax_5
res = taxes.compute_all(132.0)
self._check_compute_all_results(
154, # 'total_included'
100, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(100.0, 10.0), # | 1 | 10% | t | t
(110.0, 11.0), # | 2 | 10% | |
(110.0, 11.0), # | 3 | 10% | t |
(110.0, 11.0), # | 4 | 10% | |
(110.0, 11.0), # | 5 | 10% | t |
# ---------------------------------------------------
],
res
)
@@ -41,6 +41,8 @@ class AccountingTestTemplConsistency(HttpCase):
'''
self.check_fields_consistency('account.tax.template', 'account.tax', exceptions=['chart_template_id'])
self.check_fields_consistency('account.tax', 'account.tax.template', exceptions=['company_id'])
self.check_fields_consistency('account.tax.repartition.line.template', 'account.tax.repartition.line', exceptions=['plus_report_line_ids', 'minus_report_line_ids'])
self.check_fields_consistency('account.tax.repartition.line', 'account.tax.repartition.line.template', exceptions=['tag_ids', 'country_id', 'company_id', 'sequence'])
def test_fiscal_position_fields(self):
'''Test fields consistency for ('account.fiscal.position', 'account.fiscal.position.template')
+2
View File
@@ -15,6 +15,7 @@
<link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_dashboard.scss"/>
<link rel="stylesheet" href="/account/static/src/scss/section_and_note_backend.scss"/>
<link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_activity.scss"/>
<script type="text/javascript" src="/account/static/src/js/reconciliation/reconciliation_action.js"></script>
<script type="text/javascript" src="/account/static/src/js/reconciliation/reconciliation_model.js"></script>
@@ -22,6 +23,7 @@
<script type="text/javascript" src="/account/static/src/js/reconciliation/tour_reconciliation.js"></script>
<script type="text/javascript" src="/account/static/src/js/account_payment_field.js"></script>
<script type="text/javascript" src="/account/static/src/js/mail_activity.js"></script>
<script type="text/javascript" src="/account/static/src/js/bank_statement.js"></script>
<script type="text/javascript" src="/account/static/src/js/section_and_note_fields_backend.js"></script>
+11 -3
View File
@@ -140,6 +140,7 @@
<field name="name"/>
<field name="account_id" groups="account.group_account_user"/>
<field name="base"/>
<field name="tax_ids"/>
<field name="amount_total" string="Amount"/>
<field name="currency_id" invisible="1"/>
</tree>
@@ -159,6 +160,7 @@
<field name="manual"/>
<field name="amount_total" string="Amount"/>
<field name="base"/>
<field name="tax_ids"/>
<field name="currency_id" invisible="1"/>
</group>
</form>
@@ -181,8 +183,8 @@
<field name="user_id"/>
<field name="date_due"/>
<field name="origin"/>
<field name="amount_untaxed" string="Tax Excluded" sum="Total"/>
<field name="amount_tax" sum="Total"/>
<field name="amount_untaxed_invoice_signed" string="Tax Excluded" sum="Total"/>
<field name="amount_tax_signed" string="Tax" sum="Total"/>
<field name="amount_total_signed" string="Total" sum="Total"/>
<field name="residual_signed" string="Amount Due" sum="Amount Due"/>
<field name="currency_id" invisible="1"/>
@@ -365,10 +367,11 @@
<group>
<div class="oe_inline">
<field name="tax_line_ids">
<tree editable="bottom" string="Taxes">
<tree editable="bottom" string="Taxes" create="0" delete="0">
<field name="name"/>
<!--Need invisible fields for on_change to create all necessary info -->
<field name="tax_id" invisible="1"/>
<field name="tax_ids" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="manual" invisible="1"/>
<field name="account_id" groups="account.group_account_user"/>
@@ -378,6 +381,8 @@
<field name="amount_rounding" invisible="1"/>
<field name="amount_total" invisible="1"/>
<field name="currency_id" invisible="1" force_save="1"/>
<field name="tax_repartition_line_id" invisible="1"/> <!--Needed in order for the onchange computing the taxes to keep the repartition lines-->
<field name="base" invisible="1"/>
</tree>
</field>
</div>
@@ -634,6 +639,7 @@
<field name="name"/>
<!--Need invisible fields for on_change to create all necessary info -->
<field name="tax_id" invisible="1"/>
<field name="tax_ids" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="manual" invisible="1"/>
<field name="account_id" groups="account.group_account_user"/>
@@ -643,6 +649,8 @@
<field name="amount_rounding" invisible="1"/>
<field name="amount_total"/>
<field name="currency_id" invisible="1" force_save="1"/>
<field name="tax_repartition_line_id" invisible="1"/> <!--Needed in order for the onchange computing the taxes to keep the repartition lines-->
<field name="base" invisible="1"/>
</tree>
</field>
</page>
@@ -10,6 +10,8 @@
<field name="color"/>
<field name="show_on_dashboard"/>
<field name="kanban_dashboard"/>
<field name="activity_ids"/>
<field name="activity_state"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(record.color.raw_value)}">
@@ -20,12 +22,15 @@
<div class="row">
<t t-if="(journal_type == 'bank' || journal_type == 'cash')" t-call="JournalBodyBankCash"/>
<t t-if="journal_type == 'sale' || journal_type == 'purchase'" t-call="JournalBodySalePurchase"/>
<t t-if="journal_type == 'general' || journal_type == 'situation'">
<div class="col-6 o_kanban_primary_left">
<button type="object" name="open_action" context="{'action_name': 'action_move_journal_line', 'view_no_maturity': 1}" class="btn btn-primary">
<span>Journal Entries</span>
<t t-if="journal_type == 'general'">
<div class="col-5 o_kanban_primary_left">
<button type="object" name="action_create_new" class="btn btn-primary">
<span>New Entry</span>
</button>
</div>
<div class="col-7 o_kanban_primary_right">
<field name="json_activity_data" widget="kanban_vat_activity"/>
</div>
</t>
</div>
<t t-if="journal_type == 'bank' || journal_type == 'cash' || journal_type == 'sale' || journal_type == 'purchase'" t-call="JournalBodyGraph"/>
@@ -271,7 +276,7 @@
<t t-if="dashboard.number_to_check > 0">
<div class="row">
<div class="col-7 text-left">
<a type="object" name="action_open_to_check"><t t-esc="dashboard.number_to_check"/> moves to check</a>
<a type="object" name="action_open_to_check"><t t-esc="dashboard.number_to_check"/> to check</a>
</div>
<div class="col-5 text-right">
<span><t t-esc="dashboard.to_check_balance"/></span>
@@ -324,6 +329,16 @@
<span><t t-esc="dashboard.sum_waiting"/></span>
</div>
</div>
<t t-if="dashboard.number_to_check > 0">
<div class="row">
<div class="col-7 text-left">
<a type="object" name="open_action" context="{'action_name': 'action_move_journal_line', 'search_default_to_check': True}"><t t-esc="dashboard.number_to_check"/> to check</a>
</div>
<div class="col-5 text-right">
<span><t t-esc="dashboard.to_check_balance"/></span>
</div>
</div>
</t>
</div>
<div t-if="dashboard.is_sample_data">
<span class="badge badge-warning text-uppercase o_sample_data_label">Sample data</span>
+9 -6
View File
@@ -43,6 +43,7 @@
<group string="Taxes" attrs="{'invisible': [('tax_line_id','=',False), ('tax_ids','=',[])]}">
<field name="tax_line_id" readonly="1" attrs="{'invisible': [('tax_line_id','=',False)]}"/>
<field name="tax_ids" widget="many2many_tags" readonly="1" attrs="{'invisible': [('tax_ids','=',[])]}"/>
<field name="tax_audit"/>
</group>
<group string="Matching" attrs="{'invisible':[('full_reconcile_id','=',False), ('matched_debit_ids', '=', []),('matched_credit_ids', '=', [])]}">
<label for="full_reconcile_id"/>
@@ -173,6 +174,7 @@
<field name="full_reconcile_id" position="after">
<field name="tax_line_id"/>
<field name="tax_base_amount" sum="Total Base Amount"/>
<field name="tax_audit"/>
</field>
<field name="date_maturity" position="replace"/>
</field>
@@ -201,7 +203,7 @@
</record>
<record id="view_account_move_line_filter" model="ir.ui.view">
<field name="name">Journal Items</field>
<field name="name">account.move.line.search</field>
<field name="model">account.move.line</field>
<field name="arch" type="xml">
<search string="Search Journal Items">
@@ -336,7 +338,7 @@
<group>
<field name="journal_id" options="{'no_open': True, 'no_create': True}"/>
<field name="company_id" required="1" groups="base.group_multi_company"/>
<field name="amount" invisible="1"/>
<field name="amount" invisible="1" readonly="1"/>
<field name="currency_id" invisible="1"/>
</group>
</group>
@@ -365,14 +367,15 @@
<field name="date_maturity" required="0" invisible="context.get('view_no_maturity', False)"/>
<field name="recompute_tax_line" invisible="1" readonly="1"/>
<field name="tax_line_grouping_key" invisible="1" readonly="1"/>
<field name="tax_repartition_line_id" invisible="1"/> <!--Not to be removed, we need it so that the call to new() takes it into account when autocompleting the lines of a tax-->
<field name="tag_ids" invisible="1"/>
</tree>
</field>
<field name="narration" colspan="4" placeholder="Add an internal note..." nolabel="1" height="50"/>
</page>
<page string="Other Info">
<group>
<field name="auto_reverse" attrs="{'readonly':[('reverse_entry_id', '!=', False)]}"/>
<field name="reverse_date" attrs="{'invisible':[('auto_reverse', '=', False)], 'required':[('auto_reverse', '=', True)],'readonly':[('reverse_entry_id', '!=', False)]}"/>
<field name="auto_post" attrs="{'readonly':[('reverse_entry_id', '!=', False)]}"/>
<field name="reverse_entry_id" attrs="{'invisible':True}"/>
<field name="to_check"/>
</group>
@@ -458,7 +461,7 @@
view_id="account.view_move_line_tax_audit_tree"/>
<record id="action_account_moves_all_a" model="ir.actions.act_window">
<field name="context">{'journal_type':'general', 'search_default_group_by_move': 1}</field>
<field name="context">{'journal_type':'general', 'search_default_group_by_move': 1, 'search_default_posted':1}</field>
<field name="name">Journal Items</field>
<field name="res_model">account.move.line</field>
<field name="view_id" ref="view_move_line_tree"/>
@@ -468,7 +471,7 @@
<record id="action_account_moves_all_tree" model="ir.actions.act_window">
<field name="name">Journal Items</field>
<field name="res_model">account.move.line</field>
<field name="context">{'search_default_partner_id': [active_id], 'default_partner_id': active_id}</field>
<field name="context">{'search_default_partner_id': [active_id], 'default_partner_id': active_id, 'search_default_posted':1}</field>
<field name="view_id" ref="view_move_line_tree"/>
</record>
@@ -83,7 +83,7 @@
<div class="row mt16 o_portal_invoice_sidebar">
<!-- Sidebar -->
<t t-call="portal.portal_record_sidebar">
<t t-set="classes" t-value="'col-12 col-lg flex-lg-grow-0 d-print-none'"/>
<t t-set="classes" t-value="'col-lg-auto d-print-none'"/>
<t t-set="title">
<h2 class="mb-0">
<b t-if="invoice.residual > 0" t-field="invoice.residual"/>
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="account_tax_report_line_tree" model="ir.ui.view">
<field name="name">account.tax.report.line.tree</field>
<field name="model">account.tax.report.line</field>
<field name="arch" type="xml">
<tree create="1" delete="1">
<field name="sequence" widget="handle"/>
<field name="name"/>
</tree>
</field>
</record>
<record id="account_tax_report_line_form" model="ir.ui.view">
<field name="name">account.tax.report.line.form</field>
<field name="model">account.tax.report.line</field>
<field name="arch" type="xml">
<form>
<group>
<group>
<field name="country_id" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="name"/>
<field name="tag_name"/>
</group>
<group>
<field name="parent_id" domain="[('country_id','=',country_id)]"/>
<field name="code"/>
</group>
</group>
<group>
<field name="formula"/>
</group>
<group string="Sublines">
<field name="children_line_ids" context="{'default_country_id': country_id}">
<form>
<group>
<group>
<field name="country_id" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="name"/>
<field name="tag_name"/>
</group>
<group>
<field name="code"/>
</group>
</group>
<group>
<field name="formula"/>
</group>
<group string="Sublines">
<field name="children_line_ids" context="{'form_view_ref': 'account.account_tax_report_line_form', 'default_country_id': country_id}"/>
</group>
</form>
</field>
</group>
</form>
</field>
</record>
<record id="action_configure_tax_report" model="ir.actions.act_window">
<field name="name">Configure Tax Report</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">account.tax.report.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="account_tax_report_line_tree"/>
</record>
<menuitem id="menu_configure_tax_report" name="Tax Report" parent="account.account_management_menu" action="account.action_configure_tax_report" groups="base.group_no_one"/>
</data>
</odoo>
+75 -122
View File
@@ -306,11 +306,11 @@
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="activity_ids" widget="mail_activity"/>
<field name="message_ids" widget="mail_thread"/>
</div>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="activity_ids" widget="mail_activity"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
@@ -328,100 +328,16 @@
</field>
</record>
<record id="view_account_bank_journal_tree" model="ir.ui.view">
<field name="name">account.bank.journal.tree</field>
<field name="model">account.journal</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<tree string="Account Journal">
<field name='sequence' widget='handle'/>
<field name="name"/>
<field name="bank_acc_number"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
<record id="action_new_bank_setting" model="ir.actions.server">
<field name="name">Add a Bank Account</field>
<field name="model_id" ref="model_res_company"/>
<field name="state">code</field>
<field name="code">
action = model.setting_init_bank_account_action()
</field>
</record>
<record id="account_bank_journal_view_kanban" model="ir.ui.view">
<field name="name">account.bank.journal.kanban</field>
<field name="model">account.journal</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
<div class="row">
<div class="col-12">
<strong><field name="name"/></strong>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_account_bank_journal_form" model="ir.ui.view">
<field name="name">account.bank.journal.form</field>
<field name="model">account.journal</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<form string="Bank Account">
<sheet>
<field name="type" invisible="1"/>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Bank Account Name"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="company_partner_id" invisible="1"/>
<field name="bank_account_id"/>
<field name="bank_acc_number" attrs="{'readonly': [('bank_account_id', '!=', False)]}"/>
<field name="bank_id" attrs="{'readonly': [('bank_account_id', '!=', False)]}"/>
</group>
<group>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="currency_id" options="{'no_create': True}" groups="base.group_multi_currency"/>
</group>
</group>
<group>
<div name="advanced_info"> <!--The content of this div is hidden in the setup wizard inheriting this form view-->
<group string="Payment Method Types">
<field name="inbound_payment_method_ids" widget="many2many_checkboxes"/>
<field name="outbound_payment_method_ids" widget="many2many_checkboxes"/>
</group>
</div>
<group name="bank_statement" string="Bank Statements" groups="account.group_account_user">
<field name="post_at_bank_rec"/>
<label for="bank_statements_source"/>
<div name="bank_source">
<field name="bank_statements_source" widget="radio" attrs="{'required': [('type', '=', 'bank')]}"/>
</div>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_account_bank_journal_form" model="ir.actions.act_window">
<field name="name">Bank Accounts</field>
<field name="res_model">account.journal</field>
<field name="view_mode">tree,kanban,form</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('view_account_bank_journal_tree')}),
(0, 0, {'view_mode': 'kanban', 'view_id': ref('account_bank_journal_view_kanban')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('view_account_bank_journal_form')})]"/>
<field name="domain">[('type', '=', 'bank')]</field>
<field name="context">{'default_type': 'bank'}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a bank account
</p>
</field>
</record>
<menuitem action="action_account_bank_journal_form" id="menu_action_account_bank_journal_form" parent="account_account_menu" groups="account.group_account_manager" sequence="8"/>
<menuitem action="action_new_bank_setting" id="menu_action_account_bank_journal_form" parent="account_account_menu" groups="account.group_account_manager" sequence="8"/>
<record id="action_account_journal_form" model="ir.actions.act_window">
<field name="name">Journals</field>
@@ -477,6 +393,10 @@
</div>
<group>
<field name="name"/>
<field name="applicability"/>
<field name="tax_negate" attrs="{'invisible': [('applicability', '!=', 'taxes')]}"/>
<field name="country_id" attrs="{'invisible': [('applicability', '!=', 'taxes')]}"/>
<field name="tax_report_line_ids" attrs="{'invisible': [('applicability', '!=', 'taxes')]}"/>
</group>
</sheet>
</form>
@@ -1072,6 +992,22 @@
</field>
</record>
<record id="tax_repartition_line_tree" model="ir.ui.view">
<field name="name">account.tax.repartition.line.tree</field>
<field name="model">account.tax.repartition.line</field>
<field name="arch" type="xml">
<tree editable="bottom" create="1" delete="1">
<field name="sequence" widget="handle"/>
<field name="factor_percent" attrs="{'invisible': [('repartition_type', '=', 'base')]}"/>
<field name="repartition_type"/>
<field name="account_id" attrs="{'invisible': [('repartition_type', '=', 'base')]}" options="{'no_create': True}"/>
<field name="tag_ids" widget="many2many_tags" options="{'no_create': True}" domain="[('applicability', '=', 'taxes'), ('country_id', '=', country_id)]"/>
<field name="country_id" invisible="1"/>
<field name="company_id" invisible="1"/>
</tree>
</field>
</record>
<record id="account_tax_view_tree" model="ir.ui.view">
<field name="name">account.invoice.line.tax.search</field>
<field name="model">account.tax</field>
@@ -1151,35 +1087,34 @@
<group>
<group>
<field name="name"/>
<field name="amount_type"/>
</group>
<group>
<field name="type_tax_use"/>
<label for="amount" attrs="{'invisible':[('amount_type','not in', ('fixed', 'percent', 'division'))]}"/>
<div attrs="{'invisible':[('amount_type','not in', ('fixed', 'percent', 'division'))]}">
<field name="amount" class="oe_inline"/>
<span class="o_form_label oe_inline" attrs="{'invisible':[('amount_type','=','fixed')]}">%</span>
</div>
</group>
</group>
<notebook>
<page string="Definition">
<group>
<group>
<field name="amount_type" />
<label for="amount" attrs="{'invisible':[('amount_type','not in', ('fixed', 'percent', 'division'))]}"/>
<div attrs="{'invisible':[('amount_type','not in', ('fixed', 'percent', 'division'))]}">
<field name="amount" class="oe_inline" />
<span class="o_form_label oe_inline" attrs="{'invisible':[('amount_type','=','fixed')]}">%</span>
</div>
<div attrs="{'invisible': [('amount_type', '=', 'group')]}">
<field name="country_id" invisible="1"/>
<group string="Repartition for Invoices">
<field name="invoice_repartition_line_ids" nolabel="1" context="{'default_company_id': company_id}"/>
</group>
<group attrs="{'invisible':[('amount_type','=', 'group')]}" groups="account.group_account_user">
<field name="account_id" options="{'no_create': True}"/>
<field name="refund_account_id" options="{'no_create': True}"/>
<group string="Repartition for Credit Notes">
<field name="refund_repartition_line_ids" nolabel="1" context="{'default_company_id': company_id}"/>
</group>
</group>
<field name="children_tax_ids"
attrs="{'invisible':['|', ('amount_type','!=','group'), ('type_tax_use','=','none')]}"
domain="[('type_tax_use','in',('none',type_tax_use)), ('amount_type','!=','group')]">
</div>
<field name="children_tax_ids" attrs="{'invisible':['|', ('amount_type','!=','group'), ('type_tax_use','=','none')]}" domain="[('type_tax_use','in',('none',type_tax_use)), ('amount_type','!=','group')]">
<tree string="Children Taxes">
<field name="sequence" widget="handle" />
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="amount_type" />
<field name="amount" />
<field name="amount_type"/>
<field name="amount"/>
</tree>
</field>
</page>
@@ -1188,7 +1123,6 @@
<group>
<field name="description" attrs="{'invisible':[('amount_type','=', 'group')]}"/>
<field name="tax_group_id"/>
<field name="tag_ids" domain="[('applicability', '!=', 'accounts')]" widget="many2many_tags" context="{'default_applicability': 'taxes'}"/>
<field name="analytic" attrs="{'invisible':[('amount_type','=', 'group')]}" groups="analytic.group_analytic_accounting" />
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
@@ -1197,8 +1131,8 @@
<field name="include_base_amount" attrs="{'invisible':[('amount_type','=', 'group')]}" />
<field name="hide_tax_exigibility" invisible="1"/>
<field name="tax_exigibility" widget="radio" attrs="{'invisible':['|', ('amount_type','=', 'group'), ('hide_tax_exigibility', '=', False)]}" groups="account.group_account_user"/>
<field name="cash_basis_account_id" options="{'no_create': True}" attrs="{'invisible': [('tax_exigibility', '=', 'on_invoice')], 'required': [('tax_exigibility', '=', 'on_payment')]}" groups="account.group_account_user"/>
<field name="cash_basis_base_account_id" options="{'no_create': True}" attrs="{'invisible': [('tax_exigibility', '=', 'on_invoice')], 'required': [('tax_exigibility', '=', 'on_payment')]}" groups="account.group_account_user"/>
<field name="cash_basis_transition_account_id" options="{'no_create': True}" attrs="{'invisible': [('tax_exigibility', '=', 'on_invoice')], 'required': [('tax_exigibility', '=', 'on_payment')]}" groups="account.group_account_user"/>
</group>
</group>
</page>
@@ -1223,6 +1157,29 @@
</record>
<menuitem action="action_tax_form" id="menu_action_tax_form" parent="account_account_menu" sequence="2"/>
<!-- Tax group -->
<record id="view_tax_group_tree" model="ir.ui.view">
<field name="name">account.tax.group.tree</field>
<field name="model">account.tax.group</field>
<field name="arch" type="xml">
<tree string="Account Tax Group" editable="bottom" create="false">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="property_tax_payable_account_id"/>
<field name="property_tax_receivable_account_id"/>
<field name="property_advance_tax_payment_account_id"/>
</tree>
</field>
</record>
<record id="action_tax_group" model="ir.actions.act_window">
<field name="name">Tax Groups</field>
<field name="res_model">account.tax.group</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain" eval="False"/> <!-- Force empty -->
<field name="view_id" ref="view_tax_group_tree"/>
</record>
<!-- Full Reconcile -->
<record id="view_full_reconcile_form" model="ir.ui.view">
<field name="name">account.full.reconcile.form</field>
@@ -1521,10 +1478,6 @@
<span class="o_form_label oe_inline" attrs="{'invisible':[('amount_type','=','fixed')]}">%</span>
</div>
</group>
<group attrs="{'invisible':[('amount_type','=', 'group')]}">
<field name="account_id" options="{'no_create': True}"/>
<field name="refund_account_id" options="{'no_create': True}"/>
</group>
</group>
<field name="children_tax_ids"
attrs="{'invisible':['|', ('amount_type','!=','group'), ('type_tax_use','=','none')]}"
@@ -1548,10 +1501,10 @@
<field name="include_base_amount" attrs="{'invisible':[('amount_type','=', 'group')]}" />
</group>
<group>
<field name="tag_ids" domain="[('applicability', '!=', 'accounts')]" widget="many2many_tags" context="{'default_applicability': 'taxes'}"/>
<field name="active" groups="base.group_no_one"/>
<field name="tax_exigibility" widget="radio" attrs="{'invisible':[('amount_type','=', 'group')]}"/>
<field name="cash_basis_account_id" options="{'no_create': True}" attrs="{'invisible': [('tax_exigibility', '=', 'on_invoice')], 'required': [('tax_exigibility', '=', 'on_payment')]}"/>
<field name="cash_basis_base_account_id" attrs="{'invisible': [('tax_exigibility', '=', 'on_invoice')], 'required': [('tax_exigibility', '=', 'on_payment')]}"/>
<field name="cash_basis_transition_account_id" attrs="{'invisible': [('tax_exigibility', '=', 'on_invoice')], 'required': [('tax_exigibility', '=', 'on_payment')]}"/>
</group>
</group>
</page>
@@ -46,7 +46,7 @@
<td><span t-field="inv.date_invoice"/></td>
<td><span t-field="inv.number"/></td>
<td class="text-right"><span t-field="inv.amount_total"/></td>
<td class="text-right"><span t-esc="inv.amount_total - inv.residual" t-options="{'widget': 'monetary', 'display_currency': inv.currency_id}"/></td>
<td class="text-right"><span t-esc="o._get_invoice_payment_amount(inv)" t-options="{'widget': 'monetary', 'display_currency': inv.currency_id}"/></td>
<td class="text-right"><span t-field="inv.residual"/></td>
</tr>
</tbody>
+1 -2
View File
@@ -7,6 +7,5 @@
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<!-- TODO: debug -->
<menuitem action="tax_adjustments_form" id="menu_action_tax_adjustment" parent="account.menu_finance_entries_actions" sequence="45" groups="account.group_account_manager" />
<menuitem action="tax_adjustments_form" id="menu_action_tax_adjustment" parent="account.menu_finance_entries_actions" sequence="45" groups="base.group_no_one" />
</odoo>
@@ -24,7 +24,7 @@ class AccountInvoiceRefund(models.TransientModel):
date = fields.Date(string='Accounting Date')
description = fields.Char(string='Reason', required=True, default=lambda self: self._get_reason())
refund_only = fields.Boolean(string='Technical field to hide filter_refund in case invoice is partially paid', compute='_get_refund_only')
filter_refund = fields.Selection([('refund', 'Create a draft credit note'), ('cancel', 'Cancel: create credit note and reconcile'), ('modify', 'Modify: create credit note, reconcile and create a new draft invoice')],
filter_refund = fields.Selection([('refund', 'Create a draft credit note (partial refunding)'), ('cancel', 'Cancel: create credit note and reconcile (full refunding)'), ('modify', 'Modify: create credit note, reconcile and create a new draft invoice')],
default='refund', string='Credit Method', required=True, help='Choose how you want to credit this invoice. You cannot Modify and Cancel if the invoice is already reconciled')
@api.depends('date_invoice')
+25 -14
View File
@@ -25,25 +25,36 @@ class TaxAdjustments(models.TransientModel):
@api.multi
def _create_move(self):
adjustment_type = self.env.context.get('adjustment_type', (self.amount > 0.0 and 'debit' or 'credit'))
debit_vals = {
move_line_vals = []
is_debit = adjustment_type == 'debit'
for tax_vals in self.tax_id.compute_all(abs(self.amount))['taxes']:
repartition_line = self.env['account.tax.repartition.line'].browse(tax_vals['tax_repartition_line_id'])
# Vals for the amls corresponding to the tax
move_line_vals.append((0, 0, {
'name': self.reason,
'debit': is_debit and abs(self.amount) or 0,
'credit': not is_debit and abs(self.amount) or 0,
'account_id': is_debit and self.debit_account_id.id or self.credit_account_id.id,
'tax_repartition_line_id': repartition_line.id,
'tag_ids': [(6, False, repartition_line.tag_ids.ids)],
}))
# Vals for the counterpart line
move_line_vals.append((0, 0, {
'name': self.reason,
'debit': abs(self.amount),
'credit': 0.0,
'account_id': self.debit_account_id.id,
'tax_line_id': adjustment_type == 'debit' and self.tax_id.id or False,
}
credit_vals = {
'name': self.reason,
'debit': 0.0,
'credit': abs(self.amount),
'account_id': self.credit_account_id.id,
'tax_line_id': adjustment_type == 'credit' and self.tax_id.id or False,
}
'debit': not is_debit and abs(self.amount) or 0,
'credit': is_debit and abs(self.amount) or 0,
'account_id': is_debit and self.credit_account_id.id or self.debit_account_id.id,
'tax_repartition_line_id': False,
}))
# Create the move
vals = {
'journal_id': self.journal_id.id,
'date': self.date,
'state': 'draft',
'line_ids': [(0, 0, debit_vals), (0, 0, credit_vals)]
'line_ids': move_line_vals,
}
move = self.env['account.move'].create(vals)
move.post()
@@ -17,7 +17,7 @@
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_invoice_draft']" position="before">
<button name="action_invoice_cancel" type="object" states="draft,open,paid" string="Cancel" groups="account.group_account_invoice"/>
<button name="action_invoice_cancel" type="object" states="draft,open,in_payment,paid" string="Cancel" groups="account.group_account_invoice"/>
</xpath>
</field>
</record>
@@ -28,7 +28,7 @@
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_invoice_draft']" position="before">
<button name="action_invoice_cancel" type="object" states="draft,open,paid" string="Cancel" groups="account.group_account_invoice"/>
<button name="action_invoice_cancel" type="object" states="draft,open,in_payment,paid" string="Cancel" groups="account.group_account_invoice"/>
</xpath>
</field>
</record>
@@ -34,7 +34,7 @@ class TestPrintCheck(AccountingTestCase):
invoice = self.invoice_model.create({
'partner_id': self.partner_axelor.id,
'name': is_refund and "Supplier Refund" or "Supplier Invoice",
'type': is_refund and "in_refund" or "in_invoice",
'type': is_refund and "out_refund" or "in_invoice",
'account_id': self.account_payable.id,
'date_invoice': time.strftime('%Y') + '-06-26',
})
@@ -31,7 +31,8 @@
currency=line.currency_id,
quantity=line.quantity,
product=line.product_id,
partner=record.partner_id)"/>
partner=record.partner_id,
is_refund=line.invoice_id.type in ('in_refund', 'out_refund'))"/>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount
t-att-currencyID="currency.name"
@@ -36,7 +36,7 @@ class AccountTaxPython(models.Model):
return super(AccountTaxPython, self)._compute_amount(base_amount, price_unit, quantity, product, partner)
@api.multi
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None):
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None, is_refund=False):
taxes = self.filtered(lambda r: r.amount_type != 'code')
company = self.env.company_id
for tax in self.filtered(lambda r: r.amount_type == 'code'):
@@ -45,7 +45,7 @@ class AccountTaxPython(models.Model):
safe_eval(tax.python_applicable, localdict, mode="exec", nocopy=True)
if localdict.get('result', False):
taxes += tax
return super(AccountTaxPython, taxes).compute_all(price_unit, currency, quantity, product, partner)
return super(AccountTaxPython, taxes).compute_all(price_unit, currency, quantity, product, partner, is_refund=is_refund)
class AccountTaxTemplatePython(models.Model):
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import test_tax
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.test_tax import TestTax
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestTaxPython(TestTax):
def setUp(self):
super(TestTaxPython, self).setUp()
self.python_tax = self.tax_model.create({
'name': 'Python TAx',
'amount_type': 'code',
'amount': 0.0,
'python_compute': 'result = ((price_unit * quantity) - ((price_unit * quantity) / 1.12)) * 0.5',
'sequence': 1,
})
def test_tax_python_basic(self):
res = self.python_tax.compute_all(130.0)
self._check_compute_all_results(
136.96, # 'total_included'
130.0, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# --------------------------------------------------
(130.0, 6.96), # | 1 | 6% | t |
# --------------------------------------------------
],
res
)
def test_tax_python_price_include(self):
self.python_tax.price_include = True
res = self.python_tax.compute_all(130.0)
self._check_compute_all_results(
130, # 'total_included'
123.04, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(123.04, 6.96), # | 1 | 6% | t |
# ---------------------------------------------------
],
res
)
res = (self.python_tax + self.python_tax).compute_all(130.0)
self._check_compute_all_results(
130, # 'total_included'
116.07, # 'total_excluded'
[
# base , amount | seq | amount | incl | incl_base
# ---------------------------------------------------
(116.07, 6.96), # | 1 | 6% | t |
(116.07, 6.97), # | 1 | 6% | t |
# ---------------------------------------------------
],
res
)
+2 -2
View File
@@ -44,7 +44,7 @@ class AuthSignupHome(Home):
lang=user_sudo.lang,
auth_login=werkzeug.url_encode({'auth_login': user_sudo.email}),
).send_mail(user_sudo.id, force_send=True)
return super(AuthSignupHome, self).web_login(*args, **kw)
return self.web_login(*args, **kw)
except UserError as e:
qcontext['error'] = e.name or e.value
except (SignupError, AssertionError) as e:
@@ -69,7 +69,7 @@ class AuthSignupHome(Home):
try:
if qcontext.get('token'):
self.do_signup(qcontext)
return super(AuthSignupHome, self).web_login(*args, **kw)
return self.web_login(*args, **kw)
else:
login = qcontext.get('login')
assert login, _("No login provided.")
@@ -7,5 +7,8 @@
<record id="base.mx" model="res.country">
<field eval="'%(street_name)s %(street_number)s/%(street_number2)s'" name="street_format" />
</record>
<record id="base.hr" model="res.country">
<field eval="'%(street_name)s %(street_number)s %(street_number2)s'" name="street_format" />
</record>
</data>
</odoo>
@@ -6,7 +6,7 @@ import re
from odoo import api, fields, models, _
from odoo.exceptions import UserError
STREET_FIELDS = ('street_name', 'street_number', 'street_number2')
STREET_FIELDS = ['street_name', 'street_number', 'street_number2']
class ResCountry(models.Model):
@@ -33,6 +33,10 @@ class Partner(models.Model):
street_number2 = fields.Char('Door', compute='_split_street', help="Door Number",
inverse='_set_street', store=True)
def _formatting_address_fields(self):
"""Returns the list of address fields usable to format addresses."""
return super(Partner, self)._formatting_address_fields() + self.get_street_fields()
def get_street_fields(self):
"""Returns the fields that can be used in a street format.
Overwrite this function if you want to add your own fields."""
+14
View File
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import codecs
import collections
import unicodedata
@@ -32,6 +33,12 @@ DEFAULT_IMAGE_REGEX = r"(?:http|https)://.*(?:png|jpe?g|tiff?|gif|bmp)"
DEFAULT_IMAGE_CHUNK_SIZE = 32768
IMAGE_FIELDS = ["icon", "image", "logo", "picture"]
_logger = logging.getLogger(__name__)
BOM_MAP = {
'utf-16le': codecs.BOM_UTF16_LE,
'utf-16be': codecs.BOM_UTF16_BE,
'utf-32le': codecs.BOM_UTF32_LE,
'utf-32be': codecs.BOM_UTF32_BE,
}
try:
import xlrd
@@ -323,6 +330,13 @@ class Import(models.TransientModel):
encoding = options.get('encoding')
if not encoding:
encoding = options['encoding'] = chardet.detect(csv_data)['encoding'].lower()
# some versions of chardet (e.g. 2.3.0 but not 3.x) will return
# utf-(16|32)(le|be), which for python means "ignore / don't strip
# BOM". We don't want that, so rectify the encoding to non-marked
# IFF the guessed encoding is LE/BE and csv_data starts with a BOM
bom = BOM_MAP.get(encoding)
if bom and csv_data.startswith(bom):
encoding = options['encoding'] = encoding[:-2]
if encoding != 'utf-8':
csv_data = csv_data.decode(encoding).encode('utf-8')
+12 -3
View File
@@ -26,18 +26,27 @@ class TestEncoding(ImportCase):
options.setdefault('separator', '\t')
test_text = "text\tnumber\tdate\tdatetime\n%s\t1.23.45,67\t\t\n" % text
for encoding in ['utf-8', 'utf-16', 'utf-32', *encodings]:
if isinstance(encoding, tuple):
encoding, es = encoding
else:
es = [encoding]
preview = self._make_import(
test_text.encode(encoding)).parse_preview(dict(options))
self.assertIsNone(preview.get('error'))
guessed = preview['options']['encoding']
self.assertIsNotNone(guessed, encoding)
self.assertEqual(codecs.lookup(guessed).name, codecs.lookup(encoding).name)
self.assertIsNotNone(guessed)
self.assertIn(
codecs.lookup(guessed).name, [
codecs.lookup(e).name
for e in es
]
)
def test_autodetect_encoding(self):
""" Check that import preview can detect & return encoding
"""
self._check_text("Iñtërnâtiônàlizætiøn", ['iso-8859-1'])
self._check_text("Iñtërnâtiônàlizætiøn", [('iso-8859-1', ['iso-8859-1', 'iso-8859-2'])])
self._check_text("やぶら小路の藪柑子。海砂利水魚の、食う寝る処に住む処、パイポパイポ パイポのシューリンガン。", ['eucjp', 'shift_jis', 'iso2022_jp'])
@@ -38,6 +38,8 @@ class IrModule(models.Model):
installed_mods = [m.name for m in known_mods if m.state == 'installed']
terp = load_information_from_description_file(module, mod_path=path)
if not terp:
return False
values = self.get_values_from_terp(terp)
if 'version' in terp:
values['latest_version'] = terp['version']
@@ -133,8 +135,8 @@ class IrModule(models.Model):
try:
# assert mod_name.startswith('theme_')
path = opj(module_dir, mod_name)
self._import_module(mod_name, path, force=force)
success.append(mod_name)
if self._import_module(mod_name, path, force=force):
success.append(mod_name)
except Exception as e:
_logger.exception('Error while importing module')
errors[mod_name] = exception_to_unicode(e)
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record model="ir.config_parameter" id="show_effect">
<record model="ir.config_parameter" id="show_effect" forcecreate="False">
<field name="key">base_setup.show_effect</field>
<field name="value">True</field>
</record>
@@ -8,6 +8,9 @@
<xpath expr="//field[@name='vat']" position="attributes">
<attribute name="string">VAT</attribute>
</xpath>
<xpath expr="//span[hasclass('o_vat_label')]" position="replace">
<span class="o_vat_label">VAT</span>
</xpath>
</field>
</record>
@@ -86,12 +86,18 @@ var AddToBoardMenu = Widget.extend({
var context = new Context(this.action.context);
context.add(searchQuery.context);
context.add({
group_by: pyUtils.eval('groupbys', searchQuery.groupBys || [])
group_by: searchQuery.groupBy,
orderedBy: searchQuery.orderedBy,
});
this.trigger_up('get_controller_query_params', {
callback: function (controllerContext) {
context.add(controllerContext);
callback: function (controllerQueryParams) {
var queryContext = controllerQueryParams.context;
var allContext = _.extend(
_.omit(controllerQueryParams, ['context']),
queryContext
);
context.add(allContext);
}
});
+2 -1
View File
@@ -272,7 +272,8 @@ var BoardRenderer = FormRenderer.extend({
searchQuery: {
context: context,
domain: domain,
groupBy: context.group_by || [],
groupBy: typeof context.group_by === 'string' && context.group_by ? [context.group_by] : context.group_by || [],
orderedBy: context.orderedBy || [],
},
withControlPanel: false,
});
+91 -3
View File
@@ -109,7 +109,7 @@ QUnit.test('display the no content helper', async function (assert) {
});
QUnit.test('basic functionality, with one sub action', async function (assert) {
assert.expect(25);
assert.expect(26);
var form = await createView({
View: BoardView,
@@ -118,7 +118,7 @@ QUnit.test('basic functionality, with one sub action', async function (assert) {
arch: '<form string="My Dashboard">' +
'<board style="2-1">' +
'<column>' +
'<action context="{}" view_mode="list" string="ABC" name="51" domain="[[\'foo\', \'!=\', \'False\']]"></action>' +
'<action context="{&quot;orderedBy&quot;: [{&quot;name&quot;: &quot;foo&quot;, &quot;asc&quot;: True}]}" view_mode="list" string="ABC" name="51" domain="[[\'foo\', \'!=\', \'False\']]"></action>' +
'</column>' +
'</board>' +
'</form>',
@@ -132,6 +132,12 @@ QUnit.test('basic functionality, with one sub action', async function (assert) {
}
if (route === '/web/dataset/search_read') {
assert.deepEqual(args.domain, [['foo', '!=', 'False']], "the domain should be passed");
assert.deepEqual(args.context.orderedBy, [{
'name': 'foo',
'asc': true,
}],
'orderedBy is present in the search read when specified on the custom action'
);
}
if (route === '/web/view/edit_custom') {
assert.step('edit custom');
@@ -687,7 +693,19 @@ QUnit.test('dashboard intercepts custom events triggered by sub controllers', as
});
QUnit.test('save actions to dashboard', async function (assert) {
assert.expect(3);
assert.expect(6);
testUtils.patch(ListController, {
getOwnedQueryParams: function () {
var result = this._super.apply(this, arguments);
result.context = {
'fire': 'on the bayou',
}
return result;
}
});
this.data['partner'].fields.foo.sortable = true;
var actionManager = await createActionManager({
data: this.data,
@@ -697,6 +715,16 @@ QUnit.test('save actions to dashboard', async function (assert) {
},
mockRPC: function (route, args) {
if (route === '/board/add_to_dashboard') {
assert.deepEqual(args.context_to_save.group_by, ['foo'],
'The group_by should have been saved');
assert.deepEqual(args.context_to_save.orderedBy,
[{
name: 'foo',
asc: true,
}],
'The orderedBy should have been saved');
assert.strictEqual(args.context_to_save.fire, 'on the bayou',
'The context of a controller should be passed and flattened');
assert.strictEqual(args.action_id, 1,
"should save the correct action");
assert.strictEqual(args.view_mode, 'list',
@@ -717,12 +745,22 @@ QUnit.test('save actions to dashboard', async function (assert) {
assert.containsOnce(actionManager, '.o_list_view',
"should display the list view");
// Sort the list
await testUtils.dom.click($('.o_column_sortable'));
// Group It
await testUtils.dom.click($('.o_search_options .o_dropdown button:contains(Group By)'));
await testUtils.dom.click($('.o_search_options .o_group_by_menu button'));
await testUtils.dom.click($('.o_search_options .o_group_by_menu button.o_apply_group'));
// add this action to dashboard
await testUtils.dom.click($('.o_search_options .o_dropdown button:contains(Favorites)'));
await testUtils.dom.click($('.o_add_to_board.o_menu_header'));
testUtils.fields.editInput($('input.o_add_to_board_input'), 'a name');
await testUtils.dom.click($('.o_add_to_board_confirm_button'));
testUtils.unpatch(ListController);
actionManager.destroy();
});
@@ -769,6 +807,12 @@ QUnit.test('save two searches to dashboard', async function (assert) {
await testUtils.dom.click(actionManager.$('.o_apply_filter'));
// Add it to dashboard
await testUtils.dom.click(actionManager.$('.o_favorites_menu_button'));
$('.o_search_options .dropdown-menu.o_favorites_menu').one('click', function (ev) {
// This handler is on the webClient
// But since the test suite doesn't have one
// We manually set it here
ev.stopPropagation();
});
await testUtils.dom.click(actionManager.$('.o_add_to_board'));
await testUtils.dom.click(actionManager.$('.o_add_to_board_confirm_button'));
// Remove it
@@ -781,6 +825,12 @@ QUnit.test('save two searches to dashboard', async function (assert) {
await testUtils.dom.click(actionManager.$('.o_apply_filter'));
// Add it to dashboard
await testUtils.dom.click(actionManager.$('.o_favorites_menu_button'));
$('.o_search_options .dropdown-menu.o_favorites_menu').one('click', function (ev) {
// This handler is on the webClient
// But since the test suite doesn't have one
// We manually set it here
ev.stopPropagation();
});
await testUtils.dom.click(actionManager.$('.o_add_to_board'));
await testUtils.dom.click(actionManager.$('.o_add_to_board_confirm_button'));
@@ -912,6 +962,44 @@ QUnit.test("Dashboard should use correct groupby", async function (assert) {
form.destroy();
});
QUnit.test("Dashboard should use correct groupby when defined as a string of one field", async function (assert) {
assert.expect(1);
var form = await createView({
View: BoardView,
model: 'board',
data: this.data,
arch: '<form string="My Dashboard">' +
'<board style="2-1">' +
'<column>' +
'<action context="{\'group_by\': \'bar\'}" string="ABC" name="51"></action>' +
'</column>' +
'</board>' +
'</form>',
mockRPC: function (route, args) {
if (args.method === 'web_read_group') {
assert.deepEqual(args.kwargs.groupby, ['bar'],
'user defined groupby should have precedence on action groupby');
}
if (route === '/web/action/load') {
return Promise.resolve({
res_model: 'partner',
context: {
group_by: 'some_field',
},
views: [[4, 'list']],
});
}
return this._super.apply(this, arguments);
},
archs: {
'partner,4,list':
'<list string="Partner"><field name="foo"/></list>',
},
});
form.destroy();
});
QUnit.test('click on a cell of pivot view inside dashboard', async function (assert) {
assert.expect(3);
@@ -68,7 +68,7 @@ var BusService = CrossTab.extend(ServicesMixin, {
var session = this.getSession();
this._audio.src = session.url("/mail/static/src/audio/ting" + ext);
}
this._audio.play();
Promise.resolve(this._audio.play()).catch(_.noop);
}
},
/**
+3
View File
@@ -8,6 +8,7 @@
<field name="email_from">${(object.event_id.user_id.email_formatted or user.email_formatted or '') | safe}</field>
<field name="email_to">${('' if object.partner_id.email and object.partner_id.email == object.email else object.email) | safe}</field>
<field name="partner_to">${object.partner_id.id if object.partner_id.email and object.partner_id.email == object.email else False}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="html">
<div>
% set colors = {'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}
@@ -92,6 +93,7 @@
<field name="email_from">${(object.event_id.user_id.email_formatted or user.email_formatted or '') | safe}</field>
<field name="email_to">${('' if object.partner_id.email and object.partner_id.email == object.email else object.email) | safe}</field>
<field name="partner_to">${object.partner_id.id if object.partner_id.email and object.partner_id.email == object.email else False}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="html">
<div>
% set colors = {'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}
@@ -176,6 +178,7 @@
<field name="email_from">${(object.event_id.user_id.email_formatted or user.email_formatted or '') | safe}</field>
<field name="email_to">${('' if object.partner_id.email and object.partner_id.email == object.email else object.email) | safe}</field>
<field name="partner_to">${object.partner_id.id if object.partner_id.email and object.partner_id.email == object.email else False}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html" type="html">
<div>
% set colors = {'needsAction': 'grey', 'accepted': 'green', 'tentative': '#FFFF00', 'declined': 'red'}
+1 -1
View File
@@ -26,6 +26,6 @@ class Message(models.Model):
def _find_allowed_model_wise(self, doc_model, doc_dict):
if doc_model == 'calendar.event':
order = self._context.get('order', self.env[doc_model]._order)
for virtual_id in self.env[doc_model].browse(doc_dict).get_recurrent_ids([], order=order):
for virtual_id in self.env[doc_model].with_context(active_test=False).search([('id', 'in', list(doc_dict))], order=order).ids:
doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)])
return super(Message, self)._find_allowed_model_wise(doc_model, doc_dict)
+3 -3
View File
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="sales_team.salesteam_website_sales" model="crm.team">
<record id="sales_team.salesteam_website_sales" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<record id="sales_team.pos_sales_team" model="crm.team">
<record id="sales_team.pos_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<record id="sales_team.ebay_sales_team" model="crm.team">
<record id="sales_team.ebay_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
+1 -1
View File
@@ -5,7 +5,7 @@
<field name="groups_id" eval="[(4,ref('sales_team.group_sale_salesman'))]"/>
</record>
<record id="sales_team.team_sales_department" model="crm.team">
<record id="sales_team.team_sales_department" model="crm.team" forcecreate="False">
<field name="alias_name">sales</field>
<field name="alias_user_id" ref="base.user_admin"/>
<field name="company_id" eval="False"/>
+7 -1
View File
@@ -98,9 +98,15 @@ class SaleOrder(models.Model):
taxes_ids = self.fiscal_position_id.map_tax(taxes, carrier.product_id, self.partner_id).ids
# Create the sales order line
carrier_with_partner_lang = carrier.with_context(lang=self.partner_id.lang)
if carrier_with_partner_lang.product_id.description_sale:
so_description = '%s: %s' % (carrier_with_partner_lang.name,
carrier_with_partner_lang.product_id.description_sale)
else:
so_description = carrier_with_partner_lang.name
values = {
'order_id': self.id,
'name': carrier.with_context(lang=self.partner_id.lang).name,
'name': so_description,
'product_uom_qty': 1,
'product_uom': carrier.product_id.uom_id.id,
'product_id': carrier.product_id.id,
+2 -2
View File
@@ -42,7 +42,7 @@ class StockPicking(models.Model):
@api.one
@api.depends('move_line_ids')
@api.depends('move_line_ids', 'move_line_ids.result_package_id')
def _compute_packages(self):
self.ensure_one()
packs = set()
@@ -52,7 +52,7 @@ class StockPicking(models.Model):
self.package_ids = list(packs)
@api.one
@api.depends('move_line_ids')
@api.depends('move_line_ids', 'move_line_ids.result_package_id', 'move_line_ids.product_uom_id', 'move_line_ids.qty_done')
def _compute_bulk_weight(self):
weight = 0.0
for move_line in self.move_line_ids:
+1 -1
View File
@@ -94,7 +94,7 @@
<label for="free_over"/>
</div>
<field nolabel="1" name="amount" attrs="{'required':[('free_over','!=', False)], 'invisible':[('free_over','=', False)]}"/>
<field name="product_id" context="{'default_type': 'service', 'sale_ok': False, 'purchase_ok': False}" />
<field name="product_id" context="{'default_type': 'service', 'default_sale_ok': False, 'default_purchase_ok': False}" />
<field name="company_id" groups="base.group_multi_company"/>
<field name="can_generate_return" invisible="1"/>
<field name="return_label_on_delivery" attrs="{'invisible': [('can_generate_return', '=', False)]}"/>
@@ -53,7 +53,7 @@ class ChooseDeliveryCarrier(models.TransientModel):
def _compute_available_carrier(self):
carriers = self.env['delivery.carrier'].search([])
for rec in self:
rec.available_carrier_ids = carriers.available_carriers(rec.partner_id) if rec.partner_id else carriers
rec.available_carrier_ids = carriers.available_carriers(rec.order_id.partner_shipping_id) if rec.partner_id else carriers
def update_price(self):
vals = self.carrier_id.rate_shipment(self.order_id)
+1 -1
View File
@@ -9,7 +9,7 @@ from odoo.http import Controller, request, route, content_disposition
class EventController(Controller):
@route(['''/event/<model("event.event", "[('state', 'in', ('confirm', 'done'))]"):event>/ics'''], type='http', auth="public")
def event_ics_file(self, event):
def event_ics_file(self, event, **kwargs):
if not event or not event.registration_ids:
return request.not_found()
files = event._get_ics_file()
+2 -2
View File
@@ -42,11 +42,11 @@ class SaleOrderLine(models.Model):
registrations linked to this line. This method update existing registrations
and create new one for missing one. """
Registration = self.env['event.registration'].sudo()
registrations = Registration.search([('sale_order_line_id', 'in', self.ids), ('state', '!=', 'cancel')])
registrations = Registration.search([('sale_order_line_id', 'in', self.ids)])
for so_line in self.filtered('event_id'):
existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id)
if confirm:
existing_registrations.filtered(lambda self: self.state != 'open').confirm_registration()
existing_registrations.filtered(lambda self: self.state not in ['open', 'cancel']).confirm_registration()
if cancel_to_draft:
existing_registrations.filtered(lambda self: self.state == 'cancel').do_draft()
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from pprint import pformat
import json
import logging
@@ -183,13 +184,16 @@ class GoogleService(models.TransientModel):
except:
pass
except requests.HTTPError as error:
# https://developers.google.com/calendar/v3/errors
if error.response.status_code in (204, 404):
status = error.response.status_code
response = ""
else:
_logger.exception("Bad google request : %s !", error.response.content)
req = json.loads(error.request.body)
res = error.response.json()
_logger.exception("Error while requesting Google Services\nRequest:\n%s\nResponse:\n%s", pformat(req), pformat(res))
if error.response.status_code in (400, 401, 410):
raise error
raise UserError(_("Error while requesting Google Services: %s" % res['error']['message']))
raise self.env['res.config.settings'].get_config_warning(_("Something went wrong with your request to google"))
return (status, response, ask_time)
+7
View File
@@ -324,6 +324,13 @@
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<separator/>
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction', '=', True)]"/>
<separator/>
<filter string="Late Activities" name="activities_overdue"
domain="[('activity_ids.date_deadline', '&lt;', context_today().strftime('%Y-%m-%d'))]"/>
<filter string="Today Activities" name="activities_today"
domain="[('activity_ids.date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
<filter string="Future Activities" name="activities_upcoming_all"
domain="[('activity_ids.date_deadline', '&gt;', context_today().strftime('%Y-%m-%d'))]"/>
<group expand="0" string="Group By">
<filter name="group_manager" string="Manager" domain="[]" context="{'group_by':'parent_id'}"/>
<filter name="group_coach" string="Coach" domain="[]" context="{'group_by':'coach_id'}"/>
+7 -10
View File
@@ -29,16 +29,13 @@ class Employee(models.Model):
"""
Returns the contracts of the employee between date_from and date_to
"""
# a contract is valid if it ends between the given dates
clause_1 = ['&', ('date_end', '<=', date_to), ('date_end', '>=', date_from)]
# OR if it starts between the given dates
clause_2 = ['&', ('date_start', '<=', date_to), ('date_start', '>=', date_from)]
# OR if it starts before the date_from and finish after the date_end (or never finish)
clause_3 = ['&', ('date_start', '<=', date_from), '|', ('date_end', '=', False), ('date_end', '>=', date_to)]
clause_final = expression.AND([
[('employee_id', 'in', self.ids), ('state', 'in', states)],
expression.OR([clause_1, clause_2, clause_3])])
return self.env['hr.contract'].search(clause_final)
return self.env['hr.contract'].search([
'&', '&', '&',
('employee_id', 'in', self.ids),
('state', 'in', states),
('date_start', '<=', date_to),
'|', ('date_end', '=', False), ('date_end', '>=', date_from)
])
@api.model
def _get_all_contracts(self, date_from, date_to, states=['open', 'pending']):
+2 -2
View File
@@ -324,7 +324,7 @@ class HrExpense(models.Model):
'credit': -amount if amount < 0 else 0,
'amount_currency': amount_currency if different_currency else 0.0,
'account_id': tax['account_id'] or move_line_src['account_id'],
'tax_line_id': tax['id'],
'tax_repartition_line_id': tax['tax_repartition_line_id'],
'expense_id': expense.id,
'partner_id': partner_id,
'currency_id': expense.currency_id.id if different_currency else False,
@@ -369,7 +369,7 @@ class HrExpense(models.Model):
# get move line values
move_line_values = move_line_values_by_expense.get(expense.id)
move_line_dst = move_line_values[-1]
total_amount = abs(move_line_dst['debit'])
total_amount = move_line_dst['debit'] or -move_line_dst['credit']
total_amount_currency = move_line_dst['amount_currency']
# create one more move line, a counterline for the total on payable account
+9 -6
View File
@@ -335,19 +335,22 @@ class HolidaysRequest(models.Model):
@api.onchange('holiday_type')
def _onchange_type(self):
if self.holiday_type == 'employee' and not self.employee_id:
self.employee_id = self.env.user.employee_ids[:1].id
if self.holiday_type == 'employee':
if not self.employee_id:
self.employee_id = self.env.user.employee_ids[:1].id
self.mode_company_id = False
self.category_id = False
elif self.holiday_type == 'company' and not self.mode_company_id:
elif self.holiday_type == 'company':
self.employee_id = False
self.mode_company_id = self.env.company_id.id
if not self.mode_company_id:
self.mode_company_id = self.env.company_id.id
self.category_id = False
elif self.holiday_type == 'department' and not self.department_id:
elif self.holiday_type == 'department':
self.employee_id = False
self.mode_company_id = False
self.department_id = self.env.user.employee_ids[:1].department_id.id
self.category_id = False
if not self.department_id:
self.department_id = self.env.user.employee_ids[:1].department_id.id
elif self.holiday_type == 'category':
self.employee_id = False
self.mode_company_id = False
@@ -12,6 +12,7 @@ from odoo import api, fields, models
from odoo.addons.resource.models.resource import HOURS_PER_DAY
from odoo.exceptions import AccessError, UserError
from odoo.tools.translate import _
from odoo.tools.float_utils import float_round
_logger = logging.getLogger(__name__)
@@ -72,6 +73,8 @@ class HolidaysAllocation(models.Model):
number_of_hours_display = fields.Float(
'Duration (hours)', compute='_compute_number_of_hours_display',
help="UX field allowing to see and modify the allocation duration, computed in hours.")
duration_display = fields.Char('Allocated (Days/Hours)', compute='_compute_duration_display',
help="Field allowing to see the allocation duration in days or hours depending on the type_request_unit")
# details
parent_id = fields.Many2one('hr.leave.allocation', string='Parent')
linked_request_ids = fields.One2many('hr.leave.allocation', 'parent_id', string='Linked Requests')
@@ -206,6 +209,16 @@ class HolidaysAllocation(models.Model):
for allocation in self:
allocation.number_of_hours_display = allocation.number_of_days * (allocation.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY)
@api.multi
@api.depends('number_of_hours_display', 'number_of_days_display')
def _compute_duration_display(self):
for allocation in self:
allocation.duration_display = '%g %s' % (
(float_round(allocation.number_of_hours_display, precision_digits=2)
if allocation.type_request_unit == 'hour'
else float_round(allocation.number_of_days_display, precision_digits=2)),
_('hours') if allocation.type_request_unit == 'hour' else _('days'))
@api.multi
@api.depends('state', 'employee_id', 'department_id')
def _compute_can_reset(self):
@@ -244,16 +257,26 @@ class HolidaysAllocation(models.Model):
@api.onchange('holiday_type')
def _onchange_type(self):
if self.holiday_type == 'employee' and not self.employee_id:
if self.env.user.employee_ids:
self.employee_id = self.env.user.employee_ids[0]
if self.holiday_type == 'employee':
if not self.employee_id:
self.employee_id = self.env.user.employee_ids[:1].id
self.mode_company_id = False
self.category_id = False
elif self.holiday_type == 'company':
self.employee_id = False
if not self.mode_company_id:
self.mode_company_id = self.env.user.company_id.id
self.category_id = False
elif self.holiday_type == 'department':
if self.env.user.employee_ids:
self.department_id = self.department_id or self.env.user.employee_ids[0].department_id
self.employee_id = None
else:
self.employee_id = None
self.department_id = None
self.employee_id = False
self.mode_company_id = False
self.category_id = False
if not self.department_id:
self.department_id = self.env.user.employee_ids[:1].department_id.id
elif self.holiday_type == 'category':
self.employee_id = False
self.mode_company_id = False
self.department_id = False
@api.onchange('employee_id')
def _onchange_employee(self):
+19 -7
View File
@@ -172,10 +172,16 @@ class HolidaysType(models.Model):
for request in requests:
status_dict = result[request.holiday_status_id.id]
status_dict['virtual_remaining_leaves'] -= request.number_of_days
status_dict['virtual_remaining_leaves'] -= (request.number_of_hours_display
if request.leave_type_request_unit == 'hour'
else request.number_of_days)
if request.state == 'validate':
status_dict['leaves_taken'] += request.number_of_days
status_dict['remaining_leaves'] -= request.number_of_days
status_dict['leaves_taken'] += (request.number_of_hours_display
if request.leave_type_request_unit == 'hour'
else request.number_of_days)
status_dict['remaining_leaves'] -= (request.number_of_hours_display
if request.leave_type_request_unit == 'hour'
else request.number_of_days)
for allocation in allocations:
status_dict = result[allocation.holiday_status_id.id]
@@ -183,9 +189,15 @@ class HolidaysType(models.Model):
# note: add only validated allocation even for the virtual
# count; otherwise pending then refused allocation allow
# the employee to create more leaves than possible
status_dict['virtual_remaining_leaves'] += allocation.number_of_days
status_dict['max_leaves'] += allocation.number_of_days
status_dict['remaining_leaves'] += allocation.number_of_days
status_dict['virtual_remaining_leaves'] += (allocation.number_of_hours_display
if allocation.type_request_unit == 'hour'
else allocation.number_of_days)
status_dict['max_leaves'] += (allocation.number_of_hours_display
if allocation.type_request_unit == 'hour'
else allocation.number_of_days)
status_dict['remaining_leaves'] += (allocation.number_of_hours_display
if allocation.type_request_unit == 'hour'
else allocation.number_of_days)
return result
@@ -273,7 +285,7 @@ class HolidaysType(models.Model):
'count': _('%g remaining out of %g') % (
float_round(record.virtual_remaining_leaves, precision_digits=2) or 0.0,
float_round(record.max_leaves, precision_digits=2) or 0.0,
)
) + (_(' hours') if record.request_unit == 'hour' else _(' days'))
}
res.append((record.id, name))
return res
@@ -6,6 +6,7 @@ from dateutil.relativedelta import relativedelta
from odoo import fields
from odoo.exceptions import ValidationError
from odoo.tools import mute_logger
from odoo.tests.common import Form
from odoo.addons.hr_holidays.tests.common import TestHrHolidaysBase
@@ -150,3 +151,25 @@ class TestLeaveRequests(TestHrHolidaysBase):
'date_to': fields.Datetime.from_string('2017-07-11 19:00:00'),
'number_of_days': 1,
})
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
def test_department_leave(self):
""" Create a department leave """
self.employee_hrmanager.write({'department_id': self.hr_dept.id})
self.assertFalse(self.env['hr.leave'].search([('employee_id', 'in', self.hr_dept.member_ids.ids)]))
leave_form = Form(self.env['hr.leave'].sudo(self.user_hrmanager))
leave_form.holiday_status_id = self.holidays_type_1
leave_form.holiday_type = 'department'
leave_form.department_id = self.hr_dept
leave = leave_form.save()
leave.action_approve()
member_ids = self.hr_dept.member_ids.ids
self.assertEqual(self.env['hr.leave'].search_count([('employee_id', 'in', member_ids)]), len(member_ids), "Leave should be created for members of department")
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
def test_allocation_request(self):
""" Create an allocation request """
# employee should be set to current user
allocation_form = Form(self.env['hr.leave.allocation'].sudo(self.user_employee))
allocation_form.holiday_status_id = self.holidays_type_1
allocation = allocation_form.save()
@@ -175,7 +175,7 @@
<field name="department_id"/>
<field name="holiday_status_id"/>
<field name="name"/>
<field name="number_of_days" string="Allocated Days" sum="Total allocated days"/>
<field name="duration_display"/>
<field name="message_needaction" invisible="1"/>
<field name="state"/>
<button string="Approve" name="action_approve" type="object"
@@ -64,7 +64,7 @@
</field>
</record>
<record id="hr_employee_view_kanban" model="ir.ui.view">
<record id="hr_employee_view_kanban_inherit" model="ir.ui.view">
<field name="name">hr.employee</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.hr_kanban_view_employees"/>
+10 -5
View File
@@ -92,7 +92,7 @@ class Blackbox(Thread):
def _send_and_wait_for_ack(self, packet, serial):
ack = 0
MAX_RETRIES = 1
MAX_RETRIES = 1 # no more than 9
while ack != 0x06 and int(chr(packet[4])) < MAX_RETRIES:
serial.write(packet)
@@ -104,7 +104,7 @@ class Blackbox(Thread):
# message so it's safe to do it. Also it would be a pain
# to have to throw this all the way back to js just so it
# can increment the retry counter and then try again.
packet = packet[:4] + str(int(packet[4]) + 1) + packet[5:]
packet[4] += 1
if ack:
ack = ord(ack)
@@ -141,11 +141,11 @@ class Blackbox(Thread):
if stx == chr(0x02) and etx == chr(0x03) and bcc and self._lrc(response) == ord(bcc):
got_response = True
ser.write(chr(0x06))
ser.write(chr(0x06).encode())
else:
_logger.warning("received ACK but not a valid response, sending NACK...")
sent_nacks += 1
ser.write(chr(0x15))
ser.write(chr(0x15).encode())
if not got_response:
_logger.error("sent " + str(MAX_NACKS) + " NACKS without receiving response, giving up.")
@@ -173,4 +173,9 @@ if isfile("/home/pi/registered_blackbox_be"):
@http.route('/hw_proxy/request_serial/', type='json', auth='none', cors='*')
def request_serial(self):
return subprocess.check_output("ifconfig eth0 | grep 'ether.*' | sed 's/://g' | awk '{print $2}'", shell=True).rstrip()[-7:]
try:
with open('/sys/class/net/eth0/address', 'rb') as f:
return f.read().rstrip().replace(b':', b'')[-7:]
except IOError as e:
_logger.warning("eth0 network interface MAC address could not be found")
return b''
+7 -4
View File
@@ -9,7 +9,7 @@
function longpolling() {
$.ajax({
type: 'POST',
url: 'http://'+window.location.host+'/point_of_sale/get_serialized_order',
url: window.location.origin+'/point_of_sale/get_serialized_order',
dataType: 'json',
beforeSend: function(xhr){xhr.setRequestHeader('Content-Type', 'application/json');},
data: JSON.stringify({jsonrpc: '2.0'}),
@@ -47,14 +47,17 @@
foreign_js();
}
}
},
complete: function(jqXHR,err) {
if (!stop_longpolling) {
longpolling();
}
},
error: function (jqXHR, status, err) {
if (!stop_longpolling) {
setTimeout(longpolling, 5000);
}
},
timeout: 30000,
});
};
@@ -39,7 +39,7 @@ var WebsiteLivechatMessage = AbstractMessage.extend({
getAvatarSource: function () {
var source = this._serverURL;
if (this.hasAuthor()) {
source += '/web/image/res.partner/' + this.getAuthorID() + '/image_small?placeholder=user_placeholder.jpg';
source += '/web/partner_image/' + this.getAuthorID();
} else {
source += '/mail/static/src/img/smiley/avatar.jpg';
}
@@ -5,17 +5,61 @@
<field name="name">Tax 10%</field>
<field name="amount">10</field>
<field name="type_tax_use">sale</field>
<field name="account_id" ref="uae_account_3785"/>
<field name="refund_account_id" ref="uae_account_3785"/>
<field name="tax_group_id" ref="tax_group_15"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('uae_account_3785'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('uae_account_3785'),
}),
]"/>
</record>
<record id="purchase_tax_template" model="account.tax.template">
<field name="chart_template_id" ref="uae_chart_template_standard"/>
<field name="name">Purchase Tax 10%</field>
<field name="amount">10</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="uae_account_3726"/>
<field name="refund_account_id" ref="uae_account_3726"/>
<field name="tax_group_id" ref="tax_group_15"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('uae_account_3726'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('uae_account_3726'),
}),
]"/>
</record>
</odoo>
+1
View File
@@ -21,6 +21,7 @@ Plan contable argentino e impuestos de acuerdo a disposiciones vigentes
'data/account.account.template.csv',
'data/l10n_ar_chart_post_data.xml',
'data/account_data.xml',
'data/account_tax_report_data.xml',
'data/account_tax_data.xml',
'data/account_chart_template_data.xml',
],
+230 -187
View File
@@ -1,211 +1,254 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Account Tags -->
<record id="tag_ar_01" model="account.account.tag">
<field name="name">Base Imponible</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_02" model="account.account.tag">
<field name="name">Base Imponible - Ventas</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_03" model="account.account.tag">
<field name="name">Ventas Gravadas con IVA</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_04" model="account.account.tag">
<field name="name">Ventas NO Gravadas (Exoneradas)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_05" model="account.account.tag">
<field name="name">Ventas Gravadas Fuera de Ámbito</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_06" model="account.account.tag">
<field name="name">Base Imponible - Compras</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_07" model="account.account.tag">
<field name="name">Compras Gravadas con IVA</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_08" model="account.account.tag">
<field name="name">Compras NO Gravadas (Exoneradas)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_09" model="account.account.tag">
<field name="name">Compras Gravadas Fuera de Ámbito</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_10" model="account.account.tag">
<field name="name">Impuesto General a las Ventas (IVA) Total a Pagar</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_11" model="account.account.tag">
<field name="name">Impuesto Pagado</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_12" model="account.account.tag">
<field name="name">Impuesto Pagado IVA</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_13" model="account.account.tag">
<field name="name">Impuesto Pagado de Exonerados al IVA</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_14" model="account.account.tag">
<field name="name">Impuesto Pagado Fuera de Ámbito</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_15" model="account.account.tag">
<field name="name">Impuesto Cobrado</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_16" model="account.account.tag">
<field name="name">Impuesto Cobrado IVA</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_17" model="account.account.tag">
<field name="name">Impuesto Cobrado de Exonerados al IVA</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_18" model="account.account.tag">
<field name="name">Impuesto Cobrado Fuera de Ámbito</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_19" model="account.account.tag">
<field name="name">Impuesto Nacionales a Pagar</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_20" model="account.account.tag">
<field name="name">Impuesto a las Ganancias a Pagar</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_21" model="account.account.tag">
<field name="name">Impuesto a los Bienes Personales a Pagar</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_22" model="account.account.tag">
<field name="name">Impuesto a la Ganancia Mínima Presunta a Pagar</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_ar_23" model="account.account.tag">
<field name="name">Monotributo a Pagar</field>
<field name="applicability">taxes</field>
</record>
<record id="ITAX_21" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 21% Venta</field>
<field name="description">IVA 21%</field>
<field name="amount">21</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_03'), ref('tag_ar_16')])]"/>
<field name="tax_group_id" ref="tax_group_iva_21"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 21% Venta</field>
<field name="description">IVA 21%</field>
<field name="amount">21</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="tax_group_id" ref="tax_group_iva_21"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_base_imp_ventas_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_cobrado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_base_imp_ventas_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_cobrado_iva')],
}),
]"/>
</record>
<record id="OTAX_21" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 21% Compra</field>
<field name="description">IVA 21%</field>
<field name="amount">21</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_07'), ref('tag_ar_12')])]"/>
<field name="tax_group_id" ref="tax_group_iva_21"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 21% Compra</field>
<field name="description">IVA 21%</field>
<field name="amount">21</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="tax_group_id" ref="tax_group_iva_21"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_base_imp_compras_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_base_imp_compras_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
</record>
<record id="ITAX_27" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 27% Venta</field>
<field name="description">IVA 27%</field>
<field name="amount">27</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_16'), ref('tag_ar_03')])]"/>
<field name="tax_group_id" ref="tax_group_iva_27"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 27% Venta</field>
<field name="description">IVA 27%</field>
<field name="amount">27</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="tax_group_id" ref="tax_group_iva_27"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_base_imp_ventas_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_cobrado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_base_imp_ventas_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_cobrado_iva')],
}),
]"/>
</record>
<record id="OTAX_27" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 27% Compra</field>
<field name="description">IVA 27%</field>
<field name="amount">27</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_12'), ref('tag_ar_07')])]"/>
<field name="tax_group_id" ref="tax_group_iva_27"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 27% Compra</field>
<field name="description">IVA 27%</field>
<field name="amount">27</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="tax_group_id" ref="tax_group_iva_27"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_base_imp_compras_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_base_imp_compras_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
</record>
<record id="ITAX_105" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 10.5% Venta</field>
<field name="description">IVA 10.5%</field>
<field name="amount">10.5</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_16'), ref('tag_ar_03')])]"/>
<field name="tax_group_id" ref="tax_group_iva_105"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 10.5% Venta</field>
<field name="description">IVA 10.5%</field>
<field name="amount">10.5</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="tax_group_id" ref="tax_group_iva_105"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_base_imp_ventas_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_cobrado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_base_imp_ventas_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_cobrado_iva')],
}),
]"/>
</record>
<record id="OTAX_105" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 10.5% Compra</field>
<field name="description">IVA 10.5%</field>
<field name="amount">10.5</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_07'), ref('tag_ar_12')])]"/>
<field name="tax_group_id" ref="tax_group_iva_105"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">IVA 10.5% Compra</field>
<field name="description">IVA 10.5%</field>
<field name="amount">10.5</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="tax_group_id" ref="tax_group_iva_105"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_base_imp_compras_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_base_imp_compras_grav_iva')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
</record>
<record id="OTAX_02" model="account.tax.template">
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">Percepción IVA 2%</field>
<field name="description">Percepción IVA 2%</field>
<field name="amount">2.0</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="231"/>
<field name="account_id" ref="231"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_ar_12')])]"/>
<field name="tax_group_id" ref="tax_group_iva_2"/>
<field name="chart_template_id" ref="ar_chart_template"/>
<field name="name">Percepción IVA 2%</field>
<field name="description">Percepción IVA 2%</field>
<field name="amount">2.0</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="tax_group_id" ref="tax_group_iva_2"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'plus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('231'),
'minus_report_line_ids': [ref('tax_report_impuesto_gen_pagado_iva')],
}),
]"/>
</record>
</odoo>
@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="tax_report_base_imp" model="account.tax.report.line">
<field name="name">Base Imponible</field>
<field name="sequence" eval="1"/>
<field name="formula">base_ventas - base_compras</field>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_ventas" model="account.tax.report.line">
<field name="name">Base Imponible - Ventas</field>
<field name="code">base_ventas</field>
<field name="parent_id" ref='tax_report_base_imp'/>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_ventas_grav_iva" model="account.tax.report.line">
<field name="name">Ventas Gravadas con IVA</field>
<field name="tag_name">Ventas Gravadas con IVA</field>
<field name="parent_id" ref='tax_report_base_imp_ventas'/>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_ventas_no_grav" model="account.tax.report.line">
<field name="name">Ventas NO Gravadas (Exoneradas)</field>
<field name="tag_name">Ventas NO Gravadas (Exoneradas)</field>
<field name="parent_id" ref='tax_report_base_imp_ventas'/>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_ventas_grav_ambi" model="account.tax.report.line">
<field name="name">Ventas Gravadas Fuera de Ámbito</field>
<field name="tag_name">Ventas Gravadas Fuera de Ámbito</field>
<field name="parent_id" ref='tax_report_base_imp_ventas'/>
<field name="sequence" eval="3"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_compras" model="account.tax.report.line">
<field name="name">Base Imponible - Compras</field>
<field name="code">base_compras</field>
<field name="parent_id" ref='tax_report_base_imp'/>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_compras_grav_iva" model="account.tax.report.line">
<field name="name">Compras Gravadas con IVA</field>
<field name="tag_name">Compras Gravadas con IVA</field>
<field name="parent_id" ref='tax_report_base_imp_compras'/>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_compras_no_grav" model="account.tax.report.line">
<field name="name">Compras NO Gravadas (Exoneradas)</field>
<field name="tag_name">Compras NO Gravadas (Exoneradas)</field>
<field name="parent_id" ref='tax_report_base_imp_compras'/>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_base_imp_compras_grav_ambi" model="account.tax.report.line">
<field name="name">Compras Gravadas Fuera de Ámbito</field>
<field name="tag_name">Compras Gravadas Fuera de Ámbito</field>
<field name="parent_id" ref='tax_report_base_imp_compras'/>
<field name="sequence" eval="3"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen" model="account.tax.report.line">
<field name="name">Impuesto General a las Ventas (IVA) Total a Pagar</field>
<field name="formula">impuesto_pagado - impuesto_cobrado</field>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_pagado" model="account.tax.report.line">
<field name="name">Impuesto Pagado</field>
<field name="code">impuesto_pagado</field>
<field name="parent_id" ref="tax_report_impuesto_gen"/>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_pagado_iva" model="account.tax.report.line">
<field name="name">Impuesto Pagado IVA</field>
<field name="tag_name">Impuesto Pagado IVA</field>
<field name="parent_id" ref="tax_report_impuesto_gen_pagado"/>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_pagado_exo" model="account.tax.report.line">
<field name="name">Impuesto Pagado de Exonerados al IVA</field>
<field name="tag_name">Impuesto Pagado de Exonerados al IVA</field>
<field name="parent_id" ref="tax_report_impuesto_gen_pagado"/>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_pagado_ambi" model="account.tax.report.line">
<field name="name">Impuesto Pagado Fuera de Ámbito</field>
<field name="tag_name">Impuesto Pagado Fuera de Ámbito</field>
<field name="parent_id" ref="tax_report_impuesto_gen_pagado"/>
<field name="sequence" eval="3"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_cobrado" model="account.tax.report.line">
<field name="name">Impuesto Cobrado</field>
<field name="code">impuesto_cobrado</field>
<field name="parent_id" ref="tax_report_impuesto_gen"/>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_cobrado_iva" model="account.tax.report.line">
<field name="name">Impuesto Cobrado IVA</field>
<field name="tag_name">Impuesto Cobrado IVA</field>
<field name="parent_id" ref="tax_report_impuesto_gen_cobrado"/>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_cobrado_exo" model="account.tax.report.line">
<field name="name">Impuesto Cobrado de Exonerados al IVA</field>
<field name="tag_name">Impuesto Cobrado de Exonerados al IVA</field>
<field name="parent_id" ref="tax_report_impuesto_gen_cobrado"/>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_gen_cobrado_ambi" model="account.tax.report.line">
<field name="name">Impuesto Cobrado Fuera de Ámbito</field>
<field name="tag_name">Impuesto Cobrado Fuera de Ámbito</field>
<field name="parent_id" ref="tax_report_impuesto_gen_cobrado"/>
<field name="sequence" eval="3"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_nac" model="account.tax.report.line">
<field name="name">Impuesto Nacionales a Pagar</field>
<field name="sequence" eval="3"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_nac_ganancias" model="account.tax.report.line">
<field name="name">Impuesto a las Ganancias a Pagar</field>
<field name="formula">0</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_impuesto_nac"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_nac_bienes_perso" model="account.tax.report.line">
<field name="name">Impuesto a los Bienes Personales a Pagar</field>
<field name="formula">0</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_impuesto_nac"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_nac_minima_pres" model="account.tax.report.line">
<field name="name">Impuesto a la Ganancia Mínima Presunta a Pagar</field>
<field name="formula">0</field>
<field name="sequence" eval="3"/>
<field name="parent_id" ref="tax_report_impuesto_nac"/>
<field name="country_id" ref="base.ar"/>
</record>
<record id="tax_report_impuesto_nac_monotributo" model="account.tax.report.line">
<field name="name">Monotributo a Pagar</field>
<field name="formula">0</field>
<field name="sequence" eval="4"/>
<field name="parent_id" ref="tax_report_impuesto_nac"/>
<field name="country_id" ref="base.ar"/>
</record>
</odoo>
+1
View File
@@ -17,6 +17,7 @@ Please keep in mind that you should review and adapt it with your Accountant, be
""",
'data': ['data/l10n_at_chart_data.xml',
'data/account_data.xml',
'data/account_tax_report_data.xml',
'data/account_tax_data.xml',
'data/account_chart_template_data.xml'],
}
+366 -252
View File
@@ -1,143 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Account Tags -->
<record id="tag_at_01" model="account.account.tag">
<field name="name">UST Vorauszahlung / Überschuss - bitte dem Betrag ein Minuszeichen voranstellen</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_02" model="account.account.tag">
<field name="name">Steuern</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_03" model="account.account.tag">
<field name="name">Vorsteuer aus innergemeinschaftlichem Erwerb</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_04" model="account.account.tag">
<field name="name">Innergemeinschaftliche Erwerbe</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_05" model="account.account.tag">
<field name="name">Steuerpflichtige Umsätze (Lieferungen, sonstige Leistungen und Eigenverbrauch)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_06" model="account.account.tag">
<field name="name">zum Steuersatz von 20 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_07" model="account.account.tag">
<field name="name">BMGzum Steuersatz von 20 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_08" model="account.account.tag">
<field name="name">zum Steuersatz von 10 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_09" model="account.account.tag">
<field name="name">BMGzum Steuersatz von 10 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_10" model="account.account.tag">
<field name="name">Lieferungen, sonstige Leistungen und Eigenverbrauch</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_11" model="account.account.tag">
<field name="name">Steuerpflichtige Umsätze (Lieferungen, sonstige Leistungen und Eigenverbrauch)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_12" model="account.account.tag">
<field name="name">zum Steuersatz von 20 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_13" model="account.account.tag">
<field name="name">zum Steuersatz von 10%</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_14" model="account.account.tag">
<field name="name">Bemessungsgrundlage</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_15" model="account.account.tag">
<field name="name">Steuern</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_16" model="account.account.tag">
<field name="name">Lieferungen und sonstige Leistungen (einschließlich unentgeltlicher Wertabgaben)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_17" model="account.account.tag">
<field name="name">Steuerfreie Umsätze mit Vorsteuerabzug</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_18" model="account.account.tag">
<field name="name">§ 6 Abs. 1 Z 1 iVm § 7 (Ausfuhrlieferungen)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_19" model="account.account.tag">
<field name="name">Art. 6 Abs. 1 (Innergemeinschaftliche Lieferungen)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_20" model="account.account.tag">
<field name="name">Innergemeinschaftliche Erwerbe</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_21" model="account.account.tag">
<field name="name">Vorsteuer (dient lediglich der Verprobung)</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_22" model="account.account.tag">
<field name="name">Einfuhren</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_23" model="account.account.tag">
<field name="name">Einfuhren zum Steuersatz von 10 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_24" model="account.account.tag">
<field name="name">Einfuhren zum Steuersatz von 20 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_25" model="account.account.tag">
<field name="name">Rechnungen von anderen Unternehmern und innergemeinschaftliche Dreiecksgeschäfte</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_26" model="account.account.tag">
<field name="name">zum Steuersatz von 10 %</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_at_27" model="account.account.tag">
<field name="name">zum Steuersatz von 20 %</field>
<field name="applicability">taxes</field>
</record>
<!-- TAX TEMPLATES -->
<record id="tax_at_mwst_20" model="account.tax.template">
@@ -146,101 +8,216 @@
<field name="description">20% MwSt</field>
<field name="amount">20.0</field>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="chart3500"/>
<field name="account_id" ref="chart3500"/>
<field name="type_tax_use">sale</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_27'), ref('tag_at_12')])]"/>
<field name="tax_group_id" ref="tax_group_20"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_20')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_20')],
}),
]"/>
</record>
<record id="tax_at_mwst_10" model="account.tax.template">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Mehrwertsteuer 10%</field>
<field name="description">10% MwSt</field>
<field name="amount">10.0</field>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="chart3500"/>
<field name="account_id" ref="chart3500"/>
<field name="type_tax_use">sale</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_26'), ref('tag_at_13')])]"/>
<field name="tax_group_id" ref="tax_group_10"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_10')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_10')],
}),
]"/>
</record>
<record id="tax_at_vst_20" model="account.tax.template">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Vorsteuer 20%</field>
<field name="description">20% VSt</field>
<field name="amount">20.0</field>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="chart2500"/>
<field name="account_id" ref="chart2500"/>
<field name="type_tax_use">purchase</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_27'), ref('tag_at_07') ,ref('tag_at_06'), ref('tag_at_03')])]"/>
<field name="tax_group_id" ref="tax_group_20"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_20')],
'plus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2500'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_20')],
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_20')],
'minus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2500'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_20')],
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
]"/>
</record>
<record id="tax_at_vst_10" model="account.tax.template">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Vorsteuer 10%</field>
<field name="description">10% VSt</field>
<field name="amount">10.00</field>
<field name="amount_type">percent</field>
<field name="refund_account_id" ref="chart2500"/>
<field name="account_id" ref="chart2500"/>
<field name="type_tax_use">purchase</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_09'), ref('tag_at_03'), ref('tag_at_08')])]"/>
<field name="tax_group_id" ref="tax_group_10"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2500'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_10')],
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2500'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_10')],
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
]"/>
</record>
<record model="account.tax.template" id="tax_import_20">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">20% Einfuhrumsatzsteuer</field>
<field name="description">20% EUSt</field>
<field name="amount_type">percent</field>
<field name="amount">20.00</field>
<field name="account_id" ref="chart2510"/>
<field name="refund_account_id" ref="chart2510"/>
<field name="type_tax_use">purchase</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_24')])]"/>
<field name="tax_group_id" ref="tax_group_20"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_vorst_einfuhren_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2510'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_vorst_einfuhren_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2510'),
}),
]"/>
</record>
<record model="account.tax.template" id="tax_import_10">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">10% Einfuhrumsatzsteuer</field>
<field name="description">10% EUSt</field>
<field name="amount_type">percent</field>
<field name="amount">10</field>
<field name="account_id" ref="chart2510"/>
<field name="refund_account_id" ref="chart2510"/>
<field name="type_tax_use">purchase</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_23')])]"/>
<field name="tax_group_id" ref="tax_group_10"/>
</record>
<record model="account.tax.template" id="tax_eu_20_purchase_ust">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">20% Umsatzsteuer aus innergem. Erwerb</field>
<field name="description">20% USt</field>
<field name="amount_type">percent</field>
<field name="amount">-20.0</field>
<field name="account_id" ref="chart3501"/>
<field name="refund_account_id" ref="chart3501"/>
<field name="type_tax_use">none</field>
<field name="tax_group_id" ref="tax_group_20"/>
</record>
<record model="account.tax.template" id="tax_eu_20_purchase_vst">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">20% Vorsteuer aus innergem. Erwerb</field>
<field name="description">20% VSt</field>
<field name="amount_type">percent</field>
<field name="amount">20.0</field>
<field name="account_id" ref="chart2501"/>
<field name="refund_account_id" ref="chart2501"/>
<field name="type_tax_use">none</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_27'), ref('tag_at_07'), ref('tag_at_06'), ref('tag_at_03')])]"/>
<field name="tax_group_id" ref="tax_group_0"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_vorst_einfuhren_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2510'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_vorst_einfuhren_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2510'),
}),
]"/>
</record>
<record model="account.tax.template" id="tax_eu_20_purchase">
@@ -248,62 +225,134 @@
<field name="name">Innergem. Erwerb 20%USt/20%VSt</field>
<field name="description">innergem. Erwerb 20%</field>
<field name="amount_type">percent</field>
<field name="amount">0.0</field>
<field name="amount">20.0</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">group</field>
<field name="children_tax_ids" eval="[(6, 0, [ref('tax_eu_20_purchase_ust'), ref('tax_eu_20_purchase_vst')])]"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_07')])]"/>
<field name="tax_group_id" ref="tax_group_0"/>
</record>
<record model="account.tax.template" id="tax_eu_10_purchase_ust">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">10% Umsatzsteuer aus innergem. Erwerb</field>
<field name="description">10% USt</field>
<field name="amount_type">percent</field>
<field name="amount">-10.0</field>
<field name="account_id" ref="chart3503"/>
<field name="refund_account_id" ref="chart3503"/>
<field name="type_tax_use">none</field>
<field name="tax_group_id" ref="tax_group_10"/>
</record>
<record model="account.tax.template" id="tax_eu_10_purchase_vst">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">10% Vorsteuer aus innergem. Erwerb</field>
<field name="description">10% VSt</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="account_id" ref="chart2503"/>
<field name="refund_account_id" ref="chart2503"/>
<field name="type_tax_use">none</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_09'), ref('tag_at_03'), ref('tag_at_08')])]"/>
<field name="tax_group_id" ref="tax_group_0"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_20')],
'plus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2501'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_20')],
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
(0,0, {
'factor_percent': -100,
'repartition_type': 'tax',
'account_id': ref('chart3501'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_20')],
'minus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2501'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_20')],
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
(0,0, {
'factor_percent': -100,
'repartition_type': 'tax',
'account_id': ref('chart3501'),
}),
]"/>
</record>
<record model="account.tax.template" id="tax_eu_10_purchase">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Innergem. Erwerb 10%USt/10%VSt</field>
<field name="description">innergem. Erwerb 10%</field>
<field name="amount">0.0</field>
<field name="amount_type">group</field>
<field name="amount">10.0</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="children_tax_ids" eval="[(6, 0, [ref('tax_eu_10_purchase_ust'), ref('tax_eu_10_purchase_vst')])]"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_09')])]"/>
<field name="tax_group_id" ref="tax_group_0"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2503'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_10')],
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
(0,0, {
'factor_percent': -100,
'repartition_type': 'tax',
'account_id': ref('chart3503'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_bmg_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart2503'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_steu_10')],
'plus_report_line_ids': [ref('tax_report_ust_steuern_innergemeinschaft_vorsteuer')],
}),
(0,0, {
'factor_percent': -100,
'repartition_type': 'tax',
'account_id': ref('chart3503'),
}),
]"/>
</record>
<record model="account.tax.template" id="tax_at_mwst_20_eu">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">20% Umsatzsteuer EU Lieferung</field>
<field name="description">20% USt EU</field>
<field name="amount_type">percent</field>
<field name="amount">20.0</field>
<field name="account_id" ref="chart3510"/>
<field name="refund_account_id" ref="chart3510"/>
<field name="type_tax_use">sale</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_27'), ref('tag_at_12')])]"/>
<field name="tax_group_id" ref="tax_group_20"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3510'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_20')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_20')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3510'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_20')],
}),
]"/>
</record>
<record model="account.tax.template" id="tax_at_mwst_10_eu">
@@ -312,24 +361,68 @@
<field name="description">10% USt EU</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="account_id" ref="chart3511"/>
<field name="refund_account_id" ref="chart3511"/>
<field name="type_tax_use">sale</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_26'), ref('tag_at_13')])]"/>
<field name="tax_group_id" ref="tax_group_10"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3511'),
'plus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_10')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_vorst_rechnungen_10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3511'),
'minus_report_line_ids': [ref('tax_report_ust_steuern_lief_steu_10')],
}),
]"/>
</record>
<record model="account.tax.template" id="tax_eu_sale_at">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Steuerfreie innergem. Lieferung</field>
<field name="description">strf. i.g.L</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="account_id" ref="chart3500"/>
<field name="refund_account_id" ref="chart3500"/>
<field name="type_tax_use">sale</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_19')])]"/>
<field name="tax_group_id" ref="tax_group_0"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_steuern_lief_steuerfreie_inn')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_steuern_lief_steuerfreie_inn')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
}),
]"/>
</record>
<record model="account.tax.template" id="tax_export_at">
@@ -338,21 +431,42 @@
<field name="description">steuerfreie Ausfuhr</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="account_id" ref="chart3500"/>
<field name="refund_account_id" ref="chart3500"/>
<field name="type_tax_use">sale</field>
<field name="tag_ids" eval="[(6,0,[ref('tag_at_18')])]"/>
<field name="tax_group_id" ref="tax_group_0"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('tax_report_bemess_steuern_lief_steuerfreie_ausf')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('tax_report_bemess_steuern_lief_steuerfreie_ausf')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('chart3500'),
}),
]"/>
</record>
<!-- LIEFERANT EU UNTERNEHMEN OHNE UID -->
<!-- LIEFERANT EU UNTERNEHMEN OHNE UID -->
<!-- Fiscal Position Templates -->
<record model="account.fiscal.position.template" id="fiscal_position_eu_no_id_purchase_at">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Lieferant EU (ohne Ust-ID)</field>
</record>
<!-- Fiscal Position Tax Templates -->
<!-- Fiscal Position Tax Templates -->
<record id="account_fiscal_position_tax_eu_no_id_purchase_20" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_eu_no_id_purchase_at"/>
<field name="tax_dest_id" ref="tax_import_20"/>
@@ -373,18 +487,18 @@
<field name="position_id" ref="fiscal_position_eu_no_id_purchase_at"/>
<field name="account_src_id" ref="chart5001" />
<field name="account_dest_id" ref="chart5020" />
</record>
<!-- LIEFERANT EU UNTERNEHMEN OHNE UID -->
</record>
<!-- LIEFERANT EU UNTERNEHMEN OHNE UID -->
<!-- LIEFERANT EU UNTERNEHMEN MIT UID -->
<!-- Fiscal Position Templates -->
<!-- Fiscal Position Templates -->
<record model="account.fiscal.position.template" id="fiscal_position_eu_vat_id_purchase_at">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Lieferant EU Unternehmen (mit USt-ID)</field>
</record>
<!-- Fiscal Position Tax Templates -->
<!-- Fiscal Position Tax Templates -->
<record id="account_fiscal_position_tax_eu_vat_id_purchase_20" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_eu_vat_id_purchase_at"/>
<field name="tax_dest_id" ref="tax_eu_20_purchase"/>
@@ -406,11 +520,11 @@
<field name="account_src_id" ref="chart5001" />
<field name="account_dest_id" ref="chart5010" />
</record>
<!-- LIEFERANT EU UNTERNEHMEN MIT UID -->
<!-- LIEFERANT EU UNTERNEHMEN MIT UID -->
<!-- LIEFERANT AUSLAND -->
<!-- Fiscal Position Templates -->
<!-- Fiscal Position Templates -->
<record model="account.fiscal.position.template" id="fiscal_position_non_eu_purchase_at">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Lieferant Ausland</field>
@@ -437,13 +551,13 @@
<field name="account_src_id" ref="chart5001" />
<field name="account_dest_id" ref="chart5020" />
</record>
<!-- LIEFERANT AUSLAND -->
<!-- LIEFERANT AUSLAND -->
<!-- KUNDE EU UNTERNEHMEN OHNE UID -->
<!-- Fiscal Position Templates -->
<!-- KUNDE EU UNTERNEHMEN OHNE UID -->
<!-- Fiscal Position Templates -->
<record model="account.fiscal.position.template" id="fiscal_position_eu_no_id_sale_at">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Kunde EU (ohne USt-ID)</field>
@@ -470,11 +584,11 @@
<field name="account_src_id" ref="chart4010" />
<field name="account_dest_id" ref="chart4020" />
</record>
<!-- KUNDE EU UNTERNEHMEN OHNE UID -->
<!-- KUNDE EU UNTERNEHMEN OHNE UID -->
<!-- KUNDE EU UNTERNEHMEN MIT UID -->
<!-- KUNDE EU UNTERNEHMEN MIT UID -->
<!-- Fiscal Position Templates -->
<record model="account.fiscal.position.template" id="fiscal_position_eu_vat_id_sale_at">
<field name="chart_template_id" ref="austria_chart_template"/>
@@ -506,7 +620,7 @@
<!-- KUNDE AUSLAND -->
<!-- KUNDE AUSLAND -->
<record model="account.fiscal.position.template" id="fiscal_position_non_eu_sale_at">
<field name="chart_template_id" ref="austria_chart_template"/>
<field name="name">Kunde Ausland</field>
@@ -532,6 +646,6 @@
<field name="position_id" ref="fiscal_position_non_eu_sale_at"/>
<field name="account_src_id" ref="chart4010" />
<field name="account_dest_id" ref="chart4050" />
</record>
<!-- KUNDE AUSLAND -->
</record>
<!-- KUNDE AUSLAND -->
</odoo>
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="tax_report_bemess" model="account.tax.report.line">
<field name="name">Bemessungsgrundlage</field>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst" model="account.tax.report.line">
<field name="name">Vorsteuer (dient lediglich der Verprobung)</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_bemess"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst_einfuhren" model="account.tax.report.line">
<field name="name">Einfuhren</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_bemess_vorst"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst_einfuhren_10" model="account.tax.report.line">
<field name="name">Einfuhren zum Steuersatz von 10 %</field>
<field name="tag_name">Einfuhren zum Steuersatz von 10 %</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_bemess_vorst_einfuhren"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst_einfuhren_20" model="account.tax.report.line">
<field name="name">Einfuhren zum Steuersatz von 20 %</field>
<field name="tag_name">Einfuhren zum Steuersatz von 20 %</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_bemess_vorst_einfuhren"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst_rechnungen" model="account.tax.report.line">
<field name="name">Rechnungen von anderen Unternehmern und innergemeinschaftliche Dreiecksgeschäfte</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_bemess_vorst"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst_rechnungen_10" model="account.tax.report.line">
<field name="name">zum Steuersatz von 10 %</field>
<field name="tag_name">zum Steuersatz von 10 %</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_bemess_vorst_rechnungen"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_vorst_rechnungen_20" model="account.tax.report.line">
<field name="name">zum Steuersatz von 20 %</field>
<field name="tag_name">zum Steuersatz von 20 %</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_bemess_vorst_rechnungen"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_steuern" model="account.tax.report.line">
<field name="name">Steuern</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_bemess"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_steuern_lief" model="account.tax.report.line">
<field name="name">Lieferungen und sonstige Leistungen (einschließlich unentgeltlicher Wertabgaben)</field>
<field name="sequence" eval="3"/>
<field name="parent_id" ref="tax_report_bemess_steuern"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_steuern_lief_steuerfreie" model="account.tax.report.line">
<field name="name">Steuerfreie Umsätze mit Vorsteuerabzug</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_bemess_steuern_lief"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_steuern_lief_steuerfreie_ausf" model="account.tax.report.line">
<field name="name">§ 6 Abs. 1 Z 1 iVm § 7 (Ausfuhrlieferungen)</field>
<field name="tag_name">§ 6 Abs. 1 Z 1 iVm § 7 (Ausfuhrlieferungen)</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_bemess_steuern_lief_steuerfreie"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_steuern_lief_steuerfreie_inn" model="account.tax.report.line">
<field name="name">Art. 6 Abs. 1 (Innergemeinschaftliche Lieferungen)</field>
<field name="tag_name">Art. 6 Abs. 1 (Innergemeinschaftliche Lieferungen)</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_bemess_steuern_lief_steuerfreie"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_bemess_steuern_lief_innergemeinschaf" model="account.tax.report.line">
<field name="name">Innergemeinschaftliche Erwerbe</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_bemess_steuern_lief"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust" model="account.tax.report.line">
<field name="name">UST Vorauszahlung / Überschuss - bitte dem Betrag ein Minuszeichen voranstellen</field>
<field name="code">toto</field>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern" model="account.tax.report.line">
<field name="name">Steuern</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_lief" model="account.tax.report.line">
<field name="name">Lieferungen, sonstige Leistungen und Eigenverbrauch</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust_steuern"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_lief_steu" model="account.tax.report.line">
<field name="name">Steuerpflichtige Umsätze (Lieferungen, sonstige Leistungen und Eigenverbrauch)</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust_steuern_lief"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_lief_steu_20" model="account.tax.report.line">
<field name="name">zum Steuersatz von 20 %</field>
<field name="tag_name">zum Steuersatz von 20 %</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust_steuern_lief_steu"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_lief_steu_10" model="account.tax.report.line">
<field name="name">zum Steuersatz von 10%</field>
<field name="tag_name">zum Steuersatz von 10%</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_ust_steuern_lief_steu"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft" model="account.tax.report.line">
<field name="name">Innergemeinschaftliche Erwerbe</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_ust_steuern"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft_steu" model="account.tax.report.line">
<field name="name">Steuerpflichtige Umsätze (Lieferungen, sonstige Leistungen und Eigenverbrauch)</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust_steuern_innergemeinschaft"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft_steu_20" model="account.tax.report.line">
<field name="name">zum Steuersatz von 20 %</field>
<field name="tag_name">zum Steuersatz von 20 %</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust_steuern_innergemeinschaft_steu"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft_steu_bmg_20" model="account.tax.report.line">
<field name="name">BMGzum Steuersatz von 20 %</field>
<field name="tag_name">BMGzum Steuersatz von 20 %</field>
<field name="sequence" eval="1"/>
<field name="parent_id" ref="tax_report_ust_steuern_innergemeinschaft_steu"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft_steu_10" model="account.tax.report.line">
<field name="name">zum Steuersatz von 10 %</field>
<field name="tag_name">zum Steuersatz von 10 %</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_ust_steuern_innergemeinschaft_steu"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft_steu_bmg_10" model="account.tax.report.line">
<field name="name">BMGzum Steuersatz von 10 %</field>
<field name="tag_name">BMGzum Steuersatz von 10 %</field>
<field name="sequence" eval="2"/>
<field name="parent_id" ref="tax_report_ust_steuern_innergemeinschaft_steu"/>
<field name="country_id" ref="base.at"/>
</record>
<record id="tax_report_ust_steuern_innergemeinschaft_vorsteuer" model="account.tax.report.line">
<field name="name">Vorsteuer aus innergemeinschaftlichem Erwerb</field>
<field name="tag_name">Vorsteuer aus innergemeinschaftlichem Erwerb</field>
<field name="sequence" eval="3"/>
<field name="parent_id" ref="tax_report_ust_steuern"/>
<field name="country_id" ref="base.at"/>
</record>
</odoo>
+2 -2
View File
@@ -24,9 +24,9 @@ Also:
'data/l10n_au_chart_data.xml',
'data/account.account.template.csv',
'data/account_chart_template_data.xml',
'data/account.account.tag.csv',
'data/account_tax_report_data.xml',
'data/account.tax.group.csv',
'data/account.tax.template.csv',
'data/account_tax_template_data.xml',
'data/account_fiscal_position_tax_template_data.xml',
'data/account_chart_template_configure_data.xml',
'data/res_currency_data.xml',
@@ -1,16 +0,0 @@
id,name,applicability
tag_au_tax_sale_10,Taxable Sales Ex-GST,taxes
tag_au_tax_sale_inc_10,Taxable Sales Inc-GST,taxes
tag_au_tax_sale_0,Tax Exclusive Sales,taxes
tag_au_tax_sale_exempt,Tax Exempt Sales,taxes
tag_au_tax_sale_input,Input Taxed Sales,taxes
tag_au_tax_sale_adj,Adjustments (Sales),taxes
tag_au_tax_purchase_10,Taxable Purchases Ex-GST,taxes
tag_au_tax_purchase_inc_10,Taxable Purchases Inc-GST,taxes
tag_au_tax_purchase_capital,Capital Purchases Ex-GST,taxes
tag_au_tax_purchase_0,Tax Exempt Purchases,taxes
tag_au_tax_purchase_taxable_import,Taxable Import without GST,taxes
tag_au_tax_purchase_input,Purchases for Input Taxed Sales,taxes
tag_au_tax_purchase_private,Purchases for Private Use,taxes
tag_au_tax_purchase_gst_only,GST Payment for Taxable Imports,taxes
tag_au_tax_purchase_adj,Adjustments (Purchases),taxes
1 id name applicability
2 tag_au_tax_sale_10 Taxable Sales Ex-GST taxes
3 tag_au_tax_sale_inc_10 Taxable Sales Inc-GST taxes
4 tag_au_tax_sale_0 Tax Exclusive Sales taxes
5 tag_au_tax_sale_exempt Tax Exempt Sales taxes
6 tag_au_tax_sale_input Input Taxed Sales taxes
7 tag_au_tax_sale_adj Adjustments (Sales) taxes
8 tag_au_tax_purchase_10 Taxable Purchases Ex-GST taxes
9 tag_au_tax_purchase_inc_10 Taxable Purchases Inc-GST taxes
10 tag_au_tax_purchase_capital Capital Purchases Ex-GST taxes
11 tag_au_tax_purchase_0 Tax Exempt Purchases taxes
12 tag_au_tax_purchase_taxable_import Taxable Import without GST taxes
13 tag_au_tax_purchase_input Purchases for Input Taxed Sales taxes
14 tag_au_tax_purchase_private Purchases for Private Use taxes
15 tag_au_tax_purchase_gst_only GST Payment for Taxable Imports taxes
16 tag_au_tax_purchase_adj Adjustments (Purchases) taxes
@@ -1,16 +0,0 @@
id,chart_template_id:id,name,sequence,description,type_tax_use,amount_type,amount,price_include,account_id:id,refund_account_id:id,tag_ids:id,tax_group_id:id
au_tax_sale_10,l10n_au_chart_template,Sale (10%),1,GST Sales,sale,percent,10,FALSE,au_21310,au_21310,tag_au_tax_sale_10,tax_group_gst_10
au_tax_sale_inc_10,l10n_au_chart_template,GST Inc Sale (10%),2,GST Inclusive Sales,sale,percent,10,TRUE,au_21310,au_21310,tag_au_tax_sale_inc_10,tax_group_gst_10
au_tax_sale_0,l10n_au_chart_template,Zero (Export) Sale,3,Zero Rated (Export) Sales,sale,percent,0,FALSE,,,tag_au_tax_sale_0,tax_group_gst_0
au_tax_sale_exempt,l10n_au_chart_template,Exempt Sale,4,Exempt Sales,sale,percent,0,FALSE,,,tag_au_tax_sale_exempt,tax_group_gst_0
au_tax_sale_input,l10n_au_chart_template,Input Taxed,5,Input Taxed Sales,sale,percent,0,FALSE,,,tag_au_tax_sale_input,tax_group_gst_0
au_tax_sale_adj,l10n_au_chart_template,Sale Adj (10%),6,Tax Adjustments (Sales),sale,percent,10,FALSE,au_21310,au_21310,tag_au_tax_sale_adj,tax_group_gst_10
au_tax_purchase_10,l10n_au_chart_template,Purch (10%),1,GST Purchases,purchase,percent,10,FALSE,au_21330,au_21330,tag_au_tax_purchase_10,tax_group_gst_10
au_tax_purchase_inc_10,l10n_au_chart_template,GST Inc Purch (10%),2,GST Inclusive Purchases,purchase,percent,10,TRUE,au_21330,au_21330,tag_au_tax_purchase_inc_10,tax_group_gst_10
au_tax_purchase_capital,l10n_au_chart_template,Capital (10.0%),3,Capital Purchases,purchase,percent,10,FALSE,au_21330,au_21330,tag_au_tax_purchase_capital,tax_group_gst_10
au_tax_purchase_0,l10n_au_chart_template,Zero Rated Purch,4,Zero Rated Purchases,purchase,percent,0,FALSE,,,tag_au_tax_purchase_0,tax_group_gst_0
au_tax_purchase_taxable_import,l10n_au_chart_template,Purch (Taxable Imports),5,Purchase (Taxable Imports) - Tax Paid Separately,purchase,percent,0,FALSE,,,tag_au_tax_purchase_taxable_import,tax_group_gst_0
au_tax_purchase_input,l10n_au_chart_template,Purch for Input Sales,6,Purchases for Input Taxed Sales,purchase,percent,10,FALSE,,,tag_au_tax_purchase_input,tax_group_gst_10
au_tax_purchase_private,l10n_au_chart_template,Purch Private (10%) ,7,Purchases for Private use or not deductible,purchase,percent,10,FALSE,,,tag_au_tax_purchase_private,tax_group_gst_10
au_tax_purchase_gst_only,l10n_au_chart_template,GST Only on Imports,8,GST Only on Imports,purchase,percent,100000000,TRUE,au_21330,au_21330,tag_au_tax_purchase_gst_only,tax_group_gst_100000000
au_tax_purchase_adj,l10n_au_chart_template,Purch Adj (10%),9,Tax Adjustments (Purchases),purchase,percent,10,FALSE,au_21330,au_21330,tag_au_tax_purchase_adj,tax_group_gst_10
1 id chart_template_id:id name sequence description type_tax_use amount_type amount price_include account_id:id refund_account_id:id tag_ids:id tax_group_id:id
2 au_tax_sale_10 l10n_au_chart_template Sale (10%) 1 GST Sales sale percent 10 FALSE au_21310 au_21310 tag_au_tax_sale_10 tax_group_gst_10
3 au_tax_sale_inc_10 l10n_au_chart_template GST Inc Sale (10%) 2 GST Inclusive Sales sale percent 10 TRUE au_21310 au_21310 tag_au_tax_sale_inc_10 tax_group_gst_10
4 au_tax_sale_0 l10n_au_chart_template Zero (Export) Sale 3 Zero Rated (Export) Sales sale percent 0 FALSE tag_au_tax_sale_0 tax_group_gst_0
5 au_tax_sale_exempt l10n_au_chart_template Exempt Sale 4 Exempt Sales sale percent 0 FALSE tag_au_tax_sale_exempt tax_group_gst_0
6 au_tax_sale_input l10n_au_chart_template Input Taxed 5 Input Taxed Sales sale percent 0 FALSE tag_au_tax_sale_input tax_group_gst_0
7 au_tax_sale_adj l10n_au_chart_template Sale Adj (10%) 6 Tax Adjustments (Sales) sale percent 10 FALSE au_21310 au_21310 tag_au_tax_sale_adj tax_group_gst_10
8 au_tax_purchase_10 l10n_au_chart_template Purch (10%) 1 GST Purchases purchase percent 10 FALSE au_21330 au_21330 tag_au_tax_purchase_10 tax_group_gst_10
9 au_tax_purchase_inc_10 l10n_au_chart_template GST Inc Purch (10%) 2 GST Inclusive Purchases purchase percent 10 TRUE au_21330 au_21330 tag_au_tax_purchase_inc_10 tax_group_gst_10
10 au_tax_purchase_capital l10n_au_chart_template Capital (10.0%) 3 Capital Purchases purchase percent 10 FALSE au_21330 au_21330 tag_au_tax_purchase_capital tax_group_gst_10
11 au_tax_purchase_0 l10n_au_chart_template Zero Rated Purch 4 Zero Rated Purchases purchase percent 0 FALSE tag_au_tax_purchase_0 tax_group_gst_0
12 au_tax_purchase_taxable_import l10n_au_chart_template Purch (Taxable Imports) 5 Purchase (Taxable Imports) - Tax Paid Separately purchase percent 0 FALSE tag_au_tax_purchase_taxable_import tax_group_gst_0
13 au_tax_purchase_input l10n_au_chart_template Purch for Input Sales 6 Purchases for Input Taxed Sales purchase percent 10 FALSE tag_au_tax_purchase_input tax_group_gst_10
14 au_tax_purchase_private l10n_au_chart_template Purch Private (10%) 7 Purchases for Private use or not deductible purchase percent 10 FALSE tag_au_tax_purchase_private tax_group_gst_10
15 au_tax_purchase_gst_only l10n_au_chart_template GST Only on Imports 8 GST Only on Imports purchase percent 100000000 TRUE au_21330 au_21330 tag_au_tax_purchase_gst_only tax_group_gst_100000000
16 au_tax_purchase_adj l10n_au_chart_template Purch Adj (10%) 9 Tax Adjustments (Purchases) purchase percent 10 FALSE au_21330 au_21330 tag_au_tax_purchase_adj tax_group_gst_10
@@ -0,0 +1,228 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_tax_report_gstrpt_sale_total" model="account.tax.report.line">
<field name="name">GST amounts you owe the Tax Office from sales</field>
<field name="sequence" eval="1"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g1" model="account.tax.report.line">
<field name="name">G1: Total Sales (including any GST)</field>
<field name="tag_name">G1</field>
<field name="code">G1</field>
<field name="sequence" eval="2"/>
<field name="country_id" ref="base.au"/>
<field name="parent_id" ref="account_tax_report_gstrpt_sale_total"/>
</record>
<record id="account_tax_report_gstrpt_g2" model="account.tax.report.line">
<field name="name">G2: Export sales</field>
<field name="tag_name">G2</field>
<field name="code">G2</field>
<field name="sequence" eval="3"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g1"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g3" model="account.tax.report.line">
<field name="name">G3: Other GST-free sales</field>
<field name="tag_name">G3</field>
<field name="code">G3</field>
<field name="sequence" eval="4"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g1"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g4" model="account.tax.report.line">
<field name="name">G4: Input taxed sales</field>
<field name="tag_name">G4</field>
<field name="code">G4</field>
<field name="sequence" eval="5"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g1"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g5" model="account.tax.report.line">
<field name="name">G5: G2 + G3 + G4</field>
<field name="formula">G2+G3+G4</field>
<field name="sequence" eval="6"/>
<field name="country_id" ref="base.au"/>
<field name="parent_id" ref="account_tax_report_gstrpt_sale_total"/>
</record>
<record id="account_tax_report_gstrpt_g6" model="account.tax.report.line">
<field name="name">G6: Total sales subject to GST (G1 minus G5)</field>
<field name="sequence" eval="7"/>
<field name="formula">G1-(G2+G3+G4)</field>
<field name="parent_id" ref="account_tax_report_gstrpt_sale_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g7" model="account.tax.report.line">
<field name="name">G7: Adjustments (if applicable)</field>
<field name="tag_name">G7</field>
<field name="code">G7</field>
<field name="sequence" eval="8"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g6"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g8" model="account.tax.report.line">
<field name="name">G8: Total sales subject to GST after adjustments (G6 + G7)</field>
<field name="sequence" eval="9"/>
<field name="formula">(G1-(G2+G3+G4))+G7</field>
<field name="parent_id" ref="account_tax_report_gstrpt_sale_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g9" model="account.tax.report.line">
<field name="name">G9: GST on sales (G8 divided by eleven)</field>
<field name="sequence" eval="10"/>
<field name="formula">((G1-(G2+G3+G4))+G7)/11</field>
<field name="parent_id" ref="account_tax_report_gstrpt_sale_total"/>
<field name="country_id" ref="base.au"/>
</record>
<!-- Purchase Report -->
<record id="account_tax_report_gstrpt_purchase_total" model="account.tax.report.line">
<field name="name">GST amounts the Tax Office owes you from purchases</field>
<field name="sequence" eval="101"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g10" model="account.tax.report.line">
<field name="name">G10: Capital purchases (including any GST)</field>
<field name="tag_name">G10</field>
<field name="code">G10</field>
<field name="sequence" eval="102"/>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g11" model="account.tax.report.line">
<field name="name">G11: Non-capital purchases (including GST)</field>
<field name="tag_name">G11</field>
<field name="code">G11</field>
<field name="sequence" eval="103"/>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g12" model="account.tax.report.line">
<field name="name">G12: G10 + G11</field>
<field name="sequence" eval="104"/>
<field name="formula">G10+G11</field>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g13" model="account.tax.report.line">
<field name="name">G13: Purchases for making input taxed sales</field>
<field name="tag_name">G13</field>
<field name="code">G13</field>
<field name="sequence" eval="105"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g12"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g14" model="account.tax.report.line">
<field name="name">G14: Purchases without GST in the price</field>
<field name="tag_name">G14</field>
<field name="code">G14</field>
<field name="sequence" eval="106"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g12"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g15" model="account.tax.report.line">
<field name="name">G15: Estimated purchases for private use or not income tax deductible</field>
<field name="tag_name">G15</field>
<field name="code">G15</field>
<field name="sequence" eval="107"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g12"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g16" model="account.tax.report.line">
<field name="name">G16: G13 + G14 + G15</field>
<field name="sequence" eval="108"/>
<field name="formula">G13+G14+G15</field>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g17" model="account.tax.report.line">
<field name="name">G17: Total purchases subject to GST (G12 minus G16) </field>
<field name="sequence" eval="109"/>
<field name="formula">(G10+G11)-(G13+G14+G15)</field>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g18" model="account.tax.report.line">
<field name="name">G18: Adjustments (if applicable)</field>
<field name="tag_name">G18</field>
<field name="code">G18</field>
<field name="sequence" eval="110"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g17"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g19" model="account.tax.report.line">
<field name="name">G19: Total purchases subject to GST after adjustments (G17 + G18) </field>
<field name="sequence" eval="111"/>
<field name="formula">(G10+G11)-(G13+G14+G15)+G18</field>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g20a" model="account.tax.report.line">
<field name="name">GST on purchases (G19 divided by eleven)</field>
<field name="formula">((G10+G11)-(G13+G14+G15)+G18)/11</field>
<field name="sequence" eval="112"/>
<field name="parent_id" ref="account_tax_report_gstrpt_purchase_total"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_gstonly" model="account.tax.report.line">
<field name="name">GST only purchases</field>
<field name="tag_name">ONLY</field>
<field name="code">ONLY</field>
<field name="sequence" eval="113"/>
<field name="parent_id" ref="account_tax_report_gstrpt_g20a"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_g20b" model="account.tax.report.line">
<field name="name">G20: GST on purchases</field>
<field name="formula">(((G10+G11)-(G13+G14+G15)+G18)/11)+ONLY</field>
<field name="sequence" eval="114"/>
<field name="country_id" ref="base.au"/>
</record>
<!-- Comparison -->
<record id="account_tax_report_gstrpt_comparison" model="account.tax.report.line">
<field name="name">Comparison</field>
<field name="tag_name">Comparison</field>
<field name="sequence" eval="201"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_comparison_worksheet" model="account.tax.report.line">
<field name="name">GST from worksheet (G20-G9)</field>
<field name="formula">((((G10+G11)-(G13+G14+G15)+G18)/11)+ONLY)-(((G1-(G2+G3+G4))+G7)/11)</field>
<field name="sequence" eval="202"/>
<field name="parent_id" ref="account_tax_report_gstrpt_comparison"/>
<field name="country_id" ref="base.au"/>
</record>
<record id="account_tax_report_gstrpt_comparison_gl" model="account.tax.report.line">
<field name="name">GST from General Ledger</field>
<field name="tag_name">GST from General Ledger</field>
<field name="sequence" eval="203"/>
<field name="parent_id" ref="account_tax_report_gstrpt_comparison"/>
<field name="country_id" ref="base.au"/>
</record>
</odoo>
@@ -0,0 +1,550 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="au_tax_sale_10" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Sale (10%)</field>
<field name="sequence">1</field>
<field name="description">GST Sales</field>
<field name="type_tax_use">sale</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21310'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
'minus_report_line_ids': [ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21310'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
'plus_report_line_ids': [ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_sale_inc_10" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">GST Inc Sale (10%)</field>
<field name="sequence">2</field>
<field name="description">GST Inclusive Sales</field>
<field name="type_tax_use">sale</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="1"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21310'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
'minus_report_line_ids': [ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21310'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1')],
'plus_report_line_ids': [ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_sale_0" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Zero (Export) Sale</field>
<field name="sequence">3</field>
<field name="description">Zero Rated (Export) Sales</field>
<field name="type_tax_use">sale</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_0"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g2')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g2')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g2')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g2')],
}),
]"/>
</record>
<record id="au_tax_sale_exempt" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Exempt Sale</field>
<field name="sequence">4</field>
<field name="description">Exempt Sales</field>
<field name="type_tax_use">sale</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_0"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g3')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g3')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g3')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g3')],
}),
]"/>
</record>
<record id="au_tax_sale_input" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Input Taxed</field>
<field name="sequence">5</field>
<field name="description">Input Taxed Sales</field>
<field name="type_tax_use">sale</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_0"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g4')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g4')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g4')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g1'), ref('account_tax_report_gstrpt_g4')],
}),
]"/>
</record>
<record id="au_tax_sale_adj" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Sale Adj (10%)</field>
<field name="sequence">6</field>
<field name="description">Tax Adjustments (Sales)</field>
<field name="type_tax_use">sale</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g7')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21310'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g7')],
'minus_report_line_ids': [ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g7')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21310'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g7')],
'plus_report_line_ids': [ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_purchase_10" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Purch (10%)</field>
<field name="sequence">1</field>
<field name="description">GST Purchases</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_purchase_inc_10" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">GST Inc Purch (10%)</field>
<field name="sequence">2</field>
<field name="description">GST Inclusive Purchases</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="1"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_purchase_capital" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Capital (10.0%)</field>
<field name="sequence">3</field>
<field name="description">Capital Purchases</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g10'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g10')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g10'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_purchase_0" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Zero Rated Purch</field>
<field name="sequence">4</field>
<field name="description">Capital Purchases</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_0"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
]"/>
</record>
<record id="au_tax_purchase_taxable_import" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Purch (Taxable Imports)</field>
<field name="sequence">5</field>
<field name="description">Purchase (Taxable Imports) - Tax Paid Separately</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_0"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g14')],
}),
]"/>
</record>
<record id="au_tax_purchase_input" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Purch for Input Sales</field>
<field name="sequence">6</field>
<field name="description">Purchases for Input Taxed Sales</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g13')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g13')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g13')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g13')],
}),
]"/>
</record>
<record id="au_tax_purchase_private" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Purch Private (10%)</field>
<field name="sequence">7</field>
<field name="description">Purchases for Private use or not deductible</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g15')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g15')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g15')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g11'), ref('account_tax_report_gstrpt_g15')],
}),
]"/>
</record>
<record id="au_tax_purchase_gst_only" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">GST Only on Imports</field>
<field name="sequence">8</field>
<field name="description">GST Only on Imports</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">100000000</field>
<field name="price_include" eval="1"/>
<field name="tax_group_id" ref="tax_group_gst_100000000"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_gstonly'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_gstonly'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
<record id="au_tax_purchase_adj" model="account.tax.template">
<field name="chart_template_id" ref="l10n_au_chart_template"/>
<field name="name">Purch Adj (10%)</field>
<field name="sequence">9</field>
<field name="description">Tax Adjustments (Purchases)</field>
<field name="type_tax_use">purchase</field>
<field name="amount_type">percent</field>
<field name="amount">10.0</field>
<field name="price_include" eval="0"/>
<field name="tax_group_id" ref="tax_group_gst_10"/>
<field name="invoice_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g18')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'plus_report_line_ids': [ref('account_tax_report_gstrpt_g18'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
<field name="refund_repartition_line_ids" eval="[
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g18')],
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('au_21330'),
'minus_report_line_ids': [ref('account_tax_report_gstrpt_g18'), ref('account_tax_report_gstrpt_comparison_gl')],
}),
]"/>
</record>
</odoo>
+1
View File
@@ -47,6 +47,7 @@ Wizards provided by this module:
'data/account.account.template.csv',
'data/account_pcmn_belgium_data.xml',
'data/account_data.xml',
'data/account_tax_report_data.xml',
'data/account_tax_template_data.xml',
'data/l10n_be_sequence_data.xml',
'data/fiscal_templates_data.xml',
@@ -9,5 +9,7 @@
<field name="property_account_income_categ_id" ref="a7010"/>
<field name="expense_currency_exchange_account_id" ref="a654"/>
<field name="income_currency_exchange_account_id" ref="a754"/>
<field name="property_tax_payable_account_id" ref="a4512"/>
<field name="property_tax_receivable_account_id" ref="a4112"/>
</record>
</odoo>
@@ -32,5 +32,15 @@
<field name="amount_type">percentage</field>
<field name="amount">100</field>
<field name="label">Virements internes</field>
<field name="to_check" eval="False"/>
</record>
<record id="compte_attente_template" model="account.reconcile.model.template">
<field name="chart_template_id" ref="l10nbe_chart_template"/>
<field name="account_id" ref="a4990"/>
<field name="name">Compte Attente</field>
<field name="amount_type">percentage</field>
<field name="amount">100</field>
<field name="label"></field>
<field name="to_check" eval="True"/>
</record>
</odoo>
@@ -0,0 +1,325 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="tax_report_title_operations" model="account.tax.report.line">
<field name="name">Opérations</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
</record>
<record id="tax_report_title_operations_sortie" model="account.tax.report.line">
<field name="name">II A la sortie</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_operations"/>
</record>
<record id="tax_report_line_00" model="account.tax.report.line">
<field name="name">00 - Opérations soumises à un régime particulier</field>
<field name="tag_name">00</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_01" model="account.tax.report.line">
<field name="name">01 - Opérations avec TVA à 6%</field>
<field name="tag_name">01</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_02" model="account.tax.report.line">
<field name="name">02 - Opérations avec TVA à 12%</field>
<field name="tag_name">02</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">3</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_03" model="account.tax.report.line">
<field name="name">03 - Opérations avec TVA à 21%</field>
<field name="tag_name">03</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">4</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_44" model="account.tax.report.line">
<field name="name">44 - Services intra-communautaires</field>
<field name="tag_name">44</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">5</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_45" model="account.tax.report.line">
<field name="name">45 - Opérations avec TVA due par le cocontractant</field>
<field name="tag_name">45</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">6</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_title_operations_sortie_46" model="account.tax.report.line">
<field name="name">46 - Livraisons intra-communautaires exemptées</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">7</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_46L" model="account.tax.report.line">
<field name="name">46L - Livraisons biens intra-communautaires exemptées</field>
<field name="tag_name">46L</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_operations_sortie_46"/>
</record>
<record id="tax_report_line_46T" model="account.tax.report.line">
<field name="name">46T - Livraisons biens intra-communautaire exemptées</field>
<field name="tag_name">46T</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_operations_sortie_46"/>
</record>
<record id="tax_report_line_47" model="account.tax.report.line">
<field name="name">47 - Autres opérations exemptées</field>
<field name="tag_name">47</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">8</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_title_operations_sortie_48" model="account.tax.report.line">
<field name="name">48 - Notes de crédit aux opérations grilles [44] et [46]</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">9</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_line_48s44" model="account.tax.report.line">
<field name="name">48s44 - Notes de crédit aux opérations grilles [44]</field>
<field name="tag_name">48s44</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_operations_sortie_48"/>
</record>
<record id="tax_report_line_48s46L" model="account.tax.report.line">
<field name="name">48s46L - Notes de crédit aux opérations grilles [46L]</field>
<field name="tag_name">48s46L</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_operations_sortie_48"/>
</record>
<record id="tax_report_line_48s46T" model="account.tax.report.line">
<field name="name">48s46T - Notes de crédit aux opérations grilles [46T]</field>
<field name="tag_name">48s46T</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">3</field>
<field name="parent_id" ref="tax_report_title_operations_sortie_48"/>
</record>
<record id="tax_report_line_49" model="account.tax.report.line">
<field name="name">49 - Notes de crédit aux opérations du point II</field>
<field name="tag_name">49</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">10</field>
<field name="parent_id" ref="tax_report_title_operations_sortie"/>
</record>
<record id="tax_report_title_operations_entree" model="account.tax.report.line">
<field name="name">III A l'entrée</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_operations"/>
</record>
<record id="tax_report_line_81" model="account.tax.report.line">
<field name="name">81 - Marchandises, matières premières et auxiliaires</field>
<field name="tag_name">81</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_82" model="account.tax.report.line">
<field name="name">82 - Services et biens divers</field>
<field name="tag_name">82</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_83" model="account.tax.report.line">
<field name="name">83 - Biens d'investissement</field>
<field name="tag_name">83</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">3</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_84" model="account.tax.report.line">
<field name="name">84 - Notes de crédits sur opérations case [86] et [88]</field>
<field name="tag_name">84</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">4</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_85" model="account.tax.report.line">
<field name="name">85 - Notes de crédits autres opérations</field>
<field name="tag_name">85</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">5</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_86" model="account.tax.report.line">
<field name="name">86 - Acquisition intra-communautaires et ventes ABC</field>
<field name="tag_name">86</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">6</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_87" model="account.tax.report.line">
<field name="name">87 - Autres opérations</field>
<field name="tag_name">87</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">7</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_line_88" model="account.tax.report.line">
<field name="name">88 - Acquisition services intra-communautaires</field>
<field name="tag_name">88</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">8</field>
<field name="parent_id" ref="tax_report_title_operations_entree"/>
</record>
<record id="tax_report_title_taxes" model="account.tax.report.line">
<field name="name">Taxes</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
</record>
<record id="tax_report_title_taxes_dues" model="account.tax.report.line">
<field name="name">IV Dues</field>
<field name="code">tax_be_iv</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_taxes"/>
</record>
<record id="tax_report_line_54" model="account.tax.report.line">
<field name="name">54 - TVA sur opérations des grilles [01], [02], [03]</field>
<field name="tag_name">54</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_taxes_dues"/>
</record>
<record id="tax_report_line_55" model="account.tax.report.line">
<field name="name">55 - TVA sur opérations des grilles [86] et [88]</field>
<field name="tag_name">55</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_taxes_dues"/>
</record>
<record id="tax_report_line_56" model="account.tax.report.line">
<field name="name">56 - TVA sur opérations de la grille [87]</field>
<field name="tag_name">56</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">3</field>
<field name="parent_id" ref="tax_report_title_taxes_dues"/>
</record>
<record id="tax_report_line_57" model="account.tax.report.line">
<field name="name">57 - TVA relatives aux importations</field>
<field name="tag_name">57</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">4</field>
<field name="parent_id" ref="tax_report_title_taxes_dues"/>
</record>
<record id="tax_report_line_61" model="account.tax.report.line">
<field name="name">61 - Diverses régularisations en faveur de l'Etat</field>
<field name="tag_name">61</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">5</field>
<field name="parent_id" ref="tax_report_title_taxes_dues"/>
</record>
<record id="tax_report_line_63" model="account.tax.report.line">
<field name="name">63 - TVA à reverser sur notes de crédit recues</field>
<field name="tag_name">63</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">6</field>
<field name="parent_id" ref="tax_report_title_taxes_dues"/>
</record>
<record id="tax_report_title_taxes_deductibles" model="account.tax.report.line">
<field name="name">V Déductibles</field>
<field name="code">tax_be_v</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_taxes"/>
</record>
<record id="tax_report_line_59" model="account.tax.report.line">
<field name="name">59 - TVA déductible</field>
<field name="tag_name">59</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_taxes_deductibles"/>
</record>
<record id="tax_report_line_62" model="account.tax.report.line">
<field name="name">62 - Diverses régularisations en faveur du déclarant</field>
<field name="tag_name">62</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_taxes_deductibles"/>
</record>
<record id="tax_report_line_64" model="account.tax.report.line">
<field name="name">64 - TVA à récupérer sur notes de crédit delivrées</field>
<field name="tag_name">64</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">3</field>
<field name="parent_id" ref="tax_report_title_taxes_deductibles"/>
</record>
<record id="tax_report_title_taxes_soldes" model="account.tax.report.line">
<field name="name">VI Soldes</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">3</field>
<field name="parent_id" ref="tax_report_title_taxes"/>
</record>
<record id="tax_report_line_71" model="account.tax.report.line">
<field name="name">71 - Taxes dues à l'état</field>
<field name="formula">tax_be_iv&gt;tax_be_v and tax_be_iv-tax_be_v or 0</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">1</field>
<field name="parent_id" ref="tax_report_title_taxes_soldes"/>
</record>
<record id="tax_report_line_72" model="account.tax.report.line">
<field name="name">72 - Somme due par l'état</field>
<field name="formula">tax_be_iv&lt;tax_be_v and tax_be_v-tax_be_iv or 0</field>
<field name="country_id" ref="base.be"/>
<field name="sequence">2</field>
<field name="parent_id" ref="tax_report_title_taxes_soldes"/>
</record>
</data>
</odoo>
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -128,6 +128,7 @@ class AccountInvoice(models.Model):
lines_elements = tree.xpath('//cac:InvoiceLine', namespaces=namespaces)
for eline in lines_elements:
with invoice_form.invoice_line_ids.new() as invoice_line_form:
invoice_line_form.account_id = invoice_line_form.account_id or self.env['account.account'].browse(self.with_context(journal_id=journal_id.id).env['account.invoice.line']._default_account())
# Quantity
elements = eline.xpath('cbc:InvoicedQuantity', namespaces=namespaces)
quantity = elements and float(elements[0].text) or 1.0
@@ -164,12 +165,11 @@ class AccountInvoice(models.Model):
for etax in taxes_elements:
elements = etax.xpath('cbc:Percent', namespaces=namespaces)
if elements:
tax = self.env['account.tax'].search([('amount', '=', float(elements[0].text)), ('type_tax_use', '=', journal_id.type)], order='sequence ASC', limit=1)
tax = self.env['account.tax'].search([('company_id', '=', self.env.user.company_id.id), ('amount', '=', float(elements[0].text)), ('type_tax_use', '=', journal_id.type)], order='sequence ASC', limit=1)
if tax:
invoice_line_form.invoice_line_tax_ids.add(tax)
invoice_line_form.account_id = invoice_line_form.account_id or self.env['account.account'].browse(self.with_context(journal_id=journal_id.id).env['account.invoice.line']._default_account())
return invoice_form.save
return invoice_form.save()
@api.model
def _get_xml_decoders(self):

Some files were not shown because too many files have changed in this diff Show More