Collecte de dons et adhésions. Permet de gérer également des campagnes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

529 lines
19 KiB

<?php
/**
* Utilisations de pipelines par Souscription
*
* @plugin Souscription
* @copyright 2013
* @author Olivier Tétard
* @licence GNU/GPL
* @package SPIP\Souscription\Pipelines
*/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* ieconfig
* http://contrib.spip.net/Importeur-Exporteur-de-configurations-documentation#reply460680
*/
function souscription_ieconfig_metas($table) {
$table['souscription']['titre'] = _T('souscription:titre_configurer_souscriptions');
$table['souscription']['icone'] = 'prive/themes/spip/images/souscription-16.png';
$table['souscription']['metas_serialize'] = 'souscription';
return $table;
}
/**
* Afficher la liste des transactions d'un auteur sur la page auteur de l'espace prive
*
* @pipeline affiche_auteurs_interventions
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function souscription_affiche_auteurs_interventions($flux) {
if ($id_auteur = intval($flux['args']['id_auteur'])) {
$flux['data'] .= recuperer_fond('prive/objets/liste/souscriptions', [
'id_auteur' => $id_auteur,
], ['ajax' => true]);
}
return $flux;
}
/**
* Optimiser la base de données en supprimant les liens orphelins
* de l'objet vers quelqu'un et de quelqu'un vers l'objet.
*
* @pipeline optimiser_base_disparus
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function souscription_optimiser_base_disparus($flux) {
include_spip('action/editer_liens');
$flux['data'] += objet_optimiser_liens(['souscription' => '*'], '*');
return $flux;
}
/**
* Renseigner les infos nominatives/adresses liees a une demande de paiement
* @param $flux
* @return mixed
*/
function souscription_bank_dsp2_renseigner_facturation($flux) {
if (
$id_transaction = $flux['args']['id_transaction']
and $sous = sql_fetsel('*', 'spip_souscriptions', 'id_transaction_echeance=' . intval($id_transaction))
) {
$flux['data']['nom'] = $sous['nom'];
$flux['data']['prenom'] = $sous['prenom'];
$flux['data']['email'] = $sous['courriel'];
$flux['data']['adresse'] = $sous['adresse'];
$flux['data']['code_postal'] = $sous['code_postal'];
$flux['data']['ville'] = $sous['ville'];
$flux['data']['pays'] = $sous['pays'];
}
return $flux;
}
/**
* Envoi d'une notification après reglement
*
* @pipeline trig_bank_notifier_reglement
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function souscription_trig_bank_notifier_reglement($flux) {
$souscription = sql_fetsel(
['courriel', 'id_souscription_campagne', 'abo_statut', 'id_souscription'],
'spip_souscriptions LEFT JOIN spip_souscriptions_liens USING (id_souscription)',
[
'id_objet=' . intval($flux['args']['id_transaction']),
'objet=' . sql_quote('transaction')
]
);
// on ne notifie pas les N echeances d'un don mensuel mais seulement la premiere
$n_echeance = 1;
if ($souscription['abo_statut'] == 'ok') {
$n_echeance = sql_countsel('spip_souscriptions_liens', 'id_souscription=' . intval($souscription['id_souscription']) . ' AND objet=' . sql_quote('transaction'));
}
if ($n_echeance <= 1) {
$email = $souscription['courriel'];
$campagne = $souscription['id_souscription_campagne'];
if ($flux['args']['succes']) {
$message = recuperer_fond(
_trouver_modele_courriel_reglement('succes', $campagne),
['id_transaction' => $flux['args']['id_transaction']]
);
} else {
$message = recuperer_fond(
_trouver_modele_courriel_reglement('echec', $campagne),
['id_transaction' => $flux['args']['id_transaction']]
);
}
spip_log("Envoi de notification de confirmation de paiement a [$email] pour la souscription #" . $flux['args']['id_transaction'], 'souscription');
include_spip('inc/notifications');
notifications_envoyer_mails($email, $message, '', $GLOBALS['meta']['email_webmaster']);
}
return $flux;
}
function _trouver_modele_courriel_reglement($type, $id_souscription_campagne) {
$modele = "modeles/mail-souscription-${type}";
if (trouver_fond("${modele}-${id_souscription_campagne}")) {
$modele = "${modele}-${id_souscription_campagne}";
}
return $modele;
}
function souscription_bank_traiter_reglement($flux) {
// on peut marquer cette souscription comme effective
// et mettre a jour le montant cumul si besoin
if (
$id_transaction = $flux['args']['id_transaction']
and $r = sql_fetsel('statut,montant,abo_uid', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and ($sous = sql_fetsel('*', 'spip_souscriptions', 'id_transaction_echeance=' . intval($id_transaction))
or $sous = sql_fetsel('*', 'spip_souscriptions', 'abonne_uid=' . sql_quote($r['abo_uid']) . ' AND abo_statut=' . sql_quote('ok')))
) {
$set = [
'statut' => 'ok',
];
if ($sous['abo_statut'] === 'ok') {
$set['montant_cumul'] = round(floatval($sous['montant_cumul']) + floatval($r['montant']), 2);
$set['id_transaction_echeance'] = 0;
} elseif ($sous['abo_statut'] === 'non') {
$set['id_transaction_echeance'] = 0;
}
sql_updateq('spip_souscriptions', $set, 'id_souscription=' . intval($sous['id_souscription']));
$flux['data'] .= ' <br />Vous allez recevoir un email de confirmation.';
}
return $flux;
}
function souscription_trig_bank_reglement_en_attente($flux) {
if (
$id_transaction = $flux['args']['id_transaction']
and $r = sql_fetsel('statut,montant', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and $sous = sql_fetsel('id_souscription', 'spip_souscriptions_liens', ['objet=' . sql_quote('transaction'), 'id_objet=' . intval($id_transaction)])
) {
$set = [
'statut' => 'attente',
];
sql_updateq('spip_souscriptions', $set, 'id_souscription=' . intval($sous['id_souscription']));
}
return $flux;
}
function souscription_bank_traiter_remboursement($flux) {
// on marque cette souscription comme remboursee
// et mettre a jour le montant cumul si besoin
if (
$id_transaction = $flux['args']['id_transaction']
and $r = sql_fetsel('statut,montant', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and $sous = sql_fetsel('id_souscription', 'spip_souscriptions_liens', ['objet=' . sql_quote('transaction'), 'id_objet=' . intval($id_transaction)])
) {
$set = [
'statut' => 'rembourse'
];
#if ($sous['abo_statut']=="ok"){
# $set['montant_cumul'] = round(floatval($sous['montant_cumul']) + floatval($r['montant']),2);
#}
sql_updateq('spip_souscriptions', $set, 'id_souscription=' . intval($sous['id_souscription']));
}
$flux['data'] .= ' <br />Souscription #' . $sous['id_souscription'] . ' associée remboursée';
return $flux;
}
/**
* Activer la souscription abonnee
* @param $flux
* @return mixed
*/
function souscription_bank_abos_activer_abonnement($flux) {
if (!$flux['data']) {
$abo_uid = $flux['args']['abo_uid'];
$set = [
'abonne_uid' => sql_quote($abo_uid),
'abo_statut' => sql_quote('ok'),
];
if ($id_transaction = $flux['args']['id_transaction']) {
if (
!$row = sql_fetsel('*', 'spip_souscriptions', 'id_transaction_echeance=' . intval($id_transaction))
or !$id_souscription = $row['id_souscription']
) {
spip_log("Pas de souscription recurente a activer pour la transaction $id_transaction", 'souscriptions_abos' . _LOG_ERREUR);
return $flux;
}
if (!$r = sql_fetsel('statut,montant', 'spip_transactions', 'id_transaction=' . intval($id_transaction))) {
spip_log("transaction $id_transaction inconnue (abo $abo_uid)", 'souscriptions_abos' . _LOG_ERREUR);
return $flux;
}
if ($r['statut'] !== 'ok') {
spip_log("La transaction $id_transaction n'a pas ete reglee (abo $abo_uid)", 'souscriptions_abos' . _LOG_ERREUR);
return $flux;
}
// fixer le montant cumul des dons
$set['montant_cumul'] = sql_quote($r['montant']);
} elseif (
!$abo_uid
or !($row = sql_fetsel('*', 'spip_souscriptions', 'abonne_uid=' . sql_quote($abo_uid)))
) {
spip_log("Impossible de retrouver l'abo_uid $abo_uid", 'souscriptions_abos' . _LOG_ERREUR);
return $flux;
}
if ($row['abo_statut'] === 'non') {
// cela ne nous concerne pas : ce n'est pas une souscription recurrente
spip_log('activer_abonnement sur souscription #' . $row['id_souscription'] . ' non recurente', 'souscriptions_abos');
return $flux;
}
// ici on ne traite que le premier appel, a la premiere transaction payee
// et pas les autres appels sur paiements reccurentes (bank v3.0+)
if (
$row['abo_statut'] === 'ok'
and $row['abonne_uid'] === $abo_uid
and (!isset($set['montant_cumul']) or floatval($row['montant_cumul']) >= 0.01)
) {
// c'est un double appel, on retourne sans rien faire
spip_log('activer_abonnement sur souscription #' . $row['id_souscription'] . ' abo_statut=ok (double appel)', 'souscriptions_abos');
return $flux;
}
if (
$id_transaction
and ($id_transaction == $row['id_transaction_echeance'])
) {
$prochaine_echeance = date('Y-m-d H:i:s', strtotime('+1 month', strtotime($row['date_souscription'])));
if ($flux['args']['validite'] === 'echeance') {
$set['date_echeance'] = sql_quote($prochaine_echeance);
$set['date_fin'] = $set['date_echeance'];
} else {
if (
$prochaine_echeance < $flux['args']['validite']
or $flux['args']['validite'] < $row['date_souscription']
) {
$set['date_echeance'] = sql_quote($prochaine_echeance);
} else {
$set['date_echeance'] = sql_quote($row['date_souscription']);
}
$set['date_fin'] = sql_quote($flux['args']['validite']);
}
$set['id_transaction_echeance'] = 0;
}
if ($row['id_souscription'] and count($set)) {
sql_update('spip_souscriptions', $set, 'id_souscription=' . intval($row['id_souscription']));
}
if ($row['id_souscription']) {
$flux['data'] = $row['id_souscription'];
}
}
return $flux;
}
/**
* Decrire l'echeance d'une souscription mensuelle
* @param array $flux
* @return array
*/
function souscription_bank_abos_decrire_echeance($flux) {
if (
$id_transaction = $flux['args']['id_transaction']
and $row = sql_fetsel('*', 'spip_souscriptions', 'id_transaction_echeance=' . intval($id_transaction))
) {
$flux['data']['montant'] = $row['montant'];
$flux['data']['montant_ht'] = $row['montant'];
}
return $flux;
}
/**
* Gerer le renouvellement lors de la notification de paiement d'une echeance par le presta bancaire
*
* @param array
* @return array
*/
function souscription_bank_abos_renouveler($flux) {
if (!$flux['data']) {
$id = $flux['args']['id'];
if (strncmp($id, 'uid:', 4) == 0) {
$where = 'abonne_uid=' . sql_quote(substr($id, 4));
// retrouver la souscription via la transaction si jamais on a pas cet abonne_uid
// resilience
if (
!sql_countsel('spip_souscriptions', $where)
and $id_transaction = sql_getfetsel('id_transaction', 'spip_transactions', 'statut=' . sql_quote('ok') . ' AND abo_uid=' . sql_quote(substr($id, 4)))
and $id_souscription = sql_getfetsel('id_souscription', 'spip_souscriptions_liens', 'objet=' . sql_quote('transaction') . ' AND id_objet=' . intval($id_transaction))
) {
$where = 'id_souscription=' . intval($id_souscription);
// mettre a jour l'abonne_uid si il est reste vide
if (!sql_getfetsel('abonne_uid', 'spip_souscriptions', $where)) {
sql_updateq('spip_souscriptions', ['abonne_uid' => substr($id, 4)], $where);
}
}
} else {
$where = 'id_souscription=' . intval($id);
}
if ($row = sql_fetsel('*', 'spip_souscriptions', $where, '', 'date_souscription DESC')) {
$options = [
'auteur' => $row['courriel'],
'parrain' => 'souscription',
'tracking_id' => $row['id_souscription'],
'id_auteur' => $row['id_auteur'],
'champs' => [
'date_transaction' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']),
]
];
$inserer_transaction = charger_fonction('inserer_transaction', 'bank');
include_spip('action/editer_liens');
// verifier que c'est bien l'echeance attendue
// et sinon generer des transactions offline de rattrapage
if (!intval($row['date_echeance'])) {
spip_log('souscription #' . $row['id_souscription'] . ' date echeance vide ' . $row['date_echeance'], 'souscriptions_abos');
$row['date_echeance'] = $row['date_souscription'];
}
$date_echeance = $row['date_echeance'];
$datem45 = date('Y-m-d H:i:s', strtotime('-45 day', $_SERVER['REQUEST_TIME']));
while ($date_echeance < $datem45) {
$o = $options;
$o['champs']['date_transaction'] = $date_echeance;
$o['champs']['mode'] = 'offline';
$prochaine_echeance = date('Y-m-d H:i:s', strtotime('+1 month', strtotime($date_echeance)));
if ($id_transaction = $inserer_transaction($row['montant'], $o)) {
// regler la transacton offline
$regler_transaction = charger_fonction('regler_transaction', 'bank');
$regler_transaction($id_transaction);
// mettre a jour la souscription
$set = [
'statut' => 'ok',
'abo_statut' => 'ok',
'montant_cumul' => round(floatval($row['montant_cumul']) + floatval($row['montant']), 2),
'date_echeance' => $prochaine_echeance,
'abo_fin_raison' => '', // effacer la trace d'un rappel de paiement manquant
];
sql_updateq('spip_souscriptions', $set, 'id_souscription=' . intval($row['id_souscription']));
$row = sql_fetsel('*', 'spip_souscriptions', 'id_souscription=' . intval($row['id_souscription']));
objet_associer(['souscription' => $row['id_souscription']], ['transaction' => $id_transaction]);
spip_log("transaction offline $id_transaction sur souscription #" . $row['id_souscription'] . " / prochaine echeance $prochaine_echeance", 'souscriptions_abos');
}
$date_echeance = $prochaine_echeance;
}
// si il y a deja eu une transaction echeance il y a moins de 15j sur cette souscription
// c'est un double appel, renvoyer l'id_transaction concerne
$datem15 = date('Y-m-d H:i:s', strtotime('-15 day', $_SERVER['REQUEST_TIME']));
if (
$id_transaction = sql_getfetsel(
'id_transaction',
'spip_transactions',
'statut<>' . sql_quote('commande')
. ' AND date_transaction>' . sql_quote($datem15)
. ' AND parrain=' . sql_quote('souscription')
. ' AND tracking_id=' . intval($row['id_souscription'])
. ' AND id_auteur=' . intval($row['id_auteur']),
'',
'date_transaction'
)
) {
$flux['data'] = $id_transaction;
}
// ouvrir la transaction
elseif ($id_transaction = $inserer_transaction($row['montant'], $options)) {
$prochaine_echeance = $row['date_echeance'];
$datep15 = date('Y-m-d H:i:s', strtotime('+15 day', $_SERVER['REQUEST_TIME']));
spip_log('souscription #' . $row['id_souscription'] . " $prochaine_echeance vs $datep15", 'souscriptions_abos' . _LOG_DEBUG);
// recaler la prochaine echeance si trop en avance (double appel anterieur ou erreur de calcul)
while ($prochaine_echeance > $datep15) {
$prochaine_echeance = date('Y-m-d H:i:s', strtotime('-1 month', strtotime($prochaine_echeance)));
spip_log('souscription #' . $row['id_souscription'] . " echeance=echeance-1 month : $prochaine_echeance vs $datep15", 'souscriptions_abos' . _LOG_DEBUG);
}
// l'incrementer pour atteindre celle du mois prochain
while ($prochaine_echeance < $datep15) {
$prochaine_echeance = date('Y-m-d H:i:s', strtotime('+1 month', strtotime($prochaine_echeance)));
spip_log('souscription #' . $row['id_souscription'] . " echeance=echeance+1 month : $prochaine_echeance vs $datep15", 'souscriptions_abos' . _LOG_DEBUG);
}
// a ce stade on ne sait pas encore si la transaction est reussie ou en echec
// on ne peut donc pas incrementer le montant cumul, mais seulement mettre a jour les echeances etc
// si echec => declenchera une resiliation
// si succes => declenchera un traitement reglement ou l'on mettra a jour le cumul
$set = [
'id_transaction_echeance' => $id_transaction,
'statut' => 'ok',
'abo_statut' => 'ok',
'date_echeance' => $prochaine_echeance,
'abo_fin_raison' => '', // effacer la trace d'un rappel de paiement manquant
];
sql_updateq('spip_souscriptions', $set, 'id_souscription=' . intval($row['id_souscription']));
$row = sql_fetsel('*', 'spip_souscriptions', 'id_souscription=' . intval($row['id_souscription']));
objet_associer(['souscription' => $row['id_souscription']], ['transaction' => $id_transaction]);
$flux['data'] = $id_transaction;
// verifier si ce n'est pas la derniere transaction, auquel cas on notifie
if (
$row['date_echeance'] > $row['date_fin']
and $row['date_fin'] > $row['date_souscription']
) {
// Notifications
if ($notifications = charger_fonction('notifications', 'inc', true)) {
$notifications('informersouscriptionterminee', $row['id_souscription']);
}
}
}
}
}
return $flux;
}
/**
* Prendre en charge la resiliation demandee par le client
*
* @param array $flux
* @return array
*/
function souscription_bank_abos_resilier($flux) {
spip_log('souscription_bank_abos_resilier id=' . $flux['args']['id'], 'souscriptions_abos');
$id = $flux['args']['id'];
if (strncmp($id, 'uid:', 4) == 0) {
$where = 'abonne_uid=' . sql_quote(substr($id, 4));
} else {
$where = 'id_souscription=' . intval($id);
}
if ($row = sql_fetsel('*', 'spip_souscriptions', $where, '', 'date_souscription DESC')) {
$set = [
'abo_statut' => 'resilie',
'abo_fin_raison' => $flux['args']['message'],
];
if ($flux['args']['date_fin'] == 'date_echeance') {
$set['date_fin'] = date('Y-m-d 00:00:00', strtotime($row['date_echeance']));
if (!function_exists('souscription_derniere_echeance')) {
include_spip('public/parametrer');
}
$set['date_echeance'] = souscription_derniere_echeance($row['date_echeance'], $set['date_fin']);
} else {
$set['date_fin'] = $flux['args']['date_fin'];
}
$ok = true;
if (
$flux['args']['notify_bank']
and $mode_paiement = sql_getfetsel('mode', 'spip_transactions', 'abo_uid=' . sql_quote($row['abonne_uid'], '', 'text'), '', 'id_transaction DESC')
) {
$ok = abos_resilier_notify_bank($row['abonne_uid'], $mode_paiement);
}
if ($ok) {
sql_updateq('spip_souscriptions', $set, 'id_souscription=' . intval($row['id_souscription']));
}
// si c'est une resiliation suite a refus de paiement, notifier
if (strncmp($flux['args']['message'], '[bank]', 6) == 0) {
// Notifications
if ($notifications = charger_fonction('notifications', 'inc', true)) {
$id_transaction = 0;
if (preg_match(",\b#(\d+)\b,", $flux['args']['message'], $m)) {
$id_transaction = intval($m[1]);
}
$notifications('informersouscriptioninterrompue', $row['id_souscription'], ['id_transaction' => $id_transaction, 'message' => $flux['args']['message']]);
}
}
} else {
spip_log("Pas de souscription WHERE $where", 'souscriptions_abos' . _LOG_ERREUR);
}
return $flux;
}
/**
* Programmer la surveillance des echeances
* @param $taches_generales
* @return mixed
*/
function souscription_taches_generales_cron($taches_generales) {
$taches_generales['surveiller_paiement_souscriptions'] = 2 * 3600; // 2h
return $taches_generales;
}