v. 0.3.0 : customization form for each recurring invoice
This commit is contained in:
parent
3f14164994
commit
b5bc4bca93
12 changed files with 1470 additions and 524 deletions
|
@ -1,5 +1,8 @@
|
||||||
# CHANGELOG SENDRECURRINGINVOICEBYMAIL FOR <a href="https://www.dolibarr.org">DOLIBARR ERP CRM</a>
|
# CHANGELOG SENDRECURRINGINVOICEBYMAIL FOR <a href="https://www.dolibarr.org">DOLIBARR ERP CRM</a>
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
Dedicated tab on the template invoice's page, to be able to customize more cleanly the recipients, and the email content.
|
||||||
|
|
||||||
## 0.2.7
|
## 0.2.7
|
||||||
Add the possibility to overwrite some email fields (recipients, subject, body) for each template.
|
Add the possibility to overwrite some email fields (recipients, subject, body) for each template.
|
||||||
|
|
||||||
|
|
61
README.md
61
README.md
|
@ -2,62 +2,31 @@
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
This module send the PDF generated with recurring invoices by email to the client.
|
(en) This module send the invoice generated with recurring invoices by email to the client.
|
||||||
|
|
||||||
You can customize the mail template in Home > Setup > Emails > Email templates.
|
(fr) Ce module envoie par mail les factures générées automatiquement par les travaux planifiés et les factures modèles.
|
||||||
|
|
||||||
Beta - test in progress : you can also customize for each template invoice, by adding some of those blocks in the private notes of the template.
|
You can customize the mail globally or by recurring invoice.
|
||||||
```
|
|
||||||
This is a good client (this is outside of the %%% blocks so it won't appear in the mails :)
|
|
||||||
|
|
||||||
%%% sendrecurringinvoicebymail::body
|
![Screenshot n° 1](img/screenshot1.png?raw=true)
|
||||||
Hello dear client,
|
|
||||||
|
|
||||||
Please find attached... invoice __REF__...
|
To edit the default global mail template, go to Home > Setup > Emails > Email templates, and modify the `SendRecurringInvoiceByMail : original template`. If you don't want to attach the PDF of the invoice to the mails, set the `Attach file` input to 0 (default: 1, PDF attached).
|
||||||
|
|
||||||
__(Sincerely)__,
|
To edit the default sender address, go to Home > Setup > Emails, and edit the `Sender email for automatic emails` field.
|
||||||
|
|
||||||
__MYCOMPANY_NAME__
|
This module is triggered by the cron (Scheduled jobs module) and will not send emails when manually generating an invoice.
|
||||||
%%%
|
|
||||||
|
|
||||||
%%% sendrecurringinvoicebymail::subject
|
|
||||||
My custom subject
|
|
||||||
%%%
|
|
||||||
%%% sendrecurringinvoicebymail::sendto
|
|
||||||
test1@example.org, "Mr. Test2" <test2@example.com>
|
|
||||||
%%%
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
It requires Dolibarr version 10.0 at least (first version with the 'cron/afterCreationOfRecurringInvoice()' hook).
|
It requires Dolibarr version 10.0 at least (first version with the `cron/afterCreationOfRecurringInvoice()` hook).
|
||||||
|
|
||||||
<!--
|
Don't forget to also activate the **Scheduled jobs** module.
|
||||||
![Screenshot sendrecurringinvoicebymail](img/screenshot_sendrecurringinvoicebymail.png?raw=true "sendrecurringinvoicebymail"){imgmd}
|
|
||||||
-->
|
|
||||||
|
|
||||||
Other modules are available on <a href="https://www.dolistore.com" target="_new">Dolistore.com</a>.
|
Other modules are available on <a href="https://www.dolistore.com" target="_new">Dolistore.com</a>.
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
<!--
|
|
||||||
### Translations
|
|
||||||
|
|
||||||
Translations can be define manually by editing files into directories *langs*.
|
|
||||||
|
|
||||||
This module contains also a sample configuration for Transifex, under the hidden directory [.tx](.tx), so it is possible to manage translation using this service.
|
|
||||||
|
|
||||||
For more informations, see the [translator's documentation](https://wiki.dolibarr.org/index.php/Translator_documentation).
|
|
||||||
|
|
||||||
There is a [Transifex project](https://transifex.com/projects/p/dolibarr-module-template) for this module.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Install
|
|
||||||
-------
|
|
||||||
|
|
||||||
### From the ZIP file and GUI interface
|
### From the ZIP file and GUI interface
|
||||||
|
|
||||||
|
@ -99,7 +68,7 @@ cd ....../custom
|
||||||
git clone git@github.com:bugness-chl/sendrecurringinvoicebymail.git sendrecurringinvoicebymail
|
git clone git@github.com:bugness-chl/sendrecurringinvoicebymail.git sendrecurringinvoicebymail
|
||||||
```
|
```
|
||||||
|
|
||||||
### <a name="final_steps"></a>Final steps
|
### Final steps
|
||||||
|
|
||||||
From your browser:
|
From your browser:
|
||||||
|
|
||||||
|
@ -108,12 +77,14 @@ From your browser:
|
||||||
- You should now be able to find and enable the module
|
- You should now be able to find and enable the module
|
||||||
|
|
||||||
|
|
||||||
|
## Updating instructions
|
||||||
|
|
||||||
-->
|
* Disable the module,
|
||||||
|
* Update the files (see Install),
|
||||||
|
* Re-enable the module.
|
||||||
|
|
||||||
|
|
||||||
Licenses
|
## Licenses
|
||||||
--------
|
|
||||||
|
|
||||||
### Main code
|
### Main code
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
* Put detailed description here.
|
* Put detailed description here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Load needed classes/lib
|
||||||
|
require_once 'sribmcustommailinfo.class.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Actionssendrecurringinvoicebymail
|
* Class Actionssendrecurringinvoicebymail
|
||||||
*/
|
*/
|
||||||
|
@ -81,23 +84,19 @@ class Actionssendrecurringinvoicebymail
|
||||||
$error = 0; // Error counter
|
$error = 0; // Error counter
|
||||||
|
|
||||||
$facturerec = $parameters['facturerec'];
|
$facturerec = $parameters['facturerec'];
|
||||||
|
$mailObject = new SRIBMCustomMailInfo($this->db);
|
||||||
// We only send the mail when the invoice is not a draft
|
if ($mailObject->fetch(null, $facturerec->id, true) != 1) {
|
||||||
if ($object->brouillon) {
|
dol_syslog("Error loading SRIBMCustomMailInfo for facture rec " . (isset($facturerec->id) ? $facturerec->id : "(facturerec->id not set ??)"));
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the mail template
|
|
||||||
// (pas très précise mais je commence à en avoir marre de creuser tout dolibarr pour trouver les bonnes fonctions...)
|
|
||||||
$result = $this->db->query("SELECT * FROM " . MAIN_DB_PREFIX . "c_email_templates WHERE module = 'sendrecurringinvoicebymail' AND active = 1 AND enabled = '1' ORDER BY tms DESC LIMIT 1");
|
|
||||||
if ( ! $result or ! ($template = $this->db->fetch_object($result))) {
|
|
||||||
$this->error = "Can't find mail template for sendrecurringinvoicebymail";
|
|
||||||
$this->errors[] = $this->error;
|
|
||||||
$error++;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the substitions for mail's subject and body
|
// 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) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the substitions for mail's subject and message (ex-body)
|
||||||
$substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object);
|
$substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object);
|
||||||
complete_substitutions_array($substitutionarray, $langs, $object); // lourd et n'a rien ajouté lors de mes tests
|
complete_substitutions_array($substitutionarray, $langs, $object); // lourd et n'a rien ajouté lors de mes tests
|
||||||
|
|
||||||
|
@ -109,25 +108,24 @@ class Actionssendrecurringinvoicebymail
|
||||||
|
|
||||||
// Initialisations
|
// Initialisations
|
||||||
$mail_data = array(
|
$mail_data = array(
|
||||||
'sendto' => $object->thirdparty->name . ' <' . $object->thirdparty->email . '>',
|
'from' => $mailObject->frommail,
|
||||||
'from' => $conf->global->MAIN_MAIL_EMAIL_FROM,
|
'to' => implode(', ', $mailObject->compileEmails('to', true)),
|
||||||
|
'cc' => implode(', ', $mailObject->compileEmails('cc', true)),
|
||||||
|
'bcc' => implode(', ', $mailObject->compileEmails('bcc', true)),
|
||||||
'errorsTo' => $conf->global->MAIN_MAIL_ERRORS_TO,
|
'errorsTo' => $conf->global->MAIN_MAIL_ERRORS_TO,
|
||||||
'replyTo' => $conf->global->MAIN_MAIL_ERRORS_TO,
|
'replyTo' => $conf->global->MAIN_MAIL_ERRORS_TO,
|
||||||
'subject' => $template->topic,
|
'subject' => $mailObject->subject,
|
||||||
'body' => $template->content,
|
'message' => $mailObject->body_plaintext,
|
||||||
);
|
);
|
||||||
|
|
||||||
// If the invoice has some custom parameters (subject, body, sendto, ...)
|
|
||||||
$mail_data = array_merge($mail_data, $this->getCustomFieldsMail($object));
|
|
||||||
|
|
||||||
// Check that we have a recipient, to avoid some frequent error...
|
// Check that we have a recipient, to avoid some frequent error...
|
||||||
if (empty($mail_data['sendto'])) {
|
if (empty($mail_data['to'] . $mail_data['cc'] . $mail_data['bcc'])) {
|
||||||
dol_syslog("Empty recipient for thirdparty " . $object->thirdparty->id . ". Not sending facturerec " . $facturerec->ref . " (id:" . $facturerec->id . ").");
|
dol_syslog("Empty recipient for thirdparty " . $object->thirdparty->id . ". Not sending facturerec " . $facturerec->ref . " (id:" . $facturerec->id . ").");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the substitutions
|
// Make the substitutions
|
||||||
foreach (array('subject', 'body') as $key) {
|
foreach (array('subject', 'message') as $key) {
|
||||||
$mail_data[$key] = make_substitutions($mail_data[$key], $substitutionarray, $langs);
|
$mail_data[$key] = make_substitutions($mail_data[$key], $substitutionarray, $langs);
|
||||||
if (method_exists($object, 'makeSubstitution')) {
|
if (method_exists($object, 'makeSubstitution')) {
|
||||||
$mail_data[$key] = $object->makeSubstitution($mail_data[$key]);
|
$mail_data[$key] = $object->makeSubstitution($mail_data[$key]);
|
||||||
|
@ -138,7 +136,7 @@ class Actionssendrecurringinvoicebymail
|
||||||
$filePath = array();
|
$filePath = array();
|
||||||
$fileMime = array();
|
$fileMime = array();
|
||||||
$fileName = array();
|
$fileName = array();
|
||||||
if ($template->joinfiles) {
|
if ($mailObject->addmaindocfile) {
|
||||||
$filePath = array(DOL_DATA_ROOT . '/' . $object->last_main_doc);
|
$filePath = array(DOL_DATA_ROOT . '/' . $object->last_main_doc);
|
||||||
$fileMime = array('application/pdf'); // FIXME: à rendre dynamique, même si ce sera toujours du PDF ?
|
$fileMime = array('application/pdf'); // FIXME: à rendre dynamique, même si ce sera toujours du PDF ?
|
||||||
$fileName = array(basename($object->last_main_doc));
|
$fileName = array(basename($object->last_main_doc));
|
||||||
|
@ -147,14 +145,14 @@ class Actionssendrecurringinvoicebymail
|
||||||
// At last, send the mail
|
// At last, send the mail
|
||||||
$mailfile = new CMailFile(
|
$mailfile = new CMailFile(
|
||||||
$mail_data['subject'],
|
$mail_data['subject'],
|
||||||
$mail_data['sendto'],
|
$mail_data['to'],
|
||||||
$mail_data['from'],
|
$mail_data['from'],
|
||||||
$mail_data['body'],
|
$mail_data['message'],
|
||||||
$filePath,
|
$filePath,
|
||||||
$fileMime,
|
$fileMime,
|
||||||
$fileName,
|
$fileName,
|
||||||
'', // CC
|
$mail_data['cc'], // CC
|
||||||
'', // BCC
|
$mail_data['bcc'], // BCC
|
||||||
0, //deliveryreceipt
|
0, //deliveryreceipt
|
||||||
0, //msgishtml
|
0, //msgishtml
|
||||||
$mail_data['errorsTo'],
|
$mail_data['errorsTo'],
|
||||||
|
@ -172,16 +170,16 @@ class Actionssendrecurringinvoicebymail
|
||||||
$object->email_msgid = $mailfile->msgid;
|
$object->email_msgid = $mailfile->msgid;
|
||||||
$object->email_from = $mail_data['from'];
|
$object->email_from = $mail_data['from'];
|
||||||
$object->email_subject = $mail_data['subject'];
|
$object->email_subject = $mail_data['subject'];
|
||||||
$object->email_to = $mail_data['sendto'];
|
$object->email_to = $mail_data['to'];
|
||||||
//$object->email_tocc = $sendtocc;
|
$object->email_tocc = $mail_data['cc'];
|
||||||
//$object->email_tobcc = $sendtobcc;
|
$object->email_tobcc = $mail_data['bcc'];
|
||||||
$object->actiontypecode = 'AC_OTH_AUTO';
|
$object->actiontypecode = 'AC_OTH_AUTO';
|
||||||
$object->actionmsg2=$langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($mail_data['from'],4,0,1).' '.$langs->transnoentities('To').' '.CMailFile::getValidAddress($mail_data['sendto'],4,0,1);
|
$object->actionmsg2=$langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($mail_data['from'],4,0,1).' '.$langs->transnoentities('To').' '.CMailFile::getValidAddress($mail_data['to'],4,0,1);
|
||||||
$object->actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($mail_data['from']);
|
$object->actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($mail_data['from']);
|
||||||
$object->actionmsg = dol_concatdesc($object->actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($mail_data['sendto']));
|
$object->actionmsg = dol_concatdesc($object->actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($mail_data['to']));
|
||||||
$object->actionmsg = dol_concatdesc($object->actionmsg, $langs->transnoentities('MailTopic') . ": " . $mail_data['subject']);
|
$object->actionmsg = dol_concatdesc($object->actionmsg, $langs->transnoentities('MailTopic') . ": " . $mail_data['subject']);
|
||||||
$object->actionmsg = dol_concatdesc($object->actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
|
$object->actionmsg = dol_concatdesc($object->actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
|
||||||
$object->actionmsg = dol_concatdesc($object->actionmsg, $mail_data['body']);
|
$object->actionmsg = dol_concatdesc($object->actionmsg, $mail_data['message']);
|
||||||
|
|
||||||
// Launch triggers
|
// Launch triggers
|
||||||
$interface = new Interfaces($this->db);
|
$interface = new Interfaces($this->db);
|
||||||
|
@ -195,52 +193,4 @@ class Actionssendrecurringinvoicebymail
|
||||||
|
|
||||||
return ($error ? -1 : 0);
|
return ($error ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME: For the time being, we abuse of note_private to store our customizations
|
|
||||||
*/
|
|
||||||
public function getCustomFieldsMail($object)
|
|
||||||
{
|
|
||||||
return $this->parseCustomFieldsMail($object->note_private);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME: For the time being, we abuse of note_private to store our customizations
|
|
||||||
*
|
|
||||||
* This expect something like this in note_private:
|
|
||||||
* This is a good client... (other private infos)
|
|
||||||
* %%% sendrecurringinvoicebymail::subject
|
|
||||||
* New invoice __REF__
|
|
||||||
* %%%
|
|
||||||
* %%% sendrecurringinvoicebymail::sendto
|
|
||||||
* recipient1@example.org, recipient2@example.org
|
|
||||||
* %%%
|
|
||||||
* %%% sendrecurringinvoicebymail::body
|
|
||||||
* Hello dear client,
|
|
||||||
* Please find attached...
|
|
||||||
* %%%
|
|
||||||
*/
|
|
||||||
public function parseCustomFieldsMail($data)
|
|
||||||
{
|
|
||||||
$output = [];
|
|
||||||
|
|
||||||
// Remove eventual windows' "\r"
|
|
||||||
$data = str_replace("\r", "", $data);
|
|
||||||
|
|
||||||
$regexps = array(
|
|
||||||
'subject' => '/(^|\n)%%% sendrecurringinvoicebymail::subject\n(?<subject>.*)%%%(\n|$)/sU',
|
|
||||||
'body' => '/(^|\n)%%% sendrecurringinvoicebymail::body\n(?<body>.*)%%%(\n|$)/sU',
|
|
||||||
'sendto' => '/(^|\n)%%% sendrecurringinvoicebymail::sendto\n(?<sendto>.*)%%%(\n|$)/sU',
|
|
||||||
);
|
|
||||||
foreach ($regexps as $key => $r) {
|
|
||||||
$result_regexp = [];
|
|
||||||
if (preg_match_all($r, $data, $result_regexp)) {
|
|
||||||
$output[$key] = trim($result_regexp[$key][0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
516
class/sribmcustommailinfo.class.php
Normal file
516
class/sribmcustommailinfo.class.php
Normal file
|
@ -0,0 +1,516 @@
|
||||||
|
<?php
|
||||||
|
/* Cpoyright (C) 2021 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 class/sribmcustommailinfo.class.php
|
||||||
|
* \brief File of class for objects storing custom mail informations (module SRIBM : SendRecurringInvoiceByMail)
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
|
||||||
|
require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture-rec.class.php';
|
||||||
|
require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for objects storing custom mail informations.
|
||||||
|
*
|
||||||
|
* Part of module SRIBM : SendRecurringInvoiceByMail
|
||||||
|
*/
|
||||||
|
class SRIBMCustomMailInfo extends CommonObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string Id to identify managed objects
|
||||||
|
*/
|
||||||
|
public $element = 'sribmcustommailinfo';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Name of table without prefix where object is stored
|
||||||
|
*/
|
||||||
|
public $table_element = 'sribm_custom_mail_info';
|
||||||
|
|
||||||
|
// Database fields
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $fk_facture_rec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $active = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $addmaindocfile = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Type of sender, could be 'robot', 'user' or 'company',
|
||||||
|
* usually meaning the mail sender is determined by the
|
||||||
|
* PHP/Dolibarr config (cf. admin/mails.php?mainmenu=home ),
|
||||||
|
* this object's creator email or the company email.
|
||||||
|
*/
|
||||||
|
public $fromtype = 'robot';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $frommail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 1: Send to societe main's email, 0: don't.
|
||||||
|
*/
|
||||||
|
public $sendto_thirdparty = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Format expected: "Foo <foo@example.com>, bar@example.net"
|
||||||
|
*/
|
||||||
|
public $sendto_free;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 1: Send to societe main's email, 0: don't.
|
||||||
|
*/
|
||||||
|
public $sendcc_thirdparty = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Format expected: "Foo <foo@example.com>, bar@example.net"
|
||||||
|
*/
|
||||||
|
public $sendcc_free;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int 1: Send to societe main's email, 0: don't.
|
||||||
|
*/
|
||||||
|
public $sendbcc_thirdparty = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Format expected: "Foo <foo@example.com>, bar@example.net"
|
||||||
|
*/
|
||||||
|
public $sendbcc_free;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $body_plaintext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string (not used at the moment)
|
||||||
|
*/
|
||||||
|
public $body_html;
|
||||||
|
|
||||||
|
// End of database fields
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FactureRec object linked to this object
|
||||||
|
*
|
||||||
|
* Note : the class Facture use $fac_rec and fk_fac_rec_source which both
|
||||||
|
* seem to be integer (I don't really see the distinction), so we suffix
|
||||||
|
* with '_object' to avoid future conflict.
|
||||||
|
*
|
||||||
|
* @var FactureRec
|
||||||
|
*/
|
||||||
|
public $fac_rec_object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array SocPeoples linked via table llx_sribm_custom_mail_info_socpeople (FIXME: describe format)
|
||||||
|
*/
|
||||||
|
public $linkToSocPeoples = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param DoliDb $db Database handler
|
||||||
|
*/
|
||||||
|
public function __construct(DoliDB $db)
|
||||||
|
{
|
||||||
|
global $conf;
|
||||||
|
|
||||||
|
$this->db = $db;
|
||||||
|
|
||||||
|
// Fill default values
|
||||||
|
$this->frommail = $conf->global->MAIN_MAIL_EMAIL_FROM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create object into database
|
||||||
|
*
|
||||||
|
* Since only one mail can exist for each invoice template, this method
|
||||||
|
* only insert a row with the id of the template and delegate all the work
|
||||||
|
* on the rest of the data to the update() method.
|
||||||
|
*
|
||||||
|
* @param User $user User that creates (at the moment, we don't use it)
|
||||||
|
* @param int $notrigger 1=do not execute triggers, 0 otherwise
|
||||||
|
* @return int >0 if OK, < 0 if KO
|
||||||
|
*/
|
||||||
|
public function create(User $user, $notrigger = 0)
|
||||||
|
{
|
||||||
|
$error=0;
|
||||||
|
|
||||||
|
$this->db->begin();
|
||||||
|
|
||||||
|
$sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element;
|
||||||
|
$sql .= " (fk_facture_rec, fromtype, frommail)";
|
||||||
|
$sql .= sprintf(
|
||||||
|
" VALUES (%d, '%s', '%s')",
|
||||||
|
(int)$this->fk_facture_rec,
|
||||||
|
$this->db->escape($this->fromtype),
|
||||||
|
$this->db->escape($this->frommail)
|
||||||
|
);
|
||||||
|
|
||||||
|
dol_syslog("SRIBMCustomMailInfo::create", LOG_DEBUG);
|
||||||
|
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if ($result) {
|
||||||
|
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
|
||||||
|
$result = $this->update($user, 1);
|
||||||
|
if ($result < 0) {
|
||||||
|
$this->db->rollback();
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $notrigger)
|
||||||
|
{
|
||||||
|
// Call trigger
|
||||||
|
$result=$this->call_trigger('SRIBM_CUSTOM_MAIL_INFO_CREATE', $user);
|
||||||
|
if ($result < 0) {
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
// End call triggers
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR);
|
||||||
|
$this->db->rollback();
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
$this->db->rollback();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->commit();
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update object in database
|
||||||
|
*
|
||||||
|
* @param User $user User that creates (at the moment, we don't use it)
|
||||||
|
* @param int $notrigger 1=do not execute triggers, 0 otherwise
|
||||||
|
* @return int >0 if OK, < 0 if KO
|
||||||
|
*/
|
||||||
|
public function update(User $user, $notrigger = 0)
|
||||||
|
{
|
||||||
|
$error=0;
|
||||||
|
|
||||||
|
//$this->db->begin();
|
||||||
|
|
||||||
|
$sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
|
||||||
|
$sql .= " SET ";
|
||||||
|
$sql .= " fk_facture_rec = " . (int)$this->fk_facture_rec;
|
||||||
|
$sql .= ", active = " . (int)$this->active;
|
||||||
|
$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);
|
||||||
|
$sql .= ", sendto_free = '" . $this->db->escape($this->sendto_free) . "'";
|
||||||
|
$sql .= ", sendcc_thirdparty = " . (int)$this->db->escape($this->sendcc_thirdparty);
|
||||||
|
$sql .= ", sendcc_free = '" . $this->db->escape($this->sendcc_free) . "'";
|
||||||
|
$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 .= " WHERE rowid = " . (int)$this->id;
|
||||||
|
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if ($result) {
|
||||||
|
if (! $notrigger)
|
||||||
|
{
|
||||||
|
// Call trigger
|
||||||
|
$result=$this->call_trigger('SRIBM_CUSTOM_MAIL_INFO_MODIFY', $user);
|
||||||
|
if ($result < 0) {
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
// End call triggers
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
dol_syslog(get_class($this) . "::update " . $this->error, LOG_ERR);
|
||||||
|
$this->db->rollback();
|
||||||
|
return -$error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
$this->db->rollback();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//$this->db->commit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate object with data from DB
|
||||||
|
*
|
||||||
|
* @param int $rowid Id of the SRIBMCustomMailInfo to load
|
||||||
|
* @param int $ref Id of the fac_rec_object
|
||||||
|
* @param bool $fill_defaults_from_template If true and the model doesn't exist in DB, fill attributes using the template
|
||||||
|
* @return int < 0 if KO, > 0 if OK
|
||||||
|
*/
|
||||||
|
public function fetch($rowid, $ref=null, $fill_defaults_from_template = false)
|
||||||
|
{
|
||||||
|
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 .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
|
||||||
|
$sql .= " WHERE " . (isset($ref) ? 'fk_facture_rec = ' . (int)$ref : "rowid = " . (int)$rowid);
|
||||||
|
|
||||||
|
dol_syslog("SRIBMCustomMailInfo::fetch", LOG_DEBUG);
|
||||||
|
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if (! $result) {
|
||||||
|
$this->error=$this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->db->num_rows($result)) {
|
||||||
|
$obj = $this->db->fetch_object($result);
|
||||||
|
|
||||||
|
$this->id = $obj->rowid;
|
||||||
|
$this->fk_facture_rec = $obj->fk_facture_rec;
|
||||||
|
$this->active = $obj->active;
|
||||||
|
$this->addmaindocfile = $obj->addmaindocfile;
|
||||||
|
$this->fromtype = $obj->fromtype;
|
||||||
|
$this->frommail = $obj->frommail;
|
||||||
|
$this->sendto_thirdparty = $obj->sendto_thirdparty;
|
||||||
|
$this->sendto_free = $obj->sendto_free;
|
||||||
|
$this->sendcc_thirdparty = $obj->sendcc_thirdparty;
|
||||||
|
$this->sendcc_free = $obj->sendcc_free;
|
||||||
|
$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;
|
||||||
|
$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);
|
||||||
|
dol_syslog("SRIBMCustomMailInfo::fetch error " . $this->error, LOG_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It seems to be usual to fully fetch by default (cf. Facture source
|
||||||
|
// code with fetch_optionals()) so we copy the Dolibarr behaviour
|
||||||
|
// Link to the facture_rec
|
||||||
|
$this->fac_rec_object = new FactureRec($this->db);
|
||||||
|
if ($this->fac_rec_object->fetch($ref) <= 0) {
|
||||||
|
$this->error = "Unable to fetch FactureRec $ref.";
|
||||||
|
dol_syslog("FactureRec::Fetch error " . $this->error, LOG_ERR);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if ($this->fac_rec_object->fetch_thirdparty() <= 0) {
|
||||||
|
$this->error = "Unable to fetch ThirdParty for FactureRec $ref.";
|
||||||
|
dol_syslog("FactureRec::FetchThirdParty error " . $this->error, LOG_ERR);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
$result = $this->fac_rec_object->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0); // This load $_facrec->linkedObjectsIds
|
||||||
|
|
||||||
|
// link to socpeople
|
||||||
|
if ($this->id) {
|
||||||
|
// FIXME: create a dedicated PHP class?
|
||||||
|
$sql = "SELECT fk_socpeople, sendtype";
|
||||||
|
$sql .= " FROM " . MAIN_DB_PREFIX . "sribm_custom_mail_info_socpeople";
|
||||||
|
$sql .= " WHERE fk_sribm_cmi = " . (int)$this->id;
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if (! $result) {
|
||||||
|
$this->error=$this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the attribute
|
||||||
|
$this->linkToSocPeoples = array();
|
||||||
|
while ($obj = $this->db->fetch_object($result)) {
|
||||||
|
$tmp = new Contact($this->db);
|
||||||
|
if ($tmp->fetch($obj->fk_socpeople) > 0) {
|
||||||
|
$tmp->pivot = $obj;
|
||||||
|
$this->linkToSocPeoples[] = $tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally, if the model hasn't been found (no id), we fill with the template's data
|
||||||
|
if (!$this->id && $fill_defaults_from_template) {
|
||||||
|
$result = $this->db->query("SELECT topic, content, joinfiles FROM " . MAIN_DB_PREFIX . "c_email_templates WHERE module = 'sendrecurringinvoicebymail' AND active = 1 AND enabled = '1' ORDER BY tms DESC LIMIT 1");
|
||||||
|
if ( ! $result or ! ($template = $this->db->fetch_object($result))) {
|
||||||
|
$this->error = "Can't find mail template for sendrecurringinvoicebymail";
|
||||||
|
dol_syslog("SRIBMCustomMailInfo::fetch error " . $this->error, LOG_ERR);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->subject = $template->topic;
|
||||||
|
$this->body_plaintext = $template->content;
|
||||||
|
$this->addmaindocfile = $template->joinfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete this object's record in database
|
||||||
|
*
|
||||||
|
* @return int <0 on error, >0 if OK
|
||||||
|
*/
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
$error=0;
|
||||||
|
|
||||||
|
//$this->db->begin();
|
||||||
|
|
||||||
|
$sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element;
|
||||||
|
$sql .= " WHERE rowid = " . (int)$this->id;
|
||||||
|
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if (! $result) {
|
||||||
|
//$this->db->rollback();
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call trigger
|
||||||
|
$result = $this->call_trigger('SRIBM_CUSTOM_MAIL_INFO_DELETE', $user);
|
||||||
|
if ($result < 0) {
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
// End call triggers
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
dol_syslog(get_class($this) . "::delete " . $this->error, LOG_ERR);
|
||||||
|
//$this->db->rollback();
|
||||||
|
return -$error;
|
||||||
|
}
|
||||||
|
|
||||||
|
//$this->db->commit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quick function to synchronize the links between this object and its contacts
|
||||||
|
*
|
||||||
|
* Format of the data :
|
||||||
|
* array(
|
||||||
|
* array('id' => id_contact_1, 'sendtype' => 'to'),
|
||||||
|
* array('id' => id_contact_2, 'sendtype' => 'cc'),
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* @param array $data Format : see above
|
||||||
|
* @return int <0 on error, >0 if OK
|
||||||
|
*/
|
||||||
|
public function updateLinkSocPeople($data)
|
||||||
|
{
|
||||||
|
$this->db->begin();
|
||||||
|
|
||||||
|
$result = $this->db->query("DELETE FROM " . MAIN_DB_PREFIX . "sribm_custom_mail_info_socpeople where fk_sribm_cmi = " . (int)$this->id);
|
||||||
|
if (! $result) {
|
||||||
|
$this->error=$this->db->lasterror();
|
||||||
|
$this->db->rollback();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "sribm_custom_mail_info_socpeople";
|
||||||
|
$sql .= " (fk_sribm_cmi, fk_socpeople, sendtype) VALUES (%d, %d, '%s')";
|
||||||
|
foreach ($data as $item) {
|
||||||
|
// We insert one by one to maximize compatibility
|
||||||
|
// (if there happens to be thousands of links, I'll rework it :)
|
||||||
|
$result = $this->db->query(sprintf(
|
||||||
|
$sql,
|
||||||
|
$this->id,
|
||||||
|
$item['id'],
|
||||||
|
$this->db->escape($item['sendtype'])
|
||||||
|
));
|
||||||
|
if (! $result) {
|
||||||
|
$this->error=$this->db->lasterror();
|
||||||
|
$this->db->rollback();
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->commit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to compile the recipients in one string from sendto_thirdparty,
|
||||||
|
* sendto_free and socpeople.
|
||||||
|
*
|
||||||
|
* @param string $sendtype One of 'to', 'cc', 'bcc'
|
||||||
|
* @param bool $filterBadEmail If true, don't include recipients with empty/bad email address
|
||||||
|
* @return string String compiling emails in the format 'Foo <foo@example.com>, bar@example.com'
|
||||||
|
*/
|
||||||
|
public function compileEmails($sendtype, $filterBadEmails = false)
|
||||||
|
{
|
||||||
|
$output = array();
|
||||||
|
|
||||||
|
$listContacts = $this->fac_rec_object->thirdparty->thirdparty_and_contact_email_array(1);
|
||||||
|
|
||||||
|
switch ($sendtype) {
|
||||||
|
case 'to':
|
||||||
|
if ($this->sendto_free) {
|
||||||
|
$output[] = $this->sendto_free;
|
||||||
|
}
|
||||||
|
if ($this->sendto_thirdparty) {
|
||||||
|
$output[] = $listContacts['thirdparty'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'cc':
|
||||||
|
if ($this->sendcc_free) {
|
||||||
|
$output[] = $this->sendcc_free;
|
||||||
|
}
|
||||||
|
if ($this->sendcc_thirdparty) {
|
||||||
|
$output[] = $listContacts['thirdparty'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'bcc':
|
||||||
|
if ($this->sendbcc_free) {
|
||||||
|
$output[] = $this->sendbcc_free;
|
||||||
|
}
|
||||||
|
if ($this->sendbcc_thirdparty) {
|
||||||
|
$output[] = $listContacts['thirdparty'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->linkToSocPeoples as $contact) {
|
||||||
|
if ($contact->pivot->sendtype == $sendtype) {
|
||||||
|
$output[] = $listContacts[$contact->id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filterBadEmails) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ class modsendrecurringinvoicebymail extends DolibarrModules
|
||||||
$this->editor_url = 'https://code.bugness.org/Dolibarr/sendrecurringinvoicebymail';
|
$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'
|
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z'
|
||||||
$this->version = '0.2.7';
|
$this->version = '0.3.0';
|
||||||
|
|
||||||
//Url to the file with your last numberversion of this module
|
//Url to the file with your last numberversion of this module
|
||||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||||
|
@ -90,7 +90,9 @@ class modsendrecurringinvoicebymail extends DolibarrModules
|
||||||
'tpl' => 0, // Set this to 1 if module overwrite template dir (core/tpl)
|
'tpl' => 0, // Set this to 1 if module overwrite template dir (core/tpl)
|
||||||
'barcode' => 0, // Set this to 1 if module has its own barcode directory (core/modules/barcode)
|
'barcode' => 0, // Set this to 1 if module has its own barcode directory (core/modules/barcode)
|
||||||
'models' => 0, // Set this to 1 if module has its own models directory (core/modules/xxx)
|
'models' => 0, // Set this to 1 if module has its own models directory (core/modules/xxx)
|
||||||
|
'css' => array(),
|
||||||
//'css' => array('/sendrecurringinvoicebymail/css/sendrecurringinvoicebymail.css.php'), // Set this to relative path of css file if module has its own css file
|
//'css' => array('/sendrecurringinvoicebymail/css/sendrecurringinvoicebymail.css.php'), // Set this to relative path of css file if module has its own css file
|
||||||
|
'js' => array(),
|
||||||
//'js' => array('/sendrecurringinvoicebymail/js/sendrecurringinvoicebymail.js.php'), // Set this to relative path of js file if module must load a js on all pages
|
//'js' => array('/sendrecurringinvoicebymail/js/sendrecurringinvoicebymail.js.php'), // Set this to relative path of js file if module must load a js on all pages
|
||||||
'hooks' => array('cron'), // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context 'all'
|
'hooks' => array('cron'), // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context 'all'
|
||||||
'moduleforexternal' => 0 // Set this to 1 if feature of module are opened to external users
|
'moduleforexternal' => 0 // Set this to 1 if feature of module are opened to external users
|
||||||
|
@ -140,6 +142,7 @@ class modsendrecurringinvoicebymail extends DolibarrModules
|
||||||
|
|
||||||
// Array to add new pages in new tabs
|
// Array to add new pages in new tabs
|
||||||
$this->tabs = array();
|
$this->tabs = array();
|
||||||
|
$this->tabs[] = array('data'=>'invoice-rec:+sendrecurringinvoicebymail:SendingByMail:sendrecurringinvoicebymail@sendrecurringinvoicebymail:sendrecurringinvoicebymail/fiche-rec-tab1.php?id=__ID__'); // To add a new tab identified by code tabname1
|
||||||
// Example:
|
// Example:
|
||||||
// $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@sendrecurringinvoicebymail:$user->rights->sendrecurringinvoicebymail->read:/sendrecurringinvoicebymail/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1
|
// $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@sendrecurringinvoicebymail:$user->rights->sendrecurringinvoicebymail->read:/sendrecurringinvoicebymail/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1
|
||||||
// $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@sendrecurringinvoicebymail:$user->rights->othermodule->read:/sendrecurringinvoicebymail/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key.
|
// $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@sendrecurringinvoicebymail:$user->rights->othermodule->read:/sendrecurringinvoicebymail/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key.
|
||||||
|
@ -314,8 +317,12 @@ class modsendrecurringinvoicebymail extends DolibarrModules
|
||||||
*/
|
*/
|
||||||
public function init($options='')
|
public function init($options='')
|
||||||
{
|
{
|
||||||
$sql = array();
|
// Launch SQL files
|
||||||
|
$result=$this->_load_tables('/' . basename(dirname(dirname(dirname(__FILE__)))) . '/sql/');
|
||||||
|
if ($result < 0) return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default')
|
||||||
|
|
||||||
|
// Launch small and conditional SQL queries
|
||||||
|
$sql = array();
|
||||||
// we check if our model already exists
|
// we check if our model already exists
|
||||||
$result = $this->db->query("SELECT COUNT(*) AS cpt FROM " . MAIN_DB_PREFIX . "c_email_templates WHERE module = 'sendrecurringinvoicebymail'");
|
$result = $this->db->query("SELECT COUNT(*) AS cpt FROM " . MAIN_DB_PREFIX . "c_email_templates WHERE module = 'sendrecurringinvoicebymail'");
|
||||||
if ($result) {
|
if ($result) {
|
||||||
|
@ -334,6 +341,44 @@ class modsendrecurringinvoicebymail extends DolibarrModules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reactivate the template in case the module has been
|
||||||
|
// uninstalled which should have disabled the template.
|
||||||
|
$sql[] = "UPDATE " . MAIN_DB_PREFIX . "c_email_templates SET enabled = 1 WHERE module = 'sendrecurringinvoicebymail'";
|
||||||
|
|
||||||
|
// Cleaning up old (and ugly) system which
|
||||||
|
// used note_private to store overriding data.
|
||||||
|
// TODO : Remove this block at next version.
|
||||||
|
$result = $this->db->query("SELECT r.rowid AS rid, r.note_private, s.rowid AS sid FROM " . MAIN_DB_PREFIX . "facture_rec AS r LEFT JOIN " . MAIN_DB_PREFIX . "sribm_custom_mail_info AS s ON r.rowid = s.fk_facture_rec WHERE r.note_private LIKE '%sendrecurringinvoicebymail::%'");
|
||||||
|
if ($result) {
|
||||||
|
while($row = $this->db->fetch_object($result)) {
|
||||||
|
$mail_data = $this->parseCustomFieldsMail($row->note_private);
|
||||||
|
$sid = $row->sid;
|
||||||
|
if (! $sid) {
|
||||||
|
$this->db->query("INSERT INTO " . MAIN_DB_PREFIX . "sribm_custom_mail_info (fk_facture_rec) VALUES (" . (int)$row->rid . ")");
|
||||||
|
$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) {
|
||||||
|
if (! empty($mail_data[$key])) {
|
||||||
|
// We loop on each field.
|
||||||
|
// Not optimized, I know.
|
||||||
|
$this->db->query("UPDATE " . MAIN_DB_PREFIX . "sribm_custom_mail_info SET " . $item . " = '" . $this->db->escape($mail_data[$key]) . "' WHERE rowid = " . (int)$sid);
|
||||||
|
if ($key == 'sendto') {
|
||||||
|
// If the note_private specified a recipient, we disable sending to the
|
||||||
|
// main societe's mail.
|
||||||
|
$this->db->query("UPDATE " . MAIN_DB_PREFIX . "sribm_custom_mail_info SET sendto_thirdparty = 0 WHERE rowid = " . (int)$row->rid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$regexps = array(
|
||||||
|
'/%%% sendrecurringinvoicebymail::subject.*%%%/sU',
|
||||||
|
'/%%% sendrecurringinvoicebymail::body.*%%%/sU',
|
||||||
|
'/%%% sendrecurringinvoicebymail::sendto.*%%%/sU',
|
||||||
|
);
|
||||||
|
$row->note_private = preg_replace($regexps, array('', '', ''), $row->note_private);
|
||||||
|
$this->db->query("UPDATE " . MAIN_DB_PREFIX . "facture_rec SET note_private = '" . $this->db->escape($row->note_private) . "' WHERE rowid = " . (int)$row->rid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $this->_init($sql, $options);
|
return $this->_init($sql, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,8 +394,51 @@ class modsendrecurringinvoicebymail extends DolibarrModules
|
||||||
{
|
{
|
||||||
$sql = array();
|
$sql = array();
|
||||||
|
|
||||||
$sql[] = "DELETE FROM " . MAIN_DB_PREFIX."c_email_templates WHERE module = 'sendrecurringinvoicebymail'";
|
// Disable the template
|
||||||
|
// (instead of deleting it, which may cause unwanted work loss)
|
||||||
|
// (Yeah, counterside is data bloat... sorry...)
|
||||||
|
$sql[] = "UPDATE " . MAIN_DB_PREFIX . "c_email_templates SET enabled = 0 WHERE module = 'sendrecurringinvoicebymail'";
|
||||||
|
|
||||||
return $this->_remove($sql, $options);
|
return $this->_remove($sql, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIXME: Obsolete. Replaced by SRIBMCustomMailInfo. To be removed.
|
||||||
|
* For the time being, we abuse of note_private to store our customizations
|
||||||
|
*
|
||||||
|
* This expect something like this in note_private:
|
||||||
|
* This is a good client... (other private infos)
|
||||||
|
* %%% sendrecurringinvoicebymail::subject
|
||||||
|
* New invoice __REF__
|
||||||
|
* %%%
|
||||||
|
* %%% sendrecurringinvoicebymail::sendto
|
||||||
|
* recipient1@example.org, recipient2@example.org
|
||||||
|
* %%%
|
||||||
|
* %%% sendrecurringinvoicebymail::body
|
||||||
|
* Hello dear client,
|
||||||
|
* Please find attached...
|
||||||
|
* %%%
|
||||||
|
*/
|
||||||
|
public function parseCustomFieldsMail($data)
|
||||||
|
{
|
||||||
|
$output = [];
|
||||||
|
|
||||||
|
// Remove eventual windows' "\r"
|
||||||
|
$data = str_replace("\r", "", $data);
|
||||||
|
|
||||||
|
$regexps = array(
|
||||||
|
'subject' => '/(^|\n)%%% sendrecurringinvoicebymail::subject\n(?<subject>.*)%%%(\n|$)/sU',
|
||||||
|
'body' => '/(^|\n)%%% sendrecurringinvoicebymail::body\n(?<body>.*)%%%(\n|$)/sU',
|
||||||
|
'sendto' => '/(^|\n)%%% sendrecurringinvoicebymail::sendto\n(?<sendto>.*)%%%(\n|$)/sU',
|
||||||
|
);
|
||||||
|
foreach ($regexps as $key => $r) {
|
||||||
|
$result_regexp = [];
|
||||||
|
if (preg_match_all($r, $data, $result_regexp)) {
|
||||||
|
$output[$key] = trim($result_regexp[$key][0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
326
fiche-rec-tab1.php
Normal file
326
fiche-rec-tab1.php
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
<?php
|
||||||
|
/* Copyright (C) 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Initially copied from modulebuilder/template/myobject_card.php
|
||||||
|
|
||||||
|
// 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 && file_exists("../../../main.inc.php")) $res=@include "../../../main.inc.php";
|
||||||
|
if (! $res) die("Include of main fails");
|
||||||
|
|
||||||
|
// Load needed classes/lib
|
||||||
|
require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture-rec.class.php';
|
||||||
|
require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
|
||||||
|
require_once 'class/sribmcustommailinfo.class.php';
|
||||||
|
|
||||||
|
// Get parameters
|
||||||
|
$id = GETPOST('id', 'int');
|
||||||
|
$output = '';
|
||||||
|
|
||||||
|
// Check security (take care of everything, even page layout, if something goes wrong)
|
||||||
|
restrictedArea($user, 'facture', $id, 'facture_rec');
|
||||||
|
|
||||||
|
// Load translation files required by the page
|
||||||
|
$langs->loadLangs(array('bills', 'compta', 'other', 'mails', 'products', 'companies', 'sendrecurringinvoicebymail@sendrecurringinvoicebymail'));
|
||||||
|
|
||||||
|
// Wrap everything in a do-while(false) as a try-catch mecanisme
|
||||||
|
// in order to print llxFooter whatever happens.
|
||||||
|
do {
|
||||||
|
/**
|
||||||
|
* Part 0 : Preparations
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Load necessary data
|
||||||
|
$object = new FactureRec($db);
|
||||||
|
$mailObject = new SRIBMCustomMailInfo($db);
|
||||||
|
$form = new Form($db);
|
||||||
|
if ($object->fetch($id) <= 0 or !$object->id)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
$listFrom['robot'] = $conf->global->MAIN_MAIL_EMAIL_FROM;
|
||||||
|
$listFrom['company'] = $conf->global->MAIN_INFO_SOCIETE_NOM .' <'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'>';
|
||||||
|
if (!empty($user->email)) {
|
||||||
|
$listFrom['user'] = $user->getFullName($langs) . ' <' . $user->email . '>';
|
||||||
|
}
|
||||||
|
// If the address in the SRIBM object is not the same as the user (basically,
|
||||||
|
// the user has changed its email address or the address has been set by another
|
||||||
|
// user), we add an 'old' = 'no modification' option.
|
||||||
|
if ($mailObject->id
|
||||||
|
&& $mailObject->fromtype == 'user'
|
||||||
|
&& isset($listFrom['user'])
|
||||||
|
&& $listFrom['user'] != $mailObject->frommail
|
||||||
|
) {
|
||||||
|
$listFrom['old'] = $mailObject->frommail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of contacts of the third party
|
||||||
|
$listContacts = $mailObject->fac_rec_object->thirdparty->thirdparty_and_contact_email_array(1);
|
||||||
|
|
||||||
|
// Substitution array/string
|
||||||
|
$helpforsubstitution = $langs->trans('AvailableVariables').' :<br>'."\n";
|
||||||
|
$tmparray = getCommonSubstitutionArray($langs, 0, null, $object);
|
||||||
|
complete_substitutions_array($tmparray, $langs);
|
||||||
|
foreach($tmparray as $key => $val) {
|
||||||
|
$helpforsubstitution .= $key . ' -> ' . $langs->trans(dol_string_nohtmltag($val)) . '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Part 1 : Treatment of form submission
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If the mail form has been submitted, check and record the data
|
||||||
|
if (GETPOST('save')) {
|
||||||
|
do {
|
||||||
|
// Validate input data
|
||||||
|
if (! array_key_exists(GETPOST('fromtype', 'alpha'), $listFrom)) {
|
||||||
|
setEventMessages('Unexpected from value', null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (GETPOST('sendto_socpeople', 'array') != array_intersect(GETPOST('sendto_socpeople', 'array'), array_keys($listContacts))) {
|
||||||
|
setEventMessages("Unexpected contact value in 'to'", null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (GETPOST('sendcc_socpeople', 'array') != array_intersect(GETPOST('sendcc_socpeople', 'array'), array_keys($listContacts))) {
|
||||||
|
setEventMessages("Unexpected contact value in 'cc'", null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Validate some non-breaking stuff after feeding
|
||||||
|
if (empty(GETPOST('sendto_free', 'alpha')) && empty(GETPOST('sendto_socpeople', 'array'))) {
|
||||||
|
// Kinda weird behaviour from CMailFile but better alert the user beforehand
|
||||||
|
// FIXME: check if there is a workaround ?
|
||||||
|
setEventMessages("In some configuration, CMailFile doesn't allow empty 'to' recipient. You should set at least one.", null, 'warnings');
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
if (! strlen(GETPOST('subject', 'alpha'))) {
|
||||||
|
// Kinda weird behaviour from CMailFile but better alert the user beforehand
|
||||||
|
// FIXME: check if there is a workaround ?
|
||||||
|
setEventMessages("In some configuration, CMailFile doesn't allow empty subject. You should set one.", null, 'warnings');
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feed the input data to the model
|
||||||
|
$mailObject->active = GETPOST('active', 'int') ? 1 : 0;
|
||||||
|
$mailObject->addmaindocfile = GETPOST('addmaindocfile', 'int') ? 1 : 0;
|
||||||
|
|
||||||
|
$mailObject->fromtype = GETPOST('fromtype', 'alpha');
|
||||||
|
$mailObject->frommail = $listFrom[$mailObject->fromtype];
|
||||||
|
|
||||||
|
$mailObject->sendto_free = GETPOST('sendto_free', 'alpha');
|
||||||
|
$mailObject->sendto_thirdparty = in_array('thirdparty', GETPOST('sendto_socpeople', 'array'));
|
||||||
|
|
||||||
|
$mailObject->sendcc_free = GETPOST('sendcc_free', 'alpha');
|
||||||
|
$mailObject->sendcc_thirdparty = in_array('thirdparty', GETPOST('sendcc_socpeople', 'array'));
|
||||||
|
|
||||||
|
$mailObject->subject = GETPOST('subject', 'alpha');
|
||||||
|
$mailObject->body_plaintext = GETPOST('body_plaintext', 'alpha');
|
||||||
|
|
||||||
|
// Save into database
|
||||||
|
if ($mailObject->id) {
|
||||||
|
if ($mailObject->update($user) != 1) {
|
||||||
|
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$mailObject->fk_facture_rec = $object->id;
|
||||||
|
if ($mailObject->create($user) < 0) {
|
||||||
|
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update the linked contacts
|
||||||
|
$data = array_merge(
|
||||||
|
array_map(
|
||||||
|
function ($id) { return array('id' => $id, 'sendtype' => 'to'); },
|
||||||
|
array_filter(GETPOST('sendto_socpeople', 'array'), 'is_numeric')
|
||||||
|
),
|
||||||
|
array_map(
|
||||||
|
function ($id) { return array('id' => $id, 'sendtype' => 'cc'); },
|
||||||
|
array_filter(GETPOST('sendcc_socpeople', 'array'), 'is_numeric')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if ($mailObject->updateLinkSocPeople($data) != 1) {
|
||||||
|
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything seems ok
|
||||||
|
setEventMessages($langs->trans("CorrectlyUpdated"), null, 'mesgs');
|
||||||
|
// ... + redirect to cleanly reload all data and avoid some F5 misbehaviour
|
||||||
|
header("Location: fiche-rec-tab1.php?id=" . (int) $id, true, 302);
|
||||||
|
return;
|
||||||
|
} while(false);
|
||||||
|
} else if (GETPOST('reset') && $mailObject->id) {
|
||||||
|
if ($mailObject->delete() == 1) {
|
||||||
|
// Success message...
|
||||||
|
setEventMessages($langs->trans("ResetDone"), null, 'mesgs');
|
||||||
|
|
||||||
|
// ... + redirect to cleanly reload all data
|
||||||
|
header("Location: fiche-rec-tab1.php?id=" . (int) $id, true, 302);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setEventMessages($langs->trans("ErrorSQL") . " : " . $mailObject->error , null, 'errors');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the pre-selected id for To/Cc select inputs
|
||||||
|
$preselected = array(
|
||||||
|
'to' => array(),
|
||||||
|
'cc' => array(),
|
||||||
|
);
|
||||||
|
if (GETPOSTISSET('sendto_socpeople') || GETPOSTISSET('sendcc_socpeople')) {
|
||||||
|
// Retrieve data from last form submission
|
||||||
|
$preselected['to'] = GETPOST('sendto_socpeople');
|
||||||
|
$preselected['cc'] = GETPOST('sendcc_socpeople');
|
||||||
|
} else {
|
||||||
|
// Retrieve data from model
|
||||||
|
foreach ($mailObject->linkToSocPeoples as $contact) {
|
||||||
|
$preselected[$contact->pivot->sendtype][] = $contact->id;
|
||||||
|
}
|
||||||
|
// add the third-party's email in case sendXX_thirdparty is true
|
||||||
|
if ($mailObject->sendto_thirdparty) {
|
||||||
|
$preselected['to'][] = 'thirdparty';
|
||||||
|
}
|
||||||
|
if ($mailObject->sendcc_thirdparty) {
|
||||||
|
$preselected['cc'][] = 'thirdparty';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Part 2 : Display
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Same tabs than the main page
|
||||||
|
$head=invoice_rec_prepare_head($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";
|
||||||
|
$output .= "</div><!-- Closing div class='tabBar' -->\n\n";
|
||||||
|
|
||||||
|
$output .= '<div class="titre inline-block">' . $langs->trans("Options") . "</div>\n";
|
||||||
|
$output .= '<form id="sribmform" name="sribmform" method="POST" action="#sribmform">';
|
||||||
|
$output .= '<table class="liste" summary="mail options"><tbody>';
|
||||||
|
$output .= '<tr class="oddeven">';
|
||||||
|
$output .= ' <td><label for="active">' . $langs->trans('OptionEnable') . "</label></td>\n";
|
||||||
|
$output .= ' <td><input type="checkbox" id="active" name="active" value="1"' . ((empty($_POST) && $mailObject->active || GETPOSTISSET('active')) ? ' checked="checked"' : '') . " /></td>\n";
|
||||||
|
$output .= "</tr>\n";
|
||||||
|
$output .= "</tbody></table>\n";
|
||||||
|
|
||||||
|
// Little explanations
|
||||||
|
$output .= '<div class="titre inline-block" style="margin-top: 1.5em;">' . $langs->trans("CustomizationTitle") . "</div>\n";
|
||||||
|
// TODO: translation
|
||||||
|
$output .= "<p>" . $langs->trans('CustomizationIntro', $langs->trans('Reset')) . "<br />\n";
|
||||||
|
$output .= $langs->trans('CustomizationLinkToGlobalTemplate', DOL_URL_ROOT . '/admin/mails_templates.php?search_label=sendrecurring') . "</p>\n\n";
|
||||||
|
|
||||||
|
$output .= '<table class="tableforemailform boxtablenotop" width="100%">';
|
||||||
|
$output .= '<tr><td class="fieldrequired minwidth200">'.$langs->trans("MailFrom").'</td><td>';
|
||||||
|
$defaultFrom = 'robot';
|
||||||
|
if (isset($listFrom['old'])) {
|
||||||
|
$defaultFrom = 'old';
|
||||||
|
} elseif ($mailObject->id) {
|
||||||
|
$defaultFrom = $mailObject->fromtype;
|
||||||
|
}
|
||||||
|
$output .= $form->selectarray('fromtype', $listFrom, GETPOST('fromtype', 'alpha') ? GETPOST('fromtype', 'alpha') : $defaultFrom);
|
||||||
|
$output .= "</td></tr>\n";
|
||||||
|
|
||||||
|
|
||||||
|
// Recipient(s)
|
||||||
|
$output .= '<tr><td class="minwidth200 fieldrequired">';
|
||||||
|
$output .= $form->textwithpicto($langs->trans("MailTo"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
|
||||||
|
$output .= "</td>\n<td>";
|
||||||
|
$output .= '<input class="minwidth200" id="sendto_free" name="sendto_free" value="'.(GETPOST("sendto_free", "alpha") ? GETPOST("sendto_free", "alpha") : htmlentities($mailObject->sendto_free)) . '" />';
|
||||||
|
$output .= " " . $langs->trans("and") . "/" . $langs->trans("or") . " ";
|
||||||
|
$output .= $form->multiselectarray('sendto_socpeople', $listContacts, $preselected['to']);
|
||||||
|
$output .= "</td></tr>\n";
|
||||||
|
|
||||||
|
|
||||||
|
// CC
|
||||||
|
$output .= '<tr><td class="minwidth200">';
|
||||||
|
$output .= $form->textwithpicto($langs->trans("MailCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
|
||||||
|
$output .= "</td>\n<td>";
|
||||||
|
$output .= '<input class="minwidth200" id="sendto_free" name="sendcc_free" value="'.(GETPOST("sendcc_free", "alpha") ? GETPOST("sendcc_free", "alpha") : htmlentities($mailObject->sendcc_free)) . '" />';
|
||||||
|
$output .= " " . $langs->trans("and") . "/" . $langs->trans("or") . " ";
|
||||||
|
$output .= $form->multiselectarray('sendcc_socpeople', $listContacts, $preselected['cc']);
|
||||||
|
$output .= "</td></tr>\n";
|
||||||
|
|
||||||
|
|
||||||
|
// Subject
|
||||||
|
$output .= '<tr><td class="minwidth200 fieldrequired">';
|
||||||
|
$output .= $form->textwithpicto($langs->trans("MailTopic"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfromtopic');
|
||||||
|
$output .= "</td>\n<td>";
|
||||||
|
$output .= '<input type="text" class="quatrevingtpercent" id="subject" name="subject" value="'. (GETPOST('subject', 'alpha') ? GETPOST('subject', 'alpha') : htmlentities($mailObject->subject)) . '" />';
|
||||||
|
$output .= "</td></tr>\n";
|
||||||
|
|
||||||
|
|
||||||
|
// addmaindocfile
|
||||||
|
$output .= '<tr><td>' . $langs->trans('MailFile') . "</td>\n";
|
||||||
|
$tmp_addmaindocfile = $mailObject->addmaindocfile;
|
||||||
|
if (! empty($_POST)) {
|
||||||
|
$tmp_addmaindocfile = GETPOSTISSET('addmaindocfile') ? 1 : 0;
|
||||||
|
}
|
||||||
|
$output .= '<td><input type="checkbox" name="addmaindocfile" value="1"' . ($tmp_addmaindocfile ? ' checked="checked"' : '') . ' /> ' . $langs->trans("JoinMainDoc") . "</td>\n";
|
||||||
|
|
||||||
|
|
||||||
|
// body_plaintext
|
||||||
|
$output .= '<tr><td class="minwidth200" valign="top">';
|
||||||
|
$output .= $form->textwithpicto($langs->trans("MailText"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
|
||||||
|
$output .= "</td>\n<td>";
|
||||||
|
/*
|
||||||
|
// doleditor does some weird stuff, adding <br> and newlines, I'll get more into it when I have time.
|
||||||
|
// fallback to simple <textarea> for the time being.
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
|
||||||
|
$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>\n";
|
||||||
|
$output .= "</td></tr>\n";
|
||||||
|
|
||||||
|
$output .= "</table>\n";
|
||||||
|
|
||||||
|
$output .= '<br><div class="center">';
|
||||||
|
$output .= '<input class="button" type="submit" id="save" name="save" value="'.$langs->trans("Save").'" />';
|
||||||
|
$output .= '<input class="button warning" type="submit" id="reset" name="reset" value="'.$langs->trans("Reset").'"';
|
||||||
|
$output .= ($mailObject->id ? '' : ' title="' . $langs->trans('ResetTooltipNoCustomisationToReset') . '" disabled="disabled"') . ' />';
|
||||||
|
$output .= "</div>\n";
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
// Print everything
|
||||||
|
llxHeader('', $langs->trans('RepeatableInvoice') . ' - ' . $langs->trans('SendingByMail'), '');
|
||||||
|
print $output;
|
||||||
|
llxFooter();
|
BIN
img/screenshot1.png
Normal file
BIN
img/screenshot1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
|
@ -41,13 +41,12 @@ About = About
|
||||||
sendrecurringinvoicebymailAbout = About sendrecurringinvoicebymail
|
sendrecurringinvoicebymailAbout = About sendrecurringinvoicebymail
|
||||||
sendrecurringinvoicebymailAboutPage = sendrecurringinvoicebymail about page
|
sendrecurringinvoicebymailAboutPage = sendrecurringinvoicebymail about page
|
||||||
|
|
||||||
#
|
# Tab title on the fiche-rec page
|
||||||
# Sample 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.
|
||||||
MyPageName = My page name
|
CustomizationLinkToGlobalTemplate = As a note, the global email template can be found <a href="%s">here</a>.
|
||||||
|
OptionEnable = Send mail when generating via cron (cf. module "Scheduled Jobs")
|
||||||
#
|
Reset = Reset
|
||||||
# Sample widget
|
ResetDone = Reset done : customization deleted
|
||||||
#
|
ResetTooltipNoCustomisationToReset = No customization to delete.
|
||||||
MyWidget = My widget
|
SendingByMail = Sending by email
|
||||||
MyWidgetDescription = My widget description
|
|
||||||
|
|
|
@ -37,12 +37,13 @@ sendrecurringinvoicebymailAbout = À propos de sendrecurringinvoicebymail
|
||||||
sendrecurringinvoicebymailAboutPage = Page à propos de sendrecurringinvoicebymail
|
sendrecurringinvoicebymailAboutPage = Page à propos de sendrecurringinvoicebymail
|
||||||
|
|
||||||
#
|
#
|
||||||
# Page d'exemple
|
# Page de personnalisation par modèle
|
||||||
#
|
#
|
||||||
MyPageName = Nom de ma page
|
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 configurable par <a href="%s">ici</a>.
|
||||||
# Box d'exemple
|
OptionEnable = Envoyer par email lors d'une génération automatique via le module "Travaux planifiés"
|
||||||
#
|
Reset = Réinitialiser
|
||||||
MyWidget = Mon widget
|
ResetDone = Réinitialisation effectuée : personnalisation supprimée.
|
||||||
MyWidgetDescription = Description de mon widget
|
ResetTooltipNoCustomisationToReset = Aucune personnalisation à supprimer.
|
||||||
|
SendingByMail = Envoi par courriel
|
||||||
|
|
14
sql/data.sql
Normal file
14
sql/data.sql
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-- 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/>.
|
29
sql/llx_sribm_custom_mail_info.key.sql
Normal file
29
sql/llx_sribm_custom_mail_info.key.sql
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
-- 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/.
|
||||||
|
|
||||||
|
|
||||||
|
-- BEGIN MODULEBUILDER INDEXES
|
||||||
|
--ALTER TABLE llx_mymodule_myobject ADD INDEX idx_fieldobject (fieldobject);
|
||||||
|
-- END MODULEBUILDER INDEXES
|
||||||
|
|
||||||
|
--ALTER TABLE llx_mymodule_myobject ADD UNIQUE INDEX uk_mymodule_myobject_fieldxy(fieldx, fieldy);
|
||||||
|
|
||||||
|
--ALTER TABLE llx_mymodule_myobject ADD CONSTRAINT llx_mymodule_myobject_fk_field FOREIGN KEY (fk_field) REFERENCES llx_mymodule_myotherobject(rowid);
|
||||||
|
|
||||||
|
ALTER TABLE llx_sribm_custom_mail_info ADD UNIQUE INDEX llx_sribm_custom_mail_info_uniq_frec (fk_facture_rec);
|
||||||
|
ALTER TABLE llx_sribm_custom_mail_info ADD CONSTRAINT llx_sribm_custom_mail_info_fk_rowid FOREIGN KEY (fk_facture_rec) REFERENCES llx_facture_rec(rowid) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE llx_sribm_custom_mail_info_socpeople ADD CONSTRAINT llx_sribm_custom_mail_info_socpeople_c_fk FOREIGN KEY (fk_sribm_cmi) REFERENCES llx_sribm_custom_mail_info(rowid) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE llx_sribm_custom_mail_info_socpeople ADD CONSTRAINT llx_sribm_custom_mail_info_socpeople_s_fk FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid) ON DELETE CASCADE ON UPDATE CASCADE;
|
49
sql/llx_sribm_custom_mail_info.sql
Normal file
49
sql/llx_sribm_custom_mail_info.sql
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
-- 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/.
|
||||||
|
|
||||||
|
|
||||||
|
-- Sorry for the schema's complexity, but we have to manage 3 types
|
||||||
|
-- of recipients :
|
||||||
|
-- * the email in the societe/company's profile (default for the module)
|
||||||
|
-- * the contacts (table 'llx_socpeople')
|
||||||
|
-- * the email from the free text input
|
||||||
|
-- The From can also be a little difficult since, for the time being,
|
||||||
|
-- we avoid a free text input for the source email.
|
||||||
|
CREATE TABLE llx_sribm_custom_mail_info(
|
||||||
|
rowid INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
fk_facture_rec INTEGER NOT NULL,
|
||||||
|
active smallint DEFAULT 1 NOT NULL,
|
||||||
|
addmaindocfile smallint DEFAULT 1 NOT NULL,
|
||||||
|
fromtype text NOT NULL,
|
||||||
|
frommail text NOT NULL,
|
||||||
|
sendto_thirdparty smallint DEFAULT 1 NOT NULL,
|
||||||
|
sendto_free text,
|
||||||
|
sendcc_thirdparty smallint DEFAULT 0 NOT NULL,
|
||||||
|
sendcc_free text,
|
||||||
|
sendbcc_thirdparty smallint DEFAULT 0 NOT NULL,
|
||||||
|
sendbcc_free text,
|
||||||
|
subject text,
|
||||||
|
body_plaintext mediumtext,
|
||||||
|
body_html mediumtext
|
||||||
|
) ENGINE=innodb;
|
||||||
|
|
||||||
|
|
||||||
|
-- sendtype should only be one of 'to', 'cc' and 'bcc' but
|
||||||
|
-- I'm kinda afraid to do an ENUM with Dolibarr black magic on SQL.
|
||||||
|
CREATE TABLE llx_sribm_custom_mail_info_socpeople(
|
||||||
|
fk_sribm_cmi INTEGER NOT NULL,
|
||||||
|
fk_socpeople INTEGER NOT NULL,
|
||||||
|
sendtype text NOT NULL
|
||||||
|
) ENGINE=innodb;
|
Loading…
Reference in a new issue