On utilise la nouvelle date d'échéance.

1) Lorsqu'on initialise les dates, c'est ça qu'on teste. Par défaut la date de fin est la date d'échéance. Mais s'il y a Commandes et Bank, on regarde si l'abonnement a été activé par une transaction :
- si c'est SEPA, on annule la date de fin, par défaut ça sera infini
- si c'est carte bleue, on met comme date de fin celle de la carte bleue puisqu'on l'a
1bis) Au passage on déplace les tâches d'initialisation dans une fonction à part pour y voir plus clair.

2) Quand un abonnement est modifié et qu'on check les dates, on active entre date_debut et date_echeance maintenant.

3) Mais on désactive toujours seulement après date_fin, pas date_echeance. Ce qui permet de laisser une marge si jamais l'échéance est passée mais sans désactiver. Car ça se trouve c'est justement un paiement un peu en retard.

4) Quand on renouvelle un abonnement, on renouvelle à partir de la date d'échéance, et non plus de la date de fin. Et on repousse la date de fin si elle se retrouve avant la nouvelle échéance décalée.

5) Une nouvelle tâche génie est programmée toutes les heures pour vérifier les échéances. Si on a trop dépassé (48h par défaut qui sera configurable) alors on change la date de fin pour maintenant, ce qui va désactiver l'abonnement.

Ce n'est PAS FINI. Il manque :
- rendre configurable les deux délais qui sont en lire_config()
- afficher la nouvelle date d'échéance dans l'admin et la rendre éditable dans le form d'édition d'un abonnement
- possiblement changer la désactivation par Jobs en utilisant un génie (perf issue d'après cerdic)
- sûrement plein de bugs à corriger, j'espère pas trop…
svn/attic/branches/v3.0.12/98521
rastapopoulos@spip.org 8 years ago
parent 99787eecdb
commit 687e9f2644

1
.gitattributes vendored

@ -13,6 +13,7 @@ formulaires/editer_abonnements_offre.php -text
formulaires/editer_abonnements_offre_notifications.html -text
formulaires/editer_abonnements_offre_notifications.php -text
genie/abonnements_verifier_desactivation.php -text
genie/abonnements_verifier_echeances.php -text
genie/abonnements_verifier_notifications.php -text
inc/abonnements.php -text
lang/abonnement.xml -text

@ -41,57 +41,19 @@ function abonnements_optimiser_base_disparus($flux){
function abonnements_post_edition($flux){
// Si on modifie un abonnement
if ($flux['args']['table'] == 'spip_abonnements') {
include_spip('inc/abonnements');
$abonnement = sql_fetsel('*', 'spip_abonnements', 'id_abonnement = '.intval($flux['args']['id_objet']));
$offre = sql_fetsel('*', 'spip_abonnements_offres', 'id_abonnements_offre = '.intval($abonnement['id_abonnements_offre']));
$jourdhui = date('Y-m-d H:i:s');
$modifs = array();
// Si l'échéance est VIDE, et que pourtant l'offre parente A BIEN une durée
// alors c'est qu'il faut initialiser l'échéance !
if ($abonnement['date_fin'] == '0000-00-00 00:00:00' and ($duree = $offre['duree']) > 0){
// De combien doit-on augmenter la date
switch ($offre['periode']){
case 'heures':
$ajout = " + ${duree} hours";
break;
case 'jours':
$ajout = " + ${duree} days";
break;
case 'mois':
$ajout = " + ${duree} months";
break;
default:
$ajout ='';
break;
}
// Calcul de la date de fin
$modifs['date_fin'] = date('Y-m-d H:i:s', strtotime($abonnement['date_debut'].$ajout));
$modifs = pipeline(
'abonnement_initialisation_dates',
array(
'args' => array('abonnement' => $abonnement, 'offre' => $offre),
'data' => $modifs
)
);
// Si les dates ont été changées, on change le tableau de l'abonnement pour le test de statut qui suivra
if (isset($modifs['date_debut'])) {
$abonnement['date_debut'] = $modifs['date_debut'];
}
if (isset($modifs['date_fin'])) {
$abonnement['date_fin'] = $modifs['date_fin'];
}
// Si la date de fin a été modifiée et qu'elle est dans le future
// on reprogramme la désactivation
if (isset($flux['data']['date_fin']) and $flux['data']['date_fin'] > $jourdhui) {
abonnements_programmer_desactivation($flux['args']['id_objet'], $flux['data']['date_fin']);
}
// Si le statut est "prepa" c'est une création et on doit changer ça
// car pour l'instant SPIP ne permet pas de déclarer le statut par défaut !
if ($abonnement['statut'] == 'prepa') {
$modifs['statut'] = $abonnement['statut'] = 'actif';
}
// Si on a mis l'abonnement à la poubelle, on doit enlever les tâches liées
elseif ($abonnement['statut'] == 'poubelle') {
// Si on a mis l'abonnement inactif ou à la poubelle, on doit enlever les tâches liées
if (in_array($abonnement['statut'], array('inactif', 'poubelle'))) {
$liens = objet_trouver_liens(array('job' => '*'), array('abonnement' => $abonnement['id_abonnement']));
if ($liens and is_array($liens)){
// Et on les supprime toutes !
@ -101,21 +63,37 @@ function abonnements_post_edition($flux){
}
}
$modifs = array();
// Si l'échéance est VIDE, et que pourtant l'offre parente A BIEN une durée
// alors c'est qu'il faut initialiser les dates !
if ($abonnement['date_echeance'] == '0000-00-00 00:00:00' and ($duree = $offre['duree']) > 0) {
$modifs = abonnements_initialisation_dates($abonnement, $offre);
}
// Si les dates doivent être changées, on change le tableau de l'abonnement pour le test de statut qui suivra
if (isset($modifs['date_debut'])) {
$abonnement['date_debut'] = $modifs['date_debut'];
}
if (isset($modifs['date_fin'])) {
$abonnement['date_fin'] = $modifs['date_fin'];
}
// Seulement si personne n'a modifié le statut manuellement, alors on check les dates pour statufier
if (!$flux['data']['statut']) {
$jourdhui = date('Y-m-d H:i:s');
// Si aujourd'hui est dans les dates, on active
// Si aujourd'hui est entre date_debut et date_echeance, on active
if (
$abonnement['statut'] == 'inactif'
and $jourdhui >= $abonnement['date_debut']
and $jourdhui <= $abonnement['date_fin']
and $jourdhui <= $abonnement['date_echeance']
) {
$modifs['statut'] = 'actif';
}
// Si aujourd'hui est en dehors des dates, on désactive
// Si aujourd'hui est en dehors des dates début et FIN, on désactive
// on ne teste pas date_echeance car ce sera à un génie de désactiver si trop dépassée
elseif (
$abonnement['statut'] == 'actif'
and ($jourdhui < $abonnement['date_debut'] or $jourdhui > $abonnement['date_fin'])
and ($jourdhui < $abonnement['date_debut'] or $jourdhui >= $abonnement['date_fin'])
) {
$modifs['statut'] = 'inactif';
}
@ -126,12 +104,6 @@ function abonnements_post_edition($flux){
include_spip('action/editer_objet');
objet_modifier('abonnement', $flux['args']['id_objet'], $modifs);
}
// Si dans les modifications demandées au départ, il y a la date de fin, on reprogramme la désactivation
if (isset($flux['data']['date_fin'])) {
include_spip('inc/abonnements');
abonnements_programmer_desactivation($flux['args']['id_objet'], $flux['data']['date_fin']);
}
}
// Détection magique du plugin Commandes et d'une commande d'offre d'abonnement
elseif (
@ -179,9 +151,18 @@ function abonnements_post_edition($flux){
}
/*
* Ajout d'une tache CRON pour vérifier toutes les heures si les abonnements actifs ont une tâche de désactivation
* Ajout de tâches nécessaires aux abonnements
*
* - Une tâche pour vérifier toutes les heures si on a pas trop dépassé des échéances
* - Une tâche pour vérifier toutes les heures si les abonnements actifs ont une tâche de désactivation
* - Une tâche pour programmer les emails de notification à envoyer
*
* @pipeline taches_generales_cron
* @param array $taches Liste des génies et leur périodicité
* @return array Liste des tâches possiblement modifiées
*/
function abonnements_taches_generales_cron($taches){
$taches['abonnements_verifier_echeances'] = 60 * 60; // toutes les heures
$taches['abonnements_verifier_desactivation'] = 60 * 60; // toutes les heures
$taches['abonnements_verifier_notifications'] = 24 * 3600; // une fois par jour
return $taches;

@ -21,17 +21,20 @@ function action_modifier_echeance_abonnement_dist($arg=null) {
$duree = intval($duree)
and $id_abonnement = intval($id_abonnement)
and autoriser('modifier', 'abonnement', $id_abonnement)
and $abonnement = sql_fetsel('date_debut, date_fin', 'spip_abonnements', 'id_abonnement = '.$id_abonnement)
and $abonnement = sql_fetsel('date_debut, date_echeance, date_fin', 'spip_abonnements', 'id_abonnement = '.$id_abonnement)
) {
$jourdhui = date('Y-m-d H:i:s');
// Calculons la date de départ du renouvellement
$date_depart = $abonnement['date_fin'];
// Si la date de fin n'était pas encore défini, on reprend depuis le début
// Par défaut on part de la dernière échéance
$date_depart = $abonnement['date_echeance'];
// Si la date d'échéance n'était pas encore définie, on reprend depuis le début
if ($date_depart == '0000-00-00 00:00:00'){
$date_depart = $abonnement['date_debut'];
}
// Et si la date de fin était *déjà passée*, alors on renouvelle *à partir d'aujourd'hui* !
$jourdhui = date('Y-m-d H:i:s');
if ($date_depart < $jourdhui) {
// Et si la date d'échéance était *déjà passée*, alors on renouvelle *à partir d'aujourd'hui* !
elseif ($date_depart < $jourdhui) {
$date_depart = $jourdhui;
}
@ -53,17 +56,27 @@ function action_modifier_echeance_abonnement_dist($arg=null) {
// Si la période existe
if ($ajout){
$modifications = array();
// Si la durée est positive, on ajoute un + devant (le - est déjà là pour les négatives)
if ($duree > 0){
$ajout = ' +'.$ajout;
}
// Calcul de la date de fin
$nouvelle_echeance = date('Y-m-d H:i:s', strtotime($date_depart.$ajout));
$modifications['date_echeance'] = date('Y-m-d H:i:s', strtotime($date_depart.$ajout));
// Si la date de fin n'est PAS infinie ET qu'elle se retrouve plus petite que l'échéance
// On la remet au moins au même endroit que la nouvelle échéance
if (
$abonnement['date_fin'] != '0000-00-00 00:00:00'
and $abonnement['date_fin'] < $modifications['date_echeance']
) {
$modifications['date_fin'] = $modifications['date_echeance'];
}
// On lance la modification
include_spip('action/editer_objet');
$erreur = objet_modifier('abonnement', $id_abonnement, array('date_fin' => $nouvelle_echeance));
$erreur = objet_modifier('abonnement', $id_abonnement, $modifications);
return array($id_abonnement, $erreur);
}
@ -71,4 +84,3 @@ function action_modifier_echeance_abonnement_dist($arg=null) {
return false;
}

@ -0,0 +1,39 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Vérifier si des échéances sont dépassées
**/
function genie_abonnements_verifier_echeances_dist($time){
include_spip('base/abstract_sql');
lire_spip('inc/config');
$jourdhui = date('Y-m-d H:I:s');
$heures_max_retard = lire_config('abonnements/echeance_heures_limite', 48); // 48h par défaut
$date_max_retard = date('Y-m-d H:i:s', strtotime('-'.$heures_max_retard.'hours'));
// On va chercher tous les abonnements sans fin ou avec fin future,
// dont la dernière échéance est TROP dépassée (48h par défaut, configurable)
if (
$abonnements_retard = sql_allfetsel(
'id_abonnement, date_fin',
'spip_abonnements',
array(
"date_fin = '0000-00-00 00:00:00' or date_fin > $jourdhui",
"date_echeance < $date_max_retard",
)
)
and is_array($abonnements_retard)
) {
include_spip('action/editer_objet');
// Pour chaque abonnement trop dépassé, on met la date de fin à maintenant
// ce qui va normalement provoquer la désactivation immédiate
foreach ($abonnements_retard as $abonnement) {
objet_modifier('abonnement', $abonnement['id_abonnement'], array('date_fin' => $jourdhui));
}
}
return 1;
}

@ -7,6 +7,79 @@
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Initialiser les dates d'échéance et de fin pour un abonnement créé
*
* @pipeline_appel abonnement_initialisation_dates
* @param array $abonnement
* Informations sur l'abonnement à initialiser
* @param array $offre
* Informations sur l'offre de l'abonnement à initialiser
* @return array
* Retourne les modifications de dates initialisées
**/
function abonnements_initialisation_dates($abonnement, $offre){
$modifs = array();
// De combien doit-on augmenter la date
switch ($offre['periode']){
case 'heures':
$ajout = " + ${duree} hours";
break;
case 'jours':
$ajout = " + ${duree} days";
break;
case 'mois':
$ajout = " + ${duree} months";
break;
default:
$ajout = '';
break;
}
// Par défaut les dates de fin et de la prochaine échéance sont les mêmes
$modifs['date_echeance'] = date('Y-m-d H:i:s', strtotime($abonnement['date_debut'].$ajout));
$modifs['date_fin'] = $modifs['date_echeance'];
// Mais s'il y a le plugin Commandes et Bank et qu'on trouve commande et transaction
if (
_DIR_PLUGIN_COMMANDES
and _DIR_PLUGIN_BANK
and include_spip('action/editer_liens')
and $lien_commande = objet_trouver_liens(array('commande' => '*'), array('abonnement' => $abonnement['id_abonnement']))
and is_array($lien_commande)
// On prend juste la première commande qu'on trouve
and $id_commande = intval($lien_commande[0]['id_commande'])
// On cherche le dernier paiement bien payé pour cette commande
and $transaction = sql_fetsel(
'*', 'spip_transactions', array('id_commande = '.$id_commande, 'statut = "ok"')
)
) {
// On a trouvé la transaction qui a activé la commande qui a activé l'abonnement
// Si on détecte un prélèvement SEPA, on annule la date de fin !
if ($refcb = $transaction['refcb'] and strpos($refcb, 'SEPA') === 0) {
$modifs['date_fin'] = '0000-00-00 00:00:00';
}
// Si ya une fin de validité de carte bleue on en déduit une fin d'abonnement !
elseif ($validite = $transaction['validite']) {
include_spip('inc/bank');
list($year, $month) = explode('-', $validite);
$modifs['date_fin'] = bank_date_fin_mois($year, $month);
}
}
$modifs = pipeline(
'abonnement_initialisation_dates',
array(
'args' => array('abonnement' => $abonnement, 'offre' => $offre),
'data' => $modifs
)
);
return $modifs;
}
/*
* Programmer la désactivation d'un abonnement lors de sa date de fin
*
@ -84,5 +157,3 @@ function abonnements_notifier_echeance($id_abonnement, $nom, $email, $duree, $pe
)
);
}
?>

Loading…
Cancel
Save