diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py
index dc42188d0..bfe49d544 100644
--- a/account_banking_sepa_direct_debit/account_banking_sdd.py
+++ b/account_banking_sepa_direct_debit/account_banking_sdd.py
@@ -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):
diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml
index 5bb77ecf0..54a5a6669 100644
--- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml
+++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml
@@ -97,11 +97,12 @@
-
+
+
-
+
@@ -119,14 +120,14 @@
sdd.mandate.tree
sdd.mandate
-
+
-
+
@@ -139,6 +140,7 @@
+
@@ -175,7 +177,7 @@
SEPA Direct Debit Mandate Validated
-
+
Mandate Expired
sdd.mandate
@@ -189,6 +191,27 @@
SEPA Direct Debit Mandate Cancelled
+
+ Sequence Type set to First
+ sdd.mandate
+
+ Sequence Type set to First
+
+
+
+ Sequence Type set to Recurring
+ sdd.mandate
+
+ Sequence Type set to Recurring
+
+
+
+ Sequence Type set to Final
+ sdd.mandate
+
+ Sequence Type set to Final
+
+
sdd.mandate.res.partner.bank.form
diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py
index df08915bd..60dda58fe 100644
--- a/account_banking_sepa_direct_debit/wizard/export_sdd.py
+++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py
@@ -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'}