Relance Devis
Objectifs
Intégration d’une colonne « Relancer » dans le tableau d’administration des devis, comprenant un bouton permettant l’envoi d’un email de rappel.
Intégration d’une colonne « Dernière relance » pour présenter la date de la dernière action de relance, sans modification de la structure de la base de données.
Envoi d’un email incluant le PDF du devis en pièce jointe, avec possibilité d’ajouter un destinataire en copie cachée (BCC).
Stockage des dates de relance dans un fichier JSON plutôt que dans la base de données.
Structure du Code
L’essentiel des modifications se situe dans le contrôleur d’administration AdminOpartdevisController.php
. Ce contrôleur gère l’affichage du tableau des devis, les actions sur chaque ligne (validation, envoi d’email, etc.) et peut être étendu pour intégrer le bouton « Relancer » ainsi que la date de dernière relance.
Champs supplémentaires dans $fields_list
$fields_list
Le tableau $fields_list
permet de définir les colonnes affichées dans la liste des devis. Deux nouvelles colonnes sont ajoutées :
send_reminder
: Colonne pour afficher le bouton de relance.last_reminder_date
: Colonne pour afficher la date de dernière relance.
Exemple de configuration dans la méthode __construct()
du contrôleur :
$this->fields_list = array(
'id_opartdevis' => array(
'title' => $this->l('ID'),
'align' => 'center'
),
'name' => array(
'title' => $this->l('Name')
),
// ... autres colonnes existantes ...
'send_reminder' => array(
'title' => $this->l('Relancer'),
'align' => 'text-center',
'callback' => 'displayReminderButton',
'callback_object' => $this,
'orderby' => false,
'search' => false,
'raw' => true,
'remove_onclick' => true
),
'last_reminder_date' => array(
'title' => $this->l('Dernière relance'),
'callback' => 'displayLastReminderDate',
'callback_object' => $this,
'orderby' => false,
'search' => false,
'raw' => true,
'remove_onclick' => true
),
);
Ces colonnes s’affichent grâce à des callbacks (displayReminderButton()
et displayLastReminderDate()
), ce qui nécessite de fournir des données factices dans la requête SQL.
Données factices dans la requête SQL
Pour permettre l’appel aux callbacks, des colonnes vides sont ajoutées dans la requête SQL via la propriété $this->_select
:
$this->_select = '
a.id_opartdevis AS id_quotation,
a.date_add,
a.id_cart AS company_name,
CONCAT(LEFT(c.firstname, 1), ". ", c.lastname) AS customer,
c.email,
IF(a.id_order > 0, 1, 0) AS ordered,
\'\' AS send_reminder,
\'\' AS last_reminder_date
';
L’utilisation de \'\'
permet de fournir une chaîne vide. Ainsi, Prestashop reconnaît une colonne existante pour ces champs et appelle correctement les callbacks associées.
Callbacks pour l’affichage
Deux fonctions sont ajoutées en bas du contrôleur :
displayReminderButton($value, $row)
: Retourne du code HTML pour afficher un bouton cliquable. Ce bouton déclenche une action sendreminder
dans le contrôleur.
Exemple :
public function displayReminderButton($value, $row)
{
$id_opartdevis = (int)$row['id_opartdevis'];
$link = 'index.php?controller=AdminOpartdevis&token=' . $this->token . '&id_opartdevis=' . $id_opartdevis . '&sendreminder=1';
return '<a class="btn btn-default" href="' . $link . '">
<i class="icon-envelope"></i> ' . $this->l('Relancer') . '
</a>';
}
displayLastReminderDate($value, $row)
: Affiche la date de dernière relance lue depuis un fichier JSON.
Exemple :
public function displayLastReminderDate($value, $row)
{
$id_opartdevis = (int)$row['id_opartdevis'];
$data = $this->getRemindersData();
if (isset($data[$id_opartdevis])) {
return $data[$id_opartdevis];
}
return $this->l('Aucune relance');
}
Stockage des dates de relance dans un fichier JSON
Un répertoire data
est créé dans le module, contenant un fichier last_reminders.json
initialement vide : {}
. Des méthodes utilitaires assurent la lecture et l’écriture dans ce fichier :
private function getRemindersData()
{
$file = _PS_MODULE_DIR_.'opartdevis/data/last_reminders.json';
if (!file_exists($file)) {
@mkdir(_PS_MODULE_DIR_.'opartdevis/data/', 0755, true);
file_put_contents($file, '{}');
}
$jsonData = file_get_contents($file);
return json_decode($jsonData, true);
}
private function saveRemindersData($data)
{
$file = _PS_MODULE_DIR_.'opartdevis/data/last_reminders.json';
file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT));
}
Action sendreminder
sendreminder
Une action sendreminder
est ajoutée dans postProcess()
:
if (Tools::getValue('sendreminder')) {
$this->processSendreminder();
return;
}
La méthode processSendreminder()
gère :
Le chargement de la quotation et du client.
La récupération de l’email et du PDF.
L’envoi du mail avec pièce jointe.
La mise à jour du JSON avec la date actuelle.
public function processSendreminder()
{
$id_opartdevis = (int)Tools::getValue('id_opartdevis');
if (!$id_opartdevis) {
$this->errors[] = $this->l('Invalid quote ID.');
return;
}
$quotation = new OpartQuotation($id_opartdevis);
if (!Validate::isLoadedObject($quotation)) {
$this->errors[] = $this->l('Could not load quote.');
return;
}
$customer = new Customer($quotation->id_customer);
if (!Validate::isLoadedObject($customer) || empty($customer->email)) {
$this->errors[] = $this->l('No valid customer associated with this quote.');
return;
}
$customer_email = $customer->email;
$customer_name = trim($customer->firstname.' '.$customer->lastname);
$pdfContent = $quotation->renderPdf(false);
$file_attachment = array(
'content' => $pdfContent,
'name' => 'devis_'.$id_opartdevis.'.pdf',
'mime' => 'application/pdf'
);
$templateVars = array(
'{customer_name}' => $customer_name,
'{quote_reference}' => $quotation->name
);
$id_lang = (int)$this->context->language->id;
$subject = $this->l('Rappel de votre devis');
$template = 'reminder_quote';
$path = _PS_MODULE_DIR_.$this->name.'/mails/';
$sent = Mail::Send(
$id_lang,
$template,
$subject,
$templateVars,
$customer_email,
$customer_name,
null,
null,
$file_attachment,
null,
$path,
false,
$this->context->shop->id,
'contact@lacier.fr' // adresse BCC optionnelle
);
if ($sent) {
$data = $this->getRemindersData();
$data[$id_opartdevis] = date('Y-m-d H:i:s');
$this->saveRemindersData($data);
Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&conf=3');
} else {
$this->errors[] = $this->l('Failed to send the reminder email.');
}
}
Templates d’email
Les templates sont placés dans modules/opartdevis/mails/fr/
. Le fichier .html
correspond au message formaté en HTML, et le .txt
fournit une alternative texte.
Exemple du fichier reminder_quote.txt
:
Bonjour {customer_name},
Merci pour votre création de devis. Le devis peut être validé en ligne depuis le compte client.
Pour cela, accéder à la page : https://signaletique-inox.fr/mon-compte
Puis sélectionner « Mes devis » et « Transformer mon devis en commande ».
N’hésitez pas à contacter le support en cas de questions : 06-45-57-82-16
Cordialement,
Gilles Hossepied
Gérant
...
Ajout d’un BCC
L’ajout d’une adresse email en copie cachée (BCC) s’effectue en fournissant l’adresse dans le paramètre $bcc
de Mail::Send()
:
$sent = Mail::Send(
$id_lang,
$template,
$subject,
$templateVars,
$customer_email,
$customer_name,
null,
null,
$file_attachment,
null,
$path,
false,
$this->context->shop->id,
'contact@lacier.fr'
);
Last updated