From 687e9f26448d89273a2ee93facd7a3295c77916d Mon Sep 17 00:00:00 2001 From: "rastapopoulos@spip.org" <> Date: Sun, 14 Jun 2015 00:44:16 +0000 Subject: [PATCH] =?UTF-8?q?On=20utilise=20la=20nouvelle=20date=20d'=C3=A9c?= =?UTF-8?q?h=C3=A9ance.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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… --- .gitattributes | 1 + abonnements_pipelines.php | 97 ++++++++++-------------- action/modifier_echeance_abonnement.php | 32 +++++--- genie/abonnements_verifier_echeances.php | 39 ++++++++++ inc/abonnements.php | 75 +++++++++++++++++- 5 files changed, 174 insertions(+), 70 deletions(-) create mode 100644 genie/abonnements_verifier_echeances.php diff --git a/.gitattributes b/.gitattributes index 0523a53..da47483 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/abonnements_pipelines.php b/abonnements_pipelines.php index 64e07d4..6e3ba33 100644 --- a/abonnements_pipelines.php +++ b/abonnements_pipelines.php @@ -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; diff --git a/action/modifier_echeance_abonnement.php b/action/modifier_echeance_abonnement.php index a665c2e..1927f7c 100644 --- a/action/modifier_echeance_abonnement.php +++ b/action/modifier_echeance_abonnement.php @@ -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; } - diff --git a/genie/abonnements_verifier_echeances.php b/genie/abonnements_verifier_echeances.php new file mode 100644 index 0000000..4a17791 --- /dev/null +++ b/genie/abonnements_verifier_echeances.php @@ -0,0 +1,39 @@ + $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; +} diff --git a/inc/abonnements.php b/inc/abonnements.php index db5781a..1a91db6 100644 --- a/inc/abonnements.php +++ b/inc/abonnements.php @@ -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 ) ); } - -?>