[MIG] contract: Migration to 16.0

This commit is contained in:
Wolfgang Pichler
2022-10-24 15:12:13 +02:00
committed by Pedro M. Baeza
parent c72ead9f67
commit 10e9287cb6
15 changed files with 225 additions and 341 deletions

View File

@@ -11,7 +11,7 @@
{
"name": "Recurring - Contracts Management",
"version": "15.0.1.5.2",
"version": "16.0.1.0.0",
"category": "Contract Management",
"license": "AGPL-3",
"author": "Tecnativa, ACSONE SA/NV, Odoo Community Association (OCA)",

View File

@@ -1,24 +1,5 @@
<?xml version="1.0" ?>
<odoo>
<template
id="mail_notification_contract"
inherit_id="mail.mail_notification_paynow"
primary="True"
>
<xpath expr="//t[@t-out='message.body']" position="after">
<t t-raw="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>
<template id="template_contract_modification" name="Contract Modification">
<t t-call="contract.mail_notification_contract">
<table border="1" align="center">

View File

@@ -1,141 +0,0 @@
<?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

@@ -1,17 +0,0 @@
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

@@ -13,6 +13,7 @@ class ContractAbstractContract(models.AbstractModel):
_inherit = "contract.recurrency.basic.mixin"
_name = "contract.abstract.contract"
_description = "Abstract Recurring Contract"
_check_company_auto = True
# These fields will not be synced to the contract
NO_SYNC = ["name", "partner_id", "company_id"]
@@ -31,11 +32,12 @@ class ContractAbstractContract(models.AbstractModel):
journal_id = fields.Many2one(
comodel_name="account.journal",
string="Journal",
domain="[('type', '=', contract_type)," "('company_id', '=', company_id)]",
domain="[('type', '=', contract_type)]",
compute="_compute_journal_id",
store=True,
readonly=False,
index=True,
check_company=True,
)
company_id = fields.Many2one(
"res.company",
@@ -80,3 +82,5 @@ class ContractAbstractContract(models.AbstractModel):
journal = AccountJournal.search(domain, limit=1)
if journal:
contract.journal_id = journal.id
else:
contract.journal_id = None

View File

@@ -35,15 +35,17 @@ class ContractAbstractContractLine(models.AbstractModel):
"applying the pricelist to the product. If not, you will be "
"able to introduce a manual price",
)
specific_price = fields.Float()
price_unit = fields.Float(
# Just to have a currency_id here - will get overwriten in contract.line
# model with the related currency from the contract
currency_id = fields.Many2one("res.currency")
specific_price = fields.Monetary()
price_unit = fields.Monetary(
string="Unit Price",
compute="_compute_price_unit",
inverse="_inverse_price_unit",
)
price_subtotal = fields.Float(
price_subtotal = fields.Monetary(
compute="_compute_price_subtotal",
digits="Account",
string="Sub Total",
)
discount = fields.Float(
@@ -191,7 +193,7 @@ class ContractAbstractContractLine(models.AbstractModel):
from the pricelist otherwise.
"""
for line in self:
if line.automatic_price:
if line.automatic_price and line.product_id:
pricelist = (
line.contract_id.pricelist_id
or line.contract_id.partner_id.with_company(
@@ -209,7 +211,7 @@ class ContractAbstractContractLine(models.AbstractModel):
"old_date", fields.Date.context_today(line)
),
)
line.price_unit = product.price
line.price_unit = pricelist._get_product_price(product, quantity=1)
else:
line.price_unit = line.specific_price
@@ -248,14 +250,20 @@ class ContractAbstractContractLine(models.AbstractModel):
date = self.recurring_next_date or fields.Date.context_today(self)
partner = self.contract_id.partner_id or self.env.user.partner_id
product = self.product_id.with_context(
lang=partner.lang,
partner=partner.id,
quantity=self.quantity,
date=date,
pricelist=self.contract_id.pricelist_id.id,
uom=self.uom_id.id,
)
vals["name"] = self.product_id.get_product_multiline_description_sale()
vals["price_unit"] = product.price
if self.product_id:
product = self.product_id.with_context(
lang=partner.lang,
partner=partner.id,
quantity=self.quantity,
date=date,
pricelist=self.contract_id.pricelist_id.id,
uom=self.uom_id.id,
)
vals["name"] = self.product_id.get_product_multiline_description_sale()
if self.contract_id.pricelist_id:
vals["price_unit"] = self.contract_id.pricelist_id._get_product_price(
product, quantity=1
)
else:
vals["price_unit"] = 0.0
self.update(vals)

View File

@@ -8,10 +8,9 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import api, fields, models
from odoo import Command, api, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo.osv import expression
from odoo.tests import Form
from odoo.tools.translate import _
_logger = logging.getLogger(__name__)
@@ -312,7 +311,8 @@ class ContractContract(models.Model):
@api.depends(
"contract_line_ids.recurring_next_date",
"contract_line_ids.is_canceled",
) # pylint: disable=missing-return
)
# pylint: disable=missing-return
def _compute_recurring_next_date(self):
for contract in self:
recurring_next_date = contract.contract_line_ids.filtered(
@@ -378,7 +378,7 @@ class ContractContract(models.Model):
self.pricelist_id = partner.property_product_pricelist.id
self.fiscal_position_id = partner.env[
"account.fiscal.position"
].get_fiscal_position(partner.id)
]._get_fiscal_position(partner)
if self.contract_type == "purchase":
self.payment_term_id = partner.property_supplier_payment_term_id
else:
@@ -400,10 +400,9 @@ class ContractContract(models.Model):
return new_lines
def _prepare_invoice(self, date_invoice, journal=None):
"""Prepare in a Form the values for the generated invoice record.
"""Prepare the values for the generated invoice record.
:return: A tuple with the vals dictionary and the Form with the
preloaded values for being used in lines.
:return: A vals dictionary
"""
self.ensure_one()
if not journal:
@@ -429,33 +428,39 @@ class ContractContract(models.Model):
"company": self.company_id.name or "",
}
)
invoice_type = "out_invoice"
if self.contract_type == "purchase":
invoice_type = "in_invoice"
move_form = Form(
self.env["account.move"]
.with_company(self.company_id)
.with_context(default_move_type=invoice_type)
invoice_type = (
"in_invoice" if self.contract_type == "purchase" else "out_invoice"
)
move_form.partner_id = self.invoice_partner_id
vals = {
"move_type": invoice_type,
"company_id": self.company_id.id,
"partner_id": self.invoice_partner_id.id,
"ref": self.code,
"currency_id": self.currency_id.id,
"invoice_date": date_invoice,
"journal_id": journal.id,
"invoice_origin": self.name,
"invoice_line_ids": [],
}
if self.payment_term_id:
move_form.invoice_payment_term_id = self.payment_term_id
vals.update(
{
"invoice_payment_term_id": self.payment_term_id.id,
}
)
if self.fiscal_position_id:
move_form.fiscal_position_id = self.fiscal_position_id
vals.update(
{
"fiscal_position_id": self.fiscal_position_id.id,
}
)
if invoice_type == "out_invoice" and self.user_id:
move_form.invoice_user_id = self.user_id
invoice_vals = move_form._values_to_save(all_fields=True)
invoice_vals.update(
{
"ref": self.code,
"company_id": self.company_id.id,
"currency_id": self.currency_id.id,
"invoice_date": date_invoice,
"journal_id": journal.id,
"invoice_origin": self.name,
}
)
return invoice_vals, move_form
vals.update(
{
"invoice_user_id": self.user_id.id,
}
)
return vals
def action_contract_send(self):
self.ensure_one()
@@ -551,19 +556,22 @@ class ContractContract(models.Model):
contract_lines = contract._get_lines_to_invoice(date_ref)
if not contract_lines:
continue
invoice_vals, move_form = contract._prepare_invoice(date_ref)
invoice_vals = contract._prepare_invoice(date_ref)
invoice_vals["invoice_line_ids"] = []
for line in contract_lines:
invoice_line_vals = line._prepare_invoice_line(move_form=move_form)
invoice_line_vals = line._prepare_invoice_line()
if invoice_line_vals:
# Allow extension modules to return an empty dictionary for
# nullifying line. We should then cleanup certain values.
del invoice_line_vals["company_id"]
del invoice_line_vals["company_currency_id"]
invoice_vals["invoice_line_ids"].append((0, 0, invoice_line_vals))
if "company_id" in invoice_line_vals:
del invoice_line_vals["company_id"]
if "company_currency_id" in invoice_line_vals:
del invoice_line_vals["company_currency_id"]
invoice_vals["invoice_line_ids"].append(
Command.create(invoice_line_vals)
)
invoices_values.append(invoice_vals)
# Force the recomputation of journal items
del invoice_vals["line_ids"]
contract_lines._update_recurring_next_date()
return invoices_values

View File

@@ -19,6 +19,7 @@ class ContractLine(models.Model):
_inherit = [
"contract.abstract.contract.line",
"contract.recurrency.mixin",
"analytic.mixin",
]
_order = "sequence,id"
@@ -31,14 +32,11 @@ class ContractLine(models.Model):
auto_join=True,
ondelete="cascade",
)
currency_id = fields.Many2one(related="contract_id.currency_id")
analytic_account_id = fields.Many2one(
string="Analytic account",
comodel_name="account.analytic.account",
)
analytic_tag_ids = fields.Many2many(
comodel_name="account.analytic.tag",
string="Analytic Tags",
)
date_start = fields.Date(required=True)
date_end = fields.Date(compute="_compute_date_end", store=True, readonly=False)
termination_notice_date = fields.Date(
@@ -107,8 +105,13 @@ class ContractLine(models.Model):
)
@api.depends(
"last_date_invoiced", "date_start", "date_end", "contract_id.last_date_invoiced"
) # pylint: disable=missing-return
"last_date_invoiced",
"date_start",
"date_end",
"contract_id.last_date_invoiced",
"contract_id.contract_line_ids.last_date_invoiced",
)
# pylint: disable=missing-return
def _compute_next_period_date_start(self):
"""Rectify next period date start if another line in the contract has been
already invoiced previously when the recurrence is by contract.
@@ -146,7 +149,15 @@ class ContractLine(models.Model):
else:
rec.termination_notice_date = False
@api.depends("is_canceled", "date_start", "date_end", "is_auto_renew")
@api.depends(
"is_canceled",
"date_start",
"date_end",
"is_auto_renew",
"manual_renew_needed",
"termination_notice_date",
"successor_contract_line_id",
)
def _compute_state(self):
today = fields.Date.context_today(self)
for rec in self:
@@ -542,33 +553,24 @@ class ContractLine(models.Model):
else:
rec.create_invoice_visibility = False
def _prepare_invoice_line(self, move_form):
def _prepare_invoice_line(self):
self.ensure_one()
dates = self._get_period_to_invoice(
self.last_date_invoiced, self.recurring_next_date
)
line_form = move_form.invoice_line_ids.new()
line_form.display_type = self.display_type
line_form.product_id = self.product_id
invoice_line_vals = line_form._values_to_save(all_fields=True)
name = self._insert_markers(dates[0], dates[1])
invoice_line_vals.update(
{
"account_id": invoice_line_vals["account_id"]
if "account_id" in invoice_line_vals and not self.display_type
else False,
"quantity": self._get_quantity_to_invoice(*dates),
"product_uom_id": self.uom_id.id,
"discount": self.discount,
"contract_line_id": self.id,
"sequence": self.sequence,
"name": name,
"analytic_account_id": self.analytic_account_id.id,
"analytic_tag_ids": [(6, 0, self.analytic_tag_ids.ids)],
"price_unit": self.price_unit,
}
)
return invoice_line_vals
return {
"quantity": self._get_quantity_to_invoice(*dates),
"product_uom_id": self.uom_id.id,
"discount": self.discount,
"contract_line_id": self.id,
"analytic_distribution": self.analytic_distribution,
"sequence": self.sequence,
"name": name,
"price_unit": self.price_unit,
"display_type": self.display_type or "product",
"product_id": self.product_id.id,
}
def _get_period_to_invoice(
self, last_date_invoiced, recurring_next_date, stop_at_date_end=True
@@ -1071,9 +1073,7 @@ class ContractLine(models.Model):
to_renew.renew()
@api.model
def fields_view_get(
self, view_id=None, view_type="form", toolbar=False, submenu=False
):
def get_view(self, view_id=None, view_type="form", **options):
default_contract_type = self.env.context.get("default_contract_type")
if view_type == "tree" and default_contract_type == "purchase":
view_id = self.env.ref("contract.contract_line_supplier_tree_view").id
@@ -1082,7 +1082,7 @@ class ContractLine(models.Model):
view_id = self.env.ref("contract.contract_line_supplier_form_view").id
elif default_contract_type == "sale":
view_id = self.env.ref("contract.contract_line_customer_form_view").id
return super().fields_view_get(view_id, view_type, toolbar, submenu)
return super().get_view(view_id, view_type, **options)
def unlink(self):
"""stop unlink uncnacled lines"""

View File

@@ -19,7 +19,7 @@ class ContractModification(models.Model):
ondelete="cascade",
index=True,
)
sent = fields.Boolean(default=False)
sent = fields.Boolean()
@api.model_create_multi
def create(self, vals_list):

View File

@@ -242,12 +242,12 @@ class TestContract(TestContractBase):
self.assertEqual(self.acct_line.price_unit, 1100)
# Try to write other price
self.acct_line.price_unit = 10
self.acct_line.refresh()
self.acct_line.invalidate_model()
self.assertEqual(self.acct_line.price_unit, 1100)
# Now disable automatic price
self.acct_line.automatic_price = False
self.acct_line.price_unit = 10
self.acct_line.refresh()
self.acct_line.invalidate_model()
self.assertEqual(self.acct_line.price_unit, 10)
def test_contract(self):
@@ -266,7 +266,7 @@ class TestContract(TestContractBase):
def test_contract_level_recurrence(self):
self.contract3.recurring_create_invoice()
self.contract3.flush()
self.contract3.flush_recordset()
def test_contract_daily(self):
recurring_next_date = to_date("2018-02-23")
@@ -608,7 +608,7 @@ class TestContract(TestContractBase):
self.contract.copy()
purchase_count = self.partner.purchase_contract_count + 1
self.contract2.copy()
self.partner.refresh()
self.partner.invalidate_model()
self.assertEqual(self.partner.sale_contract_count, sale_count)
self.assertEqual(self.partner.purchase_contract_count, purchase_count)
@@ -1691,7 +1691,8 @@ class TestContract(TestContractBase):
self.assertFalse(line_4.successor_contract_line_id)
def test_renew_create_new_line(self):
date_start = fields.Date.from_string("2022-01-01")
date_start = self.today - relativedelta(months=9)
date_end = date_start + relativedelta(months=12) - relativedelta(days=1)
self.acct_line.write(
{
"is_auto_renew": True,
@@ -1701,16 +1702,17 @@ class TestContract(TestContractBase):
}
)
self.acct_line._onchange_is_auto_renew()
self.assertEqual(self.acct_line.date_end, fields.Date.from_string("2022-12-31"))
self.assertEqual(self.acct_line.date_end, date_end)
new_line = self.acct_line.renew()
self.assertFalse(self.acct_line.is_auto_renew)
self.assertTrue(new_line.is_auto_renew)
self.assertEqual(new_line.date_start, fields.Date.from_string("2023-01-01"))
self.assertEqual(new_line.date_end, fields.Date.from_string("2023-12-31"))
self.assertEqual(new_line.date_start, date_start + relativedelta(months=12))
self.assertEqual(new_line.date_end, date_end + relativedelta(months=12))
def test_renew_extend_original_line(self):
self.contract.company_id.create_new_line_at_contract_line_renew = False
date_start = fields.Date.from_string("2022-01-01")
date_start = self.today - relativedelta(months=9)
date_end = date_start + relativedelta(months=12) - relativedelta(days=1)
self.acct_line.write(
{
"is_auto_renew": True,
@@ -1720,13 +1722,11 @@ class TestContract(TestContractBase):
}
)
self.acct_line._onchange_is_auto_renew()
self.assertEqual(self.acct_line.date_end, fields.Date.from_string("2022-12-31"))
self.assertEqual(self.acct_line.date_end, date_end)
self.acct_line.renew()
self.assertTrue(self.acct_line.is_auto_renew)
self.assertEqual(
self.acct_line.date_start, fields.Date.from_string("2022-01-01")
)
self.assertEqual(self.acct_line.date_end, fields.Date.from_string("2023-12-31"))
self.assertEqual(self.acct_line.date_start, date_start)
self.assertEqual(self.acct_line.date_end, date_end + relativedelta(months=12))
def test_cron_recurring_create_invoice(self):
self.acct_line.date_start = "2018-01-01"
@@ -2045,7 +2045,8 @@ class TestContract(TestContractBase):
]
self.assertEqual(set(lines.mapped("state")), set(states))
# Test search method
lines.flush() # Needed for computed stored fields like termination_notice_date
lines.flush_recordset() # Needed for computed stored fields
# like termination_notice_date
for state in states:
lines = self.env["contract.line"].search([("state", "=", state)])
self.assertTrue(lines, state)
@@ -2152,17 +2153,17 @@ class TestContract(TestContractBase):
action["context"]["default_contract_line_id"], self.acct_line.id
)
def test_purchase_fields_view_get(self):
def test_purchase_get_view(self):
purchase_tree_view = self.env.ref("contract.contract_line_supplier_tree_view")
purchase_form_view = self.env.ref("contract.contract_line_supplier_form_view")
view = self.acct_line.with_context(
default_contract_type="purchase"
).fields_view_get(view_type="tree")
self.assertEqual(view["view_id"], purchase_tree_view.id)
view = self.acct_line.with_context(
default_contract_type="purchase"
).fields_view_get(view_type="form")
self.assertEqual(view["view_id"], purchase_form_view.id)
view = self.acct_line.with_context(default_contract_type="purchase").get_view(
view_type="tree"
)
self.assertEqual(view["id"], purchase_tree_view.id)
view = self.acct_line.with_context(default_contract_type="purchase").get_view(
view_type="form"
)
self.assertEqual(view["id"], purchase_form_view.id)
def test_multicompany_partner_edited(self):
"""Editing a partner with contracts in several companies works."""
@@ -2185,12 +2186,12 @@ class TestContract(TestContractBase):
company_id=company2.id
).write({"is_company": False, "parent_id": parent_partner.id})
def test_sale_fields_view_get(self):
def test_sale_get_view(self):
sale_form_view = self.env.ref("contract.contract_line_customer_form_view")
view = self.acct_line.with_context(
default_contract_type="sale"
).fields_view_get(view_type="form")
self.assertEqual(view["view_id"], sale_form_view.id)
view = self.acct_line.with_context(default_contract_type="sale").get_view(
view_type="form"
)
self.assertEqual(view["id"], sale_form_view.id)
def test_contract_count_invoice(self):
self.contract.recurring_create_invoice()

View File

@@ -12,34 +12,70 @@
<header attrs="{'invisible': [('display_type', '!=', False)]}" />
<sheet>
<field name="specific_price" invisible="1" />
<field name="currency_id" invisible="1" />
<field colspan="1" name="product_uom_category_id" invisible="1" />
<group>
<field
colspan="1"
name="product_id"
attrs="{'required': [('display_type', '=', 'product')],'invisible': [('display_type', '!=', False)]}"
/>
</group>
<group
col="4"
col="6"
attrs="{'invisible': [('display_type', '!=', False)]}"
>
<field
colspan="4"
name="product_id"
attrs="{'required': [('display_type', '=', False)]}"
/>
<field name="product_uom_category_id" invisible="1" />
<label for="quantity" />
<div class="o_row">
<field name="quantity" class="oe_inline" />
<group colspan="1">
<label for="automatic_price" colspan="2" />
<field colspan="2" name="automatic_price" nolabel="1" />
</group>
<group colspan="1">
<label for="price_unit" colspan="2" />
<field
colspan="2"
name="price_unit"
attrs="{'readonly': [('automatic_price', '=', True)]}"
nolabel="1"
/>
</group>
<group colspan="1">
<label for="quantity" colspan="2" />
<field
colspan="2"
name="quantity"
class="oe_inline"
nolabel="1"
/>
</group>
<group colspan="1">
<label for="uom_id" colspan="2" />
<field
colspan="2"
name="uom_id"
class="oe_inline"
groups="uom.group_uom"
attrs="{'required': [('display_type', '=', False)]}"
nolabel="1"
/>
</div>
<field colspan="2" name="automatic_price" />
<field
colspan="2"
name="price_unit"
attrs="{'readonly': [('automatic_price', '=', True)]}"
/>
<field colspan="2" name="discount" groups="base.group_no_one" />
</group>
<group colspan="1">
<label for="discount" colspan="2" />
<field
colspan="2"
name="discount"
groups="base.group_no_one"
nolabel="1"
/>
</group>
<group colspan="1">
<label for="price_subtotal" colspan="2" />
<field
colspan="2"
name="price_subtotal"
readonly="1"
nolabel="1"
/>
</group>
</group>
<label
for="name"

View File

@@ -207,6 +207,7 @@
context="{'default_display_type': 'line_note'}"
/>
</control>
<field name="currency_id" invisible="1" />
<field name="display_type" invisible="1" />
<field name="sequence" widget="handle" />
<field name="product_id" />
@@ -219,11 +220,6 @@
name="analytic_account_id"
groups="analytic.group_analytic_accounting"
/>
<field
name="analytic_tag_ids"
widget="many2many_tags"
groups="analytic.group_analytic_tags"
/>
<field name="quantity" />
<field name="uom_id" />
<field
@@ -314,6 +310,7 @@
context="{'default_display_type': 'line_note'}"
/>
</control>
<field name="currency_id" invisible="1" />
<field name="display_type" invisible="1" />
<field name="sequence" widget="handle" />
<field name="product_id" />
@@ -322,11 +319,6 @@
name="analytic_account_id"
groups="analytic.group_analytic_accounting"
/>
<field
name="analytic_tag_ids"
widget="many2many_tags"
groups="analytic.group_analytic_tags"
/>
<field name="quantity" />
<field name="uom_id" />
<field
@@ -502,9 +494,7 @@
>{'default_customer_rank': 1, 'default_supplier_rank': 0, 'res_partner_search_mode': 'customer', 'show_vat': True}</attribute>
</field>
<field name="journal_id" position="attributes">
<attribute
name="domain"
>[('type', '=', 'sale'),('company_id', '=', company_id)]</attribute>
<attribute name="domain">[('type', '=', 'sale')]</attribute>
</field>
</field>
</record>
@@ -523,9 +513,7 @@
>{'default_customer_rank': False, 'default_supplier_rank': 1, 'res_partner_search_mode': 'supplier', 'show_vat': True}</attribute>
</field>
<field name="journal_id" position="attributes">
<attribute
name="domain"
>[('type', '=', 'purchase'),('company_id', '=', company_id)]</attribute>
<attribute name="domain">[('type', '=', 'purchase')]</attribute>
</field>
</field>
</record>

View File

@@ -13,6 +13,9 @@
<group name="recurrence_info" position="inside">
<group>
<field name="create_invoice_visibility" invisible="1" />
<field name="is_stop_plan_successor_allowed" invisible="1" />
<field name="is_stop_allowed" invisible="1" />
<field name="is_cancel_allowed" invisible="1" />
<field name="date_start" required="1" />
<field name="next_period_date_start" />
<field name="recurring_next_date" />
@@ -41,7 +44,7 @@
<group name="recurrence_info" position="after">
<group
name="analytic"
groups="analytic.group_analytic_accounting,analytic.group_analytic_tags"
groups="analytic.group_analytic_accounting"
attrs="{'invisible': [('display_type', '!=', False)]}"
>
<field
@@ -49,9 +52,9 @@
groups="analytic.group_analytic_accounting"
/>
<field
name="analytic_tag_ids"
widget="many2many_tags"
groups="analytic.group_analytic_tags"
name="analytic_distribution"
widget="analytic_distribution"
groups="analytic.group_analytic_accounting"
/>
</group>
</group>
@@ -104,9 +107,9 @@
groups="analytic.group_analytic_accounting"
/>
<field
name="analytic_tag_ids"
widget="many2many_tags"
groups="analytic.group_analytic_tags"
name="analytic_distribution"
widget="analytic_distribution"
groups="analytic.group_analytic_accounting"
/>
<field name="quantity" />
<field name="uom_id" />

View File

@@ -26,6 +26,7 @@
name="contract_line_ids"
widget="section_and_note_one2many"
nolabel="1"
colspan="2"
>
<tree>
<control>
@@ -66,8 +67,11 @@
name="group_legend"
string="Legend (for the markers inside invoice lines description)"
>
<p> <strong>#START#</strong>: Start date of the invoiced period</p>
<p> <strong>#END#</strong>: End date of the invoiced period</p>
<div colspan="2">
<p> <strong
>#START#</strong>: Start date of the invoiced period</p>
<p> <strong>#END#</strong>: End date of the invoiced period</p>
</div>
</group>
</form>
</field>

View File

@@ -5,14 +5,18 @@
<record id="view_partner_form" model="ir.ui.view">
<field name="inherit_id" ref="base.view_partner_form" />
<field name="model">res.partner</field>
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]" />
<field type="xml" name="arch">
<xpath expr="//div[@name='button_box']" position="inside">
<field name="customer_rank" invisible="1" />
<field
name="customer_rank"
invisible="1"
groups="account.group_account_invoice"
/>
<button
name="act_show_contract"
type="object"
class="oe_stat_button"
groups="account.group_account_invoice"
icon="fa-book"
context="{'default_contract_type': 'sale', 'contract_type': 'sale'}"
attrs="{'invisible': [('customer_rank','=',0)]}"
@@ -24,11 +28,16 @@
string="Sale Contracts"
/>
</button>
<field name="supplier_rank" invisible="1" />
<field
name="supplier_rank"
invisible="1"
groups="account.group_account_invoice"
/>
<button
name="act_show_contract"
type="object"
class="oe_stat_button"
groups="account.group_account_invoice"
icon="fa-book"
context="{'default_contract_type': 'purchase', 'contract_type': 'purchase'}"
attrs="{'invisible': [('supplier_rank','=',0)]}"