@ -1,17 +1,17 @@
from odoo import models , fields , api , _
from odoo import models , fields , api , _
from odoo.exceptions import UserError , ValidationError , Warning
from odoo.exceptions import UserError , ValidationError , Warning
from psycopg2 import sql , DatabaseError
from psycopg2 import sql , DatabaseError
from datetime import datetime
from datetime import datetime , timedelta , date
from dateutil.relativedelta import relativedelta
from werkzeug import utils
from werkzeug import utils
import base64
import base64
class opendons_recurring_donation ( models . Model ) :
class opendons_recurring_donation ( models . Model ) :
_name = ' opendons.recurring_donation_configuration '
_name = ' opendons.recurring_donation '
_description = ' recurring donation management '
_description = ' recurring donation management '
generation_day = fields . Integer ( ' Generation day in the month ' )
limite_days_before = fields . Integer ( ' Limite_days before generation day ' )
last_execution_date = fields . Date ( ' Last execution date ' )
class DonationDonation ( models . Model ) :
class DonationDonation ( models . Model ) :
_inherit = ' donation.donation '
_inherit = ' donation.donation '
@ -37,13 +37,32 @@ class DonationDonation(models.Model):
ondelete = ' restrict '
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 ,
required = True ,
track_visibility = ' onchange '
)
end_date = fields . Date (
end_date = fields . Date (
string = ' End Date ' ,
string = ' End Date ' ,
index = True ,
index = True ,
track_visibility = ' onchange '
)
stopped_date = fields . Date (
string = ' Stopped Date ' ,
index = True ,
readonly = True ,
readonly = True ,
track_visibility = ' onchange '
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 (
suspended_date = fields . Date (
string = ' Suspended Date ' ,
string = ' Suspended Date ' ,
index = True ,
index = True ,
@ -66,39 +85,20 @@ class DonationDonation(models.Model):
string = ' Payment Batch ' ,
string = ' Payment Batch ' ,
ondelete = ' set null '
ondelete = ' set null '
)
)
@api.model
def create ( self , vals ) :
vals [ ' tax_receipt_option ' ] = ' annual '
res = super ( DonationDonation , self ) . create ( vals )
#res.tax_receipt_option='annual'
# 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:
# res.payment_mode_id=sepa_payment_mode.id
# else:
# raise Warning('Please configure mode sepa payment')
# else:
# raise Warning('Please configure method sepa payment')
return res
def _default_payment_mode_id ( self ) :
def _default_payment_mode_id ( self ) :
#if self.recurring_template=='active':
#raise Warning(self.recurring_template)
if self . recurring_template == ' active ' :
sepa_payment_method = self . env [ ' account.payment.method ' ] . search ( [ ( ' code ' , ' = ' , ' sepa_direct_debit ' ) ] )
if sepa_payment_method :
sepa_payment_method = self . env [ ' account.payment.method ' ] . search ( [ ( ' code ' , ' = ' , ' sepa_direct_debit ' ) ] )
id = int ( sepa_payment_method . id )
return 4
else :
raise Warning ( ' veuillez configurer la méthode de paiment SEPA ' )
if sepa_payment_method :
id = int ( sepa_payment_method . id )
return 4
else :
raise Warning ( ' veuillez configurer la méthode de paiment SEPA ' )
payment_mode_id = fields . Many2one (
payment_mode_id = fields . Many2one (
" account.payment.mode " ,
" account.payment.mode " ,
@ -107,10 +107,60 @@ class DonationDonation(models.Model):
copy = False ,
copy = False ,
tracking = True ,
tracking = True ,
check_company = True ,
check_company = True ,
default = _default_payment_mode_id ,
states = { " done " : [ ( " readonly " , True ) ] }
states = { " done " : [ ( " readonly " , True ) ] }
)
)
@api.model
def create ( self , vals ) :
vals [ ' tax_receipt_option ' ] = ' annual '
res = super ( DonationDonation , self ) . create ( vals )
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 ( ' operation_id ' )
@api.onchange ( ' operation_id ' )
@ -122,9 +172,48 @@ class DonationDonation(models.Model):
def generate_recurring_payment ( self ) :
def generate_recurring_payment ( self ) :
#self.ensure_one()
#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 " ]
doo = self . env [ " donation.donation " ]
#chercher les templates de dons récurrents actifs
#chercher les templates de dons récurrents actifs
donations = doo . search (
donations = doo . search (
@ -140,10 +229,11 @@ class DonationDonation(models.Model):
#création d'un don si les dates sont bonnes
#création d'un don si les dates sont bonnes
for donation in donations :
for donation in donations :
if not donation . start_date : continue
generate = True
generate = True
existing_recur_donations = doo . search ( [ ( " source_recurring_id " , " = " , int ( donation . id ) ) ] )
existing_recur_donations = doo . search ( [ ( " source_recurring_id " , " = " , int ( donation . id ) ) ] )
if donation . donation _date> fields . Date . context_today ( self ) :
if donation . start _date> fields . Date . context_today ( self ) :
generate = False
generate = False
delta = 0
delta = 0
@ -164,7 +254,7 @@ class DonationDonation(models.Model):
if generate == True :
if generate == True :
default = {
default = {
" recurring_template " : ' ' ,
" recurring_template " : ' ' ,
" donation_date " : fields . Date . context_today ( self ) ,
" donation_date " : date_generation ,
" source_recurring_id " : donation . id ,
" source_recurring_id " : donation . id ,
" payment_ref " : ' ' ,
" payment_ref " : ' ' ,
" payment_mode_id " : donation . payment_mode_id . id ,
" payment_mode_id " : donation . payment_mode_id . id ,
@ -177,7 +267,7 @@ class DonationDonation(models.Model):
#ajout du don à la collection des dons générés pour affichage
#ajout du don à la collection des dons générés pour affichage
new_donation_ids . append ( new_donation . id )
new_donation_ids . append ( new_donation . id )
#mise à jour de la date de dernière génération
#mise à jour de la date de dernière génération
donation . lastexecution_date = datetime . now ( ) . date ( )
donation . lastexecution_date = date_generation
payment_mode_id = donation . payment_mode_id . id
payment_mode_id = donation . payment_mode_id . id
if not new_donation_ids : raise Warning ( " aucun don n ' a été généré " )
if not new_donation_ids : raise Warning ( " aucun don n ' a été généré " )
@ -198,6 +288,11 @@ class DonationDonation(models.Model):
# "limit": 500,
# "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 = self . env . ref ( " account_payment_order.account_payment_order_inbound_action " ) . sudo ( ) . read ( [ ] ) [ 0 ]
action . update (
action . update (
@ -430,4 +525,56 @@ class DonationDonation(models.Model):
# }
# }
# )
# )
return action
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 ,
}
# self.write({"recurring_template": "stopped"})
# self.write({"stopped_date": fields.Date.context_today(self)})
@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