Browse Source

Merge pull request #301 from ygol/12.0-mig-ag_legal

[MIG] agreement --> agreement_legal
pull/303/head
Maxime Chambreuil 6 years ago
committed by GitHub
parent
commit
54b6415e2a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 130
      agreement_legal/README.rst
  2. 4
      agreement_legal/__init__.py
  3. 41
      agreement_legal/__manifest__.py
  4. 49
      agreement_legal/data/agreement_stage.xml
  5. 16
      agreement_legal/data/agreement_type.xml
  6. 13
      agreement_legal/data/ir_sequence.xml
  7. 9
      agreement_legal/data/module_category.xml
  8. 1782
      agreement_legal/i18n/agreement_legal.pot
  9. 1800
      agreement_legal/i18n/fr.po
  10. 18
      agreement_legal/models/__init__.py
  11. 408
      agreement_legal/models/agreement.py
  12. 101
      agreement_legal/models/agreement_appendix.py
  13. 103
      agreement_legal/models/agreement_clause.py
  14. 27
      agreement_legal/models/agreement_increasetype.py
  15. 30
      agreement_legal/models/agreement_line.py
  16. 99
      agreement_legal/models/agreement_recital.py
  17. 23
      agreement_legal/models/agreement_renewaltype.py
  18. 102
      agreement_legal/models/agreement_section.py
  19. 28
      agreement_legal/models/agreement_stage.py
  20. 12
      agreement_legal/models/agreement_status.py
  21. 14
      agreement_legal/models/agreement_subtype.py
  22. 16
      agreement_legal/models/agreement_type.py
  23. 12
      agreement_legal/models/product_template.py
  24. 38
      agreement_legal/models/res_config_settings.py
  25. 13
      agreement_legal/models/res_partner.py
  26. 6
      agreement_legal/readme/CONFIGURE.rst
  27. 6
      agreement_legal/readme/CONTRIBUTORS.rst
  28. 5
      agreement_legal/readme/CREDITS.rst
  29. 9
      agreement_legal/readme/DESCRIPTION.rst
  30. 3
      agreement_legal/readme/ROADMAP.rst
  31. 7
      agreement_legal/readme/USAGE.rst
  32. 144
      agreement_legal/report/agreement.xml
  33. 23
      agreement_legal/security/ir.model.access.csv
  34. 22
      agreement_legal/security/res_groups.xml
  35. BIN
      agreement_legal/static/description/icon.png
  36. 473
      agreement_legal/static/description/index.html
  37. 362
      agreement_legal/views/agreement.xml
  38. 95
      agreement_legal/views/agreement_appendix.xml
  39. 97
      agreement_legal/views/agreement_clause.xml
  40. 45
      agreement_legal/views/agreement_increasetype.xml
  41. 94
      agreement_legal/views/agreement_recital.xml
  42. 41
      agreement_legal/views/agreement_renewaltype.xml
  43. 109
      agreement_legal/views/agreement_section.xml
  44. 43
      agreement_legal/views/agreement_stages.xml
  45. 45
      agreement_legal/views/agreement_subtype.xml
  46. 45
      agreement_legal/views/agreement_type.xml
  47. 147
      agreement_legal/views/menu.xml
  48. 161
      agreement_legal/views/res_config_settings.xml
  49. 17
      agreement_legal/views/res_partner.xml

130
agreement_legal/README.rst

@ -0,0 +1,130 @@
==========
Agreements
==========
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github
:target: https://github.com/OCA/contract/tree/11.0/agreement
:alt: OCA/contract
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/contract-11-0/contract-11-0-agreement
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/110/11.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows you to manage agreements, letter of intent and contract content.
The module is meant to be used by the legal team of a company and to allow them
to define sections, clauses and templates with their respective content that can
be dynamic.
Based on the template, an agreement can be created and the pdf document generated.
The agreement would go through a workflow to finally become a contract with the
customer signature.
**Table of contents**
.. contents::
:local:
Configuration
=============
To configure this module:
* Go to Agreement > Configuration > Templates
* Create a new template with sections and clauses and their respective content
* Go to Agreement > Configuration > Stages
* Create and reorder stages to match your process
Usage
=====
To use this module:
* Go to Agreement > Agrements
* Create a new agreement
* Select a template
* Follow the process to get the required approval
* Send the invitation to the customer to review and sign the agreement
Known issues / Roadmap
======================
* Split the module to remove the dependencies on sale and account and provide
the same feature in extra modules (agreement_sale, agreement_account,
agreement_purchase)
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/contract/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/contract/issues/new?body=module:%20agreement%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Pavlov Media
* Open Source Integrators
Contributors
~~~~~~~~~~~~
* Patrick Wilson <pwilson@pavlovmedia.com>
* Bhavesh Odedra <bodedra@opensourceintegrators.com>
* Wolfgang Hall <whall@opensourceintegrators.com>
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
* Sandip Mangukiya <smangukiya@opensourceintegrators.com>
Other credits
~~~~~~~~~~~~~
The development of this module has been financially supported by:
* Pavlov Media
* Open Source Integrators
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px
:target: https://github.com/max3903
:alt: max3903
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-max3903|
This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/11.0/agreement>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

4
agreement_legal/__init__.py

@ -0,0 +1,4 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models

41
agreement_legal/__manifest__.py

@ -0,0 +1,41 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Agreements Legal",
"summary": "Manage Agreements, LOI and Contracts",
"author": "Pavlov Media, "
"Open Source Integrators, "
"Yves Goldberg (Ygol Internetwork), "
"Odoo Community Association (OCA)",
"website": "https://github.com/OCA/contract",
"category": "Partner",
"license": "AGPL-3",
"version": "12.0.1.0.0",
"depends": ["contacts", "agreement", "product"],
"data": [
"data/ir_sequence.xml",
"data/module_category.xml",
"data/agreement_stage.xml",
"data/agreement_type.xml",
"security/res_groups.xml",
"security/ir.model.access.csv",
"report/agreement.xml",
"views/res_config_settings.xml",
"views/agreement_appendix.xml",
"views/agreement_clause.xml",
"views/agreement_recital.xml",
"views/agreement_section.xml",
"views/agreement_stages.xml",
"views/agreement_type.xml",
"views/agreement_subtype.xml",
"views/agreement_renewaltype.xml",
"views/agreement_increasetype.xml",
"views/res_partner.xml",
"views/agreement.xml",
"views/menu.xml",
],
"application": True,
"development_status": "Beta",
"maintainers": ["max3903", "ygol"],
}

49
agreement_legal/data/agreement_stage.xml

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<odoo>
<record id="agreement_stage_new" model="agreement.stage">
<field name="name">New</field>
<field name="sequence">10</field>
</record>
<record id="agreement_stage_draft" model="agreement.stage">
<field name="name">Draft</field>
<field name="sequence">20</field>
</record>
<record id="agreement_stage_reviewed" model="agreement.stage">
<field name="name">Reviewed</field>
<field name="sequence">30</field>
</record>
<record id="agreement_stage_negotiation" model="agreement.stage">
<field name="name">Negotiation</field>
<field name="sequence">40</field>
</record>
<record id="agreement_stage_out" model="agreement.stage">
<field name="name">Out for Customer Signature</field>
<field name="sequence">50</field>
</record>
<record id="agreement_stage_internal" model="agreement.stage">
<field name="name">Waiting Internal Signature</field>
<field name="sequence">60</field>
</record>
<record id="agreement_stage_active" model="agreement.stage">
<field name="name">Active</field>
<field name="sequence">70</field>
</record>
<record id="agreement_stage_expired" model="agreement.stage">
<field name="name">Expired</field>
<field name="sequence">80</field>
</record>
<record id="agreement_stage_cancelled" model="agreement.stage">
<field name="name">Cancelled</field>
<field name="sequence">100</field>
<field name="fold">True</field>
</record>
</odoo>

16
agreement_legal/data/agreement_type.xml

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<odoo>
<record id="agreement_type_agreement" model="agreement.type">
<field name="name">Agreement</field>
</record>
<record id="agreement_type_contract" model="agreement.type">
<field name="name">Contract</field>
</record>
<record id="agreement_type_loi" model="agreement.type">
<field name="name">Letter of Intent</field>
</record>
</odoo>

13
agreement_legal/data/ir_sequence.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<!-- Sequence for agreement -->
<record id="seq_agreement" model="ir.sequence">
<field name="name">Agreements</field>
<field name="code">agreement</field>
<field name="prefix">AG</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
</odoo>

9
agreement_legal/data/module_category.xml

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

1782
agreement_legal/i18n/agreement_legal.pot
File diff suppressed because it is too large
View File

1800
agreement_legal/i18n/fr.po
File diff suppressed because it is too large
View File

18
agreement_legal/models/__init__.py

@ -0,0 +1,18 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import (
res_config_settings,
agreement_stage,
agreement,
agreement_appendix,
agreement_clause,
agreement_line,
agreement_recital,
agreement_section,
agreement_type,
agreement_subtype,
res_partner,
product_template,
agreement_renewaltype,
agreement_increasetype,
)

408
agreement_legal/models/agreement.py

@ -0,0 +1,408 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
class Agreement(models.Model):
_name = "agreement"
_inherit = ["agreement", "mail.thread"]
def _default_stage_id(self):
return self.env.ref("agreement_legal.agreement_stage_new")
# General
name = fields.Char(string="Title", required=True)
is_template = fields.Boolean(
string="Is a Template?",
default=False,
copy=False,
help="Make this agreement a template.",
)
version = fields.Integer(
string="Version",
default=1,
copy=False,
help="The versions are used to keep track of document history and "
"previous versions can be referenced.",
)
revision = fields.Integer(
string="Revision",
default=0,
copy=False,
help="The revision will increase with every save event.",
)
description = fields.Text(
string="Description",
track_visibility="onchange",
help="Description of the agreement",
)
dynamic_description = fields.Text(
compute="_compute_dynamic_description",
string="Dynamic Description",
help="Compute dynamic description",
)
start_date = fields.Date(
string="Start Date",
track_visibility="onchange",
help="When the agreement starts.",
)
end_date = fields.Date(
string="End Date",
track_visibility="onchange",
help="When the agreement ends.",
)
color = fields.Integer()
active = fields.Boolean(
string="Active",
default=True,
help="If unchecked, it will allow you to hide the agreement without "
"removing it.",
)
company_signed_date = fields.Date(
string="Signed on",
track_visibility="onchange",
help="Date the contract was signed by Company.",
)
partner_signed_date = fields.Date(
string="Signed on",
track_visibility="onchange",
help="Date the contract was signed by the Partner.",
)
term = fields.Integer(
string="Term (Months)",
track_visibility="onchange",
help="Number of months this agreement/contract is in effect with the "
"partner.",
)
expiration_notice = fields.Integer(
string="Exp. Notice (Days)",
track_visibility="onchange",
help="Number of Days before expiration to be notified.",
)
change_notice = fields.Integer(
string="Change Notice (Days)",
track_visibility="onchange",
help="Number of Days to be notified before changes.",
)
special_terms = fields.Text(
string="Special Terms",
track_visibility="onchange",
help="Any terms that you have agreed to and want to track on the "
"agreement/contract.",
)
dynamic_special_terms = fields.Text(
compute="_compute_dynamic_special_terms",
string="Dynamic Special Terms",
help="Compute dynamic special terms",
)
reference = fields.Char(
string="Reference",
copy=False,
required=True,
default=lambda self: _("New"),
track_visibility="onchange",
help="ID used for internal contract tracking.",
)
increase_type_id = fields.Many2one(
"agreement.increasetype",
string="Increase Type",
track_visibility="onchange",
help="The amount that certain rates may increase.",
)
termination_requested = fields.Date(
string="Termination Requested Date",
track_visibility="onchange",
help="Date that a request for termination was received.",
)
termination_date = fields.Date(
string="Termination Date",
track_visibility="onchange",
help="Date that the contract was terminated.",
)
reviewed_date = fields.Date(
string="Reviewed Date", track_visibility="onchange"
)
reviewed_user_id = fields.Many2one(
"res.users", string="Reviewed By", track_visibility="onchange"
)
approved_date = fields.Date(
string="Approved Date", track_visibility="onchange"
)
approved_user_id = fields.Many2one(
"res.users", string="Approved By", track_visibility="onchange"
)
currency_id = fields.Many2one("res.currency", string="Currency")
partner_id = fields.Many2one(
"res.partner",
string="Partner",
copy=True,
help="The customer or vendor this agreement is related to.",
)
company_partner_id = fields.Many2one(
"res.partner",
string="Company",
copy=True,
default=lambda self: self.env.user.company_id.partner_id,
)
partner_contact_id = fields.Many2one(
"res.partner",
string="Partner Contact",
copy=True,
help="The primary partner contact (If Applicable).",
)
partner_contact_phone = fields.Char(
related="partner_contact_id.phone", string="Phone"
)
partner_contact_email = fields.Char(
related="partner_contact_id.email", string="Email"
)
company_contact_id = fields.Many2one(
"res.partner",
string="Company Contact",
copy=True,
help="The primary contact in the company.",
)
company_contact_phone = fields.Char(
related="company_contact_id.phone", string="Phone"
)
company_contact_email = fields.Char(
related="company_contact_id.email", string="Email"
)
agreement_type_id = fields.Many2one(
"agreement.type",
string="Agreement Type",
track_visibility="onchange",
help="Select the type of agreement.",
)
agreement_subtype_id = fields.Many2one(
"agreement.subtype",
string="Agreement Sub-type",
track_visibility="onchange",
help="Select the sub-type of this agreement. Sub-Types are related to "
"agreement types.",
)
product_ids = fields.Many2many(
"product.template", string="Products & Services"
)
assigned_user_id = fields.Many2one(
"res.users",
string="Assigned To",
track_visibility="onchange",
help="Select the user who manages this agreement.",
)
company_signed_user_id = fields.Many2one(
"res.users",
string="Signed By",
track_visibility="onchange",
help="The user at our company who authorized/signed the agreement or "
"contract.",
)
partner_signed_user_id = fields.Many2one(
"res.partner",
string="Signed By",
track_visibility="onchange",
help="Contact on the account that signed the agreement/contract.",
)
parent_agreement_id = fields.Many2one(
"agreement",
string="Parent Agreement",
help="Link this agreement to a parent agreement. For example if this "
"agreement is an amendment to another agreement. This list will "
"only show other agreements related to the same account.",
)
renewal_type_id = fields.Many2one(
"agreement.renewaltype",
string="Renewal Type",
track_visibility="onchange",
help="Describes what happens after the contract expires.",
)
recital_ids = fields.One2many(
"agreement.recital", "agreement_id", string="Recitals", copy=True
)
sections_ids = fields.One2many(
"agreement.section", "agreement_id", string="Sections", copy=True
)
clauses_ids = fields.One2many(
"agreement.clause", "agreement_id", string="Clauses", copy=True
)
appendix_ids = fields.One2many(
"agreement.appendix", "agreement_id", string="Appendices", copy=True
)
previous_version_agreements_ids = fields.One2many(
"agreement",
"parent_agreement_id",
string="Child Agreements",
copy=False,
domain=[("active", "=", False)],
)
child_agreements_ids = fields.One2many(
"agreement",
"parent_agreement_id",
string="Child Agreements",
copy=False,
domain=[("active", "=", True)],
)
line_ids = fields.One2many(
"agreement.line",
"agreement_id",
string="Products/Services",
copy=False,
)
state = fields.Selection(
[("draft", "Draft"), ("active", "Active"), ("inactive", "Inactive")],
default="draft",
track_visibility="always",
)
notification_address_id = fields.Many2one(
"res.partner",
string="Notification Address",
help="The address to send notificaitons to, if different from "
"customer address.(Address Type = Other)",
)
signed_contract_filename = fields.Char(string="Filename")
signed_contract = fields.Binary(
string="Signed Document", track_visibility="always"
)
field_id = fields.Many2one(
"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(
string="Default Value",
help="Optional value to use if the target field is empty.",
)
copyvalue = fields.Char(
string="Placeholder Expression",
help="""Final placeholder expression, to be copy-pasted in the desired
template field.""",
)
# compute the dynamic content for mako expression
@api.multi
def _compute_dynamic_description(self):
MailTemplates = self.env["mail.template"]
for agreement in self:
lang = agreement.partner_id.lang or "en_US"
description = MailTemplates.with_context(
lang=lang
)._render_template(
agreement.description, "agreement", agreement.id
)
agreement.dynamic_description = description
@api.multi
def _compute_dynamic_special_terms(self):
MailTemplates = self.env["mail.template"]
for agreement in self:
lang = agreement.partner_id.lang or "en_US"
special_terms = MailTemplates.with_context(
lang=lang
)._render_template(
agreement.special_terms, "agreement", agreement.id
)
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
self.sub_object_id = 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
@api.model
def _read_group_stage_ids(self, stages, domain, order):
stage_ids = self.env["agreement.stage"].search([])
return stage_ids
stage_id = fields.Many2one(
"agreement.stage",
string="Stage",
group_expand="_read_group_stage_ids",
help="Select the current stage of the agreement.",
track_visibility="onchange",
index=True,
# default=lambda self: self._default_stage_id(),
)
# Create New Version Button
@api.multi
def create_new_version(self, vals):
for rec in self:
if not rec.state == "draft":
# Make sure status is 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
rec.copy(default=default_vals)
# Increment the Version
rec.version = rec.version + 1
# Reset revision to 0 since it's a new version
vals["revision"] = 0
return super(Agreement, self).write(vals)
def create_new_agreement(self):
default_vals = {
"name": "NEW",
"active": True,
"version": 1,
"revision": 0,
"state": "draft",
}
res = self.copy(default=default_vals)
return {
"res_model": "agreement",
"type": "ir.actions.act_window",
"view_mode": "form",
"view_type": "form",
"res_id": res.id,
}
@api.model
def create(self, vals):
if vals.get("reference", _("New")) == _("New"):
vals["reference"] = self.env["ir.sequence"].next_by_code(
"agreement"
) or _("New")
return super(Agreement, self).create(vals)
# Increments the revision on each save action
@api.multi
def write(self, vals):
vals["revision"] = self.revision + 1
return super(Agreement, self).write(vals)

101
agreement_legal/models/agreement_appendix.py

@ -0,0 +1,101 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AgreementAppendix(models.Model):
_name = "agreement.appendix"
_description = "Agreement Appendices"
_order = "sequence"
name = fields.Char(string="Name", required=True)
title = fields.Char(
string="Title",
required=True,
help="The title is displayed on the PDF." "The name is not.",
)
sequence = fields.Integer(
string="Sequence",
default=10)
content = fields.Html(string="Content")
dynamic_content = fields.Html(
compute="_compute_dynamic_content",
string="Dynamic Content",
help="compute dynamic Content",
)
agreement_id = fields.Many2one(
"agreement",
string="Agreement",
ondelete="cascade")
active = fields.Boolean(
string="Active",
default=True,
help="If unchecked, it will allow you to hide this appendix without "
"removing it.",
)
# Dynamic field editor
field_id = fields.Many2one(
"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(
string="Default Value",
help="Optional value to use if the target field is empty.",
)
copyvalue = fields.Char(
string="Placeholder Expression",
help="""Final placeholder expression, to be copy-pasted in the desired
template field.""",
)
@api.onchange('field_id', 'sub_model_object_field_id', 'default_value')
def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False
self.sub_object_id = False
if self.field_id and not self.field_id.relation:
self.copyvalue = "${object.%s or %s}" % \
(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.%s.%s or %s}" %\
(self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or '\'\'')
# compute the dynamic content for mako expression
@api.multi
def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"]
for appendix in self:
lang = (
appendix.agreement_id
and appendix.agreement_id.partner_id.lang
or "en_US"
)
content = MailTemplates.with_context(lang=lang)._render_template(
appendix.content, "agreement.appendix", appendix.id
)
appendix.dynamic_content = content

103
agreement_legal/models/agreement_clause.py

@ -0,0 +1,103 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AgreementClause(models.Model):
_name = "agreement.clause"
_description = "Agreement Clauses"
_order = "sequence"
name = fields.Char(string="Name", required=True)
title = fields.Char(
string="Title",
help="The title is displayed on the PDF." "The name is not."
)
sequence = fields.Integer(string="Sequence")
agreement_id = fields.Many2one(
"agreement",
string="Agreement",
ondelete="cascade")
section_id = fields.Many2one(
"agreement.section",
string="Section",
ondelete="cascade"
)
content = fields.Html(string="Clause Content")
dynamic_content = fields.Html(
compute="_compute_dynamic_content",
string="Dynamic Content",
help="compute dynamic Content",
)
active = fields.Boolean(
string="Active",
default=True,
help="If unchecked, it will allow you to hide the agreement without "
"removing it.",
)
# Dynamic field editor
field_id = fields.Many2one(
"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(
string="Default Value",
help="Optional value to use if the target field is empty.",
)
copyvalue = fields.Char(
string="Placeholder Expression",
help="""Final placeholder expression, to be copy-pasted in the desired
template field.""",
)
@api.onchange('field_id', 'sub_model_object_field_id', 'default_value')
def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False
self.sub_object_id = False
if self.field_id and not self.field_id.relation:
self.copyvalue = "${object.%s or %s}" % \
(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.%s.%s or %s}" %\
(self.field_id.name,
self.sub_model_object_field_id.name,
self.default_value or '\'\'')
# compute the dynamic content for mako expression
@api.multi
def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"]
for clause in self:
lang = (
clause.agreement_id
and clause.agreement_id.partner_id.lang
or "en_US"
)
content = MailTemplates.with_context(lang=lang)._render_template(
clause.content, "agreement.clause", clause.id
)
clause.dynamic_content = content

27
agreement_legal/models/agreement_increasetype.py

@ -0,0 +1,27 @@
# 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."
)

30
agreement_legal/models/agreement_line.py

@ -0,0 +1,30 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AgreementLine(models.Model):
_name = "agreement.line"
_description = "Agreement Lines"
product_id = fields.Many2one(
"product.product",
string="Product")
name = fields.Char(
string="Description",
required=True)
agreement_id = fields.Many2one(
"agreement",
string="Agreement",
ondelete="cascade")
qty = fields.Float(string="Quantity")
uom_id = fields.Many2one(
"uom.uom",
string="Unit of Measure",
required=True)
@api.onchange("product_id")
def _onchange_product_id(self):
self.name = self.product_id.name
self.uom_id = self.product_id.uom_id.id

99
agreement_legal/models/agreement_recital.py

@ -0,0 +1,99 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AgreementRecital(models.Model):
_name = "agreement.recital"
_description = "Agreement Recitals"
_order = "sequence"
name = fields.Char(string="Name", required=True)
title = fields.Char(
string="Title",
help="The title is displayed on the PDF." "The name is not.",
)
sequence = fields.Integer(string="Sequence", default=10)
content = fields.Html(string="Content")
dynamic_content = fields.Html(
compute="_compute_dynamic_content",
string="Dynamic Content",
help="compute dynamic Content",
)
agreement_id = fields.Many2one(
"agreement", string="Agreement", ondelete="cascade"
)
active = fields.Boolean(
string="Active",
default=True,
help="If unchecked, it will allow you to hide this recital without "
"removing it.",
)
# Dynamic field editor
field_id = fields.Many2one(
"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(
string="Default Value",
help="Optional value to use if the target field is empty.",
)
copyvalue = fields.Char(
string="Placeholder Expression",
help="""Final placeholder expression, to be copy-pasted in the desired
template field.""",
)
@api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False
self.sub_object_id = 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 "''",
)
# compute the dynamic content for mako expression
@api.multi
def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"]
for recital in self:
lang = (
recital.agreement_id
and recital.agreement_id.partner_id.lang
or "en_US"
)
content = MailTemplates.with_context(lang=lang)._render_template(
recital.content, "agreement.recital", recital.id
)
recital.dynamic_content = content

23
agreement_legal/models/agreement_renewaltype.py

@ -0,0 +1,23 @@
# 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."
)

102
agreement_legal/models/agreement_section.py

@ -0,0 +1,102 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AgreementSection(models.Model):
_name = "agreement.section"
_description = "Agreement Sections"
_order = "sequence"
name = fields.Char(string="Name", required=True)
title = fields.Char(
string="Title",
help="The title is displayed on the PDF." "The name is not.",
)
sequence = fields.Integer(string="Sequence")
agreement_id = fields.Many2one(
"agreement", string="Agreement", ondelete="cascade"
)
clauses_ids = fields.One2many(
"agreement.clause", "section_id", string="Clauses"
)
content = fields.Html(string="Section Content")
dynamic_content = fields.Html(
compute="_compute_dynamic_content",
string="Dynamic Content",
help="compute dynamic Content",
)
active = fields.Boolean(
string="Active",
default=True,
help="""If unchecked, it will allow you to hide the
agreement without removing it.""",
)
# Dynamic field editor
field_id = fields.Many2one(
"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(
string="Default Value",
help="Optional value to use if the target field is empty.",
)
copyvalue = fields.Char(
string="Placeholder Expression",
help="""Final placeholder expression, to be copy-pasted in the desired
template field.""",
)
@api.onchange("field_id", "sub_model_object_field_id", "default_value")
def onchange_copyvalue(self):
self.sub_object_id = False
self.copyvalue = False
self.sub_object_id = 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 "''",
)
# compute the dynamic content for mako expression
@api.multi
def _compute_dynamic_content(self):
MailTemplates = self.env["mail.template"]
for section in self:
lang = (
section.agreement_id
and section.agreement_id.partner_id.lang
or "en_US"
)
content = MailTemplates.with_context(lang=lang)._render_template(
section.content, "agreement.section", section.id
)
section.dynamic_content = content

28
agreement_legal/models/agreement_stage.py

@ -0,0 +1,28 @@
# 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 AgreementStage(models.Model):
_name = "agreement.stage"
_description = "Agreement Stages"
_order = "sequence"
# General
name = fields.Char(
string="Stage Name",
required=True)
description = fields.Text(
string="Description",
required=False)
sequence = fields.Integer(
string="Sequence",
default="1",
required=False)
fold = fields.Boolean(
string="Is Folded",
required=False,
help="This stage is folded in the kanban view by deafault.",
)

12
agreement_legal/models/agreement_status.py

@ -0,0 +1,12 @@
# 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)

14
agreement_legal/models/agreement_subtype.py

@ -0,0 +1,14 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class AgreementSubtype(models.Model):
_name = "agreement.subtype"
_description = "Agreement Subtypes"
name = fields.Char(string="Name", required=True)
agreement_type_id = fields.Many2one(
"agreement.type",
string="Agreement Type")

16
agreement_legal/models/agreement_type.py

@ -0,0 +1,16 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class AgreementType(models.Model):
_name = "agreement.type"
_description = "Agreement Types"
name = fields.Char(string="Name", required=True)
agreement_subtypes_ids = fields.One2many(
"agreement.subtype",
"agreement_type_id",
string="Subtypes"
)

12
agreement_legal/models/product_template.py

@ -0,0 +1,12 @@
# 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(
"agreement",
string="Agreements")

38
agreement_legal/models/res_config_settings.py

@ -0,0 +1,38 @@
# Copyright (C) 2018 - TODAY, Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
module_agreement_maintenance = fields.Boolean(
string="Manage maintenance agreements and contracts."
)
module_agreement_mrp = fields.Boolean(
string="Link your manufacturing orders to an agreement."
)
module_agreement_project = fields.Boolean(
string="Link your projects and tasks to an agreement."
)
module_agreement_repair = fields.Boolean(
string="Link your repair orders to an agreement."
)
module_agreement_rma = fields.Boolean(
string="Link your RMAs to an agreement.")
module_agreement_sale = fields.Boolean(
string="Create an agreement when the sale order is confirmed."
)
module_agreement_sale_subscription = fields.Boolean(
string="Link your subscriptions to an agreement."
)
module_agreement_stock = fields.Boolean(
string="Link your pickings to an agreement."
)
module_fieldservice_agreement = fields.Boolean(
string="Link your Field Service orders and equipments to an agreement."
)
module_helpdesk_agreement = fields.Boolean(
string="Link your Helpdesk tickets to an agreement."
)

13
agreement_legal/models/res_partner.py

@ -0,0 +1,13 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class Partner(models.Model):
_inherit = "res.partner"
agreement_ids = fields.One2many(
"agreement",
"partner_id",
string="Agreements")

6
agreement_legal/readme/CONFIGURE.rst

@ -0,0 +1,6 @@
To configure this module:
* Go to Agreement > Configuration > Templates
* Create a new template with sections and clauses and their respective content
* Go to Agreement > Configuration > Stages
* Create and reorder stages to match your process

6
agreement_legal/readme/CONTRIBUTORS.rst

@ -0,0 +1,6 @@
* Patrick Wilson <pwilson@pavlovmedia.com>
* Bhavesh Odedra <bodedra@opensourceintegrators.com>
* Wolfgang Hall <whall@opensourceintegrators.com>
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
* Sandip Mangukiya <smangukiya@opensourceintegrators.com>
* Yves Goldberg <yves@ygol.com>

5
agreement_legal/readme/CREDITS.rst

@ -0,0 +1,5 @@
The development of this module has been financially supported by:
* Pavlov Media
* Open Source Integrators
* Yves Goldberg

9
agreement_legal/readme/DESCRIPTION.rst

@ -0,0 +1,9 @@
This module allows you to manage agreements, letter of intent and contract content.
The module is meant to be used by the legal team of a company and to allow them
to define sections, clauses and templates with their respective content that can
be dynamic.
Based on the template, an agreement can be created and the pdf document generated.
The agreement would go through a workflow to finally become a contract with the
customer signature.

3
agreement_legal/readme/ROADMAP.rst

@ -0,0 +1,3 @@
* Split the module to remove the dependencies on sale and account and provide
the same feature in extra modules (agreement_sale, agreement_account,
agreement_purchase)

7
agreement_legal/readme/USAGE.rst

@ -0,0 +1,7 @@
To use this module:
* Go to Agreement > Agreements
* Create a new agreement
* Select a template
* Follow the process to get the required approval
* Send the invitation to the customer to review and sign the agreement

144
agreement_legal/report/agreement.xml

@ -0,0 +1,144 @@
<?xml version="1.0"?>
<odoo>
<report
id="partner_agreement_contract_document"
model="agreement"
string="Contract Document"
name="agreement_legal.report_agreement_document"
file="agreement_legal.report_agreement_document"
report_type="qweb-pdf"/>
<report
id="partner_agreement_contract_document_preview"
model="agreement"
string="Contract Document Preview"
name="agreement_legal.report_agreement_document"
file="agreement_legal.report_agreement_document"
report_type="qweb-html"/>
<template id="report_agreement_document">
<t t-name="agreement.report_agreement_document">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.external_layout">
<div class="page">
<h1 t-field="doc.name"/>
<div name="description">
<p t-field="doc.dynamic_description"/>
</div>
<h2>Parties</h2>
<h3>Company Information</h3>
<div name="company_address">
<address t-field="doc.company_partner_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
</div>
<div name="company_contact">
Represented by <span t-field="doc.company_contact_id.name"/>.
</div>
<h3>Partner Information</h3>
<div name="partner_address">
<address t-field="doc.partner_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
</div>
<div name="partner_contact">
Represented by <span t-field="doc.partner_contact_id.name"/>.
</div>
<h2>Agreement</h2>
<h3>Recitals</h3>
<table class="table table-condensed">
<tbody>
<tr>
<td>
<ol>
<li t-foreach="doc.recital_ids" t-as="r">
<t t-if="r.title">
<h3 t-field="r.title"/>
</t>
<p t-field="r.dynamic_content"/>
</li>
</ol>
</td>
</tr>
</tbody>
</table>
<table class="table table-condensed">
<tbody class="section_tbody">
<tr>
<td>
<ol>
<li t-foreach="doc.sections_ids" t-as="s">
<t t-if="s.title">
<h3 t-field="s.title"/>
</t>
<p t-field="s.dynamic_content"/>
<ol>
<li t-foreach="s.clauses_ids" t-as="c">
<t t-if="c.title">
<h4 t-field="c.title"/>
</t>
<p t-field="c.dynamic_content"/>
</li>
</ol>
</li>
</ol>
</td>
</tr>
</tbody>
</table>
<t t-if="special_term">
<h2>Special Terms</h2>
<div name="special_term">
<p t-field="doc.dynamic_special_terms"/>
</div>
</t>
<h2>Signatures</h2>
<table class="table table-condensed">
<theader>
<tr>
<th>Partner</th>
<th>Company</th>
</tr>
</theader>
<tbody class="section_tbody">
<tr>
<td>
<p t-field="doc.partner_id"/>
<p>By: </p>
<p>
Name: <span t-field="doc.partner_contact_id.name"/>
</p>
<p>
Title: <span t-field="doc.partner_contact_id.function"/>
</p>
<p>Date: </p>
</td>
<td>
<p t-field="doc.company_partner_id"/>
<p>By: </p>
<p>
Name: <span t-field="doc.company_contact_id.name"/>
</p>
<p>
Title: <span t-field="doc.company_contact_id.function"/>
</p>
<p>Date: </p>
</td>
</tr>
</tbody>
</table>
</div>
<div t-foreach="doc.appendix_ids" t-as="a">
<div class="page">
<h1 t-field="a.title"
style="page-break-before: always;"/>
<p t-field="a.dynamic_content"/>
</div>
</div>
</t>
</t>
</t>
</t>
</template>
</odoo>

23
agreement_legal/security/ir.model.access.csv

@ -0,0 +1,23 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
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_recital_allusers,recital all users,model_agreement_recital,group_agreement_user,1,1,1,0
access_agreement_recital_manager,recital manager,model_agreement_recital,group_agreement_manager,1,1,1,1
access_agreement_section_allusers,section all users,model_agreement_section,group_agreement_user,1,1,1,0
access_agreement_section_manager,section manager,model_agreement_section,group_agreement_manager,1,1,1,1
access_agreement_clause_allusers,clause all users,model_agreement_clause,group_agreement_user,1,1,1,0
access_agreement_clause_manager,clause manager,model_agreement_clause,group_agreement_manager,1,1,1,1
access_agreement_appendix_allusers,appendix all users,model_agreement_appendix,group_agreement_user,1,1,1,0
access_agreement_appendix_manager,appendix manager,model_agreement_appendix,group_agreement_manager,1,1,1,1
access_agreement_line_allusers,agreement line all users,model_agreement_line,group_agreement_user,1,1,1,0
access_agreement_line_manager,agreement line manager,model_agreement_line,group_agreement_manager,1,1,1,1
access_agreement_stage_allusers,stage all users,model_agreement_stage,group_agreement_user,1,0,0,0
access_agreement_stage_manager,stage manager,model_agreement_stage,group_agreement_manager,1,1,1,1
access_agreement_type_allusers,type all users,model_agreement_type,group_agreement_user,1,0,0,0
access_agreement_type_manager,type manager,model_agreement_type,group_agreement_manager,1,1,1,1
access_agreement_subtype_allusers,subtype all users,model_agreement_subtype,group_agreement_user,1,0,0,0
access_agreement_subtype_manager,subtype manager,model_agreement_subtype,group_agreement_manager,1,1,1,1
access_agreement_renewaltype_allusers,renewaltype all users,model_agreement_renewaltype,group_agreement_user,1,0,0,0
access_agreement_renewaltype_manager,renewaltype manager,model_agreement_renewaltype,group_agreement_manager,1,1,1,1
access_agreement_increasetype_allusers,increasetype all users,model_agreement_increasetype,group_agreement_user,1,0,0,0
access_agreement_increasetype_manager,increasetype manager,model_agreement_increasetype,group_agreement_manager,1,1,1,1

22
agreement_legal/security/res_groups.xml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="module_agreement_legal_category" model="ir.module.category">
<field name ="name">Agreement</field>
<field name ="sequence">17</field>
</record>
<!-- User group -->
<record id="group_agreement_user" model="res.groups">
<field name="name">User</field>
<field name="category_id" ref="module_agreement_legal_category"/>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<!-- Manager group -->
<record id="group_agreement_manager" model="res.groups">
<field name="name">Manager</field>
<field name="category_id" ref="module_agreement_legal_category"/>
<field name="implied_ids" eval="[(4, ref('group_agreement_user'))]"/>
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
</record>
</odoo>

BIN
agreement_legal/static/description/icon.png

After

Width: 64  |  Height: 64  |  Size: 6.6 KiB

473
agreement_legal/static/description/index.html

@ -0,0 +1,473 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>Agreements</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="agreements">
<h1 class="title">Agreements</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/contract/tree/11.0/agreement"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/contract-11-0/contract-11-0-agreement"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/110/11.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module allows you to manage agreements, letter of intent and contract content.
The module is meant to be used by the legal team of a company and to allow them
to define sections, clauses and templates with their respective content that can
be dynamic.</p>
<p>Based on the template, an agreement can be created and the pdf document generated.</p>
<p>The agreement would go through a workflow to finally become a contract with the
customer signature.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="id2">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id3">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
<li><a class="reference internal" href="#other-credits" id="id8">Other credits</a></li>
<li><a class="reference internal" href="#maintainers" id="id9">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#id1">Configuration</a></h1>
<p>To configure this module:</p>
<ul class="simple">
<li>Go to Agreement &gt; Configuration &gt; Templates</li>
<li>Create a new template with sections and clauses and their respective content</li>
<li>Go to Agreement &gt; Configuration &gt; Stages</li>
<li>Create and reorder stages to match your process</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id2">Usage</a></h1>
<p>To use this module:</p>
<ul class="simple">
<li>Go to Agreement &gt; Agrements</li>
<li>Create a new agreement</li>
<li>Select a template</li>
<li>Follow the process to get the required approval</li>
<li>Send the invitation to the customer to review and sign the agreement</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Split the module to remove the dependencies on sale and account and provide
the same feature in extra modules (agreement_sale, agreement_account,
agreement_purchase)</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/contract/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/contract/issues/new?body=module:%20agreement%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id5">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id6">Authors</a></h2>
<ul class="simple">
<li>Pavlov Media</li>
<li>Open Source Integrators</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id7">Contributors</a></h2>
<ul class="simple">
<li>Patrick Wilson &lt;<a class="reference external" href="mailto:pwilson&#64;pavlovmedia.com">pwilson&#64;pavlovmedia.com</a>&gt;</li>
<li>Bhavesh Odedra &lt;<a class="reference external" href="mailto:bodedra&#64;opensourceintegrators.com">bodedra&#64;opensourceintegrators.com</a>&gt;</li>
<li>Wolfgang Hall &lt;<a class="reference external" href="mailto:whall&#64;opensourceintegrators.com">whall&#64;opensourceintegrators.com</a>&gt;</li>
<li>Maxime Chambreuil &lt;<a class="reference external" href="mailto:mchambreuil&#64;opensourceintegrators.com">mchambreuil&#64;opensourceintegrators.com</a>&gt;</li>
<li>Sandip Mangukiya &lt;<a class="reference external" href="mailto:smangukiya&#64;opensourceintegrators.com">smangukiya&#64;opensourceintegrators.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
<h2><a class="toc-backref" href="#id8">Other credits</a></h2>
<p>The development of this module has been financially supported by:</p>
<ul class="simple">
<li>Pavlov Media</li>
<li>Open Source Integrators</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id9">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/max3903"><img alt="max3903" src="https://github.com/max3903.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/contract/tree/11.0/agreement">OCA/contract</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

362
agreement_legal/views/agreement.xml

@ -0,0 +1,362 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement List View-->
<record model="ir.ui.view" id="partner_agreement_list_view">
<field name="name">Agreement List</field>
<field name="model">agreement</field>
<field name="arch" type="xml">
<tree string="Agreements" default_order='name'>
<field name="name"/>
<field name="partner_id"/>
<field name="company_partner_id"/>
<field name="parent_agreement_id"/>
<field name="agreement_type_id"/>
<field name="agreement_subtype_id"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<!-- Agreement Form View -->
<record model="ir.ui.view" id="partner_agreement_form_view">
<field name="name">Agreement Form</field>
<field name="model">agreement</field>
<field name="arch" type="xml">
<form string="Agreements Form">
<header>
<button string="New Version" type="object" name="create_new_version" class="oe_highlight" attrs="{'invisible': [('state', '=', 'active')]}"/>
<button string="New Agreement" type="object" name="create_new_agreement" class="oe_highlight" attrs="{'invisible': [('is_template', '=', False)]}"/>
<field name="stage_id" widget="statusbar" clickable="True" options="{'fold_field': 'fold'}"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Agreement Name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group string="General">
<group>
<field name="code"/>
<field name="reference" readonly="1"/>
<field name="parent_agreement_id"
domain="[('partner_id', '=', partner_id)]"/>
<field name="is_template"/>
</group>
<group>
<field name="agreement_type_id"
widget="selection"
required="True"/>
<field name="agreement_subtype_id"
widget="selection"
domain="[('agreement_type_id', '=', agreement_type_id)]"/>
<field name="assigned_user_id"
attrs="{'invisible': [('is_template', '=', True)], 'readonly':[('is_template', '=', True)]}"/>
<field name="active" invisible="1"/>
<field name="state" invisible="1"/>
</group>
</group>
<group string="Description">
<field name="description"
required="True"
nolabel="1"/>
</group>
<group class="oe_edit_only">
<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="copyvalue"/>
</group>
<p>
This section (on the left) allows you to add dynamic fields inside the description and special terms.
<ol>
<li>Select the agreement field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li>
<li>Copy and paste the placeholder expression in the description or the special terms</li>
</ol>
</p>
</group>
<group name="parties" string="Parties">
<group name="partner"
string="Partner">
<div class="o_address_format">
<field name="partner_id"
domain="[('customer', '=', True)]"
context="{'show_address': 1}"
options="{&quot;always_reload&quot;: True}"/>
</div>
</group>
<group name="company"
string="Company">
<div class="o_address_format">
<field name="company_partner_id"
readonly="1"
context="{'show_address': 1}"
options="{&quot;always_reload&quot;: True}"/>
</div>
</group>
<group name="partner_left" string="Primary Contact">
<field name="partner_contact_id" domain="[('parent_id', '=', partner_id)]" nolabel="1"/>
<field name="partner_contact_phone" widget="phone" readonly="1" nolabel="1"/>
<field name="partner_contact_email" widget="email" readonly="1" nolabel="1"/>
</group>
<group name="contact_right" string="Primary Contact">
<field name="company_contact_id" domain="[('parent_id', '=', company_partner_id)]" nolabel="1"/>
<field name="company_contact_phone" widget="phone" readonly="1" nolabel="1"/>
<field name="company_contact_email" widget="email" readonly="1" nolabel="1"/>
</group>
</group>
<group name="term_information">
<group name="termdates_left" string="Term Dates">
<field name="start_date" attrs="{'required': [('is_template', '=', False)], 'invisible': [('is_template', '=', True)]}"/>
<field name="end_date" attrs="{'required': [('is_template', '=', False)], 'invisible': [('is_template', '=', True)]}"/>
<field name="expiration_notice"/>
<field name="change_notice"/>
<field name="notification_address_id" domain="['|', ('parent_id', '=', partner_id), ('parent_id', '=', company_partner_id)]"/>
<field name="termination_requested"/>
<field name="termination_date"/>
</group>
</group>
<group string="Special Terms">
<field name="special_terms"
nolabel="1"/>
</group>
<notebook>
<page name="structure" string="Structure">
<div>
<button name="%(partner_agreement_contract_document_preview)d" string="Preview" type="action" class="oe_highlight"/>
<button name="%(partner_agreement_contract_document)d" string="Print" type="action" class="oe_highlight"/>
</div>
<separator string="Recitals"/>
<field name="recital_ids"
default_order="sequence"
nolabel="1"
context="{'default_agreement': active_id}"/>
<separator string="Sections"/>
<field name="sections_ids"
default_order='sequence'
nolabel="1"
context="{'default_agreement': active_id}"/>
<separator string="Clauses"/>
<field name="clauses_ids"
default_order='clause_id, sequence'
nolabel="1"
context="{'default_agreement': active_id}"/>
<separator string="Appendices"/>
<field name="appendix_ids"
default_order='sequence'
nolabel="1"
context="{'default_agreement': active_id}"/>
</page>
<page name="signature" string="Signatures">
<group>
<group string="Partner">
<field name="partner_signed_date"/>
<field name="partner_signed_user_id" domain="[('parent_id', '=', partner_id)]"/>
</group>
<group string="Company">
<field name="company_signed_date"/>
<field name="company_signed_user_id"/>
<field name="signed_contract" filename="signed_contract_filename"/>
<field name="signed_contract_filename" invisible="1"/>
</group>
</group>
</page>
<page name="products" string="Products/Services">
<field name="line_ids" nolabel="1">
<tree editable="top">
<field name="product_id"/>
<field name="name"/>
<field name="qty"/>
<field name="uom_id" groups="uom.group_uom"/>
</tree>
</field>
</page>
<page name="child_agreements" string="Child Agreements">
<field name="child_agreements_ids">
<tree default_order='version desc'>
<field name="name"/>
<field name="version"/>
<field name="revision"/>
</tree>
</field>
</page>
<page name="old_versions" string="Revisions">
<field name="previous_version_agreements_ids" string="Previouse Versions">
<tree default_order='version desc'>
<field name="name"/>
<field name="version"/>
<field name="revision"/>
</tree>
</field>
</page>
<page name="performance" string="Performance">
<p>This section is a place where financial records will show the current performance of this agreement.</p>
<p>Perhaps include invoices with total vs costs? </p>
</page>
</notebook>
<group string="Administration">
<div>
<p>Reviewed by <field name="reviewed_user_id" class="oe_inline"/> on <field name="reviewed_date" class="oe_inline"/>.</p>
<p>Approved by <field name="approved_user_id" class="oe_inline"/> on <field name="approved_date" class="oe_inline"/>.</p>
</div>
</group>
<footer>
Version: <field name="version" readonly="True"/>.<field name="revision" readonly="True"/>
| Created By: <field name="create_uid" readonly="True"/>
| Created On: <field name="create_date" readonly="True"/>
</footer>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Agreement Kanban View -->
<record id="view_project_agreement_kanban" model="ir.ui.view">
<field name="name">Agreement Kanban</field>
<field name="model">agreement</field>
<field name="arch" type="xml">
<kanban default_group_by="stage_id">
<field name="color"/>
<field name="assigned_user_id"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click">
<div class="oe_kanban_content">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong><br/>
<div class="o_kanban_record_subtitle text-muted">
<field name="partner_id" invisible="context.get('default_partner_id', False)"/>
<t t-if="record.end_date.raw_value and record.end_date.raw_value lt (new Date())" t-set="red">oe_kanban_text_red</t>
<div t-attf-class="#{red || ''}">
<i><field name="end_date"/></i>
</div>
</div>
</div>
<div class="o_dropdown_kanban dropdown" groups="base.group_user">
<a role="button" class="dropdown-toggle btn" data-toggle="dropdown" href="#">
<span class="fa fa-ellipsis-v" aria-hidden="true"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li t-if="widget.editable"><a type="edit">Edit</a></li>
<li class="divider"/>
<li class="dropdown-header">Record's Colour</li>
<li>
<ul class="oe_kanban_colorpicker" data-field="color"/>
</li>
</ul>
</div>
</div>
<div class="o_kanban_record_body">
<field name="agreement_type_id"/> - <field name="agreement_subtype_id"/>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
V: <field name="version"/>
</div>
<div class="oe_kanban_bottom_right">
<img t-att-src="kanban_image('res.users', 'image_small', record.assigned_user_id.raw_value)" t-att-title="record.assigned_user_id.value" width="36" height="36" class="oe_kanban_avatar" alt="user &amp; picture"/>
</div>
</div>
</div>
<div class="oe_clear"/>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Agreement Search View -->
<record model="ir.ui.view" id="partner_agreement_search_view">
<field name="name">Agreement Search</field>
<field name="model">agreement</field>
<field name="arch" type="xml">
<search string="Agreement Search">
<field name="name"/>
<field name="partner_id"/>
<field name="agreement_type_id"/>
<field name="agreement_subtype_id"/>
<filter name="filter_non_template" string="Non-Templates" domain="[('active','=',True),('is_template', '=', False)]"/>
<filter name="filter_inactive" string="Archived" domain="[('active','=',False)]"/>
<filter name="filter_templates" string="Templates" domain="[('active','=',True),('is_template', '=', True)]"/>
<filter name="group_partner_id" string="Partners" icon="terp-partner" context="{'group_by':'partner_id'}"/>
<filter name="group_status" string="Status" icon="terp-partner" context="{'group_by':'state'}"/>
</search>
</field>
</record>
<!-- Agreement Reporting -->
<record id="agreement_graph_view" model="ir.ui.view">
<field name="name">agreement.graph</field>
<field name="model">agreement</field>
<field name="arch" type="xml">
<graph string="Agreements" type="bar">
<field name="stage_id" type="row"/>
</graph>
</field>
</record>
<record id="agreement_pivot_view" model="ir.ui.view">
<field name="name">agreement.pivot</field>
<field name="model">agreement</field>
<field name="arch" type="xml">
<pivot string="Agreements" display_quantity="true">
<field name="stage_id" type="row"/>
</pivot>
</field>
</record>
<record id="action_agreement_report_order" model="ir.actions.act_window">
<field name="name">Agreements</field>
<field name="res_model">agreement</field>
<field name="view_type">form</field>
<field name="view_mode">graph,pivot</field>
</record>
<!-- actions opening views on models -->
<record model="ir.actions.act_window" id="agreement_dashboard_agreement">
<field name="name">Agreements</field>
<field name="res_model">agreement</field>
<field name="domain">[('is_template', '=', False)]</field>
<field name="view_mode">kanban,tree,form</field>
</record>
<record model="ir.actions.act_window" id="agreement_operations_agreement">
<field name="name">Agreements</field>
<field name="res_model">agreement</field>
<field name="domain">[('is_template', '=', False)]</field>
<field name="view_mode">tree,form</field>
</record>
<record model="ir.actions.act_window" id="partner_agreement_agreement_templates">
<field name="name">Templates</field>
<field name="res_model">agreement</field>
<field name="domain">[('is_template', '=', True)]</field>
<!-- <field name="context">[('is_template', '=', True)]</field> -->
<field name="view_mode">tree,kanban,form</field>
</record>
</odoo>

95
agreement_legal/views/agreement_appendix.xml

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Appendix List View-->
<record model="ir.ui.view" id="agreement_appendix_tree">
<field name="name">Agreement Appendix Tree</field>
<field name="model">agreement.appendix</field>
<field name="arch" type="xml">
<tree string="Appendices" default_order='agreement_id, sequence'>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="title"/>
<field name="agreement_id"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<!-- Agreement Appendix Form View -->
<record model="ir.ui.view" id="agreement_appendix_form">
<field name="name">Agreement Appendix Form</field>
<field name="model">agreement.appendix</field>
<field name="arch" type="xml">
<form string="Appendix">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button" options="{&quot;terminology&quot;: &quot;archive&quot;}"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="title"/>
<field name="agreement_id"/>
</group>
<group>
<field name="sequence"/>
</group>
</group>
<field name="content" widget="html"/>
<group class="oe_edit_only">
<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="copyvalue"/>
</group>
<p>
This section (on the left) allows you to add dynamic fields inside the content.
<ol>
<li>Select the appendix field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li>
<li>Copy and paste the placeholder expression in the content</li>
</ol>
</p>
</group>
</sheet>
</form>
</field>
</record>
<!-- Agreement Appendix Search View -->
<record model="ir.ui.view" id="agreement_appendix_search">
<field name="name">Agreement Appendix Search</field>
<field name="model">agreement.appendix</field>
<field name="arch" type="xml">
<search>
<filter name="group_agreement" icon="terp-partner" context="{'group_by':'agreement_id'}"/>
</search>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="agreement_appendix_action">
<field name="name">Appendices</field>
<field name="res_model">agreement.appendix</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

97
agreement_legal/views/agreement_clause.xml

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Clause List View-->
<record model="ir.ui.view" id="partner_agreement_clause_list_view">
<field name="name">Agreement Clause List</field>
<field name="model">agreement.clause</field>
<field name="arch" type="xml">
<tree string="Clauses" default_order='agreement_id, sequence'>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="title"/>
<field name="agreement_id"/>
<field name="section_id"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<!-- Agreement Clause Form View -->
<record model="ir.ui.view" id="partner_agreement_clause_form_view">
<field name="name">Agreement clause Form</field>
<field name="model">agreement.clause</field>
<field name="arch" type="xml">
<form string="Clause">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button" options="{&quot;terminology&quot;: &quot;archive&quot;}"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="title"/>
<field name="agreement_id"/>
<field name="section_id" domain="[('agreement_id', '=', agreement_id)]"/>
</group>
<group>
<field name="sequence"/>
</group>
</group>
<field name="content" widget="html"/>
<group class="oe_edit_only">
<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="copyvalue"/>
</group>
<p>
This section (on the left) allows you to add dynamic fields inside the content.
<ol>
<li>Select the clause field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li>
<li>Copy and paste the placeholder expression in the content</li>
</ol>
</p>
</group>
</sheet>
</form>
</field>
</record>
<!-- Agreement Clause Search View -->
<record model="ir.ui.view" id="agreement_clause_search_view">
<field name="name">Agreement Clause Search</field>
<field name="model">agreement.clause</field>
<field name="arch" type="xml">
<search string="Agreement Clause Search">
<filter name="group_agreement" icon="terp-partner" context="{'group_by':'agreement_id'}"/>
<filter name="group_section" icon="terp-partner" context="{'group_by':'section_id'}"/>
</search>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_clause">
<field name="name">Clauses</field>
<field name="res_model">agreement.clause</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

45
agreement_legal/views/agreement_increasetype.xml

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

94
agreement_legal/views/agreement_recital.xml

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Recital List View-->
<record model="ir.ui.view" id="agreement_recital_tree">
<field name="name">Agreement Recital Tree</field>
<field name="model">agreement.recital</field>
<field name="arch" type="xml">
<tree string="Recitals" default_order='agreement_id, sequence'>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="title"/>
<field name="agreement_id"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<!-- Agreement Recital Form View -->
<record model="ir.ui.view" id="agreement_recital_form">
<field name="name">Agreement Recital Form</field>
<field name="model">agreement.recital</field>
<field name="arch" type="xml">
<form string="Recital">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button" options="{&quot;terminology&quot;: &quot;archive&quot;}"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="title"/>
<field name="agreement_id"/>
</group>
<group>
<field name="sequence"/>
</group>
</group>
<field name="content" widget="html"/>
<group class="oe_edit_only">
<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="copyvalue"/>
</group>
<p>
This section (on the left) allows you to add dynamic fields inside the content.
<ol>
<li>Select the recital field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li>
<li>Copy and paste the placeholder expression in the content</li>
</ol>
</p>
</group>
</sheet>
</form>
</field>
</record>
<!-- Agreement Recital Search View -->
<record model="ir.ui.view" id="agreement_recital_search">
<field name="name">Agreement Recital Search</field>
<field name="model">agreement.recital</field>
<field name="arch" type="xml">
<search>
<filter name="group_agreement" icon="terp-partner" context="{'group_by':'agreement_id'}"/>
</search>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="agreement_recital_action">
<field name="name">Recitals</field>
<field name="res_model">agreement.recital</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

41
agreement_legal/views/agreement_renewaltype.xml

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

109
agreement_legal/views/agreement_section.xml

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Sections List View-->
<record model="ir.ui.view" id="partner_agreement_section_list_view">
<field name="name">Agreement Section List</field>
<field name="model">agreement.section</field>
<field name="arch" type="xml">
<tree string="Sections" default_order='agreement_id, sequence'>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="title"/>
<field name="agreement_id"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<!-- Agreement Sections Form View -->
<record model="ir.ui.view" id="partner_agreement_section_form_view">
<field name="name">Agreement Section Form</field>
<field name="model">agreement.section</field>
<field name="arch" type="xml">
<form string="Section">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button" options="{&quot;terminology&quot;: &quot;archive&quot;}"/>
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="title"/>
<field name="agreement_id"/>
</group>
<group>
<field name="sequence"/>
</group>
</group>
<notebook>
<page string="Content">
<field name='content' nolabel="1"/>
<group class="oe_edit_only">
<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="copyvalue"/>
</group>
<p>
This section (on the left) allows you to add dynamic fields inside the content.
<ol>
<li>Select the section field</li>
<li>Select the sub-field</li>
<li>Enter the default value if the field is empty</li>
<li>Copy and paste the placeholder expression in the content</li>
</ol>
</p>
</group>
</page>
<page string="Clauses">
<field name="clauses_ids"
nolabel="1"
context="{'default_section_id': active_id, 'default_agreement_id': agreement_id}">
<tree>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="title"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Agreement Section Search View -->
<record model="ir.ui.view" id="partner_agreement_section_search_view">
<field name="name">Agreement Section Search</field>
<field name="model">agreement.section</field>
<field name="arch" type="xml">
<search string="Agreement Section Search">
<filter name="group_agreement" string="Agreements" icon="terp-partner" context="{'group_by':'agreement_id'}"/>
</search>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_section">
<field name="name">Agreement Sections</field>
<field name="res_model">agreement.section</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

43
agreement_legal/views/agreement_stages.xml

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Stage List View-->
<record model="ir.ui.view" id="partner_agreement_stage_list_view">
<field name="name">Agreement Stage List</field>
<field name="model">agreement.stage</field>
<field name="arch" type="xml">
<tree default_order='sequence, name'>
<field name="sequence" widget="handle"/>
<field name="name" string="Stage Name"/>
</tree>
</field>
</record>
<!-- Agreement Stage Form View -->
<record model="ir.ui.view" id="partner_agreement_stage_form_view">
<field name="name">Agreement Stage Form</field>
<field name="model">agreement.stage</field>
<field name="arch" type="xml">
<form string="Agreements Stage Form">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Stage Name"/>
<h1><field name="name" string="Stage Name"/></h1>
</div>
<group>
<field name="sequence"/>
<field name="fold"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_stage">
<field name="name">Agreement Stage</field>
<field name="res_model">agreement.stage</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

45
agreement_legal/views/agreement_subtype.xml

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Sub Type List View-->
<record model="ir.ui.view" id="partner_agreement_subtype_list_view">
<field name="name">Agreement Subtype List</field>
<field name="model">agreement.subtype</field>
<field name="arch" type="xml">
<tree default_order='name'>
<field name="name" string="Sub-Type Name"/>
<field name="agreement_type_id" string="Agreement Type"/>
</tree>
</field>
</record>
<!-- Agreement Sub Type Form View -->
<record model="ir.ui.view" id="partner_agreement_subtype_form_view">
<field name="name">Agreement Sub Type Form</field>
<field name="model">agreement.subtype</field>
<field name="arch" type="xml">
<form string="Agreement Sub-Types">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<group>
<group>
<field name="agreement_type_id"/>
</group>
<group></group>
</group>
</sheet>
</form>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_subtype">
<field name="name">Agreement Sub-Types</field>
<field name="res_model">agreement.subtype</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

45
agreement_legal/views/agreement_type.xml

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Agreement Type List View-->
<record model="ir.ui.view" id="partner_agreement_type_list_view">
<field name="name">Agreement Type List</field>
<field name="model">agreement.type</field>
<field name="arch" type="xml">
<tree string="Agreement Types" default_order='name'>
<field name="name" string="Type Name"/>
<field name="agreement_subtypes_ids" string="Sub-Types"/>
</tree>
</field>
</record>
<!-- Agreement Type Form View -->
<record model="ir.ui.view" id="partner_agreement_type_form_view">
<field name="name">Agreement Type Form</field>
<field name="model">agreement.type</field>
<field name="arch" type="xml">
<form string="Agreement Type">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
</div>
<field name="agreement_subtypes_ids"
nolabel="1">
<tree editable="bottom">
<field name="name"/>
</tree>
</field>
</sheet>
</form>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_type">
<field name="name">Agreement Types</field>
<field name="res_model">agreement.type</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

147
agreement_legal/views/menu.xml

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Remove top menu from agreement module -->
<!-- <delete model="ir.ui.menu" id="agreement.agreement_menu" /> -->
<!-- Top menu item -->
<menuitem
name="Agreements"
id="agreement.agreement_menu"
web_icon="agreement,static/description/icon.png"
sequence="80"
action="agreement_dashboard_agreement"
groups="agreement_legal.group_agreement_user"/>
<!-- Dashboard -->
<menuitem
name="Dashboard"
id="agreement_dashboard"
parent="agreement.agreement_menu"
sequence="10"/>
<menuitem
name="Agreements"
id="dashboard_agreements"
parent="agreement_dashboard"
sequence="10"
action="agreement_dashboard_agreement"/>
<!-- Operations -->
<menuitem
name="Operations"
id="agreement_operations"
parent="agreement.agreement_menu"
sequence="20"/>
<menuitem
name="Agreements"
id="operations_agreements"
parent="agreement_operations"
sequence="10"
action="agreement_operations_agreement"/>
<!-- Master Data -->
<menuitem
name="Master Data"
id="agreement_masterdata"
parent="agreement.agreement_menu"
sequence="30"/>
<menuitem
name="Contents"
id="agreement_data_contents"
parent="agreement_masterdata"
sequence="10"/>
<menuitem
name="Recitals"
id="agreement_recitals"
parent="agreement_data_contents"
sequence="10"
action="agreement_recital_action"/>
<menuitem
name="Clauses"
id="agreement_clauses"
parent="agreement_data_contents"
sequence="20"
action="partner_agreement_action_clause"/>
<menuitem
name="Sections"
id="agreement_sections"
parent="agreement_data_contents"
sequence="30"
action="partner_agreement_action_section"/>
<menuitem
name="Appendices"
id="agreement_appendices"
parent="agreement_data_contents"
sequence="40"
action="agreement_appendix_action"/>
<menuitem
name="Products"
id="agreement_products"
sequence="100"
parent="agreement_masterdata"
action="product.product_template_action"/>
<!-- Reporting -->
<menuitem
name="Reporting"
id="agreement_reporting"
sequence="40"
parent="agreement.agreement_menu"
groups="agreement_legal.group_agreement_manager"/>
<menuitem
name="Agreements"
id="agreement_agreement_reporting"
sequence="10"
parent="agreement_reporting"
action="action_agreement_report_order"/>
<!-- Configuration -->
<menuitem
name="Configuration"
id="agreement_configuration"
sequence="50"
parent="agreement.agreement_menu"
groups="agreement_legal.group_agreement_manager"/>
<menuitem
name="Settings"
id="agreement_settings"
sequence="10"
parent="agreement_configuration"
action="agreement_legal.action_agreement_config"/>
<menuitem
name="Templates"
id="template"
parent="agreement_configuration"
sequence="20"
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
name="Stages"
id="agreement_stages"
parent="agreement_configuration"
sequence="40"
action="partner_agreement_action_stage"/>
<menuitem
name="Types"
id="agreement_types"
parent="agreement_configuration"
sequence="50"
action="partner_agreement_action_type"/>
<menuitem
name="Sub-Types"
id="agreement_subtypes"
parent="agreement_configuration"
sequence="60"
action="partner_agreement_action_subtype"/>
</odoo>

161
agreement_legal/views/res_config_settings.xml

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.agreement</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="40"/>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<div class="app_settings_block"
data-string="Agreements"
string="Agreements"
data-key="agreement"
groups="agreement_legal.group_agreement_manager">
<h2>Operations</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="group_uom"/>
</div>
<div class="o_setting_right_pane">
<label for="group_uom"/>
<div class="text-muted">
Sell and purchase products in different units of measure
</div>
<div class="content-group">
<div class="mt16" attrs="{'invisible': [('group_uom', '=', False)]}">
<button name="%(uom.product_uom_form_action)d" icon="fa-arrow-right" type="action" string="Units Of Measure" class="btn-link"/>
</div>
</div>
</div>
</div>
</div>
<h2>Advanced Features</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_sale"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Sales"/>
<div class="text-muted">
Create an agreement when the sales order is confirmed
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box"
attrs="{'invisible': [('module_agreement_sale', '!=', True)]}">
<div class="o_setting_left_pane">
<field name="module_agreement_sale_subscription"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Sale Subscriptions"/>
<div class="text-muted">
Link your subscriptions to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_fieldservice_agreement"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Field Service"/>
<div class="text-muted">
Link your Field Service orders and equipments to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_stock"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Inventory"/>
<div class="text-muted">
Link your transfers to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_rma"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Returns"/>
<div class="text-muted">
Link your returns to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_maintenance"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Maintenance"/>
<div class="text-muted">
Manage maintenance agreements and contracts
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_mrp"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Manufacturing"/>
<div class="text-muted">
Link your manufacturing orders to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_repair"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Repair"/>
<div class="text-muted">
Link your repair orders to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_agreement_project"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Project"/>
<div class="text-muted">
Link your projects and tasks to an agreement
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_helpdesk_agreement"/>
</div>
<div class="o_setting_right_pane">
<label for="" string="Helpdesk"/>
<div class="text-muted">
Link your Helpdesk tickets to an agreement
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
<act_window id="action_agreement_config"
name="Settings"
res_model="res.config.settings"
view_mode="form"
target="inline"
context="{'module': 'agreement'}"/>
</odoo>

17
agreement_legal/views/res_partner.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="partner_form">
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='internal_notes']" position="after">
<page name="agreement" string="Agreements">
<group>
<field name="agreement_ids" nolabel="1"/>
</group>
</page>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save