diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 3b24a0a9af4..e89f30ce60a 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -831,6 +831,13 @@ if (empty($reshook)) { foreach ($object->lines as $line) { $result = $object->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); } + } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) { + // Define vat_rate + $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0); + $remise_percent = str_replace('*', '', $remise_percent); + foreach ($object->lines as $line) { + $result = $object->updateline($line->id, $line->subprice, $line->qty, $remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + } } elseif ($action == 'addline' && $usercancreate) { // Add line // Set if we used free entry or predefined product $predef = ''; diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index b3f76eafc3c..0056716972b 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -2097,7 +2097,7 @@ if ($resql) { // Note public if (!empty($arrayfields['p.note_public']['checked'])) { print ''; - print dol_escape_htmltag($obj->note_public); + print dol_string_nohtmltag($obj->note_public); print ''; if (!$i) { $totalarray['nbfield']++; @@ -2106,7 +2106,7 @@ if ($resql) { // Note private if (!empty($arrayfields['p.note_private']['checked'])) { print ''; - print dol_escape_htmltag($obj->note_private); + print dol_string_nohtmltag($obj->note_private); print ''; if (!$i) { $totalarray['nbfield']++; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index d33ea387947..ecd647c7206 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -628,6 +628,13 @@ if (empty($reshook)) { foreach ($object->lines as $line) { $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); } + } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) { + // Define remise_percent + $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0); + $remise_percent = str_replace('*', '', $remise_percent); + foreach ($object->lines as $line) { + $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + } } elseif ($action == 'addline' && $usercancreate) { // Add a new line $langs->load('errors'); $error = 0; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 0cf7af2996e..0a13114fbbc 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -1994,6 +1994,13 @@ if (empty($reshook)) { foreach ($object->lines as $line) { $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice); } + } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) { + // Define vat_rate + $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0); + $remise_percent = str_replace('*', '', $remise_percent); + foreach ($object->lines as $line) { + $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice); + } } elseif ($action == 'addline' && $usercancreate) { // Add a new line $langs->load('errors'); $error = 0; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 9203162bd12..b3175949376 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -5221,11 +5221,11 @@ class Facture extends CommonInvoice if (!empty($recipient->email)) { $to = $recipient->email; } else { - $errormesg = "Failed to send remind to thirdparty id=".$tmpinvoice->fk_soc.". No email defined for user."; + $errormesg = "Failed to send remind to thirdparty id=".$tmpinvoice->socid.". No email defined for user."; $error++; } } else { - $errormesg = "Failed to load recipient with thirdparty id=".$tmpinvoice->fk_soc; + $errormesg = "Failed to load recipient with thirdparty id=".$tmpinvoice->socid; $error++; } diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 4c326d15974..d7e5812ac9a 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -327,29 +327,51 @@ if (!$error && $massaction == 'confirm_presend') { // TODO Set subdir to be compatible with multi levels dir trees // $subdir = get_exdir($objectobj->id, 2, 0, 0, $objectobj, $objectobj->element) $filedir = $uploaddir.'/'.$subdir.dol_sanitizeFileName($objectobj->ref); - $file = $filedir.'/'.$filename; + $filepath = $filedir.'/'.$filename; // For supplier invoices, we use the file provided by supplier, not the one we generate if ($objectobj->element == 'invoice_supplier') { $fileparams = dol_most_recent_file($uploaddir.'/'.get_exdir($objectobj->id, 2, 0, 0, $objectobj, $objectobj->element).$objectobj->ref, preg_quote($objectobj->ref, '/').'([^\-])+'); - $file = $fileparams['fullname']; + $filepath = $fileparams['fullname']; } - $mime = dol_mimetype($file); + // try to find other files generated for this object (last_main_doc) + $filename_found = ''; + $filepath_found = ''; + $file_check_list = array(); + $file_check_list[] = array( + 'name' => $filename, + 'path' => $filepath, + ); + if (!empty($conf->global->MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND) && !empty($objectobj->last_main_doc)) { + $file_check_list[] = array( + 'name' => basename($objectobj->last_main_doc), + 'path' => DOL_DATA_ROOT . '/' . $objectobj->last_main_doc, + ); + } + foreach ($file_check_list as $file_check_arr) { + if (dol_is_file($file_check_arr['path'])) { + $filename_found = $file_check_arr['name']; + $filepath_found = $file_check_arr['path']; + break; + } + } - if (dol_is_file($file)) { + if ($filepath_found) { // Create form object $attachedfilesThirdpartyObj[$thirdpartyid][$objectid] = array( - 'paths'=>array($file), - 'names'=>array($filename), - 'mimes'=>array($mime) + 'paths'=>array($filepath_found), + 'names'=>array($filename_found), + 'mimes'=>array(dol_mimetype($filepath_found)) ); } else { - $nbignored++; - $langs->load("errors"); - $resaction .= '
'.$langs->trans('ErrorCantReadFile', $file).'

'; - dol_syslog('Failed to read file: '.$file, LOG_WARNING); - continue; + $nbignored++; + $langs->load("errors"); + foreach ($file_check_list as $file_check_arr) { + $resaction .= '
'.$langs->trans('ErrorCantReadFile', $file_check_arr['path']).'

'; + dol_syslog('Failed to read file: '.$file_check_arr['path'], LOG_WARNING); + } + continue; } } diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index acb7d5b5f2a..75f35e39bec 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -7,7 +7,7 @@ * Copyright (C) 2014 Marcos García * Copyright (C) 2015 Bahfir Abbes * Copyright (C) 2016-2017 Ferran Marcet - * Copyright (C) 2019-2021 Frédéric France + * Copyright (C) 2019-2022 Frédéric France * * 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 @@ -986,6 +986,8 @@ class FormFile $out .= ''; $out .= dol_print_date($file->datea, 'dayhour'); $out .= ''; + // for share link of files + $out .= ''; if ($delallowed || $printer || $morepicto) { $out .= ''; } diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 807c643e7be..244da59b5ff 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -781,7 +781,11 @@ class FormMail extends Form } elseif ($this->withmaindocfile == -1) { $out .= ''; } - $out .= '
'; + if (!empty($conf->global->MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND)) { + $out .= '
'; + } else { + $out .= '
'; + } } if (is_numeric($this->withfile)) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 5eef1b43bec..28ec44e5f83 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8990,6 +8990,9 @@ function printCommonFooter($zone = 'private') print 'jQuery("select[name=\''.$paramkey.'\']").prop(\'required\',true);'."\n"; print 'jQuery("select[name=\''.$paramkey.'\'] option[value=\'-1\']").prop(\'value\', \'\');'."\n"; print 'jQuery("select[name=\''.$paramkey.'\'] option[value=\'0\']").prop(\'value\', \'\');'."\n"; + + // Add 'field required' class on closest td for all input elements : input, textarea and select + print 'jQuery(":input[name=\'' . $paramkey . '\']").closest("tr").find("td:first").addClass("fieldrequired");' . "\n"; } } } diff --git a/htdocs/core/tpl/objectline_title.tpl.php b/htdocs/core/tpl/objectline_title.tpl.php index e8dbec2ac77..f4f962db554 100644 --- a/htdocs/core/tpl/objectline_title.tpl.php +++ b/htdocs/core/tpl/objectline_title.tpl.php @@ -105,7 +105,24 @@ if (!empty($conf->global->PRODUCT_USE_UNITS)) { } // Reduction short -print ''.$langs->trans('ReductionShort').''; +print ''; +print $langs->trans('ReductionShort'); + +if (in_array($object->element, array('propal', 'commande', 'facture')) && $object->status == $object::STATUS_DRAFT) { + global $mysoc; + + if (empty($disableedit)) { + print 'id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickvatforalllines opacitymedium paddingleft cursorpointer"').''; + } + //print ''; + if (GETPOST('mode', 'aZ09') == 'remiseforalllines') { + print '
'; + print ' %'; + print ''; + print '
'; + } +} +print ''; // Fields for situation invoice if (isset($this->situation_cycle_ref) && $this->situation_cycle_ref) { diff --git a/htdocs/install/mysql/tables/llx_webhook_target-webhook.key.sql b/htdocs/install/mysql/tables/llx_webhook_target-webhook.key.sql new file mode 100644 index 00000000000..04a0dbb306a --- /dev/null +++ b/htdocs/install/mysql/tables/llx_webhook_target-webhook.key.sql @@ -0,0 +1,27 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 https://www.gnu.org/licenses/. + + +-- BEGIN MODULEBUILDER INDEXES +ALTER TABLE llx_webhook_target ADD INDEX idx_webhook_target_rowid (rowid); +ALTER TABLE llx_webhook_target ADD INDEX idx_webhook_target_ref (ref); +ALTER TABLE llx_webhook_target ADD CONSTRAINT llx_webhook_target_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); +ALTER TABLE llx_webhook_target ADD INDEX idx_webhook_target_status (status); +-- END MODULEBUILDER INDEXES + +--ALTER TABLE llx_webhook_target ADD UNIQUE INDEX uk_webhook_target_fieldxy(fieldx, fieldy); + +--ALTER TABLE llx_webhook_target ADD CONSTRAINT llx_webhook_target_fk_field FOREIGN KEY (fk_field) REFERENCES llx_webhook_myotherobject(rowid); + diff --git a/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql b/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql new file mode 100644 index 00000000000..1e0cc0fdbac --- /dev/null +++ b/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql @@ -0,0 +1,34 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 https://www.gnu.org/licenses/. + + +CREATE TABLE llx_webhook_target( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) NOT NULL, + label varchar(255), + description text, + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + status integer DEFAULT 0 NOT NULL, + url varchar(255) NOT NULL, + trigger_codes text NOT NULL + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index b39124c7c53..530f3b6af0e 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -621,6 +621,7 @@ MonthVeryShort11=N MonthVeryShort12=D AttachedFiles=Attached files and documents JoinMainDoc=Join main document +JoinMainDocOrLastGenerated=Send the main document or the last generated one if not found DateFormatYYYYMM=YYYY-MM DateFormatYYYYMMDD=YYYY-MM-DD DateFormatYYYYMMDDHHMM=YYYY-MM-DD HH:SS @@ -1172,4 +1173,4 @@ AddLineOnPosition=Add line on position (at the end if empty) ConfirmAllocateCommercial=Assign sales representative confirmation ConfirmAllocateCommercialQuestion=Are you sure you want to assign the %s selected record(s)? CommercialsAffected=Sales representatives affected -CommercialAffected=Sales representative affected \ No newline at end of file +CommercialAffected=Sales representative affected diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index 12778f337dd..53ff7d545b3 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -620,6 +620,7 @@ MonthVeryShort11=N MonthVeryShort12=D AttachedFiles=Fichiers et documents joints JoinMainDoc=Joindre le document principal +JoinMainDocOrLastGenerated=Joindre le document principal ou le dernier généré s'il n'a pas été trouvé DateFormatYYYYMM=YYYY-MM DateFormatYYYYMMDD=YYYY-MM-DD DateFormatYYYYMMDDHHMM=YYYY-MM-DD HH:SS diff --git a/htdocs/public/ticket/create_ticket.php b/htdocs/public/ticket/create_ticket.php index dff6a0b2484..371789edc62 100644 --- a/htdocs/public/ticket/create_ticket.php +++ b/htdocs/public/ticket/create_ticket.php @@ -264,7 +264,7 @@ if (empty($reshook) && $action == 'create_ticket' && GETPOST('save', 'alpha')) { $infos_new_ticket .= $langs->transnoentities('TicketNewEmailBodyInfosTrackUrl').'

'; $message .= $infos_new_ticket; - $message .= getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE') ? getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE') : $langs->transnoentities('TicketMessageMailSignatureText', $mysoc->name); + $message .= getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE', $langs->transnoentities('TicketMessageMailSignatureText', $mysoc->name)); $sendto = GETPOST('email', 'alpha'); diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 4621423eb02..244386a8180 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -361,6 +361,13 @@ function LoadProducts(position, issubcat) { $("#prodiv"+ishow).attr("class","wrapper2"); $("#prowatermark"+ishow).hide(); ishow++; //Next product to show after print data product + executeHooks('completeJSProductDisplay', $parameters); + print $hookmanager->resPrint; + ?> } //console.log("Hide the prowatermark for ishow="+ishow); idata++; //Next data everytime @@ -627,6 +634,15 @@ function Search2(keyCodeForEnter, moreorless) { } $("#prodiv" + i).data("rowid", data[i]['rowid']); $("#prodiv" + i).data("iscat", 0); + + executeHooks('completeJSProductDisplay', $parameters); + print $hookmanager->resPrint; + ?> + nbsearchresults++; } }).always(function (data) { diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index de780d92a64..3a55d82b8ad 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -49,6 +49,8 @@ if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) { require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; +$hookmanager->initHooks(array('takeposinvoice')); global $mysoc; @@ -168,11 +170,6 @@ if ($invoice->socid > 0) { $soc->fetch(getDolGlobalString("$constforcompanyid")); } - -/* - * Actions - */ - // Change the currency of invoice if it was modified if (!empty($conf->multicurrency->enabled) && !empty($_SESSION["takeposcustomercurrency"])) { if ($invoice->multicurrency_code != $_SESSION["takeposcustomercurrency"]) { @@ -180,730 +177,738 @@ if (!empty($conf->multicurrency->enabled) && !empty($_SESSION["takeposcustomercu } } +/* + * Actions + */ -// Action to record a payment on a TakePOS invoice -if ($action == 'valid' && $user->rights->facture->creer) { - $bankaccount = 0; - $error = 0; +$parameters=array(); +$reshook=$hookmanager->executeHooks('doActions', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - if (!empty($conf->global->TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT)) { - $bankaccount = GETPOST('accountid', 'int'); - } else { - if ($pay == 'LIQ') { - $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]}; // For backward compatibility - } elseif ($pay == "CHQ") { - $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]}; // For backward compatibility +if (empty($reshook)) { + // Action to record a payment on a TakePOS invoice + if ($action == 'valid' && $user->rights->facture->creer) { + $bankaccount = 0; + $error = 0; + + if (!empty($conf->global->TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT)) { + $bankaccount = GETPOST('accountid', 'int'); } else { - $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"]; - $bankaccount = $conf->global->$accountname; + if ($pay == 'LIQ') { + $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]}; // For backward compatibility + } elseif ($pay == "CHQ") { + $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]}; // For backward compatibility + } else { + $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"]; + $bankaccount = $conf->global->$accountname; + } } - } - if ($bankaccount <= 0 && $pay != "delayed") { - $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")); - $error++; - } + if ($bankaccount <= 0 && $pay != "delayed") { + $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")); + $error++; + } - $now = dol_now(); - $res = 0; + $now = dol_now(); + $res = 0; - $invoice = new Facture($db); - $invoice->fetch($placeid); + $invoice = new Facture($db); + $invoice->fetch($placeid); - if ($invoice->total_ttc < 0) { - $invoice->type = $invoice::TYPE_CREDIT_NOTE; + if ($invoice->total_ttc < 0) { + $invoice->type = $invoice::TYPE_CREDIT_NOTE; - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture WHERE"; - $sql .= " fk_soc = ".((int) $invoice->socid); - $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE; - $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED; - $sql .= " ORDER BY rowid DESC"; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture WHERE"; + $sql .= " fk_soc = ".((int) $invoice->socid); + $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE; + $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED; + $sql .= " ORDER BY rowid DESC"; - $resql = $db->query($sql); - if ($resql) { - $obj = $db->fetch_object($resql); - $fk_source = $obj->rowid; - if ($fk_source == null) { + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + $fk_source = $obj->rowid; + if ($fk_source == null) { + fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer")); + } + } else { fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer")); } - } else { - fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer")); - } - $invoice->fk_facture_source = $fk_source; - $invoice->update($user); - } - - //$sav_FACTURE_ADDON = ''; - //if (!empty($conf->global->TAKEPOS_ADDON)) { - // $sav_FACTURE_ADDON = $conf->global->FACTURE_ADDON; - // if ($conf->global->TAKEPOS_ADDON == "terminal") $conf->global->FACTURE_ADDON = $conf->global->{'TAKEPOS_ADDON'.$_SESSION["takeposterminal"]}; - // else $conf->global->FACTURE_ADDON = $conf->global->TAKEPOS_ADDON; - //} - - $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; - if ($error) { - dol_htmloutput_errors($errormsg, null, 1); - } elseif ($invoice->statut != Facture::STATUS_DRAFT) { - //If invoice is validated but it is not fully paid is not error and make the payment - if ($invoice->getRemainToPay() > 0) { - $res = 1; - } else { - dol_syslog("Sale already validated"); - dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1); - } - } elseif (count($invoice->lines) == 0) { - $error++; - dol_syslog('Sale without lines'); - dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1); - } elseif (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") { - $savconst = $conf->global->STOCK_CALCULATE_ON_BILL; - $conf->global->STOCK_CALCULATE_ON_BILL = 1; - - $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; - dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey); - $batch_rule = 0; - if (!empty($conf->productbatch->enabled) && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) { - require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php'; - $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST; - } - $res = $invoice->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule); - - $conf->global->STOCK_CALCULATE_ON_BILL = $savconst; - } else { - $res = $invoice->validate($user); - if ($res < 0) { - $error++; - dol_htmloutput_errors($invoice->error, $invoice->errors, 1); - } - } - - // Restore save values - //if (!empty($sav_FACTURE_ADDON)) - //{ - // $conf->global->FACTURE_ADDON = $sav_FACTURE_ADDON; - //} - - // Add the payment - if (!$error && $res >= 0) { - $remaintopay = $invoice->getRemainToPay(); - if ($remaintopay > 0) { - $payment = new Paiement($db); - $payment->datepaye = $now; - $payment->fk_account = $bankaccount; - $payment->amounts[$invoice->id] = $amountofpayment; - if ($pay == 'LIQ') { - $payment->pos_change = price2num(GETPOST('excess', 'alpha')); - } - - // If user has not used change control, add total invoice payment - // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay - if ($amountofpayment == 0 || $amountofpayment > $remaintopay) { - $payment->amounts[$invoice->id] = $remaintopay; - } - - $payment->paiementid = $paiementid; - $payment->num_payment = $invoice->ref; - - if ($pay != "delayed") { - $payment->create($user); - $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); - $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded - } + $invoice->fk_facture_source = $fk_source; + $invoice->update($user); } - if ($remaintopay == 0) { - dol_syslog("Invoice is paid, so we set it to status Paid"); - $result = $invoice->setPaid($user); - if ($result > 0) { - $invoice->paye = 1; - } - // set payment method - $invoice->setPaymentMethods($paiementid); - } else { - dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay); - } - } else { - dol_htmloutput_errors($invoice->error, $invoice->errors, 1); - } -} + //$sav_FACTURE_ADDON = ''; + //if (!empty($conf->global->TAKEPOS_ADDON)) { + // $sav_FACTURE_ADDON = $conf->global->FACTURE_ADDON; + // if ($conf->global->TAKEPOS_ADDON == "terminal") $conf->global->FACTURE_ADDON = $conf->global->{'TAKEPOS_ADDON'.$_SESSION["takeposterminal"]}; + // else $conf->global->FACTURE_ADDON = $conf->global->TAKEPOS_ADDON; + //} -if ($action == 'creditnote' && $user->rights->facture->creer) { - $creditnote = new Facture($db); - $creditnote->socid = $invoice->socid; - $creditnote->date = dol_now(); - $creditnote->module_source = 'takepos'; - $creditnote->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ; - $creditnote->type = Facture::TYPE_CREDIT_NOTE; - $creditnote->fk_facture_source = $placeid; - $creditnote->remise_absolue = $invoice->remise_absolue; - $creditnote->remise_percent = $invoice->remise_percent; - $creditnote->create($user); - - foreach ($invoice->lines as $line) { - // Extrafields - if (method_exists($line, 'fetch_optionals')) { - // load extrafields - $line->fetch_optionals(); - } - // Reset fk_parent_line for no child products and special product - if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) { - $fk_parent_line = 0; - } - if ($invoice->type == Facture::TYPE_SITUATION) { - $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id - $line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from - if (!empty($invoice->tab_previous_situation_invoice)) { - // search the last standard invoice in cycle and the possible credit note between this last and invoice - // TODO Move this out of loop of $invoice->lines - $tab_jumped_credit_notes = array(); - $lineIndex = count($invoice->tab_previous_situation_invoice) - 1; - $searchPreviousInvoice = true; - while ($searchPreviousInvoice) { - if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1) { - $searchPreviousInvoice = false; // find, exit; - break; - } else { - if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) { - $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id; - } - $lineIndex--; // go to previous invoice in cycle - } - } - - $maxPrevSituationPercent = 0; - foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) { - if ($prevLine->id == $source_fk_prev_id) { - $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent); - - //$line->subprice = $line->subprice - $prevLine->subprice; - $line->total_ht = $line->total_ht - $prevLine->total_ht; - $line->total_tva = $line->total_tva - $prevLine->total_tva; - $line->total_ttc = $line->total_ttc - $prevLine->total_ttc; - $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1; - $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2; - - $line->multicurrency_subprice = $line->multicurrency_subprice - $prevLine->multicurrency_subprice; - $line->multicurrency_total_ht = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht; - $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva; - $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc; - } - } - - // prorata - $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent; - - //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'
'; - - // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta) - $maxPrevSituationPercent = 0; - foreach ($tab_jumped_credit_notes as $index => $creditnoteid) { - foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine) { - if ($prevLine->fk_prev_id == $source_fk_prev_id) { - $maxPrevSituationPercent = $prevLine->situation_percent; - - $line->total_ht -= $prevLine->total_ht; - $line->total_tva -= $prevLine->total_tva; - $line->total_ttc -= $prevLine->total_ttc; - $line->total_localtax1 -= $prevLine->total_localtax1; - $line->total_localtax2 -= $prevLine->total_localtax2; - - $line->multicurrency_subprice -= $prevLine->multicurrency_subprice; - $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht; - $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva; - $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc; - } - } - } - - // prorata - $line->situation_percent += $maxPrevSituationPercent; - - //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'
'; - } - } - - $line->fk_facture = $creditnote->id; - $line->fk_parent_line = $fk_parent_line; - - $line->subprice = -$line->subprice; // invert price for object - $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here - $line->total_ht = -$line->total_ht; - $line->total_tva = -$line->total_tva; - $line->total_ttc = -$line->total_ttc; - $line->total_localtax1 = -$line->total_localtax1; - $line->total_localtax2 = -$line->total_localtax2; - - $line->multicurrency_subprice = -$line->multicurrency_subprice; - $line->multicurrency_total_ht = -$line->multicurrency_total_ht; - $line->multicurrency_total_tva = -$line->multicurrency_total_tva; - $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc; - - $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked - - $creditnote->lines[] = $line; // insert new line in current object - - // Defined the new fk_parent_line - if ($result > 0 && $line->product_type == 9) { - $fk_parent_line = $result; - } - } - $creditnote->update_price(1); - - $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; - if (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") { - $savconst = $conf->global->STOCK_CALCULATE_ON_BILL; - $conf->global->STOCK_CALCULATE_ON_BILL = 1; - $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; - dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey); - $batch_rule = 0; - if (!empty($conf->productbatch->enabled) && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) { - require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php'; - $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST; - } - $res = $creditnote->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule); - $conf->global->STOCK_CALCULATE_ON_BILL = $savconst; - } else { - $res = $creditnote->validate($user); - } -} - -if ($action == 'history' || $action == 'creditnote') { - if ($action == 'creditnote') { - $placeid = $creditnote->id; - } else { - $placeid = (int) GETPOST('placeid', 'int'); - } - $invoice = new Facture($db); - $invoice->fetch($placeid); -} - -if (($action == "addline" || $action == "freezone") && $placeid == 0) { - $invoice->socid = getDolGlobalString("$constforcompanyid"); - $invoice->date = dol_now(); - $invoice->module_source = 'takepos'; - $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ; - $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity; - - if ($invoice->socid <= 0) { - $langs->load('errors'); - dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1); - } else { - $placeid = $invoice->create($user); - if ($placeid < 0) { - dol_htmloutput_errors($invoice->error, $invoice->errors, 1); - } - $sql = "UPDATE ".MAIN_DB_PREFIX."facture set ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' where rowid = ".((int) $placeid); - $db->query($sql); - } -} - -if ($action == "addline") { - $prod = new Product($db); - $prod->fetch($idproduct); - - $customer = new Societe($db); - $customer->fetch($invoice->socid); - - $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); - - $qty = GETPOSTISSET('qty') ? GETPOST('qty', 'int') : 1; - $price = $datapriceofproduct['pu_ht']; - $price_ttc = $datapriceofproduct['pu_ttc']; - //$price_min = $datapriceofproduct['price_min']; - $price_base_type = $datapriceofproduct['price_base_type']; - $tva_tx = $datapriceofproduct['tva_tx']; - $tva_npr = $datapriceofproduct['tva_npr']; - - // Local Taxes - $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr); - $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr); - - if (!empty($conf->global->TAKEPOS_SUPPLEMENTS)) { - require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; - $cat = new Categorie($db); - $categories = $cat->containing($idproduct, 'product'); - $found = (array_search($conf->global->TAKEPOS_SUPPLEMENTS_CATEGORY, array_column($categories, 'id'))); - if ($found !== false) { // If this product is a supplement - $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid=$selectedline"; - $resql = $db->query($sql); - $row = $db->fetch_array($resql); - if ($row[0] == null) { - $parent_line = $selectedline; + $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; + if ($error) { + dol_htmloutput_errors($errormsg, null, 1); + } elseif ($invoice->statut != Facture::STATUS_DRAFT) { + //If invoice is validated but it is not fully paid is not error and make the payment + if ($invoice->getRemainToPay() > 0) { + $res = 1; } else { - $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product + dol_syslog("Sale already validated"); + dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1); + } + } elseif (count($invoice->lines) == 0) { + $error++; + dol_syslog('Sale without lines'); + dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1); + } elseif (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") { + $savconst = $conf->global->STOCK_CALCULATE_ON_BILL; + $conf->global->STOCK_CALCULATE_ON_BILL = 1; + + $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; + dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey); + $batch_rule = 0; + if (!empty($conf->productbatch->enabled) && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) { + require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php'; + $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST; + } + $res = $invoice->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule); + + $conf->global->STOCK_CALCULATE_ON_BILL = $savconst; + } else { + $res = $invoice->validate($user); + if ($res < 0) { + $error++; + dol_htmloutput_errors($invoice->error, $invoice->errors, 1); } } - } - $idoflineadded = 0; - // Group if enabled. Skip group if line already sent to the printer - if (!empty($conf->global->TAKEPOS_GROUP_SAME_PRODUCT) && $line->special_code != "4") { - foreach ($invoice->lines as $line) { - if ($line->product_ref == $prod->ref) { - if ($line->special_code==4) continue; // If this line is sended to printer create new line - $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + $qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); - if ($result < 0) { - dol_htmloutput_errors($invoice->error, $invoice->errors, 1); - } else { - $idoflineadded = $line->id; + // Restore save values + //if (!empty($sav_FACTURE_ADDON)) + //{ + // $conf->global->FACTURE_ADDON = $sav_FACTURE_ADDON; + //} + + // Add the payment + if (!$error && $res >= 0) { + $remaintopay = $invoice->getRemainToPay(); + if ($remaintopay > 0) { + $payment = new Paiement($db); + $payment->datepaye = $now; + $payment->fk_account = $bankaccount; + $payment->amounts[$invoice->id] = $amountofpayment; + if ($pay == 'LIQ') { + $payment->pos_change = price2num(GETPOST('excess', 'alpha')); } - break; + + // If user has not used change control, add total invoice payment + // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay + if ($amountofpayment == 0 || $amountofpayment > $remaintopay) { + $payment->amounts[$invoice->id] = $remaintopay; + } + + $payment->paiementid = $paiementid; + $payment->num_payment = $invoice->ref; + + if ($pay != "delayed") { + $payment->create($user); + $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); + $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded + } + } + + if ($remaintopay == 0) { + dol_syslog("Invoice is paid, so we set it to status Paid"); + $result = $invoice->setPaid($user); + if ($result > 0) { + $invoice->paye = 1; + } + // set payment method + $invoice->setPaymentMethods($paiementid); + } else { + dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay); + } + } else { + dol_htmloutput_errors($invoice->error, $invoice->errors, 1); + } + } + + if ($action == 'creditnote' && $user->rights->facture->creer) { + $creditnote = new Facture($db); + $creditnote->socid = $invoice->socid; + $creditnote->date = dol_now(); + $creditnote->module_source = 'takepos'; + $creditnote->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ; + $creditnote->type = Facture::TYPE_CREDIT_NOTE; + $creditnote->fk_facture_source = $placeid; + $creditnote->remise_absolue = $invoice->remise_absolue; + $creditnote->remise_percent = $invoice->remise_percent; + $creditnote->create($user); + + foreach ($invoice->lines as $line) { + // Extrafields + if (method_exists($line, 'fetch_optionals')) { + // load extrafields + $line->fetch_optionals(); + } + // Reset fk_parent_line for no child products and special product + if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) { + $fk_parent_line = 0; + } + if ($invoice->type == Facture::TYPE_SITUATION) { + $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id + $line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from + if (!empty($invoice->tab_previous_situation_invoice)) { + // search the last standard invoice in cycle and the possible credit note between this last and invoice + // TODO Move this out of loop of $invoice->lines + $tab_jumped_credit_notes = array(); + $lineIndex = count($invoice->tab_previous_situation_invoice) - 1; + $searchPreviousInvoice = true; + while ($searchPreviousInvoice) { + if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1) { + $searchPreviousInvoice = false; // find, exit; + break; + } else { + if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) { + $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id; + } + $lineIndex--; // go to previous invoice in cycle + } + } + + $maxPrevSituationPercent = 0; + foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) { + if ($prevLine->id == $source_fk_prev_id) { + $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent); + + //$line->subprice = $line->subprice - $prevLine->subprice; + $line->total_ht = $line->total_ht - $prevLine->total_ht; + $line->total_tva = $line->total_tva - $prevLine->total_tva; + $line->total_ttc = $line->total_ttc - $prevLine->total_ttc; + $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1; + $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2; + + $line->multicurrency_subprice = $line->multicurrency_subprice - $prevLine->multicurrency_subprice; + $line->multicurrency_total_ht = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht; + $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva; + $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc; + } + } + + // prorata + $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent; + + //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'
'; + + // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta) + $maxPrevSituationPercent = 0; + foreach ($tab_jumped_credit_notes as $index => $creditnoteid) { + foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine) { + if ($prevLine->fk_prev_id == $source_fk_prev_id) { + $maxPrevSituationPercent = $prevLine->situation_percent; + + $line->total_ht -= $prevLine->total_ht; + $line->total_tva -= $prevLine->total_tva; + $line->total_ttc -= $prevLine->total_ttc; + $line->total_localtax1 -= $prevLine->total_localtax1; + $line->total_localtax2 -= $prevLine->total_localtax2; + + $line->multicurrency_subprice -= $prevLine->multicurrency_subprice; + $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht; + $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva; + $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc; + } + } + } + + // prorata + $line->situation_percent += $maxPrevSituationPercent; + + //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'
'; + } + } + + $line->fk_facture = $creditnote->id; + $line->fk_parent_line = $fk_parent_line; + + $line->subprice = -$line->subprice; // invert price for object + $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here + $line->total_ht = -$line->total_ht; + $line->total_tva = -$line->total_tva; + $line->total_ttc = -$line->total_ttc; + $line->total_localtax1 = -$line->total_localtax1; + $line->total_localtax2 = -$line->total_localtax2; + + $line->multicurrency_subprice = -$line->multicurrency_subprice; + $line->multicurrency_total_ht = -$line->multicurrency_total_ht; + $line->multicurrency_total_tva = -$line->multicurrency_total_tva; + $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc; + + $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked + + $creditnote->lines[] = $line; // insert new line in current object + + // Defined the new fk_parent_line + if ($result > 0 && $line->product_type == 9) { + $fk_parent_line = $result; } } - } - if ($idoflineadded <= 0) { - $invoice->fetch_thirdparty(); - $idoflineadded = $invoice->addline($prod->description, $price, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', 0, 100, '', null, 0); - if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { - $CUSTOMER_DISPLAY_line1 = $prod->label; - $CUSTOMER_DISPLAY_line2 = price($price_ttc); + $creditnote->update_price(1); + + $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; + if (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") { + $savconst = $conf->global->STOCK_CALCULATE_ON_BILL; + $conf->global->STOCK_CALCULATE_ON_BILL = 1; + $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; + dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey); + $batch_rule = 0; + if (!empty($conf->productbatch->enabled) && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) { + require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php'; + $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST; + } + $res = $creditnote->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule); + $conf->global->STOCK_CALCULATE_ON_BILL = $savconst; + } else { + $res = $creditnote->validate($user); } } - $invoice->fetch($placeid); -} - -if ($action == "freezone") { - $customer = new Societe($db); - $customer->fetch($invoice->socid); - - $tva_tx = GETPOST('tva_tx', 'alpha'); - if ($tva_tx != '') { - if (!preg_match('/\((.*)\)/', $tva_tx)) { - $tva_tx = price2num($tva_tx); + if ($action == 'history' || $action == 'creditnote') { + if ($action == 'creditnote') { + $placeid = $creditnote->id; + } else { + $placeid = (int) GETPOST('placeid', 'int'); } - } else { - $tva_tx = get_default_tva($mysoc, $customer); - } - - // Local Taxes - $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr); - $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr); - - $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', 'TTC', $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0); - $invoice->fetch($placeid); -} - -if ($action == "addnote") { - $desc = GETPOST('addnote', 'alpha'); - if ($idline==0) { - $invoice->update_note($desc, '_public'); - } else foreach ($invoice->lines as $line) { - if ($line->id == $idline) { - $result = $invoice->updateline($line->id, $desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); - } - } - $invoice->fetch($placeid); -} - -if ($action == "deleteline") { - if ($idline > 0 and $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected. - $invoice->deleteline($idline); - $invoice->fetch($placeid); - } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line. - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC"; - $resql = $db->query($sql); - $row = $db->fetch_array($resql); - $deletelineid = $row[0]; - $invoice->deleteline($deletelineid); + $invoice = new Facture($db); $invoice->fetch($placeid); } - if (count($invoice->lines) == 0) { - $invoice->delete($user); - header("Location: ".DOL_URL_ROOT."/takepos/invoice.php"); - exit; + + if (($action == "addline" || $action == "freezone") && $placeid == 0) { + $invoice->socid = getDolGlobalString("$constforcompanyid"); + $invoice->date = dol_now(); + $invoice->module_source = 'takepos'; + $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ; + $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity; + + if ($invoice->socid <= 0) { + $langs->load('errors'); + dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1); + } else { + $placeid = $invoice->create($user); + if ($placeid < 0) { + dol_htmloutput_errors($invoice->error, $invoice->errors, 1); + } + $sql = "UPDATE ".MAIN_DB_PREFIX."facture set ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' where rowid = ".((int) $placeid); + $db->query($sql); + } } -} -// Action to delete or discard an invoice -if ($action == "delete") { - // $placeid is the invoice id (it differs from place) and is defined if the place is set and the ref of invoice is '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')', so the fetch at begining of page works. - if ($placeid > 0) { - $result = $invoice->fetch($placeid); + if ($action == "addline") { + $prod = new Product($db); + $prod->fetch($idproduct); - if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) { - $db->begin(); + $customer = new Societe($db); + $customer->fetch($invoice->socid); - // We delete the lines - $resdeletelines = 1; + $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); + + $qty = GETPOSTISSET('qty') ? GETPOST('qty', 'int') : 1; + $price = $datapriceofproduct['pu_ht']; + $price_ttc = $datapriceofproduct['pu_ttc']; + //$price_min = $datapriceofproduct['price_min']; + $price_base_type = $datapriceofproduct['price_base_type']; + $tva_tx = $datapriceofproduct['tva_tx']; + $tva_npr = $datapriceofproduct['tva_npr']; + + // Local Taxes + $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr); + $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr); + + if (!empty($conf->global->TAKEPOS_SUPPLEMENTS)) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $cat = new Categorie($db); + $categories = $cat->containing($idproduct, 'product'); + $found = (array_search($conf->global->TAKEPOS_SUPPLEMENTS_CATEGORY, array_column($categories, 'id'))); + if ($found !== false) { // If this product is a supplement + $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid=$selectedline"; + $resql = $db->query($sql); + $row = $db->fetch_array($resql); + if ($row[0] == null) { + $parent_line = $selectedline; + } else { + $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product + } + } + } + + $idoflineadded = 0; + // Group if enabled. Skip group if line already sent to the printer + if (!empty($conf->global->TAKEPOS_GROUP_SAME_PRODUCT) && $line->special_code != "4") { foreach ($invoice->lines as $line) { - $tmpres = $invoice->deleteline($line->id); - if ($tmpres < 0) { - $resdeletelines = 0; + if ($line->product_ref == $prod->ref) { + if ($line->special_code==4) continue; // If this line is sended to printer create new line + $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + $qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + if ($result < 0) { + dol_htmloutput_errors($invoice->error, $invoice->errors, 1); + } else { + $idoflineadded = $line->id; + } break; } } - - $sql = "UPDATE ".MAIN_DB_PREFIX."facture"; - $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"]; - $sql .= " SET fk_soc = ".((int) $conf->global->$varforconst).", "; - $sql .= " datec = '".$db->idate(dol_now())."'"; - $sql .= " WHERE ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'"; - $resql1 = $db->query($sql); - - if ($resdeletelines && $resql1) { - $db->commit(); - } else { - $db->rollback(); + } + if ($idoflineadded <= 0) { + $invoice->fetch_thirdparty(); + $idoflineadded = $invoice->addline($prod->description, $price, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', 0, 100, '', null, 0); + if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { + $CUSTOMER_DISPLAY_line1 = $prod->label; + $CUSTOMER_DISPLAY_line2 = price($price_ttc); } + } + $invoice->fetch($placeid); + } + + if ($action == "freezone") { + $customer = new Societe($db); + $customer->fetch($invoice->socid); + + $tva_tx = GETPOST('tva_tx', 'alpha'); + if ($tva_tx != '') { + if (!preg_match('/\((.*)\)/', $tva_tx)) { + $tva_tx = price2num($tva_tx); + } + } else { + $tva_tx = get_default_tva($mysoc, $customer); + } + + // Local Taxes + $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr); + $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr); + + $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', 'TTC', $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0); + $invoice->fetch($placeid); + } + + if ($action == "addnote") { + $desc = GETPOST('addnote', 'alpha'); + if ($idline==0) { + $invoice->update_note($desc, '_public'); + } else foreach ($invoice->lines as $line) { + if ($line->id == $idline) { + $result = $invoice->updateline($line->id, $desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + } + } + $invoice->fetch($placeid); + } + + if ($action == "deleteline") { + if ($idline > 0 and $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected. + $invoice->deleteline($idline); + $invoice->fetch($placeid); + } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line. + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC"; + $resql = $db->query($sql); + $row = $db->fetch_array($resql); + $deletelineid = $row[0]; + $invoice->deleteline($deletelineid); $invoice->fetch($placeid); } + if (count($invoice->lines) == 0) { + $invoice->delete($user); + header("Location: ".DOL_URL_ROOT."/takepos/invoice.php"); + exit; + } } -} -if ($action == "updateqty") { - foreach ($invoice->lines as $line) { - if ($line->id == $idline) { - if (!$user->rights->takepos->editlines || (!$user->rights->takepos->editorderedlines && $line->special_code == "4")) { - dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1); - } else { - $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $number, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + // Action to delete or discard an invoice + if ($action == "delete") { + // $placeid is the invoice id (it differs from place) and is defined if the place is set and the ref of invoice is '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')', so the fetch at begining of page works. + if ($placeid > 0) { + $result = $invoice->fetch($placeid); + + if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) { + $db->begin(); + + // We delete the lines + $resdeletelines = 1; + foreach ($invoice->lines as $line) { + $tmpres = $invoice->deleteline($line->id); + if ($tmpres < 0) { + $resdeletelines = 0; + break; + } + } + + $sql = "UPDATE ".MAIN_DB_PREFIX."facture"; + $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"]; + $sql .= " SET fk_soc = ".((int) $conf->global->$varforconst).", "; + $sql .= " datec = '".$db->idate(dol_now())."'"; + $sql .= " WHERE ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'"; + $resql1 = $db->query($sql); + + if ($resdeletelines && $resql1) { + $db->commit(); + } else { + $db->rollback(); + } + + $invoice->fetch($placeid); } } } - $invoice->fetch($placeid); -} - -if ($action == "updateprice") { - $customer = new Societe($db); - $customer->fetch($invoice->socid); - - foreach ($invoice->lines as $line) { - if ($line->id == $idline) { - $prod = new Product($db); - $prod->fetch($line->fk_product); - $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); - $price_min = $datapriceofproduct['price_min']; - $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)); - $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU'); - //Check min price - if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) { - echo $langs->trans("CantBeLessThanMinPrice"); - } else { - if (empty($user->rights->takepos->editlines) || (empty($user->rights->takepos->editorderedlines) && $line->special_code == "4")) { + if ($action == "updateqty") { + foreach ($invoice->lines as $line) { + if ($line->id == $idline) { + if (!$user->rights->takepos->editlines || (!$user->rights->takepos->editorderedlines && $line->special_code == "4")) { dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1); - } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) { - $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); } else { - $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'TTC', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $number, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); } } } + + $invoice->fetch($placeid); } - // Reload data - $invoice->fetch($placeid); -} + if ($action == "updateprice") { + $customer = new Societe($db); + $customer->fetch($invoice->socid); -if ($action == "updatereduction") { - $customer = new Societe($db); - $customer->fetch($invoice->socid); - - foreach ($invoice->lines as $line) { - if ($line->id == $idline) { - dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%'); - - $prod = new Product($db); - $prod->fetch($line->fk_product); - - $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); - $price_min = $datapriceofproduct['price_min']; - $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)); - - $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU'); - - // Check min price - if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) { - echo $langs->trans("CantBeLessThanMinPrice"); - } else { - if (empty($user->rights->takepos->editlines) || (empty($user->rights->takepos->editorderedlines) && $line->special_code == "4")) { - dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1); + foreach ($invoice->lines as $line) { + if ($line->id == $idline) { + $prod = new Product($db); + $prod->fetch($line->fk_product); + $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); + $price_min = $datapriceofproduct['price_min']; + $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)); + $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU'); + //Check min price + if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) { + echo $langs->trans("CantBeLessThanMinPrice"); } else { - $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + if (empty($user->rights->takepos->editlines) || (empty($user->rights->takepos->editorderedlines) && $line->special_code == "4")) { + dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1); + } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) { + $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + } else { + $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'TTC', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + } } } } + + // Reload data + $invoice->fetch($placeid); } - // Reload data - $invoice->fetch($placeid); -} elseif ($action == 'update_reduction_global') { - foreach ($invoice->lines as $line) { - $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); - } + if ($action == "updatereduction") { + $customer = new Societe($db); + $customer->fetch($invoice->socid); - $invoice->fetch($placeid); -} + foreach ($invoice->lines as $line) { + if ($line->id == $idline) { + dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%'); -if ($action == "order" and $placeid != 0) { - include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; - if ($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") { - require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php'; - $printer = new dolReceiptPrinter($db); - } + $prod = new Product($db); + $prod->fetch($line->fk_product); - $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place); - $resql = $db->query($sql); - $row = $db->fetch_object($resql); - $headerorder = '
'.$langs->trans('Place').' '.$row->label.'
'; - $footerorder = '
'.$langs->trans("Label").''.$langs->trans("Qty").'
'.dol_print_date(dol_now(), 'dayhour').'
'; - $order_receipt_printer1 = ""; - $order_receipt_printer2 = ""; - $order_receipt_printer3 = ""; - $catsprinter1 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_1); - $catsprinter2 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_2); - $catsprinter3 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_3); - $linestoprint = 0; - foreach ($invoice->lines as $line) { - if ($line->special_code == "4") { - continue; + $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0); + $price_min = $datapriceofproduct['price_min']; + $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)); + + $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU'); + + // Check min price + if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) { + echo $langs->trans("CantBeLessThanMinPrice"); + } else { + if (empty($user->rights->takepos->editlines) || (empty($user->rights->takepos->editorderedlines) && $line->special_code == "4")) { + dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1); + } else { + $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); + } + } + } } - $c = new Categorie($db); - $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id'); - $result = array_intersect($catsprinter1, $existing); - $count = count($result); - if (!$line->fk_product) { - $count++; // Print Free-text item (Unassigned printer) to Printer 1 + + // Reload data + $invoice->fetch($placeid); + } elseif ($action == 'update_reduction_global') { + foreach ($invoice->lines as $line) { + $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit); } - if ($count > 0) { - $linestoprint++; - $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1 - $db->query($sql); - $order_receipt_printer1 .= ''; - if ($line->fk_product) { - $order_receipt_printer1 .= $line->product_label; + + $invoice->fetch($placeid); + } + + if ($action == "order" and $placeid != 0) { + include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + if ($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") { + require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php'; + $printer = new dolReceiptPrinter($db); + } + + $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place); + $resql = $db->query($sql); + $row = $db->fetch_object($resql); + $headerorder = '
'.$langs->trans('Place').' '.$row->label.'
'; + $footerorder = '
'.$langs->trans("Label").''.$langs->trans("Qty").'
'.dol_print_date(dol_now(), 'dayhour').'
'; + $order_receipt_printer1 = ""; + $order_receipt_printer2 = ""; + $order_receipt_printer3 = ""; + $catsprinter1 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_1); + $catsprinter2 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_2); + $catsprinter3 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_3); + $linestoprint = 0; + foreach ($invoice->lines as $line) { + if ($line->special_code == "4") { + continue; + } + $c = new Categorie($db); + $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id'); + $result = array_intersect($catsprinter1, $existing); + $count = count($result); + if (!$line->fk_product) { + $count++; // Print Free-text item (Unassigned printer) to Printer 1 + } + if ($count > 0) { + $linestoprint++; + $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1 + $db->query($sql); + $order_receipt_printer1 .= ''; + if ($line->fk_product) { + $order_receipt_printer1 .= $line->product_label; + } else { + $order_receipt_printer1 .= $line->description; + } + $order_receipt_printer1 .= ''.$line->qty; + if (!empty($line->array_options['options_order_notes'])) { + $order_receipt_printer1 .= "
(".$line->array_options['options_order_notes'].")"; + } + $order_receipt_printer1 .= ''; + } + } + if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) { + $invoice->fetch($placeid); //Reload object before send to printer + $printer->orderprinter = 1; + echo ""; + } + $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed + $db->query($sql); + $invoice->fetch($placeid); //Reload object after set lines as printed + $linestoprint = 0; + + foreach ($invoice->lines as $line) { + if ($line->special_code == "4") { + continue; + } + $c = new Categorie($db); + $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id'); + $result = array_intersect($catsprinter2, $existing); + $count = count($result); + if ($count > 0) { + $linestoprint++; + $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2 + $db->query($sql); + $order_receipt_printer2 .= ''.$line->product_label.''.$line->qty; + if (!empty($line->array_options['options_order_notes'])) { + $order_receipt_printer2 .= "
(".$line->array_options['options_order_notes'].")"; + } + $order_receipt_printer2 .= ''; + } + } + if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) { + $invoice->fetch($placeid); //Reload object before send to printer + $printer->orderprinter = 2; + echo ""; + } + $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed + $db->query($sql); + $invoice->fetch($placeid); //Reload object after set lines as printed + $linestoprint = 0; + + foreach ($invoice->lines as $line) { + if ($line->special_code == "4") { + continue; + } + $c = new Categorie($db); + $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id'); + $result = array_intersect($catsprinter3, $existing); + $count = count($result); + if ($count > 0) { + $linestoprint++; + $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3 + $db->query($sql); + $order_receipt_printer3 .= ''.$line->product_label.''.$line->qty; + if (!empty($line->array_options['options_order_notes'])) { + $order_receipt_printer3 .= "
(".$line->array_options['options_order_notes'].")"; + } + $order_receipt_printer3 .= ''; + } + } + if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) { + $invoice->fetch($placeid); //Reload object before send to printer + $printer->orderprinter = 3; + echo ""; + } + $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed + $db->query($sql); + $invoice->fetch($placeid); //Reload object after set lines as printed + } + + $sectionwithinvoicelink = ''; + if ($action == "valid" || $action == "history" || $action == 'creditnote') { + $sectionwithinvoicelink .= ''."\n"; + $sectionwithinvoicelink .= ''; + $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - "; + $remaintopay = $invoice->getRemainToPay(); + if ($remaintopay > 0) { + $sectionwithinvoicelink .= $langs->trans('RemainToPay').': '.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).''; + } else { + if ($invoice->paye) { + $sectionwithinvoicelink .= ''.$langs->trans("Paid").''; } else { - $order_receipt_printer1 .= $line->description; + $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated'); } - $order_receipt_printer1 .= ''.$line->qty; - if (!empty($line->array_options['options_order_notes'])) { - $order_receipt_printer1 .= "
(".$line->array_options['options_order_notes'].")"; + } + $sectionwithinvoicelink .= '

'; + if (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") { + if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) { + $sectionwithinvoicelink .= ' '; + } else { + $sectionwithinvoicelink .= ' '; } - $order_receipt_printer1 .= ''; - } - } - if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) { - $invoice->fetch($placeid); //Reload object before send to printer - $printer->orderprinter = 1; - echo ""; - } - $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed - $db->query($sql); - $invoice->fetch($placeid); //Reload object after set lines as printed - $linestoprint = 0; - - foreach ($invoice->lines as $line) { - if ($line->special_code == "4") { - continue; - } - $c = new Categorie($db); - $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id'); - $result = array_intersect($catsprinter2, $existing); - $count = count($result); - if ($count > 0) { - $linestoprint++; - $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2 - $db->query($sql); - $order_receipt_printer2 .= ''.$line->product_label.''.$line->qty; - if (!empty($line->array_options['options_order_notes'])) { - $order_receipt_printer2 .= "
(".$line->array_options['options_order_notes'].")"; - } - $order_receipt_printer2 .= ''; - } - } - if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) { - $invoice->fetch($placeid); //Reload object before send to printer - $printer->orderprinter = 2; - echo ""; - } - $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed - $db->query($sql); - $invoice->fetch($placeid); //Reload object after set lines as printed - $linestoprint = 0; - - foreach ($invoice->lines as $line) { - if ($line->special_code == "4") { - continue; - } - $c = new Categorie($db); - $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id'); - $result = array_intersect($catsprinter3, $existing); - $count = count($result); - if ($count > 0) { - $linestoprint++; - $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3 - $db->query($sql); - $order_receipt_printer3 .= ''.$line->product_label.''.$line->qty; - if (!empty($line->array_options['options_order_notes'])) { - $order_receipt_printer3 .= "
(".$line->array_options['options_order_notes'].")"; - } - $order_receipt_printer3 .= ''; - } - } - if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) { - $invoice->fetch($placeid); //Reload object before send to printer - $printer->orderprinter = 3; - echo ""; - } - $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed - $db->query($sql); - $invoice->fetch($placeid); //Reload object after set lines as printed -} - -$sectionwithinvoicelink = ''; -if ($action == "valid" || $action == "history" || $action == 'creditnote') { - $sectionwithinvoicelink .= ''."\n"; - $sectionwithinvoicelink .= ''; - $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - "; - $remaintopay = $invoice->getRemainToPay(); - if ($remaintopay > 0) { - $sectionwithinvoicelink .= $langs->trans('RemainToPay').': '.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).''; - } else { - if ($invoice->paye) { - $sectionwithinvoicelink .= ''.$langs->trans("Paid").''; + } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") { + $sectionwithinvoicelink .= ' '; } else { - $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated'); + $sectionwithinvoicelink .= ' '; + if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) { + $sectionwithinvoicelink .= ' '; + } + if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) { + $sectionwithinvoicelink .= ' '; + } } - } - $sectionwithinvoicelink .= '
'; - if (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") { - if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) { - $sectionwithinvoicelink .= ' '; - } else { - $sectionwithinvoicelink .= ' '; + if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && $conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE > 0) { + $sectionwithinvoicelink .= ' '; } - } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") { - $sectionwithinvoicelink .= ' '; - } else { - $sectionwithinvoicelink .= ' '; - if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) { - $sectionwithinvoicelink .= ' '; - } - if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) { - $sectionwithinvoicelink .= ' '; - } - } - if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && $conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE > 0) { - $sectionwithinvoicelink .= ' '; - } - if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS')) { - $sectionwithinvoicelink .= ''; + if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS')) { + $sectionwithinvoicelink .= ''; + } } } - /* * View */