account_banking_mandate.py 5.53 KB
Newer Older
François C. committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
# -*- coding: utf-8 -*-
# © 2014 Compassion CH - Cyril Sester <csester@compassion.ch>
# © 2014 Serv. Tecnol. Avanzados - Pedro M. Baeza
# © 2015-2016 Akretion - Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from openerp import models, fields, api, _
from openerp.exceptions import UserError, ValidationError


class AccountBankingMandate(models.Model):
    """The banking mandate is attached to a bank account and represents an
    authorization that the bank account owner gives to a company for a
    specific operation (such as direct debit)
    """
    _name = 'account.banking.mandate'
    _description = "A generic banking mandate"
    _rec_name = 'unique_mandate_reference'
    _inherit = ['mail.thread']
    _order = 'signature_date desc'

    format = fields.Selection(
        [('basic', 'Basic Mandate')], default='basic', required=True,
        string='Mandate Format', track_visibility='onchange')
    partner_bank_id = fields.Many2one(
        comodel_name='res.partner.bank', string='Bank Account',
        track_visibility='onchange')
    partner_id = fields.Many2one(
        comodel_name='res.partner', related='partner_bank_id.partner_id',
        string='Partner', store=True)
    company_id = fields.Many2one(
        comodel_name='res.company', string='Company', required=True,
        default=lambda self: self.env['res.company']._company_default_get(
            'account.banking.mandate'))
    unique_mandate_reference = fields.Char(
        string='Unique Mandate Reference', track_visibility='onchange')
    signature_date = fields.Date(string='Date of Signature of the Mandate',
                                 track_visibility='onchange')
    scan = fields.Binary(string='Scan of the Mandate')
    last_debit_date = fields.Date(string='Date of the Last Debit',
                                  readonly=True)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('valid', 'Valid'),
        ('expired', 'Expired'),
        ('cancel', 'Cancelled'),
        ], string='Status', default='draft', track_visibility='onchange',
        help="Only valid mandates can be used in a payment line. A cancelled "
        "mandate is a mandate that has been cancelled by the customer.")
    payment_line_ids = fields.One2many(
        comodel_name='account.payment.line', inverse_name='mandate_id',
        string="Related Payment Lines")

    _sql_constraints = [(
        'mandate_ref_company_uniq',
        'unique(unique_mandate_reference, company_id)',
        'A Mandate with the same reference already exists for this company!')]

    @api.multi
    @api.constrains('signature_date', 'last_debit_date')
    def _check_dates(self):
        for mandate in self:
            if (mandate.signature_date and
                    mandate.signature_date > fields.Date.context_today(
                        mandate)):
                raise ValidationError(
                    _("The date of signature of mandate '%s' "
                      "is in the future!")
                    % mandate.unique_mandate_reference)
            if (mandate.signature_date and mandate.last_debit_date and
                    mandate.signature_date > mandate.last_debit_date):
                raise ValidationError(
                    _("The mandate '%s' can't have a date of last debit "
                      "before the date of signature."
                      ) % mandate.unique_mandate_reference)

    @api.multi
    @api.constrains('state', 'partner_bank_id')
    def _check_valid_state(self):
        for mandate in self:
            if mandate.state == 'valid':
                if not mandate.signature_date:
                    raise ValidationError(
                        _("Cannot validate the mandate '%s' without a date of "
                          "signature.") % mandate.unique_mandate_reference)
                if not mandate.partner_bank_id:
                    raise ValidationError(
                        _("Cannot validate the mandate '%s' because it is not "
                          "attached to a bank account.") %
                        mandate.unique_mandate_reference)

    @api.model
    def create(self, vals=None):
        if vals.get('unique_mandate_reference', 'New') == 'New':
            vals['unique_mandate_reference'] = \
                self.env['ir.sequence'].next_by_code(
                    'account.banking.mandate') or 'New'
        return super(AccountBankingMandate, self).create(vals)

    @api.multi
    @api.onchange('partner_bank_id')
    def mandate_partner_bank_change(self):
        for mandate in self:
            mandate.partner_id = mandate.partner_bank_id.partner_id

    @api.multi
    def validate(self):
        for mandate in self:
            if mandate.state != 'draft':
                raise UserError(
                    _('Mandate should be in draft state.'))
        self.write({'state': 'valid'})
        return True

    @api.multi
    def cancel(self):
        for mandate in self:
            if mandate.state not in ('draft', 'valid'):
                raise UserError(
                    _('Mandate should be in draft or valid state.'))
        self.write({'state': 'cancel'})
        return True

    @api.multi
    def back2draft(self):
        """Allows to set the mandate back to the draft state.
        This is for mandates cancelled by mistake.
        """
        for mandate in self:
            if mandate.state != 'cancel':
                raise UserError(
                    _('Mandate should be in cancel state.'))
        self.write({'state': 'draft'})
        return True