~compassion/banking-addons/banking-addons-mandate

« back to all changes in this revision

Viewing changes to account_banking_sepa_direct_debit/account_banking_sdd.py

  • Committer: Cyril Sester
  • Date: 2014-06-12 14:15:47 UTC
  • Revision ID: csester@compassion.ch-20140612141547-c4b0ye21pw485rox
sepa mandate splitted to get a generic mandate 

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
logger = logging.getLogger(__name__)
33
33
 
34
 
 
35
34
class banking_export_sdd(orm.Model):
36
35
    '''SEPA Direct Debit export'''
37
36
    _name = 'banking.export.sdd'
100
99
 
101
100
class sdd_mandate(orm.Model):
102
101
    '''SEPA Direct Debit Mandate'''
103
 
    _name = 'sdd.mandate'
104
102
    _description = __doc__
105
 
    _rec_name = 'unique_mandate_reference'
106
 
    _inherit = ['mail.thread']
107
 
    _order = 'signature_date desc'
 
103
    _name = 'account.banking.mandate'
 
104
    _inherit = 'account.banking.mandate'
108
105
    _track = {
109
 
        'state': {
110
 
            'account_banking_sepa_direct_debit.mandate_valid':
111
 
            lambda self, cr, uid, obj, ctx=None:
112
 
            obj['state'] == 'valid',
113
 
            'account_banking_sepa_direct_debit.mandate_expired':
114
 
            lambda self, cr, uid, obj, ctx=None:
115
 
            obj['state'] == 'expired',
116
 
            'account_banking_sepa_direct_debit.mandate_cancel':
117
 
            lambda self, cr, uid, obj, ctx=None:
118
 
            obj['state'] == 'cancel',
119
 
            },
120
106
        'recurrent_sequence_type': {
121
107
            'account_banking_sepa_direct_debit.recurrent_sequence_type_first':
122
108
            lambda self, cr, uid, obj, ctx=None:
132
118
        }
133
119
 
134
120
    _columns = {
135
 
        'partner_bank_id': fields.many2one(
136
 
            'res.partner.bank', 'Bank Account', track_visibility='onchange'),
137
 
        'partner_id': fields.related(
138
 
            'partner_bank_id', 'partner_id', type='many2one',
139
 
            relation='res.partner', string='Partner', readonly=True),
140
 
        'company_id': fields.many2one('res.company', 'Company', required=True),
141
 
        'unique_mandate_reference': fields.char(
142
 
            'Unique Mandate Reference', size=35, readonly=True,
143
 
            track_visibility='always'),
144
121
        'type': fields.selection([
145
122
            ('recurrent', 'Recurrent'),
146
123
            ('oneoff', 'One-Off'),
152
129
            ], 'Sequence Type for Next Debit', track_visibility='onchange',
153
130
            help="This field is only used for Recurrent mandates, not for "
154
131
            "One-Off mandates."),
155
 
        'signature_date': fields.date(
156
 
            'Date of Signature of the Mandate', track_visibility='onchange'),
157
 
        'scan': fields.binary('Scan of the Mandate'),
158
 
        'last_debit_date': fields.date(
159
 
            'Date of the Last Debit', readonly=True),
160
 
        'state': fields.selection([
161
 
            ('draft', 'Draft'),
162
 
            ('valid', 'Valid'),
163
 
            ('expired', 'Expired'),
164
 
            ('cancel', 'Cancelled'),
165
 
            ], 'Status',
166
 
            help="Only valid mandates can be used in a payment line. A "
167
 
            "cancelled mandate is a mandate that has been cancelled by "
168
 
            "the customer. A one-off mandate expires after its first use. "
169
 
            "A recurrent mandate expires after it's final use or if it "
170
 
            "hasn't been used for 36 months."),
171
 
        'payment_line_ids': fields.one2many(
172
 
            'payment.line', 'sdd_mandate_id', "Related Payment Lines"),
173
132
        'sepa_migrated': fields.boolean(
174
133
            'Migrated to SEPA', track_visibility='onchange',
175
134
            help="If this field is not active, the mandate section of the "
188
147
        }
189
148
 
190
149
    _defaults = {
191
 
        'company_id': lambda self, cr, uid, context:
192
 
        self.pool['res.company']._company_default_get(
193
 
            cr, uid, 'sdd.mandate', context=context),
194
 
        'unique_mandate_reference': lambda self, cr, uid, ctx:
195
 
        self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'),
196
 
        'state': 'draft',
197
150
        'sepa_migrated': True,
198
151
    }
199
152
 
200
 
    _sql_constraints = [(
201
 
        'mandate_ref_company_uniq',
202
 
        'unique(unique_mandate_reference, company_id)',
203
 
        'A Mandate with the same reference already exists for this company !'
204
 
        )]
205
 
 
206
153
    def _check_sdd_mandate(self, cr, uid, ids):
207
154
        for mandate in self.browse(cr, uid, ids):
208
 
            if (mandate.signature_date and
209
 
                    mandate.signature_date >
210
 
                    datetime.today().strftime('%Y-%m-%d')):
211
 
                raise orm.except_orm(
212
 
                    _('Error:'),
213
 
                    _("The date of signature of mandate '%s' is in the "
214
 
                        "future !")
215
 
                    % mandate.unique_mandate_reference)
216
 
            if mandate.state == 'valid' and not mandate.signature_date:
217
 
                raise orm.except_orm(
218
 
                    _('Error:'),
219
 
                    _("Cannot validate the mandate '%s' without a date of "
220
 
                        "signature.")
221
 
                    % mandate.unique_mandate_reference)
222
 
            if mandate.state == 'valid' and not mandate.partner_bank_id:
223
 
                raise orm.except_orm(
224
 
                    _('Error:'),
225
 
                    _("Cannot validate the mandate '%s' because it is not "
226
 
                        "attached to a bank account.")
227
 
                    % mandate.unique_mandate_reference)
228
 
 
229
 
            if (mandate.signature_date and mandate.last_debit_date and
230
 
                    mandate.signature_date > mandate.last_debit_date):
231
 
                raise orm.except_orm(
232
 
                    _('Error:'),
233
 
                    _("The mandate '%s' can't have a date of last debit "
234
 
                        "before the date of signature.")
235
 
                    % mandate.unique_mandate_reference)
236
155
            if (mandate.type == 'recurrent'
237
156
                    and not mandate.recurrent_sequence_type):
238
157
                raise orm.except_orm(
259
178
 
260
179
    _constraints = [
261
180
        (_check_sdd_mandate, "Error msg in raise", [
262
 
            'last_debit_date', 'signature_date', 'state', 'partner_bank_id',
263
181
            'type', 'recurrent_sequence_type', 'sepa_migrated',
264
182
            'original_mandate_identification',
265
183
            ]),
276
194
    def mandate_partner_bank_change(
277
195
            self, cr, uid, ids, partner_bank_id, type, recurrent_sequence_type,
278
196
            last_debit_date, state):
279
 
        res = {'value': {}}
280
 
        if partner_bank_id:
281
 
            partner_bank_read = self.pool['res.partner.bank'].read(
282
 
                cr, uid, partner_bank_id, ['partner_id'])['partner_id']
283
 
            if partner_bank_read:
284
 
                res['value']['partner_id'] = partner_bank_read[0]
 
197
        res = super(sdd_mandate, self).mandate_partner_bank_change(self, cr, uid,
 
198
            ids, partner_bank_id, last_debit_date, state)
285
199
        if (state == 'valid' and partner_bank_id
286
200
                and type == 'recurrent'
287
201
                and recurrent_sequence_type != 'first'):
295
209
                }
296
210
        return res
297
211
 
298
 
    def validate(self, cr, uid, ids, context=None):
299
 
        to_validate_ids = []
300
 
        for mandate in self.browse(cr, uid, ids, context=context):
301
 
            assert mandate.state == 'draft', 'Mandate should be in draft state'
302
 
            to_validate_ids.append(mandate.id)
303
 
        self.write(
304
 
            cr, uid, to_validate_ids, {'state': 'valid'}, context=context)
305
 
        return True
306
 
 
307
 
    def cancel(self, cr, uid, ids, context=None):
308
 
        to_cancel_ids = []
309
 
        for mandate in self.browse(cr, uid, ids, context=context):
310
 
            assert mandate.state in ('draft', 'valid'),\
311
 
                'Mandate should be in draft or valid state'
312
 
            to_cancel_ids.append(mandate.id)
313
 
        self.write(
314
 
            cr, uid, to_cancel_ids, {'state': 'cancel'}, context=context)
315
 
        return True
316
 
 
317
212
    def _sdd_mandate_set_state_to_expired(self, cr, uid, context=None):
318
213
        logger.info('Searching for SDD Mandates that must be set to Expired')
319
214
        expire_limit_date = datetime.today() + \
335
230
                % expired_mandate_ids)
336
231
        else:
337
232
            logger.info('0 SDD Mandates must be set to Expired')
338
 
        return True
339
 
 
340
 
 
341
 
class res_partner_bank(orm.Model):
342
 
    _inherit = 'res.partner.bank'
343
 
 
344
 
    _columns = {
345
 
        'sdd_mandate_ids': fields.one2many(
346
 
            'sdd.mandate', 'partner_bank_id', 'SEPA Direct Debit Mandates'),
347
 
        }
348
 
 
349
 
 
350
 
class payment_line(orm.Model):
351
 
    _inherit = 'payment.line'
352
 
 
353
 
    _columns = {
354
 
        'sdd_mandate_id': fields.many2one(
355
 
            'sdd.mandate', 'SEPA Direct Debit Mandate',
356
 
            domain=[('state', '=', 'valid')]),
357
 
        }
358
 
 
359
 
    def create(self, cr, uid, vals, context=None):
360
 
        '''If the customer invoice has a mandate, take it
361
 
        otherwise, take the first valid mandate of the bank account'''
362
 
        if context is None:
363
 
            context = {}
364
 
        if not vals:
365
 
            vals = {}
366
 
        partner_bank_id = vals.get('bank_id')
367
 
        move_line_id = vals.get('move_line_id')
368
 
        if (context.get('default_payment_order_type') == 'debit'
369
 
                and 'sdd_mandate_id' not in vals):
370
 
            if move_line_id:
371
 
                line = self.pool['account.move.line'].browse(
372
 
                    cr, uid, move_line_id, context=context)
373
 
                if (line.invoice and line.invoice.type == 'out_invoice'
374
 
                        and line.invoice.sdd_mandate_id):
375
 
                    vals.update({
376
 
                        'sdd_mandate_id': line.invoice.sdd_mandate_id.id,
377
 
                        'bank_id':
378
 
                        line.invoice.sdd_mandate_id.partner_bank_id.id,
379
 
                    })
380
 
            if partner_bank_id and 'sdd_mandate_id' not in vals:
381
 
                mandate_ids = self.pool['sdd.mandate'].search(cr, uid, [
382
 
                    ('partner_bank_id', '=', partner_bank_id),
383
 
                    ('state', '=', 'valid'),
384
 
                    ], context=context)
385
 
                if mandate_ids:
386
 
                    vals['sdd_mandate_id'] = mandate_ids[0]
387
 
        return super(payment_line, self).create(cr, uid, vals, context=context)
388
 
 
389
 
    def _check_mandate_bank_link(self, cr, uid, ids):
390
 
        for payline in self.browse(cr, uid, ids):
391
 
            if (payline.sdd_mandate_id and payline.bank_id
392
 
                    and payline.sdd_mandate_id.partner_bank_id.id !=
393
 
                    payline.bank_id.id):
394
 
                raise orm.except_orm(
395
 
                    _('Error:'),
396
 
                    _("The payment line with reference '%s' has the bank "
397
 
                        "account '%s' which is not attached to the mandate "
398
 
                        "'%s' (this mandate is attached to the bank account "
399
 
                        "'%s').") % (
400
 
                        payline.name,
401
 
                        self.pool['res.partner.bank'].name_get(
402
 
                            cr, uid, [payline.bank_id.id])[0][1],
403
 
                        payline.sdd_mandate_id.unique_mandate_reference,
404
 
                        self.pool['res.partner.bank'].name_get(
405
 
                            cr, uid,
406
 
                            [payline.sdd_mandate_id.partner_bank_id.id])[0][1],
407
 
                    ))
408
 
        return True
409
 
 
410
 
    _constraints = [
411
 
        (_check_mandate_bank_link, 'Error msg in raise',
412
 
            ['sdd_mandate_id', 'bank_id']),
413
 
    ]
414
 
 
415
 
 
416
 
class account_invoice(orm.Model):
417
 
    _inherit = 'account.invoice'
418
 
 
419
 
    _columns = {
420
 
        'sdd_mandate_id': fields.many2one(
421
 
            'sdd.mandate', 'SEPA Direct Debit Mandate',
422
 
            domain=[('state', '=', 'valid')], readonly=True,
423
 
            states={'draft': [('readonly', False)]})
424
 
        }
 
233
        return True
 
 
b'\\ No newline at end of file'