" + str(error) + "
"
- ]), body_is_html=True
+ rec.message_post(
+ body="" + str(error) + "
",
+ ]
+ ),
+ body_is_html=True,
)
- @api.onchange('partner_id')
+ @api.onchange("partner_id")
def _onchange_partner_commercial(self):
if self.partner_id.user_id:
self.invoice_user_id = self.partner_id.user_id.id
@@ -72,8 +70,13 @@ def get_accounting_rate(company_currency, amount, amount_currency, currency):
else:
return abs(amount_currency) / abs(amount)
- rate = get_accounting_rate(move.company_id.currency_id, move.amount_total_signed, move.amount_total_in_currency_signed, move.currency_id)
- amount = abs(line.amount_residual) * rate
+ rate = get_accounting_rate(
+ move.company_id.currency_id,
+ move.amount_total_signed,
+ move.amount_total_in_currency_signed,
+ move.currency_id,
+ )
+ amount = abs(line.amount_residual) * rate
return amount
### Comentamos este método debido a que el campo invoice_outstanding_credits_debits_widget no se estaba seteando correctamente en super
@@ -113,27 +116,35 @@ def get_accounting_rate(company_currency, amount, amount_currency, currency):
# amount_residual = self.env['account.move.line'].browse(item['id']).amount_residual
# item['amount'] = move.currency_id.round(amount_residual * rate)
- @api.depends('invoice_date')
+ @api.depends("invoice_date")
def _compute_invoice_date_due(self):
- """ Si la factura no tiene término de pago y la misma tiene fecha de vencimiento anterior al día de hoy y la factura no tiene fecha entonces cuando se publica la factura, la fecha de vencimiento tiene que coincidir con la fecha de hoy. """
- invoices_with_old_data_due = self.filtered(lambda x: x.invoice_date and not x.invoice_payment_term_id and (not x.invoice_date_due or x.invoice_date_due < x.invoice_date))
+ """Si la factura no tiene término de pago y la misma tiene fecha de vencimiento anterior al día de hoy y la factura no tiene fecha entonces cuando se publica la factura, la fecha de vencimiento tiene que coincidir con la fecha de hoy."""
+ invoices_with_old_data_due = self.filtered(
+ lambda x: x.invoice_date
+ and not x.invoice_payment_term_id
+ and (not x.invoice_date_due or x.invoice_date_due < x.invoice_date)
+ )
invoices = self - invoices_with_old_data_due
for inv in invoices_with_old_data_due:
if inv.invoice_date:
inv.invoice_date_due = inv.invoice_date
return super(AccountMove, invoices)._compute_invoice_date_due()
- @api.constrains('date', 'invoice_date')
+ @api.constrains("date", "invoice_date")
def _check_dates_on_invoices(self):
- """ Prevenir que en facturas de cliente queden distintos los campos de factura/recibo y fecha (date e invoice date). Pueden quedar distintos si se modifica alguna de esas fechas a través de edición masiva por ejemplo, entonces con esta constrains queremos prevenir que eso suceda. """
- invoices_to_check = self.filtered(lambda x: x.date!=x.invoice_date if x.is_sale_document() and x.date and x.invoice_date else False)
+ """Prevenir que en facturas de cliente queden distintos los campos de factura/recibo y fecha (date e invoice date). Pueden quedar distintos si se modifica alguna de esas fechas a través de edición masiva por ejemplo, entonces con esta constrains queremos prevenir que eso suceda."""
+ invoices_to_check = self.filtered(
+ lambda x: x.date != x.invoice_date if x.is_sale_document() and x.date and x.invoice_date else False
+ )
if invoices_to_check:
- error_msg = _('\nDate\t\t\tInvoice Date\t\tInvoice\n')
+ error_msg = _("\nDate\t\t\tInvoice Date\t\tInvoice\n")
for rec in invoices_to_check:
- error_msg += str(rec.date) + '\t'*2 + str(rec.invoice_date) + '\t'*3 + rec.display_name + '\n'
- raise UserError(_('The date and invoice date of a sale invoice must be the same: %s') % (error_msg))
+ error_msg += str(rec.date) + "\t" * 2 + str(rec.invoice_date) + "\t" * 3 + rec.display_name + "\n"
+ raise UserError(_("The date and invoice date of a sale invoice must be the same: %s") % (error_msg))
- @api.depends('invoice_currency_rate')
+ @api.depends("invoice_currency_rate")
def _compute_inverse_invoice_currency_rate(self):
for record in self:
- record.inverse_invoice_currency_rate = 1 / record.invoice_currency_rate if record.invoice_currency_rate else 1.0
+ record.inverse_invoice_currency_rate = (
+ 1 / record.invoice_currency_rate if record.invoice_currency_rate else 1.0
+ )
diff --git a/account_ux/models/account_move_line.py b/account_ux/models/account_move_line.py
index 0bc17e07f..c73db0b39 100644
--- a/account_ux/models/account_move_line.py
+++ b/account_ux/models/account_move_line.py
@@ -9,11 +9,14 @@ class AccountMoveLine(models.Model):
_inherit = "account.move.line"
user_id = fields.Many2one(
- string='Contact Salesperson', related='partner_id.user_id', store=True,
- help='Salesperson of contact related to this journal item')
+ string="Contact Salesperson",
+ related="partner_id.user_id",
+ store=True,
+ help="Salesperson of contact related to this journal item",
+ )
# lo agregamos para que al agrupar en vista tree se vea y ademas que aparezca com messure en la pivot
amount_residual_currency = fields.Monetary(
- aggregator='sum',
+ aggregator="sum",
)
@api.model
@@ -49,50 +52,73 @@ def _prepare_reconciliation_single_partial(self, debit_values, credit_values, sh
"""
def get_accounting_rate(vals):
- if company_debit_currency.is_zero(abs(vals['aml'].balance)) or vals['currency'].is_zero(vals['aml'].amount_currency):
+ if company_debit_currency.is_zero(abs(vals["aml"].balance)) or vals["currency"].is_zero(
+ vals["aml"].amount_currency
+ ):
return 0.0
else:
- return abs(vals['aml'].amount_currency) / abs(vals['aml'].balance)
+ return abs(vals["aml"].amount_currency) / abs(vals["aml"].balance)
- company_debit_currency = debit_values['aml'].company_currency_id
- company_credit_currency = credit_values['aml'].company_currency_id
- reconcile_on_company_currency = debit_values['aml'].company_id.reconcile_on_company_currency and \
- (debit_values['aml'].currency_id != company_debit_currency or credit_values['aml'].currency_id != company_debit_currency) and \
- not debit_values['aml'].account_id.currency_id
+ company_debit_currency = debit_values["aml"].company_currency_id
+ company_credit_currency = credit_values["aml"].company_currency_id
+ reconcile_on_company_currency = (
+ debit_values["aml"].company_id.reconcile_on_company_currency
+ and (
+ debit_values["aml"].currency_id != company_debit_currency
+ or credit_values["aml"].currency_id != company_debit_currency
+ )
+ and not debit_values["aml"].account_id.currency_id
+ )
if reconcile_on_company_currency:
shadowed_aml_values = {}
- if debit_values['aml'].currency_id != company_debit_currency:
- debit_values['original_currency'] = debit_values['aml'].currency_id
- debit_values['currency'] = company_debit_currency
- debit_values['amount_residual_currency'] = debit_values['amount_residual']
- shadowed_aml_values[debit_values['aml']] = {'currency_id': company_debit_currency,
- 'amount_residual_currency': debit_values['amount_residual']}
- if credit_values['aml'].currency_id != company_credit_currency:
- credit_values['original_currency'] = credit_values['aml'].currency_id
- credit_values['currency'] = company_credit_currency
- credit_values['amount_residual_currency'] = credit_values['amount_residual']
- shadowed_aml_values[credit_values['aml']] = {'currency_id': company_credit_currency,
- 'amount_residual_currency': credit_values['amount_residual']}
- res = super(AccountMoveLine, self.with_context(no_exchange_difference=True))._prepare_reconciliation_single_partial(debit_values, credit_values, shadowed_aml_values)
+ if debit_values["aml"].currency_id != company_debit_currency:
+ debit_values["original_currency"] = debit_values["aml"].currency_id
+ debit_values["currency"] = company_debit_currency
+ debit_values["amount_residual_currency"] = debit_values["amount_residual"]
+ shadowed_aml_values[debit_values["aml"]] = {
+ "currency_id": company_debit_currency,
+ "amount_residual_currency": debit_values["amount_residual"],
+ }
+ if credit_values["aml"].currency_id != company_credit_currency:
+ credit_values["original_currency"] = credit_values["aml"].currency_id
+ credit_values["currency"] = company_credit_currency
+ credit_values["amount_residual_currency"] = credit_values["amount_residual"]
+ shadowed_aml_values[credit_values["aml"]] = {
+ "currency_id": company_credit_currency,
+ "amount_residual_currency": credit_values["amount_residual"],
+ }
+ res = super(
+ AccountMoveLine, self.with_context(no_exchange_difference=True)
+ )._prepare_reconciliation_single_partial(debit_values, credit_values, shadowed_aml_values)
else:
res = super()._prepare_reconciliation_single_partial(debit_values, credit_values, shadowed_aml_values)
- if reconcile_on_company_currency and 'partial_values' in res:
- if 'original_currency' in credit_values:
- credit_values['currency'] = credit_values['original_currency']
+ if reconcile_on_company_currency and "partial_values" in res:
+ if "original_currency" in credit_values:
+ credit_values["currency"] = credit_values["original_currency"]
rate = get_accounting_rate(credit_values)
- res['partial_values']['credit_amount_currency'] = credit_values['aml'].currency_id.round(
- res['partial_values']['credit_amount_currency'] * rate)
- if 'original_currency' in debit_values:
- debit_values['currency'] = debit_values['original_currency']
+ res["partial_values"]["credit_amount_currency"] = credit_values["aml"].currency_id.round(
+ res["partial_values"]["credit_amount_currency"] * rate
+ )
+ if "original_currency" in debit_values:
+ debit_values["currency"] = debit_values["original_currency"]
rate = get_accounting_rate(debit_values)
- res['partial_values']['debit_amount_currency'] = credit_values['aml'].currency_id.round(
- res['partial_values']['debit_amount_currency'] * rate)
+ res["partial_values"]["debit_amount_currency"] = credit_values["aml"].currency_id.round(
+ res["partial_values"]["debit_amount_currency"] * rate
+ )
return res
def _compute_amount_residual(self):
- """ Cuando se realiza un cobro de un recibo y el comprobante que se paga tiene moneda secundaria y queda totalmente conciliado en moneda de compañía pero no en moneda secundaria (ejemplo: diferencia de un centavo) lo que hacemos con este método es forzar que quede conciliado también en moneda secundaria. """
+ """Cuando se realiza un cobro de un recibo y el comprobante que se paga tiene moneda secundaria y queda totalmente conciliado en moneda de compañía pero no en moneda secundaria (ejemplo: diferencia de un centavo) lo que hacemos con este método es forzar que quede conciliado también en moneda secundaria."""
super()._compute_amount_residual()
- need_amount_residual_currency_adjustment = self.filtered(lambda x: not x.reconciled and x.company_id.reconcile_on_company_currency and (x.account_id.reconcile or x.account_id.account_type in ('asset_cash', 'liability_credit_card')) and (x.company_currency_id or self.env.company.currency_id).is_zero(x.amount_residual) and not (x.currency_id or (x.company_currency_id or self.env.company.currency_id)).is_zero(x.amount_residual_currency))
+ need_amount_residual_currency_adjustment = self.filtered(
+ lambda x: not x.reconciled
+ and x.company_id.reconcile_on_company_currency
+ and (x.account_id.reconcile or x.account_id.account_type in ("asset_cash", "liability_credit_card"))
+ and (x.company_currency_id or self.env.company.currency_id).is_zero(x.amount_residual)
+ and not (x.currency_id or (x.company_currency_id or self.env.company.currency_id)).is_zero(
+ x.amount_residual_currency
+ )
+ )
need_amount_residual_currency_adjustment.amount_residual_currency = 0.0
need_amount_residual_currency_adjustment.reconciled = True
diff --git a/account_ux/models/account_payment.py b/account_ux/models/account_payment.py
index d28252cdf..25d9a64f7 100644
--- a/account_ux/models/account_payment.py
+++ b/account_ux/models/account_payment.py
@@ -1,25 +1,24 @@
-from odoo import models, fields, api
+from odoo import api, models
class AccountPayment(models.Model):
_inherit = "account.payment"
-
- @api.onchange('available_journal_ids')
+ @api.onchange("available_journal_ids")
def _onchange_available_journal_ids(self):
- """ Fix the use case where a journal only suitable for one kind of operation (lets said inbound) is selected
+ """Fix the use case where a journal only suitable for one kind of operation (lets said inbound) is selected
and then the user selects "outbound" type, the journals remains selected."""
if not self.journal_id or self.journal_id not in self.available_journal_ids._origin:
self.journal_id = self.available_journal_ids._origin[:1]
- @api.depends('invoice_ids.payment_state', 'move_id.line_ids.amount_residual')
+ @api.depends("invoice_ids.payment_state", "move_id.line_ids.amount_residual")
def _compute_state(self):
super()._compute_state()
for payment in self:
if (
- not self.env.context.get('skip_payment_state_computation') and
- payment.journal_id.type in ('bank', 'cash') and
- payment.outstanding_account_id and
- len(payment.move_id.line_ids._reconciled_lines()) > 1
+ not self.env.context.get("skip_payment_state_computation")
+ and payment.journal_id.type in ("bank", "cash")
+ and payment.outstanding_account_id
+ and len(payment.move_id.line_ids._reconciled_lines()) > 1
):
- payment.state = 'paid'
+ payment.state = "paid"
diff --git a/account_ux/models/res_company.py b/account_ux/models/res_company.py
index 9057225a5..a71d39854 100644
--- a/account_ux/models/res_company.py
+++ b/account_ux/models/res_company.py
@@ -1,10 +1,11 @@
-from odoo import models, fields
+from odoo import fields, models
class ResCompany(models.Model):
- _inherit = 'res.company'
+ _inherit = "res.company"
reconcile_on_company_currency = fields.Boolean(
help="When reconciling debt with secondary currency, if the account doesn't have a currency configured, then"
" reconcile on company currency. This will avoid all the automatic exchange rates journal entries by forcing "
- " same rate of the original document being reconcile")
+ " same rate of the original document being reconcile"
+ )
diff --git a/account_ux/models/res_currency_rate.py b/account_ux/models/res_currency_rate.py
index f65757fef..56670a7d3 100644
--- a/account_ux/models/res_currency_rate.py
+++ b/account_ux/models/res_currency_rate.py
@@ -1,25 +1,29 @@
# © 2018 ADHOC SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-from odoo import api, models, _
+from odoo import _, api, models
from odoo.exceptions import ValidationError
class ResCurrencyRate(models.Model):
+ _inherit = "res.currency.rate"
- _inherit = 'res.currency.rate'
-
- @api.constrains('company_id')
+ @api.constrains("company_id")
def _check_date_rate(self):
for rec in self.filtered(lambda x: not x.company_id):
- others_with_company = self.search([
- ('name', '<=', rec.name),
- ('currency_id', '=', rec.currency_id.id),
- ('company_id', '!=', False),
- ])
+ others_with_company = self.search(
+ [
+ ("name", "<=", rec.name),
+ ("currency_id", "=", rec.currency_id.id),
+ ("company_id", "!=", False),
+ ]
+ )
if others_with_company:
- raise ValidationError(_(
- 'You can not create a rate without company'
- ' since you already have rates before %s with'
- ' company set. The rate you want to create will not'
- ' have any effect, will not be take into account.'
- ) % rec.name)
+ raise ValidationError(
+ _(
+ "You can not create a rate without company"
+ " since you already have rates before %s with"
+ " company set. The rate you want to create will not"
+ " have any effect, will not be take into account."
+ )
+ % rec.name
+ )
diff --git a/account_ux/reports/invoice_report.py b/account_ux/reports/invoice_report.py
index 10ef58312..62fe32d93 100644
--- a/account_ux/reports/invoice_report.py
+++ b/account_ux/reports/invoice_report.py
@@ -1,29 +1,46 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import models, fields
+from odoo import fields, models
from odoo.tools import SQL
-class AccountInvoiceReport(models.Model):
- _inherit = 'account.invoice.report'
+class AccountInvoiceReport(models.Model):
+ _inherit = "account.invoice.report"
# agregamos widgets monetary, referencia a company currency en string y help
price_subtotal = fields.Monetary(
- currency_field='company_currency_id', string="Untaxed Total (CC)", help="Untaxed Total in company currency")
- price_total = fields.Monetary(string='Total', currency_field='invoice_currency_id')
+ currency_field="company_currency_id", string="Untaxed Total (CC)", help="Untaxed Total in company currency"
+ )
+ price_total = fields.Monetary(string="Total", currency_field="invoice_currency_id")
price_average = fields.Monetary(
- currency_field='company_currency_id', string='Average Price (CC)', help="Average Price in company currency")
+ currency_field="company_currency_id", string="Average Price (CC)", help="Average Price in company currency"
+ )
# creamos nuevos campos para tener descuentos, vinculos e importes en moneda de compañía
total_cc = fields.Monetary(
- string='Total (CC)', readonly=True, help="Untaxed Total in company currency",
- currency_field='company_currency_id')
- invoice_currency_id = fields.Many2one('res.currency', string='Invoice Currency', readonly=True)
- line_id = fields.Many2one('account.move.line', string='Journal Item', readonly=True)
- price_subtotal_ic = fields.Monetary('Untaxed Total', readonly=True, currency_field='invoice_currency_id',)
- price_unit = fields.Monetary('Unit Price', readonly=True, currency_field='invoice_currency_id',)
- discount = fields.Float('Discount (%)', readonly=True)
- discount_amount = fields.Monetary(readonly=True, aggregator="sum", currency_field='invoice_currency_id',)
+ string="Total (CC)",
+ readonly=True,
+ help="Untaxed Total in company currency",
+ currency_field="company_currency_id",
+ )
+ invoice_currency_id = fields.Many2one("res.currency", string="Invoice Currency", readonly=True)
+ line_id = fields.Many2one("account.move.line", string="Journal Item", readonly=True)
+ price_subtotal_ic = fields.Monetary(
+ "Untaxed Total",
+ readonly=True,
+ currency_field="invoice_currency_id",
+ )
+ price_unit = fields.Monetary(
+ "Unit Price",
+ readonly=True,
+ currency_field="invoice_currency_id",
+ )
+ discount = fields.Float("Discount (%)", readonly=True)
+ discount_amount = fields.Monetary(
+ readonly=True,
+ aggregator="sum",
+ currency_field="invoice_currency_id",
+ )
- _depends = {'account.move.line': ['price_unit', 'discount']}
+ _depends = {"account.move.line": ["price_unit", "discount"]}
def _select(self):
query = SQL("""
diff --git a/account_ux/tests/test_account_ux.py b/account_ux/tests/test_account_ux.py
index 7fa4fff50..20e2a40f3 100644
--- a/account_ux/tests/test_account_ux.py
+++ b/account_ux/tests/test_account_ux.py
@@ -3,44 +3,53 @@
class TestAccountUXChangeCurrency(common.TransactionCase):
-
def setUp(self):
super().setUp()
self.today = fields.Date.today()
- self.first_company = self.env['res.company'].search([], limit=1)
- self.partner_ri = self.env['res.partner'].search([], limit=1)
+ self.first_company = self.env["res.company"].search([], limit=1)
+ self.partner_ri = self.env["res.partner"].search([], limit=1)
- self.currency_usd = self.env['res.currency'].search([('name', '=', 'USD')])
- self.currency_ars = self.env['res.currency'].search([('name', '=', 'ARS'), ('active', 'in', [False])])
+ self.currency_usd = self.env["res.currency"].search([("name", "=", "USD")])
+ self.currency_ars = self.env["res.currency"].search([("name", "=", "ARS"), ("active", "in", [False])])
self.currency_ars.active = True
- self.first_company_journal_usd = self.env['account.journal'].search([('company_id', '=', self.first_company.id), ('type', '=', 'sale')], limit=1)
- self.first_company_journal_ars = self.env['account.journal'].create({
- 'name': 'ARS sale journal',
- 'company_id': self.first_company.id,
- 'type': 'sale',
- 'currency_id': self.currency_ars.id,
- 'code': 'ARS'
- })
+ self.first_company_journal_usd = self.env["account.journal"].search(
+ [("company_id", "=", self.first_company.id), ("type", "=", "sale")], limit=1
+ )
+ self.first_company_journal_ars = self.env["account.journal"].create(
+ {
+ "name": "ARS sale journal",
+ "company_id": self.first_company.id,
+ "type": "sale",
+ "currency_id": self.currency_ars.id,
+ "code": "ARS",
+ }
+ )
def test_account_ux_change_currency(self):
- invoice = self.env['account.move'].create({
- 'partner_id': self.partner_ri.id,
- 'date': self.today,
- 'move_type': 'out_invoice',
- 'journal_id': self.first_company_journal_usd.id,
- 'company_id': self.first_company.id,
- 'invoice_line_ids': [
- Command.create({
- 'product_id': self.env.ref('product.product_product_16').id,
- 'quantity': 1,
- 'price_unit': 1000,
- }),
- ],
- })
- invoice.write({
- 'journal_id': self.first_company_journal_ars.id
- })
+ invoice = self.env["account.move"].create(
+ {
+ "partner_id": self.partner_ri.id,
+ "date": self.today,
+ "move_type": "out_invoice",
+ "journal_id": self.first_company_journal_usd.id,
+ "company_id": self.first_company.id,
+ "invoice_line_ids": [
+ Command.create(
+ {
+ "product_id": self.env.ref("product.product_product_16").id,
+ "quantity": 1,
+ "price_unit": 1000,
+ }
+ ),
+ ],
+ }
+ )
+ invoice.write({"journal_id": self.first_company_journal_ars.id})
invoice.action_post()
- self.assertEqual(invoice.currency_id, self.first_company_journal_ars.currency_id, "La moneda de la factura no esta siendo modificada al cambiar el diario.")
+ self.assertEqual(
+ invoice.currency_id,
+ self.first_company_journal_ars.currency_id,
+ "La moneda de la factura no esta siendo modificada al cambiar el diario.",
+ )
diff --git a/account_ux/views/account_move_views.xml b/account_ux/views/account_move_views.xml
index d376a37dc..47d44fd07 100644
--- a/account_ux/views/account_move_views.xml
+++ b/account_ux/views/account_move_views.xml
@@ -142,7 +142,7 @@
-
+