New field "recurrent_sequence_type" on mandate with tracking. The field "last_debit_date" is not used to compute the sequence type any more. When the bank account changes, the sequence type is set back to first FIX xml_id of expired mandate mail.message.subtype

This commit is contained in:
Alexis de Lattre
2013-11-11 02:10:35 +01:00
committed by Enric Tobella
parent 1c7c1069d2
commit 90c3dc1ab9
3 changed files with 117 additions and 36 deletions

View File

@@ -105,6 +105,17 @@ class sdd_mandate(orm.Model):
lambda self, cr, uid, obj, ctx=None: obj['state'] == 'expired',
'account_banking_sepa_direct_debit.mandate_cancel':
lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel',
},
'recurrent_sequence_type': {
'account_banking_sepa_direct_debit.recurrent_sequence_type_first':
lambda self, cr, uid, obj, ctx=None:
obj['recurrent_sequence_type'] == 'first',
'account_banking_sepa_direct_debit.recurrent_sequence_type_recurring':
lambda self, cr, uid, obj, ctx=None:
obj['recurrent_sequence_type'] == 'recurring',
'account_banking_sepa_direct_debit.recurrent_sequence_type_final':
lambda self, cr, uid, obj, ctx=None:
obj['recurrent_sequence_type'] == 'final',
}
}
@@ -120,17 +131,22 @@ class sdd_mandate(orm.Model):
('recurrent', 'Recurrent'),
('oneoff', 'One-Off'),
], 'Type of Mandate', required=True),
'recurrent_sequence_type': fields.selection([
('first', 'First'),
('recurring', 'Recurring'),
('final', 'Final'),
], 'Sequence Type for Next Debit',
help="This field is only used for Recurrent mandates, not for One-Off mandates."),
'signature_date': fields.date('Date of Signature of the Mandate'),
'scan': fields.binary('Scan of the mandate'),
'last_debit_date': fields.date(
'Date of the Last Debit',
help="For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not."),
'Date of the Last Debit', readonly=True),
'state': fields.selection([
('draft', 'Draft'),
('valid', 'Valid'),
('expired', 'Expired'),
('cancel', 'Cancelled'),
], 'Mandate Status',
], 'Status',
help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), # TODO : update help
'payment_line_ids': fields.one2many(
'payment.line', 'sdd_mandate_id', "Related Payment Lines"),
@@ -154,7 +170,8 @@ class sdd_mandate(orm.Model):
def _check_sdd_mandate(self, cr, uid, ids, context=None):
for mandate in self.read(cr, uid, ids, [
'last_debit_date', 'signature_date',
'unique_mandate_reference', 'state', 'partner_bank_id'
'unique_mandate_reference', 'state', 'partner_bank_id',
'type', 'recurrent_sequence_type',
], context=context):
if (mandate['signature_date'] and
mandate['signature_date'] >
@@ -171,7 +188,7 @@ class sdd_mandate(orm.Model):
if mandate['state'] == 'valid' and not mandate['partner_bank_id']:
raise orm.except_orm(
_('Error:'),
_("Cannot validate the mandate '%s' because it is not linked to a bank account.")
_("Cannot validate the mandate '%s' because it is not attached to a bank account.")
% mandate['unique_mandate_reference'])
if (mandate['signature_date'] and mandate['last_debit_date'] and
@@ -180,13 +197,45 @@ class sdd_mandate(orm.Model):
_('Error:'),
_("The mandate '%s' can't have a date of last debit before the date of signature.")
% mandate['unique_mandate_reference'])
if (mandate['type'] == 'recurrent'
and not mandate['recurrent_sequence_type']):
raise orm.except_orm(
_('Error:'),
_("The recurrent mandate '%s' must have a sequence type.")
% mandate['unique_mandate_reference'])
return True
_constraints = [
(_check_sdd_mandate, "Error msg in raise",
['last_debit_date', 'signature_date', 'state', 'partner_bank_id']),
(_check_sdd_mandate, "Error msg in raise", [
'last_debit_date', 'signature_date', 'state', 'partner_bank_id',
'type', 'recurrent_sequence_type',
]),
]
def mandate_type_change(self, cr, uid, ids, type):
if type == 'recurrent':
recurrent_sequence_type = 'first'
else:
recurrent_sequence_type = False
res = {'value': {'recurrent_sequence_type': recurrent_sequence_type}}
return res
def mandate_partner_bank_change(
self, cr, uid, ids, partner_bank_id, type, recurrent_sequence_type,
last_debit_date, state):
if (state == 'valid' and partner_bank_id
and type == 'recurrent'
and recurrent_sequence_type != 'first'):
return {
'value': {'recurrent_sequence_type': first},
'warning': {
'title': _('Mandate update'),
'message': _("As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'."),
}
}
else:
return True
def validate(self, cr, uid, ids, context=None):
to_validate_ids = []
for mandate in self.browse(cr, uid, ids, context=context):

View File

@@ -97,11 +97,12 @@
<group name="main">
<field name="company_id" groups="base.group_multi_company"/>
<field name="partner_id" invisible="not context.get('sdd_mandate_main_view')"/>
<field name="type"/>
<field name="type" on_change="mandate_type_change(type)"/>
<field name="recurrent_sequence_type" attrs="{'invisible': [('type', '=', 'oneoff')], 'required': [('type', '=', 'recurrent')]}"/>
<field name="signature_date"/>
<field name="scan"/>
<field name="last_debit_date"/>
<field name="partner_bank_id" invisible="not context.get('sdd_mandate_main_view')"/>
<field name="partner_bank_id" on_change="mandate_partner_bank_change(partner_bank_id, type, recurrent_sequence_type, last_debit_date, state)" invisible="not context.get('sdd_mandate_main_view')"/>
</group>
<group name="payment_lines" string="Related Payment Lines">
<field name="payment_line_ids" nolabel="1"/>
@@ -119,14 +120,14 @@
<field name="name">sdd.mandate.tree</field>
<field name="model">sdd.mandate</field>
<field name="arch" type="xml">
<tree string="SEPA Direct Debit Mandate" colors="blue:state=='draft';black:state=='expired'">
<tree string="SEPA Direct Debit Mandate" colors="blue:state=='draft';black:state in ('expired', 'cancel')">
<field name="company_id" groups="base.group_multi_company"/>
<field name="partner_id" invisible="not context.get('sdd_mandate_main_view')"/>
<field name="unique_mandate_reference" string="Reference"/>
<field name="type" string="Type"/>
<field name="signature_date" string="Signature Date"/>
<field name="last_debit_date"/>
<field name="state" string="Status"/>
<field name="state"/>
</tree>
</field>
</record>
@@ -139,6 +140,7 @@
<field name="partner_id"/>
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]" />
<filter name="valid" string="Valid" domain="[('state', '=', 'valid')]" />
<filter name="cancel" string="Cancelled" domain="[('state', '=', 'cancel')]" />
<filter name="expired" string="Expired" domain="[('state', '=', 'expired')]" />
<filter name="oneoff" string="One-Off" domain="[('type', '=', 'oneoff')]" />
<filter name="recurrent" string="Recurrent" domain="[('type', '=', 'recurrent')]" />
@@ -175,7 +177,7 @@
<field name="description">SEPA Direct Debit Mandate Validated</field>
</record>
<record id="mandate_expire" model="mail.message.subtype">
<record id="mandate_expired" model="mail.message.subtype">
<field name="name">Mandate Expired</field>
<field name="res_model">sdd.mandate</field>
<field name="default" eval="False"/>
@@ -189,6 +191,27 @@
<field name="description">SEPA Direct Debit Mandate Cancelled</field>
</record>
<record id="recurrent_sequence_type_first" model="mail.message.subtype">
<field name="name">Sequence Type set to First</field>
<field name="res_model">sdd.mandate</field>
<field name="default" eval="False"/>
<field name="description">Sequence Type set to First</field>
</record>
<record id="recurrent_sequence_type_recurring" model="mail.message.subtype">
<field name="name">Sequence Type set to Recurring</field>
<field name="res_model">sdd.mandate</field>
<field name="default" eval="False"/>
<field name="description">Sequence Type set to Recurring</field>
</record>
<record id="recurrent_sequence_type_final" model="mail.message.subtype">
<field name="name">Sequence Type set to Final</field>
<field name="res_model">sdd.mandate</field>
<field name="default" eval="False"/>
<field name="description">Sequence Type set to Final</field>
</record>
<record id="sdd_mandate_partner_bank_form" model="ir.ui.view">
<field name="name">sdd.mandate.res.partner.bank.form</field>

View File

@@ -233,7 +233,7 @@ class banking_export_sdd_wizard(orm.TransientModel):
transactions_count_1_6 = 0
total_amount = 0.0
amount_control_sum_1_7 = 0.0
first_recur_lines = {}
lines_per_seq_type = {}
# key = sequence type ; value = list of lines as objects
# Iterate on payment orders
for payment_order in sepa_export.payment_order_ids:
@@ -253,7 +253,6 @@ class banking_export_sdd_wizard(orm.TransientModel):
_("The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired.")
% (line.sdd_mandate_id.unique_mandate_reference,
line.sdd_mandate_id.partner_id.name))
if not line.sdd_mandate_id.signature_date:
raise orm.except_orm(
_('Error:'),
@@ -268,13 +267,12 @@ class banking_export_sdd_wizard(orm.TransientModel):
% (line.sdd_mandate_id.unique_mandate_reference,
line.sdd_mandate_id.partner_id.name,
line.sdd_mandate_id.signature_date))
if line.sdd_mandate_id.type == 'oneoff':
if not line.sdd_mandate_id.last_debit_date:
if first_recur_lines.get('OOFF'):
first_recur_lines['OOFF'].append(line)
if lines_per_seq_type.get('OOFF'):
lines_per_seq_type['OOFF'].append(line)
else:
first_recur_lines['OOFF'] = [line]
lines_per_seq_type['OOFF'] = [line]
else:
raise orm.except_orm(
_('Error:'),
@@ -283,18 +281,20 @@ class banking_export_sdd_wizard(orm.TransientModel):
line.sdd_mandate_id.partner_id.name,
line.sdd_mandate_id.last_debit_date))
elif line.sdd_mandate_id.type == 'recurrent':
if line.sdd_mandate_id.last_debit_date:
if first_recur_lines.get('RCUR'):
first_recur_lines['RCUR'].append(line)
else:
first_recur_lines['RCUR'] = [line]
seq_type_map = {
'recurring': 'RCUR',
'first': 'FRST',
'final': 'FNAL',
}
seq_type_label = line.sdd_mandate_id.recurrent_sequence_type
assert seq_type_label is not False
seq_type = seq_type_map[seq_type_label]
if lines_per_seq_type.get(seq_type):
lines_per_seq_type[seq_type].append(line)
else:
if first_recur_lines.get('FRST'):
first_recur_lines['FRST'].append(line)
else:
first_recur_lines['FRST'] = [line]
lines_per_seq_type[seq_type] = [line]
for sequence_type, lines in first_recur_lines.items():
for sequence_type, lines in lines_per_seq_type.items():
# B. Payment info
payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf')
payment_info_identification_2_1 = etree.SubElement(
@@ -516,14 +516,23 @@ class banking_export_sdd_wizard(orm.TransientModel):
wf_service.trg_validate(uid, 'payment.order', order.id, 'done', cr)
mandate_ids = [line.sdd_mandate_id.id for line in order.line_ids]
self.pool['sdd.mandate'].write(
cr, uid, mandate_ids, {
'last_debit_date': datetime.today().strftime('%Y-%m-%d')
},
cr, uid, mandate_ids,
{'last_debit_date': datetime.today().strftime('%Y-%m-%d')},
context=context)
oneoff_mandate_ids = \
[line.sdd_mandate_id.id for line in order.line_ids
if line.sdd_mandate_id.type == 'oneoff']
to_expire_ids = []
first_mandate_ids = []
for line in order.line_ids:
if line.sdd_mandate_id.type == 'oneoff':
to_expire_ids.append(line.sdd_mandate_id.id)
elif line.sdd_mandate_id.type == 'recurrent':
seq_type = line.sdd_mandate_id.recurrent_sequence_type
if seq_type == 'final':
to_expire_ids.append(line.sdd_mandate_id.id)
elif seq_type == 'first':
first_mandate_ids.append(line.sdd_mandate_id.id)
self.pool['sdd.mandate'].write(
cr, uid, oneoff_mandate_ids, {'state': 'expired'},
context=context)
cr, uid, to_expire_ids, {'state': 'expired'}, context=context)
self.pool['sdd.mandate'].write(
cr, uid, first_mandate_ids,
{'recurrent_sequence_type': 'recurring'}, context=context)
return {'type': 'ir.actions.act_window_close'}