mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[REF] Contract Sale Invoicing: split from analytic account
[REF] Contract Sale Invoicing: update translations [IMP] - Assert that the predecessor is available for new link at uncancel [RMV] - remove usless changes [RMV] - Remove usless field recurring_invoices after the total isolation between contract model and account analytic one. recurring_invoices which was used to mark analytic account as contract became usless [IMP] - P3 syntax [IMP] - use @openupgrade.migrate() and openupgrade.logged_query [IMP] - drop transient table in migration script
This commit is contained in:
committed by
Francisco Ivan Anton Prieto
parent
3ca769e079
commit
c770e97adb
@@ -15,7 +15,6 @@
|
||||
'author': "OpenERP SA, "
|
||||
"Tecnativa, "
|
||||
"LasLabs, "
|
||||
"ACSONE SA/NV, "
|
||||
"Odoo Community Association (OCA)",
|
||||
'website': 'https://github.com/oca/contract',
|
||||
'depends': ['base', 'account', 'product'],
|
||||
|
||||
@@ -11,7 +11,7 @@ _logger = logging.getLogger(__name__)
|
||||
def migrate(cr, version):
|
||||
"""Copy recurrence info from contract to contract lines and compute
|
||||
last_date_invoiced"""
|
||||
|
||||
_logger.info(">> Post-Migration 12.0.2.0.0")
|
||||
cr.execute(
|
||||
"""UPDATE account_analytic_invoice_line AS contract_line
|
||||
SET recurring_rule_type=contract.recurring_rule_type,
|
||||
@@ -23,8 +23,6 @@ def migrate(cr, version):
|
||||
FROM account_analytic_account AS contract
|
||||
WHERE contract.id=contract_line.contract_id"""
|
||||
)
|
||||
|
||||
_logger.info("order all contract line")
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
contract_lines = env["account.analytic.invoice.line"].search(
|
||||
[("recurring_next_date", "!=", False)]
|
||||
|
||||
@@ -12,7 +12,7 @@ def migrate(cr, version):
|
||||
"""
|
||||
set recurring_next_date to false for finished contract
|
||||
"""
|
||||
_logger.info("order all contract line")
|
||||
_logger.info(">> Pre-Migration 12.0.2.0.0")
|
||||
with api.Environment(cr, SUPERUSER_ID, {}) as env:
|
||||
contracts = env["account.analytic.account"].search([])
|
||||
finished_contract = contracts.filtered(
|
||||
|
||||
@@ -9,6 +9,7 @@ _logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
_logger.info(">> Post-Migration 12.0.3.0.0")
|
||||
_logger.info("Populate invoicing partner field on contracts")
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
contracts = env["account.analytic.account"].search([])
|
||||
|
||||
@@ -8,8 +8,11 @@ from openupgradelib import openupgrade
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
cr.execute(
|
||||
@openupgrade.migrate()
|
||||
def migrate(env, version):
|
||||
cr = env.cr
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
INSERT INTO contract_contract (
|
||||
id,
|
||||
@@ -24,7 +27,6 @@ def migrate(cr, version):
|
||||
code,
|
||||
group_id,
|
||||
contract_template_id,
|
||||
recurring_invoices,
|
||||
user_id,
|
||||
recurring_next_date,
|
||||
date_end,
|
||||
@@ -49,7 +51,6 @@ def migrate(cr, version):
|
||||
code,
|
||||
group_id,
|
||||
contract_template_id,
|
||||
recurring_invoices,
|
||||
user_id,
|
||||
recurring_next_date,
|
||||
date_end,
|
||||
@@ -62,10 +63,13 @@ def migrate(cr, version):
|
||||
write_uid,
|
||||
write_date
|
||||
FROM account_analytic_account
|
||||
WHERE recurring_invoices = TRUE
|
||||
WHERE id in (
|
||||
SELECT DISTINCT contract_id FROM account_analytic_invoice_line
|
||||
)
|
||||
"""
|
||||
)
|
||||
cr.execute(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
INSERT INTO contract_line (
|
||||
id,
|
||||
@@ -126,18 +130,21 @@ def migrate(cr, version):
|
||||
)
|
||||
openupgrade.rename_models(cr, [('account.analytic.invoice.line',
|
||||
'contract.line')])
|
||||
cr.execute(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
DROP TABLE account_analytic_invoice_line
|
||||
"""
|
||||
)
|
||||
cr.execute(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
UPDATE account_invoice_line
|
||||
SET contract_line_id = contract_line_id_tmp
|
||||
"""
|
||||
)
|
||||
cr.execute(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
ALTER TABLE account_invoice_line
|
||||
DROP COLUMN contract_line_id_tmp
|
||||
|
||||
@@ -8,7 +8,16 @@ from openupgradelib import openupgrade
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
@openupgrade.migrate()
|
||||
def migrate(env, version):
|
||||
_logger.info(">> Pre-Migration 12.0.4.0.0")
|
||||
cr = env.cr
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
DROP TABLE IF EXISTS account_analytic_invoice_line_wizard
|
||||
"""
|
||||
)
|
||||
models_to_rename = [
|
||||
# Contract Line Wizard
|
||||
('account.analytic.invoice.line.wizard', 'contract.line.wizard'),
|
||||
@@ -25,8 +34,6 @@ def migrate(cr, version):
|
||||
('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
|
||||
@@ -53,19 +60,22 @@ def migrate(cr, version):
|
||||
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(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
ALTER TABLE account_invoice_line
|
||||
ADD COLUMN contract_line_id_tmp INTEGER
|
||||
"""
|
||||
)
|
||||
cr.execute(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
UPDATE account_invoice_line
|
||||
SET contract_line_id_tmp = contract_line_id
|
||||
"""
|
||||
)
|
||||
cr.execute(
|
||||
openupgrade.logged_query(
|
||||
cr,
|
||||
"""
|
||||
UPDATE account_invoice_line SET contract_line_id = NULL
|
||||
"""
|
||||
|
||||
@@ -45,9 +45,7 @@ class ContractContract(models.Model):
|
||||
copy=True,
|
||||
oldnae='contract_line_ids',
|
||||
)
|
||||
recurring_invoices = fields.Boolean(
|
||||
string='Generate recurring invoices automatically'
|
||||
)
|
||||
|
||||
user_id = fields.Many2one(
|
||||
comodel_name='res.users',
|
||||
string='Responsible',
|
||||
@@ -80,7 +78,9 @@ class ContractContract(models.Model):
|
||||
ondelete='restrict',
|
||||
)
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name='res.partner', inverse='_inverse_partner_id'
|
||||
comodel_name='res.partner',
|
||||
inverse='_inverse_partner_id',
|
||||
required=True
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@@ -225,15 +225,6 @@ class ContractContract(models.Model):
|
||||
}
|
||||
}
|
||||
|
||||
@api.constrains('partner_id', 'recurring_invoices')
|
||||
def _check_partner_id_recurring_invoices(self):
|
||||
for contract in self.filtered('recurring_invoices'):
|
||||
if not contract.partner_id:
|
||||
raise ValidationError(
|
||||
_("You must supply a partner for the contract '%s'")
|
||||
% contract.name
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _convert_contract_lines(self, contract):
|
||||
self.ensure_one()
|
||||
@@ -393,12 +384,7 @@ class ContractContract(models.Model):
|
||||
domain = []
|
||||
if not date_ref:
|
||||
date_ref = fields.Date.context_today(self)
|
||||
domain.extend(
|
||||
[
|
||||
('recurring_invoices', '=', True),
|
||||
('recurring_next_date', '<=', date_ref),
|
||||
]
|
||||
)
|
||||
domain.extend([('recurring_next_date', '<=', date_ref)])
|
||||
return domain
|
||||
|
||||
@api.multi
|
||||
|
||||
@@ -455,7 +455,7 @@ class ContractLine(models.Model):
|
||||
|
||||
@api.constrains('recurring_next_date')
|
||||
def _check_recurring_next_date_recurring_invoices(self):
|
||||
for rec in self.filtered('contract_id.recurring_invoices'):
|
||||
for rec in self:
|
||||
if not rec.recurring_next_date and (
|
||||
not rec.date_end
|
||||
or not rec.last_date_invoiced
|
||||
@@ -916,9 +916,9 @@ class ContractLine(models.Model):
|
||||
contract.message_post(body=msg)
|
||||
for rec in self:
|
||||
if rec.predecessor_contract_line_id:
|
||||
rec.predecessor_contract_line_id.successor_contract_line_id = (
|
||||
rec
|
||||
)
|
||||
predecessor_contract_line = rec.predecessor_contract_line_id
|
||||
assert not predecessor_contract_line.successor_contract_line_id
|
||||
predecessor_contract_line.successor_contract_line_id = rec
|
||||
rec.is_canceled = False
|
||||
rec.recurring_next_date = recurring_next_date
|
||||
return True
|
||||
@@ -1052,7 +1052,6 @@ class ContractLine(models.Model):
|
||||
return [
|
||||
('is_auto_renew', '=', True),
|
||||
('is_canceled', '=', False),
|
||||
('contract_id.recurring_invoices', '=', True),
|
||||
('termination_notice_date', '<=', fields.Date.context_today(self)),
|
||||
]
|
||||
|
||||
@@ -1080,7 +1079,7 @@ class ContractLine(models.Model):
|
||||
view_id = self.env.ref(
|
||||
'contract.contract_line_customer_form_view'
|
||||
).id
|
||||
return super(ContractLine, self).fields_view_get(
|
||||
return super().fields_view_get(
|
||||
view_id, view_type, toolbar, submenu
|
||||
)
|
||||
|
||||
@@ -1091,7 +1090,7 @@ class ContractLine(models.Model):
|
||||
raise ValidationError(
|
||||
_("Contract line must be canceled before delete")
|
||||
)
|
||||
return super(ContractLine, self).unlink()
|
||||
return super().unlink()
|
||||
|
||||
@api.multi
|
||||
def _get_quantity_to_invoice(
|
||||
|
||||
@@ -8,43 +8,30 @@ class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
sale_contract_count = fields.Integer(
|
||||
string='Sale Contracts', compute='_compute_contract_count'
|
||||
string='Sale Contracts',
|
||||
compute='_compute_contract_count',
|
||||
)
|
||||
purchase_contract_count = fields.Integer(
|
||||
string='Purchase Contracts', compute='_compute_contract_count'
|
||||
string='Purchase Contracts',
|
||||
compute='_compute_contract_count',
|
||||
)
|
||||
|
||||
def _compute_contract_count(self):
|
||||
contract_model = self.env['contract.contract']
|
||||
fetch_data = contract_model.read_group(
|
||||
[
|
||||
('recurring_invoices', '=', True),
|
||||
('partner_id', 'child_of', self.ids),
|
||||
],
|
||||
['partner_id', 'contract_type'],
|
||||
['partner_id', 'contract_type'],
|
||||
lazy=False,
|
||||
)
|
||||
result = [
|
||||
[data['partner_id'][0], data['contract_type'], data['__count']]
|
||||
for data in fetch_data
|
||||
]
|
||||
fetch_data = contract_model.read_group([
|
||||
('partner_id', 'child_of', self.ids)],
|
||||
['partner_id', 'contract_type'], ['partner_id', 'contract_type'],
|
||||
lazy=False)
|
||||
result = [[data['partner_id'][0], data['contract_type'],
|
||||
data['__count']] for data in fetch_data]
|
||||
for partner in self:
|
||||
partner_child_ids = partner.child_ids.ids + partner.ids
|
||||
partner.sale_contract_count = sum(
|
||||
[
|
||||
r[2]
|
||||
for r in result
|
||||
if r[0] in partner_child_ids and r[1] == 'sale'
|
||||
]
|
||||
)
|
||||
partner.purchase_contract_count = sum(
|
||||
[
|
||||
r[2]
|
||||
for r in result
|
||||
if r[0] in partner_child_ids and r[1] == 'purchase'
|
||||
]
|
||||
)
|
||||
partner.sale_contract_count = sum([
|
||||
r[2] for r in result
|
||||
if r[0] in partner_child_ids and r[1] == 'sale'])
|
||||
partner.purchase_contract_count = sum([
|
||||
r[2] for r in result
|
||||
if r[0] in partner_child_ids and r[1] == 'purchase'])
|
||||
|
||||
def act_show_contract(self):
|
||||
""" This opens contract view
|
||||
@@ -57,12 +44,10 @@ class ResPartner(models.Model):
|
||||
res.update(
|
||||
context=dict(
|
||||
self.env.context,
|
||||
search_default_recurring_invoices=True,
|
||||
search_default_partner_id=self.id,
|
||||
default_partner_id=self.id,
|
||||
default_recurring_invoices=True,
|
||||
default_pricelist_id=self.property_product_pricelist.id,
|
||||
)
|
||||
),
|
||||
)
|
||||
return res
|
||||
|
||||
|
||||
@@ -9,54 +9,34 @@
|
||||
<div class="oe_structure"/>
|
||||
<div class="row" id="partner_info">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<p id="partner_info">
|
||||
<strong>Partner:</strong>
|
||||
</p>
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "mobile", "fax", "email"], "no_marker": true, "phone_icons": true}'/>
|
||||
<p t-if="o.partner_id.vat">VAT:
|
||||
<span t-field="o.partner_id.vat"/>
|
||||
</p>
|
||||
<p id="partner_info"><strong>Partner:</strong></p>
|
||||
<div t-field="o.partner_id" t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "mobile", "fax", "email"], "no_marker": true, "phone_icons": true}'/>
|
||||
<p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="header_info">
|
||||
<div class="col-xs-3">
|
||||
<strong>Responsible:</strong>
|
||||
<p t-field="o.user_id"/>
|
||||
<strong>Contract:</strong>
|
||||
<p t-field="o.code"/>
|
||||
<strong>Responsible: </strong><p t-field="o.user_id"/>
|
||||
<strong>Contract: </strong><p t-field="o.code"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="invoice_info">
|
||||
<t t-set="total" t-value="0"/>
|
||||
<div class="col-xs-12">
|
||||
<t t-set="total" t-value="0"/>
|
||||
<p id="services_info">
|
||||
<strong>Recurring Items</strong>
|
||||
</p>
|
||||
<p id="services_info"><strong>Recurring Items</strong></p>
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<strong>Description</strong>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
<strong>Quantity</strong>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
<strong>Unit Price</strong>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
<strong>Price</strong>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
<strong>Date Start</strong>
|
||||
</th>
|
||||
<th><strong>Description</strong></th>
|
||||
<th class="text-right"><strong>Quantity</strong></th>
|
||||
<th class="text-right"><strong>Unit Price</strong></th>
|
||||
<th class="text-right"><strong>Price</strong></th>
|
||||
<th class="text-right"><strong>Date Start</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="o.contract_line_ids"
|
||||
t-as="l">
|
||||
<tr t-foreach="o.recurring_invoice_line_ids" t-as="l">
|
||||
<td>
|
||||
<span t-field="l.name"/>
|
||||
</td>
|
||||
@@ -64,18 +44,15 @@
|
||||
<span t-field="l.quantity"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.price_unit"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
<span t-field="l.price_unit" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.price_subtotal"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
<span t-field="l.price_subtotal" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="l.date_start"/>
|
||||
</td>
|
||||
<t t-set="total"
|
||||
t-value="total + l.price_subtotal"/>
|
||||
<t t-set="total" t-value="total + l.price_subtotal"/>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -83,12 +60,9 @@
|
||||
<div class="col-xs-4 pull-right">
|
||||
<table class="table table-condensed">
|
||||
<tr class="border-black">
|
||||
<td>
|
||||
<strong>Total</strong>
|
||||
</td>
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-esc="total"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
<span t-esc="total" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -16,7 +16,7 @@ def to_date(date):
|
||||
class TestContractBase(common.SavepointCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestContractBase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.today = fields.Date.today()
|
||||
cls.partner = cls.env.ref('base.res_partner_2')
|
||||
cls.product_1 = cls.env.ref('product.product_product_1')
|
||||
@@ -56,7 +56,6 @@ class TestContractBase(common.SavepointCase):
|
||||
'name': 'Test Contract',
|
||||
'partner_id': cls.partner.id,
|
||||
'pricelist_id': cls.partner.property_product_pricelist.id,
|
||||
'recurring_invoices': True,
|
||||
}
|
||||
)
|
||||
cls.contract2 = cls.env['contract.contract'].create(
|
||||
@@ -64,7 +63,6 @@ class TestContractBase(common.SavepointCase):
|
||||
'name': 'Test Contract 2',
|
||||
'partner_id': cls.partner.id,
|
||||
'pricelist_id': cls.partner.property_product_pricelist.id,
|
||||
'recurring_invoices': True,
|
||||
'contract_type': 'purchase',
|
||||
'contract_line_ids': [
|
||||
(
|
||||
@@ -141,8 +139,6 @@ class TestContract(TestContractBase):
|
||||
res = self.acct_line._onchange_product_id()
|
||||
self.assertIn('uom_id', res['domain'])
|
||||
self.acct_line.price_unit = 100.0
|
||||
with self.assertRaises(ValidationError):
|
||||
self.contract.partner_id = False
|
||||
self.contract.partner_id = self.partner.id
|
||||
self.contract.recurring_create_invoice()
|
||||
self.invoice_monthly = self.contract._get_related_invoices()
|
||||
@@ -388,11 +384,6 @@ class TestContract(TestContractBase):
|
||||
}
|
||||
)
|
||||
|
||||
def test_check_recurring_next_date_recurring_invoices(self):
|
||||
with self.assertRaises(ValidationError):
|
||||
self.contract.write({'recurring_invoices': True})
|
||||
self.acct_line.write({'recurring_next_date': False})
|
||||
|
||||
def test_onchange_contract_template_id(self):
|
||||
"""It should change the contract values to match the template."""
|
||||
self.contract.contract_template_id = False
|
||||
|
||||
@@ -74,11 +74,6 @@
|
||||
context="{'default_contract_type': contract_type}"/>
|
||||
</page>
|
||||
<page name="info" string="Other Information">
|
||||
<div invisible="1">
|
||||
<field name="recurring_invoices"
|
||||
class="oe_inline"/>
|
||||
<label for="recurring_invoices"/>
|
||||
</div>
|
||||
<field name="create_invoice_visibility"
|
||||
invisible="1"/>
|
||||
<group>
|
||||
@@ -184,10 +179,6 @@
|
||||
<field name="journal_id"/>
|
||||
<field name="pricelist_id"/>
|
||||
<separator/>
|
||||
<filter name="recurring_invoices"
|
||||
string="Recurring Invoices"
|
||||
domain="[('recurring_invoices','=',True)]"
|
||||
/>
|
||||
<separator/>
|
||||
<filter name="not_finished"
|
||||
string="In progress"
|
||||
@@ -230,8 +221,6 @@
|
||||
<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'}
|
||||
</field>
|
||||
<field name="search_view_id" ref="contract_contract_search_view"/>
|
||||
@@ -271,10 +260,7 @@
|
||||
<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'}
|
||||
'default_contract_type': 'purchase'}
|
||||
</field>
|
||||
<field name="search_view_id" ref="contract_contract_search_view"/>
|
||||
<field name="help" type="html">
|
||||
|
||||
Reference in New Issue
Block a user