Browse Source

[REF] Contract: split from analytic account

13.0-mig-contract
Thomas Binsfeld 5 years ago
committed by Administrator
parent
commit
78dc76b58d
  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. 10
      contract/views/abstract_contract_line.xml
  22. 156
      contract/views/contract.xml
  23. 75
      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', 'name': 'Recurring - Contracts Management',
'version': '12.0.3.0.1',
'version': '12.0.4.0.0',
'category': 'Contract Management', 'category': 'Contract Management',
'license': 'AGPL-3', 'license': 'AGPL-3',
'author': "OpenERP SA, " 'author': "OpenERP SA, "
@ -18,10 +18,9 @@
"ACSONE SA/NV, " "ACSONE SA/NV, "
"Odoo Community Association (OCA)", "Odoo Community Association (OCA)",
'website': 'https://github.com/oca/contract', 'website': 'https://github.com/oca/contract',
'depends': ['base', 'account', 'analytic', 'product'],
'depends': ['base', 'account', 'product'],
"external_dependencies": {"python": ["dateutil"]}, "external_dependencies": {"python": ["dateutil"]},
'data': [ 'data': [
'wizards/contract_line_wizard.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'security/contract_security.xml', 'security/contract_security.xml',
'report/report_contract.xml', 'report/report_contract.xml',
@ -29,11 +28,12 @@
'data/contract_cron.xml', 'data/contract_cron.xml',
'data/contract_renew_cron.xml', 'data/contract_renew_cron.xml',
'data/mail_template.xml', 'data/mail_template.xml',
'wizards/contract_line_wizard.xml',
'views/abstract_contract_line.xml', 'views/abstract_contract_line.xml',
'views/contract.xml', 'views/contract.xml',
'views/contract_template_line.xml',
'views/contract_template.xml',
'views/contract_line.xml', 'views/contract_line.xml',
'views/contract_template.xml',
'views/contract_template_line.xml',
'views/res_partner_view.xml', 'views/res_partner_view.xml',
], ],
'installable': True, 'installable': True,

4
contract/data/contract_cron.xml

@ -1,9 +1,9 @@
<?xml version="1.0" encoding='UTF-8'?> <?xml version="1.0" encoding='UTF-8'?>
<odoo noupdate="1"> <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="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="state">code</field>
<field name="code">model.cron_recurring_create_invoice()</field> <field name="code">model.cron_recurring_create_invoice()</field>
<field name="user_id" ref="base.user_root" /> <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"> <record model="ir.cron" id="contract_line_cron_for_renew">
<field name="name">Renew Contract lines</field> <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="state">code</field>
<field name="code">model.cron_renew_contract_line()</field> <field name="code">model.cron_renew_contract_line()</field>
<field name="user_id" ref="base.user_root" /> <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="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="subject">${object.company_id.name} Contract (Ref ${object.name or 'n/a'})</field>
<field name="partner_to">${object.partner_id.id}</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="auto_delete" eval="True"/>
<field name="report_template" ref="contract.report_contract"/> <field name="report_template" ref="contract.report_contract"/>
<field name="report_name">Contract</field> <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 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' _description = 'Abstract Recurring Contract'
# These fields will not be synced to the contract # These fields will not be synced to the contract
@ -50,7 +50,7 @@ class AbstractAccountAnalyticContract(models.AbstractModel):
@api.onchange('contract_type') @api.onchange('contract_type')
def _onchange_contract_type(self): def _onchange_contract_type(self):
if self.contract_type == 'purchase': 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} {'automatic_price': False}
) )
self.journal_id = self.env['account.journal'].search( 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 _ 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' _description = 'Abstract Recurring Contract Line'
product_id = fields.Many2one( product_id = fields.Many2one(
@ -110,7 +110,7 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
) )
contract_id = fields.Many2one( contract_id = fields.Many2one(
string='Contract', string='Contract',
comodel_name='account.abstract.analytic.contract',
comodel_name='contract.abstract.contract',
required=True, required=True,
ondelete='cascade', ondelete='cascade',
oldname='analytic_account_id', 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 # We keep this field for migration purpose
old_contract_id = fields.Many2one( 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' _inherit = 'account.invoice.line'
contract_line_id = fields.Many2one( 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 _ 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( 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', inverse_name='contract_id',
copy=True, copy=True,
oldnae='contract_line_ids',
) )
recurring_invoices = fields.Boolean( recurring_invoices = fields.Boolean(
string='Generate recurring invoices automatically' string='Generate recurring invoices automatically'
@ -84,7 +102,7 @@ class AccountAnalyticAccount(models.Model):
( (
'contract_line_id', 'contract_line_id',
'in', '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')] action['views'] = [(tree_view.id, 'tree'), (form_view.id, 'form')]
return action return action
@api.depends('recurring_invoice_line_ids.date_end')
@api.depends('contract_line_ids.date_end')
def _compute_date_end(self): def _compute_date_end(self):
for contract in self: for contract in self:
contract.date_end = False 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): if date_end and all(date_end):
contract.date_end = max(date_end) contract.date_end = max(date_end)
@api.depends( @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): def _compute_recurring_next_date(self):
for contract in 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 lambda l: l.recurring_next_date and not l.is_canceled
).mapped('recurring_next_date') ).mapped('recurring_next_date')
if recurring_next_date: if recurring_next_date:
contract.recurring_next_date = min(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): def _compute_create_invoice_visibility(self):
for contract in self: for contract in self:
contract.create_invoice_visibility = any( contract.create_invoice_visibility = any(
contract.recurring_invoice_line_ids.mapped(
contract.contract_line_ids.mapped(
'create_invoice_visibility' 'create_invoice_visibility'
) )
) )
@ -160,7 +178,7 @@ class AccountAnalyticAccount(models.Model):
def _onchange_contract_template_id(self): def _onchange_contract_template_id(self):
"""Update the contract fields with that of the template. """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 which must be created using the data from the contract lines. Cascade
deletion ensures that any errant lines that are created are also deletion ensures that any errant lines that are created are also
deleted. deleted.
@ -169,9 +187,9 @@ class AccountAnalyticAccount(models.Model):
if not contract_template_id: if not contract_template_id:
return return
for field_name, field in contract_template_id._fields.items(): 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) lines = self._convert_contract_lines(contract_template_id)
self.recurring_invoice_line_ids += lines
self.contract_line_ids += lines
elif not any( elif not any(
( (
field.compute, field.compute,
@ -219,9 +237,9 @@ class AccountAnalyticAccount(models.Model):
@api.multi @api.multi
def _convert_contract_lines(self, contract): def _convert_contract_lines(self, contract):
self.ensure_one() 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]) vals = contract_line._convert_to_write(contract_line.read()[0])
# Remove template link field # Remove template link field
vals.pop('contract_template_id', False) vals.pop('contract_template_id', False)
@ -282,7 +300,7 @@ class AccountAnalyticAccount(models.Model):
template = self.env.ref('contract.email_contract_template', False) template = self.env.ref('contract.email_contract_template', False)
compose_form = self.env.ref('mail.email_compose_message_wizard_form') compose_form = self.env.ref('mail.email_compose_message_wizard_form')
ctx = dict( ctx = dict(
default_model='account.analytic.account',
default_model='contract.contract',
default_res_id=self.id, default_res_id=self.id,
default_use_template=bool(template), default_use_template=bool(template),
default_template_id=template and template.id or False, 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): def _get_contracts_to_invoice_domain(self, date_ref=None):
""" """
This method builds the domain to use to find all 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 :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 = [] domain = []
if not date_ref: if not date_ref:
@ -389,10 +407,10 @@ class AccountAnalyticAccount(models.Model):
This method fetches and returns the lines to invoice on the contract This method fetches and returns the lines to invoice on the contract
(self), based on the given date. (self), based on the given date.
:param date_ref: date used as reference date to find lines to invoice :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() self.ensure_one()
return self.recurring_invoice_line_ids.filtered(
return self.contract_line_ids.filtered(
lambda l: not l.is_canceled lambda l: not l.is_canceled
and l.recurring_next_date and l.recurring_next_date
and l.recurring_next_date <= date_ref 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 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( contract_id = fields.Many2one(
comodel_name='account.analytic.account',
comodel_name='contract.contract',
string='Contract', string='Contract',
required=True, required=True,
index=True, index=True,
@ -43,7 +46,7 @@ class AccountAnalyticInvoiceLine(models.Model):
compute='_compute_create_invoice_visibility' compute='_compute_create_invoice_visibility'
) )
successor_contract_line_id = fields.Many2one( successor_contract_line_id = fields.Many2one(
comodel_name='account.analytic.invoice.line',
comodel_name='contract.line',
string="Successor Contract Line", string="Successor Contract Line",
required=False, required=False,
readonly=True, readonly=True,
@ -53,7 +56,7 @@ class AccountAnalyticInvoiceLine(models.Model):
"contract line created.", "contract line created.",
) )
predecessor_contract_line_id = fields.Many2one( predecessor_contract_line_id = fields.Many2one(
comodel_name='account.analytic.invoice.line',
comodel_name='contract.line',
string="Predecessor Contract Line", string="Predecessor Contract Line",
required=False, required=False,
readonly=True, readonly=True,
@ -511,12 +514,11 @@ class AccountAnalyticInvoiceLine(models.Model):
invoice_line._onchange_product_id() invoice_line._onchange_product_id()
invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache) invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache)
# Insert markers # Insert markers
contract = self.contract_id
name = self._insert_markers(dates[0], dates[1]) name = self._insert_markers(dates[0], dates[1])
invoice_line_vals.update( invoice_line_vals.update(
{ {
'name': name, 'name': name,
'account_analytic_id': contract.id,
'account_analytic_id': self.contract_id.analytic_account_id.id,
'price_unit': self.price_unit, 'price_unit': self.price_unit,
} }
) )
@ -737,7 +739,7 @@ class AccountAnalyticInvoiceLine(models.Model):
successor_contract_line successor_contract_line
:return: 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: for rec in self:
if not rec.is_plan_successor_allowed: if not rec.is_plan_successor_allowed:
raise ValidationError( raise ValidationError(
@ -804,7 +806,7 @@ class AccountAnalyticInvoiceLine(models.Model):
raise ValidationError( raise ValidationError(
_('Stop/Plan successor not allowed for this line') _('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: for rec in self:
if rec.date_start >= date_start: if rec.date_start >= date_start:
if rec.date_start < date_end: if rec.date_start < date_end:
@ -935,7 +937,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return { return {
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'name': 'Un-Cancel Contract Line', 'name': 'Un-Cancel Contract Line',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form', 'view_type': 'form',
'view_mode': 'form', 'view_mode': 'form',
'views': [(view_id, 'form')], 'views': [(view_id, 'form')],
@ -957,7 +959,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return { return {
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'name': 'Plan contract line successor', 'name': 'Plan contract line successor',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form', 'view_type': 'form',
'view_mode': 'form', 'view_mode': 'form',
'views': [(view_id, 'form')], 'views': [(view_id, 'form')],
@ -979,7 +981,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return { return {
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'name': 'Resiliate contract line', 'name': 'Resiliate contract line',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form', 'view_type': 'form',
'view_mode': 'form', 'view_mode': 'form',
'views': [(view_id, 'form')], 'views': [(view_id, 'form')],
@ -1001,7 +1003,7 @@ class AccountAnalyticInvoiceLine(models.Model):
return { return {
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'name': 'Suspend contract line', 'name': 'Suspend contract line',
'res_model': 'account.analytic.invoice.line.wizard',
'res_model': 'contract.line.wizard',
'view_type': 'form', 'view_type': 'form',
'view_mode': 'form', 'view_mode': 'form',
'views': [(view_id, 'form')], 'views': [(view_id, 'form')],
@ -1020,7 +1022,7 @@ class AccountAnalyticInvoiceLine(models.Model):
@api.multi @api.multi
def renew(self): def renew(self):
res = self.env['account.analytic.invoice.line']
res = self.env['contract.line']
for rec in self: for rec in self:
is_auto_renew = rec.is_auto_renew is_auto_renew = rec.is_auto_renew
rec.stop(rec.date_end, post_message=False) 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') default_contract_type = self.env.context.get('default_contract_type')
if view_type == 'tree' and default_contract_type == 'purchase': if view_type == 'tree' and default_contract_type == 'purchase':
view_id = self.env.ref( view_id = self.env.ref(
'contract.account_analytic_invoice_line_purchase_view_tree'
'contract.contract_line_supplier_tree_view'
).id ).id
if view_type == 'form': if view_type == 'form':
if default_contract_type == 'purchase': if default_contract_type == 'purchase':
view_id = self.env.ref( view_id = self.env.ref(
'contract.account_analytic_invoice_line_purchase_view_form'
'contract.contract_line_supplier_form_view'
).id ).id
elif default_contract_type == 'sale': elif default_contract_type == 'sale':
view_id = self.env.ref( view_id = self.env.ref(
'contract.account_analytic_invoice_line_sale_view_form'
'contract.contract_line_customer_form_view'
).id ).id
return super(AccountAnalyticInvoiceLine, self).fields_view_get(
return super(ContractLine, self).fields_view_get(
view_id, view_type, toolbar, submenu view_id, view_type, toolbar, submenu
) )
@ -1089,7 +1091,7 @@ class AccountAnalyticInvoiceLine(models.Model):
raise ValidationError( raise ValidationError(
_("Contract line must be canceled before delete") _("Contract line must be canceled before delete")
) )
return super(AccountAnalyticInvoiceLine, self).unlink()
return super(ContractLine, self).unlink()
@api.multi @api.multi
def _get_quantity_to_invoice( def _get_quantity_to_invoice(

15
contract/models/contract_template.py

@ -9,14 +9,15 @@
from odoo import fields, models 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', inverse_name='contract_id',
copy=True, 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 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" _order = "sequence,id"
contract_id = fields.Many2one( contract_id = fields.Many2one(
string='Contract', string='Contract',
comodel_name='account.analytic.contract',
comodel_name='contract.template',
required=True, required=True,
ondelete='cascade', ondelete='cascade',
oldname='analytic_account_id', oldname='analytic_account_id',

6
contract/models/res_partner.py

@ -15,7 +15,7 @@ class ResPartner(models.Model):
) )
def _compute_contract_count(self): def _compute_contract_count(self):
contract_model = self.env['account.analytic.account']
contract_model = self.env['contract.contract']
fetch_data = contract_model.read_group( fetch_data = contract_model.read_group(
[ [
('recurring_invoices', '=', True), ('recurring_invoices', '=', True),
@ -69,9 +69,9 @@ class ResPartner(models.Model):
def _get_act_window_contract_xml(self, contract_type): def _get_act_window_contract_xml(self, contract_type):
if contract_type == 'purchase': if contract_type == 'purchase':
return self.env['ir.actions.act_window'].for_xml_id( return self.env['ir.actions.act_window'].for_xml_id(
'contract', 'action_account_analytic_purchase_overdue_all'
'contract', 'action_supplier_contract'
) )
else: else:
return self.env['ir.actions.act_window'].for_xml_id( 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 <report
id="report_contract" id="report_contract"
model="account.analytic.account"
model="contract.contract"
string="Contract" string="Contract"
report_type="qweb-pdf" report_type="qweb-pdf"
name="contract.report_contract_document" name="contract.report_contract_document"

2
contract/report/report_contract.xml

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

10
contract/views/abstract_contract_line.xml

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <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"> <field name="arch" type="xml">
<form> <form>
<header/>
<sheet> <sheet>
<group col="4"> <group col="4">
<field colspan="4" name="product_id"/> <field colspan="4" name="product_id"/>

156
contract/views/contract.xml

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <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"> <field name="arch" type="xml">
<form> <form>
<header> <header>
@ -70,7 +70,7 @@
<notebook> <notebook>
<page name="recurring_invoice_line" <page name="recurring_invoice_line"
string="Recurring Invoices"> string="Recurring Invoices">
<field name="recurring_invoice_line_ids"
<field name="contract_line_ids"
context="{'default_contract_type': contract_type}"/> context="{'default_contract_type': contract_type}"/>
</page> </page>
<page name="info" string="Other Information"> <page name="info" string="Other Information">
@ -119,20 +119,18 @@
</field> </field>
</record> </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="mode">primary</field>
<field name="priority" eval="20"/> <field name="priority" eval="20"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="partner_id" position="attributes"> <field name="partner_id" position="attributes">
<attribute name="string">Customer</attribute> <attribute name="string">Customer</attribute>
<attribute name="domain">[('customer', '=', True)]</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>
<field name="journal_id" position="attributes"> <field name="journal_id" position="attributes">
<attribute name="domain">[('type', '=', 'sale'),('company_id', '=', company_id)]</attribute> <attribute name="domain">[('type', '=', 'sale'),('company_id', '=', company_id)]</attribute>
@ -140,20 +138,18 @@
</field> </field>
</record> </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="mode">primary</field>
<field name="priority" eval="20"/> <field name="priority" eval="20"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="partner_id" position="attributes"> <field name="partner_id" position="attributes">
<attribute name="string">Supplier</attribute> <attribute name="string">Supplier</attribute>
<attribute name="domain">[('supplier', '=', True)]</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>
<field name="journal_id" position="attributes"> <field name="journal_id" position="attributes">
<attribute name="domain">[('type', '=', 'purchase'),('company_id', '=', company_id)]</attribute> <attribute name="domain">[('type', '=', 'purchase'),('company_id', '=', company_id)]</attribute>
@ -161,30 +157,30 @@
</field> </field>
</record> </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="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 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> </field>
</record> </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="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="journal_id"/>
<field name="pricelist_id"/> <field name="pricelist_id"/>
<separator/> <separator/>
@ -201,37 +197,44 @@
string="Finished" string="Finished"
domain="[('date_end', '&lt;', context_today().strftime('%Y-%m-%d')), ('recurring_next_date', '=', False)]" 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..."> <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" string="Next Invoice"
domain="[('recurring_next_date', '!=', False)]" domain="[('recurring_next_date', '!=', False)]"
context="{'group_by':'recurring_next_date'}" context="{'group_by':'recurring_next_date'}"
/> />
<filter name="date_end"
<filter name="group_by_date_end"
string="Date End" string="Date End"
domain="[]" domain="[]"
context="{'group_by':'date_end'}" context="{'group_by':'date_end'}"
/> />
</group> </group>
</field>
</search>
</field> </field>
</record> </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="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_type">form</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
<field name="domain">[('contract_type', '=', 'sale')]</field> <field name="domain">[('contract_type', '=', 'sale')]</field>
<field name="context">{'is_contract':1, <field name="context">{'is_contract':1,
'search_default_not_finished':1, 'search_default_not_finished':1,
'search_default_recurring_invoices':1, 'search_default_recurring_invoices':1,
'default_recurring_invoices': 1, 'default_contract_type': 'sale'}
'default_recurring_invoices': 1,
'default_contract_type': 'sale'}
</field> </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"> <field name="help" type="html">
<p class="oe_view_nocontent_create"> <p class="oe_view_nocontent_create">
Click to create a new contract. Click to create a new contract.
@ -239,47 +242,41 @@
</field> </field>
</record> </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="sequence" eval="1"/>
<field name="view_mode">tree</field> <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>
<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="sequence" eval="2"/>
<field name="view_mode">form</field> <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> </record>
<menuitem id="menu_action_account_analytic_sale_overdue_all"
<menuitem id="menu_contract_contract_customer"
parent="account.menu_finance_receivables" parent="account.menu_finance_receivables"
action="action_account_analytic_sale_overdue_all"
action="action_customer_contract"
sequence="99" 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="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_type">form</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
<field name="domain">[('contract_type', '=', 'purchase')]</field> <field name="domain">[('contract_type', '=', 'purchase')]</field>
<field name="context">{'is_contract':1, <field name="context">{'is_contract':1,
'search_default_not_finished':1, 'search_default_not_finished':1,
'search_default_recurring_invoices':1, 'search_default_recurring_invoices':1,
'default_recurring_invoices': 1, 'default_contract_type':
'default_recurring_invoices': 1,
'default_contract_type':
'purchase'} 'purchase'}
</field> </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"> <field name="help" type="html">
<p class="oe_view_nocontent_create"> <p class="oe_view_nocontent_create">
Click to create a new contract. Click to create a new contract.
@ -287,28 +284,23 @@
</field> </field>
</record> </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="sequence" eval="1"/>
<field name="view_mode">tree</field> <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>
<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="sequence" eval="2"/>
<field name="view_mode">form</field> <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> </record>
<menuitem id="menu_action_account_analytic_purchase_overdue_all"
<menuitem id="menu_contract_contract_supplier"
parent="account.menu_finance_payables" parent="account.menu_finance_payables"
action="action_account_analytic_purchase_overdue_all"
action="action_supplier_contract"
sequence="99" sequence="99"
/> />

75
contract/views/contract_line.xml

@ -1,22 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <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="mode">primary</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//sheet" position="before">
<header>
<header position="inside">
<field name="state" widget="statusbar"/> <field name="state" widget="statusbar"/>
</header> </header>
</xpath>
<xpath expr="//form" position="attributes">
<attribute name="string">Contract Line</attribute>
</xpath>
<xpath expr="//group[@name='recurrence_info']" position="inside">
<group name="recurrence_info" position="inside">
<group> <group>
<field name="create_invoice_visibility" invisible="1"/> <field name="create_invoice_visibility" invisible="1"/>
<field name="date_start" required="1"/> <field name="date_start" required="1"/>
@ -33,23 +28,21 @@
<group> <group>
<field name="manual_renew_needed"/> <field name="manual_renew_needed"/>
</group> </group>
<group> <group>
<field name="predecessor_contract_line_id"/> <field name="predecessor_contract_line_id"/>
</group> </group>
<group> <group>
<field name="successor_contract_line_id"/> <field name="successor_contract_line_id"/>
</group> </group>
</xpath>
</group>
</field> </field>
</record> </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="mode">primary</field>
<field name="priority" eval="20"/> <field name="priority" eval="20"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
@ -59,29 +52,27 @@
</field> </field>
</record> </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="mode">primary</field>
<field name="priority" eval="20"/> <field name="priority" eval="20"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="product_id" position="attributes"> <field name="product_id" position="attributes">
<attribute name="domain">[('purchase_ok', '=', True)]
</attribute>
<attribute name="domain">[('purchase_ok', '=', True)]</attribute>
</field> </field>
<xpath expr="//field[@name='automatic_price']"
position="attributes">
<field name="automatic_price" position="attributes">
<attribute name="invisible">True</attribute> <attribute name="invisible">True</attribute>
</xpath>
</field>
</field> </field>
</record> </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"> <field name="arch" type="xml">
<tree decoration-muted="is_canceled" <tree decoration-muted="is_canceled"
decoration-info="create_invoice_visibility and not is_canceled"> decoration-info="create_invoice_visibility and not is_canceled">
@ -155,19 +146,17 @@
</field> </field>
</record> </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="mode">primary</field>
<field name="priority" eval="20"/> <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"> <field name="arch" type="xml">
<xpath expr="//field[@name='automatic_price']"
position="attributes">
<field name="automatic_price" position="attributes">
<attribute name="invisible">True</attribute> <attribute name="invisible">True</attribute>
</xpath>
</field>
</field> </field>
</record> </record>

42
contract/views/contract_template.xml

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <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"> <field name="arch" type="xml">
<form string="Contract Template"> <form string="Contract Template">
<group name="name"> <group name="name">
@ -17,9 +18,9 @@
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/> <field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group> </group>
</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="sequence" widget="handle" />
<field name="product_id" /> <field name="product_id" />
<field name="name" /> <field name="name" />
@ -46,11 +47,12 @@
</field> </field>
</record> </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"> <field name="arch" type="xml">
<tree string="Contract Templates">
<tree>
<field name="name" /> <field name="name" />
<field name="contract_type" /> <field name="contract_type" />
<field name="pricelist_id" /> <field name="pricelist_id" />
@ -58,11 +60,12 @@
</field> </field>
</record> </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"> <field name="arch" type="xml">
<search string="Contract Templates">
<search>
<field name="name" /> <field name="name" />
<field name="contract_type" /> <field name="contract_type" />
<field name="pricelist_id" /> <field name="pricelist_id" />
@ -83,12 +86,13 @@
</field> </field>
</record> </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="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_type">form</field>
<field name="view_mode">tree,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"> <field name="help" type="html">
<p class="oe_view_nocontent_create"> <p class="oe_view_nocontent_create">
Click to create a new contract template. Click to create a new contract template.
@ -102,9 +106,9 @@
parent="account.menu_finance_configuration" parent="account.menu_finance_configuration"
/> />
<menuitem id="account_analytic_contract_menu"
<menuitem id="contract_template_menu"
parent="menu_config_contract" parent="menu_config_contract"
action="account_analytic_contract_action"
action="contract_template_action"
sequence="1" sequence="1"
/> />

16
contract/views/contract_template_line.xml

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <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="mode">primary</field>
<field name="arch" type="xml"> <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> </field>
</record> </record>

6
contract/wizards/contract_line_wizard.py

@ -4,9 +4,9 @@
from odoo import api, fields, models 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' _description = 'Contract Line Wizard'
date_start = fields.Date(string='Date Start') date_start = fields.Date(string='Date Start')
@ -21,7 +21,7 @@ class AccountAnalyticInvoiceLineWizard(models.TransientModel):
"successor in advance", "successor in advance",
) )
contract_line_id = fields.Many2one( contract_line_id = fields.Many2one(
comodel_name="account.analytic.invoice.line",
comodel_name="contract.line",
string="Contract Line", string="Contract Line",
required=True, required=True,
index=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"> <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="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"> <field name="arch" type="xml">
<form> <form>
<group> <group>
@ -29,7 +29,7 @@
<record model="ir.ui.view" id="contract_line_wizard_plan_successor_form_view"> <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="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"> <field name="arch" type="xml">
<form> <form>
<group> <group>
@ -53,7 +53,7 @@
<record model="ir.ui.view" id="contract_line_wizard_stop_plan_successor_form_view"> <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="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"> <field name="arch" type="xml">
<form> <form>
<group> <group>
@ -77,7 +77,7 @@
<record model="ir.ui.view" id="contract_line_wizard_uncancel_form_view"> <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="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"> <field name="arch" type="xml">
<form> <form>
<group> <group>

Loading…
Cancel
Save