[MERGE] forward port branch saas-12.3 up to 60e71302a3
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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'})
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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');
|
||||
|
||||
|
||||
@@ -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': '/',
|
||||
|
||||
@@ -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")
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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
|
||||
)
|
||||
@@ -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."""
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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="{"orderedBy": [{"name": "foo", "asc": 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);
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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', '<', 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', '>', 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'}"/>
|
||||
|
||||
@@ -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']):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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''
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
|
||||
@@ -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>
|
||||
@@ -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'],
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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,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
|
||||
|
@@ -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>
|
||||
@@ -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>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<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
@@ -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
Reference in New Issue
Block a user