| from odoo import models, fields, api,_ | |
| from odoo.exceptions import UserError, ValidationError,Warning | |
| from psycopg2 import sql, DatabaseError | |
| from datetime import datetime,timedelta,date | |
| from dateutil.relativedelta import relativedelta | |
| 
 | |
| from werkzeug import utils | |
| import base64 | |
| 
 | |
| class opendons_recurring_donation(models.Model): | |
|     _name = 'opendons.recurring_donation' | |
|     _description = 'recurring donation management' | |
| 
 | |
|     last_execution_date=fields.Date('Last execution date') | |
| 
 | |
| class DonationDonation(models.Model): | |
|     _inherit = 'donation.donation' | |
| 
 | |
|     donor_id=fields.Char(related='partner_id.donor_id') | |
| 
 | |
|     operation_id = fields.Many2one( | |
|         'opendons.operation', | |
|         string='Operation', | |
|         track_visibility='onchange', | |
|         ondelete='restrict', | |
|         # required=True, | |
|         domain=[('state', '=', 'exported')] | |
|          | |
|     ) | |
|     # operation_state= fields.Char(related='operation_id.state') | |
|      | |
|     segment_id = fields.Many2one( | |
|         'opendons.segment', | |
|         string='Segment', | |
|         track_visibility='onchange', | |
|         # required=True, | |
|         ondelete='restrict' | |
|          | |
|     ) | |
|     recurring_template = fields.Selection( | |
|         [("active", "Active"), ("suspended", "Suspended"),("stopped", "Stopped")], | |
|         string="Recurring Template", | |
|         copy=False, | |
|         index=True, | |
|         tracking=True, | |
|     ) | |
|     start_date= fields.Date( | |
|         string='Start Date', | |
|         index=True, | |
|         track_visibility='onchange' | |
|     ) | |
|     end_date = fields.Date( | |
|         string='End Date', | |
|         index=True, | |
|         track_visibility='onchange' | |
|     ) | |
|     stopped_date = fields.Date( | |
|         string='Stopped Date', | |
|         index=True, | |
|         readonly=True, | |
|         track_visibility='onchange' | |
|     ) | |
|     stopped_reason=fields.Selection(string='Stop reason',selection=[('motif1', 'Motif 1'), ('motif2', 'Motif 2')],default='motif1',track_visibility='onchange') | |
| 
 | |
|     suspended_date = fields.Date( | |
|         string='Suspended Date', | |
|         index=True, | |
|         readonly=True, | |
|         track_visibility='onchange' | |
|     ) | |
|     lastexecution_date = fields.Date( | |
|         string='Last execution Date', | |
|         index=True, | |
|         readonly=True, | |
|         track_visibility='onchange' | |
|     ) | |
|     frequency =fields.Selection( | |
|          [('monthly','Monthly'), ('bimonthly','Bimonthly'),('quarterly','Quarterly'),('half-yearly','Half-yearly'),('annually','Annually')], | |
|          default='monthly' | |
|          ) | |
|      | |
|     payment_batch_id = fields.Many2one( | |
|             'opendons_payment_batch', | |
|             string='Payment Batch', | |
|             ondelete='set null' | |
|         ) | |
|     accountingdeposit_id = fields.Many2one( | |
|             'opendons.accountingdeposit', | |
|             string='accounting deposit', | |
|             ondelete='set null' | |
|         ) | |
| 
 | |
|     #bank_deposit_date=fields.Datetime(related='payment_batch_id.bank_deposit_date') | |
|     payment_state=fields.Selection(string='payment state',selection=[ | |
|         ('draft', 'Draft'), | |
|         ('validated', 'Validated'), | |
|         ('deposited_in_bank', 'Deposited in bank'), | |
|         ('deposited_in_accounting', 'Deposited in accounting') | |
|         ], | |
|          compute='_compute_payment_state', store=True) | |
|     | |
|     @api.onchange("recurring_template") | |
|     def recurring_template_change(self): | |
|         res = {"warning": {}} | |
|         if self.recurring_template and self.tax_receipt_option == "each": | |
|             self.tax_receipt_option = "annual" | |
|              | |
|         if not self.recurring_template and self.commercial_partner_id: | |
|             if self.commercial_partner_id.tax_receipt_option != self.tax_receipt_option: | |
|                 self.tax_receipt_option = self.commercial_partner_id.tax_receipt_option | |
|         return res | |
|          | |
|     def create_mandate(self): | |
|         return True | |
|     def generate_each_tax_receipt(self): | |
|         #pas de création du RF à la validation du don, mais génération des RF ponctuels en mode batch | |
|         return False | |
|      | |
|     def generate_each_tax_receipt_batch(self): | |
|        #on générère tous les dons avec taxreceipt_option= qui n'on pas de RF rattaché | |
|         donations=self.env['donation.donation'].search([('tax_receipt_option','=','each'),('tax_receipt_id','=',False)]) | |
|         | |
|         for d in donations: | |
|             if not d.company_currency_id.is_zero(d.tax_receipt_total): | |
|                 receipt_vals = d._prepare_each_tax_receipt() | |
|                 receipt = self.env["donation.tax.receipt"].create(receipt_vals) | |
|                 d.tax_receipt_id=receipt.id | |
| 
 | |
|         return True | |
| 
 | |
| 
 | |
|     def _compute_payment_state(self): | |
|         for rec in self: | |
|             rec.payment_state='draft' | |
|             if rec.payment_batch_id: | |
|                 rec.payment_state=rec.payment_batch_id.state | |
|             if rec.source_recurring_id: | |
|                 rec.payment_state='deposited_in_bank' | |
|     | |
| 
 | |
|     year_donation_date=fields.Integer('Year donation date',compute='_compute_year_donation_date',store=True) | |
|     print_email_history_ids=fields.One2many( | |
|         'opendons.donation.print_email_history', | |
|         'donation_id', | |
|         string='print or email history ', | |
|         readonly=True | |
|     ) | |
|     html_content_print=fields.Html('html content print') | |
|     cancel_reason=fields.Selection(string='cancel reason',selection=[ | |
|         ('debit error','Debit error'), | |
|         ('donor error','Donor error'), | |
|         ('amount error','Amount error'), | |
|         ('invalid check','invalid check'), | |
|         ('affectation error','Affectation error'), | |
|         ('date error','Date error'), | |
|         ('other','Other'), | |
|         ]) | |
| 
 | |
|     def done2cancel(self): | |
|         """from Done state to Cancel state""" | |
|         for donation in self: | |
|             if donation.tax_receipt_id: | |
|                 raise UserError( | |
|                     _( | |
|                         "You cannot cancel this donation because " | |
|                         "it is linked to the tax receipt %s. You should first " | |
|                         "delete this tax receipt (but it may not be legally " | |
|                         "allowed)." | |
|                     ) | |
|                     % donation.tax_receipt_id.number | |
|                 ) | |
|              | |
|              | |
|             view=self.env.ref('opendons.donation_cancel_view') | |
| 
 | |
|             wiz=self.env['opendons.donation_cancel.wizard'].create({'donation_id':self.id}) | |
| 
 | |
|             return { | |
|                 'name': _('Cancel donation'), | |
|                 'type': 'ir.actions.act_window', | |
|                 'view_type': 'form', | |
|                 'view_mode': 'form', | |
|                 'res_model': 'opendons.donation_cancel.wizard', | |
|                 'views': [(view.id, 'form')], | |
|                 'view_id': view.id, | |
|                 'target': 'new', | |
|                 'res_id': wiz.id, | |
|                 'context': self.env.context, | |
|             } | |
|              | |
|      | |
|     def reverse_accounting_entries(self): | |
|         move=self.env['account.move'].search([('id','=',int(self.move_id))]) | |
|         #création de la pièce comptable d'extourne | |
|         vals={} | |
|         vals['ref']='Extourne de '+ move.name | |
|         vals['date']=datetime.now() | |
|         vals['journal_id']=int(move.journal_id) | |
|         vals['reversed_entry_id']=int(move.id) | |
|         move_r=self.env['account.move'].create(vals) | |
|         #création des écritures comptables d'extourne | |
|         for line in move.line_ids: | |
|             vals={} | |
|             vals['move_id']=int(move_r.id) | |
|             vals['partner_id']=int(line.partner_id) | |
|             vals['account_id']=int(line.account_id) | |
|             vals['debit']=line.credit | |
|             vals['credit']=line.debit | |
|             vals['quantity']=line.quantity | |
|             vals['date']=move_r.date | |
|              | |
|             line_r=self.env['account.move.line'].with_context(check_move_validity=False).create(vals) | |
|         move_r._post() | |
| 
 | |
|     def _compute_year_donation_date(self): | |
|         for rec in self: | |
|             rec.year_donation_date=rec.donation_date.year | |
|     def _default_payment_mode_id(self): | |
|          | |
|          | |
|         if self.recurring_template=='active': | |
|              | |
|             sepa_payment_method=self.env['account.payment.method'].search([('code','=','sepa_direct_debit')],limit=1) | |
|             if sepa_payment_method: | |
|                 sepa_payment_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int(sepa_payment_method.id))],limit=1) | |
|                 if sepa_payment_mode: | |
|                     self.payment_mode_id=sepa_payment_mode.id | |
|                 else: | |
|                     raise Warning(_('Please configure a SEPA payment mode')) | |
| 
 | |
|     payment_mode_id = fields.Many2one( | |
|         "account.payment.mode", | |
|         string="Payment Mode", | |
|         domain="[('company_id', '=', company_id), ('donation', '=', True)]", | |
|         copy=False, | |
|         tracking=True, | |
|         check_company=True, | |
|         default=_default_payment_mode_id, | |
|         states={"done": [("readonly", True)]} | |
|          | |
|     ) | |
|     bank_deposit_date=fields.Date('bank deposit date') | |
|     accounting_deposit_date=fields.Date('bank deposit date') | |
| 
 | |
|     @api.model | |
|     def create(self, vals): | |
|         # #vals['tax_receipt_option']='annual' | |
|         # if vals['tax_receipt_option']!='annual': raise Warning('The tax receipt option must be annual') | |
|          | |
|         # #si montant du PA=0 => message | |
|         # total=0 | |
|         # if not vals['line_ids']: | |
|         #     total=0 | |
|         #     #raise Warning('please add a donation line') | |
|         # else: | |
|         #     for line_d in vals['line_ids']: | |
|                  | |
|         #         total=total+float(line_d[2]['unit_price']) | |
|         # if total==0:raise Warning('The total amount is null') | |
|         res = super(DonationDonation, self).create(vals) | |
| 
 | |
|          | |
| 
 | |
|         #si don hors lot de paiement,ne provenant pas d'un PA : création auto du lot de paiement | |
|         if not res.payment_batch_id and res.state!='draft' and res.source_recurring_id==False : | |
|            vals={} | |
|            vals['payment_mode_id']=int(res.payment_mode_id) | |
|            batch=self.env['opendons_payment_batch'].create(vals) | |
|            batch.write({'donation_ids':[(4,int(res.id))]}) | |
| 
 | |
| 
 | |
|         return res | |
| 
 | |
|     @api.onchange("partner_id") | |
|     def donation_partner_direct_debit_change(self): | |
|          | |
|         if not self.payment_mode_id and self.recurring_template=='active': | |
|             self.mandate_id=False | |
|             sepa_payment_method=self.env['account.payment.method'].search([('code','=','sepa_direct_debit')],limit=1) | |
|             if sepa_payment_method: | |
|                 sepa_payment_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int(sepa_payment_method.id))],limit=1) | |
|                 if sepa_payment_mode: | |
|                     self.payment_mode_id=sepa_payment_mode.id | |
|                 else: | |
|                     raise Warning(_('Please configure a SEPA payment mode')) | |
| 
 | |
|             else: | |
|                 raise Warning(_('Please configure a SEPA payment method')) | |
|          | |
|         if ( | |
|              | |
|             self.partner_id | |
|             and self.payment_mode_id | |
|             and self.payment_mode_id.payment_method_id.mandate_required | |
|             | |
|         ): | |
|              | |
|             mandate = self.env["account.banking.mandate"].search( | |
|                 [ | |
|                     ("state", "=", "valid"), | |
|                     ("partner_id", "=", int(self.partner_id)), | |
|                 ], | |
|                 limit=1, | |
|             ) | |
|             if mandate: | |
|                 self.mandate_id = mandate | |
|             else: | |
|                 self.mandate_id=False | |
|      | |
| 
 | |
|     @api.onchange("payment_mode_id") | |
|     def donation_payment_mode_id_change(self): | |
|         if self.recurring_template=='active' and self.payment_mode_id: | |
|             sepa_payment_method=self.env['account.payment.method'].search([('code','=','sepa_direct_debit')],limit=1) | |
|             if sepa_payment_method: | |
|                 sepa_payment_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int(sepa_payment_method.id))],limit=1) | |
|                 if sepa_payment_mode: | |
|                     if self.payment_mode_id!=sepa_payment_mode.id : | |
|                         self.payment_mode_id=sepa_payment_mode.id  | |
|                      | |
|                 else: | |
|                     raise ValidationError(_('Please configure SEPA Payment')) | |
| 
 | |
| 
 | |
| 
 | |
|     @api.onchange('operation_id') | |
|     def _onchange_operation_id(self): | |
|         res = {} | |
|         res['domain']={'segment_id':[('operation_id', '=', self.operation_id.id)]} | |
|         return res | |
| 
 | |
|      | |
|     def generate_recurring_payment(self): | |
|         #self.ensure_one() | |
|          | |
|          | |
|         generation_day = self.env['ir.config_parameter'].get_param('opendons.generation_day', '') | |
|         limit_days_before = int(self.env['ir.config_parameter'].get_param('opendons.limit_days_before')) | |
|         debug_mode = self.env['ir.config_parameter'].get_param('opendons.pa_debug_mode') | |
| 
 | |
|         r=self.env['opendons.recurring_donation'].search([]) | |
|          | |
|         if r.last_execution_date and not debug_mode: | |
|             month_last_exe=r.last_execution_date.month | |
|             month_today=datetime.now().date().month | |
|             | |
|             #si le mois en cours a déjà été executé, l'execution est donc pour le mois suivant : | |
|             if month_last_exe==month_today: | |
|                 date_generation=r.last_execution_date+relativedelta(months=1) | |
|                 date_before=date_generation-timedelta(days=limit_days_before) | |
|                 date_today=datetime.now().date() | |
|                 #si la date du jour est antérieur à la date limite alors message | |
|                 if date_today<date_before: raise Warning('you can\'t generate recurring payment before the '+str(date_before)) | |
|          | |
| 
 | |
|         elif debug_mode : | |
|             #en mode debug on génère les dons même si déjà généré pour le mois | |
|             date_generation=datetime(datetime.now().date().year,datetime.now().date().month,int(generation_day)) | |
|         else: | |
|             #si aucune génération de don effectuée, la date de génération est le mois en cours | |
|             date_generation=datetime(datetime.now().date().year,datetime.now().date().month,int(generation_day)) | |
|          | |
|          | |
|          | |
|          | |
|             #si le mois en cours a déjà été executé, l'execution est donc pour le mois suivant : | |
|              | |
|             #si la date < date limite inférieur du mois suivant : message d'erreur | |
|             #la date de dernière execution sera alors celle du mois suivant | |
| 
 | |
|             #si le mois en cours n'a pas été executé alors execution | |
|             #la date de dernière execution sera alors celle du mois actuel | |
| 
 | |
|         #if date_today<date_before and date_today>date_after:raise Warning('today you can\'t generate recurring payment') | |
| 
 | |
|          | |
|         doo = self.env["donation.donation"] | |
|         #chercher les templates de dons récurrents actifs | |
|         donations = doo.search( | |
|             [ | |
|                 ("recurring_template", "=", "active") | |
|                  | |
|             ] | |
|         ) | |
|         new_donation_ids = [] | |
| 
 | |
|          | |
|         #pour chaque template de don récurrent | |
|         #création d'un don si les dates sont bonnes | |
|          | |
|         for donation in donations: | |
|             if not donation.start_date: continue | |
|             generate=True | |
|             existing_recur_donations = doo.search([("source_recurring_id", "=",int(donation.id))]) | |
|              | |
|             if donation.start_date>fields.Date.context_today(self): | |
|                 generate=False | |
|                  | |
|             delta=0 | |
|             if donation.frequency=='annually':delta=365 | |
|             if donation.frequency=='half-yearly':delta=365/2 | |
|             if donation.frequency=='quarterly':delta=365/4 | |
|             if donation.frequency=='bimonthly':delta=365/6 | |
|             if donation.frequency=='monthly':delta=365/12 | |
|              | |
|             if existing_recur_donations: | |
|                 for d in existing_recur_donations: | |
|                     days_diff=(d.donation_date-fields.Date.context_today(self)).days | |
|                     if days_diff<=delta:  | |
|                         generate=False | |
|                         break | |
|              | |
|             #si tout est ok pour la date, génération du don | |
|             if generate==True: | |
|                 default = { | |
|                     "recurring_template":'', | |
|                     "donation_date": date_generation, | |
|                     "source_recurring_id": donation.id, | |
|                     "payment_ref": '', | |
|                     "payment_mode_id":donation.payment_mode_id.id, | |
|                     "mandate_required":'True', | |
|                     "mandate_id":donation.mandate_id.id, | |
|                     "state":"draft" | |
|                 } | |
|                 #creation du don à partir du template de don récurrent | |
|                 new_donation = donation.copy(default=default) | |
|                 new_donation.payment_state='deposited_in_bank' | |
|                 #ajout du don à la collection des dons générés pour affichage | |
|                 new_donation_ids.append(new_donation.id) | |
|                 #mise à jour de la date de dernière génération | |
|                 donation.lastexecution_date=date_generation | |
|                  | |
|                  | |
|         payment_mode_id=donation.payment_mode_id.id | |
|         if not new_donation_ids : raise Warning ("aucun don n'a été généré") | |
|          | |
|         #on teste l'existence d'un ordre de paiement en status brouillon | |
|         #si plusieurs, c'est le dernier créé qui sera alimenté | |
|         #payorder=self.env['account.payment.order'].search([('state','=','draft')],order='create_date desc', limit=2) | |
|         #if payorder[0]: | |
|         #    payorder_id=self.update_direct_debit_payment_order(new_donation_ids,payment_mode_id,payorder[0]) | |
|         #sinon création de l'ordre de paiement SEPA avec tous les dons générés | |
|         #else: | |
|         payorder_id=self.create_direct_debit_payment_order(new_donation_ids,payment_mode_id) | |
|         #affichage des dons générés | |
|         # action = self.env.ref("donation.donation_action").sudo().read([])[0] | |
|         # action.update( | |
|         #     { | |
|         #         "domain": [("id", "in", new_donation_ids)], | |
|         #         "limit": 500, | |
|         #     } | |
|         # ) | |
|         if not r:r.create({'last_execution_date':date_generation}) | |
|         if r:r.write({'last_execution_date':date_generation}) | |
|         r=self.env['opendons.recurring_donation'].search([]) | |
|          | |
| 
 | |
|         action = self.env.ref("account_payment_order.account_payment_order_inbound_action").sudo().read([])[0] | |
|          | |
|         action.update( | |
|             { | |
|                 "view_mode": "form", | |
|                 "view_type":"list", | |
|                 "res_id": payorder_id if payorder_id else False | |
|             } | |
|         ) | |
|         #affichage de l'ordre de prélèvement | |
|         #action = self.env.ref("account_payment_order.account_payment_order_inbound_action").sudo().read([])[0] | |
|         return action | |
| 
 | |
|     def create_direct_debit_payment_order(self,donation_ids,payment_mode_id): | |
|         """Create Direct debit payment order on donation validation or update | |
|         an existing draft Direct Debit pay order""" | |
|          | |
|         apoo = self.env["account.payment.order"].sudo() | |
|         vals={} | |
|         vals['payment_mode_id']=payment_mode_id | |
|          | |
|          | |
|         payorder = apoo.create(vals) | |
|          | |
|          | |
|         msg = _( | |
|                         "A new draft direct debit order " | |
|                         "<a href=# data-oe-model=account.payment.order " | |
|                         "data-oe-id=%d>%s</a> has been automatically created" | |
|                     ) % (payorder.id, payorder.name) | |
|                  | |
|          | |
|         # add payment lines | |
|         | |
|         donations=self.env["donation.donation"].search([("id", "in",donation_ids)]) | |
| 
 | |
|         for donation in donations: | |
|             #validation du don et génération des écritures comptables | |
|              | |
|             self.validate_donation(donation) | |
|              | |
|              | |
|              | |
| 
 | |
|             if donation.payment_mode_id.payment_type == "inbound": | |
|                  | |
|                  | |
|                 #génération de la ligne de paiement dans l'ordre de prélèvement | |
|                 payment_account_id = ( | |
|                     donation.payment_mode_id.fixed_journal_id.payment_debit_account_id.id | |
|                 ) | |
|                  | |
|                 for mline in donation.move_id.line_ids: | |
|                     if mline.account_id.id == payment_account_id: | |
|                         mline.sudo().create_payment_line_from_move_line(payorder) | |
|                         break | |
|          | |
|         if donations:donation.message_post(body=msg)   | |
|         return int(payorder.id) | |
|          | |
|     def update_direct_debit_payment_order(self,donation_ids,payment_mode_id,payorder): | |
|          | |
|         payorder_vals = {"payment_mode_id": payment_mode_id} | |
| 
 | |
|          | |
|         msg = _( | |
|                         "A new draft direct debit order " | |
|                         "<a href=# data-oe-model=account.payment.order " | |
|                         "data-oe-id=%d>%s</a> has been automatically created" | |
|                     ) % (payorder.id, payorder.name) | |
|                  | |
|          | |
|         # add payment lines | |
|         | |
|         donations=self.env["donation.donation"].search([("id", "in",donation_ids)]) | |
| 
 | |
|         for donation in donations: | |
|             #validation du don et génération des écritures comptables | |
|              | |
|             self.validate_donation(donation) | |
|              | |
|              | |
|              | |
| 
 | |
|             if donation.payment_mode_id.payment_type == "inbound": | |
|                  | |
|                  | |
|                 #génération de la ligne de paiement dans l'ordre de prélèvement | |
|                 payment_account_id = ( | |
|                     donation.payment_mode_id.fixed_journal_id.payment_debit_account_id.id | |
|                 ) | |
|                  | |
|                 for mline in donation.move_id.line_ids: | |
|                     if mline.account_id.id == payment_account_id: | |
|                         mline.sudo().create_payment_line_from_move_line(payorder) | |
|                         break | |
|          | |
|         if donations:donation.message_post(body=msg)   | |
|         return int(payorder.id) | |
|      | |
| 
 | |
|     def validate_donation(self,donations): | |
|         check_total = self.env["res.users"].has_group( | |
|             "donation.group_donation_check_total" | |
|         ) | |
|         for donation in donations: | |
|             if donation.donation_date > fields.Date.context_today(self): | |
|                 raise UserError( | |
|                     _( | |
|                         "The date of donation %s should be today " | |
|                         "or in the past, not in the future!" | |
|                     ) | |
|                     % donation.number | |
|                 ) | |
|             if not donation.line_ids: | |
|                 raise UserError( | |
|                     _( | |
|                         "Cannot validate donation %s because it doesn't " | |
|                         "have any lines!" | |
|                     ) | |
|                     % donation.number | |
|                 ) | |
| 
 | |
|             if donation.currency_id.is_zero(donation.amount_total): | |
|                 raise UserError( | |
|                     _("Cannot validate donation %s because the " "total amount is 0!") | |
|                     % donation.number | |
|                 ) | |
| 
 | |
|             if donation.state != "draft": | |
|                 raise UserError( | |
|                     _( | |
|                         "Cannot validate donation %s because it is not " | |
|                         "in draft state." | |
|                     ) | |
|                     % donation.number | |
|                 ) | |
| 
 | |
|             if check_total and donation.currency_id.compare_amounts( | |
|                 donation.check_total, donation.amount_total | |
|             ): | |
|                 raise UserError( | |
|                     _( | |
|                         "The amount of donation %s (%s) is different " | |
|                         "from the sum of the donation lines (%s)." | |
|                     ) | |
|                     % ( | |
|                         donation.number, | |
|                         format_amount( | |
|                             self.env, donation.check_total, donation.currency_id | |
|                         ), | |
|                         format_amount( | |
|                             self.env, donation.amount_total, donation.currency_id | |
|                         ), | |
|                     ) | |
|                 ) | |
|             full_in_kind = all([line.in_kind for line in donation.line_ids]) | |
|             if not donation.payment_mode_id and not full_in_kind: | |
|                 raise UserError( | |
|                     _( | |
|                         "Payment Mode is not set on donation %s (only fully " | |
|                         "in-kind donations don't require a payment mode)." | |
|                     ) | |
|                     % donation.number | |
|                 ) | |
| 
 | |
|             vals = {"state": "done"} | |
|             if full_in_kind and donation.payment_mode_id: | |
|                 vals["payment_mode_id"] = False | |
| 
 | |
|             if not full_in_kind: | |
|                 move_vals = donation._prepare_donation_move() | |
|                 # when we have a full in-kind donation: no account move | |
|                 if move_vals: | |
|                     move = self.env["account.move"].create(move_vals) | |
|                     move.action_post() | |
|                     vals["move_id"] = move.id | |
|             else: | |
|                 donation.message_post( | |
|                     body=_("Full in-kind donation: no account move generated") | |
|                 ) | |
| 
 | |
|             receipt = donation.generate_each_tax_receipt() | |
|             if receipt: | |
|                 vals["tax_receipt_id"] = receipt.id | |
| 
 | |
|             donation.write(vals) | |
|             if donation.bank_statement_line_id: | |
|                 donation._reconcile_donation_from_bank_statement() | |
|             donation.partner_id._update_donor_rank() | |
|         return | |
|     def recurring_donation_action(self): | |
|          | |
|         sepa_payment_method=self.env['account.payment.method'].search([('code','=','sepa_direct_debit')]) | |
|         if sepa_payment_method: | |
|           sepa_payment_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int( sepa_payment_method))]) | |
|           if sepa_payment_mode: | |
|               payment_mode_id=sepa_payment_mode.id | |
|           else: | |
|               raise Warning('Please configure mode sepa payment') | |
| 
 | |
|         else: | |
|             raise Warning('Please configure method sepa payment') | |
| 
 | |
|         today=fields.Date.context_today(self) | |
|         action = self.env.ref("opendons.donation_recurring_action").sudo().read([])[0] | |
|          | |
|         action.update( | |
|             { | |
|                 "res_model": 'donation.donation', | |
|                 "view_mode": 'tree,form,pivot,graph', | |
|                 "context": {'default_recurring_template': 'active', 'recurring_view': True,'default_payment_mode_id':payment_mode_id, | |
|                 'default_tax_receipt_option':'annual', | |
|                 'default_donation_date':today}, | |
|                 "domain": [('recurring_template', '!=', False)] | |
|             } | |
|         ) | |
|          | |
|         return action | |
| 
 | |
|     def recurring_donation_action_partner(self): | |
|          | |
|         partner_id = self._context.get('active_id') | |
| 
 | |
|         sepa_payment_method=self.env['account.payment.method'].search([('code','=','sepa_direct_debit')]) | |
|         if sepa_payment_method: | |
|           sepa_payment_mode=self.env['account.payment.mode'].search([('payment_method_id','=',int( sepa_payment_method))]) | |
|           if sepa_payment_mode: | |
|               payment_mode_id=sepa_payment_mode.id | |
|           else: | |
|               raise Warning('Please configure mode sepa payment') | |
| 
 | |
|         else: | |
|             raise Warning('Please configure method sepa payment') | |
| 
 | |
|          | |
|         action = self.env.ref("opendons.donation_recurring_action").sudo().read([])[0] | |
|         today=fields.Date.context_today(self) | |
|         action.update( | |
|             { | |
|                 "res_model": 'donation.donation', | |
|                 "view_mode": 'tree,form,pivot,graph', | |
|                 "context": {'default_recurring_template': 'active', 'recurring_view': True, | |
|                 'default_payment_mode_id':payment_mode_id,'default_partner_id':partner_id, | |
|                 'default_tax_receipt_option':'annual', | |
|                 'default_donation_date':today}, | |
|                 "domain": [('recurring_template', '!=', False),('partner_id','=',partner_id)] | |
|             } | |
|         ) | |
|          | |
|         return action | |
| 
 | |
|     def payment_order_action(self): | |
|          | |
|          | |
|         action = self.env.ref("account_payment_order.account_payment_order_inbound_action").sudo().read([])[0] | |
|          | |
|          | |
|         return action | |
|      | |
|     def active2suspended(self): | |
|         self.ensure_one() | |
|         assert self.recurring_template == "active" | |
|         self.write({"recurring_template": "suspended"}) | |
|         self.write({"suspended_date": fields.Date.context_today(self)}) | |
|      | |
|     def suspended2active(self): | |
|         self.ensure_one() | |
|         assert self.recurring_template == "suspended" | |
|         self.write({"recurring_template": "active"}) | |
|         self.write({"suspended_date": False}) | |
|      | |
|     def active2stopped(self): | |
|         self.ensure_one() | |
|         assert self.recurring_template == "active" | |
|         view=self.env.ref('opendons.recurring_donation_view') | |
| 
 | |
|         wiz=self.env['opendons.recurringdonation.wizard'].create({'stopped_reason':'motif1','donation_id':self.id}) | |
| 
 | |
|         return { | |
|             'name': _('Stop recurring donation'), | |
|             'type': 'ir.actions.act_window', | |
|             'view_type': 'form', | |
|             'view_mode': 'form', | |
|             'res_model': 'opendons.recurringdonation.wizard', | |
|             'views': [(view.id, 'form')], | |
|             'view_id': view.id, | |
|             'target': 'new', | |
|             'res_id': wiz.id, | |
|             'context': self.env.context, | |
|         } | |
|      | |
|     def show_print_wizard(self): | |
|         self.ensure_one() | |
|         assert self.recurring_template == "active" | |
|         view=self.env.ref('opendons.recurring_donation_view') | |
| 
 | |
|         wiz=self.env['opendons.recurringdonationprint.wizard'].create({'donation_id':self.id}) | |
| 
 | |
|         return { | |
|             'name': _('Print letter'), | |
|             'type': 'ir.actions.act_window', | |
|             'view_type': 'form', | |
|             'view_mode': 'form', | |
|             'res_model': 'opendons.recurringdonationprint.wizard', | |
|             'views': [(view.id, 'form')], | |
|             'view_id': view.id, | |
|             'target': 'new', | |
|             'res_id': wiz.id, | |
|             'context': self.env.context, | |
|         } | |
| 
 | |
|          | |
|      | |
|     @api.depends("state", "partner_id", "move_id", "recurring_template") | |
|     def name_get(self): | |
|         res = [] | |
|         for donation in self: | |
|             if donation.recurring_template == "active": | |
|                 name = _("Recurring Donation %s") % (donation.number) | |
|             elif donation.recurring_template == "suspended": | |
|                 name = _("Suspended Recurring Donation %s") % (donation.number) | |
|             elif donation.recurring_template == "stopped": | |
|                 name = _("Stopped Recurring Donation %s") % (donation.number) | |
|             else: | |
|                 name = super(DonationDonation, donation).name_get()[0][1] | |
|             res.append((donation.id, name)) | |
|         return res | |
| 
 | |
|     def print_thanks(self): | |
|             self.ensure_one() | |
|             self.write({"thanks_printed": True}) | |
| 
 | |
|             html_content_print=self.thanks_template_id.html_content | |
|             html_content_print=html_content_print.replace('{{partner_id.name}}',self.partner_id.name) | |
|             html_content_print=html_content_print.replace('{{partner_id.firstname}}',self.partner_id.firstname) | |
|             html_content_print=html_content_print.replace('{{adresse}}',self.env['donation.tax.receipt'].update_adresse()) | |
|             html_content_print=html_content_print.replace('{{donor_id}}',self.partner_id.donor_id) | |
|             self.html_content_print=html_content_print | |
|              | |
|              | |
|             return self.env.ref("opendons.report_donation_thanks").report_action(self) | |
| 
 | |
| class DonationLine(models.Model): | |
|     _inherit = 'donation.line' | |
| 
 | |
|     donation_date=fields.Date(related='donation_id.donation_date') | |
|     partner_id=fields.Many2one(related='donation_id.partner_id') | |
| 
 | |
|     @api.model | |
|     def create(self, values):  | |
| 
 | |
|         res = super(DonationLine, self).create(values) | |
|         res.analytic_account_id=res.product_id.analytic_account_id | |
|         return res | |
| 
 | |
| 
 | |
| 
 | |
|          |