Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docsource/modules190-200.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Module coverage 19.0 -> 20.0
+---------------------------------------------------+----------------------+-------------------------------------------------+
| Module | Status + Extra Information |
+===================================================+======================+=================================================+
| account | | |
| account |Done | |
+---------------------------------------------------+----------------------+-------------------------------------------------+
| |del| account_add_gln | | |
+---------------------------------------------------+----------------------+-------------------------------------------------+
Expand Down
129 changes: 129 additions & 0 deletions openupgrade_scripts/scripts/account/20.0.1.5/noupdate_changes.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?xml version='1.0' encoding='utf-8'?>
<odoo>
<record id="account_send_payment_receipt_by_email_action" model="ir.actions.act_window">
<field name="context" eval="{ 'mail_post_autofollow': True, 'default_composition_mode': 'comment', 'default_template_id': ref('account.mail_template_data_payment_receipt'), }"/>
</record>
<record id="account_send_payment_receipt_by_email_action_multi" model="ir.actions.act_window">
<field name="context" eval="{ 'mail_post_autofollow': True, 'default_composition_mode': 'mass_mail', 'default_template_id': ref('account.mail_template_data_payment_receipt'), }"/>
</record>
<record id="action_open_settings" model="ir.actions.act_window">
<field name="context">{'module': 'general_settings'}</field>
</record>
<record id="email_template_edi_credit_note" model="mail.template">
<field name="email_layout_xmlid">mail.mail_notification_layout_with_responsible_signature</field>
</record>
<record id="email_template_edi_invoice" model="mail.template">
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-if="object.partner_id.parent_id"><t t-if="object.partner_id.name"><t t-out="object.partner_id.name">Brandon Freeman</t> (<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>),
</t><t t-else=""><t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>,
</t></t>
<t t-else=""><t t-out="object.partner_id.name or ''">Brandon Freeman</t>,
</t>
<br/><br/>
Here is your
<t t-if="object.name">
invoice <span style="font-weight:bold;" t-out="object.name or ''">INV/2021/05/0005</span>
</t>
<t t-else="">
invoice
</t>
<t t-if="object.invoice_origin">
(with reference: <t t-out="object.invoice_origin or ''">SUB003</t>)
</t>
amounting in <span style="font-weight:bold;" t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</span>
from <t t-out="object.company_id.name or ''">YourCompany</t>.
<t t-if="object.payment_state in ('paid', 'in_payment')">
This invoice is already paid.
</t>
<t t-else="">
Please remit payment at your earliest convenience.
<t t-if="object.payment_reference"><br/><br/>
Please use the following communication for your payment: <strong t-out="object.payment_reference or ''">INV/2021/05/0005</strong>
<t t-if="object.partner_bank_id">
on the account <strong t-out="object.partner_bank_id.account_number"/>
</t>
.
</t>
</t>
<br/><br/>
Do not hesitate to contact us if you have any questions.
<t t-if="not is_html_empty(object.invoice_user_id.signature)"><br/><br/><div>--<br/><t t-out="object.invoice_user_id.signature or ''">Mitchell Admin</t></div></t>
</p>
</div>
</field>
<field name="email_layout_xmlid">mail.mail_notification_layout_with_responsible_signature</field>
</record>
<record id="email_template_edi_self_billing_invoice" model="mail.template">
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-if="object.partner_id.parent_id"><t t-if="object.partner_id.name"><t t-out="object.partner_id.name">Brandon Freeman</t> (<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>),
</t><t t-else=""><t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>,
</t></t>
<t t-else=""><t t-out="object.partner_id.name or ''">Brandon Freeman</t>,
</t>
<br/><br/>
Here is your
<t t-if="object.name">
self-billing invoice <span style="font-weight:bold;" t-out="object.name or ''">INV/2021/05/0005</span>
</t>
<t t-else="">
self-billing invoice
</t>
<t t-if="object.invoice_origin">
(with reference: <t t-out="object.invoice_origin or ''">SUB003</t>)
</t>
amounting in <span style="font-weight:bold;" t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</span>
from <t t-out="object.company_id.name or ''">YourCompany</t>.
<t t-if="object.payment_state in ('paid', 'in_payment')">
This self-billing invoice has already been paid.
</t>
<br/><br/>
Do not hesitate to contact us if you have any questions.
<t t-if="not is_html_empty(object.invoice_user_id.signature)"><br/><br/><div>--<br/><t t-out="object.invoice_user_id.signature or ''">Mitchell Admin</t></div></t>
</p>
</div>
</field>
</record>
<template id="email_template_mail_gateway_failed">
<p>
Hi,
<br/><br/>
Your email has been discarded. the e-mail address you have used only accepts new invoices:
<ul><li>For new invoices, please ensure a PDF or electronic invoice file is attached</li><li>To add information to a previously sent invoice, reply to your "sent" email</li></ul>
For any other question, write to <t t-out="company_email"/>.
<br/>
--
<br/>
<t t-out="company_name"/>
</p>
</template>
<record id="mail_template_data_payment_receipt" model="mail.template">
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear <t t-out="object.partner_id.name or ''">Azure Interior</t><br/><br/>
<t t-if="object.partner_type == 'customer' and object.payment_type == 'outbound'">We have processed your refund of</t>
<t t-elif="object.partner_type == 'supplier' and object.payment_type == 'outbound'">We have processed your payment of</t>
<t t-elif="object.partner_type == 'supplier' and object.payment_type == 'inbound'">Thank you for your refund of</t>
<t t-else="">Thank you for your payment of</t> <span style="font-weight:bold;" t-out="format_amount(object.amount, object.currency_id) or ''">$ 10.00</span>.
Please find the <t t-out="object.payment_receipt_title.lower()">payment receipt</t> <span t-if="object.name" style="font-weight:bold;" t-out="object.name.replace('/','-')">BNK1-2021-05-0002</span> from <t t-out="object.company_id.name or ''">YourCompany</t>.
<br/><br/>
Do not hesitate to contact us if you have any questions.
<br/><br/>
Best regards,
<t t-if="not is_html_empty(user.signature)"><br/><br/><div>--<br/><t t-out="user.signature or ''">Mitchell Admin</t></div></t>
</p>
</div>
</field>
<field name="subject">{{ object.company_id.name }} {{ object.payment_receipt_title }} (Ref {{ object.name or 'n/a' }})</field>
<field name="email_layout_xmlid">mail.mail_notification_light</field>
</record>
<record id="onboarding_onboarding_account_dashboard" model="onboarding.onboarding">
<field name="step_ids" eval="[ Command.link(ref('account.onboarding_onboarding_step_company_data')), Command.link(ref('account.onboarding_onboarding_step_chart_of_accounts')), ]"/>
</record>
</odoo>
100 changes: 100 additions & 0 deletions openupgrade_scripts/scripts/account/20.0.1.5/post-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Copyright 2026 Don Kendall
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from openupgradelib import openupgrade


def _settle_in_process_payments(env):
"""19.0's payment state had an "In Process" step that 20.0 does not.

19.0 ran draft -> in_process -> paid; 20.0 runs draft -> paid ->
reconciled. The middle step is gone, and because the column already holds a
value the stored compute leaves it there: the payment reads as blank in the
interface and matches no branch of a domain over the state.

'paid' is the honest landing point. It states only what is certainly true --
the payment was made -- and 20.0's own _compute_state takes it from there:
for a payment already in 'paid' or 'reconciled' it re-derives which of the
two applies from the liquidity lines' residual. Writing 'reconciled'
directly would assert a bank match this migration has no evidence for.
"""
openupgrade.logged_query(
env.cr,
"UPDATE account_payment SET state = 'paid' WHERE state = 'in_process'",
)


def _carry_a_deliberate_not_reviewed_into_the_review_queue(env):
"""19.0's `checked` becomes 20.0's review_state, and only part of it is real.

19.0 carried a boolean "Reviewed". It was a stored COMPUTE with the value
written by::

move.checked = move.state == 'posted' and (
move.journal_id.type == 'general' or move._is_user_able_to_review())

and `readonly=False`, so a user could tick or untick it afterwards.

20.0 replaces it with `review_state`, a plain stored selection of no_review
/ todo / reviewed / supervised / anomaly defaulting to 'no_review', and
keeps an index named after the field it replaced::

_checked_idx = models.Index(
"(journal_id) WHERE (review_state IN ('todo', 'anomaly'))")

which is what makes it a work queue rather than a label.

**Only the deviation is carried.** A True that merely reproduces the compute
records nothing a reader could not derive, and writing 'reviewed' for it
would assert a review of every posted invoice in the database -- 3206 of the
seed's 3223 moves, on the strength of a value that is really just "posted".
A posted move whose `checked` is FALSE is the opposite: the compute would
have set it True, so False is there because somebody put it there, and
'todo' is what 20.0 calls that.

Nothing is written for a draft move. 19.0 left those unchecked by the same
formula, which says "not posted yet", not "waiting to be reviewed".

**This seed contains no such row** -- `checked` equals `state = 'posted'` on
all 3223 of its moves -- so the branch is unreachable here and the migration
test builds the row that reaches it. The count is reported either way, so a
database where it does fire says so in the log rather than only in the data.
"""
openupgrade.logged_query(
env.cr,
"""
UPDATE account_move
SET review_state = 'todo'
WHERE state = 'posted' AND NOT checked AND review_state = 'no_review'
""",
)
if env.cr.rowcount:
openupgrade.message(
env.cr,
"account",
False,
False,
"%s posted journal entr(ies) had been marked as NOT reviewed by hand "
"in 19.0 and are now in 20.0's review queue as 'todo'; entries that "
"merely carried the computed default were left on 'no_review'",
env.cr.rowcount,
)


@openupgrade.migrate()
def migrate(env, version):
openupgrade.load_data(env, "account", "20.0.1.5/noupdate_changes.xml")
openupgrade.delete_record_translations(
env.cr,
"account",
["email_template_edi_invoice", "email_template_edi_self_billing_invoice"],
["body_html"],
)
openupgrade.delete_record_translations(
env.cr,
"account",
["mail_template_data_payment_receipt"],
["body_html", "subject"],
)
_settle_in_process_payments(env)
_carry_a_deliberate_not_reviewed_into_the_review_queue(env)
20 changes: 20 additions & 0 deletions openupgrade_scripts/scripts/account/20.0.1.5/pre-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2026 Don Kendall
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from openupgradelib import openupgrade

_renamed_xmlids = [
# the stock valuation report moved from stock_account into account
(
"stock_account.action_report_stock_valuation",
"account.action_report_stock_valuation",
),
]


@openupgrade.migrate()
def migrate(env, version):
# The client action keeps its path, which is unique, so account's copy of
# the record has to land on the existing row instead of inserting a second
# one and tripping ir_act_client_path_unique.
openupgrade.rename_xmlids(env.cr, _renamed_xmlids)
Loading
Loading