Merge PR #726 into 13.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2021-10-13 23:18:36 +00:00
55 changed files with 1514 additions and 992 deletions

View File

@@ -1,14 +1,5 @@
# Copyright (C) 2018 - TODAY, Pavlov Media # Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, SUPERUSER_ID
from . import models from . import models
from . import wizards
def post_init_agreement_legal(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, dict())
cr.execute(
"UPDATE agreement SET stage_id = %s WHERE stage_id IS NULL;",
(env.ref("agreement_legal.agreement_stage_new").id,),
)
return True

View File

@@ -15,7 +15,6 @@
"depends": ["contacts", "agreement", "product"], "depends": ["contacts", "agreement", "product"],
"data": [ "data": [
"data/ir_sequence.xml", "data/ir_sequence.xml",
"data/module_category.xml",
"data/agreement_stage.xml", "data/agreement_stage.xml",
"data/agreement_type.xml", "data/agreement_type.xml",
"security/res_groups.xml", "security/res_groups.xml",
@@ -29,15 +28,14 @@
"views/agreement_stages.xml", "views/agreement_stages.xml",
"views/agreement_type.xml", "views/agreement_type.xml",
"views/agreement_subtype.xml", "views/agreement_subtype.xml",
"views/agreement_renewaltype.xml",
"views/agreement_increasetype.xml",
"views/res_partner.xml", "views/res_partner.xml",
"views/agreement.xml", "views/agreement.xml",
"views/menu.xml", "views/menu.xml",
"views/assets.xml",
"wizards/create_agreement_wizard.xml",
], ],
"demo": ["demo/demo.xml"], "demo": ["demo/demo.xml"],
"qweb": ["static/src/xml/domain_widget_view.xml"], "qweb": ["static/src/xml/agreement.xml"],
"post_init_hook": "post_init_agreement_legal",
"application": True, "application": True,
"development_status": "Beta", "development_status": "Beta",
"maintainers": ["max3903", "ygol"], "maintainers": ["max3903", "ygol"],

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="agreement_stage_new" model="agreement.stage"> <record id="agreement_stage_new" model="agreement.stage">
<field name="name">New</field> <field name="name">New</field>
@@ -40,6 +40,12 @@
<field name="sequence">80</field> <field name="sequence">80</field>
<field name="stage_type">agreement</field> <field name="stage_type">agreement</field>
</record> </record>
<record id="agreement_stage_terminated" model="agreement.stage">
<field name="name">Terminated</field>
<field name="sequence">90</field>
<field name="fold">True</field>
<field name="stage_type">agreement</field>
</record>
<record id="agreement_stage_cancelled" model="agreement.stage"> <record id="agreement_stage_cancelled" model="agreement.stage">
<field name="name">Cancelled</field> <field name="name">Cancelled</field>
<field name="sequence">100</field> <field name="sequence">100</field>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="agreement_type_agreement" model="agreement.type"> <record id="agreement_type_agreement" model="agreement.type">
<field name="name">Agreement</field> <field name="name">Agreement</field>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1"> <odoo noupdate="1">
<!-- Sequence for agreement --> <!-- Sequence for agreement -->
<record id="seq_agreement" model="ir.sequence"> <record id="seq_agreement" model="ir.sequence">

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="agreement" model="ir.module.category">
<field name="name">Agreement</field>
<field name="sequence">80</field>
</record>
</odoo>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!-- <!--
© 2019 Ygol Internetwork (yves@ygol.com) © 2019 Ygol Internetwork (yves@ygol.com)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

View File

@@ -12,7 +12,4 @@ from . import (
agreement_type, agreement_type,
agreement_subtype, agreement_subtype,
res_partner, res_partner,
product_template,
agreement_renewaltype,
agreement_increasetype,
) )

View File

@@ -1,13 +1,17 @@
# Copyright (C) 2018 - TODAY, Pavlov Media # Copyright (C) 2018 - TODAY, Pavlov Media
# 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 ast
import json as simplejson
from lxml import etree
from odoo import _, api, fields, models from odoo import _, api, fields, models
class Agreement(models.Model): class Agreement(models.Model):
_inherit = "agreement" _inherit = "agreement"
# General
name = fields.Char(string="Title", required=True) name = fields.Char(string="Title", required=True)
version = fields.Integer( version = fields.Integer(
string="Version", string="Version",
@@ -23,7 +27,7 @@ class Agreement(models.Model):
help="The revision will increase with every save event.", help="The revision will increase with every save event.",
) )
description = fields.Text( description = fields.Text(
string="Description", tracking=True, help="Description of the agreement", string="Description", tracking=True, help="Description of the agreement"
) )
dynamic_description = fields.Text( dynamic_description = fields.Text(
compute="_compute_dynamic_description", compute="_compute_dynamic_description",
@@ -31,7 +35,7 @@ class Agreement(models.Model):
help="Compute dynamic description", help="Compute dynamic description",
) )
start_date = fields.Date( start_date = fields.Date(
string="Start Date", tracking=True, help="When the agreement starts.", string="Start Date", tracking=True, help="When the agreement starts."
) )
end_date = fields.Date( end_date = fields.Date(
string="End Date", tracking=True, help="When the agreement ends." string="End Date", tracking=True, help="When the agreement ends."
@@ -53,12 +57,6 @@ class Agreement(models.Model):
tracking=True, tracking=True,
help="Date the contract was signed by the Partner.", help="Date the contract was signed by the Partner.",
) )
term = fields.Integer(
string="Term (Months)",
tracking=True,
help="Number of months this agreement/contract is in effect with the "
"partner.",
)
expiration_notice = fields.Integer( expiration_notice = fields.Integer(
string="Exp. Notice (Days)", string="Exp. Notice (Days)",
tracking=True, tracking=True,
@@ -88,12 +86,6 @@ class Agreement(models.Model):
copy=False, copy=False,
help="ID used for internal contract tracking.", help="ID used for internal contract tracking.",
) )
increase_type_id = fields.Many2one(
comodel_name="agreement.increasetype",
string="Increase Type",
tracking=True,
help="The amount that certain rates may increase.",
)
termination_requested = fields.Date( termination_requested = fields.Date(
string="Termination Requested Date", string="Termination Requested Date",
tracking=True, tracking=True,
@@ -105,23 +97,18 @@ class Agreement(models.Model):
help="Date that the contract was terminated.", help="Date that the contract was terminated.",
) )
reviewed_date = fields.Date(string="Reviewed Date", tracking=True) reviewed_date = fields.Date(string="Reviewed Date", tracking=True)
reviewed_user_id = fields.Many2one( reviewed_user_id = fields.Many2one("res.users", string="Reviewed By", tracking=True)
comodel_name="res.users", string="Reviewed By", tracking=True
)
approved_date = fields.Date(string="Approved Date", tracking=True) approved_date = fields.Date(string="Approved Date", tracking=True)
approved_user_id = fields.Many2one( approved_user_id = fields.Many2one("res.users", string="Approved By", tracking=True)
comodel_name="res.users", string="Approved By", tracking=True
)
currency_id = fields.Many2one(comodel_name="res.currency", string="Currency")
partner_id = fields.Many2one( partner_id = fields.Many2one(
comodel_name="res.partner", "res.partner",
string="Partner", string="Partner",
required=False, required=False,
copy=True, copy=True,
help="The customer or vendor this agreement is related to.", help="The customer or vendor this agreement is related to.",
) )
partner_contact_id = fields.Many2one( partner_contact_id = fields.Many2one(
comodel_name="res.partner", "res.partner",
string="Partner Contact", string="Partner Contact",
copy=True, copy=True,
help="The primary partner contact (If Applicable).", help="The primary partner contact (If Applicable).",
@@ -133,7 +120,7 @@ class Agreement(models.Model):
related="partner_contact_id.email", string="Partner Email" related="partner_contact_id.email", string="Partner Email"
) )
company_contact_id = fields.Many2one( company_contact_id = fields.Many2one(
comodel_name="res.partner", "res.partner",
string="Company Contact", string="Company Contact",
copy=True, copy=True,
help="The primary contact in the company.", help="The primary contact in the company.",
@@ -187,89 +174,66 @@ class Agreement(models.Model):
string="Dynamic Parties", string="Dynamic Parties",
help="Compute dynamic parties", help="Compute dynamic parties",
) )
agreement_type_id = fields.Many2one(tracking=True) agreement_type_id = fields.Many2one(tracking=True,)
agreement_subtype_id = fields.Many2one( agreement_subtype_id = fields.Many2one(
comodel_name="agreement.subtype", "agreement.subtype",
string="Agreement Sub-type", string="Agreement Sub-type",
tracking=True, tracking=True,
help="Select the sub-type of this agreement. Sub-Types are related to " help="Select the sub-type of this agreement. Sub-Types are related to "
"agreement types.", "agreement types.",
) )
product_ids = fields.Many2many(
comodel_name="product.template", string="Products & Services"
)
assigned_user_id = fields.Many2one( assigned_user_id = fields.Many2one(
comodel_name="res.users", "res.users",
string="Assigned To", string="Assigned To",
tracking=True, tracking=True,
help="Select the user who manages this agreement.", help="Select the user who manages this agreement.",
) )
company_signed_user_id = fields.Many2one( company_signed_user_id = fields.Many2one(
comodel_name="res.users", "res.users",
string="Signed By", string="Signed By",
tracking=True, tracking=True,
help="The user at our company who authorized/signed the agreement or " help="The user at our company who authorized/signed the agreement or "
"contract.", "contract.",
) )
partner_signed_user_id = fields.Many2one( partner_signed_user_id = fields.Many2one(
comodel_name="res.partner", "res.partner",
string="Signed By (Partner)", string="Signed By (Partner)",
tracking=True, tracking=True,
help="Contact on the account that signed the agreement/contract.", help="Contact on the account that signed the agreement/contract.",
) )
parent_agreement_id = fields.Many2one( parent_agreement_id = fields.Many2one(
comodel_name="agreement", "agreement",
string="Parent Agreement", string="Parent Agreement",
help="Link this agreement to a parent agreement. For example if this " help="Link this agreement to a parent agreement. For example if this "
"agreement is an amendment to another agreement. This list will " "agreement is an amendment to another agreement. This list will "
"only show other agreements related to the same account.", "only show other agreements related to the same account.",
) )
renewal_type_id = fields.Many2one(
comodel_name="agreement.renewaltype",
string="Renewal Type",
tracking=True,
help="Describes what happens after the contract expires.",
)
recital_ids = fields.One2many( recital_ids = fields.One2many(
comodel_name="agreement.recital", "agreement.recital", "agreement_id", string="Recitals", copy=True
inverse_name="agreement_id",
string="Recitals",
copy=True,
) )
sections_ids = fields.One2many( sections_ids = fields.One2many(
comodel_name="agreement.section", "agreement.section", "agreement_id", string="Sections", copy=True
inverse_name="agreement_id",
string="Sections",
copy=True,
)
clauses_ids = fields.One2many(
comodel_name="agreement.clause", inverse_name="agreement_id", string="Clauses"
) )
clauses_ids = fields.One2many("agreement.clause", "agreement_id", string="Clauses")
appendix_ids = fields.One2many( appendix_ids = fields.One2many(
comodel_name="agreement.appendix", "agreement.appendix", "agreement_id", string="Appendices", copy=True
inverse_name="agreement_id",
string="Appendices",
copy=True,
) )
previous_version_agreements_ids = fields.One2many( previous_version_agreements_ids = fields.One2many(
comodel_name="agreement", "agreement",
inverse_name="parent_agreement_id", "parent_agreement_id",
string="Previous Versions", string="Previous Versions",
copy=False, copy=False,
context={"active_test": False}, context={"active_test": False},
) )
child_agreements_ids = fields.One2many( child_agreements_ids = fields.One2many(
comodel_name="agreement", "agreement",
inverse_name="parent_agreement_id", "parent_agreement_id",
string="Child Agreements", string="Child Agreements",
copy=False, copy=False,
domain=[("active", "=", True)], domain=[("active", "=", True)],
) )
line_ids = fields.One2many( line_ids = fields.One2many(
comodel_name="agreement.line", "agreement.line", "agreement_id", string="Products/Services", copy=False
inverse_name="agreement_id",
string="Products/Services",
copy=False,
) )
state = fields.Selection( state = fields.Selection(
[("draft", "Draft"), ("active", "Active"), ("inactive", "Inactive")], [("draft", "Draft"), ("active", "Active"), ("inactive", "Inactive")],
@@ -277,17 +241,32 @@ class Agreement(models.Model):
tracking=True, tracking=True,
) )
notification_address_id = fields.Many2one( notification_address_id = fields.Many2one(
comodel_name="res.partner", "res.partner",
string="Notification Address", string="Notification Address",
help="The address to send notificaitons to, if different from " help="The address to send notificaitons to, if different from "
"customer address.(Address Type = Other)", "customer address.(Address Type = Other)",
) )
signed_contract_filename = fields.Char(string="Filename") signed_contract_filename = fields.Char(string="Filename")
signed_contract = fields.Binary(string="Signed Document", tracking=True) signed_contract = fields.Binary(string="Signed Document", tracking=True)
field_id = fields.Many2one(
# Dynamic field editor "ir.model.fields",
field_domain = fields.Char( string="Field",
string="Field Expression", default='[["active", "=", True]]' help="""Select target field from the related document model. If it is a
relationship field you will be able to select a target field at the
destination of the relationship.""",
)
sub_object_id = fields.Many2one(
"ir.model",
string="Sub-model",
help="""When a relationship field is selected as first field, this
field shows the document model the relationship goes to.""",
)
sub_model_object_field_id = fields.Many2one(
"ir.model.fields",
string="Sub-field",
help="""When a relationship field is selected as first field, this
field lets you select the target field within the destination document
model (sub-model).""",
) )
default_value = fields.Char( default_value = fields.Char(
string="Default Value", string="Default Value",
@@ -298,26 +277,32 @@ class Agreement(models.Model):
help="""Final placeholder expression, to be copy-pasted in the desired help="""Final placeholder expression, to be copy-pasted in the desired
template field.""", template field.""",
) )
created_by = fields.Many2one(
"res.users",
string="Created By",
copy=False,
default=lambda self: self.env.user,
help="User which create the agreement.",
)
date_created = fields.Datetime(
string="Created On",
copy=False,
default=lambda self: fields.Datetime.now(),
help="Date which create the agreement.",
)
template_id = fields.Many2one(
"agreement", string="Template", domain=[("is_template", "=", True)],
)
readonly = fields.Boolean(related="stage_id.readonly",)
@api.onchange("field_domain", "default_value") # compute the dynamic content for jinja expression
def onchange_copyvalue(self):
self.copyvalue = False
if self.field_domain:
string_list = self.field_domain.split(",")
if string_list:
field_domain = string_list[0][3:-1]
self.copyvalue = "${{object.{} or {}}}".format(
field_domain, self.default_value or "''"
)
# compute the dynamic content for mako expression
def _compute_dynamic_description(self): def _compute_dynamic_description(self):
MailTemplates = self.env["mail.template"] MailTemplates = self.env["mail.template"]
for agreement in self: for agreement in self:
lang = agreement.partner_id.lang or "en_US" lang = agreement.partner_id.lang or "en_US"
description = MailTemplates.with_context(lang=lang)._render_template( description = MailTemplates.with_context(lang=lang)._render_template(
agreement.description, "agreement", agreement.id agreement.description, "agreement", [agreement.id]
) )[agreement.id]
agreement.dynamic_description = description agreement.dynamic_description = description
def _compute_dynamic_parties(self): def _compute_dynamic_parties(self):
@@ -325,8 +310,8 @@ class Agreement(models.Model):
for agreement in self: for agreement in self:
lang = agreement.partner_id.lang or "en_US" lang = agreement.partner_id.lang or "en_US"
parties = MailTemplates.with_context(lang=lang)._render_template( parties = MailTemplates.with_context(lang=lang)._render_template(
agreement.parties, "agreement", agreement.id agreement.parties, "agreement", [agreement.id]
) )[agreement.id]
agreement.dynamic_parties = parties agreement.dynamic_parties = parties
def _compute_dynamic_special_terms(self): def _compute_dynamic_special_terms(self):
@@ -334,10 +319,30 @@ class Agreement(models.Model):
for agreement in self: for agreement in self:
lang = agreement.partner_id.lang or "en_US" lang = agreement.partner_id.lang or "en_US"
special_terms = MailTemplates.with_context(lang=lang)._render_template( special_terms = MailTemplates.with_context(lang=lang)._render_template(
agreement.special_terms, "agreement", agreement.id agreement.special_terms, "agreement", [agreement.id]
) )[agreement.id]
agreement.dynamic_special_terms = special_terms agreement.dynamic_special_terms = special_terms
@api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False
if self.field_id and not self.field_id.relation:
self.copyvalue = "${{object.{} or {}}}".format(
self.field_id.name, self.default_value or "''"
)
self.sub_model_object_field_id = False
if self.field_id and self.field_id.relation:
self.sub_object_id = self.env["ir.model"].search(
[("model", "=", self.field_id.relation)]
)[0]
if self.sub_model_object_field_id:
self.copyvalue = "${{object.{}.{} or {}}}".format(
self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or "''",
)
# Used for Kanban grouped_by view # Used for Kanban grouped_by view
@api.model @api.model
def _read_group_stage_ids(self, stages, domain, order): def _read_group_stage_ids(self, stages, domain, order):
@@ -347,40 +352,73 @@ class Agreement(models.Model):
return stage_ids return stage_ids
stage_id = fields.Many2one( stage_id = fields.Many2one(
comodel_name="agreement.stage", "agreement.stage",
string="Stage", string="Stage",
group_expand="_read_group_stage_ids", group_expand="_read_group_stage_ids",
help="Select the current stage of the agreement.", help="Select the current stage of the agreement.",
default=lambda self: self._get_default_stage_id(),
tracking=True, tracking=True,
index=True, index=True,
copy=False,
) )
@api.model
def _get_default_stage_id(self):
try:
stage_id = self.env.ref("agreement_legal.agreement_stage_new").id
except ValueError:
stage_id = False
return stage_id
def _get_old_version_default_vals(self):
self.ensure_one()
default_vals = {
"name": "{} - OLD VERSION".format(self.name),
"active": False,
"parent_agreement_id": self.id,
"version": self.version,
"revision": self.revision,
"created_by": self.created_by.id,
"date_created": self.date_created,
"code": "{}-V{}".format(self.code, str(self.version)),
"stage_id": self.stage_id.id,
}
return default_vals
# Create New Version Button # Create New Version Button
def create_new_version(self): def create_new_version(self):
for rec in self: for rec in self:
if not rec.state == "draft": if not rec.state == "draft":
# Make sure status is draft # Make sure status is draft
rec.state = "draft" rec.state = "draft"
default_vals = {
"name": "{} - OLD VERSION".format(rec.name),
"active": False,
"parent_agreement_id": rec.id,
}
# Make a current copy and mark it as old # Make a current copy and mark it as old
rec.copy(default=default_vals) rec.copy(default=rec._get_old_version_default_vals())
# Update version, created by and created on
rec.update(
{
"version": rec.version + 1,
"created_by": self.env.user.id,
"date_created": fields.Datetime.now(),
}
)
# Reset revision to 0 since it's a new version
return super().write({"revision": 0}) return super().write({"revision": 0})
def create_new_agreement(self): def _get_new_agreement_default_vals(self):
self.ensure_one()
default_vals = { default_vals = {
"name": "NEW", "name": "New",
"active": True, "active": True,
"version": 1, "version": 1,
"revision": 0, "revision": 0,
"state": "draft", "state": "draft",
"stage_id": self.env.ref("agreement_legal.agreement_stage_new").id, "is_template": False,
} }
res = self.copy(default=default_vals) return default_vals
res.sections_ids.mapped("clauses_ids").write({"agreement_id": res.id})
def create_new_agreement(self):
self.ensure_one()
res = self.copy(default=self._get_new_agreement_default_vals())
return { return {
"res_model": "agreement", "res_model": "agreement",
"type": "ir.actions.act_window", "type": "ir.actions.act_window",
@@ -394,13 +432,72 @@ class Agreement(models.Model):
if vals.get("code", _("New")) == _("New"): if vals.get("code", _("New")) == _("New"):
vals["code"] = self.env["ir.sequence"].next_by_code("agreement") or _("New") vals["code"] = self.env["ir.sequence"].next_by_code("agreement") or _("New")
if not vals.get("stage_id"): if not vals.get("stage_id"):
vals["stage_id"] = self.env.ref("agreement_legal.agreement_stage_new").id vals["stage_id"] = self._get_default_stage_id()
return super(Agreement, self).create(vals) return super().create(vals)
# Increments the revision on each save action # Increments the revision on each save action
def write(self, vals): def write(self, vals):
res = True res = True
for rec in self: for rec in self:
vals["revision"] = rec.revision + 1 has_revision = False
if "revision" not in vals:
vals["revision"] = rec.revision + 1
has_revision = True
res = super(Agreement, rec).write(vals) res = super(Agreement, rec).write(vals)
if has_revision:
vals.pop("revision")
return res
def copy(self, default=None):
"""Assign a value for code is New"""
default = dict(default or {})
if not default.get("code", False):
default.setdefault("code", _("New"))
res = super().copy(default)
res.sections_ids.mapped("clauses_ids").write({"agreement_id": res.id})
return res
def _exclude_readonly_field(self):
return ["stage_id"]
@api.model
def fields_view_get(
self, view_id=None, view_type=False, toolbar=False, submenu=False
):
res = super().fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
)
# Readonly fields
doc = etree.XML(res["arch"])
if view_type == "form":
for node in doc.xpath("//field"):
if node.attrib.get("name") in self._exclude_readonly_field():
continue
attrs = ast.literal_eval(node.attrib.get("attrs", "{}"))
if attrs:
if attrs.get("readonly"):
attrs["readonly"] = ["|", ("readonly", "=", True)] + attrs[
"readonly"
]
else:
attrs["readonly"] = [("readonly", "=", True)]
else:
attrs["readonly"] = [("readonly", "=", True)]
node.set("attrs", simplejson.dumps(attrs))
modifiers = ast.literal_eval(
node.attrib.get("modifiers", "{}")
.replace("true", "True")
.replace("false", "False")
)
readonly = modifiers.get("readonly")
invisible = modifiers.get("invisible")
required = modifiers.get("required")
if isinstance(readonly, bool) and readonly:
attrs["readonly"] = readonly
if isinstance(invisible, bool) and invisible:
attrs["invisible"] = invisible
if isinstance(required, bool) and required:
attrs["required"] = required
node.set("modifiers", simplejson.dumps(attrs))
res["arch"] = etree.tostring(doc)
return res return res

View File

@@ -13,7 +13,7 @@ class AgreementAppendix(models.Model):
title = fields.Char( title = fields.Char(
string="Title", string="Title",
required=True, required=True,
help="The title is displayed on the PDF." "The name is not.", help="The title is displayed on the PDF. The name is not.",
) )
sequence = fields.Integer(string="Sequence", default=10) sequence = fields.Integer(string="Sequence", default=10)
content = fields.Html(string="Content") content = fields.Html(string="Content")
@@ -22,9 +22,7 @@ class AgreementAppendix(models.Model):
string="Dynamic Content", string="Dynamic Content",
help="compute dynamic Content", help="compute dynamic Content",
) )
agreement_id = fields.Many2one( agreement_id = fields.Many2one("agreement", string="Agreement", ondelete="cascade")
comodel_name="agreement", string="Agreement", ondelete="cascade"
)
active = fields.Boolean( active = fields.Boolean(
string="Active", string="Active",
default=True, default=True,
@@ -33,8 +31,25 @@ class AgreementAppendix(models.Model):
) )
# Dynamic field editor # Dynamic field editor
field_domain = fields.Char( field_id = fields.Many2one(
string="Field Expression", default='[["active", "=", True]]' "ir.model.fields",
string="Field",
help="""Select target field from the related document model. If it is a
relationship field you will be able to select a target field at the
destination of the relationship.""",
)
sub_object_id = fields.Many2one(
"ir.model",
string="Sub-model",
help="""When a relationship field is selected as first field, this
field shows the document model the relationship goes to.""",
)
sub_model_object_field_id = fields.Many2one(
"ir.model.fields",
string="Sub-field",
help="""When a relationship field is selected as first field, this
field lets you select the target field within the destination document
model (sub-model).""",
) )
default_value = fields.Char( default_value = fields.Char(
string="Default Value", string="Default Value",
@@ -46,18 +61,27 @@ class AgreementAppendix(models.Model):
template field.""", template field.""",
) )
@api.onchange("field_domain", "default_value") @api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self): def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False self.copyvalue = False
if self.field_domain: if self.field_id and not self.field_id.relation:
string_list = self.field_domain.split(",") self.copyvalue = "${{object.{} or {}}}".format(
if string_list: self.field_id.name, self.default_value or "''",
field_domain = string_list[0][3:-1] )
self.copyvalue = "${{object.{} or {}}}".format( self.sub_model_object_field_id = False
field_domain, self.default_value or "''" if self.field_id and self.field_id.relation:
) self.sub_object_id = self.env["ir.model"].search(
[("model", "=", self.field_id.relation)]
)[0]
if self.sub_model_object_field_id:
self.copyvalue = "${{object.{}.{} or {}}}".format(
self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or "''",
)
# compute the dynamic content for mako expression # compute the dynamic content for jinja expression
def _compute_dynamic_content(self): def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"] MailTemplates = self.env["mail.template"]
for appendix in self: for appendix in self:
@@ -67,6 +91,6 @@ class AgreementAppendix(models.Model):
or "en_US" or "en_US"
) )
content = MailTemplates.with_context(lang=lang)._render_template( content = MailTemplates.with_context(lang=lang)._render_template(
appendix.content, "agreement.appendix", appendix.id appendix.content, "agreement.appendix", [appendix.id]
) )[appendix.id]
appendix.dynamic_content = content appendix.dynamic_content = content

View File

@@ -11,14 +11,15 @@ class AgreementClause(models.Model):
name = fields.Char(string="Name", required=True) name = fields.Char(string="Name", required=True)
title = fields.Char( title = fields.Char(
string="Title", help="The title is displayed on the PDF." "The name is not." string="Title", help="The title is displayed on the PDF. The name is not."
) )
sequence = fields.Integer(string="Sequence") sequence = fields.Integer(string="Sequence")
agreement_id = fields.Many2one( agreement_id = fields.Many2one("agreement", string="Agreement", ondelete="cascade")
comodel_name="agreement", string="Agreement", ondelete="cascade" temp_agreement_id = fields.Many2one(
"agreement", string="Temp Agreement", help="This field help to filter section."
) )
section_id = fields.Many2one( section_id = fields.Many2one(
comodel_name="agreement.section", string="Section", ondelete="cascade" "agreement.section", string="Section", ondelete="cascade"
) )
content = fields.Html(string="Clause Content") content = fields.Html(string="Clause Content")
dynamic_content = fields.Html( dynamic_content = fields.Html(
@@ -34,8 +35,25 @@ class AgreementClause(models.Model):
) )
# Dynamic field editor # Dynamic field editor
field_domain = fields.Char( field_id = fields.Many2one(
string="Field Expression", default='[["active", "=", True]]' "ir.model.fields",
string="Field",
help="""Select target field from the related document model. If it is a
relationship field you will be able to select a target field at the
destination of the relationship.""",
)
sub_object_id = fields.Many2one(
"ir.model",
string="Sub-model",
help="""When a relationship field is selected as first field, this
field shows the document model the relationship goes to.""",
)
sub_model_object_field_id = fields.Many2one(
"ir.model.fields",
string="Sub-field",
help="""When a relationship field is selected as first field, this
field lets you select the target field within the destination document
model (sub-model).""",
) )
default_value = fields.Char( default_value = fields.Char(
string="Default Value", string="Default Value",
@@ -47,18 +65,27 @@ class AgreementClause(models.Model):
template field.""", template field.""",
) )
@api.onchange("field_domain", "default_value") @api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self): def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False self.copyvalue = False
if self.field_domain: if self.field_id and not self.field_id.relation:
string_list = self.field_domain.split(",") self.copyvalue = "${{object.{} or {}}}".format(
if string_list: self.field_id.name, self.default_value or "''",
field_domain = string_list[0][3:-1] )
self.copyvalue = "${{object.{} or {}}}".format( self.sub_model_object_field_id = False
field_domain, self.default_value or "''" if self.field_id and self.field_id.relation:
) self.sub_object_id = self.env["ir.model"].search(
[("model", "=", self.field_id.relation)]
)[0]
if self.sub_model_object_field_id:
self.copyvalue = "${{object.{}.{} or {}}}".format(
self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or "''",
)
# compute the dynamic content for mako expression # compute the dynamic content for jinja expression
def _compute_dynamic_content(self): def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"] MailTemplates = self.env["mail.template"]
for clause in self: for clause in self:
@@ -66,6 +93,6 @@ class AgreementClause(models.Model):
clause.agreement_id and clause.agreement_id.partner_id.lang or "en_US" clause.agreement_id and clause.agreement_id.partner_id.lang or "en_US"
) )
content = MailTemplates.with_context(lang=lang)._render_template( content = MailTemplates.with_context(lang=lang)._render_template(
clause.content, "agreement.clause", clause.id clause.content, "agreement.clause", [clause.id]
) )[clause.id]
clause.dynamic_content = content clause.dynamic_content = content

View File

@@ -1,24 +0,0 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
# Main Agreement Increase Type Records Model
class AgreementIncreaseType(models.Model):
_name = "agreement.increasetype"
_description = "Agreement Increase Type"
# General
name = fields.Char(
string="Title",
required=True,
help="Increase types describe any increases that may happen during "
"the contract.",
)
description = fields.Text(
string="Description", required=True, help="Description of the renewal type."
)
increase_percent = fields.Integer(
string="Increase Percentage", help="Percentage that the amount will increase."
)

View File

@@ -8,15 +8,11 @@ class AgreementLine(models.Model):
_name = "agreement.line" _name = "agreement.line"
_description = "Agreement Lines" _description = "Agreement Lines"
product_id = fields.Many2one(comodel_name="product.product", string="Product") product_id = fields.Many2one("product.product", string="Product")
name = fields.Char(string="Description", required=True) name = fields.Char(string="Description", required=True)
agreement_id = fields.Many2one( agreement_id = fields.Many2one("agreement", string="Agreement", ondelete="cascade")
comodel_name="agreement", string="Agreement", ondelete="cascade"
)
qty = fields.Float(string="Quantity") qty = fields.Float(string="Quantity")
uom_id = fields.Many2one( uom_id = fields.Many2one("uom.uom", string="Unit of Measure", required=True)
comodel_name="uom.uom", string="Unit of Measure", required=True
)
@api.onchange("product_id") @api.onchange("product_id")
def _onchange_product_id(self): def _onchange_product_id(self):

View File

@@ -11,7 +11,7 @@ class AgreementRecital(models.Model):
name = fields.Char(string="Name", required=True) name = fields.Char(string="Name", required=True)
title = fields.Char( title = fields.Char(
string="Title", help="The title is displayed on the PDF." "The name is not." string="Title", help="The title is displayed on the PDF. The name is not.",
) )
sequence = fields.Integer(string="Sequence", default=10) sequence = fields.Integer(string="Sequence", default=10)
content = fields.Html(string="Content") content = fields.Html(string="Content")
@@ -20,9 +20,7 @@ class AgreementRecital(models.Model):
string="Dynamic Content", string="Dynamic Content",
help="compute dynamic Content", help="compute dynamic Content",
) )
agreement_id = fields.Many2one( agreement_id = fields.Many2one("agreement", string="Agreement", ondelete="cascade")
comodel_name="agreement", string="Agreement", ondelete="cascade"
)
active = fields.Boolean( active = fields.Boolean(
string="Active", string="Active",
default=True, default=True,
@@ -31,8 +29,25 @@ class AgreementRecital(models.Model):
) )
# Dynamic field editor # Dynamic field editor
field_domain = fields.Char( field_id = fields.Many2one(
string="Field Expression", default='[["active", "=", True]]' "ir.model.fields",
string="Field",
help="""Select target field from the related document model. If it is a
relationship field you will be able to select a target field at the
destination of the relationship.""",
)
sub_object_id = fields.Many2one(
"ir.model",
string="Sub-model",
help="""When a relationship field is selected as first field, this
field shows the document model the relationship goes to.""",
)
sub_model_object_field_id = fields.Many2one(
"ir.model.fields",
string="Sub-field",
help="""When a relationship field is selected as first field, this
field lets you select the target field within the destination document
model (sub-model).""",
) )
default_value = fields.Char( default_value = fields.Char(
string="Default Value", string="Default Value",
@@ -44,18 +59,27 @@ class AgreementRecital(models.Model):
template field.""", template field.""",
) )
@api.onchange("field_domain", "default_value") @api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self): def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False self.copyvalue = False
if self.field_domain: if self.field_id and not self.field_id.relation:
string_list = self.field_domain.split(",") self.copyvalue = "${{object.{} or {}}}".format(
if string_list: self.field_id.name, self.default_value or "''"
field_domain = string_list[0][3:-1] )
self.copyvalue = "${{object.{} or {}}}".format( self.sub_model_object_field_id = False
field_domain, self.default_value or "''" if self.field_id and self.field_id.relation:
) self.sub_object_id = self.env["ir.model"].search(
[("model", "=", self.field_id.relation)]
)[0]
if self.sub_model_object_field_id:
self.copyvalue = "${{object.{}.{} or {}}}".format(
self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or "''",
)
# compute the dynamic content for mako expression # compute the dynamic content for jinja expression
def _compute_dynamic_content(self): def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"] MailTemplates = self.env["mail.template"]
for recital in self: for recital in self:
@@ -63,6 +87,6 @@ class AgreementRecital(models.Model):
recital.agreement_id and recital.agreement_id.partner_id.lang or "en_US" recital.agreement_id and recital.agreement_id.partner_id.lang or "en_US"
) )
content = MailTemplates.with_context(lang=lang)._render_template( content = MailTemplates.with_context(lang=lang)._render_template(
recital.content, "agreement.recital", recital.id recital.content, "agreement.recital", [recital.id]
) )[recital.id]
recital.dynamic_content = content recital.dynamic_content = content

View File

@@ -1,21 +0,0 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
# Main Agreement Section Records Model
class AgreementRenewalType(models.Model):
_name = "agreement.renewaltype"
_description = "Agreement Renewal Type"
# General
name = fields.Char(
string="Title",
required=True,
help="Renewal types describe what happens after the "
"agreement/contract expires.",
)
description = fields.Text(
string="Description", required=True, help="Description of the renewal type."
)

View File

@@ -14,14 +14,9 @@ class AgreementSection(models.Model):
string="Title", help="The title is displayed on the PDF. The name is not." string="Title", help="The title is displayed on the PDF. The name is not."
) )
sequence = fields.Integer(string="Sequence") sequence = fields.Integer(string="Sequence")
agreement_id = fields.Many2one( agreement_id = fields.Many2one("agreement", string="Agreement", ondelete="cascade")
comodel_name="agreement", string="Agreement", ondelete="cascade"
)
clauses_ids = fields.One2many( clauses_ids = fields.One2many(
comodel_name="agreement.clause", "agreement.clause", "section_id", string="Clauses", copy=True
inverse_name="section_id",
string="Clauses",
copy=True,
) )
content = fields.Html(string="Section Content") content = fields.Html(string="Section Content")
dynamic_content = fields.Html( dynamic_content = fields.Html(
@@ -37,8 +32,25 @@ class AgreementSection(models.Model):
) )
# Dynamic field editor # Dynamic field editor
field_domain = fields.Char( field_id = fields.Many2one(
string="Field Expression", default='[["active", "=", True]]' "ir.model.fields",
string="Field",
help="""Select target field from the related document model. If it is a
relationship field you will be able to select a target field at the
destination of the relationship.""",
)
sub_object_id = fields.Many2one(
"ir.model",
string="Sub-model",
help="""When a relationship field is selected as first field, this
field shows the document model the relationship goes to.""",
)
sub_model_object_field_id = fields.Many2one(
"ir.model.fields",
string="Sub-field",
help="""When a relationship field is selected as first field, this
field lets you select the target field within the destination document
model (sub-model).""",
) )
default_value = fields.Char( default_value = fields.Char(
string="Default Value", string="Default Value",
@@ -50,18 +62,27 @@ class AgreementSection(models.Model):
template field.""", template field.""",
) )
@api.onchange("field_domain", "default_value") @api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self): def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False self.copyvalue = False
if self.field_domain: if self.field_id and not self.field_id.relation:
string_list = self.field_domain.split(",") self.copyvalue = "${{object.{} or {}}}".format(
if string_list: self.field_id.name, self.default_value or "''"
field_domain = string_list[0][3:-1] )
self.copyvalue = "${{object.{} or {}}}".format( self.sub_model_object_field_id = False
field_domain, self.default_value or "''" if self.field_id and self.field_id.relation:
) self.sub_object_id = self.env["ir.model"].search(
[("model", "=", self.field_id.relation)]
)[0]
if self.sub_model_object_field_id:
self.copyvalue = "${{object.{}.{} or {}}}".format(
self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or "''",
)
# compute the dynamic content for mako expression # compute the dynamic content for jinja expression
def _compute_dynamic_content(self): def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"] MailTemplates = self.env["mail.template"]
for section in self: for section in self:
@@ -69,6 +90,6 @@ class AgreementSection(models.Model):
section.agreement_id and section.agreement_id.partner_id.lang or "en_US" section.agreement_id and section.agreement_id.partner_id.lang or "en_US"
) )
content = MailTemplates.with_context(lang=lang)._render_template( content = MailTemplates.with_context(lang=lang)._render_template(
section.content, "agreement.section", section.id section.content, "agreement.section", [section.id]
) )[section.id]
section.dynamic_content = content section.dynamic_content = content

View File

@@ -4,7 +4,7 @@
from odoo import fields, models from odoo import fields, models
# Main Agreement Section Records Model # Main Stage on the Agreement
class AgreementStage(models.Model): class AgreementStage(models.Model):
_name = "agreement.stage" _name = "agreement.stage"
_description = "Agreement Stages" _description = "Agreement Stages"
@@ -12,7 +12,6 @@ class AgreementStage(models.Model):
# General # General
name = fields.Char(string="Stage Name", required=True) name = fields.Char(string="Stage Name", required=True)
description = fields.Text(string="Description", required=False)
sequence = fields.Integer(string="Sequence", default="1", required=False) sequence = fields.Integer(string="Sequence", default="1", required=False)
fold = fields.Boolean( fold = fields.Boolean(
string="Is Folded", string="Is Folded",
@@ -22,3 +21,9 @@ class AgreementStage(models.Model):
stage_type = fields.Selection( stage_type = fields.Selection(
[("agreement", "Agreement")], string="Type", required=True [("agreement", "Agreement")], string="Type", required=True
) )
active = fields.Boolean(string="Active", default=True)
readonly = fields.Boolean(
string="Readonly",
default=False,
help="The agreement can not edit if set Readonly = True.",
)

View File

@@ -1,12 +0,0 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
# Main Agreement Status Records Model
class AgreementStatus(models.Model):
_name = "agreement.type"
# General
name = fields.Char(string="Title", required=True)

View File

@@ -8,7 +8,6 @@ class AgreementSubtype(models.Model):
_name = "agreement.subtype" _name = "agreement.subtype"
_description = "Agreement Subtypes" _description = "Agreement Subtypes"
name = fields.Char(string="Name", required=True) name = fields.Char(string="Sub-Type Name", required=True)
agreement_type_id = fields.Many2one( agreement_type_id = fields.Many2one("agreement.type", string="Agreement Type")
comodel_name="agreement.type", string="Agreement Type" active = fields.Boolean(string="Active", default=True)
)

View File

@@ -9,7 +9,5 @@ class AgreementType(models.Model):
_description = "Agreement Types" _description = "Agreement Types"
agreement_subtypes_ids = fields.One2many( agreement_subtypes_ids = fields.One2many(
comodel_name="agreement.subtype", "agreement.subtype", "agreement_type_id", string="Sub-Types"
inverse_name="agreement_type_id",
string="Subtypes",
) )

View File

@@ -1,10 +0,0 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class Product(models.Model):
_inherit = "product.template"
agreements_ids = fields.Many2many(comodel_name="agreement", string="Agreements")

View File

@@ -7,6 +7,4 @@ from odoo import fields, models
class Partner(models.Model): class Partner(models.Model):
_inherit = "res.partner" _inherit = "res.partner"
agreement_ids = fields.One2many( agreement_ids = fields.One2many("agreement", "partner_id", string="Agreements")
comodel_name="agreement", inverse_name="partner_id", string="Agreements"
)

View File

@@ -4,6 +4,7 @@
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com> * Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
* Sandip Mangukiya <smangukiya@opensourceintegrators.com> * Sandip Mangukiya <smangukiya@opensourceintegrators.com>
* Yves Goldberg <yves@ygol.com> * Yves Goldberg <yves@ygol.com>
* Tharathip Chaweewongphan <tharathipc@ecosoft.co.th>
* `Tecnativa <https://www.tecnativa.com>`_: * `Tecnativa <https://www.tecnativa.com>`_:

View File

@@ -1,21 +1,23 @@
<?xml version="1.0" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<report <record id="partner_agreement_contract_document" model="ir.actions.report">
id="partner_agreement_contract_document" <field name="name">Agreement</field>
model="agreement" <field name="model">agreement</field>
string="Contract Document" <field name="binding_model_id" ref="model_agreement" />
name="agreement_legal.report_agreement_document" <field name="report_type">qweb-pdf</field>
file="agreement_legal.report_agreement_document" <field name="report_name">agreement_legal.report_agreement_document</field>
report_type="qweb-pdf" <field name="report_file">agreement_legal.report_agreement_document</field>
/> <field name="binding_view_types">list,form</field>
<report </record>
id="partner_agreement_contract_document_preview" <record id="partner_agreement_contract_document_preview" model="ir.actions.report">
model="agreement" <field name="name">Agreement Preview</field>
string="Contract Document Preview" <field name="model">agreement</field>
name="agreement_legal.report_agreement_document" <field name="binding_model_id" ref="model_agreement" />
file="agreement_legal.report_agreement_document" <field name="report_type">qweb-html</field>
report_type="qweb-html" <field name="report_name">agreement_legal.report_agreement_document</field>
/> <field name="report_file">agreement_legal.report_agreement_document</field>
<field name="binding_view_types">list,form</field>
</record>
<template id="report_agreement_document"> <template id="report_agreement_document">
<t t-name="agreement.report_agreement_document"> <t t-name="agreement.report_agreement_document">
<t t-call="web.html_container"> <t t-call="web.html_container">
@@ -111,7 +113,7 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<t t-if="doc.special_terms"> <t t-if="special_term">
<h2>Special Terms</h2> <h2>Special Terms</h2>
<div name="special_term"> <div name="special_term">
<p t-field="doc.dynamic_special_terms" /> <p t-field="doc.dynamic_special_terms" />

View File

@@ -3,19 +3,19 @@ access_agreement_readonly,agreement readonly,model_agreement,group_agreement_rea
access_agreement_allusers,agreement all users,model_agreement,group_agreement_user,1,1,1,0 access_agreement_allusers,agreement all users,model_agreement,group_agreement_user,1,1,1,0
access_agreement_manager,agreement manager,model_agreement,group_agreement_manager,1,1,1,1 access_agreement_manager,agreement manager,model_agreement,group_agreement_manager,1,1,1,1
access_agreement_recital_readonly,recital readonly,model_agreement_recital,group_agreement_readonly,1,0,0,0 access_agreement_recital_readonly,recital readonly,model_agreement_recital,group_agreement_readonly,1,0,0,0
access_agreement_recital_allusers,recital all users,model_agreement_recital,group_agreement_user,1,1,1,0 access_agreement_recital_allusers,recital all users,model_agreement_recital,group_agreement_user,1,1,1,1
access_agreement_recital_manager,recital manager,model_agreement_recital,group_agreement_manager,1,1,1,1 access_agreement_recital_manager,recital manager,model_agreement_recital,group_agreement_manager,1,1,1,1
access_agreement_section_readonly,section readonly,model_agreement_section,group_agreement_readonly,1,0,0,0 access_agreement_section_readonly,section readonly,model_agreement_section,group_agreement_readonly,1,0,0,0
access_agreement_section_allusers,section all users,model_agreement_section,group_agreement_user,1,1,1,0 access_agreement_section_allusers,section all users,model_agreement_section,group_agreement_user,1,1,1,1
access_agreement_section_manager,section manager,model_agreement_section,group_agreement_manager,1,1,1,1 access_agreement_section_manager,section manager,model_agreement_section,group_agreement_manager,1,1,1,1
access_agreement_clause_readonly,clause readonly,model_agreement_clause,group_agreement_readonly,1,0,0,0 access_agreement_clause_readonly,clause readonly,model_agreement_clause,group_agreement_readonly,1,0,0,0
access_agreement_clause_allusers,clause all users,model_agreement_clause,group_agreement_user,1,1,1,0 access_agreement_clause_allusers,clause all users,model_agreement_clause,group_agreement_user,1,1,1,1
access_agreement_clause_manager,clause manager,model_agreement_clause,group_agreement_manager,1,1,1,1 access_agreement_clause_manager,clause manager,model_agreement_clause,group_agreement_manager,1,1,1,1
access_agreement_appendix_readonly,appendix readonly,model_agreement_appendix,group_agreement_readonly,1,0,0,0 access_agreement_appendix_readonly,appendix readonly,model_agreement_appendix,group_agreement_readonly,1,0,0,0
access_agreement_appendix_allusers,appendix all users,model_agreement_appendix,group_agreement_user,1,1,1,0 access_agreement_appendix_allusers,appendix all users,model_agreement_appendix,group_agreement_user,1,1,1,1
access_agreement_appendix_manager,appendix manager,model_agreement_appendix,group_agreement_manager,1,1,1,1 access_agreement_appendix_manager,appendix manager,model_agreement_appendix,group_agreement_manager,1,1,1,1
access_agreement_line_readonly,agreement line readonly,model_agreement_line,group_agreement_readonly,1,0,0,0 access_agreement_line_readonly,agreement line readonly,model_agreement_line,group_agreement_readonly,1,0,0,0
access_agreement_line_allusers,agreement line all users,model_agreement_line,group_agreement_user,1,1,1,0 access_agreement_line_allusers,agreement line all users,model_agreement_line,group_agreement_user,1,1,1,1
access_agreement_line_manager,agreement line manager,model_agreement_line,group_agreement_manager,1,1,1,1 access_agreement_line_manager,agreement line manager,model_agreement_line,group_agreement_manager,1,1,1,1
access_agreement_stage_readonly,stage readonly,model_agreement_stage,group_agreement_readonly,1,0,0,0 access_agreement_stage_readonly,stage readonly,model_agreement_stage,group_agreement_readonly,1,0,0,0
access_agreement_stage_manager,stage manager,model_agreement_stage,group_agreement_manager,1,1,1,1 access_agreement_stage_manager,stage manager,model_agreement_stage,group_agreement_manager,1,1,1,1
@@ -23,7 +23,3 @@ access_agreement_type_readonly,type readonly,model_agreement_type,group_agreemen
access_agreement_type_manager,type manager,model_agreement_type,group_agreement_manager,1,1,1,1 access_agreement_type_manager,type manager,model_agreement_type,group_agreement_manager,1,1,1,1
access_agreement_subtype_readonly,subtype readonly,model_agreement_subtype,group_agreement_readonly,1,0,0,0 access_agreement_subtype_readonly,subtype readonly,model_agreement_subtype,group_agreement_readonly,1,0,0,0
access_agreement_subtype_manager,subtype manager,model_agreement_subtype,group_agreement_manager,1,1,1,1 access_agreement_subtype_manager,subtype manager,model_agreement_subtype,group_agreement_manager,1,1,1,1
access_agreement_renewaltype_readonly,renewaltype readonly,model_agreement_renewaltype,group_agreement_readonly,1,0,0,0
access_agreement_renewaltype_manager,renewaltype manager,model_agreement_renewaltype,group_agreement_manager,1,1,1,1
access_agreement_increasetype_readonly,increasetype readonly,model_agreement_increasetype,group_agreement_readonly,1,0,0,0
access_agreement_increasetype_manager,increasetype manager,model_agreement_increasetype,group_agreement_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_agreement_allusers agreement all users model_agreement group_agreement_user 1 1 1 0
4 access_agreement_manager agreement manager model_agreement group_agreement_manager 1 1 1 1
5 access_agreement_recital_readonly recital readonly model_agreement_recital group_agreement_readonly 1 0 0 0
6 access_agreement_recital_allusers recital all users model_agreement_recital group_agreement_user 1 1 1 0 1
7 access_agreement_recital_manager recital manager model_agreement_recital group_agreement_manager 1 1 1 1
8 access_agreement_section_readonly section readonly model_agreement_section group_agreement_readonly 1 0 0 0
9 access_agreement_section_allusers section all users model_agreement_section group_agreement_user 1 1 1 0 1
10 access_agreement_section_manager section manager model_agreement_section group_agreement_manager 1 1 1 1
11 access_agreement_clause_readonly clause readonly model_agreement_clause group_agreement_readonly 1 0 0 0
12 access_agreement_clause_allusers clause all users model_agreement_clause group_agreement_user 1 1 1 0 1
13 access_agreement_clause_manager clause manager model_agreement_clause group_agreement_manager 1 1 1 1
14 access_agreement_appendix_readonly appendix readonly model_agreement_appendix group_agreement_readonly 1 0 0 0
15 access_agreement_appendix_allusers appendix all users model_agreement_appendix group_agreement_user 1 1 1 0 1
16 access_agreement_appendix_manager appendix manager model_agreement_appendix group_agreement_manager 1 1 1 1
17 access_agreement_line_readonly agreement line readonly model_agreement_line group_agreement_readonly 1 0 0 0
18 access_agreement_line_allusers agreement line all users model_agreement_line group_agreement_user 1 1 1 0 1
19 access_agreement_line_manager agreement line manager model_agreement_line group_agreement_manager 1 1 1 1
20 access_agreement_stage_readonly stage readonly model_agreement_stage group_agreement_readonly 1 0 0 0
21 access_agreement_stage_manager stage manager model_agreement_stage group_agreement_manager 1 1 1 1
23 access_agreement_type_manager type manager model_agreement_type group_agreement_manager 1 1 1 1
24 access_agreement_subtype_readonly subtype readonly model_agreement_subtype group_agreement_readonly 1 0 0 0
25 access_agreement_subtype_manager subtype manager model_agreement_subtype group_agreement_manager 1 1 1 1
access_agreement_renewaltype_readonly renewaltype readonly model_agreement_renewaltype group_agreement_readonly 1 0 0 0
access_agreement_renewaltype_manager renewaltype manager model_agreement_renewaltype group_agreement_manager 1 1 1 1
access_agreement_increasetype_readonly increasetype readonly model_agreement_increasetype group_agreement_readonly 1 0 0 0
access_agreement_increasetype_manager increasetype manager model_agreement_increasetype group_agreement_manager 1 1 1 1

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="module_agreement_legal_category" model="ir.module.category"> <record id="module_agreement_legal_category" model="ir.module.category">
<field name="name">Agreement</field> <field name="name">Agreement</field>

View File

@@ -0,0 +1,40 @@
odoo.define("agreement_legal.agreement", function(require) {
"use strict";
var KanbanController = require("web.KanbanController");
var ListController = require("web.ListController");
var FormController = require("web.FormController");
var includeDict = {
renderButtons: function() {
this._super.apply(this, arguments);
if (this.modelName === "agreement" && this.$buttons) {
var self = this;
var data = this.model.get(this.handle);
if (data.context.default_is_template === true) {
// Hide create from template
this.$buttons.find(".create_agreement_from_template").hide();
} else {
// Hide create button
this.$buttons.find(".o-kanban-button-new").hide();
this.$buttons.find(".o_list_button_add").hide();
this.$buttons.find(".o_form_button_create").hide();
}
this.$buttons
.find(".create_agreement_from_template")
.on("click", function() {
self.do_action(
"agreement_legal.create_agreement_from_template_action",
{
additional_context: {},
}
);
});
}
},
};
KanbanController.include(includeDict);
ListController.include(includeDict);
FormController.include(includeDict);
});

View File

@@ -1,86 +0,0 @@
odoo.define("agreement_legal.domain_widget_ext", function(require) {
"use strict";
const basic_fields = require("web.basic_fields");
const DomainSelector = require("web.DomainSelector");
const session = require("web.session");
const core = require("web.core");
const qweb = core.qweb;
basic_fields.FieldDomain.include({
/**
* Init
*/
init: function() {
this._super.apply(this, arguments);
// Add Additional options
this.partialUse = this.nodeOptions.partial_use || false;
},
// ----------------------------------------------------------------------
// Private
// ----------------------------------------------------------------------
/**
* @private
* @override _render from AbstractField
* @returns {Deferred}
*/
/* eslint-disable no-unused-vars */
_render: function() {
// If there is no model, only change the non-domain-selector content
if (!this._domainModel) {
this._replaceContent();
return $.when();
}
// Convert char value to array value
const value = this.value || "[]";
// Create the domain selector or change the value of the current
// one...
var def = null;
if (this.domainSelector) {
def = this.domainSelector.setDomain(value);
} else {
this.domainSelector = new DomainSelector(
this,
this._domainModel,
value,
{
readonly: this.mode === "readonly" || this.inDialog,
filters: this.fsFilters,
debugMode: session.debug,
partialUse: this.partialUse || false,
}
);
def = this.domainSelector.prependTo(this.$el);
}
// ... then replace the other content (matched records, etc)
return def.then(this._replaceContent.bind(this));
},
/**
* Render the field DOM except for the domain selector part. The full
* field DOM is composed of a DIV which contains the domain selector
* widget, followed by other content. This other content is handled by
* this method.
*
* @private
*/
_replaceContent: function() {
if (this._$content) {
this._$content.remove();
}
this._$content = $(
qweb.render("FieldDomain.content", {
hasModel: Boolean(this._domainModel),
isValid: Boolean(this._isValidForModel),
nbRecords: this.record.specialData[this.name].nbRecords || 0,
inDialogEdit: this.inDialog && this.mode === "edit",
partialUse: this.partialUse || false,
})
);
this._$content.appendTo(this.$el);
},
});
});

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-extend="ListView.buttons">
<t t-jquery="button.o_list_button_add" t-operation="after">
<button
type="button"
t-if="widget and widget.modelName and widget.modelName == 'agreement'"
class="create_agreement_from_template btn btn-primary"
>Create From Template
</button>
</t>
</t>
<t t-extend="KanbanView.buttons">
<t t-jquery="button" t-operation="after">
<button
type="button"
t-if="widget and widget.modelName and widget.modelName == 'agreement'"
class="create_agreement_from_template btn btn-primary"
>Create From Template
</button>
</t>
</t>
</templates>

View File

@@ -1,310 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates id="template" xml:space="preserve">
<t t-name="FieldDomain.content">
<t t-if="partialUse">
<div t-if="hasModel" class="o_field_domain_panel">
<!--<div t-if="hasModel" class="o_field_domain_panel">
<i class="fa fa-arrow-right" role="img" aria-label="Domain" title="Domain"/>
<button t-if="isValid" class="btn btn-sm btn-secondary o_domain_show_selection_button" type="button">
<t t-esc="nbRecords"/> record(s)
</button>
<span t-else="" class="text-warning" role="alert"><i class="fa fa-exclamation-triangle" role="img" aria-label="Warning" title="Warning"/> Invalid domain</span>
<button t-if="inDialogEdit" class="btn btn-sm btn-primary o_field_domain_dialog_button">Edit Domain</button>
</div>
<div t-else="">Select a model to add a filter.</div>-->
</div>
</t>
<t t-if="!partialUse">
<div t-if="hasModel" class="o_field_domain_panel">
<i
class="fa fa-arrow-right"
role="img"
aria-label="Domain"
title="Domain"
/>
<button
t-if="isValid"
class="btn btn-sm btn-secondary o_domain_show_selection_button"
type="button"
>
<t t-esc="nbRecords" /> record(s)
</button>
<span t-else="" class="text-warning" role="alert"><i
class="fa fa-exclamation-triangle"
role="img"
aria-label="Warning"
title="Warning"
/> Invalid domain</span>
<button
t-if="inDialogEdit"
class="btn btn-sm btn-primary o_field_domain_dialog_button"
>Edit Domain</button>
</div>
<div t-else="">Select a model to add a filter.</div>
</t>
</t>
<div
aria-atomic="true"
t-name="DomainSelector"
t-attf-class="o_domain_node o_domain_tree o_domain_selector #{widget.readonly ? 'o_read_mode' : 'o_edit_mode'}"
>
<t t-if="widget.options.partialUse">
<t t-if="widget.children.length === 0">
<span>SMatch <strong>all records</strong></span>
<button
t-if="!widget.readonly"
class="btn btn-sm btn-primary o_domain_add_first_node_button"
><i class="fa fa-plus" /> Add filter</button>
</t>
<t t-else="">
<div class="o_domain_tree_header">
<t
t-if="widget.children.length === 1"
>Please navigate below and select field:</t>
<t t-else="">
<span>SSMatch records with</span>
<t t-call="DomainTree.OperatorSelector" />
<span>of the following rules:</span>
</t>
</div>
<div class="o_domain_node_children_container" />
</t>
</t>
<t t-if="!widget.options.partialUse">
<t t-if="widget.children.length === 0">
<span>Match <strong>all records</strong></span>
<button
t-if="!widget.readonly"
class="btn btn-sm btn-primary o_domain_add_first_node_button"
><i class="fa fa-plus" /> Add filter</button>
</t>
<t t-else="">
<div class="o_domain_tree_header">
<t
t-if="widget.children.length === 1"
>Match records with the following rule:</t>
<t t-else="">
<span>Match records with</span>
<t t-call="DomainTree.OperatorSelector" />
<span>of the following rules:</span>
</t>
</div>
<div class="o_domain_node_children_container" />
</t>
<label
t-if="widget.debug &amp;&amp; !widget.readonly"
class="o_domain_debug_container"
>
<span class="small"># Code editor</span>
<input type="text" class="o_domain_debug_input" />
</label>
</t>
</div>
<t t-name="DomainNode.ControlPanel">
<t t-if="widget.options.partialUse">
<div
t-if="!widget.readonly &amp;&amp; !widget.noControlPanel"
class="o_domain_node_control_panel"
role="toolbar"
aria-label="Domain node"
>
</div>
</t>
<t t-if="!widget.options.partialUse">
<div
t-if="!widget.readonly &amp;&amp; !widget.noControlPanel"
class="o_domain_node_control_panel"
role="toolbar"
aria-label="Domain node"
>
<button
class="btn o_domain_delete_node_button"
title="Delete node"
aria-label="Delete node"
>
<i class="fa fa-times" />
</button>
<button
class="btn o_domain_add_node_button"
title="Add node"
aria-label="Add node"
>
<i class="fa fa-plus-circle" />
</button>
<button
class="btn o_domain_add_node_button"
title="Add branch"
aria-label="Add branch"
data-branch="1"
>
<i class="fa fa-ellipsis-h" />
</button>
</div>
</t>
</t>
<div
t-name="DomainLeaf"
t-attf-class="o_domain_node o_domain_leaf o_domain_selector_row #{widget.readonly ? 'o_read_mode' : 'o_edit_mode'}"
>
<t t-call="DomainNode.ControlPanel" />
<div t-if="!widget.readonly" class="o_domain_leaf_edition">
<!-- field selector will be instantiated here -->
<t t-if="!widget.options.partialUse">
<div>
<!-- used for flex stretching -->
<select class="o_domain_leaf_operator_select o_input">
<option
t-foreach="widget.operators"
t-as="key"
t-att-value="key"
t-att-selected="widget.displayOperator === key ? 'selected' : None"
>
<t t-esc="key_value" />
</option>
</select>
</div>
<div
t-attf-class="o_ds_value_cell#{_.contains(['set', 'not set'], widget.displayOperator) ? ' d-none' : ''}"
>
<t t-if="widget.selectionChoices !== null">
<select class="o_domain_leaf_value_input o_input">
<option
t-foreach="widget.selectionChoices"
t-as="val"
t-att-value="val[0]"
t-att-selected="_.contains(val, widget.displayValue) ? 'selected' : None"
>
<t t-esc="val[1]" />
</option>
</select>
</t>
<t t-else="">
<t t-if="_.contains(['in', 'not in'], widget.operator)">
<div class="o_domain_leaf_value_input">
<span
class="badge badge-pill"
t-foreach="widget.displayValue"
t-as="val"
>
<t t-esc="val" />
<i
class="o_domain_leaf_value_remove_tag_button fa fa-times"
t-att-data-value="val"
role="img"
aria-label="Remove tag"
title="Remove tag"
/>
</span>
</div>
<div class="o_domain_leaf_value_tags">
<input
placeholder="Add new value"
type="text"
class="o_input"
/>
<button
class="btn btn-sm btn-primary fa fa-plus o_domain_leaf_value_add_tag_button"
aria-label="Add tag"
title="Add tag"
/>
</div>
</t>
<t t-else="">
<input
class="o_domain_leaf_value_input o_input"
type="text"
t-att-value="widget.displayValue"
/>
</t>
</t>
</div>
</t>
</div>
<div t-else="" class="o_domain_leaf_info">
<!-- field selector will be instantiated here -->
<t t-if="_.isString(widget.value)">
<span class="o_domain_leaf_operator">
<t t-esc="widget.operator_mapping[widget.operator]" />
</span>
<span class="o_domain_leaf_value text-primary">"<t
t-esc="widget.value"
/>"</span>
</t>
<t t-if="_.isArray(widget.value)">
<span class="o_domain_leaf_operator">
<t t-esc="widget.operator_mapping[widget.operator]" />
</span>
<t t-foreach="widget.value" t-as="v">
<span class="o_domain_leaf_value text-primary">"<t
t-esc="v"
/>"</span>
<t t-if="!v_last"> or </t>
</t>
</t>
<t t-if="_.isNumber(widget.value)">
<span class="o_domain_leaf_operator">
<t t-esc="widget.operator_mapping[widget.operator]" />
</span>
<span class="o_domain_leaf_value text-primary">
<t t-esc="widget.value" />
</span>
</t>
<t t-if="_.isBoolean(widget.value)">
is
<t
t-if="widget.operator === '=' &amp;&amp; widget.value === false || widget.operator === '!=' &amp;&amp; widget.value === true"
>not</t>
set
</t>
</div>
</div>
<div
aria-atomic="true"
t-name="ModelFieldSelector"
t-attf-class="o_field_selector#{!widget.options.readonly ? ' o_edit_mode o_input' : ''}"
>
<div class="o_field_selector_value" tabindex="0" />
<t t-if="!widget.options.partialUse">
<div class="o_field_selector_controls" tabindex="0">
<i
role="alert"
class="fa fa-exclamation-triangle o_field_selector_warning d-none"
title="Invalid field chain"
aria-label="Invalid field chain"
/>
</div>
</t>
<div
t-if="!widget.options.readonly"
class="o_field_selector_popover d-none"
tabindex="0"
>
<div class="o_field_selector_popover_header text-center">
<i
class="fa fa-arrow-left o_field_selector_popover_option o_field_selector_prev_page"
title="Previous"
role="img"
aria-label="Previous"
/>
<div class="o_field_selector_title" />
<i
class="fa fa-times o_field_selector_popover_option o_field_selector_close"
title="Close"
role="img"
aria-label="Close"
/>
</div>
<div class="o_field_selector_popover_body">
<ul class="o_field_selector_page" />
</div>
<div
t-if="widget.options.debugMode"
class="o_field_selector_popover_footer"
>
<input type="text" class="o_input" />
</div>
</div>
</div>
</templates>

View File

@@ -1 +1,9 @@
# License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html).
from . import test_agreement from . import test_agreement
from . import test_agreement_appendix
from . import test_agreement_clause
from . import test_agreement_line
from . import test_agreement_recital
from . import test_agreement_section
from . import test_create_agreement_wizard

View File

@@ -1,13 +1,128 @@
# Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from odoo.addons.agreement.tests import test_agreement
from datetime import timedelta
from lxml import etree
from odoo import fields
from odoo.tests.common import TransactionCase
class TestAgreement(test_agreement.TestAgreement): class TestAgreement(TransactionCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"})
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
self.test_agreement = self.env["agreement"].create(
{
"name": "TestAgreement",
"description": "Test",
"special_terms": "Test",
"partner_id": self.test_customer.id,
"start_date": fields.Date.today(),
"end_date": fields.Date.today() + timedelta(days=365),
"state": "active",
}
)
# TEST 01: Set 'Field' for dynamic placeholder, test onchange method
def test_onchange_copyvalue(self):
agreement_01 = self.test_agreement
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement"), ("name", "=", "active")]
)
agreement_01.field_id = field_01.id
agreement_01.onchange_copyvalue()
self.assertEqual(agreement_01.copyvalue, "${object.active or ''}")
# TEST 02: Set related 'Field' for dynamic placeholder to
# test onchange method
def test_onchange_copyvalue2(self):
agreement_01 = self.test_agreement
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement"), ("name", "=", "agreement_type_id")]
)
sub_field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.type"), ("name", "=", "active")]
)
agreement_01.field_id = field_01.id
agreement_01.onchange_copyvalue()
self.assertEqual(agreement_01.sub_object_id.model, "agreement.type")
agreement_01.sub_model_object_field_id = sub_field_01.id
agreement_01.onchange_copyvalue()
self.assertEqual(
agreement_01.copyvalue, "${object.agreement_type_id.active or ''}"
)
# TEST 03: Create New Version
def test_create_new_version(self):
agreement_01 = self.test_agreement
agreement_01.create_new_version()
old_agreement = self.env["agreement"].search(
[("code", "=", agreement_01.code + "-V1"), ("active", "=", False)]
)
self.assertEqual(len(old_agreement), 1)
new_agreement = self.env["agreement"].search(
[("name", "=", "TestAgreement"), ("version", "=", 2)]
)
self.assertEqual(len(new_agreement), 1)
# TEST 04: Create New Agreement
def test_create_new_agreement(self):
agreement_01 = self.test_agreement
agreement_01.create_new_agreement()
new_agreement = self.env["agreement"].search([("name", "=", "New")])
self.assertEqual(len(new_agreement), 1)
# TEST 05: Test Description Dynamic Field
def test_compute_dynamic_description(self):
agreement_01 = self.test_agreement
agreement_01.description = "${object.name}"
self.assertEqual(
agreement_01.dynamic_description, "TestAgreement",
)
# TEST 06: Test Parties Dynamic Field
def test_compute_dynamic_parties(self):
agreement_01 = self.test_agreement
agreement_01.parties = "${object.name}"
self.assertEqual(
agreement_01.dynamic_parties, "<p>TestAgreement</p>",
)
# TEST 07: Test Special Terms Dynamic Field
def test_compute_dynamic_special_terms(self):
agreement_01 = self.test_agreement
agreement_01.special_terms = "${object.name}"
self.assertEqual(
agreement_01.dynamic_special_terms, "TestAgreement",
)
# TEST 02: Check Read Stages
def test_read_group_stage_ids(self):
agreement_01 = self.test_agreement
self.assertEqual(
agreement_01._read_group_stage_ids(self.env["agreement.stage"], [], "id"),
self.env["agreement.stage"].search(
[("stage_type", "=", "agreement")], order="id",
),
)
# Test fields_view_get
def test_agreement_fields_view_get(self):
res = self.env["agreement"].fields_view_get(
view_id=self.ref("agreement_legal.partner_agreement_form_view"),
view_type="form",
)
doc = etree.XML(res["arch"])
field = doc.xpath("//field[@name='partner_contact_id']")
self.assertEqual(
field[0].get("modifiers", ""), '{"readonly": [["readonly", "=", true]]}'
)
def test_action_create_new_version(self): def test_action_create_new_version(self):
self.agreement.create_new_version() self.test_agreement.create_new_version()
self.assertEqual(self.agreement.state, "draft") self.assertEqual(self.test_agreement.state, "draft")
self.assertEqual(len(self.agreement.previous_version_agreements_ids), 1) self.assertEqual(len(self.test_agreement.previous_version_agreements_ids), 1)

View File

@@ -0,0 +1,68 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from datetime import timedelta
from odoo import fields
from odoo.tests.common import TransactionCase
class TestAgreementAppendices(TransactionCase):
def setUp(self):
super().setUp()
self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"})
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
self.test_agreement = self.env["agreement"].create(
{
"name": "TestAgreement",
"description": "Test",
"special_terms": "Test",
"partner_id": self.test_customer.id,
"start_date": fields.Date.today(),
"end_date": fields.Date.today() + timedelta(days=365),
}
)
self.test_appendices = self.env["agreement.appendix"].create(
{
"name": "TestAppendices",
"title": "Test",
"content": "Test",
"agreement_id": self.test_agreement.id,
}
)
# TEST 01: Set 'Field' for dynamic placeholder, test onchange method
def test_onchange_copyvalue(self):
appendix_01 = self.test_appendices
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.appendix"), ("name", "=", "active")]
)
appendix_01.field_id = field_01.id
appendix_01.onchange_copyvalue()
self.assertEqual(appendix_01.copyvalue, "${object.active or ''}")
# TEST 02: Set related 'Field' for dynamic placeholder to
# test onchange method
def test_onchange_copyvalue2(self):
appendix_01 = self.test_appendices
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.appendix"), ("name", "=", "agreement_id")]
)
sub_field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement"), ("name", "=", "active")]
)
appendix_01.field_id = field_01.id
appendix_01.onchange_copyvalue()
self.assertEqual(appendix_01.sub_object_id.model, "agreement")
appendix_01.sub_model_object_field_id = sub_field_01.id
appendix_01.onchange_copyvalue()
self.assertEqual(appendix_01.copyvalue, "${object.agreement_id.active or ''}")
# TEST 03: Test Dynamic Field
def test_compute_dynamic_content(self):
appendix_01 = self.test_appendices
appendix_01.content = "${object.name}"
self.assertEqual(
appendix_01.dynamic_content, "<p>TestAppendices</p>",
)

View File

@@ -0,0 +1,68 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from datetime import timedelta
from odoo import fields
from odoo.tests.common import TransactionCase
class TestAgreementClauses(TransactionCase):
def setUp(self):
super().setUp()
self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"})
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
self.test_agreement = self.env["agreement"].create(
{
"name": "TestAgreement",
"description": "Test",
"special_terms": "Test",
"partner_id": self.test_customer.id,
"start_date": fields.Date.today(),
"end_date": fields.Date.today() + timedelta(days=365),
}
)
self.test_clause = self.env["agreement.clause"].create(
{
"name": "TestClause",
"title": "Test",
"content": "Test",
"agreement_id": self.test_agreement.id,
}
)
# TEST 01: Set 'Field' for dynamic placeholder, test onchange method
def test_onchange_copyvalue(self):
clause_01 = self.test_clause
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.clause"), ("name", "=", "active")]
)
clause_01.field_id = field_01.id
clause_01.onchange_copyvalue()
self.assertEqual(clause_01.copyvalue, "${object.active or ''}")
# TEST 02: Set related 'Field' for dynamic placeholder to
# test onchange method
def test_onchange_copyvalue2(self):
clause_01 = self.test_clause
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.clause"), ("name", "=", "agreement_id")]
)
sub_field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement"), ("name", "=", "active")]
)
clause_01.field_id = field_01.id
clause_01.onchange_copyvalue()
self.assertEqual(clause_01.sub_object_id.model, "agreement")
clause_01.sub_model_object_field_id = sub_field_01.id
clause_01.onchange_copyvalue()
self.assertEqual(clause_01.copyvalue, "${object.agreement_id.active or ''}")
# TEST 03: Test Dynamic Field
def test_compute_dynamic_content(self):
clause_01 = self.test_clause
clause_01.content = "${object.name}"
self.assertEqual(
clause_01.dynamic_content, "<p>TestClause</p>",
)

View File

@@ -0,0 +1,42 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from datetime import timedelta
from odoo import fields
from odoo.tests.common import TransactionCase
class TestAgreementLine(TransactionCase):
def setUp(self):
super().setUp()
self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"})
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
self.test_agreement = self.env["agreement"].create(
{
"name": "TestAgreement",
"description": "Test",
"special_terms": "Test",
"partner_id": self.test_customer.id,
"start_date": fields.Date.today(),
"end_date": fields.Date.today() + timedelta(days=365),
}
)
self.test_product1 = self.env["product.product"].create({"name": "TEST1"})
self.test_product2 = self.env["product.product"].create({"name": "TEST2"})
self.test_line = self.env["agreement.line"].create(
{
"product_id": self.test_product1.id,
"name": "Test",
"uom_id": 1,
"agreement_id": self.test_agreement.id,
}
)
# TEST 01: Set line product onchange method
def test_onchange_product_id(self):
line_01 = self.test_line
line_01.product_id = self.test_product2.id
line_01._onchange_product_id()
self.assertEqual(line_01.name, "TEST2")

View File

@@ -0,0 +1,68 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from datetime import timedelta
from odoo import fields
from odoo.tests.common import TransactionCase
class TestAgreementRectical(TransactionCase):
def setUp(self):
super().setUp()
self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"})
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
self.test_agreement = self.env["agreement"].create(
{
"name": "TestAgreement",
"description": "Test",
"special_terms": "Test",
"partner_id": self.test_customer.id,
"start_date": fields.Date.today(),
"end_date": fields.Date.today() + timedelta(days=365),
}
)
self.test_recital = self.env["agreement.recital"].create(
{
"name": "TestRecital",
"title": "Test",
"content": "Test",
"agreement_id": self.test_agreement.id,
}
)
# TEST 01: Set 'Field' for dynamic placeholder, test onchange method
def test_onchange_copyvalue(self):
recital_01 = self.test_recital
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.recital"), ("name", "=", "active")]
)
recital_01.field_id = field_01.id
recital_01.onchange_copyvalue()
self.assertEqual(recital_01.copyvalue, "${object.active or ''}")
# TEST 02: Set related 'Field' for dynamic placeholder to
# test onchange method
def test_onchange_copyvalue2(self):
recital_01 = self.test_recital
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.recital"), ("name", "=", "agreement_id")]
)
sub_field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement"), ("name", "=", "active")]
)
recital_01.field_id = field_01.id
recital_01.onchange_copyvalue()
self.assertEqual(recital_01.sub_object_id.model, "agreement")
recital_01.sub_model_object_field_id = sub_field_01.id
recital_01.onchange_copyvalue()
self.assertEqual(recital_01.copyvalue, "${object.agreement_id.active or ''}")
# TEST 03: Test Dynamic Field
def test_compute_dynamic_content(self):
recital_01 = self.test_recital
recital_01.content = "${object.name}"
self.assertEqual(
recital_01.dynamic_content, "<p>TestRecital</p>",
)

View File

@@ -0,0 +1,68 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from datetime import timedelta
from odoo import fields
from odoo.tests.common import TransactionCase
class TestAgreementSection(TransactionCase):
def setUp(self):
super().setUp()
self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"})
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
self.test_agreement = self.env["agreement"].create(
{
"name": "TestAgreement",
"description": "Test",
"special_terms": "Test",
"partner_id": self.test_customer.id,
"start_date": fields.Date.today(),
"end_date": fields.Date.today() + timedelta(days=365),
}
)
self.test_section = self.env["agreement.section"].create(
{
"name": "TestSection",
"title": "Test",
"content": "Test",
"agreement_id": self.test_agreement.id,
}
)
# TEST 01: Set 'Field' for dynamic placeholder, test onchange method
def test_onchange_copyvalue(self):
section_01 = self.test_section
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.section"), ("name", "=", "active")]
)
section_01.field_id = field_01.id
section_01.onchange_copyvalue()
self.assertEqual(section_01.copyvalue, "${object.active or ''}")
# TEST 02: Set related 'Field' for dynamic placeholder to
# test onchange method
def test_onchange_copyvalue2(self):
section_01 = self.test_section
field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement.section"), ("name", "=", "agreement_id")]
)
sub_field_01 = self.env["ir.model.fields"].search(
[("model", "=", "agreement"), ("name", "=", "active")]
)
section_01.field_id = field_01.id
section_01.onchange_copyvalue()
self.assertEqual(section_01.sub_object_id.model, "agreement")
section_01.sub_model_object_field_id = sub_field_01.id
section_01.onchange_copyvalue()
self.assertEqual(section_01.copyvalue, "${object.agreement_id.active or ''}")
# TEST 03: Test Dynamic Field
def test_compute_dynamic_content(self):
section_01 = self.test_section
section_01.content = "${object.name}"
self.assertEqual(
section_01.dynamic_content, "<p>TestSection</p>",
)

View File

@@ -0,0 +1,74 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from odoo.tests.common import TransactionCase
class TestCreateAgreementWizard(TransactionCase):
def setUp(self):
super().setUp()
self.agreement_type = self.env["agreement.type"].create(
{"name": "Test Agreement Type", "domain": "sale"}
)
# Create Agreement Template
self.agreement_template = self.env["agreement"].create(
{
"name": "Test Agreement Template",
"description": "Test",
"state": "active",
"agreement_type_id": self.agreement_type.id,
"is_template": True,
}
)
# Create Recital
self.env["agreement.recital"].create(
{
"name": "Test Recital",
"title": "Test",
"content": "Test",
"agreement_id": self.agreement_template.id,
}
)
# Create Section
self.section = self.env["agreement.section"].create(
{
"name": "Test Section",
"title": "Test",
"content": "Test",
"agreement_id": self.agreement_template.id,
}
)
# Create Clause
self.env["agreement.clause"].create(
{
"name": "Test Clause",
"title": "Test",
"content": "Test",
"agreement_id": self.agreement_template.id,
"section_id": self.section.id,
}
)
# Create Appendix
self.env["agreement.appendix"].create(
{
"name": "Test Appendices",
"title": "Test",
"content": "Test",
"agreement_id": self.agreement_template.id,
}
)
# Test create agreement from template
def test_create_agreement(self):
template = self.agreement_template
wizard = self.env["create.agreement.wizard"].create(
{"template_id": self.agreement_template.id, "name": "Test Agreement"}
)
res = wizard.create_agreement()
agreement = self.env[res["res_model"]].browse(res["res_id"])
self.assertEqual(agreement.template_id, template)
self.assertEqual(agreement.is_template, False)
self.assertEqual(agreement.recital_ids.name, template.recital_ids.name)
self.assertEqual(agreement.sections_ids.name, template.sections_ids.name)
self.assertEqual(agreement.clauses_ids.name, template.clauses_ids.name)
self.assertEqual(agreement.clauses_ids.section_id, agreement.sections_ids)
self.assertEqual(agreement.appendix_ids.name, template.appendix_ids.name)

View File

@@ -1,29 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<template
id="assets_backend"
name="agreement_legal assets"
inherit_id="web.assets_backend"
>
<xpath expr="." position="inside">
<script
type="text/javascript"
src="/agreement_legal/static/src/js/domain_widget_ext.js"
/>
</xpath>
</template>
<!-- Agreement List View--> <!-- Agreement List View-->
<record model="ir.ui.view" id="partner_agreement_list_view"> <record model="ir.ui.view" id="partner_agreement_list_view">
<field name="name">Agreement List</field> <field name="name">Agreement List</field>
<field name="model">agreement</field> <field name="model">agreement</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Agreements" default_order='name'> <tree string="Agreements" default_order="code desc, name">
<field name="code" />
<field name="name" /> <field name="name" />
<field name="partner_id" /> <field name="partner_id" />
<field name="company_id" /> <field name="company_id" />
<field name="parent_agreement_id" /> <field name="parent_agreement_id" />
<field name="agreement_type_id" /> <field name="agreement_type_id" />
<field name="agreement_subtype_id" /> <field name="agreement_subtype_id" />
<field name="stage_id" />
<field name="active" invisible="1" /> <field name="active" invisible="1" />
</tree> </tree>
</field> </field>
@@ -54,13 +44,18 @@
name="stage_id" name="stage_id"
widget="statusbar" widget="statusbar"
clickable="True" clickable="True"
options="{'fold_field': 'fold'}" options="{'clickable': 1, 'fold_field': 'fold'}"
domain="[('stage_type', '=', 'agreement')]" domain="[('stage_type', '=', 'agreement')]"
/> />
</header> </header>
<sheet> <sheet>
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box" />
</div> <widget
name="web_ribbon"
title="Template"
bg_color="bg-info"
attrs="{'invisible': [('is_template', '=', False)]}"
/>
<div class="oe_title"> <div class="oe_title">
<label <label
for="name" for="name"
@@ -78,7 +73,11 @@
name="parent_agreement_id" name="parent_agreement_id"
domain="[('partner_id', '=', partner_id)]" domain="[('partner_id', '=', partner_id)]"
/> />
<field name="is_template" /> <field name="is_template" invisible="1" />
<field
name="template_id"
attrs="{'invisible': [('is_template', '=', True)]}"
/>
</group> </group>
<group> <group>
<field <field
@@ -97,27 +96,37 @@
/> />
<field name="active" invisible="1" /> <field name="active" invisible="1" />
<field name="state" invisible="1" /> <field name="state" invisible="1" />
<field name="readonly" invisible="1" />
</group> </group>
</group> </group>
<group string="Description"> <group string="Description">
<field name="description" required="True" nolabel="1" /> <field name="description" required="True" nolabel="1" />
</group> </group>
<group class="oe_edit_only"> <group class="oe_edit_only">
<field
name="field_domain"
widget="domain"
nolabel="1"
options="{'model': 'agreement',
'partial_use': True}"
/>
<group> <group>
<field
name="field_id"
domain="[('model_id', '=', active_model),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
/>
<field name="sub_object_id" readonly="1" />
<field
name="sub_model_object_field_id"
domain="[('model_id', '=', sub_object_id),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
attrs="{'readonly':[('sub_object_id', '=', False)],
'required':[('sub_object_id', '!=', False)]}"
/>
<field name="default_value" /> <field name="default_value" />
<field name="copyvalue" /> <field name="copyvalue" />
</group> </group>
<p> <p>
This section (on the left) allows you to add dynamic fields inside the description and special terms. This section (on the left) allows you to add dynamic fields inside the description and special terms.
<ol> <ol>
<li>Select the agreement field using the popup</li> <li>Select the agreement field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li> <li>Enter the default value if the field is empty</li>
<li <li
>Copy and paste the placeholder expression in the description or the special terms</li> >Copy and paste the placeholder expression in the description or the special terms</li>
@@ -141,7 +150,7 @@
<field <field
name="partner_id" name="partner_id"
context="{'show_address': 1}" context="{'show_address': 1}"
options="{&quot;always_reload&quot;: True}" options="{'always_reload': True}"
/> />
</div> </div>
</group> </group>
@@ -151,7 +160,7 @@
name="company_id" name="company_id"
readonly="1" readonly="1"
context="{'show_address': 1}" context="{'show_address': 1}"
options="{&quot;always_reload&quot;: True}" options="{'always_reload': True}"
/> />
</div> </div>
<field name="company_partner_id" invisible="1" /> <field name="company_partner_id" invisible="1" />
@@ -204,6 +213,10 @@
</group> </group>
<group name="term_information"> <group name="term_information">
<group name="termdates_left" string="Term Dates"> <group name="termdates_left" string="Term Dates">
<field
name="signature_date"
attrs="{'invisible': [('is_template', '=', True)]}"
/>
<field <field
name="start_date" name="start_date"
attrs="{'required': [('is_template', '=', False)], 'invisible': [('is_template', '=', True)]}" attrs="{'required': [('is_template', '=', False)], 'invisible': [('is_template', '=', True)]}"
@@ -244,30 +257,26 @@
<separator string="Recitals" /> <separator string="Recitals" />
<field <field
name="recital_ids" name="recital_ids"
default_order="sequence"
nolabel="1" nolabel="1"
context="{'default_agreement': active_id}" context="{'tree_view_ref': 'agreement_legal.agreement_recital_tree2', 'form_view_ref': 'agreement_legal.agreement_recital_form2'}"
/> />
<separator string="Sections" /> <separator string="Sections" />
<field <field
name="sections_ids" name="sections_ids"
default_order='sequence'
nolabel="1" nolabel="1"
context="{'default_agreement': active_id}" context="{'tree_view_ref': 'agreement_legal.partner_agreement_section_list_view2', 'form_view_ref': 'agreement_legal.partner_agreement_section_form_view2'}"
/> />
<separator string="Clauses" /> <separator string="Clauses" />
<field <field
name="clauses_ids" name="clauses_ids"
default_order='clause_id, sequence'
nolabel="1" nolabel="1"
context="{'default_agreement': active_id}" context="{'tree_view_ref': 'agreement_legal.partner_agreement_clause_list_view2', 'form_view_ref': 'agreement_legal.partner_agreement_clause_form_view2', 'default_temp_agreement_id': active_id}"
/> />
<separator string="Appendices" /> <separator string="Appendices" />
<field <field
name="appendix_ids" name="appendix_ids"
default_order='sequence'
nolabel="1" nolabel="1"
context="{'default_agreement': active_id}" context="{'tree_view_ref': 'agreement_legal.agreement_appendix_tree2', 'form_view_ref': 'agreement_legal.agreement_appendix_form2'}"
/> />
</page> </page>
<page name="signature" string="Signatures"> <page name="signature" string="Signatures">
@@ -305,7 +314,7 @@
</page> </page>
<page name="child_agreements" string="Child Agreements"> <page name="child_agreements" string="Child Agreements">
<field name="child_agreements_ids"> <field name="child_agreements_ids">
<tree default_order='version desc'> <tree default_order="version desc">
<field name="name" /> <field name="name" />
<field name="version" /> <field name="version" />
<field name="revision" /> <field name="revision" />
@@ -316,8 +325,9 @@
<field <field
name="previous_version_agreements_ids" name="previous_version_agreements_ids"
string="Previouse Versions" string="Previouse Versions"
readonly="1"
> >
<tree default_order='version desc'> <tree default_order="version desc">
<field name="name" /> <field name="name" />
<field name="version" /> <field name="version" />
<field name="revision" /> <field name="revision" />
@@ -348,14 +358,14 @@
/>.</p> />.</p>
</div> </div>
</group> </group>
<footer> <p name="footer">
Version: <field name="version" readonly="True" />.<field Version: <field name="version" readonly="True" />.<field
name="revision" name="revision"
readonly="True" readonly="True"
/> />
| Created By: <field name="create_uid" readonly="True" /> | Created By: <field name="created_by" readonly="True" />
| Created On: <field name="create_date" readonly="True" /> | Created On: <field name="date_created" readonly="True" />
</footer> </p>
</sheet> </sheet>
<div class="oe_chatter"> <div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" /> <field name="message_follower_ids" widget="mail_followers" />
@@ -388,10 +398,7 @@
<div <div
class="o_kanban_record_subtitle text-muted" class="o_kanban_record_subtitle text-muted"
> >
<field <field name="partner_id" />
name="partner_id"
invisible="context.get('default_partner_id', False)"
/>
<t <t
t-if="record.end_date.raw_value and record.end_date.raw_value lt (new Date())" t-if="record.end_date.raw_value and record.end_date.raw_value lt (new Date())"
t-set="red" t-set="red"
@@ -416,6 +423,7 @@
<span <span
class="fa fa-ellipsis-v" class="fa fa-ellipsis-v"
aria-hidden="true" aria-hidden="true"
title="Icon"
/> />
</a> </a>
<ul <ul
@@ -473,6 +481,7 @@
<field name="model">agreement</field> <field name="model">agreement</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Agreement Search"> <search string="Agreement Search">
<field name="code" />
<field name="name" /> <field name="name" />
<field name="partner_id" /> <field name="partner_id" />
<field name="agreement_type_id" /> <field name="agreement_type_id" />
@@ -498,11 +507,23 @@
icon="terp-partner" icon="terp-partner"
context="{'group_by':'partner_id'}" context="{'group_by':'partner_id'}"
/> />
<filter
name="group_agreement_type_id"
string="Agreement Type"
icon="terp-partner"
context="{'group_by':'agreement_type_id'}"
/>
<filter
name="group_agreement_subtype_id"
string="Agreement Sub-type"
icon="terp-partner"
context="{'group_by':'agreement_subtype_id'}"
/>
<filter <filter
name="group_status" name="group_status"
string="Status" string="Status"
icon="terp-partner" icon="terp-partner"
context="{'group_by':'state'}" context="{'group_by':'stage_id'}"
/> />
</search> </search>
</field> </field>
@@ -536,19 +557,21 @@
<field name="name">Agreements</field> <field name="name">Agreements</field>
<field name="res_model">agreement</field> <field name="res_model">agreement</field>
<field name="domain">[('is_template', '=', False)]</field> <field name="domain">[('is_template', '=', False)]</field>
<field name="context">{'default_is_template': False}</field>
<field name="view_mode">kanban,tree,form</field> <field name="view_mode">kanban,tree,form</field>
</record> </record>
<record model="ir.actions.act_window" id="agreement_operations_agreement"> <record model="ir.actions.act_window" id="agreement_operations_agreement">
<field name="name">Agreements</field> <field name="name">Agreements</field>
<field name="res_model">agreement</field> <field name="res_model">agreement</field>
<field name="domain">[('is_template', '=', False)]</field> <field name="domain">[('is_template', '=', False)]</field>
<field name="context">{'default_is_template': False}</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<record model="ir.actions.act_window" id="partner_agreement_agreement_templates"> <record model="ir.actions.act_window" id="partner_agreement_agreement_templates">
<field name="name">Templates</field> <field name="name">Templates</field>
<field name="res_model">agreement</field> <field name="res_model">agreement</field>
<field name="domain">[('is_template', '=', True)]</field> <field name="domain">[('is_template', '=', True)]</field>
<!-- <field name="context">[('is_template', '=', True)]</field> --> <field name="context">{'default_is_template': True}</field>
<field name="view_mode">tree,kanban,form</field> <field name="view_mode">tree,kanban,form</field>
</record> </record>
</odoo> </odoo>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Appendix List View--> <!-- Agreement Appendix List View-->
<record model="ir.ui.view" id="agreement_appendix_tree"> <record model="ir.ui.view" id="agreement_appendix_tree">
<field name="name">Agreement Appendix Tree</field> <field name="name">Agreement Appendix Tree</field>
<field name="model">agreement.appendix</field> <field name="model">agreement.appendix</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Appendices" default_order='agreement_id, sequence'> <tree string="Appendices" default_order="agreement_id, sequence">
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="name" /> <field name="name" />
<field name="title" /> <field name="title" />
@@ -21,20 +21,14 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Appendix"> <form string="Appendix">
<sheet> <sheet>
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box" />
<button <widget
name="toggle_active" name="web_ribbon"
type="object" title="Archived"
class="oe_stat_button" bg_color="bg-danger"
icon="fa-archive" attrs="{'invisible': [('active', '=', True)]}"
> />
<field <field name="active" invisible="1" />
name="active"
widget="boolean_button"
options="{&quot;terminology&quot;: &quot;archive&quot;}"
/>
</button>
</div>
<div class="oe_title"> <div class="oe_title">
<label for="name" class="oe_edit_only" /> <label for="name" class="oe_edit_only" />
<h1> <h1>
@@ -52,21 +46,30 @@
</group> </group>
<field name="content" widget="html" /> <field name="content" widget="html" />
<group class="oe_edit_only"> <group class="oe_edit_only">
<field
name="field_domain"
widget="domain"
nolabel="1"
options="{'model': 'agreement.appendix',
'partial_use': True}"
/>
<group> <group>
<field
name="field_id"
domain="[('model_id', '=', active_model),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
/>
<field name="sub_object_id" readonly="1" />
<field
name="sub_model_object_field_id"
domain="[('model_id', '=', sub_object_id),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
attrs="{'readonly':[('sub_object_id', '=', False)],
'required':[('sub_object_id', '!=', False)]}"
/>
<field name="default_value" /> <field name="default_value" />
<field name="copyvalue" /> <field name="copyvalue" />
</group> </group>
<p> <p>
This section (on the left) allows you to add dynamic fields inside the content. This section (on the left) allows you to add dynamic fields inside the content.
<ol> <ol>
<li>Select the field using the popup</li> <li>Select the appendix field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li> <li>Enter the default value if the field is empty</li>
<li <li
>Copy and paste the placeholder expression in the content</li> >Copy and paste the placeholder expression in the content</li>
@@ -82,7 +85,8 @@
<field name="name">Agreement Appendix Search</field> <field name="name">Agreement Appendix Search</field>
<field name="model">agreement.appendix</field> <field name="model">agreement.appendix</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search string="Appendix">
<field name="name" />
<filter <filter
name="group_agreement" name="group_agreement"
icon="terp-partner" icon="terp-partner"
@@ -97,4 +101,33 @@
<field name="res_model">agreement.appendix</field> <field name="res_model">agreement.appendix</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<!-- Agreement Appendix List View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="agreement_appendix_tree2">
<field name="name">Agreement Appendix Tree2</field>
<field name="model">agreement.appendix</field>
<field name="inherit_id" ref="agreement_appendix_tree" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<tree position="attributes">
<attribute name="default_order">sequence</attribute>
</tree>
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
<!-- Agreement Appendix Form View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="agreement_appendix_form2">
<field name="name">Agreement Appendix Form2</field>
<field name="model">agreement.appendix</field>
<field name="inherit_id" ref="agreement_appendix_form" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
</odoo> </odoo>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Clause List View--> <!-- Agreement Clause List View-->
<record model="ir.ui.view" id="partner_agreement_clause_list_view"> <record model="ir.ui.view" id="partner_agreement_clause_list_view">
<field name="name">Agreement Clause List</field> <field name="name">Agreement Clause List</field>
<field name="model">agreement.clause</field> <field name="model">agreement.clause</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Clauses" default_order='agreement_id, sequence'> <tree string="Clauses" default_order="agreement_id, sequence">
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="name" /> <field name="name" />
<field name="title" /> <field name="title" />
@@ -22,20 +22,14 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Clause"> <form string="Clause">
<sheet> <sheet>
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box" />
<button <widget
name="toggle_active" name="web_ribbon"
type="object" title="Archived"
class="oe_stat_button" bg_color="bg-danger"
icon="fa-archive" attrs="{'invisible': [('active', '=', True)]}"
> />
<field <field name="active" invisible="1" />
name="active"
widget="boolean_button"
options="{&quot;terminology&quot;: &quot;archive&quot;}"
/>
</button>
</div>
<div class="oe_title"> <div class="oe_title">
<label for="name" class="oe_edit_only" /> <label for="name" class="oe_edit_only" />
<h1> <h1>
@@ -57,21 +51,30 @@
</group> </group>
<field name="content" widget="html" /> <field name="content" widget="html" />
<group class="oe_edit_only"> <group class="oe_edit_only">
<field
name="field_domain"
widget="domain"
nolabel="1"
options="{'model': 'agreement.clause',
'partial_use': True}"
/>
<group> <group>
<field
name="field_id"
domain="[('model_id', '=', active_model),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
/>
<field name="sub_object_id" readonly="1" />
<field
name="sub_model_object_field_id"
domain="[('model_id', '=', sub_object_id),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
attrs="{'readonly':[('sub_object_id', '=', False)],
'required':[('sub_object_id', '!=', False)]}"
/>
<field name="default_value" /> <field name="default_value" />
<field name="copyvalue" /> <field name="copyvalue" />
</group> </group>
<p> <p>
This section (on the left) allows you to add dynamic fields inside the content. This section (on the left) allows you to add dynamic fields inside the content.
<ol> <ol>
<li>Select the field using the popup</li> <li>Select the clause field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li> <li>Enter the default value if the field is empty</li>
<li <li
>Copy and paste the placeholder expression in the content</li> >Copy and paste the placeholder expression in the content</li>
@@ -87,7 +90,8 @@
<field name="name">Agreement Clause Search</field> <field name="name">Agreement Clause Search</field>
<field name="model">agreement.clause</field> <field name="model">agreement.clause</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Agreement Clause Search"> <search string="Clause">
<field name="name" />
<filter <filter
name="group_agreement" name="group_agreement"
icon="terp-partner" icon="terp-partner"
@@ -107,4 +111,41 @@
<field name="res_model">agreement.clause</field> <field name="res_model">agreement.clause</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<!-- Agreement Clause List View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="partner_agreement_clause_list_view2">
<field name="name">Agreement Clause List2</field>
<field name="model">agreement.clause</field>
<field name="inherit_id" ref="partner_agreement_clause_list_view" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<tree position="attributes">
<attribute name="default_order">sequence</attribute>
</tree>
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
<!-- Agreement Clause Form View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="partner_agreement_clause_form_view2">
<field name="name">Agreement Clause Form2</field>
<field name="model">agreement.clause</field>
<field name="inherit_id" ref="partner_agreement_clause_form_view" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<field name="agreement_id" position="after">
<field name="temp_agreement_id" invisible="1" />
</field>
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
<field name="section_id" position="attributes">
<attribute
name="domain"
>[('agreement_id', '=', temp_agreement_id)]</attribute>
</field>
</field>
</record>
</odoo> </odoo>

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Agreement Increase Type List View-->
<record model="ir.ui.view" id="partner_agreement_increasetype_list_view">
<field name="name">Agreement Increase Type List</field>
<field name="model">agreement.increasetype</field>
<field name="arch" type="xml">
<tree default_order='name'>
<field name="name" />
<field name="description" />
<field name="increase_percent" />
</tree>
</field>
</record>
<!-- Agreement Increase Type Form View -->
<record model="ir.ui.view" id="partner_agreement_increasetype_form_view">
<field name="name">Agreement Increase Type Form</field>
<field name="model">agreement.increasetype</field>
<field name="arch" type="xml">
<form string="Agreements Type Form">
<sheet>
<group>
<field name="name" />
</group>
<group>
<field name="increase_percent" />
</group>
<group string="Description">
<field name="description" nolabel="1" />
</group>
</sheet>
</form>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_increasetype">
<field name="name">Agreement Increase Type</field>
<field name="res_model">agreement.increasetype</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Recital List View--> <!-- Agreement Recital List View-->
<record model="ir.ui.view" id="agreement_recital_tree"> <record model="ir.ui.view" id="agreement_recital_tree">
<field name="name">Agreement Recital Tree</field> <field name="name">Agreement Recital Tree</field>
<field name="model">agreement.recital</field> <field name="model">agreement.recital</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Recitals" default_order='agreement_id, sequence'> <tree string="Recitals" default_order="agreement_id, sequence">
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="name" /> <field name="name" />
<field name="title" /> <field name="title" />
@@ -21,20 +21,14 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Recital"> <form string="Recital">
<sheet> <sheet>
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box" />
<button <widget
name="toggle_active" name="web_ribbon"
type="object" title="Archived"
class="oe_stat_button" bg_color="bg-danger"
icon="fa-archive" attrs="{'invisible': [('active', '=', True)]}"
> />
<field <field name="active" invisible="1" />
name="active"
widget="boolean_button"
options="{&quot;terminology&quot;: &quot;archive&quot;}"
/>
</button>
</div>
<div class="oe_title"> <div class="oe_title">
<label for="name" class="oe_edit_only" /> <label for="name" class="oe_edit_only" />
<h1> <h1>
@@ -52,21 +46,30 @@
</group> </group>
<field name="content" widget="html" /> <field name="content" widget="html" />
<group class="oe_edit_only"> <group class="oe_edit_only">
<field
name="field_domain"
widget="domain"
nolabel="1"
options="{'model': 'agreement.recital',
'partial_use': True}"
/>
<group> <group>
<field
name="field_id"
domain="[('model_id', '=', active_model),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
/>
<field name="sub_object_id" readonly="1" />
<field
name="sub_model_object_field_id"
domain="[('model_id', '=', sub_object_id),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
attrs="{'readonly':[('sub_object_id', '=', False)],
'required':[('sub_object_id', '!=', False)]}"
/>
<field name="default_value" /> <field name="default_value" />
<field name="copyvalue" /> <field name="copyvalue" />
</group> </group>
<p> <p>
This section (on the left) allows you to add dynamic fields inside the content. This section (on the left) allows you to add dynamic fields inside the content.
<ol> <ol>
<li>Select the field using the popup</li> <li>Select the recital field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li> <li>Enter the default value if the field is empty</li>
<li <li
>Copy and paste the placeholder expression in the content</li> >Copy and paste the placeholder expression in the content</li>
@@ -82,7 +85,8 @@
<field name="name">Agreement Recital Search</field> <field name="name">Agreement Recital Search</field>
<field name="model">agreement.recital</field> <field name="model">agreement.recital</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search string="Recitals">
<field name="name" />
<filter <filter
name="group_agreement" name="group_agreement"
icon="terp-partner" icon="terp-partner"
@@ -97,4 +101,33 @@
<field name="res_model">agreement.recital</field> <field name="res_model">agreement.recital</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<!-- Agreement Recital List View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="agreement_recital_tree2">
<field name="name">Agreement Recital Tree2</field>
<field name="model">agreement.recital</field>
<field name="inherit_id" ref="agreement_recital_tree" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<tree position="attributes">
<attribute name="default_order">sequence</attribute>
</tree>
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
<!-- Agreement Recital Form View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="agreement_recital_form2">
<field name="name">Agreement Recital Form2</field>
<field name="model">agreement.recital</field>
<field name="inherit_id" ref="agreement_recital_form" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
</odoo> </odoo>

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Agreement Renewal Type List View-->
<record model="ir.ui.view" id="partner_agreement_renewaltype_list_view">
<field name="name">Agreement Renewal Type List</field>
<field name="model">agreement.renewaltype</field>
<field name="arch" type="xml">
<tree default_order='name'>
<field name="name" />
<field name="description" />
</tree>
</field>
</record>
<!-- Agreement Renewal Type Form View -->
<record model="ir.ui.view" id="partner_agreement_renewaltype_form_view">
<field name="name">Agreement Renewal Type Form</field>
<field name="model">agreement.renewaltype</field>
<field name="arch" type="xml">
<form string="Agreements Type Form">
<sheet>
<group>
<field name="name" />
</group>
<group string="Description">
<field name="description" nolabel="1" />
</group>
</sheet>
</form>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_renewaltype">
<field name="name">Agreement Renewal Type</field>
<field name="res_model">agreement.renewaltype</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Sections List View--> <!-- Agreement Sections List View-->
<record model="ir.ui.view" id="partner_agreement_section_list_view"> <record model="ir.ui.view" id="partner_agreement_section_list_view">
<field name="name">Agreement Section List</field> <field name="name">Agreement Section List</field>
<field name="model">agreement.section</field> <field name="model">agreement.section</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Sections" default_order='agreement_id, sequence'> <tree string="Sections" default_order="agreement_id, sequence">
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="name" /> <field name="name" />
<field name="title" /> <field name="title" />
@@ -21,20 +21,14 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Section"> <form string="Section">
<sheet> <sheet>
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box" />
<button <widget
name="toggle_active" name="web_ribbon"
type="object" title="Archived"
class="oe_stat_button" bg_color="bg-danger"
icon="fa-archive" attrs="{'invisible': [('active', '=', True)]}"
> />
<field <field name="active" invisible="1" />
name="active"
widget="boolean_button"
options="{&quot;terminology&quot;: &quot;archive&quot;}"
/>
</button>
</div>
<div class="oe_title"> <div class="oe_title">
<label for="name" class="oe_edit_only" /> <label for="name" class="oe_edit_only" />
<h1> <h1>
@@ -54,21 +48,30 @@
<page string="Content"> <page string="Content">
<field name='content' nolabel="1" /> <field name='content' nolabel="1" />
<group class="oe_edit_only"> <group class="oe_edit_only">
<field
name="field_domain"
widget="domain"
nolabel="1"
options="{'model': 'agreement.section',
'partial_use': True}"
/>
<group> <group>
<field
name="field_id"
domain="[('model_id', '=', active_model),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
/>
<field name="sub_object_id" readonly="1" />
<field
name="sub_model_object_field_id"
domain="[('model_id', '=', sub_object_id),
('ttype', '!=', 'one2many'),
('ttype', '!=', 'many2many')]"
attrs="{'readonly':[('sub_object_id', '=', False)],
'required':[('sub_object_id', '!=', False)]}"
/>
<field name="default_value" /> <field name="default_value" />
<field name="copyvalue" /> <field name="copyvalue" />
</group> </group>
<p> <p>
This section (on the left) allows you to add dynamic fields inside the content. This section (on the left) allows you to add dynamic fields inside the content.
<ol> <ol>
<li>Select the field using the popup</li> <li>Select the section field</li>
<li>Select the sub-field</li>
<li <li
>Enter the default value if the field is empty</li> >Enter the default value if the field is empty</li>
<li <li
@@ -100,7 +103,8 @@
<field name="name">Agreement Section Search</field> <field name="name">Agreement Section Search</field>
<field name="model">agreement.section</field> <field name="model">agreement.section</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Agreement Section Search"> <search string="Section">
<field name="name" />
<filter <filter
name="group_agreement" name="group_agreement"
string="Agreements" string="Agreements"
@@ -116,4 +120,33 @@
<field name="res_model">agreement.section</field> <field name="res_model">agreement.section</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<!-- Agreement Sections List View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="partner_agreement_section_list_view2">
<field name="name">Agreement Section List2</field>
<field name="model">agreement.section</field>
<field name="inherit_id" ref="partner_agreement_section_list_view" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<tree position="attributes">
<attribute name="default_order">sequence</attribute>
</tree>
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
<!-- Agreement Sections Form View 2 (Call this view from agreement)-->
<record model="ir.ui.view" id="partner_agreement_section_form_view2">
<field name="name">Agreement Section Form2</field>
<field name="model">agreement.section</field>
<field name="inherit_id" ref="partner_agreement_section_form_view" />
<field name="mode">primary</field>
<field name="priority">999</field>
<field name="arch" type="xml">
<field name="agreement_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
</odoo> </odoo>

View File

@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Stage List View--> <!-- Agreement Stage List View-->
<record model="ir.ui.view" id="partner_agreement_stage_list_view"> <record model="ir.ui.view" id="partner_agreement_stage_list_view">
<field name="name">Agreement Stage List</field> <field name="name">Agreement Stage List</field>
<field name="model">agreement.stage</field> <field name="model">agreement.stage</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree default_order='sequence, name'> <tree default_order="sequence, name">
<field name="sequence" widget="handle" /> <field name="sequence" widget="handle" />
<field name="name" string="Stage Name" /> <field name="name" />
<field name="stage_type" /> <field name="stage_type" />
<field name="active" widget="boolean_toggle" />
</tree> </tree>
</field> </field>
</record> </record>
@@ -19,21 +20,52 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Agreements Stage Form"> <form string="Agreements Stage Form">
<sheet> <sheet>
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<div class="oe_title"> <div class="oe_title">
<label for="name" class="oe_edit_only" string="Stage Name" /> <label for="name" class="oe_edit_only" />
<h1> <h1>
<field name="name" string="Stage Name" /> <field name="name" />
</h1> </h1>
</div> </div>
<group> <group>
<field name="sequence" /> <field name="sequence" />
<field name="stage_type" /> <field name="stage_type" />
<field name="fold" /> <field name="fold" />
<field name="readonly" />
<field name="active" invisible="1" />
</group> </group>
</sheet> </sheet>
</form> </form>
</field> </field>
</record> </record>
<!-- Agreement Stage Search View -->
<record model="ir.ui.view" id="partner_agreement_stage_search_view">
<field name="name">Agreement Stage Search</field>
<field name="model">agreement.stage</field>
<field name="arch" type="xml">
<search string="Agreements Stage Search">
<field name="name" />
<separator />
<filter
name="archived"
string="Archived"
domain="[('active', '=', False)]"
/>
<group name="groupby">
<filter
name="type_groupby"
string="Type"
context="{'group_by': 'stage_type'}"
/>
</group>
</search>
</field>
</record>
<!-- Actions opening views on models --> <!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_stage"> <record model="ir.actions.act_window" id="partner_agreement_action_stage">
<field name="name">Agreement Stage</field> <field name="name">Agreement Stage</field>

View File

@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Sub Type List View--> <!-- Agreement Sub Type List View-->
<record model="ir.ui.view" id="partner_agreement_subtype_list_view"> <record model="ir.ui.view" id="partner_agreement_subtype_list_view">
<field name="name">Agreement Subtype List</field> <field name="name">Agreement Subtype List</field>
<field name="model">agreement.subtype</field> <field name="model">agreement.subtype</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree default_order='name'> <tree default_order="name">
<field name="name" string="Sub-Type Name" /> <field name="name" />
<field name="agreement_type_id" string="Agreement Type" /> <field name="agreement_type_id" />
<field name="active" widget="boolean_toggle" />
</tree> </tree>
</field> </field>
</record> </record>
@@ -18,6 +19,12 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Agreement Sub-Types"> <form string="Agreement Sub-Types">
<sheet> <sheet>
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<div class="oe_title"> <div class="oe_title">
<label for="name" class="oe_edit_only" /> <label for="name" class="oe_edit_only" />
<h1> <h1>
@@ -27,6 +34,7 @@
<group> <group>
<group> <group>
<field name="agreement_type_id" /> <field name="agreement_type_id" />
<field name="active" invisible="1" />
</group> </group>
<group /> <group />
</group> </group>
@@ -34,6 +42,30 @@
</form> </form>
</field> </field>
</record> </record>
<!-- Agreement Sub Type Search View -->
<record model="ir.ui.view" id="partner_agreement_subtype_search_view">
<field name="name">Agreement Sub Type Search</field>
<field name="model">agreement.subtype</field>
<field name="arch" type="xml">
<search string="Agreements Sub-Types Search">
<field name="name" />
<field name="agreement_type_id" />
<separator />
<filter
name="archived"
string="Archived"
domain="[('active', '=', False)]"
/>
<group name="groupby">
<filter
name="agreement_type_groupby"
string="Agreement Type"
context="{'group_by': 'agreement_type_id'}"
/>
</group>
</search>
</field>
</record>
<!-- Actions opening views on models --> <!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_subtype"> <record model="ir.actions.act_window" id="partner_agreement_action_subtype">
<field name="name">Agreement Sub-Types</field> <field name="name">Agreement Sub-Types</field>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Agreement Type List View--> <!-- Agreement Type List View-->
<record model="ir.ui.view" id="partner_agreement_type_list_view"> <record model="ir.ui.view" id="partner_agreement_type_list_view">
@@ -7,7 +7,7 @@
<field name="inherit_id" ref="agreement.agreement_type_list_view" /> <field name="inherit_id" ref="agreement.agreement_type_list_view" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="name" position="after"> <field name="name" position="after">
<field name="agreement_subtypes_ids" string="Sub-Types" /> <field name="agreement_subtypes_ids" widget="many2many_tags" />
</field> </field>
</field> </field>
</record> </record>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template
id="assets_backend"
name="agreement_legal assets"
inherit_id="web.assets_backend"
>
<xpath expr="." position="inside">
<script
type="text/javascript"
src="/agreement_legal/static/src/js/agreement.js"
/>
</xpath>
</template>
</odoo>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Remove top menu from agreement module --> <!-- Remove top menu from agreement module -->
<!-- <delete model="ir.ui.menu" id="agreement.agreement_menu" /> --> <!-- <delete model="ir.ui.menu" id="agreement.agreement_menu" /> -->
@@ -124,39 +124,25 @@
sequence="20" sequence="20"
action="partner_agreement_agreement_templates" action="partner_agreement_agreement_templates"
/> />
<menuitem
name="Renewal Types"
id="agreement_renewaltype"
parent="agreement_configuration"
sequence="30"
action="partner_agreement_action_renewaltype"
/>
<menuitem
name="Increase Types"
id="agreement_increamenttypes"
parent="agreement_configuration"
sequence="31"
action="partner_agreement_action_increasetype"
/>
<menuitem <menuitem
name="Stages" name="Stages"
id="agreement_stages" id="agreement_stages"
parent="agreement_configuration" parent="agreement_configuration"
sequence="40" sequence="30"
action="partner_agreement_action_stage" action="partner_agreement_action_stage"
/> />
<menuitem <menuitem
name="Types" name="Types"
id="agreement_types" id="agreement_types"
parent="agreement_configuration" parent="agreement_configuration"
sequence="50" sequence="40"
action="partner_agreement_action_type" action="partner_agreement_action_type"
/> />
<menuitem <menuitem
name="Sub-Types" name="Sub-Types"
id="agreement_subtypes" id="agreement_subtypes"
parent="agreement_configuration" parent="agreement_configuration"
sequence="60" sequence="50"
action="partner_agreement_action_subtype" action="partner_agreement_action_subtype"
/> />
</odoo> </odoo>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="res_config_settings_view_form" model="ir.ui.view"> <record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.agreement</field> <field name="name">res.config.settings.view.form.agreement</field>
@@ -49,7 +49,7 @@
<field name="module_agreement_sale" /> <field name="module_agreement_sale" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Sales" /> <label for="module_agreement_sale" string="Sales" />
<div class="text-muted"> <div class="text-muted">
Create an agreement when the sales order is confirmed Create an agreement when the sales order is confirmed
</div> </div>
@@ -63,7 +63,10 @@
<field name="module_agreement_sale_subscription" /> <field name="module_agreement_sale_subscription" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Sale Subscriptions" /> <label
for="module_agreement_sale_subscription"
string="Sale Subscriptions"
/>
<div class="text-muted"> <div class="text-muted">
Link your subscriptions to an agreement Link your subscriptions to an agreement
</div> </div>
@@ -74,7 +77,10 @@
<field name="module_fieldservice_agreement" /> <field name="module_fieldservice_agreement" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Field Service" /> <label
for="module_fieldservice_agreement"
string="Field Service"
/>
<div class="text-muted"> <div class="text-muted">
Link your Field Service orders and equipments to an agreement Link your Field Service orders and equipments to an agreement
</div> </div>
@@ -85,7 +91,10 @@
<field name="module_agreement_stock" /> <field name="module_agreement_stock" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Inventory" /> <label
for="module_agreement_stock"
string="Inventory"
/>
<div class="text-muted"> <div class="text-muted">
Link your transfers to an agreement Link your transfers to an agreement
</div> </div>
@@ -96,7 +105,7 @@
<field name="module_agreement_rma" /> <field name="module_agreement_rma" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Returns" /> <label for="module_agreement_rma" string="Returns" />
<div class="text-muted"> <div class="text-muted">
Link your returns to an agreement Link your returns to an agreement
</div> </div>
@@ -107,7 +116,10 @@
<field name="module_agreement_maintenance" /> <field name="module_agreement_maintenance" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Maintenance" /> <label
for="module_agreement_maintenance"
string="Maintenance"
/>
<div class="text-muted"> <div class="text-muted">
Manage maintenance agreements and contracts Manage maintenance agreements and contracts
</div> </div>
@@ -118,7 +130,10 @@
<field name="module_agreement_mrp" /> <field name="module_agreement_mrp" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Manufacturing" /> <label
for="module_agreement_mrp"
string="Manufacturing"
/>
<div class="text-muted"> <div class="text-muted">
Link your manufacturing orders to an agreement Link your manufacturing orders to an agreement
</div> </div>
@@ -129,7 +144,7 @@
<field name="module_agreement_repair" /> <field name="module_agreement_repair" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Repair" /> <label for="module_agreement_repair" string="Repair" />
<div class="text-muted"> <div class="text-muted">
Link your repair orders to an agreement Link your repair orders to an agreement
</div> </div>
@@ -140,7 +155,10 @@
<field name="module_agreement_project" /> <field name="module_agreement_project" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Project" /> <label
for="module_agreement_project"
string="Project"
/>
<div class="text-muted"> <div class="text-muted">
Link your projects and tasks to an agreement Link your projects and tasks to an agreement
</div> </div>
@@ -151,7 +169,10 @@
<field name="module_agreement_helpdesk" /> <field name="module_agreement_helpdesk" />
</div> </div>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="" string="Helpdesk" /> <label
for="module_agreement_helpdesk"
string="Helpdesk"
/>
<div class="text-muted"> <div class="text-muted">
Link your Helpdesk tickets to an agreement Link your Helpdesk tickets to an agreement
</div> </div>
@@ -162,12 +183,11 @@
</xpath> </xpath>
</field> </field>
</record> </record>
<act_window <record id="action_agreement_config" model="ir.actions.act_window">
id="action_agreement_config" <field name="name">Settings</field>
name="Settings" <field name="res_model">res.config.settings</field>
res_model="res.config.settings" <field name="view_mode">form</field>
view_mode="form" <field name="target">inline</field>
target="inline" <field name="context">{'module': 'agreement'}</field>
context="{'module': 'agreement'}" </record>
/>
</odoo> </odoo>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record model="ir.ui.view" id="partner_form"> <record model="ir.ui.view" id="partner_form">
<field name="model">res.partner</field> <field name="model">res.partner</field>

View File

@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import create_agreement_wizard

View File

@@ -0,0 +1,31 @@
# Copyright 2021 Ecosoft Co., Ltd (http://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class CreateAgreementWizard(models.TransientModel):
_name = "create.agreement.wizard"
_description = "Create Agreement Wizard"
template_id = fields.Many2one(
"agreement",
string="Template",
required=True,
domain=[("is_template", "=", True)],
)
name = fields.Char(string="Title", required=True)
def create_agreement(self):
self.ensure_one()
res = self.template_id.create_new_agreement()
agreement = self.env[res["res_model"]].browse(res["res_id"])
agreement.write(
{
"name": self.name,
"description": self.name,
"template_id": self.template_id.id,
"revision": 0,
}
)
return res

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="create_agreement_from_template_form_view" model="ir.ui.view">
<field name="name">Create Agreement From Template</field>
<field name="model">create.agreement.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<group>
<field name="template_id" />
</group>
<group>
<field name="name" />
</group>
</group>
<footer>
<button
name="create_agreement"
string="Create Agreement"
class="btn-primary"
type="object"
/>
<button string="Cancel" class="btn-default" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="create_agreement_from_template_action" model="ir.actions.act_window">
<field name="name">Create From Template</field>
<field name="res_model">create.agreement.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>