Browse Source

Merge pull request #194 from ursais/11.0-add-agreement

[ADD] agreement
pull/206/head
Maxime Chambreuil 6 years ago
committed by GitHub
parent
commit
8582c36f57
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      agreement/README.rst
  2. 4
      agreement/__init__.py
  3. 43
      agreement/__manifest__.py
  4. 49
      agreement/data/agreement_stage.xml
  5. 13
      agreement/data/ir_sequence.xml
  6. 9
      agreement/data/module_category.xml
  7. 15
      agreement/models/__init__.py
  8. 402
      agreement/models/agreement.py
  9. 80
      agreement/models/agreement_clause.py
  10. 26
      agreement/models/agreement_increasetype.py
  11. 22
      agreement/models/agreement_renewaltype.py
  12. 80
      agreement/models/agreement_section.py
  13. 30
      agreement/models/agreement_stage.py
  14. 15
      agreement/models/agreement_status.py
  15. 19
      agreement/models/agreement_subtype.py
  16. 20
      agreement/models/agreement_type.py
  17. 13
      agreement/models/product_template.py
  18. 8
      agreement/models/res_config_settings.py
  19. 10
      agreement/models/res_partner.py
  20. 6
      agreement/readme/CONFIGURE.rst
  21. 4
      agreement/readme/CONTRIBUTORS.rst
  22. 4
      agreement/readme/CREDITS.rst
  23. 9
      agreement/readme/DESCRIPTION.rst
  24. 3
      agreement/readme/ROADMAP.rst
  25. 7
      agreement/readme/USAGE.rst
  26. 17
      agreement/security/ir.model.access.csv
  27. 19
      agreement/security/res_groups.xml
  28. BIN
      agreement/static/description/icon.png
  29. 329
      agreement/views/agreement.xml
  30. 95
      agreement/views/agreement_clause.xml
  31. 45
      agreement/views/agreement_increasetype.xml
  32. 41
      agreement/views/agreement_renewaltype.xml
  33. 89
      agreement/views/agreement_section.xml
  34. 43
      agreement/views/agreement_stages.xml
  35. 42
      agreement/views/agreement_subtype.xml
  36. 41
      agreement/views/agreement_type.xml
  37. 113
      agreement/views/menu.xml
  38. 52
      agreement/views/reports.xml
  39. 28
      agreement/views/res_config_settings.xml
  40. 17
      agreement/views/res_partner.xml

21
agreement/README.rst

@ -0,0 +1,21 @@
**This file is going to be generated by oca-gen-addon-readme.**
*Manual changes will be overwritten.*
Please provide content in the ``readme`` directory:
* **DESCRIPTION.rst** (required)
* INSTALL.rst (optional)
* CONFIGURE.rst (optional)
* **USAGE.rst** (optional, highly recommended)
* DEVELOP.rst (optional)
* ROADMAP.rst (optional)
* HISTORY.rst (optional, recommended)
* **CONTRIBUTORS.rst** (optional, highly recommended)
* CREDITS.rst (optional)
Content of this README will also be drawn from the addon manifest,
from keys such as name, authors, maintainers, development_status,
and license.
A good, one sentence summary in the manifest is also highly recommended.

4
agreement/__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

43
agreement/__manifest__.py

@ -0,0 +1,43 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Agreements',
'summary': 'Manage Agreements, LOI and Contracts',
'author': 'Pavlov Media, '
'Open Source Integrators, '
'Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/contract',
'category': 'Partner',
'license': 'AGPL-3',
'version': '11.0.0.0.1',
'depends': [
'account',
'contacts',
'mail',
'product',
'sale_management',
],
'data': [
'data/ir_sequence.xml',
'data/module_category.xml',
'data/agreement_stage.xml',
'security/res_groups.xml',
'security/ir.model.access.csv',
'views/res_config_settings.xml',
'views/reports.xml',
'views/agreement.xml',
'views/agreement_clause.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/menu.xml',
],
'application': True,
'development_status': 'Beta',
'maintainers': 'max3903',
}

49
agreement/data/agreement_stage.xml

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<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>

13
agreement/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/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>

15
agreement/models/__init__.py

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

402
agreement/models/agreement.py

@ -0,0 +1,402 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models, fields, _
class Agreement(models.Model):
_name = 'agreement'
_inherit = ['mail.thread']
def _default_stage_id(self):
return self.env.ref('agreement.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"
)
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="Company Signed Date",
track_visibility='onchange',
help="Date the contract was signed by Company."
)
customer_signed_date = fields.Date(
string="Customer Signed Date",
track_visibility='onchange',
help="Date the contract was signed by Customer."
)
customer_term = fields.Integer(
string="Customer Term (Months)",
track_visibility='onchange',
help="Number of months this agreement/contract is in effect with "
"customer."
)
vendor_term = fields.Integer(
string="Vendor Term (Months)",
track_visibility='onchange',
help="Number of months this agreement/contract is in effect with "
"vendor."
)
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."
)
contract_value = fields.Monetary(
compute='_compute_contract_value',
string="Contract Value",
help="Total value of the contract over ther entire term.",
store=True
)
reference = fields.Char(
string="Reference",
required=True,
default=lambda self: _('New'),
track_visibility='onchange',
help="ID used for internal contract tracking.")
total_company_mrc = fields.Monetary(
'Company MRC',
currency_field='currency_id',
help="Total company monthly recurring costs."
)
total_customer_mrc = fields.Monetary(
'Customer MRC',
currency_field='currency_id',
help="Total custemer monthly recurring costs."
)
total_company_nrc = fields.Monetary(
'Company NRC',
currency_field='currency_id',
help="Total company non-recurring costs."
)
total_customer_nrc = fields.Monetary(
'Customer NRC',
currency_field='currency_id',
help="Total custemer non-monthly recurring costs."
)
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'
)
customer_id = fields.Many2one(
'res.partner',
string="Customer",
copy=True,
help="The customer this agreement is related to (If Applicable)."
)
vendor_id = fields.Many2one(
'res.partner',
string="Vendor",
copy=True,
help="The vendor this agreement is related to (If Applicable)."
)
customer_contact_id = fields.Many2one(
'res.partner',
string="Customer Contact",
copy=True,
help="The primary customer contact (If Applicable)."
)
customer_contact_phone = fields.Char(
related='customer_contact_id.phone',
string="Phone"
)
customer_contact_email = fields.Char(
related='customer_contact_id.email',
string="Email"
)
vendor_contact_id = fields.Many2one(
'res.partner',
string="Vendor Contact",
copy=True,
help="The primary vendor contact (If Applicable)."
)
vendor_contact_phone = fields.Char(
related='vendor_contact_id.phone',
string="Phone"
)
vendor_contact_email = fields.Char(
related='vendor_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")
sale_order_id = fields.Many2one(
'sale.order',
string="Sales Order",
track_visibility='onchange',
copy=False,
help="Select the Sales Order that this agreement is related to."
)
payment_term_id = fields.Many2one(
'account.payment.term',
string="Payment Term",
track_visibility='onchange',
help="Terms of payments."
)
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="Company Signed By",
track_visibility='onchange',
help="The user at our company who authorized/signed the agreement or "
"contract."
)
customer_signed_user_id = fields.Many2one(
'res.partner',
string="Customer 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."
)
order_lines_services_ids = fields.One2many(
related='sale_order_id.order_line',
string="Service Order Lines",
copy=False
)
sections_ids = fields.One2many(
'agreement.section',
'agreement_id',
string="Sections",
copy=True
)
clauses_ids = fields.One2many(
'agreement.clause',
'agreement_id',
string="Clauses",
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)]
)
products_ids = fields.Many2many(
'product.template',
string="Products",
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'
)
# compute contract_value field
@api.depends('total_customer_mrc', 'total_customer_nrc', 'customer_term')
def _compute_contract_value(self):
for record in self:
record.contract_value =\
(record.total_customer_mrc * record.customer_term) +\
record.total_customer_nrc
# compute total_company_mrc field
@api.depends('order_lines_services_ids', 'sale_order_id')
def _compute_company_mrc(self):
order_lines = self.env['sale.order.line'].search(
[('is_service', '=', True)])
amount_total = sum(order_lines.mapped('purchase_price'))
for record in self:
record.total_company_mrc = amount_total
# 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': '{0} - 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)

80
agreement/models/agreement_clause.py

@ -0,0 +1,80 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
# Main Agreement clause Records Model
class AgreementClause(models.Model):
_name = 'agreement.clause'
_order = 'clause_sequence'
# General
name = fields.Char(
string="Title",
required=True
)
clause_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"
)
active = fields.Boolean(
string="Active",
default=True,
help="If unchecked, it will allow you to hide the agreement without "
"removing it."
)
# Placeholder fields
model_id = fields.Many2one(
'ir.model',
string="Applies to",
help="The type of document this template can be used with."
)
model_object_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)."
)
null_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.model
def create(self, vals):
seq = self.env['ir.sequence'].next_by_code('agreement.clause') or '/'
vals['clause_sequence'] = seq
return super(AgreementClause, self).create(vals)

26
agreement/models/agreement_increasetype.py

@ -0,0 +1,26 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
# Main Agreement Increase Type Records Model
class AgreementIncreaseType(models.Model):
_name = 'agreement.increasetype'
# 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."
)

22
agreement/models/agreement_renewaltype.py

@ -0,0 +1,22 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
# Main Agreement Section Records Model
class AgreementRenewalType(models.Model):
_name = 'agreement.renewaltype'
# 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."
)

80
agreement/models/agreement_section.py

@ -0,0 +1,80 @@
# Copyright (C) 2018 - TODAY, Pavlov Media
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
# Main Agreement Section Records Model
class AgreementSection(models.Model):
_name = 'agreement.section'
_order = 'section_sequence'
# General
name = fields.Char(
string="Title",
required=True
)
section_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"
)
active = fields.Boolean(
string="Active",
default=True,
help="If unchecked, it will allow you to hide the agreement without "
"removing it."
)
# Placeholder fields
model_id = fields.Many2one(
'ir.model',
string="Applies to",
help="The type of document this template can be used with."
)
model_object_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)."
)
null_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.model
def create(self, vals):
seq = self.env['ir.sequence'].next_by_code('agreement.section') or '/'
vals['section_sequence'] = seq
return super(AgreementSection, self).create(vals)

30
agreement/models/agreement_stage.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 models, fields
# Main Agreement Section Records Model
class AgreementStage(models.Model):
_name = 'agreement.stage'
_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."
)

15
agreement/models/agreement_status.py

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

19
agreement/models/agreement_subtype.py

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

20
agreement/models/agreement_type.py

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

13
agreement/models/product_template.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 models, fields
class Product(models.Model):
_inherit = 'product.template'
agreements_ids = fields.Many2many(
'agreement',
string="Agreements"
)

8
agreement/models/res_config_settings.py

@ -0,0 +1,8 @@
# Copyright (C) 2018 - TODAY, Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

10
agreement/models/res_partner.py

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

6
agreement/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

4
agreement/readme/CONTRIBUTORS.rst

@ -0,0 +1,4 @@
* Patrick Wilson <pwilson@pavlovmedia.com>
* Bhavesh Odedra <bodedra@opensourceintegrators.com>
* Wolfgang Hall <whall@opensourceintegrators.com>
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>

4
agreement/readme/CREDITS.rst

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

9
agreement/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/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/readme/USAGE.rst

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

17
agreement/security/ir.model.access.csv

@ -0,0 +1,17 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_agreement_allusers,agreement all users,model_agreement,agreement.group_agreement_user,1,1,1,0
access_agreement_allusers,agreement all users,model_agreement,agreement.group_agreement_manager,1,1,1,1
access_agreement_section_allusers,section all users,model_agreement_section,agreement.group_agreement_user,1,1,1,0
access_agreement_section_allusers,section all users,model_agreement_section,agreement.group_agreement_manager,1,1,1,1
access_agreement_clause_allusers,clause all users,model_agreement_clause,agreement.group_agreement_user,1,1,1,0
access_agreement_clause_allusers,clause all users,model_agreement_clause,agreement.group_agreement_manager,1,1,1,1
access_agreement_stage_allusers,stage all users,model_agreement_stage,agreement.group_agreement_user,1,0,0,0
access_agreement_stage_allusers,stage all users,model_agreement_stage,agreement.group_agreement_manager,1,1,1,1
access_agreement_type_allusers,type all users,model_agreement_type,agreement.group_agreement_user,1,0,0,0
access_agreement_type_allusers,type all users,model_agreement_type,agreement.group_agreement_manager,1,1,1,1
access_agreement_subtype_allusers,subtype all users,model_agreement_subtype,agreement.group_agreement_user,1,0,0,0
access_agreement_subtype_allusers,subtype all users,model_agreement_subtype,agreement.group_agreement_manager,1,1,1,1
access_agreement_renewaltype_allusers,renewaltype all users,model_agreement_renewaltype,agreement.group_agreement_user,1,0,0,0
access_agreement_renewaltype_allusers,renewaltype all users,model_agreement_renewaltype,agreement.group_agreement_manager,1,1,1,1
access_agreement_increasetype_allusers,increasetype all users,model_agreement_increasetype,agreement.group_agreement_user,1,0,0,0
access_agreement_increasetype_allusers,increasetype all users,model_agreement_increasetype,agreement.group_agreement_manager,1,1,1,1

19
agreement/security/res_groups.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- User group -->
<record id="group_agreement_user" model="res.groups">
<field name="name">User</field>
<field name="category_id" ref="agreement"/>
<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="agreement"/>
<field name="implied_ids" eval="[(4, ref('group_agreement_user'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</odoo>

BIN
agreement/static/description/icon.png

After

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

329
agreement/views/agreement.xml

@ -0,0 +1,329 @@
<?xml version="1.0"?>
<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 default_order='name'>
<field name="name"/>
<field name="customer_id"/>
<field name="vendor_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_title">
<label for="name" class="oe_edit_only" string="Agreement Name"/>
<h1>
<field name="name"/>
</h1>
</div>
<group string="General">
<group>
<field name="reference" readonly="1"/>
<field name="parent_agreement_id"
domain="[('customer_id', '=', customer_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 name="parties" string="Parties">
<group name="customer_left"
string="Customer">
<div class="o_address_format">
<field name="customer_id"
domain="[('customer', '=', True)]"
context="{'show_address': 1}"
options="{&quot;always_reload&quot;: True}"/>
</div>
</group>
<group name="vendor_right"
string="Vendor">
<div class="o_address_format">
<field name="vendor_id"
domain="[('supplier', '=', True)]"
context="{'show_address': 1}"
options="{&quot;always_reload&quot;: True}"/>
</div>
</group>
<group name="contact_left" string="Primary Contact">
<field name="customer_contact_id" domain="[('parent_id', '=', customer_id)]" nolabel="1"/>
<field name="customer_contact_phone" widget="phone" readonly="1" nolabel="1"/>
<field name="customer_contact_email" widget="email" readonly="1" nolabel="1"/>
</group>
<group name="contact_right" string="Primary Contact">
<field name="vendor_contact_id" domain="[('parent_id', '=', vendor_id)]" nolabel="1"/>
<field name="vendor_contact_phone" widget="phone" readonly="1" nolabel="1"/>
<field name="vendor_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" required="True" attrs="{'required': [('is_template', '=', False)], 'readonly':[('is_template', '=', True)]}"/>
<field name="end_date" required="True" attrs="{'required': [('is_template', '=', False)], 'readonly':[('is_template', '=', True)]}"/>
<field name="expiration_notice"/>
<field name="change_notice"/>
<field name="notification_address_id" domain="['|',('parent_id','=',customer_id),('parent_id','=',vendor_id)]"/>
<field name="termination_requested"/>
<field name="termination_date"/>
</group>
<group name="paymentterm_right" string="Payment Terms">
<field name="customer_term" attrs="{'invisible': [('customer_id', '=', False)]}"/>
<field name="vendor_term" attrs="{'invisible': [('vendor_id', '=', False)]}"/>
<field name="payment_term_id" widget="selection"/>
<field name="renewal_type_id" widget="selection"/>
<field name="increase_type_id" widget="selection"/>
</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>
<group string="Sections" default_order='section_sequence'>
<field name="sections_ids"
nolabel="1"
context="{'default_agreement': active_id}">
<tree default_order='section_sequence'>
<field name="section_sequence" widget="handle"/>
<field name="name"/>
</tree>
</field>
</group>
<group string="Clauses" default_order='section_id, clause_sequence'>
<field name="clauses_ids"
nolabel="1"
context="{'default_agreement': active_id}">
<tree default_order='section_id, clause_sequence'>
<field name="clause_sequence" widget="handle"/>
<field name="section_id"/>
<field name="name"/>
</tree>
</field>
</group>
</page>
<page name="signature" string="Signatures">
<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 string="Customer">
<field name="customer_signed_date"/>
<field name="customer_signed_user_id" domain="[('parent_id', '=', customer_id)]"/>
</group>
</group>
</page>
<page name="products" string="Products/Services">
<group>
<field name="product_ids" nolabel="1"/>
</group>
</page>
<page name="costs" string="Costs">
<group string="Financial Details">
<group string="Company">
<field name="total_company_mrc"/>
<field name="total_company_nrc"/>
<field name="currency_id"/>
<field name="contract_value" readonly="1"/>
</group>
<group string="Customer">
<field name="total_customer_mrc"/>
<field name="total_customer_nrc"/>
</group>
</group>
</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="peformance" 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="customer_id" invisible="context.get('default_customer_id', False)"/>
<t t-if="record.start_date.raw_value and record.start_date.raw_value lt (new Date())" t-set="red">oe_kanban_text_red</t>
<div t-attf-class="#{red || ''}">
<i><field name="start_date"/></i>
</div>
</div>
</div>
<div class="o_dropdown_kanban dropdown" groups="base.group_user">
<a 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"/>
</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">
<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_customer_id" string="customers" icon="terp-partner" context="{'group_by':'customer_id'}"/>
<filter name="group_status" string="Status" icon="terp-partner" context="{'group_by':'state'}"/>
</search>
</field>
</record>
<!-- Adding a new filter to the order line search view -->
<record id="order_lines_search_view" model="ir.ui.view">
<field name="name">Order Lines Search</field>
<field name="model">sale.order.line</field>
<field name="type">search</field>
<field name="inherit_id" ref="sale.view_sales_order_line_filter"/>
<field name="arch" type="xml">
<xpath expr="/search/filter[1]" position="after">
<filter name="filter_service_product_type" string="Service Type" domain="[('type', '=', 'service')]"/>
</xpath>
</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="view_mode">tree,kanban,form</field>
</record>
</odoo>

95
agreement/views/agreement_clause.xml

@ -0,0 +1,95 @@
<?xml version="1.0"?>
<odoo>
<!-- Agreement Clauses Sequences-->
<record id="seq_agreement_clause" model="ir.sequence">
<field name="name">agreement_clause_sequencer</field>
<field name="code">agreement.clause</field>
<field name="prefix">0</field>
<field name="padding">1</field>
</record>
<!-- 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 default_order='agreement_id, clause_sequence'>
<field name="clause_sequence" widget="handle"/>
<field name="agreement_id"/>
<field name="name"/>
<field name="section_id"/>
<field name="content" widget="html"/>
<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="Agreements Clause Form">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Clause Name"/>
<h1><field name="name"/></h1>
</div>
<group>
<field name="agreement_id"/>
<field name="section_id" domain="[('agreement_id', '=', agreement_id)]"/>
<field name="content" widget="html"/>
</group>
<notebook>
<page string="Dynamic Placeholder Generator">
THIS IS UNDER DEVELOPEMENT: The purpose of this section is to be able to create dynamic fields inside your content.
<group>
<field name="model_id"/>
<field name="model_object_field_id" domain="[('model_id','=',model_id),('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="null_value"/>
<field name="copyvalue"/>
</group>
</page>
</notebook>
Sequence #<field name="clause_sequence"/>
</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>
<!-- Agreement Clause Pivot View -->
<record model="ir.ui.view" id="agreement_clause_pivot_view">
<field name="name">Agreement Clause Pivot</field>
<field name="model">agreement.clause</field>
<field name="arch" type="xml">
<pivot string="Agreement Clause Pivot">
<field name="agreement_id" type="row"/>
<field name="section_id" type="row"/>
<field name="name" type="row"/>
</pivot>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_clause">
<field name="name">Agreement Clauses</field>
<field name="res_model">agreement.clause</field>
<field name="view_mode">tree,pivot,form</field>
</record>
</odoo>

45
agreement/views/agreement_increasetype.xml

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<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>

41
agreement/views/agreement_renewaltype.xml

@ -0,0 +1,41 @@
<?xml version="1.0"?>
<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>

89
agreement/views/agreement_section.xml

@ -0,0 +1,89 @@
<?xml version="1.0"?>
<odoo>
<!-- Agreement Sections Sequences-->
<record id="seq_agreement_section" model="ir.sequence">
<field name="name">agreement_section_sequencer</field>
<field name="code">agreement.section</field>
<field name="prefix">0</field>
<field name="padding">1</field>
</record>
<!-- 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 default_order='agreement_id, section_sequence'>
<field name="agreement_id" string="Agreement"/>
<field name="section_sequence" string="Sequence"/>
<field name="name" string="Section Name"/>
<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="Agreements Section Form">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Section Name"/>
<h1><field name="name" string="Section Name"/></h1>
</div>
<group>
<field name="agreement_id" string="Agreement"/>
</group>
<group>
<field name='content' string="Content"/>
</group>
<notebook>
<page string="Clauses">
<field name="clauses_ids" string="Clauses" context="{'default_section_id': active_id,'default_agreement_id': agreement_id}">
<tree>
<field name="clause_sequence" widget="handle"/>
<field name="name"/>
<field name="content"/>
</tree>
</field>
</page>
<page string="Dynamic Placeholder Generator">
THIS IS UNDER DEVELOPEMENT: The purpose of this section is to be able to create dynamic fields inside your content.
<group>
<field name="model_id"/>
<field name="model_object_field_id" domain="[('model_id','=',model_id),('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="null_value"/>
<field name="copyvalue"/>
</group>
</page>
</notebook>
Sequence #<field name="section_sequence" readonly="1"/>
</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/views/agreement_stages.xml

@ -0,0 +1,43 @@
<?xml version="1.0"?>
<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>

42
agreement/views/agreement_subtype.xml

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<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>
<group>
<field name="name"/>
</group>
<group>
<field name="agreement_type_id"
required="True"/>
</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>

41
agreement/views/agreement_type.xml

@ -0,0 +1,41 @@
<?xml version="1.0"?>
<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 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="Agreements Type Form">
<sheet>
<group>
<field name="name"/>
</group>
<group string="Sub-Types">
<field name="agreement_subtypes_ids" nolabel="1"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Actions opening views on models -->
<record model="ir.actions.act_window" id="partner_agreement_action_type">
<field name="name">Agreement Type</field>
<field name="res_model">agreement.type</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

113
agreement/views/menu.xml

@ -0,0 +1,113 @@
<?xml version="1.0"?>
<odoo>
<!-- Top menu item -->
<menuitem
name="Agreements"
id="agreement_root"
web_icon="agreement,static/description/icon.png"
sequence="80"
groups="agreement.group_agreement_user"/>
<!-- Dashboard -->
<menuitem
name="Dashboard"
id="agreement_dashboard"
parent="agreement_root"
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_root"
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_root"
sequence="30"/>
<menuitem
name="Parts"
id="agreement_parts"
sequence="10"
parent="agreement_masterdata"/>
<menuitem
name="Clauses"
id="agreement_clauses"
parent="agreement_masterdata"
sequence="20"
action="partner_agreement_action_clause"/>
<menuitem
name="Sections"
id="agreement_sections"
parent="agreement_masterdata"
sequence="30"
action="partner_agreement_action_section"/>
<!-- Reporting -->
<menuitem
name="Reporting"
id="agreement_reporting"
sequence="40"
parent="agreement_root"
groups="agreement.group_agreement_manager"/>
<!-- Configuration -->
<menuitem
name="Configuration"
id="agreement_configuration"
sequence="50"
parent="agreement_root"
groups="agreement.group_agreement_manager"/>
<menuitem
name="Settings"
id="agreement_settings"
sequence="10"
parent="agreement_configuration"
action="agreement.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="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>

52
agreement/views/reports.xml

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<odoo>
<report
id="partner_agreement_contract_document"
model="agreement"
string="Contract Document"
name="agreement.report_agreement_document"
file="agreement.report_agreement_document"
report_type="qweb-pdf"/>
<report
id="partner_agreement_contract_document_preview"
model="agreement"
string="Contract Document Preview"
name="agreement.report_agreement_document"
file="agreement.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"/>
<h2>Parties</h2>
<h3>Company Information</h3>
<h3>Customer Information</h3>
<table class="table table-condensed">
<tbody class="section_tbody">
<tr t-foreach="doc.sections_ids" t-as="s">
<h2 t-field="s.name"/>
<span t-field="s.content"/>
<table class="table table-condensed">
<tbody class="clause_tbody">
<tr t-foreach="s.clauses_ids" t-as="c">
<h3 style="padding:20px" t-field="c.name"/>
<h4 style="padding:20px" t-field="c.content"/>
</tr>
</tbody>
</table>
</tr>
</tbody>
</table>
</div>
</t>
</t>
</t>
</t>
</template>
</odoo>

28
agreement/views/res_config_settings.xml

@ -0,0 +1,28 @@
<?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.group_agreement_manager">
</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/views/res_partner.xml

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<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