Browse Source

[REF] Contract: split from analytic account

pull/207/head
Thomas Binsfeld 5 years ago
committed by sbejaoui
parent
commit
da7826797c
  1. 10
      contract/__manifest__.py
  2. 4
      contract/data/contract_cron.xml
  3. 2
      contract/data/contract_renew_cron.xml
  4. 2
      contract/data/mail_template.xml
  5. 145
      contract/migrations/12.0.4.0.0/post-migration.py
  6. 72
      contract/migrations/12.0.4.0.0/pre-migration.py
  7. 6
      contract/models/abstract_contract.py
  8. 6
      contract/models/abstract_contract_line.py
  9. 2
      contract/models/account_invoice.py
  10. 2
      contract/models/account_invoice_line.py
  11. 76
      contract/models/contract.py
  12. 42
      contract/models/contract_line.py
  13. 15
      contract/models/contract_template.py
  14. 10
      contract/models/contract_template_line.py
  15. 6
      contract/models/res_partner.py
  16. 2
      contract/report/contract_views.xml
  17. 2
      contract/report/report_contract.xml
  18. 2
      contract/security/contract_security.xml
  19. 14
      contract/security/ir.model.access.csv
  20. 109
      contract/tests/test_contract.py
  21. 12
      contract/views/abstract_contract_line.xml
  22. 166
      contract/views/contract.xml
  23. 79
      contract/views/contract_line.xml
  24. 42
      contract/views/contract_template.xml
  25. 16
      contract/views/contract_template_line.xml
  26. 6
      contract/wizards/contract_line_wizard.py
  27. 8
      contract/wizards/contract_line_wizard.xml

10
contract/__manifest__.py

@ -9,7 +9,7 @@
{
'name': 'Recurring - Contracts Management',
'version': '12.0.3.0.1',
'version': '12.0.4.0.0',
'category': 'Contract Management',
'license': 'AGPL-3',
'author': "OpenERP SA, "
@ -18,10 +18,9 @@
"ACSONE SA/NV, "
"Odoo Community Association (OCA)",
'website': 'https://github.com/oca/contract',
'depends': ['base', 'account', 'analytic', 'product'],
'depends': ['base', 'account', 'product'],
"external_dependencies": {"python": ["dateutil"]},
'data': [
'wizards/contract_line_wizard.xml',
'security/ir.model.access.csv',
'security/contract_security.xml',
'report/report_contract.xml',
@ -29,11 +28,12 @@
'data/contract_cron.xml',
'data/contract_renew_cron.xml',
'data/mail_template.xml',
'wizards/contract_line_wizard.xml',
'views/abstract_contract_line.xml',
'views/contract.xml',
'views/contract_template_line.xml',
'views/contract_template.xml',
'views/contract_line.xml',
'views/contract_template.xml',
'views/contract_template_line.xml',
'views/res_partner_view.xml',
],
'installable': True,

4
contract/data/contract_cron.xml

@ -1,9 +1,9 @@
<?xml version="1.0" encoding='UTF-8'?>
<odoo noupdate="1">
<record model="ir.cron" id="account_analytic_cron_for_invoice">
<record model="ir.cron" id="contract_cron_for_invoice">
<field name="name">Generate Recurring Invoices from Contracts</field>
<field name="model_id" ref="analytic.model_account_analytic_account"/>
<field name="model_id" ref="model_contract_contract"/>
<field name="state">code</field>
<field name="code">model.cron_recurring_create_invoice()</field>
<field name="user_id" ref="base.user_root" />

2
contract/data/contract_renew_cron.xml

@ -3,7 +3,7 @@
<record model="ir.cron" id="contract_line_cron_for_renew">
<field name="name">Renew Contract lines</field>
<field name="model_id" ref="model_account_analytic_invoice_line"/>
<field name="model_id" ref="model_contract_line"/>
<field name="state">code</field>
<field name="code">model.cron_renew_contract_line()</field>
<field name="user_id" ref="base.user_root" />

2
contract/data/mail_template.xml

@ -6,7 +6,7 @@
<field name="email_from">${(object.user_id.email and '%s &lt;%s&gt;' % (object.user_id.name, object.user_id.email) or '')|safe}</field>
<field name="subject">${object.company_id.name} Contract (Ref ${object.name or 'n/a'})</field>
<field name="partner_to">${object.partner_id.id}</field>
<field name="model_id" ref="contract.model_account_analytic_account"/>
<field name="model_id" ref="model_contract_contract"/>
<field name="auto_delete" eval="True"/>
<field name="report_template" ref="contract.report_contract"/>
<field name="report_name">Contract</field>

145
contract/migrations/12.0.4.0.0/post-migration.py

@ -0,0 +1,145 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from openupgradelib import openupgrade
_logger = logging.getLogger(__name__)
def migrate(cr, version):
cr.execute(
"""
INSERT INTO contract_contract (
id,
name,
partner_id,
pricelist_id,
contract_type,
journal_id,
company_id,
analytic_account_id,
active,
code,
group_id,
contract_template_id,
recurring_invoices,
user_id,
recurring_next_date,
date_end,
payment_term_id,
fiscal_position_id,
invoice_partner_id,
message_main_attachment_id,
create_uid,
create_date,
write_uid,
write_date
)
SELECT id,
name,
partner_id,
pricelist_id,
contract_type,
journal_id,
company_id,
id,
active,
code,
group_id,
contract_template_id,
recurring_invoices,
user_id,
recurring_next_date,
date_end,
payment_term_id,
fiscal_position_id,
invoice_partner_id,
message_main_attachment_id,
create_uid,
create_date,
write_uid,
write_date
FROM account_analytic_account
WHERE recurring_invoices = TRUE
"""
)
cr.execute(
"""
INSERT INTO contract_line (
id,
product_id,
name,
quantity,
uom_id,
automatic_price,
specific_price,
discount,
recurring_rule_type,
recurring_invoicing_type,
recurring_interval,
sequence,
contract_id,
date_start,
date_end,
recurring_next_date,
last_date_invoiced,
termination_notice_date,
successor_contract_line_id,
predecessor_contract_line_id,
manual_renew_needed,
active,
create_uid,
create_date,
write_uid,
write_date
)
SELECT id,
product_id,
name,
quantity,
uom_id,
automatic_price,
specific_price,
discount,
recurring_rule_type,
recurring_invoicing_type,
recurring_interval,
sequence,
contract_id,
date_start,
date_end,
recurring_next_date,
last_date_invoiced,
termination_notice_date,
successor_contract_line_id,
predecessor_contract_line_id,
manual_renew_needed,
active,
create_uid,
create_date,
write_uid,
write_date
FROM account_analytic_invoice_line
"""
)
openupgrade.rename_models(cr, [('account.analytic.invoice.line',
'contract.line')])
cr.execute(
"""
DROP TABLE account_analytic_invoice_line
"""
)
cr.execute(
"""
UPDATE account_invoice_line
SET contract_line_id = contract_line_id_tmp
"""
)
cr.execute(
"""
ALTER TABLE account_invoice_line
DROP COLUMN contract_line_id_tmp
"""
)

72
contract/migrations/12.0.4.0.0/pre-migration.py

@ -0,0 +1,72 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from openupgradelib import openupgrade
_logger = logging.getLogger(__name__)
def migrate(cr, version):
models_to_rename = [
# Contract Line Wizard
('account.analytic.invoice.line.wizard', 'contract.line.wizard'),
# Abstract Contract
('account.abstract.analytic.contract', 'contract.abstract.contract'),
# Abstract Contract Line
('account.abstract.analytic.contract.line',
'contract.abstract.contract.line'),
# Contract Line
('account.analytic.invoice.line', 'contract.line'),
# Contract Template
('account.analytic.contract', 'contract.template'),
# Contract Template Line
('account.analytic.contract.line', 'contract.template.line'),
]
tables_to_rename = [
# Contract Line Wizard
('account_analytic_invoice_line_wizard', 'contract_line_wizard'),
# Contract Template
('account_analytic_contract', 'contract_template'),
# Contract Template Line
('account_analytic_contract_line', 'contract_template_line'),
]
xmlids_to_rename = [
('contract.account_analytic_cron_for_invoice',
'contract.contract_cron_for_invoice'),
('contract.account_analytic_contract_manager',
'contract.contract_template_manager'),
('contract.account_analytic_contract_user',
'contract.contract_template_user'),
('contract.account_analytic_invoice_line_manager',
'contract.contract_line_manager'),
('contract.account_analytic_invoice_line_user',
'contract.contract_line_user'),
('contract.account_analytic_contract_line_manager',
'contract.contract_template_line_manager'),
('contract.account_analytic_contract_line_user',
'contract.contract_template_line_user'),
]
openupgrade.rename_models(cr, models_to_rename)
openupgrade.rename_tables(cr, tables_to_rename)
openupgrade.rename_xmlids(cr, xmlids_to_rename)
# A temporary column is needed to avoid breaking the foreign key constraint
# The temporary column is dropped in the post-migration script
cr.execute(
"""
ALTER TABLE account_invoice_line
ADD COLUMN contract_line_id_tmp INTEGER
"""
)
cr.execute(
"""
UPDATE account_invoice_line
SET contract_line_id_tmp = contract_line_id
"""
)
cr.execute(
"""
UPDATE account_invoice_line SET contract_line_id = NULL
"""
)

6
contract/models/abstract_contract.py

@ -9,8 +9,8 @@
from odoo import api, models, fields
class AbstractAccountAnalyticContract(models.AbstractModel):
_name = 'account.abstract.analytic.contract'
class ContractAbstractContract(models.AbstractModel):
_name = 'contract.abstract.contract'
_description = 'Abstract Recurring Contract'
# These fields will not be synced to the contract
@ -50,7 +50,7 @@ class AbstractAccountAnalyticContract(models.AbstractModel):
@api.onchange('contract_type')
def _onchange_contract_type(self):
if self.contract_type == 'purchase':
self.recurring_invoice_line_ids.filtered('automatic_price').update(
self.contract_line_ids.filtered('automatic_price').update(
{'automatic_price': False}
)
self.journal_id = self.env['account.journal'].search(

6
contract/models/abstract_contract_line.py

@ -12,8 +12,8 @@ from odoo.exceptions import ValidationError
from odoo.tools.translate import _
class AccountAbstractAnalyticContractLine(models.AbstractModel):
_name = 'account.abstract.analytic.contract.line'
class ContractAbstractContractLine(models.AbstractModel):
_name = 'contract.abstract.contract.line'
_description = 'Abstract Recurring Contract Line'
product_id = fields.Many2one(
@ -110,7 +110,7 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
)
contract_id = fields.Many2one(
string='Contract',
comodel_name='account.abstract.analytic.contract',
comodel_name='contract.abstract.contract',
required=True,
ondelete='cascade',
oldname='analytic_account_id',

2
contract/models/account_invoice.py

@ -9,5 +9,5 @@ class AccountInvoice(models.Model):
# We keep this field for migration purpose
old_contract_id = fields.Many2one(
'account.analytic.account', oldname="contract_id"
'contract.contract', oldname="contract_id"
)

2
contract/models/account_invoice_line.py

@ -8,5 +8,5 @@ class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
contract_line_id = fields.Many2one(
'account.analytic.invoice.line', string='Contract Line', index=True
'contract.line', string='Contract Line', index=True
)

76
contract/models/contract.py

@ -11,21 +11,39 @@ from odoo.exceptions import ValidationError
from odoo.tools.translate import _
class AccountAnalyticAccount(models.Model):
_name = 'account.analytic.account'
_inherit = [
'account.analytic.account',
'account.abstract.analytic.contract',
]
class ContractContract(models.Model):
_name = 'contract.contract'
_inherit = ['mail.thread', 'contract.abstract.contract']
active = fields.Boolean(
default=True,
)
code = fields.Char(
string="Reference",
)
group_id = fields.Many2one(
string="Group",
comodel_name='account.analytic.account',
ondelete='restrict',
)
analytic_account_id = fields.Many2one(
string="Analytic account",
comodel_name='account.analytic.account',
)
currency_id = fields.Many2one(
related="company_id.currency_id",
string="Currency",
readonly=True,
)
contract_template_id = fields.Many2one(
string='Contract Template', comodel_name='account.analytic.contract'
string='Contract Template', comodel_name='contract.template'
)
recurring_invoice_line_ids = fields.One2many(
string='Invoice Lines',
comodel_name='account.analytic.invoice.line',
contract_line_ids = fields.One2many(
string='Contract lines',
comodel_name='contract.line',
inverse_name='contract_id',
copy=True,
oldnae='contract_line_ids',
)
recurring_invoices = fields.Boolean(
string='Generate recurring invoices automatically'
@ -84,7 +102,7 @@ class AccountAnalyticAccount(models.Model):
(
'contract_line_id',
'in',
self.recurring_invoice_line_ids.ids,
self.contract_line_ids.ids,
)
]
)
@ -127,31 +145,31 @@ class AccountAnalyticAccount(models.Model):
action['views'] = [(tree_view.id, 'tree'), (form_view.id, 'form')]
return action
@api.depends('recurring_invoice_line_ids.date_end')
@api.depends('contract_line_ids.date_end')
def _compute_date_end(self):
for contract in self:
contract.date_end = False
date_end = contract.recurring_invoice_line_ids.mapped('date_end')
date_end = contract.contract_line_ids.mapped('date_end')
if date_end and all(date_end):
contract.date_end = max(date_end)
@api.depends(
'recurring_invoice_line_ids.recurring_next_date',
'recurring_invoice_line_ids.is_canceled',
'contract_line_ids.recurring_next_date',
'contract_line_ids.is_canceled',
)
def _compute_recurring_next_date(self):
for contract in self:
recurring_next_date = contract.recurring_invoice_line_ids.filtered(
recurring_next_date = contract.contract_line_ids.filtered(
lambda l: l.recurring_next_date and not l.is_canceled
).mapped('recurring_next_date')
if recurring_next_date:
contract.recurring_next_date = min(recurring_next_date)
@api.depends('recurring_invoice_line_ids.create_invoice_visibility')
@api.depends('contract_line_ids.create_invoice_visibility')
def _compute_create_invoice_visibility(self):
for contract in self:
contract.create_invoice_visibility = any(
contract.recurring_invoice_line_ids.mapped(
contract.contract_line_ids.mapped(
'create_invoice_visibility'
)
)
@ -160,7 +178,7 @@ class AccountAnalyticAccount(models.Model):
def _onchange_contract_template_id(self):
"""Update the contract fields with that of the template.
Take special consideration with the `recurring_invoice_line_ids`,
Take special consideration with the `contract_line_ids`,
which must be created using the data from the contract lines. Cascade
deletion ensures that any errant lines that are created are also
deleted.
@ -169,9 +187,9 @@ class AccountAnalyticAccount(models.Model):
if not contract_template_id:
return
for field_name, field in contract_template_id._fields.items():
if field.name == 'recurring_invoice_line_ids':
if field.name == 'contract_line_ids':
lines = self._convert_contract_lines(contract_template_id)
self.recurring_invoice_line_ids += lines
self.contract_line_ids += lines
elif not any(
(
field.compute,
@ -219,9 +237,9 @@ class AccountAnalyticAccount(models.Model):
@api.multi
def _convert_contract_lines(self, contract):
self.ensure_one()
new_lines = self.env['account.analytic.invoice.line']
contract_line_model = self.env['account.analytic.invoice.line']
for contract_line in contract.recurring_invoice_line_ids:
new_lines = self.env['contract.line']
contract_line_model = self.env['contract.line']
for contract_line in contract.contract_line_ids:
vals = contract_line._convert_to_write(contract_line.read()[0])
# Remove template link field
vals.pop('contract_template_id', False)
@ -282,7 +300,7 @@ class AccountAnalyticAccount(models.Model):
template = self.env.ref('contract.email_contract_template', False)
compose_form = self.env.ref('mail.email_compose_message_wizard_form')
ctx = dict(
default_model='account.analytic.account',
default_model='contract.contract',
default_res_id=self.id,
default_use_template=bool(template),
default_template_id=template and template.id or False,
@ -368,9 +386,9 @@ class AccountAnalyticAccount(models.Model):
def _get_contracts_to_invoice_domain(self, date_ref=None):
"""
This method builds the domain to use to find all
contracts (account.analytic.account) to invoice.
contracts (contract.contract) to invoice.
:param date_ref: optional reference date to use instead of today
:return: list (domain) usable on account.analytic.account
:return: list (domain) usable on contract.contract
"""
domain = []
if not date_ref:
@ -389,10 +407,10 @@ class AccountAnalyticAccount(models.Model):
This method fetches and returns the lines to invoice on the contract
(self), based on the given date.
:param date_ref: date used as reference date to find lines to invoice
:return: contract lines (account.analytic.invoice.line recordset)
:return: contract lines (contract.line recordset)
"""
self.ensure_one()
return self.recurring_invoice_line_ids.filtered(
return self.contract_line_ids.filtered(
lambda l: not l.is_canceled
and l.recurring_next_date
and l.recurring_next_date <= date_ref

42
contract/models/contract_line.py

@ -11,12 +11,15 @@ from odoo.exceptions import ValidationError
from .contract_line_constraints import get_allowed
class AccountAnalyticInvoiceLine(models.Model):
_name = 'account.analytic.invoice.line'
_inherit = 'account.abstract.analytic.contract.line'
class ContractLine(models.Model):
_name = 'contract.line'
_inherit = 'contract.abstract.contract.line'
sequence = fields.Integer(
string="Sequence",
)
contract_id = fields.Many2one(
comodel_name='account.analytic.account',
comodel_name='contract.contract',
string='Contract',
required=True,
index=True,
@ -43,7 +46,7 @@ class AccountAnalyticInvoiceLine(models.Model):
compute='_compute_create_invoice_visibility'
)
successor_contract_line_id = fields.Many2one(
comodel_name='account.analytic.invoice.line',
comodel_name='contract.line',
string="Successor Contract Line",
required=False,
readonly=True,
@ -53,7 +56,7 @@ class AccountAnalyticInvoiceLine(models.Model):
"contract line created.",
)
predecessor_contract_line_id = fields.Many2one(
comodel_name='account.analytic.invoice.line',
comodel_name='contract.line',
string="Predecessor Contract Line",
required=False,
readonly=True,
@ -511,12 +514,11 @@ class AccountAnalyticInvoiceLine(models.Model):
invoice_line._onchange_product_id()
invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache)
# Insert markers
contract = self.contract_id
name = self._insert_markers(dates[0], dates[1])
invoice_line_vals.update(
{
'name': name,
'account_analytic_id': contract.id,
'account_analytic_id': self.contract_id.analytic_account_id.id,
'price_unit': self.price_unit,
}
)
@ -737,7 +739,7 @@ class AccountAnalyticInvoiceLine(models.Model):
successor_contract_line
:return: successor_contract_line
"""
contract_line = self.env['account.analytic.invoice.line']
contract_line = self.env['contract.line']
for rec in self:
if not rec.is_plan_successor_allowed:
raise ValidationError(
@ -804,7 +806,7 @@ class AccountAnalyticInvoiceLine(models.Model):
raise ValidationError(
_('Stop/Plan successor not allowed for this line')
)
contract_line = self.env['account.analytic.invoice.line']
contract_line = self.env['contract.line']
for rec in self:
if rec.date_start >= date_start:
if rec.date_start < date_end:
@ -935,7 +937,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return {
'type': 'ir.actions.act_window',
'name': 'Un-Cancel Contract Line',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form',
'view_mode': 'form',
'views': [(view_id, 'form')],
@ -957,7 +959,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return {
'type': 'ir.actions.act_window',
'name': 'Plan contract line successor',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form',
'view_mode': 'form',
'views': [(view_id, 'form')],
@ -979,7 +981,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return {
'type': 'ir.actions.act_window',
'name': 'Resiliate contract line',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form',
'view_mode': 'form',
'views': [(view_id, 'form')],
@ -1001,7 +1003,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return {
'type': 'ir.actions.act_window',
'name': 'Suspend contract line',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form',
'view_mode': 'form',
'views': [(view_id, 'form')],
@ -1020,7 +1022,7 @@ class AccountAnalyticInvoiceLine(models.Model):
@api.multi
def renew(self):
res = self.env['account.analytic.invoice.line']
res = self.env['contract.line']
for rec in self:
is_auto_renew = rec.is_auto_renew
rec.stop(rec.date_end, post_message=False)
@ -1067,18 +1069,18 @@ class AccountAnalyticInvoiceLine(models.Model):
default_contract_type = self.env.context.get('default_contract_type')
if view_type == 'tree' and default_contract_type == 'purchase':
view_id = self.env.ref(
'contract.account_analytic_invoice_line_purchase_view_tree'
'contract.contract_line_supplier_tree_view'
).id
if view_type == 'form':
if default_contract_type == 'purchase':
view_id = self.env.ref(
'contract.account_analytic_invoice_line_purchase_view_form'
'contract.contract_line_supplier_form_view'
).id
elif default_contract_type == 'sale':
view_id = self.env.ref(
'contract.account_analytic_invoice_line_sale_view_form'
'contract.contract_line_customer_form_view'
).id
return super(AccountAnalyticInvoiceLine, self).fields_view_get(
return super(ContractLine, self).fields_view_get(
view_id, view_type, toolbar, submenu
)
@ -1089,7 +1091,7 @@ class AccountAnalyticInvoiceLine(models.Model):
raise ValidationError(
_("Contract line must be canceled before delete")
)
return super(AccountAnalyticInvoiceLine, self).unlink()
return super(ContractLine, self).unlink()
@api.multi
def _get_quantity_to_invoice(

15
contract/models/contract_template.py

@ -9,14 +9,15 @@
from odoo import fields, models
class AccountAnalyticContract(models.Model):
_name = 'account.analytic.contract'
_inherit = 'account.abstract.analytic.contract'
_description = "Account Analytic Contract"
class ContractTemplate(models.Model):
_name = 'contract.template'
_inherit = 'contract.abstract.contract'
_description = "Contract Template"
recurring_invoice_line_ids = fields.One2many(
comodel_name='account.analytic.contract.line',
contract_line_ids = fields.One2many(
comodel_name='contract.template.line',
inverse_name='contract_id',
copy=True,
string='Invoice Lines',
string='Contract template lines',
oldname='contract_line_ids',
)

10
contract/models/contract_template_line.py

@ -9,15 +9,15 @@
from odoo import fields, models
class AccountAnalyticContractLine(models.Model):
_name = 'account.analytic.contract.line'
_inherit = 'account.abstract.analytic.contract.line'
_description = 'Contract Lines'
class ContractTemplateLine(models.Model):
_name = 'contract.template.line'
_inherit = 'contract.abstract.contract.line'
_description = "Contract Template Line"
_order = "sequence,id"
contract_id = fields.Many2one(
string='Contract',
comodel_name='account.analytic.contract',
comodel_name='contract.template',
required=True,
ondelete='cascade',
oldname='analytic_account_id',

6
contract/models/res_partner.py

@ -15,7 +15,7 @@ class ResPartner(models.Model):
)
def _compute_contract_count(self):
contract_model = self.env['account.analytic.account']
contract_model = self.env['contract.contract']
fetch_data = contract_model.read_group(
[
('recurring_invoices', '=', True),
@ -69,9 +69,9 @@ class ResPartner(models.Model):
def _get_act_window_contract_xml(self, contract_type):
if contract_type == 'purchase':
return self.env['ir.actions.act_window'].for_xml_id(
'contract', 'action_account_analytic_purchase_overdue_all'
'contract', 'action_supplier_contract'
)
else:
return self.env['ir.actions.act_window'].for_xml_id(
'contract', 'action_account_analytic_sale_overdue_all'
'contract', 'action_customer_contract'
)

2
contract/report/contract_views.xml

@ -3,7 +3,7 @@
<report
id="report_contract"
model="account.analytic.account"
model="contract.contract"
string="Contract"
report_type="qweb-pdf"
name="contract.report_contract_document"

2
contract/report/report_contract.xml

@ -55,7 +55,7 @@
</tr>
</thead>
<tbody>
<tr t-foreach="o.recurring_invoice_line_ids"
<tr t-foreach="o.contract_line_ids"
t-as="l">
<td>
<span t-field="l.name"/>

2
contract/security/contract_security.xml

@ -2,7 +2,7 @@
<record id="rule_contract_template_multi_company" model="ir.rule">
<field name="name">Contract template multi-company</field>
<field name="model_id" ref="model_account_analytic_contract"/>
<field name="model_id" ref="model_contract_template"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>

14
contract/security/ir.model.access.csv

@ -1,7 +1,9 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"account_analytic_contract_manager","Recurring manager","model_account_analytic_contract","account.group_account_manager",1,1,1,1
"account_analytic_contract_user","Recurring user","model_account_analytic_contract","account.group_account_invoice",1,0,0,0
"account_analytic_invoice_line_manager","Recurring manager","model_account_analytic_invoice_line","account.group_account_manager",1,1,1,1
"account_analytic_invoice_line_user","Recurring user","model_account_analytic_invoice_line","account.group_account_invoice",1,0,0,0
"account_analytic_contract_line_manager","Recurring manager","model_account_analytic_contract_line","account.group_account_manager",1,1,1,1
"account_analytic_contract_line_user","Recurring user","model_account_analytic_contract_line","account.group_account_invoice",1,0,0,0
"contract_template_manager","Recurring manager","model_contract_template","account.group_account_manager",1,1,1,1
"contract_template_user","Recurring user","model_contract_template","account.group_account_invoice",1,0,0,0
"contract_manager","Recurring manager","model_contract_contract","account.group_account_manager",1,1,1,1
"contract_user","Recurring user","model_contract_contract","account.group_account_invoice",1,0,0,0
"contract_line_manager","Recurring manager","model_contract_line","account.group_account_manager",1,1,1,1
"contract_line_user","Recurring user","model_contract_line","account.group_account_invoice",1,0,0,0
"contract_template_line_manager","Recurring manager","model_contract_template_line","account.group_account_manager",1,1,1,1
"contract_template_line_user","Recurring user","model_contract_template_line","account.group_account_invoice",1,0,0,0

109
contract/tests/test_contract.py

@ -37,9 +37,9 @@ class TestContractBase(common.SavepointCase):
}
cls.template_vals = {
'name': 'Test Contract Template',
'recurring_invoice_line_ids': [(0, 0, cls.line_template_vals)],
'contract_line_ids': [(0, 0, cls.line_template_vals)],
}
cls.template = cls.env['account.analytic.contract'].create(
cls.template = cls.env['contract.template'].create(
cls.template_vals
)
# For being sure of the applied price
@ -51,7 +51,7 @@ class TestContractBase(common.SavepointCase):
'base': 'list_price',
}
)
cls.contract = cls.env['account.analytic.account'].create(
cls.contract = cls.env['contract.contract'].create(
{
'name': 'Test Contract',
'partner_id': cls.partner.id,
@ -59,14 +59,14 @@ class TestContractBase(common.SavepointCase):
'recurring_invoices': True,
}
)
cls.contract2 = cls.env['account.analytic.account'].create(
cls.contract2 = cls.env['contract.contract'].create(
{
'name': 'Test Contract 2',
'partner_id': cls.partner.id,
'pricelist_id': cls.partner.property_product_pricelist.id,
'recurring_invoices': True,
'contract_type': 'purchase',
'recurring_invoice_line_ids': [
'contract_line_ids': [
(
0,
0,
@ -100,7 +100,7 @@ class TestContractBase(common.SavepointCase):
'recurring_next_date': '2018-01-15',
'is_auto_renew': False,
}
cls.acct_line = cls.env['account.analytic.invoice.line'].create(
cls.acct_line = cls.env['contract.line'].create(
cls.line_vals
)
cls.acct_line.product_id.is_auto_renew = True
@ -115,7 +115,7 @@ class TestContract(TestContractBase):
del vals['date_start']
vals['contract_id'] = self.template.id
vals.update(overrides)
return self.env['account.analytic.contract.line'].create(vals)
return self.env['contract.template.line'].create(vals)
def test_check_discount(self):
with self.assertRaises(ValidationError):
@ -360,7 +360,7 @@ class TestContract(TestContractBase):
)
def test_onchange_product_id(self):
line = self.env['account.analytic.invoice.line'].new()
line = self.env['contract.line'].new()
res = line._onchange_product_id()
self.assertFalse(res['domain']['uom_id'])
@ -400,7 +400,7 @@ class TestContract(TestContractBase):
self.contract.contract_template_id = self.template
self.contract._onchange_contract_template_id()
res = {
'recurring_invoice_line_ids': [
'contract_line_ids': [
(
0,
0,
@ -427,15 +427,15 @@ class TestContract(TestContractBase):
self.contract.contract_template_id = self.template
self.assertFalse(
self.contract.recurring_invoice_line_ids,
self.contract.contract_line_ids,
'Recurring lines were not removed.',
)
self.contract.contract_template_id = self.template
self.contract._onchange_contract_template_id()
self.assertEqual(len(self.contract.recurring_invoice_line_ids), 1)
self.assertEqual(len(self.contract.contract_line_ids), 1)
for key, value in self.line_template_vals.items():
test_value = self.contract.recurring_invoice_line_ids[0][key]
test_value = self.contract.contract_line_ids[0][key]
try:
test_value = test_value.id
except AttributeError:
@ -456,7 +456,7 @@ class TestContract(TestContractBase):
self.contract._onchange_contract_type()
self.assertFalse(
any(
self.contract.recurring_invoice_line_ids.mapped(
self.contract.contract_line_ids.mapped(
'automatic_price'
)
)
@ -464,7 +464,7 @@ class TestContract(TestContractBase):
def test_contract_onchange_product_id_domain_blank(self):
"""It should return a blank UoM domain when no product."""
line = self.env['account.analytic.contract.line'].new()
line = self.env['contract.template.line'].new()
res = line._onchange_product_id()
self.assertFalse(res['domain']['uom_id'])
@ -533,8 +533,8 @@ class TestContract(TestContractBase):
'name': 'Customer Contracts',
'type': 'ir.actions.act_window',
'view_type': 'form',
'res_model': 'account.analytic.account',
'xml_id': 'contract.action_account_analytic_sale_overdue_all',
'res_model': 'contract.contract',
'xml_id': 'contract.action_customer_contract',
},
show_contract,
'There was an error and the view couldn\'t be opened.',
@ -605,7 +605,7 @@ class TestContract(TestContractBase):
(to_date('2018-01-05'), 'post-paid', 'yearly', 1),
),
]
contract_line_env = self.env['account.analytic.invoice.line']
contract_line_env = self.env['contract.line']
for recurring_next_date, combination in combinations:
self.assertEqual(
recurring_next_date,
@ -621,7 +621,7 @@ class TestContract(TestContractBase):
self.assertEqual(
self.contract.recurring_next_date,
min(
self.contract.recurring_invoice_line_ids.mapped(
self.contract.contract_line_ids.mapped(
'recurring_next_date'
)
),
@ -701,7 +701,7 @@ class TestContract(TestContractBase):
'is_auto_renew': True,
}
)
wizard = self.env['account.analytic.invoice.line.wizard'].create(
wizard = self.env['contract.line.wizard'].create(
{
'date_end': self.today + relativedelta(months=3),
'contract_line_id': self.acct_line.id,
@ -754,7 +754,7 @@ class TestContract(TestContractBase):
suspension_start, suspension_end, True
)
self.assertEqual(self.acct_line.date_end, end_date)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -785,7 +785,7 @@ class TestContract(TestContractBase):
self.assertEqual(
self.acct_line.date_end, suspension_start - relativedelta(days=1)
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertTrue(new_line)
@ -826,7 +826,7 @@ class TestContract(TestContractBase):
self.assertEqual(
self.acct_line.date_end, suspension_start - relativedelta(days=1)
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertTrue(new_line)
@ -868,7 +868,7 @@ class TestContract(TestContractBase):
self.assertEqual(
self.acct_line.date_end, suspension_start - relativedelta(days=1)
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertTrue(new_line)
@ -906,7 +906,7 @@ class TestContract(TestContractBase):
self.acct_line.date_end,
end_date + (suspension_end - start_date) + timedelta(days=1),
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -939,7 +939,7 @@ class TestContract(TestContractBase):
self.acct_line.date_end,
end_date + (suspension_end - start_date) + timedelta(days=1),
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -970,7 +970,7 @@ class TestContract(TestContractBase):
start_date + (suspension_end - start_date) + timedelta(days=1),
)
self.assertFalse(self.acct_line.date_end)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -1005,7 +1005,7 @@ class TestContract(TestContractBase):
self.acct_line.date_end,
end_date + (suspension_end - suspension_start) + timedelta(days=1),
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -1038,7 +1038,7 @@ class TestContract(TestContractBase):
+ timedelta(days=1),
)
self.assertFalse(self.acct_line.date_end)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -1055,7 +1055,7 @@ class TestContract(TestContractBase):
'date_end': end_date,
}
)
wizard = self.env['account.analytic.invoice.line.wizard'].create(
wizard = self.env['contract.line.wizard'].create(
{
'date_start': suspension_start,
'date_end': suspension_end,
@ -1074,7 +1074,7 @@ class TestContract(TestContractBase):
self.acct_line.date_end,
end_date + (suspension_end - suspension_start) + timedelta(days=1),
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(new_line)
@ -1093,7 +1093,7 @@ class TestContract(TestContractBase):
self.today + relativedelta(months=7),
True,
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(self.acct_line.is_auto_renew)
@ -1120,7 +1120,7 @@ class TestContract(TestContractBase):
self.today + relativedelta(months=7),
True,
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
with self.assertRaises(ValidationError):
@ -1137,7 +1137,7 @@ class TestContract(TestContractBase):
'is_auto_renew': False,
}
)
wizard = self.env['account.analytic.invoice.line.wizard'].create(
wizard = self.env['contract.line.wizard'].create(
{
'date_start': self.today + relativedelta(months=3),
'date_end': self.today + relativedelta(months=5),
@ -1146,7 +1146,7 @@ class TestContract(TestContractBase):
}
)
wizard.plan_successor()
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertFalse(self.acct_line.is_auto_renew)
@ -1177,7 +1177,7 @@ class TestContract(TestContractBase):
def test_uncancel_wizard(self):
self.acct_line.cancel()
self.assertTrue(self.acct_line.is_canceled)
wizard = self.env['account.analytic.invoice.line.wizard'].create(
wizard = self.env['contract.line.wizard'].create(
{
'recurring_next_date': self.today,
'contract_line_id': self.acct_line.id,
@ -1204,7 +1204,7 @@ class TestContract(TestContractBase):
self.assertEqual(
self.acct_line.date_end, suspension_start - relativedelta(days=1)
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
self.assertEqual(self.acct_line.successor_contract_line_id, new_line)
@ -1235,7 +1235,7 @@ class TestContract(TestContractBase):
self.acct_line.stop_plan_successor(
suspension_start, suspension_end, True
)
new_line = self.env['account.analytic.invoice.line'].search(
new_line = self.env['contract.line'].search(
[('predecessor_contract_line_id', '=', self.acct_line.id)]
)
new_line.cancel()
@ -1324,12 +1324,13 @@ class TestContract(TestContractBase):
contracts = self.contract2
for i in range(10):
contracts |= self.contract.copy()
self.env['account.analytic.account'].cron_recurring_create_invoice()
self.env['contract.contract'].cron_recurring_create_invoice()
invoice_lines = self.env['account.invoice.line'].search(
[('account_analytic_id', 'in', contracts.ids)]
[('contract_line_id', 'in',
contracts.mapped('contract_line_ids').ids)]
)
self.assertEqual(
len(contracts.mapped('recurring_invoice_line_ids')),
len(contracts.mapped('contract_line_ids')),
len(invoice_lines),
)
@ -1535,7 +1536,7 @@ class TestContract(TestContractBase):
self.acct_line.unlink()
def test_contract_line_state(self):
lines = self.env['account.analytic.invoice.line']
lines = self.env['contract.line']
# upcoming
lines |= self.acct_line.copy(
{
@ -1607,39 +1608,39 @@ class TestContract(TestContractBase):
]
self.assertEqual(set(lines.mapped('state')), set(states))
for state in states:
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', '=', state)]
)
self.assertEqual(len(set(lines.mapped('state'))), 1, state)
self.assertEqual(lines.mapped('state')[0], state, state)
for state in states:
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', '!=', state)]
)
self.assertFalse(state in lines.mapped('state'))
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', 'in', states)]
)
self.assertEqual(set(lines.mapped('state')), set(states))
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', 'in', [])]
)
self.assertFalse(lines.mapped('state'))
with self.assertRaises(TypeError):
self.env['account.analytic.invoice.line'].search(
self.env['contract.line'].search(
[('state', 'in', 'upcoming')]
)
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', 'not in', [])]
)
self.assertEqual(set(lines.mapped('state')), set(states))
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', 'not in', states)]
)
self.assertFalse(lines.mapped('state'))
lines = self.env['account.analytic.invoice.line'].search(
lines = self.env['contract.line'].search(
[('state', 'not in', ['upcoming', 'in-progress'])]
)
self.assertEqual(
@ -1780,10 +1781,10 @@ class TestContract(TestContractBase):
def test_purchase_fields_view_get(self):
purchase_tree_view = self.env.ref(
'contract.account_analytic_invoice_line_purchase_view_tree'
'contract.contract_line_supplier_tree_view'
)
purchase_form_view = self.env.ref(
'contract.account_analytic_invoice_line_purchase_view_form'
'contract.contract_line_supplier_form_view'
)
view = self.acct_line.with_context(
default_contract_type='purchase'
@ -1796,7 +1797,7 @@ class TestContract(TestContractBase):
def test_sale_fields_view_get(self):
sale_form_view = self.env.ref(
'contract.account_analytic_invoice_line_sale_view_form'
'contract.contract_line_customer_form_view'
)
view = self.acct_line.with_context(
default_contract_type='sale'
@ -1832,8 +1833,8 @@ class TestContract(TestContractBase):
self.assertFalse(self.contract.create_invoice_visibility)
def test_invoice_contract_without_lines(self):
self.contract.recurring_invoice_line_ids.cancel()
self.contract.recurring_invoice_line_ids.unlink()
self.contract.contract_line_ids.cancel()
self.contract.contract_line_ids.unlink()
self.assertFalse(self.contract.recurring_create_invoice())
def test_stop_at_last_date_invoiced(self):

12
contract/views/abstract_contract_line.xml

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_abstract_analytic_contract_line_view_form"
model="ir.ui.view">
<field name="name">Account Abstract Analytic Contract Line Form View
</field>
<field name="model">account.abstract.analytic.contract.line</field>
<!--FORM view-->
<record id="contract_abstract_contract_line_form_view" model="ir.ui.view">
<field name="name">contract.abstract.contract.line form view (in contract)</field>
<field name="model">contract.abstract.contract.line</field>
<field name="arch" type="xml">
<form>
<header/>
<sheet>
<group col="4">
<field colspan="4" name="product_id"/>
@ -60,7 +60,7 @@
</group>
<group>
<field name="recurring_invoicing_type"
attrs="{'invisible': [('recurring_rule_type', '=', 'monthlylastday')]}"/>
attrs="{'invisible': [('recurring_rule_type', '=', 'monthlylastday')]}"/>
</group>
</group>
</sheet>

166
contract/views/contract.xml

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_analytic_account_recurring_form_form"
model="ir.ui.view">
<field name="name">Contract form</field>
<field name="model">account.analytic.account</field>
<!--Main FORM view-->
<record id="contract_contract_form_view" model="ir.ui.view">
<field name="name">contract.contract form view (in contract)</field>
<field name="model">contract.contract</field>
<field name="arch" type="xml">
<form>
<header>
@ -70,7 +70,7 @@
<notebook>
<page name="recurring_invoice_line"
string="Recurring Invoices">
<field name="recurring_invoice_line_ids"
<field name="contract_line_ids"
context="{'default_contract_type': contract_type}"/>
</page>
<page name="info" string="Other Information">
@ -119,20 +119,18 @@
</field>
</record>
<record id="account_analytic_account_sale_form" model="ir.ui.view">
<field name="name">account.analytic.account.sale.form</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id"
ref="account_analytic_account_recurring_form_form"/>
<!--Customer FORM view-->
<record id="contract_contract_customer_form_view" model="ir.ui.view">
<field name="name">contract.contract customer form view (in contract)</field>
<field name="model">contract.contract</field>
<field name="inherit_id" ref="contract_contract_form_view"/>
<field name="mode">primary</field>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<field name="partner_id" position="attributes">
<attribute name="string">Customer</attribute>
<attribute name="domain">[('customer', '=', True)]</attribute>
<attribute name="context">{'default_customer': True,
'default_supplier': False}
</attribute>
<attribute name="context">{'default_customer': True, 'default_supplier': False}</attribute>
</field>
<field name="journal_id" position="attributes">
<attribute name="domain">[('type', '=', 'sale'),('company_id', '=', company_id)]</attribute>
@ -140,20 +138,18 @@
</field>
</record>
<record id="account_analytic_account_purchase_form" model="ir.ui.view">
<field name="name">account.analytic.account.purchase.form</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id"
ref="account_analytic_account_recurring_form_form"/>
<!--Supplier FORM view-->
<record id="contract_contract_supplier_form_view" model="ir.ui.view">
<field name="name">contract.contract supplier form view (in contract)</field>
<field name="model">contract.contract</field>
<field name="inherit_id" ref="contract_contract_form_view"/>
<field name="mode">primary</field>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<field name="partner_id" position="attributes">
<attribute name="string">Supplier</attribute>
<attribute name="domain">[('supplier', '=', True)]</attribute>
<attribute name="context">{'default_customer': False,
'default_supplier': True}
</attribute>
<attribute name="context">{'default_customer': False, 'default_supplier': True}</attribute>
</field>
<field name="journal_id" position="attributes">
<attribute name="domain">[('type', '=', 'purchase'),('company_id', '=', company_id)]</attribute>
@ -161,30 +157,30 @@
</field>
</record>
<!-- Inherited Analytic Account list for contracts -->
<record id="view_account_analytic_account_journal_tree" model="ir.ui.view">
<field name="name">Contract list</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id"
ref="analytic.view_account_analytic_account_list"/>
<field name="mode">primary</field>
<field name="priority" eval="9999"/>
<!--TREE view-->
<record id="contract_contract_tree_view" model="ir.ui.view">
<field name="name">contract.contract tree view (in contract)</field>
<field name="model">contract.contract</field>
<field name="arch" type="xml">
<field name="partner_id" position="before">
<tree>
<field name="name" string="Name"/>
<field name="code"/>
<field name="journal_id" groups="account.group_account_user"/>
</field>
<field name="partner_id"/>
<field name="active" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<!-- Analytic Account search view for contract -->
<record id="view_account_analytic_account_contract_search"
model="ir.ui.view">
<field name="name">Contract search</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id"
ref="analytic.view_account_analytic_account_search"/>
<!--SEARCH view-->
<record id="contract_contract_search_view" model="ir.ui.view">
<field name="name">contract.contract search view (in contract)</field>
<field name="model">contract.contract</field>
<field name="arch" type="xml">
<field name="name" position="after">
<search>
<field name="name"
filter_domain="['|', ('name','ilike',self), ('code','ilike',self)]"/>
<field name="journal_id"/>
<field name="pricelist_id"/>
<separator/>
@ -201,37 +197,44 @@
string="Finished"
domain="[('date_end', '&lt;', context_today().strftime('%Y-%m-%d')), ('recurring_next_date', '=', False)]"
/>
<field name="partner_id"/>
<filter string="Archived"
domain="[('active', '=', False)]"
name="inactive"/>
<group expand="0" string="Group By...">
<filter name="next_invoice"
<filter string="Associated Partner"
name="group_by_partner"
domain="[]"
context="{'group_by':'partner_id'}"/>
<filter name="group_by_next_invoice"
string="Next Invoice"
domain="[('recurring_next_date', '!=', False)]"
context="{'group_by':'recurring_next_date'}"
/>
<filter name="date_end"
<filter name="group_by_date_end"
string="Date End"
domain="[]"
context="{'group_by':'date_end'}"
/>
</group>
</field>
</search>
</field>
</record>
<!-- Action Sales/Sales/Contracts -->
<record id="action_account_analytic_sale_overdue_all"
model="ir.actions.act_window">
<!--ACTION customer contracts-->
<record id="action_customer_contract" model="ir.actions.act_window">
<field name="name">Customer Contracts</field>
<field name="res_model">account.analytic.account</field>
<field name="res_model">contract.contract</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('contract_type', '=', 'sale')]</field>
<field name="context">{'is_contract':1,
'search_default_not_finished':1,
'search_default_recurring_invoices':1,
'default_recurring_invoices': 1, 'default_contract_type': 'sale'}
'search_default_not_finished':1,
'search_default_recurring_invoices':1,
'default_recurring_invoices': 1,
'default_contract_type': 'sale'}
</field>
<field name="search_view_id"
ref="view_account_analytic_account_contract_search"/>
<field name="search_view_id" ref="contract_contract_search_view"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new contract.
@ -239,47 +242,41 @@
</field>
</record>
<record id="action_account_analytic_sale_overdue_all_tree"
model="ir.actions.act_window.view">
<record id="action_customer_contract_view_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="view_id"
ref="view_account_analytic_account_journal_tree"/>
<field name="act_window_id"
ref="action_account_analytic_sale_overdue_all"/>
<field name="view_id" ref="contract_contract_tree_view"/>
<field name="act_window_id" ref="action_customer_contract"/>
</record>
<record id="action_account_analytic_sale_overdue_all_form"
model="ir.actions.act_window.view">
<record id="action_customer_contract_view_form" model="ir.actions.act_window.view">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="account_analytic_account_sale_form"/>
<field name="act_window_id"
ref="action_account_analytic_sale_overdue_all"/>
<field name="view_id" ref="contract_contract_customer_form_view"/>
<field name="act_window_id" ref="action_customer_contract"/>
</record>
<menuitem id="menu_action_account_analytic_sale_overdue_all"
<menuitem id="menu_contract_contract_customer"
parent="account.menu_finance_receivables"
action="action_account_analytic_sale_overdue_all"
action="action_customer_contract"
sequence="99"
/>
<!-- Action Purchases/Purchases/Contracts -->
<record id="action_account_analytic_purchase_overdue_all"
model="ir.actions.act_window">
<!--ACTION supplier contracts-->
<record id="action_supplier_contract" model="ir.actions.act_window">
<field name="name">Supplier Contracts</field>
<field name="res_model">account.analytic.account</field>
<field name="res_model">contract.contract</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('contract_type', '=', 'purchase')]</field>
<field name="context">{'is_contract':1,
'search_default_not_finished':1,
'search_default_recurring_invoices':1,
'default_recurring_invoices': 1, 'default_contract_type':
'purchase'}
'search_default_not_finished':1,
'search_default_recurring_invoices':1,
'default_recurring_invoices': 1,
'default_contract_type':
'purchase'}
</field>
<field name="search_view_id"
ref="view_account_analytic_account_contract_search"/>
<field name="search_view_id" ref="contract_contract_search_view"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new contract.
@ -287,28 +284,23 @@
</field>
</record>
<record id="action_account_analytic_purchase_overdue_all_tree"
model="ir.actions.act_window.view">
<record id="action_supplier_contract_view_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="view_id"
ref="view_account_analytic_account_journal_tree"/>
<field name="act_window_id"
ref="action_account_analytic_purchase_overdue_all"/>
<field name="view_id" ref="contract_contract_tree_view"/>
<field name="act_window_id" ref="action_supplier_contract"/>
</record>
<record id="action_account_analytic_purchase_overdue_all_form"
model="ir.actions.act_window.view">
<record id="action_supplier_contract_view_form" model="ir.actions.act_window.view">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="account_analytic_account_purchase_form"/>
<field name="act_window_id"
ref="action_account_analytic_purchase_overdue_all"/>
<field name="view_id" ref="contract_contract_supplier_form_view"/>
<field name="act_window_id" ref="action_supplier_contract"/>
</record>
<menuitem id="menu_action_account_analytic_purchase_overdue_all"
<menuitem id="menu_contract_contract_supplier"
parent="account.menu_finance_payables"
action="action_account_analytic_purchase_overdue_all"
action="action_supplier_contract"
sequence="99"
/>

79
contract/views/contract_line.xml

@ -1,22 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_analytic_invoice_line_view_form" model="ir.ui.view">
<field name="name">account.analytic.invoice.line.form</field>
<field name="model">account.analytic.invoice.line</field>
<field name="inherit_id"
ref="account_abstract_analytic_contract_line_view_form"/>
<!--FORM view-->
<record id="contract_line_form_view" model="ir.ui.view">
<field name="name">contract.line form view (in contract)</field>
<field name="model">contract.line</field>
<field name="inherit_id" ref="contract_abstract_contract_line_form_view"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//sheet" position="before">
<header>
<field name="state" widget="statusbar"/>
</header>
</xpath>
<xpath expr="//form" position="attributes">
<attribute name="string">Contract Line</attribute>
</xpath>
<xpath expr="//group[@name='recurrence_info']" position="inside">
<header position="inside">
<field name="state" widget="statusbar"/>
</header>
<group name="recurrence_info" position="inside">
<group>
<field name="create_invoice_visibility" invisible="1"/>
<field name="date_start" required="1"/>
@ -33,23 +28,21 @@
<group>
<field name="manual_renew_needed"/>
</group>
<group>
<field name="predecessor_contract_line_id"/>
</group>
<group>
<field name="successor_contract_line_id"/>
</group>
</xpath>
</group>
</field>
</record>
<record id="account_analytic_invoice_line_sale_view_form"
model="ir.ui.view">
<field name="name">account.analytic.invoice.line.sale.form</field>
<field name="model">account.analytic.invoice.line</field>
<field name="inherit_id"
ref="account_analytic_invoice_line_view_form"/>
<!--Customer FORM view-->
<record id="contract_line_customer_form_view" model="ir.ui.view">
<field name="name">contract.line customer form view (in contract)</field>
<field name="model">contract.line</field>
<field name="inherit_id" ref="contract_line_form_view"/>
<field name="mode">primary</field>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
@ -59,29 +52,27 @@
</field>
</record>
<record id="account_analytic_invoice_line_purchase_view_form"
model="ir.ui.view">
<field name="name">account.analytic.invoice.line.purchase.form</field>
<field name="model">account.analytic.invoice.line</field>
<field name="inherit_id"
ref="account_analytic_invoice_line_view_form"/>
<!--Supplier FORM view-->
<record id="contract_line_supplier_form_view" model="ir.ui.view">
<field name="name">contract.line supplier form view (in contract)</field>
<field name="model">contract.line</field>
<field name="inherit_id" ref="contract_line_form_view"/>
<field name="mode">primary</field>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<field name="product_id" position="attributes">
<attribute name="domain">[('purchase_ok', '=', True)]
</attribute>
<attribute name="domain">[('purchase_ok', '=', True)]</attribute>
</field>
<xpath expr="//field[@name='automatic_price']"
position="attributes">
<field name="automatic_price" position="attributes">
<attribute name="invisible">True</attribute>
</xpath>
</field>
</field>
</record>
<record id="account_analytic_invoice_line_view_tree" model="ir.ui.view">
<field name="name">account.analytic.invoice.line.tree</field>
<field name="model">account.analytic.invoice.line</field>
<!--TREE view-->
<record id="contract_line_tree_view" model="ir.ui.view">
<field name="name">contract.line tree view (in contract)</field>
<field name="model">contract.line</field>
<field name="arch" type="xml">
<tree decoration-muted="is_canceled"
decoration-info="create_invoice_visibility and not is_canceled">
@ -155,19 +146,17 @@
</field>
</record>
<record id="account_analytic_invoice_line_purchase_view_tree"
model="ir.ui.view">
<field name="name">account.analytic.invoice.line.purchase.tree</field>
<field name="model">account.analytic.invoice.line</field>
<!--Supplier TREE view-->
<record id="contract_line_supplier_tree_view" model="ir.ui.view">
<field name="name">contract.line supplier tree view (in contract)</field>
<field name="model">contract.line</field>
<field name="mode">primary</field>
<field name="priority" eval="20"/>
<field name="inherit_id"
ref="account_analytic_invoice_line_view_tree"/>
<field name="inherit_id" ref="contract_line_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='automatic_price']"
position="attributes">
<field name="automatic_price" position="attributes">
<attribute name="invisible">True</attribute>
</xpath>
</field>
</field>
</record>

42
contract/views/contract_template.xml

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_analytic_contract_view_form" model="ir.ui.view">
<field name="name">Account Analytic Contract Form View</field>
<field name="model">account.analytic.contract</field>
<!--FORM view-->
<record id="contract_template_form_view" model="ir.ui.view">
<field name="name">contract.template form view (in contract)</field>
<field name="model">contract.template</field>
<field name="arch" type="xml">
<form string="Contract Template">
<group name="name">
@ -17,9 +18,9 @@
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
</group>
<group name="group_invoice_lines" string="Invoice Lines">
<field name="recurring_invoice_line_ids" nolabel="1">
<tree string="Account Analytic Lines">
<group name="group_invoice_lines" string="Contract Template Lines">
<field name="contract_line_ids" nolabel="1">
<tree>
<field name="sequence" widget="handle" />
<field name="product_id" />
<field name="name" />
@ -46,11 +47,12 @@
</field>
</record>
<record id="account_analytic_contract_view_tree" model="ir.ui.view">
<field name="name">Account Analytic Contract Tree View</field>
<field name="model">account.analytic.contract</field>
<!--TREE view-->
<record id="contract_template_tree_view" model="ir.ui.view">
<field name="name">contract.template tree view (in contract)</field>
<field name="model">contract.template</field>
<field name="arch" type="xml">
<tree string="Contract Templates">
<tree>
<field name="name" />
<field name="contract_type" />
<field name="pricelist_id" />
@ -58,11 +60,12 @@
</field>
</record>
<record id="account_analytic_contract_view_search" model="ir.ui.view">
<field name="name">Account Analytic Contract Search View</field>
<field name="model">account.analytic.contract</field>
<!--SEARCH view-->
<record id="contract_template_search_view" model="ir.ui.view">
<field name="name">contract.template search view (in contract)</field>
<field name="model">contract.template</field>
<field name="arch" type="xml">
<search string="Contract Templates">
<search>
<field name="name" />
<field name="contract_type" />
<field name="pricelist_id" />
@ -83,12 +86,13 @@
</field>
</record>
<record id="account_analytic_contract_action" model="ir.actions.act_window">
<!--ACTION-->
<record id="contract_template_action" model="ir.actions.act_window">
<field name="name">Contract Templates</field>
<field name="res_model">account.analytic.contract</field>
<field name="res_model">contract.template</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="account_analytic_contract_view_search"/>
<field name="search_view_id" ref="contract_template_search_view"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new contract template.
@ -102,9 +106,9 @@
parent="account.menu_finance_configuration"
/>
<menuitem id="account_analytic_contract_menu"
<menuitem id="contract_template_menu"
parent="menu_config_contract"
action="account_analytic_contract_action"
action="contract_template_action"
sequence="1"
/>

16
contract/views/contract_template_line.xml

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_analytic_contract_line_view_form" model="ir.ui.view">
<field name="name">account.analytic.contract.line.form</field>
<field name="model">account.analytic.contract.line</field>
<field name="inherit_id"
ref="account_abstract_analytic_contract_line_view_form"/>
<!--FORM view-->
<record id="contract_template_line_form_view" model="ir.ui.view">
<field name="name">contract.template.line form view (in contract)</field>
<field name="model">contract.template.line</field>
<field name="inherit_id" ref="contract_abstract_contract_line_form_view"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//form" position="attributes">
<attribute name="string">Contract Line Template</attribute>
</xpath>
<form position="attributes">
<attribute name="string">Contract Template Line</attribute>
</form>
</field>
</record>

6
contract/wizards/contract_line_wizard.py

@ -4,9 +4,9 @@
from odoo import api, fields, models
class AccountAnalyticInvoiceLineWizard(models.TransientModel):
class ContractLineWizard(models.TransientModel):
_name = 'account.analytic.invoice.line.wizard'
_name = 'contract.line.wizard'
_description = 'Contract Line Wizard'
date_start = fields.Date(string='Date Start')
@ -21,7 +21,7 @@ class AccountAnalyticInvoiceLineWizard(models.TransientModel):
"successor in advance",
)
contract_line_id = fields.Many2one(
comodel_name="account.analytic.invoice.line",
comodel_name="contract.line",
string="Contract Line",
required=True,
index=True,

8
contract/wizards/contract_line_wizard.xml

@ -6,7 +6,7 @@
<record model="ir.ui.view" id="contract_line_wizard_stop_form_view">
<field name="name">contract.line.stop.wizard.form (in contract)</field>
<field name="model">account.analytic.invoice.line.wizard</field>
<field name="model">contract.line.wizard</field>
<field name="arch" type="xml">
<form>
<group>
@ -29,7 +29,7 @@
<record model="ir.ui.view" id="contract_line_wizard_plan_successor_form_view">
<field name="name">contract.line.plan_successor.wizard.form (in contract)</field>
<field name="model">account.analytic.invoice.line.wizard</field>
<field name="model">contract.line.wizard</field>
<field name="arch" type="xml">
<form>
<group>
@ -53,7 +53,7 @@
<record model="ir.ui.view" id="contract_line_wizard_stop_plan_successor_form_view">
<field name="name">contract.line.stop_plan_successor.wizard.form (in contract)</field>
<field name="model">account.analytic.invoice.line.wizard</field>
<field name="model">contract.line.wizard</field>
<field name="arch" type="xml">
<form>
<group>
@ -77,7 +77,7 @@
<record model="ir.ui.view" id="contract_line_wizard_uncancel_form_view">
<field name="name">contract.line.stop_plan_successor.wizard.form (in contract)</field>
<field name="model">account.analytic.invoice.line.wizard</field>
<field name="model">contract.line.wizard</field>
<field name="arch" type="xml">
<form>
<group>

Loading…
Cancel
Save