diff --git a/htdocs/accountancy/class/accountancysystem.class.php b/htdocs/accountancy/class/accountancysystem.class.php index a62dddd6a26..99f908e70e3 100644 --- a/htdocs/accountancy/class/accountancysystem.class.php +++ b/htdocs/accountancy/class/accountancysystem.class.php @@ -38,6 +38,11 @@ class AccountancySystem */ public $error = ''; + /** + * @var string[] Array of Errors code (or messages) + */ + public $errors = array(); + /** * @var int ID */ diff --git a/htdocs/core/ajax/flowjs-server.php b/htdocs/core/ajax/flowjs-server.php new file mode 100644 index 00000000000..e1f5feaaf10 --- /dev/null +++ b/htdocs/core/ajax/flowjs-server.php @@ -0,0 +1,161 @@ + + * + * 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 . + */ + +/** + * \file htdocs/core/ajax/bankconciliate.php + * \brief File to set data for bank concilation + */ + +if (!defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); // Disables token renewal +} +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} +if (!defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); +} +if (!defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (!defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', '1'); +} +// If there is no need to load and show top and left menu +if (!defined("NOLOGIN")) { + define("NOLOGIN", '1'); +} +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Required to know date format for dol_print_date + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + +$action = GETPOST('action', 'aZ09'); +$module = GETPOST('module', 'aZ09'); +$upload_dir = GETPOST('upload_dir', 'alpha'); +$flowFilename = GETPOST('flowFilename', 'alpha'); +$flowIdentifier = GETPOST('flowIdentifier', 'alpha'); +$flowChunkNumber = GETPOST('flowChunkNumber', 'alpha'); +$flowChunkSize = GETPOST('flowChunkSize', 'alpha'); +$flowTotalSize = GETPOST('flowTotalSize', 'alpha'); + +/* + * Action + */ + + +top_httphead(); +dol_syslog(join(',', $_GET)); + +$result = true; + +if (!empty($upload_dir)) { + $temp_dir = $upload_dir.'/'.$flowIdentifier; +} else { + $temp_dir = DOL_DATA_ROOT.'/'.$module.'/temp/'.$flowIdentifier; + $upload_dir = $temp_dir; +} + +if ($_SERVER['REQUEST_METHOD'] === 'GET') { + $chunk_file = $temp_dir.'/'.$flowFilename.'.part'.$flowChunkNumber; + if (file_exists($chunk_file)) { + header("HTTP/1.0 200 Ok"); + } else { + header("HTTP/1.0 404 Not Found"); + } +} else { + // loop through files and move the chunks to a temporarily created directory + if (file_exists($upload_dir.'/'.$flowFilename)) { + echo json_encode('File '.$flowIdentifier.' was already uploaded'); + header("HTTP/1.0 200 Ok"); + } elseif (!empty($_FILES)) foreach ($_FILES as $file) { + // check the error status + if ($file['error'] != 0) { + dol_syslog('error '.$file['error'].' in file '.$flowFilename); + continue; + } + + // init the destination file (format .part<#chunk> + // the file is stored in a temporary directory + $dest_file = $temp_dir.'/'.$flowFilename.'.part'.$flowChunkNumber; + + // create the temporary directory + if (!dol_is_dir($temp_dir)) { + dol_mkdir($temp_dir); + } + + // move the temporary file + if (!dol_move_uploaded_file($file['tmp_name'], $dest_file, 0)) { + dol_syslog('Error saving (move_uploaded_file) chunk '.$flowChunkNumber.' for file '.$flowFilename); + } else { + // check if all the parts present, and create the final destination file + $result = createFileFromChunks($temp_dir, $upload_dir, $flowFilename, $flowChunkSize, $flowTotalSize); + } + } +} +if ($result) { + echo json_encode('File '.$flowIdentifier.' uploaded'); +} else { + echo json_encode('Error while uploading file '.$flowIdentifier); +} + + +/** + * Check if all the parts exist, and + * gather all the parts of the file together + * @param string $temp_dir - the temporary directory holding all the parts of the file + * @param string $upload_dir - the temporary directory to create file + * @param string $fileName - the original file name + * @param string $chunkSize - each chunk size (in bytes) + * @param string $totalSize - original file size (in bytes) + * @return bool true if Ok false else + */ +function createFileFromChunks($temp_dir, $upload_dir, $fileName, $chunkSize, $totalSize) +{ + + dol_syslog(__METHOD__, LOG_DEBUG); + // count all the parts of this file + $total_files = 0; + $files = dol_dir_list($temp_dir, 'files'); + foreach ($files as $file) { + if (stripos($file, $fileName) !== false) { + $total_files++; + } + } + + // check that all the parts are present + // the size of the last part is between chunkSize and 2*$chunkSize + if ($total_files * $chunkSize >= ($totalSize - $chunkSize + 1)) { + // create the final destination file + if (($fp = fopen($upload_dir.'/'.$fileName, 'w')) !== false) { + for ($i=1; $i<=$total_files; $i++) { + fwrite($fp, file_get_contents($temp_dir.'/'.$fileName.'.part'.$i)); + dol_syslog('writing chunk '.$i); + } + fclose($fp); + } else { + dol_syslog('cannot create the destination file'); + return false; + } + + // rename the temporary directory (to avoid access from other + // concurrent chunks uploads) + @rename($temp_dir, $temp_dir.'_UNUSED'); + } + return true; +} diff --git a/htdocs/core/class/commonobjectline.class.php b/htdocs/core/class/commonobjectline.class.php index 972ab7e4476..02749aa1f55 100644 --- a/htdocs/core/class/commonobjectline.class.php +++ b/htdocs/core/class/commonobjectline.class.php @@ -79,8 +79,20 @@ abstract class CommonObjectLine extends CommonObject public $product_type; // type in line public $fk_product; // product id in line (when line is linked to a product) + /** + * Description of the line + * @var string + */ public $desc; + /** + * Description of the line + * @var string + * @deprecated + * @see $desc + */ + public $description; + public $product; // To store full product object after a fetch_product() on a line public $product_ref; // ref in product table public $product_label; // label in product table diff --git a/htdocs/core/class/commonorder.class.php b/htdocs/core/class/commonorder.class.php index 65ae367c3b2..8f2edc005ec 100644 --- a/htdocs/core/class/commonorder.class.php +++ b/htdocs/core/class/commonorder.class.php @@ -167,12 +167,6 @@ abstract class CommonOrderLine extends CommonObjectLine */ public $product_type = 0; - /** - * Description of the line - * @var string - */ - public $desc; - /** * Id of corresponding product * @var int diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 48458c036b1..6bf4807ea6f 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -1,6 +1,8 @@ - * Copyright (C) 2022 Charlene Benke +/* Copyright (C) 2017-2018 Laurent Destailleur + * Copyright (C) 2022 Charlene Benke + * Copyright (C) 2023 Maxime Nicolas + * Copyright (C) 2023 Benjamin GREMBI * * 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 @@ -129,7 +131,11 @@ if ($action == 'presend') { if ($formmail->fromtype === 'user') { $formmail->fromid = $user->id; } - + if ($object->element == 'salary' && !empty($conf->global->INVOICE_EMAIL_SENDER)) { + $formmail->frommail = $conf->global->SINVOICE_EMAIL_SENDER; + $formmail->fromname = (!empty($conf->global->INVOICE_EMAIL_SENDER_NAME) ? $conf->global->INVOICE_EMAIL_SENDER_NAME : ''); + $formmail->fromtype = 'special'; + } if ($object->element === 'facture' && !empty($conf->global->INVOICE_EMAIL_SENDER)) { $formmail->frommail = $conf->global->INVOICE_EMAIL_SENDER; $formmail->fromname = (!empty($conf->global->INVOICE_EMAIL_SENDER_NAME) ? $conf->global->INVOICE_EMAIL_SENDER_NAME : ''); @@ -194,6 +200,10 @@ if ($action == 'presend') { $liste['contact'] = $object->getFullName($outputlangs)." <".$object->email.">"; } elseif ($object->element == 'user' || $object->element == 'member') { $liste['thirdparty'] = $object->getFullName($outputlangs)." <".$object->email.">"; + } elseif ($object->element == 'salary') { + $fuser = new User($db); + $fuser->fetch($object->fk_user); + $liste['thirdparty'] = $fuser->getFullName($outputlangs)." <".$fuser->email.">"; } else { if (!empty($object->socid) && $object->socid > 0 && !is_object($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) { $object->fetch_thirdparty(); diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 42fecf28b37..2b118d50d58 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -5,6 +5,8 @@ * Copyright (C) 2015 Charlie BENKE * Copyright (C) 2018-2022 Frédéric France * Copyright (C) 2021 Gauthier VERDOL + * Copyright (C) 2023 Maxime Nicolas + * Copyright (C) 2023 Benjamin GREMBI * * 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 @@ -148,6 +150,12 @@ if (empty($reshook)) { } $action = ''; } + // Actions to send emails + $triggersendname = 'COMPANY_SENTBYMAIL'; + $paramname = 'id'; + $mode = 'emailfromthirdparty'; + $trackid = 'thi'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; } // Link to a project @@ -382,7 +390,7 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->salaries- $object->id = $object->ref = null; if (GETPOST('amount', 'alphanohtml')) { - $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2); + $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2); } if (GETPOST('clone_label', 'alphanohtml')) { @@ -451,7 +459,6 @@ if (isModEnabled('project')) $formproject = new FormProjets($db); $title = $langs->trans('Salary')." - ".$object->ref; $help_url = ""; - llxHeader('', $title, $help_url); @@ -665,6 +672,7 @@ if ($action == 'create' && $permissiontoadd) { var fk_user = $("#fk_user").val() var url = "'.DOL_URL_ROOT.'/salaries/ajax/ajaxsalaries.php?fk_user="+fk_user; console.log("We click on link to autofill salary amount url="+url); + if (fk_user != -1) { $.get( url, @@ -704,7 +712,6 @@ if ($action == 'create' && $permissiontoadd) { print ''; } - // View mode if ($id > 0) { $head = salaries_prepare_head($object); @@ -969,11 +976,8 @@ if ($id > 0) { while ($i < $num) { $objp = $db->fetch_object($resql); - print ''; - // Date - print ''; + print ''; print ''.img_object($langs->trans("Payment"), "payment").' '.$objp->rowid.''; - // Date print ''.dol_print_date($db->jdate($objp->dp), 'dayhour', 'tzuserrel')."\n"; $labeltype = $langs->trans("PaymentType".$objp->type_code) != ("PaymentType".$objp->type_code) ? $langs->trans("PaymentType".$objp->type_code) : $objp->paiement_type; print "".$labeltype.' '.$objp->num_payment."\n"; @@ -1046,6 +1050,17 @@ if ($id > 0) { print '
'."\n"; if ($action != 'edit') { + // Dynamic send mail button + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + if (empty($user->socid)) { + $canSendMail = true; + + print dolGetButtonAction($langs->trans('SendMail'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=presend&token='.newToken().'&mode=init#formmailbeforetitle', '', $canSendMail, $params); + } + } + // Reopen if ($object->paye && $user->rights->salaries->write) { print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); @@ -1137,6 +1152,10 @@ if ($id > 0) { $trackid = 'salary'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; + + // Hook to add more things on page + $parameters = array(); + $reshook = $hookmanager->executeHooks('salaryCardTabAddMore', $parameters, $object, $action); // Note that $action and $object may have been modified by hook } // End of page