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 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