[MIG] contract: Migration to 17.0

This commit is contained in:
Christopher Rogos
2024-03-27 17:12:44 +00:00
parent fcaddfcb46
commit d1cb9312ae
22 changed files with 268 additions and 350 deletions

View File

@@ -11,7 +11,7 @@
{ {
"name": "Recurring - Contracts Management", "name": "Recurring - Contracts Management",
"version": "16.0.2.7.0", "version": "17.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)",
@@ -47,11 +47,8 @@
"views/contract_portal_templates.xml", "views/contract_portal_templates.xml",
], ],
"assets": { "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_frontend": ["contract/static/src/scss/frontend.scss"],
"web.assets_tests": ["contract/static/src/js/contract_portal_tour.js"], "web.assets_tests": ["contract/static/src/js/contract_portal_tour.esm.js"],
}, },
"installable": True, "installable": True,
} }

View File

@@ -11,8 +11,10 @@
<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
<field name="report_name">Contract</field> name="report_template_ids"
eval="[(4, ref('contract.report_contract'))]"
/>
<field name="lang">{{ object.partner_id.lang }}</field> <field name="lang">{{ object.partner_id.lang }}</field>
<field name="body_html" type="html"> <field name="body_html" type="html">
<div <div

View File

@@ -1,33 +0,0 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import json
import logging
_logger = logging.getLogger(__name__)
def migrate(cr, version):
"""Migrate analytic account from contract line to analytic distribution"""
_logger.info("Migrating analytic distribution for contract.line")
cr.execute(
"""
SELECT id, analytic_account_id, analytic_distribution
FROM contract_line
WHERE analytic_account_id IS NOT NULL
"""
)
for line_id, analytic_account_id, analytic_distribution in cr.fetchall():
analytic_account_id = str(analytic_account_id)
if analytic_distribution:
analytic_distribution[analytic_account_id] = (
analytic_distribution.get(analytic_account_id, 0) + 100
)
else:
analytic_distribution = {analytic_account_id: 100}
cr.execute(
"UPDATE contract_line SET analytic_distribution = %s WHERE id = %s",
(json.dumps(analytic_distribution), line_id),
)

View File

@@ -38,8 +38,8 @@ class ContractAbstractContractLine(models.AbstractModel):
# Just to have a currency_id here - will get overwriten in contract.line # Just to have a currency_id here - will get overwriten in contract.line
# model with the related currency from the contract # model with the related currency from the contract
currency_id = fields.Many2one("res.currency") currency_id = fields.Many2one("res.currency")
specific_price = fields.Monetary() specific_price = fields.Float()
price_unit = fields.Monetary( price_unit = fields.Float(
string="Unit Price", string="Unit Price",
compute="_compute_price_unit", compute="_compute_price_unit",
inverse="_inverse_price_unit", inverse="_inverse_price_unit",

View File

@@ -156,7 +156,7 @@ class ContractContract(models.Model):
).write(vals) ).write(vals)
self._modification_mail_send() self._modification_mail_send()
else: else:
res = super(ContractContract, self).write(vals) res = super().write(vals)
return res return res
@api.model @api.model
@@ -186,13 +186,15 @@ class ContractContract(models.Model):
) )
if modification_ids_not_sent: if modification_ids_not_sent:
if not self.env.context.get("skip_modification_mail"): if not self.env.context.get("skip_modification_mail"):
record.with_context( subtype_id = self.env["ir.model.data"]._xmlid_to_res_id(
default_subtype_id=self.env.ref(
"contract.mail_message_subtype_contract_modification" "contract.mail_message_subtype_contract_modification"
).id, )
).message_post_with_template( template_id = self.env.ref(
self.env.ref("contract.mail_template_contract_modification").id, "contract.mail_template_contract_modification"
email_layout_xmlid="contract.template_contract_modification", )
record.message_post_with_source(
template_id,
subtype_id=subtype_id,
) )
modification_ids_not_sent.write({"sent": True}) modification_ids_not_sent.write({"sent": True})
@@ -318,10 +320,10 @@ class ContractContract(models.Model):
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(
lambda l: ( lambda line: (
l.recurring_next_date line.recurring_next_date
and not l.is_canceled and not line.is_canceled
and (not l.display_type or l.is_recurring_note) and (not line.display_type or line.is_recurring_note)
) )
).mapped("recurring_next_date") ).mapped("recurring_next_date")
# we give priority to computation from date_start if modified # we give priority to computation from date_start if modified
@@ -622,7 +624,8 @@ class ContractContract(models.Model):
body=( body=(
_( _(
( (
"%(msg)s by contract <a href=# data-oe-model=contract.contract" "%(msg)s by contract <a href=#"
" data-oe-model=contract.contract"
" data-oe-id=%(contract_id)d>%(contract)s</a>." " data-oe-id=%(contract_id)d>%(contract)s</a>."
), ),
msg=move._creation_message(), msg=move._creation_message(),
@@ -672,8 +675,11 @@ class ContractContract(models.Model):
# Invoice by companies, so assignation emails get correct context # Invoice by companies, so assignation emails get correct context
for company in companies: for company in companies:
contracts_to_invoice = contracts.filtered( contracts_to_invoice = contracts.filtered(
lambda c: c.company_id == company lambda contract, comp=company: contract.company_id == comp
and (not c.date_end or c.recurring_next_date <= c.date_end) and (
not contract.date_end
or contract.recurring_next_date <= contract.date_end
)
).with_company(company) ).with_company(company)
_recurring_create_func(contracts_to_invoice, date_ref) _recurring_create_func(contracts_to_invoice, date_ref)
return True return True

View File

@@ -876,14 +876,11 @@ class ContractLine(models.Model):
if not all(self.mapped("is_cancel_allowed")): if not all(self.mapped("is_cancel_allowed")):
raise ValidationError(_("Cancel not allowed for this line")) raise ValidationError(_("Cancel not allowed for this line"))
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 line, c=contract: line.contract_id == c)
msg = _( msg = _(
"Contract line canceled: %s", "Contract line canceled: %s",
"<br/>- ".join( "<br/>- ".join(
[ [f"<strong>{name}</strong>" 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)
@@ -896,14 +893,11 @@ class ContractLine(models.Model):
if not all(self.mapped("is_un_cancel_allowed")): if not all(self.mapped("is_un_cancel_allowed")):
raise ValidationError(_("Un-cancel not allowed for this line")) raise ValidationError(_("Un-cancel not allowed for this line"))
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 line, c=contract: line.contract_id == c)
msg = _( msg = _(
"Contract line Un-canceled: %s", "Contract line Un-canceled: %s",
"<br/>- ".join( "<br/>- ".join(
[ [f"<strong>{name}</strong>" 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)

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>

View File

@@ -0,0 +1,18 @@
/** @odoo-module **/
import {registry} from "@web/core/registry";
registry.category("web_tour.tours").add("contract_portal_tour", {
test: true,
url: "/my",
steps: () => [
{
content: "Go /my/contracts url",
trigger: 'a[href*="/my/contracts"]',
},
{
content: "Go to Contract item",
trigger: ".tr_contract_link:eq(0)",
},
],
});

View File

@@ -1,23 +0,0 @@
odoo.define("contract.tour", function (require) {
"use strict";
var tour = require("web_tour.tour");
tour.register(
"contract_portal_tour",
{
test: true,
url: "/my",
},
[
{
content: "Go /my/contracts url",
trigger: 'a[href*="/my/contracts"]',
},
{
content: "Go to Contract item",
trigger: ".tr_contract_link:eq(0)",
},
]
);
});

View File

@@ -1,39 +0,0 @@
/* Copyright 2020 Tecnativa - Ernesto Tejeda
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
*/
/*
If in the sub-tree view where the sections and notes are to be used
there are fields that have defined in the XML attrs = {'invisible': ....}
and this condition is met, then an extra space appears in the rows
corresponding to the sections and lines.
This js was written to deal with that problem, but a solution based on
this can be applied directly to Odoo*/
odoo.define("contract.section_and_note_backend", function (require) {
"use strict";
require("account.section_and_note_backend");
var fieldRegistry = require("web.field_registry");
var section_and_note_one2many = fieldRegistry.get("section_and_note_one2many");
section_and_note_one2many.include({
_getRenderer: function () {
var result = this._super.apply(this, arguments);
if (this.view.arch.tag === "tree") {
result.include({
_renderBodyCell: function (record) {
var $cell = this._super.apply(this, arguments);
var isSection = record.data.display_type === "line_section";
var isNote = record.data.display_type === "line_note";
if (isSection || isNote) {
$cell.removeClass("o_invisible_modifier");
}
return $cell;
},
});
}
return result;
},
});
});

View File

@@ -857,25 +857,15 @@ class TestContract(TestContractBase):
max_date_end, max_date_end,
): ):
return ( return (
"Error in case %s:" f"Error in case {case}:"
"date_start: %s, " f"date_start: {date_start}, "
"date_end: %s, " f"date_end: {date_end}, "
"last_date_invoiced: %s, " f"last_date_invoiced: {last_date_invoiced}, "
"recurring_next_date: %s, " f"recurring_next_date: {recurring_next_date}, "
"recurring_invoicing_type: %s, " f"recurring_invoicing_type: {recurring_invoicing_type}, "
"recurring_rule_type: %s, " f"recurring_rule_type: {recurring_rule_type}, "
"recurring_interval: %s, " f"recurring_interval: {recurring_interval}, "
"max_date_end: %s, " f"max_date_end: {max_date_end}, "
) % (
case,
date_start,
date_end,
last_date_invoiced,
recurring_next_date,
recurring_invoicing_type,
recurring_rule_type,
recurring_interval,
max_date_end,
) )
Result = namedtuple( Result = namedtuple(

View File

@@ -8,12 +8,16 @@ class ContractMulticompanyCase(TestContractBase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super().setUpClass() super().setUpClass()
chart_template = cls.env.ref("l10n_generic_coa.configurable_chart_template")
cls.company_obj = cls.env["res.company"] cls.company_obj = cls.env["res.company"]
cls.company_1 = cls.env.ref("base.main_company") cls.company_1 = cls.env.ref("base.main_company")
vals = {"name": "Company 2"} vals = {"name": "Company 2"}
cls.company_2 = cls.company_obj.create(vals) cls.company_2 = cls.company_obj.create(vals)
chart_template.try_loading(company=cls.company_2) chart_template = cls.env["account.chart.template"]._guess_chart_template(
cls.company_2.country_id
)
cls.env["account.chart.template"].try_loading(
chart_template, company=cls.company_2, install_demo=False
)
cls.env.user.company_ids |= cls.company_2 cls.env.user.company_ids |= cls.company_2
cls.contract_mc = ( cls.contract_mc = (

View File

@@ -1,12 +1,12 @@
# Copyright 2020 Tecnativa - Víctor Martínez # Copyright 2020 Tecnativa - Víctor Martínez
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
import odoo.tests
from odoo import http from odoo import http
from odoo.tests import HttpCase, tagged
@odoo.tests.tagged("post_install", "-at_install") @tagged("post_install", "-at_install")
class TestContractPortal(odoo.tests.HttpCase): class TestContractPortal(HttpCase):
def test_tour(self): def test_tour(self):
partner = self.env["res.partner"].create({"name": "partner test contract"}) partner = self.env["res.partner"].create({"name": "partner test contract"})
contract = self.env["contract.contract"].create( contract = self.env["contract.contract"].create(
@@ -14,12 +14,7 @@ class TestContractPortal(odoo.tests.HttpCase):
) )
user_portal = self.env.ref("base.demo_user0") user_portal = self.env.ref("base.demo_user0")
contract.message_subscribe(partner_ids=user_portal.partner_id.ids) contract.message_subscribe(partner_ids=user_portal.partner_id.ids)
self.browser_js( self.start_tour("/", "contract_portal_tour", login="portal")
"/",
"odoo.__DEBUG__.services['web_tour.tour'].run('contract_portal_tour')",
"odoo.__DEBUG__.services['web_tour.tour'].tours.contract_portal_tour.ready",
login="portal",
)
# Contract access # Contract access
self.authenticate("portal", "portal") self.authenticate("portal", "portal")
http.root.session_store.save(self.session) http.root.session_store.save(self.session)

View File

@@ -9,7 +9,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<field name="display_type" invisible="1" /> <field name="display_type" invisible="1" />
<header attrs="{'invisible': [('display_type', '!=', False)]}" /> <header invisible="display_type" />
<sheet> <sheet>
<field name="specific_price" invisible="1" /> <field name="specific_price" invisible="1" />
<field name="currency_id" invisible="1" /> <field name="currency_id" invisible="1" />
@@ -17,23 +17,23 @@
<group> <group>
<field <field
name="product_id" name="product_id"
attrs="{'required': [('display_type', '=', 'product')],'invisible': [('display_type', '!=', False)]}" required="display_type == 'product'"
invisible="display_type"
/> />
</group> </group>
<group attrs="{'invisible': [('display_type', '!=', False)]}"> <group invisible="display_type">
<group> <group>
<field name="automatic_price" /> <field name="automatic_price" />
<field
name="price_unit"
attrs="{'readonly': [('automatic_price', '=', True)]}" <field name="price_unit" readonly="automatic_price" />
/>
<field name="quantity" /> <field name="quantity" />
</group> </group>
<group> <group>
<field <field
name="uom_id" name="uom_id"
groups="uom.group_uom" groups="uom.group_uom"
attrs="{'required': [('display_type', '=', False)]}" required="not display_type"
/> />
<field <field
name="discount" name="discount"
@@ -42,45 +42,41 @@
<field name="price_subtotal" readonly="1" /> <field name="price_subtotal" readonly="1" />
</group> </group>
</group> </group>
<label <label for="name" string="Description" invisible="display_type" />
for="name"
string="Description"
attrs="{'invisible': [('display_type', '!=', False)]}"
/>
<label <label
for="name" for="name"
string="Section" string="Section"
attrs="{'invisible': [('display_type', '!=', 'line_section')]}" invisible="display_type != 'line_section'"
/> />
<label <label
for="name" for="name"
string="Note" string="Note"
attrs="{'invisible': [('display_type', '!=', 'line_note')]}" invisible="display_type != 'line_note'"
/> />
<field name="name" nolabel="1" /> <field name="name" nolabel="1" />
<group <group
name="note_invoicing_mode" name="note_invoicing_mode"
attrs="{'invisible': [('display_type', '!=', 'line_note')]}" invisible="display_type != 'line_note'"
> >
<field name="note_invoicing_mode" widget="radio" /> <field name="note_invoicing_mode" widget="radio" />
</group> </group>
<group attrs="{'invisible': [('display_type', '!=', False)]}"> <group invisible="display_type">
<field name="is_auto_renew" /> <field name="is_auto_renew" />
<field name="is_canceled" invisible="1" /> <field name="is_canceled" invisible="1" />
</group> </group>
<group <group invisible="not is_auto_renew or display_type">
attrs="{'invisible':['|', ('is_auto_renew', '=', False), ('display_type', '!=', False)]}"
>
<group> <group>
<label for="auto_renew_interval" /> <label for="auto_renew_interval" />
<div class="o_row"> <div class="o_row">
<field <field
name="auto_renew_interval" name="auto_renew_interval"
attrs="{'required':[('is_auto_renew', '=', True)]}" class="oe_inline"
required="is_auto_renew"
/> />
<field <field
name="auto_renew_rule_type" name="auto_renew_rule_type"
attrs="{'required':[('is_auto_renew', '=', True)]}" class="oe_inline"
required="is_auto_renew"
/> />
</div> </div>
</group> </group>
@@ -90,19 +86,19 @@
<field <field
name="termination_notice_interval" name="termination_notice_interval"
class="oe_inline" class="oe_inline"
attrs="{'required':[('is_auto_renew', '=', True)]}" required="is_auto_renew"
/> />
<field <field
name="termination_notice_rule_type" name="termination_notice_rule_type"
class="oe_inline" class="oe_inline"
attrs="{'required':[('is_auto_renew', '=', True)]}" required="is_auto_renew"
/> />
</div> </div>
</group> </group>
</group> </group>
<group <group
name="recurrence_info" name="recurrence_info"
attrs="{'invisible': ['|', ('display_type', '=', 'line_section'), '&amp;', ('display_type', '=', 'line_note'), ('note_invoicing_mode', '!=', 'custom')]}" invisible="display_type == 'line_section' or (display_type == 'line_note' and note_invoicing_mode != 'custom')"
> >
<group> <group>
<label for="recurring_interval" /> <label for="recurring_interval" />

View File

@@ -7,11 +7,12 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<field name="is_terminated" invisible="1" /> <field name="is_terminated" invisible="1" />
<field name="company_id" invisible="1" />
<div <div
class="alert alert-danger" class="alert alert-danger"
role="alert" role="alert"
style="margin-bottom:0px;" style="margin-bottom:0px;"
attrs="{'invisible': [('is_terminated','=',False)]}" invisible="not is_terminated"
> >
<p> <p>
This contract was terminated for the reason This contract was terminated for the reason
@@ -34,13 +35,13 @@
name="action_contract_send" name="action_contract_send"
type="object" type="object"
string="Send by Email" string="Send by Email"
attrs="{'invisible': [('is_terminated','=',True)]}" invisible="is_terminated"
groups="base.group_user" groups="base.group_user"
/> />
<button <button
name="recurring_create_invoice" name="recurring_create_invoice"
type="object" type="object"
attrs="{'invisible': ['|', ('create_invoice_visibility', '=', False),('generation_type','!=','invoice')]}" invisible="not create_invoice_visibility and generation_type != 'invoice'"
string="Create invoices" string="Create invoices"
groups="base.group_no_one" groups="base.group_no_one"
/> />
@@ -48,14 +49,14 @@
name="action_terminate_contract" name="action_terminate_contract"
type="object" type="object"
string="Terminate Contract" string="Terminate Contract"
attrs="{'invisible': [('is_terminated','=',True)]}" invisible="is_terminated"
groups="contract.can_terminate_contract" groups="contract.can_terminate_contract"
/> />
<button <button
name="action_terminate_contract" name="action_terminate_contract"
type="object" type="object"
string="Update Termination Details" string="Update Termination Details"
attrs="{'invisible': [('is_terminated','=',False)]}" invisible="not is_terminated"
groups="contract.can_terminate_contract" groups="contract.can_terminate_contract"
/> />
<button <button
@@ -63,7 +64,7 @@
type="object" type="object"
confirm="Are you sure you want to re-activate this contract?" confirm="Are you sure you want to re-activate this contract?"
string="Cancel Contract Termination" string="Cancel Contract Termination"
attrs="{'invisible': [('is_terminated','=',False)]}" invisible="not is_terminated"
groups="contract.can_terminate_contract" groups="contract.can_terminate_contract"
/> />
<button type="object" string="Preview" name="action_preview" /> <button type="object" string="Preview" name="action_preview" />
@@ -76,7 +77,7 @@
type="object" type="object"
icon="fa-list" icon="fa-list"
class="oe_stat_button" class="oe_stat_button"
attrs="{'invisible': [('generation_type','!=','invoice')]}" invisible="generation_type != 'invoice'"
> >
<field <field
string="Invoices" string="Invoices"
@@ -89,7 +90,7 @@
name="web_ribbon" name="web_ribbon"
title="Archived" title="Archived"
bg_color="bg-danger" bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}" invisible="active"
/> />
<div class="oe_title"> <div class="oe_title">
<label for="name" string="Contract Name" class="oe_edit_only" /> <label for="name" string="Contract Name" class="oe_edit_only" />
@@ -97,7 +98,7 @@
<field <field
name="name" name="name"
class="oe_inline" class="oe_inline"
attrs="{'readonly': [('is_terminated','=',True)]}" readonly="is_terminated"
placeholder="e.g. Contract XYZ" placeholder="e.g. Contract XYZ"
/> />
</h3> </h3>
@@ -108,37 +109,25 @@
<field <field
name="partner_id" name="partner_id"
required="1" required="1"
attrs="{'readonly': [('is_terminated','=',True)]}" readonly="is_terminated"
/>
<field
name="pricelist_id"
attrs="{'readonly': [('is_terminated','=',True)]}"
/>
<field
name="payment_term_id"
attrs="{'readonly': [('is_terminated','=',True)]}"
/>
<field
name="user_id"
attrs="{'readonly': [('is_terminated','=',True)]}"
/> />
<field name="pricelist_id" readonly="is_terminated" />
<field name="payment_term_id" readonly="is_terminated" />
<field name="user_id" readonly="is_terminated" />
</group> </group>
<group> <group>
<field <field
name="contract_template_id" name="contract_template_id"
attrs="{'readonly': [('is_terminated','=',True)]}" readonly="is_terminated"
domain="['|', ('contract_type', '=', contract_type), ('contract_type', '=', False)]" domain="['|', ('contract_type', '=', contract_type), ('contract_type', '=', False)]"
context="{'default_contract_type': contract_type}" context="{'default_contract_type': contract_type}"
/> />
<field name="contract_type" invisible="1" required="1" /> <field name="contract_type" invisible="1" required="1" />
<field <field name="fiscal_position_id" readonly="is_terminated" />
name="fiscal_position_id"
attrs="{'readonly': [('is_terminated','=',True)]}"
/>
<field <field
name="journal_id" name="journal_id"
required="1" required="1"
attrs="{'readonly': [('is_terminated','=',True)]}" readonly="is_terminated"
/> />
<field <field
name="tag_ids" name="tag_ids"
@@ -148,38 +137,36 @@
</group> </group>
</group> </group>
<group name="recurring_invoices"> <group name="recurring_invoices">
<group>
<field <field
name="line_recurrence" name="line_recurrence"
class="oe_inline" class="oe_inline"
attrs="{'readonly': [('line_recurrence', '=', True), ('invoice_count', '!=', 0)]}" readonly="line_recurrence and invoice_count != 0"
/> />
<label for="line_recurrence" /> </group>
<group attrs="{'invisible': [('line_recurrence', '=', True)]}"> <group invisible="line_recurrence">
<label for="recurring_interval" /> <label for="recurring_interval" />
<div class="o_row"> <div class="o_row">
<field <field
name="recurring_interval" name="recurring_interval"
attrs="{'required': [('line_recurrence', '=', False)]}" required="not line_recurrence"
class="oe_inline" class="oe_inline"
nolabel="1" nolabel="1"
/> />
<field <field
name="recurring_rule_type" name="recurring_rule_type"
attrs="{'required': [('line_recurrence', '=', False)]}" required="not line_recurrence"
class="oe_inline" class="oe_inline"
nolabel="1" nolabel="1"
/> />
</div> </div>
<field <field
name="recurring_invoicing_type" name="recurring_invoicing_type"
attrs="{'required': [('line_recurrence', '=', False)]}" required="not line_recurrence"
/> />
</group> </group>
<group attrs="{'invisible': [('line_recurrence', '=', True)]}"> <group invisible="line_recurrence">
<field <field name="date_start" required="not line_recurrence" />
name="date_start"
attrs="{'required': [('line_recurrence', '=', False)]}"
/>
<field name="date_end" /> <field name="date_end" />
<field name="recurring_next_date" /> <field name="recurring_next_date" />
</group> </group>
@@ -191,7 +178,8 @@
<page name="recurring_invoice_line" string="Recurring Invoices"> <page name="recurring_invoice_line" string="Recurring Invoices">
<field <field
name="contract_line_fixed_ids" name="contract_line_fixed_ids"
attrs="{'readonly': [('is_terminated','=',True)], 'invisible': [('line_recurrence', '=', True)]}" readonly="is_terminated"
invisible="line_recurrence"
widget="section_and_note_one2many" widget="section_and_note_one2many"
context="{'default_contract_type': contract_type, 'default_recurring_rule_type': recurring_rule_type, 'default_recurring_invoicing_type': recurring_invoicing_type, 'default_recurring_interval': recurring_interval, 'default_date_start': date_start, 'default_recurring_next_date': recurring_next_date}" context="{'default_contract_type': contract_type, 'default_recurring_rule_type': recurring_rule_type, 'default_recurring_invoicing_type': recurring_invoicing_type, 'default_recurring_interval': recurring_interval, 'default_date_start': date_start, 'default_recurring_next_date': recurring_next_date}"
> >
@@ -211,13 +199,16 @@
context="{'default_display_type': 'line_note'}" context="{'default_display_type': 'line_note'}"
/> />
</control> </control>
<field name="currency_id" invisible="1" /> <field name="currency_id" column_invisible="True" />
<field name="display_type" invisible="1" /> <field
name="display_type"
column_invisible="True"
/>
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="product_id" /> <field name="product_id" />
<field <field
name="product_uom_category_id" name="product_uom_category_id"
invisible="1" column_invisible="True"
/> />
<field name="name" widget="section_and_note_text" /> <field name="name" widget="section_and_note_text" />
<field <field
@@ -229,26 +220,38 @@
<field name="uom_id" /> <field name="uom_id" />
<field <field
name="automatic_price" name="automatic_price"
attrs="{'column_invisible': [('parent.contract_type', '=', 'purchase')]}" column_invisible="parent.contract_type == 'purchase'"
/> />
<field <field
name="price_unit" name="price_unit"
attrs="{'readonly': [('automatic_price', '=', True)]}" readonly="automatic_price"
/>
<field
name="specific_price"
column_invisible="True"
/> />
<field name="specific_price" invisible="1" />
<field <field
name="discount" name="discount"
groups="product.group_discount_per_so_line" groups="product.group_discount_per_so_line"
/> />
<field name="price_subtotal" /> <field name="price_subtotal" />
<field name="recurring_interval" invisible="1" /> <field
<field name="recurring_rule_type" invisible="1" /> name="recurring_interval"
column_invisible="True"
/>
<field
name="recurring_rule_type"
column_invisible="True"
/>
<field <field
name="recurring_invoicing_type" name="recurring_invoicing_type"
invisible="1" column_invisible="True"
/> />
<field name="recurring_next_date" invisible="1" /> <field
<field name="date_start" invisible="1" /> name="recurring_next_date"
column_invisible="True"
/>
<field name="date_start" column_invisible="True" />
<field name="date_end" /> <field name="date_end" />
<field <field
name="last_date_invoiced" name="last_date_invoiced"
@@ -256,21 +259,31 @@
/> />
<field <field
name="create_invoice_visibility" name="create_invoice_visibility"
invisible="1" column_invisible="True"
/> />
<field <field
name="is_plan_successor_allowed" name="is_plan_successor_allowed"
invisible="1" column_invisible="True"
/> />
<field name="is_stop_allowed" invisible="1" /> <field
<field name="is_cancel_allowed" invisible="1" /> name="is_stop_allowed"
<field name="is_un_cancel_allowed" invisible="1" /> column_invisible="True"
<field name="is_canceled" invisible="1" /> />
<field
name="is_cancel_allowed"
column_invisible="True"
/>
<field
name="is_un_cancel_allowed"
column_invisible="True"
/>
<field name="is_canceled" column_invisible="True" />
</tree> </tree>
</field> </field>
<field <field
name="contract_line_ids" name="contract_line_ids"
attrs="{'readonly': [('is_terminated','=',True)], 'invisible': [('line_recurrence', '=', False)]}" readonly="is_terminated"
invisible="not line_recurrence"
widget="section_and_note_one2many" widget="section_and_note_one2many"
context="{'default_contract_type': contract_type}" context="{'default_contract_type': contract_type}"
> >
@@ -289,8 +302,11 @@
context="{'default_display_type': 'line_note'}" context="{'default_display_type': 'line_note'}"
/> />
</control> </control>
<field name="currency_id" invisible="1" /> <field name="currency_id" column_invisible="True" />
<field name="display_type" invisible="1" /> <field
name="display_type"
column_invisible="True"
/>
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="product_id" /> <field name="product_id" />
<field name="name" widget="section_and_note_text" /> <field name="name" widget="section_and_note_text" />
@@ -303,23 +319,32 @@
<field name="uom_id" /> <field name="uom_id" />
<field <field
name="automatic_price" name="automatic_price"
attrs="{'column_invisible': [('parent.contract_type', '=', 'purchase')]}" column_invisible="parent.contract_type == 'purchase'"
/> />
<field <field
name="price_unit" name="price_unit"
attrs="{'readonly': [('automatic_price', '=', True)]}" readonly="automatic_price"
/>
<field
name="specific_price"
column_invisible="True"
/> />
<field name="specific_price" invisible="1" />
<field <field
name="discount" name="discount"
groups="product.group_discount_per_so_line" groups="product.group_discount_per_so_line"
/> />
<field name="price_subtotal" /> <field name="price_subtotal" />
<field name="recurring_interval" invisible="1" /> <field
<field name="recurring_rule_type" invisible="1" /> name="recurring_interval"
column_invisible="True"
/>
<field
name="recurring_rule_type"
column_invisible="True"
/>
<field <field
name="recurring_invoicing_type" name="recurring_invoicing_type"
invisible="1" column_invisible="True"
/> />
<field name="date_start" required="1" /> <field name="date_start" required="1" />
<field name="date_end" /> <field name="date_end" />
@@ -330,41 +355,53 @@
/> />
<field <field
name="create_invoice_visibility" name="create_invoice_visibility"
invisible="1" column_invisible="True"
/> />
<field <field
name="is_plan_successor_allowed" name="is_plan_successor_allowed"
invisible="1" column_invisible="True"
/> />
<field <field
name="is_stop_plan_successor_allowed" name="is_stop_plan_successor_allowed"
invisible="1" column_invisible="True"
/> />
<field name="is_stop_allowed" invisible="1" /> <field
<field name="is_cancel_allowed" invisible="1" /> name="is_stop_allowed"
<field name="is_un_cancel_allowed" invisible="1" /> column_invisible="True"
<field name="is_auto_renew" invisible="1" /> />
<field name="is_canceled" invisible="1" /> <field
name="is_cancel_allowed"
column_invisible="True"
/>
<field
name="is_un_cancel_allowed"
column_invisible="True"
/>
<field
name="is_auto_renew"
column_invisible="True"
/>
<field name="is_canceled" column_invisible="True" />
<button <button
name="action_plan_successor" name="action_plan_successor"
string="Plan Start" string="Plan Start"
type="object" type="object"
icon="fa-calendar text-success" icon="fa-calendar text-success"
attrs="{'invisible': [('is_plan_successor_allowed', '=', False)]}" invisible="not is_plan_successor_allowed"
/> />
<button <button
name="action_stop_plan_successor" name="action_stop_plan_successor"
string="Stop Plan Successor" string="Stop Plan Successor"
type="object" type="object"
icon="fa-pause text-muted" icon="fa-pause text-muted"
attrs="{'invisible': [('is_stop_plan_successor_allowed', '=', False)]}" invisible="not is_stop_plan_successor_allowed"
/> />
<button <button
name="action_stop" name="action_stop"
string="Stop" string="Stop"
type="object" type="object"
icon="fa-stop text-danger" icon="fa-stop text-danger"
attrs="{'invisible': [('is_stop_allowed', '=', False)]}" invisible="not is_stop_allowed"
/> />
<button <button
name="cancel" name="cancel"
@@ -372,14 +409,14 @@
type="object" type="object"
icon="fa-ban text-danger" icon="fa-ban text-danger"
confirm="Are you sure you want to cancel this line" confirm="Are you sure you want to cancel this line"
attrs="{'invisible': [('is_cancel_allowed', '=', False)]}" invisible="not is_cancel_allowed"
/> />
<button <button
name="action_uncancel" name="action_uncancel"
string="Un-cancel" string="Un-cancel"
type="object" type="object"
icon="fa-ban text-success" icon="fa-ban text-success"
attrs="{'invisible': [('is_un_cancel_allowed', '=', False)]}" invisible="not is_un_cancel_allowed"
/> />
<button <button
name="renew" name="renew"
@@ -387,17 +424,14 @@
type="object" type="object"
icon="fa-fast-forward text-success" icon="fa-fast-forward text-success"
groups="base.group_no_one" groups="base.group_no_one"
attrs="{'invisible': [('is_auto_renew', '=', False)]}" invisible="not is_auto_renew"
/> />
</tree> </tree>
</field> </field>
<field name="note" /> <field name="note" />
</page> </page>
<page name="modications" string="Modifications"> <page name="modications" string="Modifications">
<field <field name="modification_ids" readonly="is_terminated">
name="modification_ids"
attrs="{'readonly': [('is_terminated','=',True)]}"
>
<tree editable="bottom"> <tree editable="bottom">
<field name="date" /> <field name="date" />
<field name="description" /> <field name="description" />
@@ -408,17 +442,11 @@
<page name="info" string="Other Information"> <page name="info" string="Other Information">
<field name="create_invoice_visibility" invisible="1" /> <field name="create_invoice_visibility" invisible="1" />
<group> <group>
<field <field name="code" readonly="is_terminated" />
name="code" <field name="group_id" readonly="is_terminated" />
attrs="{'readonly': [('is_terminated','=',True)]}"
/>
<field
name="group_id"
attrs="{'readonly': [('is_terminated','=',True)]}"
/>
<field <field
name="company_id" name="company_id"
attrs="{'readonly': [('is_terminated','=',True)]}" readonly="is_terminated"
options="{'no_create': True}" options="{'no_create': True}"
groups="base.group_multi_company" groups="base.group_multi_company"
/> />
@@ -428,7 +456,7 @@
/> />
<field <field
name="invoice_partner_id" name="invoice_partner_id"
attrs="{'readonly': [('is_terminated','=',True)]}" readonly="is_terminated"
required="1" required="1"
/> />
</group> </group>
@@ -515,7 +543,7 @@
widget="many2many_tags" widget="many2many_tags"
options="{'color_field': 'color'}" options="{'color_field': 'color'}"
/> />
<field name="active" invisible="1" /> <field name="active" column_invisible="True" />
<field name="company_id" groups="base.group_multi_company" /> <field name="company_id" groups="base.group_multi_company" />
</tree> </tree>
</field> </field>

View File

@@ -21,10 +21,7 @@
<field name="recurring_next_date" /> <field name="recurring_next_date" />
</group> </group>
<group> <group>
<field <field name="date_end" required="is_auto_renew" />
name="date_end"
attrs="{'required': [('is_auto_renew', '=', True)]}"
/>
<field name="next_period_date_end" /> <field name="next_period_date_end" />
</group> </group>
<group groups="base.group_no_one"> <group groups="base.group_no_one">
@@ -45,7 +42,7 @@
<group <group
name="analytic" name="analytic"
groups="analytic.group_analytic_accounting" groups="analytic.group_analytic_accounting"
attrs="{'invisible': [('display_type', '!=', False)]}" invisible="display_type"
> >
<field <field
name="analytic_distribution" name="analytic_distribution"
@@ -106,48 +103,45 @@
<field name="quantity" /> <field name="quantity" />
<field name="uom_id" /> <field name="uom_id" />
<field name="automatic_price" /> <field name="automatic_price" />
<field <field name="price_unit" readonly="automatic_price" />
name="price_unit" <field name="specific_price" column_invisible="True" />
attrs="{'readonly': [('automatic_price', '=', True)]}"
/>
<field name="specific_price" invisible="1" />
<field name="discount" groups="product.group_discount_per_so_line" /> <field name="discount" groups="product.group_discount_per_so_line" />
<field name="price_subtotal" /> <field name="price_subtotal" />
<field name="recurring_interval" invisible="1" /> <field name="recurring_interval" column_invisible="True" />
<field name="recurring_rule_type" invisible="1" /> <field name="recurring_rule_type" column_invisible="True" />
<field name="recurring_invoicing_type" invisible="1" /> <field name="recurring_invoicing_type" column_invisible="True" />
<field name="date_start" required="1" /> <field name="date_start" column_invisible="True" />
<field name="date_end" /> <field name="date_end" />
<field name="recurring_next_date" required="1" /> <field name="recurring_next_date" column_invisible="True" />
<field name="last_date_invoiced" groups="base.group_no_one" /> <field name="last_date_invoiced" groups="base.group_no_one" />
<field name="create_invoice_visibility" invisible="1" /> <field name="create_invoice_visibility" column_invisible="True" />
<field name="is_plan_successor_allowed" invisible="1" /> <field name="is_plan_successor_allowed" column_invisible="True" />
<field name="is_stop_plan_successor_allowed" invisible="1" /> <field name="is_stop_plan_successor_allowed" column_invisible="True" />
<field name="is_stop_allowed" invisible="1" /> <field name="is_stop_allowed" column_invisible="True" />
<field name="is_cancel_allowed" invisible="1" /> <field name="is_cancel_allowed" column_invisible="True" />
<field name="is_un_cancel_allowed" invisible="1" /> <field name="is_un_cancel_allowed" column_invisible="True" />
<field name="is_auto_renew" invisible="1" /> <field name="is_auto_renew" column_invisible="True" />
<field name="is_canceled" invisible="1" /> <field name="is_canceled" column_invisible="True" />
<button <button
name="action_plan_successor" name="action_plan_successor"
title="Plan Start" title="Plan Start"
type="object" type="object"
icon="fa-calendar text-success" icon="fa-calendar text-success"
attrs="{'invisible': [('is_plan_successor_allowed', '=', False)]}" invisible="not is_plan_successor_allowed"
/> />
<button <button
name="action_stop_plan_successor" name="action_stop_plan_successor"
title="Stop Plan Successor" title="Stop Plan Successor"
type="object" type="object"
icon="fa-pause text-muted" icon="fa-pause text-muted"
attrs="{'invisible': [('is_stop_plan_successor_allowed', '=', False)]}" invisible="not is_stop_plan_successor_allowed"
/> />
<button <button
name="action_stop" name="action_stop"
title="Stop" title="Stop"
type="object" type="object"
icon="fa-stop text-danger" icon="fa-stop text-danger"
attrs="{'invisible': [('is_stop_allowed', '=', False)]}" invisible="not is_stop_allowed"
/> />
<button <button
name="cancel" name="cancel"
@@ -155,14 +149,14 @@
type="object" type="object"
icon="fa-ban text-danger" icon="fa-ban text-danger"
confirm="Are you sure you want to cancel this line" confirm="Are you sure you want to cancel this line"
attrs="{'invisible': [('is_cancel_allowed', '=', False)]}" invisible="not is_cancel_allowed"
/> />
<button <button
name="action_uncancel" name="action_uncancel"
title="Un-cancel" title="Un-cancel"
type="object" type="object"
icon="fa-ban text-success" icon="fa-ban text-success"
attrs="{'invisible': [('is_un_cancel_allowed', '=', False)]}" invisible="not is_un_cancel_allowed"
/> />
<button <button
name="renew" name="renew"
@@ -170,7 +164,7 @@
type="object" type="object"
icon="fa-fast-forward text-success" icon="fa-fast-forward text-success"
groups="base.group_no_one" groups="base.group_no_one"
attrs="{'invisible': [('is_auto_renew', '=', False)]}" invisible="not is_auto_renew"
/> />
</tree> </tree>
</field> </field>

View File

@@ -12,6 +12,7 @@
<group name="group_main"> <group name="group_main">
<group name="group_main_left"> <group name="group_main_left">
<field name="contract_type" /> <field name="contract_type" />
<field name="company_id" invisible="1" />
<field name="journal_id" /> <field name="journal_id" />
<field name="pricelist_id" /> <field name="pricelist_id" />
<field <field
@@ -40,29 +41,30 @@
context="{'default_display_type': 'line_note'}" context="{'default_display_type': 'line_note'}"
/> />
</control> </control>
<field name="display_type" invisible="1" /> <field name="display_type" column_invisible="True" />
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="product_id" /> <field name="product_id" />
<field name="name" widget="section_and_note_text" /> <field name="name" widget="section_and_note_text" />
<field name="quantity" /> <field name="quantity" />
<field name="is_auto_renew" column_invisible="True" />
<field name="uom_id" /> <field name="uom_id" />
<field <field
name="automatic_price" name="automatic_price"
attrs="{'column_invisible': [('parent.contract_type','=','purchase')]}" column_invisible="parent.contract_type == 'purchase' and not is_auto_renew"
/> />
<field <field name="price_unit" readonly="automatic_price" />
name="price_unit" <field name="specific_price" column_invisible="True" />
attrs="{'readonly': [('automatic_price', '=', True)]}"
/>
<field name="specific_price" invisible="1" />
<field <field
name="discount" name="discount"
groups="product.group_discount_per_so_line" groups="product.group_discount_per_so_line"
/> />
<field name="price_subtotal" /> <field name="price_subtotal" />
<field name="recurring_rule_type" invisible="1" /> <field name="recurring_rule_type" column_invisible="True" />
<field name="recurring_interval" invisible="1" /> <field name="recurring_interval" column_invisible="True" />
<field name="recurring_invoicing_type" invisible="1" /> <field
name="recurring_invoicing_type"
column_invisible="True"
/>
</tree> </tree>
</field> </field>
</group> </group>

View File

@@ -6,18 +6,13 @@
<field name="model">res.config.settings</field> <field name="model">res.config.settings</field>
<field name="inherit_id" ref="account.res_config_settings_view_form" /> <field name="inherit_id" ref="account.res_config_settings_view_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//div[@data-key='account']" position="inside"> <xpath expr="//app[@name='account']" position="inside">
<h2>Contract</h2> <block class="row mt16 o_settings_container" title="Contract">
<div class="row mt16 o_settings_container"> <setting class="col-12 col-lg-6 o_setting_box">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="create_new_line_at_contract_line_renew" /> <field name="create_new_line_at_contract_line_renew" />
</div>
<div class="o_setting_right_pane">
<label for="create_new_line_at_contract_line_renew" /> <label for="create_new_line_at_contract_line_renew" />
</div> </setting>
</div> </block>
</div>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@@ -19,7 +19,7 @@
groups="account.group_account_invoice" groups="account.group_account_invoice"
icon="fa-book" icon="fa-book"
context="{'default_contract_type': 'sale', 'contract_type': 'sale'}" context="{'default_contract_type': 'sale', 'contract_type': 'sale'}"
attrs="{'invisible': [('customer_rank','=',0)]}" invisible="customer_rank == 0"
help="Show the sale contracts for this partner" help="Show the sale contracts for this partner"
> >
<field <field
@@ -40,7 +40,7 @@
groups="account.group_account_invoice" groups="account.group_account_invoice"
icon="fa-book" icon="fa-book"
context="{'default_contract_type': 'purchase', 'contract_type': 'purchase'}" context="{'default_contract_type': 'purchase', 'contract_type': 'purchase'}"
attrs="{'invisible': [('supplier_rank','=',0)]}" invisible="supplier_rank == 0"
help="Show the purchase contracts for this partner" help="Show the purchase contracts for this partner"
> >
<field <field

View File

@@ -13,7 +13,7 @@
<field name="terminate_reason_id" widget="selection" /> <field name="terminate_reason_id" widget="selection" />
<field <field
name="terminate_comment" name="terminate_comment"
attrs="{'required': [('terminate_comment_required', '=', True)]}" required="terminate_comment_required"
/> />
</group> </group>
<footer> <footer>

View File

@@ -37,10 +37,7 @@
<group> <group>
<field name="contract_line_id" invisible="True" /> <field name="contract_line_id" invisible="True" />
<field name="date_start" required="True" /> <field name="date_start" required="True" />
<field <field name="date_end" required="is_auto_renew" />
name="date_end"
attrs="{'required': [('is_auto_renew', '=', True)]}"
/>
<field name="is_auto_renew" /> <field name="is_auto_renew" />
</group> </group>
<footer> <footer>

View File

@@ -16,17 +16,13 @@
name="action_show_contract_to_invoice" name="action_show_contract_to_invoice"
type="object" type="object"
class="btn-link" class="btn-link"
attrs="{'invisible': [('contract_to_invoice_count', '=', 0)]}" invisible="contract_to_invoice_count == 0"
> >
<field name="contract_to_invoice_count" /> <field name="contract_to_invoice_count" />
<span <span invisible="contract_to_invoice_count > 1">
attrs="{'invisible': [('contract_to_invoice_count', '&gt;', 1)]}"
>
contract to invoice contract to invoice
</span> </span>
<span <span invisible="contract_to_invoice_count &lt;= 1">
attrs="{'invisible': [('contract_to_invoice_count', '&lt;=', 1)]}"
>
contracts to invoice contracts to invoice
</span> </span>
</button> </button>
@@ -35,7 +31,7 @@
<footer> <footer>
<button <button
name="create_invoice" name="create_invoice"
attrs="{'invisible': [('contract_to_invoice_count', '=', 0)]}" invisible="contract_to_invoice_count == 0"
string="Create Invoices" string="Create Invoices"
class="btn-primary" class="btn-primary"
type="object" type="object"