[MIG] contract: Migration to 15.0

Most changes are related to the switch from jinja to qweb in mail templates.

Also included:
- convert deprecated onchange that returns a domain and other deprecation warnings
  (see below)
- Add migration scripts from version 14.0 (force the update of the mail templates)
- Fix warnings from pre-commit checks

Fixes depreciation warnings:

- onchange method ContractAbstractContractLine._onchange_product_id returned
  a domain, this is deprecated
- SavepointCase is deprecated:
  https://github.com/odoo/odoo/blob/15.0/odoo/tests/common.py#L742
- assertDictContainsSubset: According to:
  https://stackoverflow.com/questions/20050913/python-unittests-assertdictcontainssubset-recommended-alternative
This commit is contained in:
Jean-Charles Drubay
2021-10-28 18:24:51 +07:00
committed by Christopher Rogos
parent 162d266218
commit da393c937d
22 changed files with 510 additions and 363 deletions

View File

@@ -14,13 +14,13 @@ Recurring - Contracts Management
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github
:target: https://github.com/OCA/contract/tree/14.0/contract :target: https://github.com/OCA/contract/tree/15.0/contract
:alt: OCA/contract :alt: OCA/contract
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/contract-14-0/contract-14-0-contract :target: https://translation.odoo-community.org/projects/contract-15-0/contract-15-0-contract
:alt: Translate me on Weblate :alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/110/14.0 :target: https://runbot.odoo-community.org/runbot/110/15.0
:alt: Try me on Runbot :alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5| |badge1| |badge2| |badge3| |badge4| |badge5|
@@ -76,9 +76,9 @@ Usage
* Contracts appear in portal to following users in every contract: * Contracts appear in portal to following users in every contract:
.. image:: https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-my.png .. image:: https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-my.png
.. image:: https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-list.png .. image:: https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-list.png
.. image:: https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-detail.png .. image:: https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-detail.png
Known issues / Roadmap Known issues / Roadmap
====================== ======================
@@ -92,7 +92,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/contract/issues>`_. Bugs are tracked on `GitHub Issues <https://github.com/OCA/contract/issues>`_.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/contract/issues/new?body=module:%20contract%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. `feedback <https://github.com/OCA/contract/issues/new?body=module:%20contract%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues. Do not contact contributors directly about support or help with technical issues.
@@ -138,6 +138,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use. promote its widespread use.
This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/14.0/contract>`_ project on GitHub. This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/15.0/contract>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -11,7 +11,7 @@
{ {
"name": "Recurring - Contracts Management", "name": "Recurring - Contracts Management",
"version": "14.0.1.2.3", "version": "15.0.1.0.0",
"category": "Contract Management", "category": "Contract Management",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Tecnativa, ACSONE SA/NV, Odoo Community Association (OCA)", "author": "Tecnativa, ACSONE SA/NV, Odoo Community Association (OCA)",
@@ -35,7 +35,6 @@
"wizards/contract_manually_create_invoice.xml", "wizards/contract_manually_create_invoice.xml",
"wizards/contract_contract_terminate.xml", "wizards/contract_contract_terminate.xml",
"views/contract_tag.xml", "views/contract_tag.xml",
"views/assets.xml",
"views/abstract_contract_line.xml", "views/abstract_contract_line.xml",
"views/contract.xml", "views/contract.xml",
"views/contract_line.xml", "views/contract_line.xml",
@@ -46,5 +45,12 @@
"views/contract_terminate_reason.xml", "views/contract_terminate_reason.xml",
"views/contract_portal_templates.xml", "views/contract_portal_templates.xml",
], ],
"assets": {
"web.assets_backend": [
"contract/static/src/js/section_and_note_fields_backend.js",
],
"web.assets_frontend": ["contract/static/src/scss/frontend.scss"],
"web.assets_tests": ["contract/static/src/js/contract_portal_tour.js"],
},
"installable": True, "installable": True,
} }

View File

@@ -4,93 +4,121 @@
<field name="name">Email Contract Template</field> <field name="name">Email Contract Template</field>
<field <field
name="email_from" name="email_from"
>${(object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '')|safe}</field> >{{ (object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '') }}</field>
<field <field
name="subject" name="subject"
>${object.company_id.name} Contract (Ref ${object.name or 'n/a'})</field> >{{ object.company_id.name }} Contract (Ref {{ object.name or 'n/a' }})</field>
<field name="partner_to">${object.partner_id.id}</field> <field name="partner_to">{{ object.partner_id.id }}</field>
<field name="model_id" ref="model_contract_contract" /> <field name="model_id" ref="model_contract_contract" />
<field name="auto_delete" eval="True" /> <field name="auto_delete" eval="True" />
<field name="report_template" ref="contract.report_contract" /> <field name="report_template" ref="contract.report_contract" />
<field name="report_name">Contract</field> <field name="report_name">Contract</field>
<field name="lang">${object.partner_id.lang}</field> <field name="lang">{{ object.partner_id.lang }}</field>
<field <field name="body_html" type="html">
name="body_html" <div
><![CDATA[ style="font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; "
<div style="font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; "> >
<p>Hello ${object.partner_id.name or ''},</p> <p>Hello <t t-out="object.partner_id.name or '' " />,</p>
<p>A new contract has been created: </p> <p>A new contract has been created: </p>
<p style="border-left: 1px solid #8e0000; margin-left: 30px;"> <p style="border-left: 1px solid #8e0000; margin-left: 30px;">
&nbsp;&nbsp;<strong>REFERENCES</strong><br /> &amp;nbsp;&amp;nbsp;<strong>REFERENCES</strong><br />
&nbsp;&nbsp;Contract: <strong>${object.name}</strong><br /> &amp;nbsp;&amp;nbsp;Contract: <strong t-out="object.name" /><br />
% if object.date_start: <t t-if="object.date_start">
&nbsp;&nbsp;Contract Date Start: ${object.date_start or ''}<br /> &amp;nbsp;&amp;nbsp;Contract Date Start: <t
% endif t-out="object.date_start or ''"
/><br />
</t>
% if object.user_id: <t t-if="object.user_id">
% if object.user_id.email: <t t-if="object.user_id.email">
&nbsp;&nbsp;Your Contact: <a href="mailto:${object.user_id.email or ''}?subject=Contract%20${object.name}">${object.user_id.name}</a> &amp;nbsp;&amp;nbsp;Your Contact: <a
% else: t-att-href="'mailto:%s?subject=Contract %s' % (object.user_id.email, object.name)"
&nbsp;&nbsp;Your Contact: ${object.user_id.name} t-out="object.user_id.name"
% endif />
% endif </t>
</p> <t t-else="">
&amp;nbsp;&amp;nbsp;Your Contact: <t
t-out="object.user_id.name"
/>
</t>
</t>
</p>
<br/> <br />
<p>If you have any questions, do not hesitate to contact us.</p> <p>If you have any questions, do not hesitate to contact us.</p>
<p>Thank you for choosing ${object.company_id.name or 'us'}!</p> <p>Thank you for choosing <t
<br/> t-out="object.company_id.name or 'us'"
<br/> />!</p>
<div style="width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;"> <br />
<h3 style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;"> <br />
<strong style="text-transform:uppercase;">${object.company_id.name}</strong></h3> <div
</div> style="width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;"
<div style="width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;"> >
<span style="color: #222; margin-bottom: 5px; display: block; "> <h3
${object.company_id.partner_id.sudo().with_context(show_address=True, html_format=True).name_get()[0][1] | safe} style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;"
</span> >
% if object.company_id.phone: <strong
<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "> style="text-transform:uppercase;"
Phone: ${object.company_id.phone} t-out="object.company_id.name"
/></h3>
</div>
<div
style="width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;"
>
<span style="color: #222; margin-bottom: 5px; display: block; ">
<address
t-field="object.company_id.sudo().partner_id"
t-options='{"widget": "contact", "fields": ["name", "address"], "no_marker": True}'
/>
</span>
<t t-if="object.company_id.phone">
<div
style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "
>
Phone: <t t-out="object.company_id.phone" />
</div>
</t>
<t t-if="object.company_id.website">
<div>
Web: <a
t-att-href="object.company_id.website"
t-out="object.company_id.website"
/>
</div>
</t>
</div>
<br />
<a
t-att-href="'%s/my/contracts/%s?access_token=%s' % (object.get_base_url(), object.id, object.access_token)"
target="_blank"
style="background-color:#875A7B;padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;"
>View contract</a>
</div> </div>
% endif </field>
% if object.company_id.website:
<div>
Web: <a href="${object.company_id.website}">${object.company_id.website}</a>
</div>
%endif
<p></p>
</div>
<p></p>
<a href="${object.get_base_url()}/my/contracts/${object.id}?access_token=${object.access_token}" target="_blank" style="background-color:#875A7B;padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">View contract</a>
</div>
]]></field>
</record> </record>
<record id="mail_template_contract_modification" model="mail.template"> <record id="mail_template_contract_modification" model="mail.template">
<field name="name">Contract Modification Template</field> <field name="name">Contract Modification Template</field>
<field <field
name="email_from" name="email_from"
>${(object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '')|safe}</field> >{{ (object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '') }}</field>
<field <field
name="subject" name="subject"
>${object.company_id.name} Contract (Ref ${object.name or 'n/a'}) - Modifications</field> >{{ object.company_id.name }} Contract (Ref {{ object.name or 'n/a' }}) - Modifications</field>
<field name="model_id" ref="model_contract_contract" /> <field name="model_id" ref="model_contract_contract" />
<field name="lang">${object.partner_id.lang}</field> <field name="lang">{{ object.partner_id.lang }}</field>
<field <field name="body_html" type="html">
name="body_html"
><![CDATA[
<p>Hello</p> <p>Hello</p>
<p>We have modifications on the contract that we want to notify you.</p> <p>We have modifications on the contract that we want to notify you.</p>
]]></field> </field>
</record> </record>
<template <template
id="mail_notification_contract" id="mail_notification_contract"
inherit_id="mail.mail_notification_paynow" inherit_id="mail.mail_notification_paynow"
primary="True" primary="True"
> >
<xpath expr="//t[@t-raw='message.body']" position="after"> <xpath expr="//t[@t-out='message.body']" position="after">
<t t-raw="0" /> <t t-out="0" />
<t t-if="record._name == 'contract.contract'"> <t t-if="record._name == 'contract.contract'">
<t <t
t-set="share_url" t-set="share_url"

View File

@@ -4,7 +4,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
@@ -13,80 +13,66 @@ msgstr ""
"Content-Transfer-Encoding: \n" "Content-Transfer-Encoding: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#. module: contract
#: model:mail.template,body_html:contract.mail_template_contract_modification
msgid ""
"\n"
" <p>Hello</p>\n"
" <p>We have modifications on the contract that we want to notify you.</p>\n"
" "
msgstr ""
#. module: contract #. module: contract
#: model:mail.template,body_html:contract.email_contract_template #: model:mail.template,body_html:contract.email_contract_template
msgid "" msgid ""
"\n"
"<div style=\"font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n" "<div style=\"font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
" <p>Hello ${object.partner_id.name or ''},</p>\n" " <p>Hello <t t-out=\"object.partner_id.name or '' \"/>,</p>\n"
" <p>A new contract has been created: </p>\n" " <p>A new contract has been created: </p>\n"
"\n" "\n"
" <p style=\"border-left: 1px solid #8e0000; margin-left: 30px;\">\n" " <p style=\"border-left: 1px solid #8e0000; margin-left: 30px;\">\n"
" &nbsp;&nbsp;<strong>REFERENCES</strong><br />\n" " &amp;nbsp;&amp;nbsp;<strong>REFERENCES</strong><br/>\n"
" &nbsp;&nbsp;Contract: <strong>${object.name}</strong><br />\n" " &amp;nbsp;&amp;nbsp;Contract: <strong t-out=\"object.name\"/><br/>\n"
" % if object.date_start:\n" " <t t-if=\"object.date_start\">\n"
" &nbsp;&nbsp;Contract Date Start: ${object.date_start or ''}<br />\n" " &amp;nbsp;&amp;nbsp;Contract Date Start: <t t-out=\"object.date_start or ''\"/><br/>\n"
" % endif\n" " </t>\n"
"\n" "\n"
" % if object.user_id:\n" " <t t-if=\"object.user_id\">\n"
" % if object.user_id.email:\n" " <t t-if=\"object.user_id.email\">\n"
" &nbsp;&nbsp;Your Contact: <a href=\"mailto:${object.user_id.email or ''}?subject=Contract%20${object.name}\">${object.user_id.name}</a>\n" " &amp;nbsp;&amp;nbsp;Your Contact: <a t-att-href=\"'mailto:%s?subject=Contract %s' % (object.user_id.email, object.name)\" t-out=\"object.user_id.name\"/>\n"
" % else:\n" " </t>\n"
" &nbsp;&nbsp;Your Contact: ${object.user_id.name}\n" " <t t-else=\"\">\n"
" % endif\n" " &amp;nbsp;&amp;nbsp;Your Contact: <t t-out=\"object.user_id.name\"/>\n"
" % endif\n" " </t>\n"
" </p>\n" " </t>\n"
" </p>\n"
"\n" "\n"
" <br/>\n" " <br/>\n"
" <p>If you have any questions, do not hesitate to contact us.</p>\n" " <p>If you have any questions, do not hesitate to contact us.</p>\n"
" <p>Thank you for choosing ${object.company_id.name or 'us'}!</p>\n" " <p>Thank you for choosing <t t-out=\"object.company_id.name or 'us'\"/>!</p>\n"
" <br/>\n" " <br/>\n"
" <br/>\n" " <br/>\n"
" <div style=\"width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;\">\n" " <div style=\"width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;\">\n"
" <h3 style=\"margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;\">\n" " <h3 style=\"margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;\">\n"
" <strong style=\"text-transform:uppercase;\">${object.company_id.name}</strong></h3>\n" " <strong style=\"text-transform:uppercase;\" t-out=\"object.company_id.name\"/></h3>\n"
" </div>\n" " </div>\n"
" <div style=\"width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;\">\n" " <div style=\"width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;\">\n"
" <span style=\"color: #222; margin-bottom: 5px; display: block; \">\n" " <span style=\"color: #222; margin-bottom: 5px; display: block; \">\n"
" ${object.company_id.partner_id.sudo().with_context(show_address=True, html_format=True).name_get()[0][1] | safe}\n" " <address t-field=\"object.company_id.sudo().partner_id\" t-options=\"{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;name&quot;, &quot;address&quot;], &quot;no_marker&quot;: True}\"/>\n"
" </span>\n" " </span>\n"
" % if object.company_id.phone:\n" " <t t-if=\"object.company_id.phone\">\n"
" <div style=\"margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; \">\n" " <div style=\"margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; \">\n"
" Phone: ${object.company_id.phone}\n" " Phone: <t t-out=\"object.company_id.phone\"/>\n"
" </div>\n"
" </t>\n"
" <t t-if=\"object.company_id.website\">\n"
" <div>\n"
" Web: <a t-att-href=\"object.company_id.website\" t-out=\"object.company_id.website\"/>\n"
" </div>\n"
" </t>\n"
" </div>\n"
" <br/>\n"
" <a t-att-href=\"'%s/my/contracts/%s?access_token=%s' % (object.get_base_url(), object.id, object.access_token)\" target=\"_blank\" style=\"background-color:#875A7B;padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;\">View contract</a>\n"
" </div>\n" " </div>\n"
" % endif\n"
" % if object.company_id.website:\n"
" <div>\n"
" Web: <a href=\"${object.company_id.website}\">${object.company_id.website}</a>\n"
" </div>\n"
" %endif\n"
" <p></p>\n"
" </div>\n"
" <p></p>\n"
" <a href=\"${object.get_base_url()}/my/contracts/${object.id}?access_token=${object.access_token}\" target=\"_blank\" style=\"background-color:#875A7B;padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;\">View contract</a>\n"
"</div>\n"
" " " "
msgstr "" msgstr ""
#. module: contract #. module: contract
#: model:mail.template,subject:contract.email_contract_template #: model:mail.template,body_html:contract.mail_template_contract_modification
msgid "${object.company_id.name} Contract (Ref ${object.name or 'n/a'})"
msgstr ""
#. module: contract
#: model:mail.template,subject:contract.mail_template_contract_modification
msgid "" msgid ""
"${object.company_id.name} Contract (Ref ${object.name or 'n/a'}) - " "<p>Hello</p>\n"
"Modifications" " <p>We have modifications on the contract that we want to notify you.</p>\n"
" "
msgstr "" msgstr ""
#. module: contract #. module: contract
@@ -352,7 +338,6 @@ msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__is_auto_renew #: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__is_auto_renew
#: model:ir.model.fields,field_description:contract.field_contract_line__is_auto_renew #: model:ir.model.fields,field_description:contract.field_contract_line__is_auto_renew
#: model:ir.model.fields,field_description:contract.field_contract_line_wizard__is_auto_renew
#: model:ir.model.fields,field_description:contract.field_contract_template_line__is_auto_renew #: model:ir.model.fields,field_description:contract.field_contract_template_line__is_auto_renew
msgid "Auto Renew" msgid "Auto Renew"
msgstr "" msgstr ""
@@ -405,6 +390,13 @@ msgstr ""
msgid "Canceled" msgid "Canceled"
msgstr "" msgstr ""
#. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__product_uom_category_id
#: model:ir.model.fields,field_description:contract.field_contract_line__product_uom_category_id
#: model:ir.model.fields,field_description:contract.field_contract_template_line__product_uom_category_id
msgid "Category"
msgstr ""
#. module: contract #. module: contract
#: model_terms:ir.actions.act_window,help:contract.contract_template_action #: model_terms:ir.actions.act_window,help:contract.contract_template_action
msgid "Click to create a new contract template." msgid "Click to create a new contract template."
@@ -526,6 +518,11 @@ msgstr ""
msgid "Contract Modification" msgid "Contract Modification"
msgstr "" msgstr ""
#. module: contract
#: model:mail.template,name:contract.mail_template_contract_modification
msgid "Contract Modification Template"
msgstr ""
#. module: contract #. module: contract
#: model_terms:ir.ui.view,arch_db:contract.contract_contract_form_view #: model_terms:ir.ui.view,arch_db:contract.contract_contract_form_view
msgid "Contract Name" msgid "Contract Name"
@@ -601,7 +598,7 @@ msgstr ""
#. module: contract #. module: contract
#: code:addons/contract/models/contract_line.py:0 #: code:addons/contract/models/contract_line.py:0
#, python-format #, python-format
msgid "Contract line Un-canceled: %s<br/>- " msgid "Contract line Un-canceled: %s"
msgstr "" msgstr ""
#. module: contract #. module: contract
@@ -619,16 +616,16 @@ msgstr ""
#. module: contract #. module: contract
#: code:addons/contract/models/contract_line.py:0 #: code:addons/contract/models/contract_line.py:0
#, python-format #, python-format
msgid "Contract line canceled: %s<br/>- " msgid "Contract line canceled: %s"
msgstr "" msgstr ""
#. module: contract #. module: contract
#: code:addons/contract/models/contract_line.py:0 #: code:addons/contract/models/contract_line.py:0
#, python-format #, python-format
msgid "" msgid ""
"Contract line for <strong>{product}</strong>\n" "Contract line for <strong>%(product)s</strong>\n"
" stopped: <br/>\n" " stopped: <br/>\n"
" - <strong>End</strong>: {old_end} -- {new_end}\n" " - <strong>End</strong>: %(old_end)s -- %(new_end)s\n"
" " " "
msgstr "" msgstr ""
@@ -636,11 +633,11 @@ msgstr ""
#: code:addons/contract/models/contract_line.py:0 #: code:addons/contract/models/contract_line.py:0
#, python-format #, python-format
msgid "" msgid ""
"Contract line for <strong>{product}</strong>\n" "Contract line for <strong>%(product)s</strong>\n"
" planned a successor: <br/>\n" " planned a successor: <br/>\n"
" - <strong>Start</strong>: {new_date_start}\n" " - <strong>Start</strong>: %(new_date_start)s\n"
" <br/>\n" " <br/>\n"
" - <strong>End</strong>: {new_date_end}\n" " - <strong>End</strong>: %(new_date_end)s\n"
" " " "
msgstr "" msgstr ""
@@ -648,11 +645,11 @@ msgstr ""
#: code:addons/contract/models/contract_line.py:0 #: code:addons/contract/models/contract_line.py:0
#, python-format #, python-format
msgid "" msgid ""
"Contract line for <strong>{product}</strong>\n" "Contract line for <strong>%(product)s</strong>\n"
" renewed: <br/>\n" " renewed: <br/>\n"
" - <strong>Start</strong>: {new_date_start}\n" " - <strong>Start</strong>: %(new_date_start)s\n"
" <br/>\n" " <br/>\n"
" - <strong>End</strong>: {new_date_end}\n" " - <strong>End</strong>: %(new_date_end)s\n"
" " " "
msgstr "" msgstr ""
@@ -660,11 +657,11 @@ msgstr ""
#: code:addons/contract/models/contract_line.py:0 #: code:addons/contract/models/contract_line.py:0
#, python-format #, python-format
msgid "" msgid ""
"Contract line for <strong>{product}</strong>\n" "Contract line for <strong>%(product)s</strong>\n"
" suspended: <br/>\n" " suspended: <br/>\n"
" - <strong>Suspension Start</strong>: {new_date_start}\n" " - <strong>Suspension Start</strong>: %(new_date_start)s\n"
" <br/>\n" " <br/>\n"
" - <strong>Suspension End</strong>: {new_date_end}\n" " - <strong>Suspension End</strong>: %(new_date_end)s\n"
" " " "
msgstr "" msgstr ""
@@ -688,8 +685,8 @@ msgstr ""
#: code:addons/contract/models/contract.py:0 #: code:addons/contract/models/contract.py:0
#, python-format #, python-format
msgid "" msgid ""
"Contract manually invoiced: <a href=\"#\" data-oe-model=\"%s\" data-oe-" "Contract manually invoiced: <a href=\"#\" data-oe-"
"id=\"%s\">Invoice</a>" "model=\"%(model_name)s\" data-oe-id=\"%(rec_id)s\">Invoice</a>"
msgstr "" msgstr ""
#. module: contract #. module: contract
@@ -729,6 +726,15 @@ msgstr ""
msgid "Contracts to invoice" msgid "Contracts to invoice"
msgstr "" msgstr ""
#. module: contract
#: model:ir.model.fields,help:contract.field_contract_abstract_contract_line__product_uom_category_id
#: model:ir.model.fields,help:contract.field_contract_line__product_uom_category_id
#: model:ir.model.fields,help:contract.field_contract_template_line__product_uom_category_id
msgid ""
"Conversion between Units of Measure can only occur if they belong to the "
"same category. The conversion will be made based on the ratios."
msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__create_invoice_visibility #: model:ir.model.fields,field_description:contract.field_contract_contract__create_invoice_visibility
#: model:ir.model.fields,field_description:contract.field_contract_line__create_invoice_visibility #: model:ir.model.fields,field_description:contract.field_contract_line__create_invoice_visibility
@@ -929,25 +935,16 @@ msgid ""
msgstr "" msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_account_move__display_name
#: model:ir.model.fields,field_description:contract.field_account_move_line__display_name
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract__display_name
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__display_name
#: model:ir.model.fields,field_description:contract.field_contract_contract__display_name #: model:ir.model.fields,field_description:contract.field_contract_contract__display_name
#: model:ir.model.fields,field_description:contract.field_contract_contract_terminate__display_name #: model:ir.model.fields,field_description:contract.field_contract_contract_terminate__display_name
#: model:ir.model.fields,field_description:contract.field_contract_line__display_name #: model:ir.model.fields,field_description:contract.field_contract_line__display_name
#: model:ir.model.fields,field_description:contract.field_contract_line_wizard__display_name #: model:ir.model.fields,field_description:contract.field_contract_line_wizard__display_name
#: model:ir.model.fields,field_description:contract.field_contract_manually_create_invoice__display_name #: model:ir.model.fields,field_description:contract.field_contract_manually_create_invoice__display_name
#: model:ir.model.fields,field_description:contract.field_contract_modification__display_name #: model:ir.model.fields,field_description:contract.field_contract_modification__display_name
#: model:ir.model.fields,field_description:contract.field_contract_recurrency_basic_mixin__display_name
#: model:ir.model.fields,field_description:contract.field_contract_recurrency_mixin__display_name
#: model:ir.model.fields,field_description:contract.field_contract_tag__display_name #: model:ir.model.fields,field_description:contract.field_contract_tag__display_name
#: model:ir.model.fields,field_description:contract.field_contract_template__display_name #: model:ir.model.fields,field_description:contract.field_contract_template__display_name
#: model:ir.model.fields,field_description:contract.field_contract_template_line__display_name #: model:ir.model.fields,field_description:contract.field_contract_template_line__display_name
#: model:ir.model.fields,field_description:contract.field_contract_terminate_reason__display_name #: model:ir.model.fields,field_description:contract.field_contract_terminate_reason__display_name
#: model:ir.model.fields,field_description:contract.field_res_company__display_name
#: model:ir.model.fields,field_description:contract.field_res_config_settings__display_name
#: model:ir.model.fields,field_description:contract.field_res_partner__display_name
msgid "Display Name" msgid "Display Name"
msgstr "" msgstr ""
@@ -958,6 +955,11 @@ msgstr ""
msgid "Display Type" msgid "Display Type"
msgstr "" msgstr ""
#. module: contract
#: model:mail.template,name:contract.email_contract_template
msgid "Email Contract Template"
msgstr ""
#. module: contract #. module: contract
#: model_terms:ir.ui.view,arch_db:contract.contract_contract_search_view #: model_terms:ir.ui.view,arch_db:contract.contract_contract_search_view
msgid "Finished" msgid "Finished"
@@ -973,11 +975,6 @@ msgstr ""
msgid "Followers" msgid "Followers"
msgstr "" msgstr ""
#. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__message_channel_ids
msgid "Followers (Channels)"
msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__message_partner_ids #: model:ir.model.fields,field_description:contract.field_contract_contract__message_partner_ids
msgid "Followers (Partners)" msgid "Followers (Partners)"
@@ -1006,25 +1003,21 @@ msgid "Group By..."
msgstr "" msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_account_move__id #: model:ir.model.fields,field_description:contract.field_contract_contract__has_message
#: model:ir.model.fields,field_description:contract.field_account_move_line__id msgid "Has Message"
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract__id msgstr ""
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__id
#. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__id #: model:ir.model.fields,field_description:contract.field_contract_contract__id
#: model:ir.model.fields,field_description:contract.field_contract_contract_terminate__id #: model:ir.model.fields,field_description:contract.field_contract_contract_terminate__id
#: model:ir.model.fields,field_description:contract.field_contract_line__id #: model:ir.model.fields,field_description:contract.field_contract_line__id
#: model:ir.model.fields,field_description:contract.field_contract_line_wizard__id #: model:ir.model.fields,field_description:contract.field_contract_line_wizard__id
#: model:ir.model.fields,field_description:contract.field_contract_manually_create_invoice__id #: model:ir.model.fields,field_description:contract.field_contract_manually_create_invoice__id
#: model:ir.model.fields,field_description:contract.field_contract_modification__id #: model:ir.model.fields,field_description:contract.field_contract_modification__id
#: model:ir.model.fields,field_description:contract.field_contract_recurrency_basic_mixin__id
#: model:ir.model.fields,field_description:contract.field_contract_recurrency_mixin__id
#: model:ir.model.fields,field_description:contract.field_contract_tag__id #: model:ir.model.fields,field_description:contract.field_contract_tag__id
#: model:ir.model.fields,field_description:contract.field_contract_template__id #: model:ir.model.fields,field_description:contract.field_contract_template__id
#: model:ir.model.fields,field_description:contract.field_contract_template_line__id #: model:ir.model.fields,field_description:contract.field_contract_template_line__id
#: model:ir.model.fields,field_description:contract.field_contract_terminate_reason__id #: model:ir.model.fields,field_description:contract.field_contract_terminate_reason__id
#: model:ir.model.fields,field_description:contract.field_res_company__id
#: model:ir.model.fields,field_description:contract.field_res_config_settings__id
#: model:ir.model.fields,field_description:contract.field_res_partner__id
msgid "ID" msgid "ID"
msgstr "" msgstr ""
@@ -1161,6 +1154,11 @@ msgstr ""
msgid "Invoicing type" msgid "Invoicing type"
msgstr "" msgstr ""
#. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_line_wizard__is_auto_renew
msgid "Is Auto Renew"
msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__message_is_follower #: model:ir.model.fields,field_description:contract.field_contract_contract__message_is_follower
msgid "Is Follower" msgid "Is Follower"
@@ -1206,25 +1204,16 @@ msgid "Last Date Invoiced"
msgstr "" msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_account_move____last_update
#: model:ir.model.fields,field_description:contract.field_account_move_line____last_update
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract____last_update
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line____last_update
#: model:ir.model.fields,field_description:contract.field_contract_contract____last_update #: model:ir.model.fields,field_description:contract.field_contract_contract____last_update
#: model:ir.model.fields,field_description:contract.field_contract_contract_terminate____last_update #: model:ir.model.fields,field_description:contract.field_contract_contract_terminate____last_update
#: model:ir.model.fields,field_description:contract.field_contract_line____last_update #: model:ir.model.fields,field_description:contract.field_contract_line____last_update
#: model:ir.model.fields,field_description:contract.field_contract_line_wizard____last_update #: model:ir.model.fields,field_description:contract.field_contract_line_wizard____last_update
#: model:ir.model.fields,field_description:contract.field_contract_manually_create_invoice____last_update #: model:ir.model.fields,field_description:contract.field_contract_manually_create_invoice____last_update
#: model:ir.model.fields,field_description:contract.field_contract_modification____last_update #: model:ir.model.fields,field_description:contract.field_contract_modification____last_update
#: model:ir.model.fields,field_description:contract.field_contract_recurrency_basic_mixin____last_update
#: model:ir.model.fields,field_description:contract.field_contract_recurrency_mixin____last_update
#: model:ir.model.fields,field_description:contract.field_contract_tag____last_update #: model:ir.model.fields,field_description:contract.field_contract_tag____last_update
#: model:ir.model.fields,field_description:contract.field_contract_template____last_update #: model:ir.model.fields,field_description:contract.field_contract_template____last_update
#: model:ir.model.fields,field_description:contract.field_contract_template_line____last_update #: model:ir.model.fields,field_description:contract.field_contract_template_line____last_update
#: model:ir.model.fields,field_description:contract.field_contract_terminate_reason____last_update #: model:ir.model.fields,field_description:contract.field_contract_terminate_reason____last_update
#: model:ir.model.fields,field_description:contract.field_res_company____last_update
#: model:ir.model.fields,field_description:contract.field_res_config_settings____last_update
#: model:ir.model.fields,field_description:contract.field_res_partner____last_update
msgid "Last Modified on" msgid "Last Modified on"
msgstr "" msgstr ""
@@ -1275,7 +1264,7 @@ msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_line__manual_renew_needed #: model:ir.model.fields,field_description:contract.field_contract_line__manual_renew_needed
#: model:ir.model.fields,field_description:contract.field_contract_line_wizard__manual_renew_needed #: model:ir.model.fields,field_description:contract.field_contract_line_wizard__manual_renew_needed
msgid "Manual renew needed" msgid "Manual Renew Needed"
msgstr "" msgstr ""
#. module: contract #. module: contract
@@ -1504,7 +1493,8 @@ msgstr ""
#. module: contract #. module: contract
#: code:addons/contract/models/contract.py:0 #: code:addons/contract/models/contract.py:0
#, python-format #, python-format
msgid "Please define a %s journal for the company '%s'." msgid ""
"Please define a %(contract_type)s journal for the company '%(company)s'."
msgstr "" msgstr ""
#. module: contract #. module: contract
@@ -1931,6 +1921,11 @@ msgstr ""
msgid "Termination Notice Before" msgid "Termination Notice Before"
msgstr "" msgstr ""
#. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_line__termination_notice_date
msgid "Termination Notice Date"
msgstr ""
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__termination_notice_rule_type #: model:ir.model.fields,field_description:contract.field_contract_abstract_contract_line__termination_notice_rule_type
#: model:ir.model.fields,field_description:contract.field_contract_line__termination_notice_rule_type #: model:ir.model.fields,field_description:contract.field_contract_line__termination_notice_rule_type
@@ -1944,11 +1939,6 @@ msgstr ""
msgid "Termination Reason" msgid "Termination Reason"
msgstr "" msgstr ""
#. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_line__termination_notice_date
msgid "Termination notice date"
msgstr ""
#. module: contract #. module: contract
#: model_terms:ir.ui.view,arch_db:contract.contract_contract_form_view #: model_terms:ir.ui.view,arch_db:contract.contract_contract_form_view
msgid "This contract was terminated for the reason" msgid "This contract was terminated for the reason"
@@ -2162,3 +2152,15 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:contract.contract_contract_form_view #: model_terms:ir.ui.view,arch_db:contract.contract_contract_form_view
msgid "on" msgid "on"
msgstr "" msgstr ""
#. module: contract
#: model:mail.template,subject:contract.email_contract_template
msgid "{{ object.company_id.name }} Contract (Ref {{ object.name or 'n/a' }})"
msgstr ""
#. module: contract
#: model:mail.template,subject:contract.mail_template_contract_modification
msgid ""
"{{ object.company_id.name }} Contract (Ref {{ object.name or 'n/a' }}) - "
"Modifications"
msgstr ""

View File

@@ -1566,7 +1566,7 @@ msgstr ""
#: code:addons/contract/models/contract.py:0 #: code:addons/contract/models/contract.py:0
#, fuzzy, python-format #, fuzzy, python-format
msgid "Please define a %s journal for the company '%s'." msgid "Please define a %s journal for the company '%s'."
msgstr "Molimo definirajte dnevnik prodaje za poduzeće '%s'." msgstr "Molimo definirajte dnevnik prodaje '%s' za poduzeće '%s'."
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__access_url #: model:ir.model.fields,field_description:contract.field_contract_contract__access_url

View File

@@ -1581,7 +1581,7 @@ msgstr "Pianificazione successore non permessa per questa riga"
#: code:addons/contract/models/contract.py:0 #: code:addons/contract/models/contract.py:0
#, python-format #, python-format
msgid "Please define a %s journal for the company '%s'." msgid "Please define a %s journal for the company '%s'."
msgstr "Definire un registro vendite per l'azienda \"%s\"." msgstr "Definire un registro vendite %s per l'azienda \"%s\"."
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__access_url #: model:ir.model.fields,field_description:contract.field_contract_contract__access_url

View File

@@ -1564,7 +1564,7 @@ msgstr ""
#: code:addons/contract/models/contract.py:0 #: code:addons/contract/models/contract.py:0
#, fuzzy, python-format #, fuzzy, python-format
msgid "Please define a %s journal for the company '%s'." msgid "Please define a %s journal for the company '%s'."
msgstr "Lütfen '%s' şirketi için bir satış yevmiyesi tanımlayın." msgstr "Lütfen '%s' şirketi için bir satış yevmiyesi tanımlayın ('%s')."
#. module: contract #. module: contract
#: model:ir.model.fields,field_description:contract.field_contract_contract__access_url #: model:ir.model.fields,field_description:contract.field_contract_contract__access_url

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
This is a copy / paste from contract/data/mail_template.xml
The only differences are:
- Use noupdate=0
- remove template_contract_modification which remains unchanged between 14 and 15
-->
<odoo>
<record id="email_contract_template" model="mail.template">
<field name="name">Email Contract Template</field>
<field
name="email_from"
>{{ (object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '') }}</field>
<field
name="subject"
>{{ object.company_id.name }} Contract (Ref {{ object.name or 'n/a' }})</field>
<field name="partner_to">{{ object.partner_id.id }}</field>
<field name="model_id" ref="model_contract_contract" />
<field name="auto_delete" eval="True" />
<field name="report_template" ref="contract.report_contract" />
<field name="report_name">Contract</field>
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="body_html" type="html">
<div
style="font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; "
>
<p>Hello <t t-out="object.partner_id.name or '' " />,</p>
<p>A new contract has been created: </p>
<p style="border-left: 1px solid #8e0000; margin-left: 30px;">
&amp;nbsp;&amp;nbsp;<strong>REFERENCES</strong><br />
&amp;nbsp;&amp;nbsp;Contract: <strong t-out="object.name" /><br />
<t t-if="object.date_start">
&amp;nbsp;&amp;nbsp;Contract Date Start: <t
t-out="object.date_start or ''"
/><br />
</t>
<t t-if="object.user_id">
<t t-if="object.user_id.email">
&amp;nbsp;&amp;nbsp;Your Contact: <a
t-att-href="'mailto:%s?subject=Contract %s' % (object.user_id.email, object.name)"
t-out="object.user_id.name"
/>
</t>
<t t-else="">
&amp;nbsp;&amp;nbsp;Your Contact: <t
t-out="object.user_id.name"
/>
</t>
</t>
</p>
<br />
<p>If you have any questions, do not hesitate to contact us.</p>
<p>Thank you for choosing <t
t-out="object.company_id.name or 'us'"
/>!</p>
<br />
<br />
<div
style="width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;"
>
<h3
style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;"
>
<strong
style="text-transform:uppercase;"
t-out="object.company_id.name"
/></h3>
</div>
<div
style="width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;"
>
<span style="color: #222; margin-bottom: 5px; display: block; ">
<address
t-field="object.company_id.sudo().partner_id"
t-options='{"widget": "contact", "fields": ["name", "address"], "no_marker": True}'
/>
</span>
<t t-if="object.company_id.phone">
<div
style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "
>
Phone: <t t-out="object.company_id.phone" />
</div>
</t>
<t t-if="object.company_id.website">
<div>
Web: <a
t-att-href="object.company_id.website"
t-out="object.company_id.website"
/>
</div>
</t>
</div>
<br />
<a
t-att-href="'%s/my/contracts/%s?access_token=%s' % (object.get_base_url(), object.id, object.access_token)"
target="_blank"
style="background-color:#875A7B;padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;"
>View contract</a>
</div>
</field>
</record>
<record id="mail_template_contract_modification" model="mail.template">
<field name="name">Contract Modification Template</field>
<field
name="email_from"
>{{ (object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '') }}</field>
<field
name="subject"
>{{ object.company_id.name }} Contract (Ref {{ object.name or 'n/a' }}) - Modifications</field>
<field name="model_id" ref="model_contract_contract" />
<field name="lang">{{ object.partner_id.lang }}</field>
<field name="body_html" type="html">
<p>Hello</p>
<p>We have modifications on the contract that we want to notify you.</p>
</field>
</record>
<template
id="mail_notification_contract"
inherit_id="mail.mail_notification_paynow"
primary="True"
>
<xpath expr="//t[@t-out='message.body']" position="after">
<t t-out="0" />
<t t-if="record._name == 'contract.contract'">
<t
t-set="share_url"
t-value="record._get_share_url(redirect=True, signup_partner=True, share_token=True)"
/>
<t
t-set="access_url"
t-value="is_online and share_url and base_url + share_url or ''"
/>
</t>
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,17 @@
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
openupgrade.load_data(
env.cr, "contract", "migrations/15.0.1.0.0/noupdate_changes.xml"
)
openupgrade.delete_record_translations(
env.cr,
"contract",
[
"email_contract_template",
"mail_template_contract_modification",
"mail_notification_contract",
],
)

View File

@@ -20,14 +20,22 @@ class ContractAbstractContractLine(models.AbstractModel):
name = fields.Text(string="Description", required=True) name = fields.Text(string="Description", required=True)
quantity = fields.Float(default=1.0, required=True) quantity = fields.Float(default=1.0, required=True)
uom_id = fields.Many2one("uom.uom", string="Unit of Measure") product_uom_category_id = fields.Many2one( # Used for domain of field uom_id
comodel_name="uom.category",
related="product_id.uom_id.category_id",
)
uom_id = fields.Many2one(
comodel_name="uom.uom",
string="Unit of Measure",
domain="[('category_id', '=', product_uom_category_id)]",
)
automatic_price = fields.Boolean( automatic_price = fields.Boolean(
string="Auto-price?", string="Auto-price?",
help="If this is marked, the price will be obtained automatically " help="If this is marked, the price will be obtained automatically "
"applying the pricelist to the product. If not, you will be " "applying the pricelist to the product. If not, you will be "
"able to introduce a manual price", "able to introduce a manual price",
) )
specific_price = fields.Float(string="Specific Price") specific_price = fields.Float()
price_unit = fields.Float( price_unit = fields.Float(
string="Unit Price", string="Unit Price",
compute="_compute_price_unit", compute="_compute_price_unit",
@@ -45,7 +53,6 @@ class ContractAbstractContractLine(models.AbstractModel):
" It should be less or equal to 100", " It should be less or equal to 100",
) )
sequence = fields.Integer( sequence = fields.Integer(
string="Sequence",
default=10, default=10,
help="Sequence of the contract line when displaying contracts", help="Sequence of the contract line when displaying contracts",
) )
@@ -76,7 +83,7 @@ class ContractAbstractContractLine(models.AbstractModel):
readonly=False, readonly=False,
copy=True, copy=True,
) )
last_date_invoiced = fields.Date(string="Last Date Invoiced") last_date_invoiced = fields.Date()
is_canceled = fields.Boolean(string="Canceled", default=False) is_canceled = fields.Boolean(string="Canceled", default=False)
is_auto_renew = fields.Boolean(string="Auto Renew", default=False) is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
auto_renew_interval = fields.Integer( auto_renew_interval = fields.Integer(
@@ -157,6 +164,7 @@ class ContractAbstractContractLine(models.AbstractModel):
def _compute_date_start(self): def _compute_date_start(self):
self._set_recurrence_field("date_start") self._set_recurrence_field("date_start")
# pylint: disable=missing-return
@api.depends("contract_id.recurring_next_date", "contract_id.line_recurrence") @api.depends("contract_id.recurring_next_date", "contract_id.line_recurrence")
def _compute_recurring_next_date(self): def _compute_recurring_next_date(self):
super()._compute_recurring_next_date() super()._compute_recurring_next_date()
@@ -232,13 +240,7 @@ class ContractAbstractContractLine(models.AbstractModel):
@api.onchange("product_id") @api.onchange("product_id")
def _onchange_product_id(self): def _onchange_product_id(self):
if not self.product_id:
return {"domain": {"uom_id": []}}
vals = {} vals = {}
domain = {
"uom_id": [("category_id", "=", self.product_id.uom_id.category_id.id)]
}
if not self.uom_id or ( if not self.uom_id or (
self.product_id.uom_id.category_id.id != self.uom_id.category_id.id self.product_id.uom_id.category_id.id != self.uom_id.category_id.id
): ):
@@ -257,4 +259,3 @@ class ContractAbstractContractLine(models.AbstractModel):
vals["name"] = self.product_id.get_product_multiline_description_sale() vals["name"] = self.product_id.get_product_multiline_description_sale()
vals["price_unit"] = product.price vals["price_unit"] = product.price
self.update(vals) self.update(vals)
return {"domain": domain}

View File

@@ -89,6 +89,7 @@ class ContractContract(models.Model):
string="Invoicing contact", string="Invoicing contact",
comodel_name="res.partner", comodel_name="res.partner",
ondelete="restrict", ondelete="restrict",
domain="['|',('id', 'parent_of', partner_id), ('id', 'child_of', partner_id)]",
) )
partner_id = fields.Many2one( partner_id = fields.Many2one(
comodel_name="res.partner", inverse="_inverse_partner_id", required=True comodel_name="res.partner", inverse="_inverse_partner_id", required=True
@@ -299,7 +300,7 @@ class ContractContract(models.Model):
@api.depends( @api.depends(
"contract_line_ids.recurring_next_date", "contract_line_ids.recurring_next_date",
"contract_line_ids.is_canceled", "contract_line_ids.is_canceled",
) ) # pylint: disable=missing-return
def _compute_recurring_next_date(self): def _compute_recurring_next_date(self):
for contract in self: for contract in self:
recurring_next_date = contract.contract_line_ids.filtered( recurring_next_date = contract.contract_line_ids.filtered(
@@ -371,15 +372,6 @@ class ContractContract(models.Model):
else: else:
self.payment_term_id = partner.property_payment_term_id self.payment_term_id = partner.property_payment_term_id
self.invoice_partner_id = self.partner_id.address_get(["invoice"])["invoice"] self.invoice_partner_id = self.partner_id.address_get(["invoice"])["invoice"]
return {
"domain": {
"invoice_partner_id": [
"|",
("id", "parent_of", self.partner_id.id),
("id", "child_of", self.partner_id.id),
]
}
}
def _convert_contract_lines(self, contract): def _convert_contract_lines(self, contract):
self.ensure_one() self.ensure_one()
@@ -416,8 +408,14 @@ class ContractContract(models.Model):
) )
if not journal: if not journal:
raise ValidationError( raise ValidationError(
_("Please define a %s journal for the company '%s'.") _(
% (self.contract_type, self.company_id.name or "") "Please define a %(contract_type)s journal "
"for the company '%(company)s'."
)
% {
"contract_type": self.contract_type,
"company": self.company_id.name or "",
}
) )
invoice_type = "out_invoice" invoice_type = "out_invoice"
if self.contract_type == "purchase": if self.contract_type == "purchase":
@@ -566,10 +564,16 @@ class ContractContract(models.Model):
self.message_post( self.message_post(
body=_( body=_(
"Contract manually invoiced: " "Contract manually invoiced: "
'<a href="#" data-oe-model="%s" data-oe-id="%s">Invoice' "<a"
' href="#" data-oe-model="%(model_name)s" '
' data-oe-id="%(rec_id)s"'
">Invoice"
"</a>" "</a>"
) )
% (invoice._name, invoice.id) % {
"model_name": invoice._name,
"rec_id": invoice.id,
}
) )
return invoice return invoice

View File

@@ -22,9 +22,7 @@ class ContractLine(models.Model):
] ]
_order = "sequence,id" _order = "sequence,id"
sequence = fields.Integer( sequence = fields.Integer()
string="Sequence",
)
contract_id = fields.Many2one( contract_id = fields.Many2one(
comodel_name="contract.contract", comodel_name="contract.contract",
string="Contract", string="Contract",
@@ -44,7 +42,6 @@ class ContractLine(models.Model):
date_start = fields.Date(required=True) date_start = fields.Date(required=True)
date_end = fields.Date(compute="_compute_date_end", store=True, readonly=False) date_end = fields.Date(compute="_compute_date_end", store=True, readonly=False)
termination_notice_date = fields.Date( termination_notice_date = fields.Date(
string="Termination notice date",
compute="_compute_termination_notice_date", compute="_compute_termination_notice_date",
store=True, store=True,
copy=False, copy=False,
@@ -72,7 +69,6 @@ class ContractLine(models.Model):
help="Contract Line origin of this one.", help="Contract Line origin of this one.",
) )
manual_renew_needed = fields.Boolean( manual_renew_needed = fields.Boolean(
string="Manual renew needed",
default=False, default=False,
help="This flag is used to make a difference between a definitive stop" help="This flag is used to make a difference between a definitive stop"
"and temporary one for which a user is not able to plan a" "and temporary one for which a user is not able to plan a"
@@ -92,7 +88,6 @@ class ContractLine(models.Model):
string="Un-Cancel allowed?", compute="_compute_allowed" string="Un-Cancel allowed?", compute="_compute_allowed"
) )
state = fields.Selection( state = fields.Selection(
string="State",
selection=[ selection=[
("upcoming", "Upcoming"), ("upcoming", "Upcoming"),
("in-progress", "In-progress"), ("in-progress", "In-progress"),
@@ -109,12 +104,11 @@ class ContractLine(models.Model):
related="contract_id.active", related="contract_id.active",
store=True, store=True,
readonly=True, readonly=True,
default=True,
) )
@api.depends( @api.depends(
"last_date_invoiced", "date_start", "date_end", "contract_id.last_date_invoiced" "last_date_invoiced", "date_start", "date_end", "contract_id.last_date_invoiced"
) ) # pylint: disable=missing-return
def _compute_next_period_date_start(self): def _compute_next_period_date_start(self):
"""Rectify next period date start if another line in the contract has been """Rectify next period date start if another line in the contract has been
already invoiced previously when the recurrence is by contract. already invoiced previously when the recurrence is by contract.
@@ -696,15 +690,15 @@ class ContractLine(models.Model):
) )
if post_message: if post_message:
msg = _( msg = _(
"""Contract line for <strong>{product}</strong> """Contract line for <strong>%(product)s</strong>
stopped: <br/> stopped: <br/>
- <strong>End</strong>: {old_end} -- {new_end} - <strong>End</strong>: %(old_end)s -- %(new_end)s
""".format( """
product=rec.name, ) % {
old_end=old_date_end, "product": rec.name,
new_end=rec.date_end, "old_end": old_date_end,
) "new_end": rec.date_end,
) }
rec.contract_id.message_post(body=msg) rec.contract_id.message_post(body=msg)
else: else:
rec.write( rec.write(
@@ -770,17 +764,17 @@ class ContractLine(models.Model):
contract_line |= new_line contract_line |= new_line
if post_message: if post_message:
msg = _( msg = _(
"""Contract line for <strong>{product}</strong> """Contract line for <strong>%(product)s</strong>
planned a successor: <br/> planned a successor: <br/>
- <strong>Start</strong>: {new_date_start} - <strong>Start</strong>: %(new_date_start)s
<br/> <br/>
- <strong>End</strong>: {new_date_end} - <strong>End</strong>: %(new_date_end)s
""".format( """
product=rec.name, ) % {
new_date_start=new_line.date_start, "product": rec.name,
new_date_end=new_line.date_end, "new_date_start": new_line.date_start,
) "new_date_end": new_line.date_end,
) }
rec.contract_id.message_post(body=msg) rec.contract_id.message_post(body=msg)
return contract_line return contract_line
@@ -873,17 +867,17 @@ class ContractLine(models.Model):
post_message=False, post_message=False,
) )
msg = _( msg = _(
"""Contract line for <strong>{product}</strong> """Contract line for <strong>%(product)s</strong>
suspended: <br/> suspended: <br/>
- <strong>Suspension Start</strong>: {new_date_start} - <strong>Suspension Start</strong>: %(new_date_start)s
<br/> <br/>
- <strong>Suspension End</strong>: {new_date_end} - <strong>Suspension End</strong>: %(new_date_end)s
""".format( """
product=rec.name, ) % {
new_date_start=date_start, "product": rec.name,
new_date_end=date_end, "new_date_start": date_start,
) "new_date_end": date_end,
) }
rec.contract_id.message_post(body=msg) rec.contract_id.message_post(body=msg)
return contract_line return contract_line
@@ -893,10 +887,13 @@ class ContractLine(models.Model):
for contract in self.mapped("contract_id"): for contract in self.mapped("contract_id"):
lines = self.filtered(lambda l, c=contract: l.contract_id == c) lines = self.filtered(lambda l, c=contract: l.contract_id == c)
msg = _( msg = _(
"""Contract line canceled: %s""" "Contract line canceled: %s",
% "<br/>- ".join( "<br/>- ".join(
["<strong>%s</strong>" % name for name in lines.mapped("name")] [
) "<strong>%(product)s</strong>" % {"product": name}
for name in lines.mapped("name")
]
),
) )
contract.message_post(body=msg) contract.message_post(body=msg)
self.mapped("predecessor_contract_line_id").write( self.mapped("predecessor_contract_line_id").write(
@@ -910,10 +907,13 @@ class ContractLine(models.Model):
for contract in self.mapped("contract_id"): for contract in self.mapped("contract_id"):
lines = self.filtered(lambda l, c=contract: l.contract_id == c) lines = self.filtered(lambda l, c=contract: l.contract_id == c)
msg = _( msg = _(
"""Contract line Un-canceled: %s""" "Contract line Un-canceled: %s",
% "<br/>- ".join( "<br/>- ".join(
["<strong>%s</strong>" % name for name in lines.mapped("name")] [
) "<strong>%(product)s</strong>" % {"product": name}
for name in lines.mapped("name")
]
),
) )
contract.message_post(body=msg) contract.message_post(body=msg)
for rec in self: for rec in self:
@@ -1036,17 +1036,17 @@ class ContractLine(models.Model):
new_line = rec._renew_extend_line(date_end) new_line = rec._renew_extend_line(date_end)
res |= new_line res |= new_line
msg = _( msg = _(
"""Contract line for <strong>{product}</strong> """Contract line for <strong>%(product)s</strong>
renewed: <br/> renewed: <br/>
- <strong>Start</strong>: {new_date_start} - <strong>Start</strong>: %(new_date_start)s
<br/> <br/>
- <strong>End</strong>: {new_date_end} - <strong>End</strong>: %(new_date_end)s
""".format( """
product=rec.name, ) % {
new_date_start=date_start, "product": rec.name,
new_date_end=date_end, "new_date_start": date_start,
) "new_date_end": date_end,
) }
rec.contract_id.message_post(body=msg) rec.contract_id.message_post(body=msg)
return res return res

View File

@@ -10,8 +10,8 @@ class ContractModification(models.Model):
_description = "Contract Modification" _description = "Contract Modification"
_order = "date desc" _order = "date desc"
date = fields.Date(required=True, string="Date") date = fields.Date(required=True)
description = fields.Text(required=True, string="Description") description = fields.Text(required=True)
contract_id = fields.Many2one( contract_id = fields.Many2one(
string="Contract", string="Contract",
comodel_name="contract.contract", comodel_name="contract.contract",
@@ -19,10 +19,7 @@ class ContractModification(models.Model):
ondelete="cascade", ondelete="cascade",
index=True, index=True,
) )
sent = fields.Boolean( sent = fields.Boolean(default=False)
string="Sent",
default=False,
)
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):

View File

@@ -47,7 +47,7 @@ class ContractRecurrencyBasicMixin(models.AbstractModel):
string="Invoice Every", string="Invoice Every",
help="Invoice every (Days/Week/Month/Year)", help="Invoice every (Days/Week/Month/Year)",
) )
date_start = fields.Date(string="Date Start") date_start = fields.Date()
recurring_next_date = fields.Date(string="Date of Next Invoice") recurring_next_date = fields.Date(string="Date of Next Invoice")
@api.depends("recurring_invoicing_type", "recurring_rule_type") @api.depends("recurring_invoicing_type", "recurring_rule_type")
@@ -80,7 +80,7 @@ class ContractRecurrencyMixin(models.AbstractModel):
recurring_next_date = fields.Date( recurring_next_date = fields.Date(
compute="_compute_recurring_next_date", store=True, readonly=False, copy=True compute="_compute_recurring_next_date", store=True, readonly=False, copy=True
) )
date_end = fields.Date(string="Date End", index=True) date_end = fields.Date(index=True)
next_period_date_start = fields.Date( next_period_date_start = fields.Date(
string="Next Period Start", string="Next Period Start",
compute="_compute_next_period_date_start", compute="_compute_next_period_date_start",
@@ -89,9 +89,7 @@ class ContractRecurrencyMixin(models.AbstractModel):
string="Next Period End", string="Next Period End",
compute="_compute_next_period_date_end", compute="_compute_next_period_date_end",
) )
last_date_invoiced = fields.Date( last_date_invoiced = fields.Date(readonly=True, copy=False)
string="Last Date Invoiced", readonly=True, copy=False
)
@api.depends("next_period_date_start") @api.depends("next_period_date_start")
def _compute_recurring_next_date(self): def _compute_recurring_next_date(self):

View File

@@ -9,7 +9,6 @@ class ResCompany(models.Model):
_inherit = "res.company" _inherit = "res.company"
create_new_line_at_contract_line_renew = fields.Boolean( create_new_line_at_contract_line_renew = fields.Boolean(
string="Create New Line At Contract Line Renew",
help="If checked, a new line will be generated at contract line renew " help="If checked, a new line will be generated at contract line renew "
"and linked to the original one as successor. The default " "and linked to the original one as successor. The default "
"behavior is to extend the end date of the contract by a new " "behavior is to extend the end date of the contract by a new "

View File

@@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !! !! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/contract/tree/14.0/contract"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/contract-14-0/contract-14-0-contract"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/110/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p> <p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/contract/tree/15.0/contract"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/contract-15-0/contract-15-0-contract"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/110/15.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module enables contracts management with recurring <p>This module enables contracts management with recurring
invoicing functions. Also you can print and send by email contract report.</p> invoicing functions. Also you can print and send by email contract report.</p>
<p>It works for customer contract and supplier contracts.</p> <p>It works for customer contract and supplier contracts.</p>
@@ -425,9 +425,9 @@ To use it, just select the template on the contract and fields will be filled au
<ul class="simple"> <ul class="simple">
<li>Contracts appear in portal to following users in every contract:</li> <li>Contracts appear in portal to following users in every contract:</li>
</ul> </ul>
<img alt="https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-my.png" src="https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-my.png" /> <img alt="https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-my.png" src="https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-my.png" />
<img alt="https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-list.png" src="https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-list.png" /> <img alt="https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-list.png" src="https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-list.png" />
<img alt="https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-detail.png" src="https://raw.githubusercontent.com/OCA/contract/14.0/contract/static/src/screenshots/portal-detail.png" /> <img alt="https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-detail.png" src="https://raw.githubusercontent.com/OCA/contract/15.0/contract/static/src/screenshots/portal-detail.png" />
</div> </div>
<div class="section" id="known-issues-roadmap"> <div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1> <h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
@@ -441,7 +441,7 @@ To use it, just select the template on the contract and fields will be filled au
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/contract/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/contract/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/contract/issues/new?body=module:%20contract%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> <a class="reference external" href="https://github.com/OCA/contract/issues/new?body=module:%20contract%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
@@ -492,7 +492,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use.</p> promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/contract/tree/14.0/contract">OCA/contract</a> project on GitHub.</p> <p>This module is part of the <a class="reference external" href="https://github.com/OCA/contract/tree/15.0/contract">OCA/contract</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p> <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div> </div>
</div> </div>

View File

@@ -3,6 +3,7 @@
# Copyright 2021 Tecnativa - Víctor Martínez # Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from collections import namedtuple from collections import namedtuple
from datetime import timedelta from datetime import timedelta
@@ -17,7 +18,7 @@ def to_date(date):
return fields.Date.to_date(date) return fields.Date.to_date(date)
class TestContractBase(common.SavepointCase): class TestContractBase(common.TransactionCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super().setUpClass() super().setUpClass()
@@ -252,8 +253,6 @@ class TestContract(TestContractBase):
def test_contract(self): def test_contract(self):
self.assertEqual(self.contract.recurring_next_date, to_date("2018-01-15")) self.assertEqual(self.contract.recurring_next_date, to_date("2018-01-15"))
self.assertAlmostEqual(self.acct_line.price_subtotal, 50.0) self.assertAlmostEqual(self.acct_line.price_subtotal, 50.0)
res = self.acct_line._onchange_product_id()
self.assertIn("uom_id", res["domain"])
self.acct_line.price_unit = 100.0 self.acct_line.price_unit = 100.0
self.contract.partner_id = self.partner.id self.contract.partner_id = self.partner.id
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
@@ -489,11 +488,6 @@ class TestContract(TestContractBase):
self.acct_line._onchange_product_id() self.acct_line._onchange_product_id()
self.assertEqual(self.acct_line.uom_id, self.acct_line.product_id.uom_id) self.assertEqual(self.acct_line.uom_id, self.acct_line.product_id.uom_id)
def test_onchange_product_id(self):
line = self.env["contract.line"].new()
res = line._onchange_product_id()
self.assertFalse(res["domain"]["uom_id"])
def test_no_pricelist(self): def test_no_pricelist(self):
self.contract.pricelist_id = False self.contract.pricelist_id = False
self.acct_line.quantity = 2 self.acct_line.quantity = 2
@@ -565,8 +559,15 @@ class TestContract(TestContractBase):
test_value = contract_line[key] test_value = contract_line[key]
try: try:
test_value = test_value.id test_value = test_value.id
except AttributeError: except AttributeError as ae:
pass # This try/except is for relation fields.
# For normal fields, test_value would be
# str, float, int ... without id
logging.info(
"Ignored AttributeError ('%s' is not a relation field): %s",
key,
ae,
)
self.assertEqual(test_value, value) self.assertEqual(test_value, value)
def test_send_mail_contract(self): def test_send_mail_contract(self):
@@ -581,21 +582,6 @@ class TestContract(TestContractBase):
self.contract._onchange_contract_type() self.contract._onchange_contract_type()
self.assertFalse(any(self.contract.contract_line_ids.mapped("automatic_price"))) self.assertFalse(any(self.contract.contract_line_ids.mapped("automatic_price")))
def test_contract_onchange_product_id_domain_blank(self):
"""It should return a blank UoM domain when no product."""
line = self.env["contract.template.line"].new()
res = line._onchange_product_id()
self.assertFalse(res["domain"]["uom_id"])
def test_contract_onchange_product_id_domain(self):
"""It should return UoM category domain."""
line = self._add_template_line()
res = line._onchange_product_id()
self.assertEqual(
res["domain"]["uom_id"][0],
("category_id", "=", self.product_1.uom_id.category_id.id),
)
def test_contract_onchange_product_id_uom(self): def test_contract_onchange_product_id_uom(self):
"""It should update the UoM for the line.""" """It should update the UoM for the line."""
line = self._add_template_line( line = self._add_template_line(
@@ -647,14 +633,17 @@ class TestContract(TestContractBase):
show_contract = self.partner.with_context( show_contract = self.partner.with_context(
contract_type="sale" contract_type="sale"
).act_show_contract() ).act_show_contract()
self.assertDictContainsSubset( self.assertEqual(
{
"name": "Customer Contracts",
"type": "ir.actions.act_window",
"res_model": "contract.contract",
"xml_id": "contract.action_customer_contract",
},
show_contract, show_contract,
{
**show_contract,
**{
"name": "Customer Contracts",
"type": "ir.actions.act_window",
"res_model": "contract.contract",
"xml_id": "contract.action_customer_contract",
},
},
"There was an error and the view couldn't be opened.", "There was an error and the view couldn't be opened.",
) )
@@ -2309,7 +2298,7 @@ class TestContract(TestContractBase):
action = self.contract.action_terminate_contract() action = self.contract.action_terminate_contract()
wizard = ( wizard = (
self.env[action["res_model"]] self.env[action["res_model"]]
.with_context(action["context"]) .with_context(**action["context"])
.create( .create(
{ {
"terminate_date": "2018-03-01", "terminate_date": "2018-03-01",

View File

@@ -21,6 +21,8 @@
name="product_id" name="product_id"
attrs="{'required': [('display_type', '=', False)]}" attrs="{'required': [('display_type', '=', False)]}"
/> />
<field name="product_uom_category_id" invisible="1" />
<label for="quantity" /> <label for="quantity" />
<div class="o_row"> <div class="o_row">
<field name="quantity" class="oe_inline" /> <field name="quantity" class="oe_inline" />

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
Copyright 2020 Tecnativa - Víctor Martínez
Copyright 2020 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<template
id="assets_backend"
name="contract assets"
inherit_id="web.assets_backend"
>
<xpath expr="." position="inside">
<script
type="text/javascript"
src="/contract/static/src/js/section_and_note_fields_backend.js"
/>
</xpath>
</template>
<template
id="assets_frontend"
inherit_id="web.assets_frontend"
name="contract assets"
>
<xpath expr="." position="inside">
<link
rel="stylesheet"
href="/contract/static/src/scss/frontend.scss"
type="text/css"
/>
</xpath>
</template>
<template id="assets_tests" inherit_id="web.assets_tests">
<xpath expr="." position="inside">
<script
type="text/javascript"
src="/contract/static/src/js/contract_portal_tour.js"
/>
</xpath>
</template>
</odoo>

View File

@@ -202,6 +202,10 @@
<field name="display_type" invisible="1" /> <field name="display_type" invisible="1" />
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="product_id" /> <field name="product_id" />
<field
name="product_uom_category_id"
invisible="1"
/>
<field name="name" widget="section_and_note_text" /> <field name="name" widget="section_and_note_text" />
<field <field
name="analytic_account_id" name="analytic_account_id"

View File

@@ -9,12 +9,11 @@ class ContractLineWizard(models.TransientModel):
_name = "contract.line.wizard" _name = "contract.line.wizard"
_description = "Contract Line Wizard" _description = "Contract Line Wizard"
date_start = fields.Date(string="Date Start") date_start = fields.Date()
date_end = fields.Date(string="Date End") date_end = fields.Date()
recurring_next_date = fields.Date(string="Next Invoice Date") recurring_next_date = fields.Date(string="Next Invoice Date")
is_auto_renew = fields.Boolean(string="Auto Renew", default=False) is_auto_renew = fields.Boolean(default=False)
manual_renew_needed = fields.Boolean( manual_renew_needed = fields.Boolean(
string="Manual renew needed",
default=False, default=False,
help="This flag is used to make a difference between a definitive stop" help="This flag is used to make a difference between a definitive stop"
"and temporary one for which a user is not able to plan a" "and temporary one for which a user is not able to plan a"

View File

@@ -9,7 +9,7 @@ class ContractManuallyCreateInvoice(models.TransientModel):
_name = "contract.manually.create.invoice" _name = "contract.manually.create.invoice"
_description = "Contract Manually Create Invoice Wizard" _description = "Contract Manually Create Invoice Wizard"
invoice_date = fields.Date(string="Invoice Date", required=True) invoice_date = fields.Date(required=True)
contract_to_invoice_count = fields.Integer( contract_to_invoice_count = fields.Integer(
compute="_compute_contract_to_invoice_ids" compute="_compute_contract_to_invoice_ids"
) )