You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
commandes/commandes_pipelines.php

627 lines
22 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* Pieplines utilisées par le plugin Commandes
*
* @plugin Commandes
* @copyright 2014
* @author Ateliers CYM, Matthieu Marcillaud, Les Développements Durables
* @licence GPL 3
* @package SPIP\Commandes\Pipelines
*/
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Insertion de la feuille de style CSS sur les pages publiques
*
* @pipeline insert_head_css
* @param string $flux Données du pipeline
* @return string Données du pipeline
*/
function commandes_insert_head_css($flux) {
$css = find_in_path('css/commandes.css');
$flux .= "<link rel='stylesheet' type='text/css' media='all' href='$css' />\n";
return $flux;
}
/**
* Optimiser la base de donnée en abandonnant toutes les commandes en cours qui sont trop vieilles
*
* Le délai de "péremption" est défini dans les options de configuration du plugin.
* Par défaut, c'est 24h
*
* @pipeline optimiser_base_disparus
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function commandes_optimiser_base_disparus($flux) {
include_spip('inc/config');
include_spip('base/abstract_sql');
$duree_vie = lire_config('commandes/duree_vie', 24);
// On cherche la date depuis quand on a le droit d'avoir fait la commande
$depuis = date('Y-m-d H:i:s', time() - 3600 * intval($duree_vie));
// On récupère les commandes trop vieilles
$commandes = sql_allfetsel(
'id_commande',
'spip_commandes',
'statut = ' . sql_quote('encours') . ' and date<' . sql_quote($depuis)
);
// S'il y a bien des commandes à abandonner
if ($commandes) {
$ids_commandes = array_column($commandes, 'id_commande');
include_spip('action/editer_objet');
foreach ($ids_commandes as $id_commande) {
objet_instituer('commande', $id_commande, ['statut' => 'abandonne']);
}
$flux['data'] += count($commandes);
}
return $flux;
}
/**
* Ajout de contenu sur certaines pages
*
* - Formulaires pour modifier les dates sur la fiche d'une commande
*
* @pipeline affiche_milieu
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function commandes_affiche_milieu($flux) {
if (
$exec = trouver_objet_exec($flux['args']['exec'])
and $exec['edition'] == false
and $exec['type'] == 'commande'
and $id_table_objet = $exec['id_table_objet']
and (isset($flux['args'][$id_table_objet]) and $id_commande = intval($flux['args'][$id_table_objet]))
) {
$texte = recuperer_fond('prive/squelettes/contenu/commande_affiche_milieu', ['id_commande' => $id_commande]);
}
if (isset($texte)) {
if ($p = strpos($flux['data'], '<!--affiche_milieu-->')) {
$flux['data'] = substr_replace($flux['data'], $texte, $p, 0);
} else {
$flux['data'] .= $texte;
}
}
return $flux;
}
/**
* Ajout de contenu dans la liste des éléments en attente de validation
*
* - Liste des commandes aux statuts définis comme "actifs" dans les options de configuration
*
* @pipeline accueil_encours
* @param array $flux Données du pipeline
* @return array Données du pipeline
*/
function commandes_accueil_encours($flux) {
include_spip('inc/config');
$activer = lire_config('commandes/accueil_encours');
$statuts = lire_config('commandes/statuts_actifs');
if ($activer and is_array($statuts)) {
foreach ($statuts as $statut) {
if ($nb = sql_countsel(table_objet_sql('commande'), 'statut=' . sql_quote($statut))) {
$titre = singulier_ou_pluriel($nb, 'commandes:info_1_commande_statut_' . $statut, 'commandes:info_nb_commandes_statut_' . $statut);
$flux .= recuperer_fond(
'prive/objets/liste/commandes',
[
'titre' => $titre,
'statut' => $statut,
'cacher_tri' => true,
'nb' => 5],
['ajax' => true]
);
}
}
}
return $flux;
}
/**
* Ajout de liste sur la vue d'un auteur
*
* - Liste des commandes de l'auteur
*
* @pipeline affiche_auteurs_interventions
* @param array $flux Données du pipeline
* @return array Données du pipeline
**/
function commandes_affiche_auteurs_interventions($flux) {
if ($id_auteur = intval($flux['args']['id_auteur'])) {
$ins = recuperer_fond(
'prive/objets/liste/commandes',
[
'id_auteur' => $id_auteur,
'titre' => _T('commandes:titre_commandes_auteur'),
'cacher_tri' => true
],
['ajax' => true]
);
$mark = '<!--bank-->';
if (($p = strpos($flux['data'], $mark)) !== false) {
$flux['data'] = substr_replace($flux['data'], $ins, $p + strlen($mark), 0);
} else {
$flux['data'] .= $ins;
}
}
return $flux;
}
/**
* Compléter la liste des types d'adresses du plugin Coordonnées
*
* Ajout de 2 types d'adresses : facturation et livraison
*
* @pipeline types_coordonnees
* @param array $liste Données du pipeline
* @return array Données du pipeline
**/
function commandes_types_coordonnees($liste) {
$types_adresses = $liste['adresse'];
if (!$types_adresses or !is_array($types_adresses)) {
$types_adresses = [];
}
// on définit les couples types + chaînes de langue à ajouter
$types_adresses_commandes = [
'livraison' => _T('commandes:type_adresse_livraison'),
'facturation' => _T('commandes:type_adresse_facturation')
];
// on les rajoute à la liste des types des adresses
$liste['adresse'] = array_merge($types_adresses, $types_adresses_commandes);
return $liste;
}
/**
* Renseigner les infos de facturation liee a une commande
* @param array $flux
* @return array mixed
*/
function commandes_bank_dsp2_renseigner_facturation($flux) {
if (
isset($flux['args']['id_transaction'])
and $id_transaction = intval($flux['args']['id_transaction'])
and isset($flux['args']['id_commande'])
and $id_commande = intval($flux['args']['id_commande'])
) {
$commande_infos_client = charger_fonction('infos_client', 'commande');
$client = $commande_infos_client($id_commande);
if (!empty($client['nom'])) {
$flux['data']['nom'] = $client['nom'];
}
if (!empty($client['facturation'])) {
if (!empty($client['facturation']['nom'])) {
$flux['data']['nom'] = $client['facturation']['nom'];
}
$organisation = $client["facturation"]['organisation'];
if ($organisation and empty($flux['data']['nom'])) {
$flux['data']['nom'] = $organisation;
$organisation = '';
}
if (!empty($client['facturation']['adresse'])) {
$adresse = [$organisation];
$adresse[] = (empty($client['facturation']['adresse']['voie']) ? '' : $client['facturation']['adresse']['voie']);
$adresse[] = (empty($client['facturation']['adresse']['complement']) ? '' : $client['facturation']['adresse']['complement']);
$adresse = array_filter($adresse);
$flux['data']['adresse'] = trim(implode("\n", $adresse));
$flux['data']['code_postal'] = (empty($client['facturation']['adresse']['code_postal']) ? '' : $client['facturation']['adresse']['code_postal']);
$flux['data']['ville'] = (empty($client['facturation']['adresse']['ville']) ? '' : $client['facturation']['adresse']['ville']);
$flux['data']['pays'] = (empty($client['facturation']['adresse']['pays']) ? '' : $client['facturation']['adresse']['pays']);
}
}
}
return $flux;
}
/**
* Avant facturation, remettre encours une commande en attente ou en erreur suite à une première tentative de paiement
* sinon le modeles/transaction_details renvoie du vide, et la facture et vide
* (et potentiellement autres soucis de workflow)
*
* @param array $flux
* @return array
*/
function commandes_bank_pre_facturer_reglement($flux) {
// Si on est dans le bon cas d'un paiement de commande et qu'il y a un id_commande et que la commande existe toujours
if (
$id_transaction = $flux['args']['id_transaction']
and $transaction = sql_fetsel('*', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and $id_commande = $transaction['id_commande']
and $commande = sql_fetsel('id_commande, statut, id_auteur, echeances, reference, mode', 'spip_commandes', 'id_commande=' . intval($id_commande))
) {
$statut_commande = $commande['statut'];
if (in_array($statut_commande, ['attente', 'erreur', 'abandonne'])) {
$statut_nouveau = 'encours';
}
// S'il y a bien un statut à changer
if ($statut_nouveau !== $statut_commande) {
spip_log("commandes_bank_pre_facturer_reglement marquer la commande #$id_commande statut: $statut_commande -> $statut_nouveau mode=''", 'commandes');
// On met a jour la commande
include_spip('action/editer_commande');
commande_modifier($id_commande, ['statut' => $statut_nouveau, 'mode' => '']);
}
}
return $flux;
}
/**
* Enregistrer le bon reglement d'une commande liee a une transaction du plugin bank
*
* @pipeline bank_traiter_reglement
* @param array $flux
* @return array mixed
*/
function commandes_bank_traiter_reglement($flux) {
// Si on est dans le bon cas d'un paiement de commande et qu'il y a un id_commande et que la commande existe toujours
if (
$id_transaction = $flux['args']['id_transaction']
and $transaction = sql_fetsel('*', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and $id_commande = $transaction['id_commande']
and $commande = sql_fetsel('id_commande, statut, id_auteur, echeances, reference', 'spip_commandes', 'id_commande=' . intval($id_commande))
) {
$statut_commande = $commande['statut'];
$montant_regle = $transaction['montant_regle'];
$transaction_mode = $transaction['mode'];
$statut_nouveau = 'paye';
// Si la commande n'a pas d'échéance, le montant attendu est celui du prix de la commande
include_spip('inc/commandes_echeances');
if (
!$commande['echeances']
or !$echeances = unserialize($commande['echeances'])
or !$desc = commandes_trouver_prochaine_echeance_desc($id_commande, $echeances, true)
or !isset($desc['montant'])
) {
$fonction_prix = charger_fonction('prix', 'inc/');
$montant_attendu = $fonction_prix('commande', $id_commande);
} // Sinon le montant attendu est celui de la prochaine échéance (en ignorant la dernière transaction OK que justement on cherche à tester)
else {
$montant_attendu = $desc['montant'];
}
spip_log("commande #$id_commande attendu:$montant_attendu regle:$montant_regle", 'commandes');
// Si le plugin n'était pas déjà en payé et qu'on a pas assez payé
// (si le plugin était déjà en payé, ce sont possiblement des renouvellements)
if (
$statut_commande != 'paye'
and (floatval($montant_attendu) - floatval($montant_regle)) >= 0.01
) {
$statut_nouveau = 'partiel';
}
// S'il y a bien un statut à changer
if ($statut_nouveau !== $statut_commande) {
spip_log("commandes_bank_traiter_reglement marquer la commande #$id_commande statut: $statut_commande -> $statut_nouveau mode=$transaction_mode", 'commandes');
// On met a jour la commande
include_spip('action/editer_commande');
commande_modifier($id_commande, ['statut' => $statut_nouveau, 'mode' => $transaction_mode]);
}
// un message gentil pour l'utilisateur qui vient de payer, on lui rappelle son numero de commande
$flux['data'] .= '<br />' . _T('commandes:merci_de_votre_commande_paiement', ['reference' => $commande['reference']]);
}
return $flux;
}
/**
* Enregistrer le reglement en attente d'une commande liee a une transaction du plugin bank
* (cas du reglement par cheque par exemple)
*
* @pipeline trig_bank_reglement_en_attente
* @param array $flux
* @return array mixed
*/
function commandes_trig_bank_reglement_en_attente($flux) {
// Si on est dans le bon cas d'un paiement de commande et qu'il y a un id_commande et que la commande existe toujours
if (
$id_transaction = $flux['args']['id_transaction']
and $transaction = sql_fetsel('*', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and $id_commande = $transaction['id_commande']
and $commande = sql_fetsel('id_commande, statut, id_auteur, mode', 'spip_commandes', 'id_commande=' . intval($id_commande))
) {
$statut_commande = $commande['statut'];
$transaction_mode = $transaction['mode'];
$commande_mode = $commande['mode'];
$statut_nouveau = 'attente';
if ($statut_nouveau !== $statut_commande or $transaction_mode !== $commande_mode) {
spip_log("commandes_trig_bank_reglement_en_attente marquer la commande #$id_commande statut: $statut_commande -> $statut_nouveau mode=$transaction_mode", 'commandes');
//on met a jour la commande
include_spip('action/editer_commande');
commande_modifier($id_commande, ['statut' => $statut_nouveau, 'mode' => $transaction_mode]);
}
}
return $flux;
}
/**
* Enregistrer le reglement en echec d'une commande liee a une transaction du plugin bank
* (cas du reglement annule ou du refus de carte etc)
*
* @pipeline trig_bank_reglement_en_echec
* @param array $flux
* @return array mixed
*/
function commandes_trig_bank_reglement_en_echec($flux) {
// Si on est dans le bon cas d'un paiement de commande et qu'il y a un id_commande et que la commande existe toujours
if (
$id_transaction = $flux['args']['id_transaction']
and $transaction = sql_fetsel('*', 'spip_transactions', 'id_transaction=' . intval($id_transaction))
and $id_commande = $transaction['id_commande']
and $commande = sql_fetsel('id_commande, statut, id_auteur', 'spip_commandes', 'id_commande=' . intval($id_commande))
) {
$statut_commande = $commande['statut'];
$transaction_mode = $transaction['mode'];
$statut_nouveau = $statut_commande;
// on ne passe la commande en erreur que si le reglement a effectivement echoue,
// pas si c'est une simple annulation (retour en arriere depuis la page de paiement bancaire)
if (strncmp($transaction['statut'], 'echec', 5) == 0) {
$statut_nouveau = 'erreur';
}
if ($statut_nouveau !== $statut_commande) {
spip_log("commandes_trig_bank_reglement_en_echec marquer la commande #$id_commande statut: $statut_commande -> $statut_nouveau mode=$transaction_mode", 'commandes');
//on met a jour la commande
include_spip('action/editer_commande');
commande_modifier($id_commande, ['statut' => $statut_nouveau, 'mode' => $transaction_mode]);
}
}
return $flux;
}
/**
* Déclarer les échéances à la banque
*
* @pipeline bank_abos_decrire_echeance
**/
function commandes_bank_abos_decrire_echeance($flux) {
if (
// on a une transaction sous la main
$id_transaction = intval($flux['args']['id_transaction'])
// et que cette transaction a un id_commande
and $id_commande = intval(sql_getfetsel('id_commande', 'spip_transactions', 'id_transaction = ' . $id_transaction))
// et que la commande a des informations d'échéances
and $commande = sql_fetsel('echeances_type, echeances_date_debut, echeances', 'spip_commandes', 'id_commande = ' . $id_commande)
and $echeances = unserialize($commande['echeances'])
and $echeances_type = $commande['echeances_type']
and in_array($echeances_type, ['mois', 'annee'])
) {
// On définit la périodicité
switch ($echeances_type) {
case 'mois':
$flux['data']['freq'] = 'monthly';
break;
case 'annee':
$flux['data']['freq'] = 'yearly';
break;
}
if (
$commande['echeances_date_debut']
and strtotime($commande['echeances_date_debut']) > $_SERVER['REQUEST_TIME']
) {
$flux['data']['date_start'] = $commande['echeances_date_debut'];
}
// Si c'est une seule valeur toute simple
if (!is_array($echeances)) {
$echeances = floatval($echeances);
$flux['data']['montant'] = $echeances;
} // ou un array d'une seule echeance
elseif (count($echeances) == 1) {
$echeance = reset($echeances);
$flux['data']['montant'] = floatval($echeance['montant']);
if (isset($echeance['nb'])) {
$flux['data']['count'] = $echeance['nb'];
}
} // Sinon c'est un peu plus compliqué, et pour l'instant on ne gère que DEUX montants possibles
elseif (count($echeances) >= 2) {
// Premier montant d'échéances
$flux['data']['montant_init'] = $echeances[0]['montant'];
$flux['data']['count_init'] = $echeances[0]['nb'];
// Deuxième montant d'échéances
$flux['data']['montant'] = $echeances[1]['montant'];
if (isset($echeances[1]['nb'])) {
$flux['data']['count'] = $echeances[1]['nb'];
}
}
}
return $flux;
}
/**
* Lier une commande à un identifiant bancaire lorsqu'un prélèvement bancaire est bien validé
*
* @pipeline bank_abos_activer_abonnement
**/
function commandes_bank_abos_activer_abonnement($flux) {
// Si on a une transaction
if ($id_transaction = intval($flux['args']['id_transaction'])) {
$where = 'id_transaction = ' . $id_transaction;
} // Sinon on cherche par l'identifiant d'abonnement bancaire
elseif ($abo_uid = $flux['args']['abo_uid']) {
$where = 'abo_uid = ' . sql_quote($abo_uid);
}
// On gère d'abord les erreurs possibles si on ne trouve pas la bonne transaction
if (!$where or !$transaction = sql_fetsel('*', 'spip_transactions', $where)) {
spip_log("Impossible de trouver la transaction ($id_transaction / $abo_uid).", 'commandes.' . _LOG_ERREUR);
$flux['data'] = false;
} elseif ($transaction['statut'] == 'commande') {
spip_log("La transaction ${transaction['id_transaction']} na pas été réglée.", 'commandes.' . _LOG_ERREUR);
$flux['data'] = false;
} elseif (strncmp($transaction['statut'], 'echec', 5) == 0) {
spip_log("La transaction ${transaction['id_transaction']} a echoué.", 'commandes.' . _LOG_ERREUR);
$flux['data'] = false;
} // Si on a trouvé ce qu'il faut, on va lier la commande à l'identifiant bancaire
elseif ($id_commande = intval($transaction['id_commande'])) {
include_spip('action/editer_objet');
objet_modifier('commande', $id_commande, ['bank_uid' => $flux['args']['abo_uid']]);
}
return $flux;
}
/**
* Créer la transaction correspondant à la prochaine échéance d'une commande
*
* @pipeline bank_abos_preparer_echeance
**/
function commandes_bank_abos_preparer_echeance($flux) {
// On commence par chercher la commande dont il s'agit
// et vérifier qu'elle a des échéances
if (
isset($flux['args']['id'])
and $id = $flux['args']['id']
and strncmp($id, 'uid:', 4) == 0
and $bank_uid = substr($id, 4)
) {
// robustesse pour retrouver la comande correspondant a un numero d'abonnement
if (
$id_commande = sql_getfetsel('id_commande', 'spip_commandes', 'bank_uid=' . sql_quote($bank_uid))
or $id_commande = sql_getfetsel('id_commande', 'spip_transactions', 'abo_uid=' . sql_quote($bank_uid))
) {
if (
$commande = sql_fetsel('*', 'spip_commandes', 'id_commande=' . intval($id_commande))
and $echeances = unserialize($commande['echeances'])
and $echeances_type = $commande['echeances_type']
) {
include_spip('inc/commandes_echeances');
// Si on a bien trouvé une prochaine échéance
if (
$desc = commandes_trouver_prochaine_echeance_desc($id_commande, $echeances)
and isset($desc['montant'])
) {
include_spip('action/editer_objet');
$set = ['statut' => 'attente_echeance'];
// robustesse/reparation si echec d'update a la premiere echeance payee
if (!$commande['bank_uid']) {
$set['bank_uid'] = $bank_uid;
}
// On remet la commande en attente_echeance de paiement puisqu'on attend le paiement d'une échéance
objet_modifier('commande', $id_commande, $set);
// On crée la transaction qui testera le vrai paiement
$montant = $desc['montant'];
$inserer_transaction = charger_fonction('inserer_transaction', 'bank');
$options_transaction = [
'id_auteur' => intval($commande['id_auteur']),
'champs' => [
'id_commande' => $id_commande,
],
];
if (isset($desc['montant_ht'])) {
$options_transaction['montant_ht'] = $desc['montant_ht'];
}
$id_transaction = intval($inserer_transaction($montant, $options_transaction));
$flux['data'] = $id_transaction;
}
}
}
}
return $flux;
}
/**
* Mettre en erreur une commande dont le prélèvement automatique aurait échoué
* on repere ce cas via le flag erreur=true envoyer lors de la resiliation
*
* @pipeline bank_abos_resilier
**/
function commandes_bank_abos_resilier($flux) {
// On commence par chercher la commande dont il s'agit
// et vérifier qu'elle a des échéances
if (
isset($flux['args']['erreur']) and $flux['args']['erreur']
and isset($flux['args']['id']) and $id = $flux['args']['id']
and strncmp($id, 'uid:', 4) == 0
and $bank_uid = substr($id, 4)
and $commande = sql_fetsel('*', 'spip_commandes', 'bank_uid = ' . sql_quote($bank_uid))
and $id_commande = intval($commande['id_commande'])
) {
include_spip('action/editer_objet');
// Le prélèvement a échoué explicitement, donc la commande d'origine est en erreur
objet_modifier('commande', $id_commande, ['statut' => 'erreur']);
}
return $flux;
}
/**
* Si le plugin Bank est activé, un changement de statut vers Payée redirige vers la page de paiement de la transaction
*
* @pipeline pre_edition
**/
function commandes_pre_edition($flux) {
if (
test_plugin_actif('bank')
and $flux['args']['table'] == 'spip_commandes'
and $flux['args']['action'] == 'instituer'
and !empty($flux['data']['statut'])
and $flux['data']['statut'] == 'paye'
) {
/*
$id_commande = $flux['args']['id_objet'];
$transaction = sql_fetsel('id_transaction, transaction_hash, statut', 'spip_transactions', 'id_commande='.intval($id_commande));
if (!is_null($transaction) AND $transaction['statut'] != 'ok') {
$arguments = "id_transaction=".$transaction['id_transaction']."&transaction_hash=".$transaction['transaction_hash'];
include_spip('inc/headers');
redirige_url_ecrire('payer' , $arguments);
}
*/
} elseif (
$flux['args']['table'] == 'spip_commandes_details'
and $flux['args']['action'] == 'modifier'
and isset($flux['data']['infos_extras'])
and !is_string($flux['data']['infos_extras'])
) {
// On assure que le champ s'enregistre bien en texte
$flux['data']['infos_extras'] = json_encode($flux['data']['infos_extras']);
}
return $flux;
}