Compare commits

...

13 Commits

Author SHA1 Message Date
Chl 0b08f125c9 readme: specify 'customer invoice'
Following the arrival of supplier invoice templates in Dolibarr 16, it's better
to specify than this module only manage customer invoices.

Adding the management of supplier invoice seems possible but I don't really see
a use case at the moment.
2024-03-13 18:54:01 +01:00
Chl a7532db483 Execute the hook only for customer invoices
With the introduction of supplier invoice templates in Dolibarr 16, with the
same hook but different table, this module tried to load the customer invoice
having the same id than the supplier invoice template being treated. This could
result in severe information disclosure.

Fixes gh-10
2024-03-13 18:29:27 +01:00
Chl d3bac76b2e CSRF-protect the form + update the version
Fix #8
2023-12-17 00:22:26 +01:00
Chl cdde859aea Correct the module's family
CRM -> Financial, with the invoice module.
2023-06-05 12:39:50 +02:00
Chl 704fd77e82 Little rewrite on why there is no dedicated scheduled job 2022-01-11 18:11:12 +01:00
Chl 97f6eb9ff1 a little chauvinism :) 2021-12-05 18:19:29 +01:00
Chl faa3ff6a02 Preparing 0.3.2 release 2021-12-05 02:09:37 +01:00
Chl 904554a0e1 Add a notice if the module cron is disabled 2021-12-05 02:09:37 +01:00
Chl 224e82f9fa Default choice for body format (auto/txt/html) in module's setup
Enhancement for issue #1
2021-12-05 02:04:18 +01:00
Chl faa9dcaa6c Allow sending emails even when the invoice is a draft 2021-12-05 02:04:18 +01:00
Chl 4c49334c31 optimization: Don't load the facture-rec twice 2021-12-05 02:04:18 +01:00
Chl 1e694ef51d [DB upgrade] Adding a field to select the mail's body format
Technical reminder about the DB upgrade :
There doesn't seem to be an easy and reusable way to give CMail both
parts of an text+html email, so we rework the database schema to have
a simple 'body' field with a 'body_ishtml' switch, following CMail
interface.

Enhancement from issue #1
2021-12-05 02:01:00 +01:00
Chl 0043e39f30 readme: more helpful download links + typos & format 2021-08-11 19:57:51 +02:00
10 changed files with 335 additions and 49 deletions

View File

@ -1,4 +1,25 @@
# CHANGELOG SENDRECURRINGINVOICEBYMAIL FOR <a href="https://www.dolibarr.org">DOLIBARR ERP CRM</a>
# CHANGELOG SENDRECURRINGINVOICEBYMAIL FOR [DOLIBARR ERP CRM](https://www.dolibarr.org)
## 0.3.4
Fix: the hook was also triggered by supplier invoices.
Thanks to jpardenoy for the report and the fix.
## 0.3.3
Fix: adds CSRF protection.
## 0.3.2
Note: This release includes a DB schema modification. Reactivate the module to trigger it.
Enhancements:
* Mails can now be sent in HTML (via global module configuration and via the customzation tab).
* Mails can now be sent even when the invoice is a draft.
## 0.3.1

View File

@ -2,9 +2,9 @@
## Features
(en) This module send the invoice generated with recurring invoices by email to the client.
(en) This module sends by email the customer invoice generated with a recurring invoice template via scheduled jobs.
(fr) Ce module envoie par mail les factures générées automatiquement par les travaux planifiés et les factures modèles.
(fr) Ce module envoie par mail les factures clientes générées automatiquement par les travaux planifiés et les factures modèles.
You can customize the mail globally or by recurring invoice.
@ -14,7 +14,7 @@ To edit the default global mail template, go to Home > Setup > Emails > Email te
To edit the default sender address, go to Home > Setup > Emails, and edit the `Sender email for automatic emails` field.
This module is triggered by the cron (Scheduled jobs module) and will not send emails when manually generating an invoice.
This module hooks himself on the end of the `Recurring invoices` job from the Scheduled jobs (aka. `cron`) module. It will only be triggered via this Scheduled job and will not send mail when manually generating an invoice from a recurring invoice template.
## Requirements
@ -30,11 +30,18 @@ Other modules are available on <a href="https://www.dolistore.com" target="_new"
### From the ZIP file and GUI interface
- If you get the module in a zip file (like when downloading it from the market place [Dolistore](https://www.dolistore.com)), go into
menu ```Home - Setup - Modules - Deploy external module``` and upload the zip file.
Go to `Home` > `Setup` > `Modules/Applications` and finally the `Deploy/install external app/module` tab
and upload the module_sendrecurringinvoicebymail-x.y.z.zip file (you can get it from the
[original forge](https://code.bugness.org/Dolibarr/sendrecurringinvoicebymail/releases)
or [Github](https://github.com/bugness-chl/sendrecurringinvoicebymail/releases)).
Next, on the `Modules/Applications` page, activate the newly available sendrecurringinvoicebymail module,
and probably the Scheduled jobs (alias cron or modCron) integrated module too.
Note: If this screen tell you there is no custom directory, check your setup is correct:
#### Troubleshooting
Note: If the module screen tells you there is no custom directory, check that your setup is correct:
- In your Dolibarr installation directory, edit the ```htdocs/conf/conf.php``` file and check that following lines are not commented:
@ -65,12 +72,10 @@ Note: If this screen tell you there is no custom directory, check your setup is
```sh
cd ....../custom
git clone git@github.com:bugness-chl/sendrecurringinvoicebymail.git sendrecurringinvoicebymail
git clone https://code.bugness.org/Dolibarr/sendrecurringinvoicebymail.git sendrecurringinvoicebymail
```
### Final steps
From your browser:
Then, from your browser:
- Log into Dolibarr as a super-administrator
- Go to "Setup" -> "Modules"
@ -94,7 +99,7 @@ GPLv3 or (at your option) any later version.
See file COPYING for more information.
#### Documentation
### Documentation
All texts and readmes.

181
admin/setup.php Normal file
View File

@ -0,0 +1,181 @@
<?php
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2021 Chl <chl-dev@bugness.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file sendrecurringinvoicebymail/admin/setup.php
* \ingroup sendrecurringinvoicebymail
* \brief SRIBM setup page.
*/
// Load Dolibarr environment
$res=0;
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1;
while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; }
if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include substr($tmp, 0, ($i+1))."/main.inc.php";
if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include dirname(substr($tmp, 0, ($i+1)))."/main.inc.php";
// Try main.inc.php using relative path
if (! $res && file_exists("../../main.inc.php")) $res=@include "../../main.inc.php";
if (! $res && file_exists("../../../main.inc.php")) $res=@include "../../../main.inc.php";
if (! $res) die("Include of main fails");
global $langs, $user;
// Libraries
require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php";
//require_once '../lib/mymodule.lib.php';
//require_once "../class/myclass.class.php";
// Translations
$langs->loadLangs(array("admin", "sendrecurringinvoicebymail@sendrecurringinvoicebymail"));
// Access control
if (! $user->admin) accessforbidden();
// Parameters
$action = GETPOST('action', 'alpha');
$backtopage = GETPOST('backtopage', 'alpha');
$arrayofparameters=array(
//'SENDRECURRINGINVOICEBYMAIL_MYPARAM2'=>array('css'=>'minwidth500','enabled'=>1)
'SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULT' => array(
'css' => 'minwidth200',
'selectvalues' => array(
-1 => 'MailBodyFormatAutoDetect',
0 => 'MailBodyFormatPlainText',
1 => 'MailBodyFormatHtml',
),
),
);
/*
* Actions
*/
if ((float) DOL_VERSION >= 6)
{
include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
}
/*
* View
*/
$page_name = "sendrecurringinvoicebymailSetup";
llxHeader('', $langs->trans($page_name));
// Subheader
$linkback = '<a href="'.($backtopage?$backtopage:DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1').'">'.$langs->trans("BackToModuleList").'</a>';
print load_fiche_titre($langs->trans($page_name), $linkback, 'object_mymodule@mymodule');
// Configuration header
//$head = mymoduleAdminPrepareHead();
$head = array();
dol_fiche_head($head, 'settings', '', -1, "sendrecurringinvoicebymail@sendrecurringinvoicebymail");
// Setup page goes here
echo '<span class="opacitymedium">'.$langs->trans("sendrecurringinvoicebymailSetupPage").'</span><br><br>';
if ($action == 'edit')
{
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="update">';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre"><td class="titlefield">'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>';
foreach($arrayofparameters as $key => $val)
{
print '<tr class="oddeven"><td>';
$tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : '');
print $form->textwithpicto($langs->trans($key), $tooltiphelp);
print "</td>\n";
print '<td>';
if (isset($val['selectvalues'])) {
// Select input
print '<select name="' . $key . '">';
foreach ($val['selectvalues'] as $k => $item) {
print '<option value="' . $k . '"';
if ($k == $conf->global->$key) {
print ' selected="selected"';
}
print '>' . $langs->trans($item) . "</option>\n";
}
print "</select>\n";
} else {
// Simple input
print '<input name="'.$key.'" class="flat '.(empty($val['css'])?'minwidth200':$val['css']).'" value="' . $conf->global->$key . '">';
}
print "</td></tr>\n";
}
print '</table>';
print '<br><div class="center">';
print '<input class="button" type="submit" value="'.$langs->trans("Save").'">';
print '</div>';
print '</form>';
print '<br>';
}
else
{
if (! empty($arrayofparameters))
{
print '<table class="noborder centpercent">';
print '<tr class="liste_titre"><td class="titlefield">'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>';
foreach($arrayofparameters as $key => $val)
{
print '<tr class="oddeven"><td>';
$tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : '');
print $form->textwithpicto($langs->trans($key), $tooltiphelp);
print '</td><td>' . $conf->global->$key . '</td></tr>';
}
print '</table>';
print '<div class="tabsAction">';
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit">'.$langs->trans("Modify").'</a>';
print '</div>';
}
else
{
print '<br>'.$langs->trans("NothingToSetup");
}
// Display a notice if the 'cron' module is not enabled
if (! in_array('cron', $conf->modules, true)) {
print '<div class="info"><p>' . $langs->trans('NoticeCronIsDisabled') . "</p></div>\n";
}
}
// Page end
dol_fiche_end();
llxFooter();
$db->close();

View File

@ -84,15 +84,23 @@ class Actionssendrecurringinvoicebymail
$error = 0; // Error counter
$facturerec = $parameters['facturerec'];
// Since Dolibarr 16, this hook is also used for the FactureFournisseurRec class.
if (! $facturerec instanceof FactureRec) {
return 0;
}
// Load our own object, linked to this facture
// (if it doesn't exist in database, fetch(,,true) will fill the object
// from the global mail template)
$mailObject = new SRIBMCustomMailInfo($this->db);
if ($mailObject->fetch(null, $facturerec->id, true) != 1) {
dol_syslog("Error loading SRIBMCustomMailInfo for facture rec " . (isset($facturerec->id) ? $facturerec->id : "(facturerec->id not set ??)"));
return -1;
}
// We only send the mail when the invoice is not a draft
// and the sending is enabled for the template.
if ($object->brouillon || !$mailObject->active) {
// Abort sending when inactive
// (draft invoice or explictly disabled)
if (!$mailObject->active) {
return 0;
}
@ -115,7 +123,8 @@ class Actionssendrecurringinvoicebymail
'errorsTo' => $conf->global->MAIN_MAIL_ERRORS_TO,
'replyTo' => $conf->global->MAIN_MAIL_ERRORS_TO,
'subject' => $mailObject->subject,
'message' => $mailObject->body_plaintext,
'message' => $mailObject->body,
'ishtml' => $mailObject->body_ishtml,
);
// Check that we have a recipient, to avoid some frequent error...
@ -154,7 +163,7 @@ class Actionssendrecurringinvoicebymail
$mail_data['cc'], // CC
$mail_data['bcc'], // BCC
0, //deliveryreceipt
0, //msgishtml
$mail_data['ishtml'], //msgishtml
$mail_data['errorsTo'],
'', // css
'', // trackid

View File

@ -109,12 +109,12 @@ class SRIBMCustomMailInfo extends CommonObject
/**
* @var string
*/
public $body_plaintext;
public $body;
/**
* @var string (not used at the moment)
* @var int 0: plain text, 1: html, -1: auto (see CMailFile and dol_ishtml())
*/
public $body_html;
public $body_ishtml = 0;
// End of database fields
@ -228,7 +228,7 @@ class SRIBMCustomMailInfo extends CommonObject
$sql .= " SET ";
$sql .= " fk_facture_rec = " . (int)$this->fk_facture_rec;
$sql .= ", active = " . (int)$this->active;
$sql .= ", addmaindocfile = '" . (int)$this->addmaindocfile . "'";
$sql .= ", addmaindocfile = " . (int)$this->addmaindocfile;
$sql .= ", fromtype = '" . $this->db->escape($this->fromtype) . "'";
$sql .= ", frommail = '" . $this->db->escape($this->frommail) . "'";
$sql .= ", sendto_thirdparty = " . (int)$this->db->escape($this->sendto_thirdparty);
@ -238,8 +238,8 @@ class SRIBMCustomMailInfo extends CommonObject
$sql .= ", sendbcc_thirdparty = " . (int)$this->db->escape($this->sendbcc_thirdparty);
$sql .= ", sendbcc_free = '" . $this->db->escape($this->sendbcc_free) . "'";
$sql .= ", subject = '" . $this->db->escape($this->subject) . "'";
$sql .= ", body_plaintext = '" . $this->db->escape($this->body_plaintext) . "'";
$sql .= ", body_html = '" . $this->db->escape($this->body_html) . "'";
$sql .= ", body = '" . $this->db->escape($this->body) . "'";
$sql .= ", body_ishtml = " . (int)$this->body_ishtml;
$sql .= " WHERE rowid = " . (int)$this->id;
$result = $this->db->query($sql);
@ -281,7 +281,7 @@ class SRIBMCustomMailInfo extends CommonObject
{
global $conf;
$sql = "SELECT rowid, fk_facture_rec, active, addmaindocfile, fromtype, frommail, sendto_thirdparty, sendto_free, sendcc_thirdparty, sendcc_free, sendbcc_thirdparty, sendbcc_free, subject, body_plaintext, body_html";
$sql = "SELECT rowid, fk_facture_rec, active, addmaindocfile, fromtype, frommail, sendto_thirdparty, sendto_free, sendcc_thirdparty, sendcc_free, sendbcc_thirdparty, sendbcc_free, subject, body, body_ishtml";
$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
$sql .= " WHERE " . (isset($ref) ? 'fk_facture_rec = ' . (int)$ref : "rowid = " . (int)$rowid);
@ -309,8 +309,8 @@ class SRIBMCustomMailInfo extends CommonObject
$this->sendbcc_thirdparty = $obj->sendbcc_thirdparty;
$this->sendbcc_free = $obj->sendbcc_free;
$this->subject = $obj->subject;
$this->body_plaintext = $obj->body_plaintext;
$this->body_html = $obj->body_html;
$this->body = $obj->body;
$this->body_ishtml = $obj->body_ishtml;
$ref = $obj->fk_facture_rec;
} elseif (!$fill_defaults_from_template) {
$this->error = "SRIBMCustomMailInfo not found (id: " . var_export($rowid, true) . ", ref: " . var_export($ref, true);
@ -366,8 +366,15 @@ class SRIBMCustomMailInfo extends CommonObject
}
$this->subject = $template->topic;
$this->body_plaintext = $template->content;
$this->body = $template->content;
$this->addmaindocfile = $template->joinfiles;
// By default, we don't send emails when the generated invoice is
// still a draft.
$this->active = $this->fac_rec_object->auto_validate;
// Retrieve the default body format from config.
$this->body_ishtml = $conf->global->SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULT;
}
return 1;

View File

@ -52,7 +52,7 @@ class modsendrecurringinvoicebymail extends DolibarrModules
// Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...'
// It is used to group modules by family in module setup page
$this->family = "crm";
$this->family = "financial";
// Module position in the family on 2 digits ('01', '10', '20', ...)
$this->module_position = '90';
// Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this)
@ -69,7 +69,7 @@ class modsendrecurringinvoicebymail extends DolibarrModules
$this->editor_url = 'https://code.bugness.org/Dolibarr/sendrecurringinvoicebymail';
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z'
$this->version = '0.3.1';
$this->version = '0.3.4';
//Url to the file with your last numberversion of this module
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
@ -103,7 +103,7 @@ class modsendrecurringinvoicebymail extends DolibarrModules
$this->dirs = array("/sendrecurringinvoicebymail/temp");
// Config pages. Put here list of php page, stored into sendrecurringinvoicebymail/admin directory, to use to setup module.
//$this->config_page_url = array("setup.php@sendrecurringinvoicebymail");
$this->config_page_url = array("setup.php@sendrecurringinvoicebymail");
// Dependencies
$this->hidden = false; // A condition to hide module
@ -124,6 +124,15 @@ class modsendrecurringinvoicebymail extends DolibarrModules
// 1=>array('SENDRECURRINGINVOICEBYMAIL_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1)
// );
$this->const = array(
0 => array(
'SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULT', // key
'chaine', // always 'chaine' ?
'0', // value
'default format for mail body : -1 for auto-detect, 0 for plain text, 1 for HTML.', // desc
1, // visible
'current', // current or allentities
0, // deleteonunactive
),
//1=>array('SENDRECURRINGINVOICEBYMAIL_MYCONSTANT', 'chaine', 'avalue', 'This is a constant to add', 1, 'allentities', 1)
);
@ -357,7 +366,7 @@ class modsendrecurringinvoicebymail extends DolibarrModules
$this->db->query("INSERT INTO " . MAIN_DB_PREFIX . "sribm_custom_mail_info (fk_facture_rec, fromtype, frommail) VALUES (" . (int)$row->rid . ", 'robot', '" . $this->db->escape($conf->global->MAIN_MAIL_EMAIL_FROM) . "')");
$sid = $this->db->last_insert_id(MAIN_DB_PREFIX . 'sribm_custom_mail_info');
}
foreach (array('subject' => 'subject', 'body' => 'body_plaintext', 'sendto' => 'sendto_free') as $key => $item) {
foreach (array('subject' => 'subject', 'body' => 'body', 'sendto' => 'sendto_free') as $key => $item) {
if (! empty($mail_data[$key])) {
// We loop on each field.
// Not optimized, I know.

View File

@ -56,18 +56,14 @@ do {
*/
// Load necessary data
$object = new FactureRec($db);
$mailObject = new SRIBMCustomMailInfo($db);
$form = new Form($db);
if ($object->fetch($id) <= 0 or !$object->id)
{
if ($mailObject->fetch(null, $id, true) <= 0) {
// Note : this should only happen when facture-rec doesn't exist or some database error.
// If sribmcustommailinfo doesn't exist in database, we should still get a instance of the template.
setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
break;
}
if ($mailObject->fetch(null, $object->id, true) <= 0) {
setEventMessages("Weird stuff, shouldn't happen : " . $mailObject->error);
break;
}
// List of senders (user, company, robot, ...)
$listFrom = array();
@ -92,7 +88,7 @@ do {
// Substitution array/string
$helpforsubstitution = $langs->trans('AvailableVariables').' :<br>'."\n";
$tmparray = getCommonSubstitutionArray($langs, 0, null, $object);
$tmparray = getCommonSubstitutionArray($langs, 0, null, $mailObject->fac_rec_object);
complete_substitutions_array($tmparray, $langs);
foreach($tmparray as $key => $val) {
$helpforsubstitution .= $key . ' -> ' . $langs->trans(dol_string_nohtmltag($val)) . '<br>';
@ -132,6 +128,10 @@ do {
setEventMessages("In some configuration, CMailFile doesn't allow empty subject. You should set one.", null, 'warnings');
//break;
}
if (! in_array(GETPOST('body_ishtml', 'int'), array('-1', '0', '1'), true)) {
setEventMessages("Unexpected body_ishtml value", null, 'errors');
break;
}
// Feed the input data to the model
$mailObject->active = GETPOST('active', 'int') ? 1 : 0;
@ -147,7 +147,8 @@ do {
$mailObject->sendcc_thirdparty = in_array('thirdparty', GETPOST('sendcc_socpeople', 'array'));
$mailObject->subject = GETPOST('subject', 'alpha');
$mailObject->body_plaintext = GETPOST('body_plaintext', 'alpha');
$mailObject->body = GETPOST('body', 'alpha');
$mailObject->body_ishtml = (int)GETPOST('body_ishtml', 'int');
// Save into database
if ($mailObject->id) {
@ -156,7 +157,7 @@ do {
break;
}
} else {
$mailObject->fk_facture_rec = $object->id;
$mailObject->fk_facture_rec = $mailObject->fac_rec_object->id;
if ($mailObject->create($user) < 0) {
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
break;
@ -225,7 +226,7 @@ do {
*/
// Same tabs than the main page
$head=invoice_rec_prepare_head($object);
$head=invoice_rec_prepare_head($mailObject->fac_rec_object);
$output .= dol_get_fiche_head($head, 'sendrecurringinvoicebymail', $langs->trans("RepeatableInvoice"), -1, 'bill'); // Add a div
$output .= '<div class="inline-block floatleft valignmiddle refid refidpadding">' . $mailObject->fac_rec_object->ref . "</div>\n";
$output .= '<div class="refidno">' . $langs->trans('ThirdParty') . ' : ' . $mailObject->fac_rec_object->thirdparty->getNomUrl(1) . "</div>\n";
@ -233,6 +234,12 @@ do {
$output .= '<div class="titre inline-block">' . $langs->trans("Options") . "</div>\n";
$output .= '<form id="sribmform" name="sribmform" method="POST" action="#sribmform">';
if (function_exists('newToken')) {
$output .= '<input type="hidden" name="token" value="'.newToken().'">'; // CSRF protection
} else {
// Used before Dolibar 13
$output .= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; // CSRF protection
}
$output .= '<table class="liste" summary="mail options"><tbody>';
$output .= '<tr class="oddeven">';
$output .= ' <td><label for="active">' . $langs->trans('OptionEnable') . "</label></td>\n";
@ -295,7 +302,7 @@ do {
$output .= '<td><input type="checkbox" name="addmaindocfile" value="1"' . ($tmp_addmaindocfile ? ' checked="checked"' : '') . ' /> ' . $langs->trans("JoinMainDoc") . "</td>\n";
// body_plaintext
// body
$output .= '<tr><td class="minwidth200" valign="top">';
$output .= $form->textwithpicto($langs->trans("MailText"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
$output .= "</td>\n<td>";
@ -306,11 +313,24 @@ do {
$doleditor = new DolEditor('body_plaintext', (GETPOST('body_plaintext', 'alpha') ? GETPOST('body_plaintext', 'alpha') : $mailObject->body_plaintext), '', 280);
$output .= $doleditor->Create(1);
*/
$output .= '<textarea id="body_plaintext" name="body_plaintext" rows="14" cols="80" class="flat">';
$output .= htmlentities(GETPOST('body_plaintext', 'alpha') ? GETPOST('body_plaintext', 'alpha') : $mailObject->body_plaintext);
$output .= '<textarea id="body" name="body" rows="14" cols="80" class="flat">';
$output .= htmlentities(GETPOST('body', 'alpha') ? GETPOST('body', 'alpha') : $mailObject->body);
$output .= "</textarea>\n";
$output .= "</td></tr>\n";
// body_ishtml
$output .= '<tr><td>' . $langs->trans('MailBodyFormat') . "</td>\n";
$tmp_ishtml = (int)(GETPOSTISSET('body_ishtml') ? GETPOST('body_ishtml', 'int') : $mailObject->body_ishtml);
// selectarray() does funny things with -1 key, so we build it manually.
//$output .= $form->selectarray('body_ishtml', $listBodyIsHtml, $mailObject->body_ishtml);
$output .= '<td><select name="body_ishtml">';
foreach (array(-1 => 'MailBodyFormatAutoDetect', 0 => 'MailBodyFormatPlainText', 1 => 'MailBodyFormatHtml') as $key => $item) {
$output .= '<option value="' . $key . '"';
$output .= ($key === $tmp_ishtml) ? ' selected="selected"' : '';
$output .= '>' . $langs->trans($item) . "</option>\n";
}
$output .= "</select>\n</td>\n";
$output .= "</table>\n";
$output .= '<br><div class="center">';

View File

@ -28,10 +28,9 @@ ModulesendrecurringinvoicebymailDesc = Send FactureRec generated invoices by mai
sendrecurringinvoicebymailSetup = sendrecurringinvoicebymail setup
Settings = Settings
sendrecurringinvoicebymailSetupPage = sendrecurringinvoicebymail setup page
SENDRECURRINGINVOICEBYMAIL_MYPARAM1 = My param 1
SENDRECURRINGINVOICEBYMAIL_MYPARAM1Tooltip = My param 1 tooltip
SENDRECURRINGINVOICEBYMAIL_MYPARAM2=My param 2
SENDRECURRINGINVOICEBYMAIL_MYPARAM2Tooltip=My param 2 tooltip
NoticeCronIsDisabled = Notice: the cron / Scheduled Jobs module seems disabled. Unless you know what you are doing, invoices won't be generated and emails won't be sent.
SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULT = Default mail body's format
SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULTTooltip = -1 for auto-detect, 0 for plaintext, 1 for HTML
#
@ -41,10 +40,16 @@ About = About
sendrecurringinvoicebymailAbout = About sendrecurringinvoicebymail
sendrecurringinvoicebymailAboutPage = sendrecurringinvoicebymail about page
#
# Tab title on the fiche-rec page
#
CustomizationTitle = Customization
CustomizationIntro = Below, you can override the global email template for this particular recurring invoice. To remove all customization, click on the %s button.
CustomizationLinkToGlobalTemplate = As a note, the global email template can be <a href="%s">configured here</a>, and the default sender address can be <a href="%s">configured there</a>.
MailBodyFormat = Message format
MailBodyFormatAutoDetect = Auto-detect
MailBodyFormatPlainText = Plain text
MailBodyFormatHtml = HTML
OptionEnable = Send mail when generating via cron (cf. module "Scheduled Jobs")
Reset = Reset
ResetDone = Reset done : customization deleted

View File

@ -28,6 +28,10 @@ ModulesendrecurringinvoicebymailDesc = Envoi par mail des factures générées p
sendrecurringinvoicebymailSetup = Configuration du module sendrecurringinvoicebymail
Settings = Réglages
sendrecurringinvoicebymailSetupPage = Page de configuration du module sendrecurringinvoicebymail
NoticeCronIsDisabled = Notice : le module cron / Travaux Planifiés semble désactivé. Sauf cas particulier, les factures ne seront pas générées et les mails ne seront pas envoyés.
SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULT = Format par défaut du corps du mail
SENDRECURRINGINVOICEBYMAIL_BODY_ISHTML_DEFAULTTooltip = -1: auto-détection, 0: texte pur, 1: HTML
#
# Page À propos
@ -42,6 +46,10 @@ sendrecurringinvoicebymailAboutPage = Page à propos de sendrecurringinvoicebyma
CustomizationTitle = Personnalisation
CustomizationIntro = Ci-dessous, vous pouvez personnaliser les emails pour cette facture-modèle. Pour annuler toute personnalisation, cliquez sur le bouton '%s'.
CustomizationLinkToGlobalTemplate = Pour mémoire, le template global est <a href="%s">configurable par ici</a>, et l'adresse de l'émetteur par défaut est <a href="%s">configurable par là</a>.
MailBodyFormat = Format du message
MailBodyFormatAutoDetect = Auto-detect
MailBodyFormatPlainText = Texte pur
MailBodyFormatHtml = HTML
OptionEnable = Envoyer par email lors d'une génération automatique via le module "Travaux planifiés"
Reset = Réinitialiser
ResetDone = Réinitialisation effectuée : personnalisation supprimée.

View File

@ -0,0 +1,21 @@
-- Copyright (C) 2021 Chl <chl-dev@bugness.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see http://www.gnu.org/licenses/.
-- We designed the schema too quickly : CMailFile doesn't let us manage
-- independently the text and html parts. All we can do is set the mode.
ALTER TABLE llx_sribm_custom_mail_info CHANGE COLUMN body_plaintext body mediumtext;
ALTER TABLE llx_sribm_custom_mail_info DROP COLUMN body_html;
ALTER TABLE llx_sribm_custom_mail_info ADD COLUMN body_ishtml smallint DEFAULT 0 NOT NULL;