Browse Source
[12.0][IMP] - Add strat/stop wizard to contract line
[12.0][IMP] - Add strat/stop wizard to contract line
[12.0][IMP] - Add pause button to contract line [IMP] - Add state filed in contract line form [FIX] - stop don't change date_end for finished contract line [IMP] - Change contract line buttons visibility Add renewal process with termination notice [FIX] - don't consider stop_date If it is after the contract line end_date [IMP] - consider more cases in stop_plan_successor [IMP] - cancel upcoming line on stop [IMP] - Chnage next invoice date on un-cancel [IMP] - Post message in contract on contract line actions [IMP] - check contract line overlappull/207/head
sbejaoui
6 years ago
14 changed files with 1724 additions and 119 deletions
-
1contract/__init__.py
-
2contract/__manifest__.py
-
1contract/data/__init__.py
-
230contract/data/contract_line_constraints.py
-
16contract/data/contract_renew_cron.xml
-
24contract/models/abstract_contract_line.py
-
534contract/models/contract_line.py
-
583contract/tests/test_contract.py
-
60contract/views/abstract_contract_line.xml
-
173contract/views/contract.xml
-
13contract/views/contract_line.xml
-
1contract/wizards/__init__.py
-
48contract/wizards/contract_line_wizard.py
-
99contract/wizards/contract_line_wizard.xml
@ -1 +1,2 @@ |
|||||
from . import models |
from . import models |
||||
|
from . import wizards |
@ -0,0 +1 @@ |
|||||
|
from . import contract_line_constraints |
@ -0,0 +1,230 @@ |
|||||
|
# Copyright 2018 ACSONE SA/NV. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from collections import namedtuple |
||||
|
from odoo.fields import Date |
||||
|
|
||||
|
CRITERIA = namedtuple( |
||||
|
'CRITERIA', |
||||
|
['WHEN', 'HAS_DATE_END', 'IS_AUTO_RENEW', 'HAS_SUCCESSOR', 'CANCELED'], |
||||
|
) |
||||
|
ALLOWED = namedtuple( |
||||
|
'ALLOWED', |
||||
|
['PLAN_SUCCESSOR', 'STOP_PLAN_SUCCESSOR', 'STOP', 'CANCEL', 'UN_CANCEL'], |
||||
|
) |
||||
|
|
||||
|
CRITERIA_ALLOWED_DICT = { |
||||
|
CRITERIA( |
||||
|
WHEN='BEFORE', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=True, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=True, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='BEFORE', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=True, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=False, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='BEFORE', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=True, |
||||
|
STOP_PLAN_SUCCESSOR=True, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='BEFORE', |
||||
|
HAS_DATE_END=False, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=True, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='IN', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=True, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=True, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='IN', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=True, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=False, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='IN', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=True, |
||||
|
STOP_PLAN_SUCCESSOR=True, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='IN', |
||||
|
HAS_DATE_END=False, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=True, |
||||
|
STOP=True, |
||||
|
CANCEL=True, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='AFTER', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=True, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=False, |
||||
|
STOP=False, |
||||
|
CANCEL=False, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='AFTER', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=True, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=False, |
||||
|
STOP=False, |
||||
|
CANCEL=False, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN='AFTER', |
||||
|
HAS_DATE_END=True, |
||||
|
IS_AUTO_RENEW=False, |
||||
|
HAS_SUCCESSOR=False, |
||||
|
CANCELED=False, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=True, |
||||
|
STOP_PLAN_SUCCESSOR=False, |
||||
|
STOP=False, |
||||
|
CANCEL=False, |
||||
|
UN_CANCEL=False, |
||||
|
), |
||||
|
CRITERIA( |
||||
|
WHEN=None, |
||||
|
HAS_DATE_END=None, |
||||
|
IS_AUTO_RENEW=None, |
||||
|
HAS_SUCCESSOR=None, |
||||
|
CANCELED=True, |
||||
|
): ALLOWED( |
||||
|
PLAN_SUCCESSOR=False, |
||||
|
STOP_PLAN_SUCCESSOR=False, |
||||
|
STOP=False, |
||||
|
CANCEL=False, |
||||
|
UN_CANCEL=True, |
||||
|
), |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def compute_when(date_start, date_end): |
||||
|
today = Date.today() |
||||
|
if today < date_start: |
||||
|
return 'BEFORE' |
||||
|
if date_end and today > date_end: |
||||
|
return 'AFTER' |
||||
|
return 'IN' |
||||
|
|
||||
|
|
||||
|
def compute_criteria( |
||||
|
date_start, |
||||
|
date_end, |
||||
|
is_auto_renew, |
||||
|
successor_contract_line_id, |
||||
|
is_canceled, |
||||
|
): |
||||
|
if is_canceled: |
||||
|
return CRITERIA( |
||||
|
WHEN=None, |
||||
|
HAS_DATE_END=None, |
||||
|
IS_AUTO_RENEW=None, |
||||
|
HAS_SUCCESSOR=None, |
||||
|
CANCELED=True, |
||||
|
) |
||||
|
when = compute_when(date_start, date_end) |
||||
|
has_date_end = date_end if not date_end else True |
||||
|
is_auto_renew = is_auto_renew |
||||
|
has_successor = True if successor_contract_line_id else False |
||||
|
canceled = is_canceled |
||||
|
return CRITERIA( |
||||
|
WHEN=when, |
||||
|
HAS_DATE_END=has_date_end, |
||||
|
IS_AUTO_RENEW=is_auto_renew, |
||||
|
HAS_SUCCESSOR=has_successor, |
||||
|
CANCELED=canceled, |
||||
|
) |
||||
|
|
||||
|
|
||||
|
def get_allowed( |
||||
|
date_start, |
||||
|
date_end, |
||||
|
is_auto_renew, |
||||
|
successor_contract_line_id, |
||||
|
is_canceled, |
||||
|
): |
||||
|
criteria = compute_criteria( |
||||
|
date_start, |
||||
|
date_end, |
||||
|
is_auto_renew, |
||||
|
successor_contract_line_id, |
||||
|
is_canceled, |
||||
|
) |
||||
|
if criteria in CRITERIA_ALLOWED_DICT: |
||||
|
return CRITERIA_ALLOWED_DICT[criteria] |
||||
|
return False |
@ -0,0 +1,16 @@ |
|||||
|
<?xml version="1.0" encoding='UTF-8'?> |
||||
|
<odoo noupdate="1"> |
||||
|
|
||||
|
<record model="ir.cron" id="contract_line_cron_for_renew"> |
||||
|
<field name="name">Renew Contract lines</field> |
||||
|
<field name="model_id" ref="model_account_analytic_invoice_line"/> |
||||
|
<field name="state">code</field> |
||||
|
<field name="code">model.cron_renew_contract_line()</field> |
||||
|
<field name="user_id" ref="base.user_root" /> |
||||
|
<field name="interval_number">1</field> |
||||
|
<field name="interval_type">days</field> |
||||
|
<field name="numbercall">-1</field> |
||||
|
<field eval="False" name="doall" /> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1 @@ |
|||||
|
from . import contract_line_wizard |
@ -0,0 +1,48 @@ |
|||||
|
# Copyright 2018 ACSONE SA/NV |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class AccountAnalyticInvoiceLineWizard(models.TransientModel): |
||||
|
|
||||
|
_name = 'account.analytic.invoice.line.wizard' |
||||
|
_description = 'Contract Line Wizard' |
||||
|
|
||||
|
date_start = fields.Date(string='Date Start') |
||||
|
date_end = fields.Date(string='Date End') |
||||
|
recurring_next_date = fields.Date(string='Next Invoice Date') |
||||
|
is_auto_renew = fields.Boolean(string="Auto Renew", default=False) |
||||
|
contract_line_id = fields.Many2one( |
||||
|
comodel_name="account.analytic.invoice.line", |
||||
|
string="Contract Line", |
||||
|
required=True, |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
def stop(self): |
||||
|
for wizard in self: |
||||
|
wizard.contract_line_id.stop(wizard.date_end) |
||||
|
return True |
||||
|
|
||||
|
@api.multi |
||||
|
def plan_successor(self): |
||||
|
for wizard in self: |
||||
|
wizard.contract_line_id.plan_successor( |
||||
|
wizard.date_start, wizard.date_end, wizard.is_auto_renew |
||||
|
) |
||||
|
return True |
||||
|
|
||||
|
@api.multi |
||||
|
def stop_plan_successor(self): |
||||
|
for wizard in self: |
||||
|
wizard.contract_line_id.stop_plan_successor( |
||||
|
wizard.date_start, wizard.date_end, wizard.is_auto_renew |
||||
|
) |
||||
|
return True |
||||
|
|
||||
|
@api.multi |
||||
|
def uncancel(self): |
||||
|
for wizard in self: |
||||
|
wizard.contract_line_id.uncancel(wizard.recurring_next_date) |
||||
|
return True |
@ -0,0 +1,99 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- Copyright 2018 ACSONE SA/NV |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
||||
|
|
||||
|
<odoo> |
||||
|
|
||||
|
<record model="ir.ui.view" id="contract_line_wizard_stop_form_view"> |
||||
|
<field name="name">contract.line.stop.wizard.form (in contract)</field> |
||||
|
<field name="model">account.analytic.invoice.line.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="contract_line_id" invisible="True"/> |
||||
|
<field string="Stop Date" name="date_end" required="True"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button name="stop" |
||||
|
string="Validate" |
||||
|
class="btn-primary" |
||||
|
type="object"/> |
||||
|
<button string="Cancel" |
||||
|
class="btn-default" |
||||
|
special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="contract_line_wizard_plan_successor_form_view"> |
||||
|
<field name="name">contract.line.plan_successor.wizard.form (in contract)</field> |
||||
|
<field name="model">account.analytic.invoice.line.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="contract_line_id" invisible="True"/> |
||||
|
<field name="date_start" required="True"/> |
||||
|
<field name="date_end" attrs="{'required': [('is_auto_renew', '=', True)]}"/> |
||||
|
<field name="is_auto_renew"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button name="plan_successor" |
||||
|
string="Validate" |
||||
|
class="btn-primary" |
||||
|
type="object"/> |
||||
|
<button string="Cancel" |
||||
|
class="btn-default" |
||||
|
special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="contract_line_wizard_stop_plan_successor_form_view"> |
||||
|
<field name="name">contract.line.stop_plan_successor.wizard.form (in contract)</field> |
||||
|
<field name="model">account.analytic.invoice.line.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="contract_line_id" invisible="True"/> |
||||
|
<field string="Suspension Start Date" name="date_start" required="True"/> |
||||
|
<field string="Suspension End Date" name="date_end" required="True"/> |
||||
|
<field name="is_auto_renew" invisible="1"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button name="stop_plan_successor" |
||||
|
string="Validate" |
||||
|
class="btn-primary" |
||||
|
type="object"/> |
||||
|
<button string="Cancel" |
||||
|
class="btn-default" |
||||
|
special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="contract_line_wizard_uncancel_form_view"> |
||||
|
<field name="name">contract.line.stop_plan_successor.wizard.form (in contract)</field> |
||||
|
<field name="model">account.analytic.invoice.line.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="contract_line_id" invisible="True"/> |
||||
|
<field name="recurring_next_date" required="True"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button name="uncancel" |
||||
|
string="Validate" |
||||
|
class="btn-primary" |
||||
|
type="object"/> |
||||
|
<button string="Cancel" |
||||
|
class="btn-default" |
||||
|
special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue