Merge branch 'develop' of github.com:Dolibarr/dolibarr into NEW_Reverse_Movement_Product_Consumption

This commit is contained in:
kevin 2022-04-08 09:51:41 +02:00
commit 68e60fe628
82 changed files with 1215 additions and 497 deletions

View File

@ -50,8 +50,8 @@ TCPDI 1.0.0 LGPL-3+ / Apache 2.0 Yes
JS libraries:
Ace 1.4.14 BSD Yes JS library to get code syntaxique coloration in a textarea.
ChartJS 3.7.1 MIT License Yes JS library for graph
jQuery 3.5.1 MIT License Yes JS library
jQuery UI 1.12.1 GPL and MIT License Yes JS library plugin UI
jQuery 3.6.0 MIT License Yes JS library
jQuery UI 1.13.1 GPL and MIT License Yes JS library plugin UI
jQuery select2 4.0.13 GPL and Apache License Yes JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css
jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups)
jQuery Colorpicker 1.1 MIT License Yes JS library for color picker for a defined list of colors

View File

@ -9,7 +9,8 @@ English Dolibarr ChangeLog
For users:
---------------
NEW: ...
NEW: PHP 8.0 compatibility
Modules

View File

@ -1,8 +1,12 @@
# File of all ISO-4217 currencies codes
# http://en.wikipedia.org/wiki/ISO_4217
# http://fx.sauder.ubc.ca/currency_table.html for symbols for 2 letter code
#
# Code,Name,Nb decimals
# https://en.wikipedia.org/wiki/ISO_4217
# https://en.wikipedia.org/wiki/Currency_symbol for symbols for 2 letter code
#
# Code, Currency Name, Nb decimals
AED,UAE Dirham,2
AFN,Afghanistan Afghani,2
ALL,Albanian Lek,2

View File

@ -505,7 +505,7 @@ if (GETPOSTISSET("search_status")) {
if ($search_type > 0) {
$membertype = new AdherentType($db);
$result = $membertype->fetch(GETPOST("type", 'int'));
$result = $membertype->fetch($search_type);
$titre .= " (".$membertype->label.")";
}
@ -767,7 +767,7 @@ if (!empty($arrayfields['d.email']['checked'])) {
}
// End of subscription date
if (!empty($arrayfields['d.datefin']['checked'])) {
print '<td class="liste_titre left">';
print '<td class="liste_titre center">';
$selectarray = array('-1'=>'', 'withoutsubscription'=>$langs->trans("WithoutSubscription"), 'uptodate'=>$langs->trans("UpToDate"), 'outofdate'=>$langs->trans("OutOfDate"));
print $form->selectarray('search_filter', $selectarray, $search_filter);
print '</td>';
@ -858,7 +858,7 @@ if (!empty($arrayfields['state.nom']['checked'])) {
print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder);
}
if (!empty($arrayfields['country.code_iso']['checked'])) {
print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "country.code_iso", "", $param, 'align="center"', $sortfield, $sortorder);
print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "country.code_iso", "", $param, '', $sortfield, $sortorder, 'center ');
}
if (!empty($arrayfields['d.phone']['checked'])) {
print_liste_field_titre($arrayfields['d.phone']['label'], $_SERVER["PHP_SELF"], 'd.phone', '', $param, '', $sortfield, $sortorder);
@ -873,7 +873,7 @@ if (!empty($arrayfields['d.email']['checked'])) {
print_liste_field_titre($arrayfields['d.email']['label'], $_SERVER["PHP_SELF"], 'd.email', '', $param, '', $sortfield, $sortorder);
}
if (!empty($arrayfields['d.datefin']['checked'])) {
print_liste_field_titre($arrayfields['d.datefin']['label'], $_SERVER["PHP_SELF"], 'd.datefin', '', $param, 'align="center"', $sortfield, $sortorder);
print_liste_field_titre($arrayfields['d.datefin']['label'], $_SERVER["PHP_SELF"], 'd.datefin', '', $param, '', $sortfield, $sortorder, 'center ');
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
@ -1110,16 +1110,14 @@ while ($i < min($num, $limit)) {
// End of subscription date
$datefin = $db->jdate($obj->datefin);
if (!empty($arrayfields['d.datefin']['checked'])) {
print '<td class="nowrap center">';
if ($datefin) {
print '<td class="nowrap center">';
print dol_print_date($datefin, 'day');
if ($memberstatic->hasDelay()) {
$textlate = ' ('.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24) >= 0 ? '+' : '').ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24).' '.$langs->trans("days").')';
print " ".img_warning($langs->trans("SubscriptionLate").$textlate);
}
print '</td>';
} else {
print '<td class="nowrap left">';
if (!empty($obj->subscription)) {
print $langs->trans("SubscriptionNotReceived");
if ($obj->statut > 0) {
@ -1128,8 +1126,8 @@ while ($i < min($num, $limit)) {
} else {
print '&nbsp;';
}
print '</td>';
}
print '</td>';
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';

View File

@ -185,31 +185,31 @@ if ($action != 'edit') {
echo '<table class="noborder centpercent">';
echo '<tr class="liste_titre">';
echo '<th>' . $langs->trans('ExpenseReportApplyTo') . '</th>';
echo '<th>' . $langs->trans('Type') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportLimitOn') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportDateStart') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportDateEnd') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportLimitAmount') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportRestrictive') . '</th>';
echo '<tr class="liste_titre headerexpensereportrules">';
echo '<th class="linecolapplyto">' . $langs->trans('ExpenseReportApplyTo') . '</th>';
echo '<th class="linecoltype">' . $langs->trans('Type') . '</th>';
echo '<th class="linecollimiton">' . $langs->trans('ExpenseReportLimitOn') . '</th>';
echo '<th class="linecoldatestart">' . $langs->trans('ExpenseReportDateStart') . '</th>';
echo '<th class="linecoldateend">' . $langs->trans('ExpenseReportDateEnd') . '</th>';
echo '<th class="linecollimitamount">' . $langs->trans('ExpenseReportLimitAmount') . '</th>';
echo '<th class="linecolrestrictive">' . $langs->trans('ExpenseReportRestrictive') . '</th>';
echo '<th>&nbsp;</th>';
echo '</tr>';
echo '<tr class="oddeven">';
echo '<td>';
echo '<div class="float">' . $form->selectarray('apply_to', $tab_apply, '', 0) . '</div>';
echo '<div id="user" class="float">' . $form->select_dolusers('', 'fk_user') . '</div>';
echo '<div id="group" class="float">' . $form->select_dolgroups('', 'fk_usergroup') . '</div>';
echo '<div class="float linecolapplyto">' . $form->selectarray('apply_to', $tab_apply, '', 0) . '</div>';
echo '<div id="user" class="float linecoluser">' . $form->select_dolusers('', 'fk_user') . '</div>';
echo '<div id="group" class="float linecolgroup">' . $form->select_dolgroups('', 'fk_usergroup') . '</div>';
echo '</td>';
echo '<td>' . $form->selectExpense('', 'fk_c_type_fees', 0, 1, 1) . '</td>';
echo '<td>' . $form->selectarray('code_expense_rules_type', $tab_rules_type, '', 0) . '</td>';
echo '<td>' . $form->selectDate(strtotime(date('Y-m-01', dol_now())), 'start', '', '', 0, '', 1, 0) . '</td>';
echo '<td>' . $form->selectDate(strtotime(date('Y-m-t', dol_now())), 'end', '', '', 0, '', 1, 0) . '</td>';
echo '<td><input type="text" value="" class="maxwidth100" name="amount" class="amount" /> ' . $conf->currency . '</td>';
echo '<td>' . $form->selectyesno('restrictive', 0, 1) . '</td>';
echo '<td class="right"><input type="submit" class="button button-add" value="' . $langs->trans('Add') . '" /></td>';
echo '<td class="linecoltype">' . $form->selectExpense('', 'fk_c_type_fees', 0, 1, 1) . '</td>';
echo '<td class="linecoltyperule">' . $form->selectarray('code_expense_rules_type', $tab_rules_type, '', 0) . '</td>';
echo '<td class="linecoldatestart">' . $form->selectDate(strtotime(date('Y-m-01', dol_now())), 'start', '', '', 0, '', 1, 0) . '</td>';
echo '<td class="linecoldateend>' . $form->selectDate(strtotime(date('Y-m-t', dol_now())), 'end', '', '', 0, '', 1, 0) . '</td>';
echo '<td class="linecolamount"><input type="text" value="" class="maxwidth100" name="amount" class="amount" /> ' . $conf->currency . '</td>';
echo '<td class="linecolrestrictive">' . $form->selectyesno('restrictive', 0, 1) . '</td>';
echo '<td class="right linecolbutton"><input type="submit" class="button button-add" value="' . $langs->trans('Add') . '" /></td>';
echo '</tr>';
echo '</table>';
@ -227,21 +227,21 @@ if ($action == 'edit') {
echo '<table class="noborder centpercent">';
echo '<tr class="liste_titre">';
echo '<th>' . $langs->trans('ExpenseReportApplyTo') . '</th>';
echo '<th>' . $langs->trans('Type') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportLimitOn') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportDateStart') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportDateEnd') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportLimitAmount') . '</th>';
echo '<th>' . $langs->trans('ExpenseReportRestrictive') . '</th>';
echo '<tr class="liste_titre expensereportrules">';
echo '<th class="linecolapplyto">' . $langs->trans('ExpenseReportApplyTo') . '</th>';
echo '<th class="linecoltype">' . $langs->trans('Type') . '</th>';
echo '<th class="linecollimiton">' . $langs->trans('ExpenseReportLimitOn') . '</th>';
echo '<th class="linecoldatestart">' . $langs->trans('ExpenseReportDateStart') . '</th>';
echo '<th class="linecoldateend">' . $langs->trans('ExpenseReportDateEnd') . '</th>';
echo '<th class="linecollimitamount">' . $langs->trans('ExpenseReportLimitAmount') . '</th>';
echo '<th class="linecolrestrictive">' . $langs->trans('ExpenseReportRestrictive') . '</th>';
echo '<th>&nbsp;</th>';
echo '</tr>';
foreach ($rules as $rule) {
echo '<tr class="oddeven">';
echo '<tr class="oddeven linetrdata" id="'.$rule->id.'">';
echo '<td>';
echo '<td class="linecolusergroup">';
if ($action == 'edit' && $object->id == $rule->id) {
$selected = ($object->is_for_all > 0) ? 'A' : ($object->fk_usergroup > 0 ? 'G' : 'U');
echo '<div class="float">' . $form->selectarray('apply_to', $tab_apply, $selected, 0) . '</div>';
@ -259,7 +259,7 @@ foreach ($rules as $rule) {
echo '</td>';
echo '<td>';
echo '<td class="linecoltype">';
if ($action == 'edit' && $object->id == $rule->id) {
echo $form->selectExpense($object->fk_c_type_fees, 'fk_c_type_fees', 0, 1, 1);
} else {
@ -278,7 +278,7 @@ foreach ($rules as $rule) {
echo '</td>';
echo '<td>';
echo '<td class="linecoltyperule">';
if ($action == 'edit' && $object->id == $rule->id) {
echo $form->selectarray('code_expense_rules_type', $tab_rules_type, $object->code_expense_rules_type, 0);
} else {
@ -287,7 +287,7 @@ foreach ($rules as $rule) {
echo '</td>';
echo '<td>';
echo '<td class="linecoldatestart">';
if ($action == 'edit' && $object->id == $rule->id) {
print $form->selectDate(strtotime(date('Y-m-d', $object->dates)), 'start', '', '', 0, '', 1, 0);
} else {
@ -296,7 +296,7 @@ foreach ($rules as $rule) {
echo '</td>';
echo '<td>';
echo '<td class="linecoldateend">';
if ($action == 'edit' && $object->id == $rule->id) {
print $form->selectDate(strtotime(date('Y-m-d', $object->datee)), 'end', '', '', 0, '', 1, 0);
} else {
@ -305,7 +305,7 @@ foreach ($rules as $rule) {
echo '</td>';
echo '<td>';
echo '<td class="linecolamount">';
if ($action == 'edit' && $object->id == $rule->id) {
echo '<input type="text" value="' . price2num($object->amount) . '" name="amount" class="amount" />' . $conf->currency;
} else {
@ -314,7 +314,7 @@ foreach ($rules as $rule) {
echo '</td>';
echo '<td>';
echo '<td class="linecolrestrictive">';
if ($action == 'edit' && $object->id == $rule->id) {
echo $form->selectyesno('restrictive', $object->restrictive, 1);
} else {

View File

@ -266,10 +266,20 @@ print '<br>';
print '<strong>$dolibarr_main_restrict_ip</strong>: ';
if (empty($dolibarr_main_restrict_ip)) {
print '<span class="opacitymedium">'.$langs->trans("None").'</span>';
print $langs->trans("None");
//print ' <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("IPsOfUsers")).')</span>';
} else {
print $dolibarr_main_restrict_ip;
}
print '<br>';
print '<strong>$dolibarr_main_restrict_os_commands</strong>: ';
if (empty($dolibarr_main_restrict_os_commands)) {
print $langs->trans("None");
} else {
print $dolibarr_main_restrict_os_commands;
}
print ' <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", 'mysqldump, mysql, pg_dump, pgrestore').')</span>';
print '<br>';
if (empty($conf->global->SECURITY_DISABLE_TEST_ON_OBFUSCATED_CONF)) {

View File

@ -1103,6 +1103,23 @@ class BOM extends CommonObject
}
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'bom_bomline'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Get Net needs by product
*

View File

@ -868,6 +868,16 @@ class ActionComm extends CommonObject
$this->event_paid = $obj->event_paid;
$this->status = $obj->status;
//email information
$this->email_msgid=$obj->email_msgid;
$this->email_from=$obj->email_from;
$this->email_sender=$obj->email_sender;
$this->email_to=$obj->email_to;
$this->email_tocc=$obj->email_tocc;
$this->email_tobcc=$obj->email_tobcc;
$this->email_subject=$obj->email_subject;
$this->errors_to=$obj->errors_to;
$this->fetch_optionals();
if ($loadresources) {
@ -1582,8 +1592,25 @@ class ActionComm extends CommonObject
if (isset($this->transparency)) {
$tooltip .= '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
}
if (!empty($this->email_msgid)) {
$langs->load("mails");
$tooltip .= '<br>';
//$tooltip .= '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
$tooltip .= '<br><b>'.$langs->trans('MailTopic').':</b> '.$this->email_subject;
$tooltip .= '<br><b>'.$langs->trans('MailFrom').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_from);
$tooltip .= '<br><b>'.$langs->trans('MailTo').':</b>, '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_to);
if (!empty($this->email_tocc)) {
$tooltip .= '<br><b>'.$langs->trans('MailCC').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
}
/* Disabled because bcc must remain by defintion not visible
if (!empty($this->email_tobcc)) {
$tooltip .= '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
} */
}
if (!empty($this->note_private)) {
$tooltip .= '<br><b>'.$langs->trans('Note').':</b> '.(dol_textishtml($this->note_private) ? str_replace(array("\r", "\n"), "", $this->note_private) : str_replace(array("\r", "\n"), '<br>', $this->note_private));
$tooltip .= '<br><br><b>'.$langs->trans('Description').':</b><br>';
$texttoshow = dolGetFirstLineOfText($this->note_private, 10);
$tooltip .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
}
$linkclose = '';
//if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color)
@ -1594,9 +1621,8 @@ class ActionComm extends CommonObject
$label = $langs->trans("ShowAction");
$linkclose .= ' alt="'.dol_escape_htmltag($tooltip, 1).'"';
}
$linkclose .= ' title="'.dol_escape_htmltag($tooltip, 1).'"';
$linkclose .= ' title="'.dol_escape_htmltag($tooltip, 1, 0, 0, '', 1).'"';
$linkclose .= ' class="'.$classname.' classfortooltip"';
/*
$hookmanager->initHooks(array('actiondao'));
$parameters=array('id'=>$this->id);
@ -2210,6 +2236,26 @@ class ActionComm extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $dbs Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $dbs, $origin_id, $dest_id)
{
$sql = 'UPDATE ' . MAIN_DB_PREFIX . 'actioncomm SET fk_element = ' . ((int) $dest_id) . ' WHERE elementtype="product" AND fk_element = '.((int) $origin_id);
// using $dbs, not $this->db because function is static
if (!$dbs->query($sql)) {
//$this->errors = $dbs->lasterror();
return false;
}
return true;
}
/**
* Is the action delayed?
*

View File

@ -1892,11 +1892,13 @@ if ($action == 'create') {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList();
print '</table>';
print '</div>';
}
} elseif ($object->id > 0) {
/*

View File

@ -3821,8 +3821,24 @@ class Propal extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'propaldet'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
}
/**
* Class to manage commercial proposal lines

View File

@ -1862,11 +1862,13 @@ if ($action == 'create' && $usercancreate) {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList('', $selectedLines);
print '</table>';
print '</div>';
}
print '</form>';

View File

@ -4039,6 +4039,23 @@ class Commande extends CommonOrder
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'commandedet',
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Is the customer order delayed?
*

View File

@ -65,7 +65,7 @@ $hookmanager->initHooks(array('bankcard', 'globalcard'));
// Security check
$id = GETPOST("id", 'int') ? GETPOST("id", 'int') : GETPOST('ref', 'alpha');
$fieldid = GETPOST("id") ? 'rowid' : 'ref';
$fieldid = GETPOST("id", 'int') ? 'rowid' : 'ref';
$result = restrictedArea($user, 'banque', $id, 'bank_account&bank_account', '', '', $fieldid);

View File

@ -1728,7 +1728,7 @@ class Account extends CommonObject
if ($dbs->query($sql)) {
return true;
} else {
//if ($ignoreerrors) return true; // TODO Not enough. If there is A-B on kept thirdarty and B-C on old one, we must get A-B-C after merge. Not A-B.
//if ($ignoreerrors) return true; // TODO Not enough. If there is A-B on kept thirdparty and B-C on old one, we must get A-B-C after merge. Not A-B.
//$this->errors = $dbs->lasterror();
return false;
}

View File

@ -2560,9 +2560,10 @@ if (empty($reshook)) {
setEventMessages($mesg, null, 'warnings');
$result = -1;
} else {
$object->update_percent($line, GETPOST('all_progress'));
$object->update_percent($line, GETPOST('all_progress'), false);
}
}
$object->update_price(1);
}
} elseif ($action == 'updateline' && $usercancreate && !$cancel) {
header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id); // To show again edited page
@ -3522,7 +3523,7 @@ if ($action == 'create') {
if ($socid > 0) {
// Discounts for third party
print '<tr><td>'.$langs->trans('Discounts').'</td><td colspan="2">';
print '<tr><td>'.$langs->trans('DiscountStillRemaining').'</td><td colspan="2">';
$thirdparty = $soc;
$discount_type = 0;
@ -3815,11 +3816,13 @@ if ($action == 'create') {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList('', $selectedLines);
print '</table>';
print '</div>';
}
print "</form>\n";
@ -4353,8 +4356,8 @@ if ($action == 'create') {
// Relative and absolute discounts
print '<!-- Discounts -->'."\n";
print '<tr><td>'.$langs->trans('Discounts');
print '</td><td>';
print '<tr><td>'.$langs->trans('DiscountStillRemaining').'</td>';
print '<td>';
$thirdparty = $soc;
$discount_type = 0;
$backtopage = urlencode($_SERVER["PHP_SELF"].'?facid='.$object->id);
@ -5220,7 +5223,7 @@ if ($action == 'create') {
print '</div>';
print '</div>';
print '<div class="clearboth"></div><br>';
print '<div class="clearboth"></div><br><br>';
if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
$blocname = 'contacts';

View File

@ -1759,6 +1759,23 @@ class FactureRec extends CommonInvoice
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'facturedet_rec'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Update frequency and unit
*

View File

@ -3725,11 +3725,12 @@ class Facture extends CommonInvoice
/**
* Update invoice line with percentage
*
* @param FactureLigne $line Invoice line
* @param int $percent Percentage
* @param FactureLigne $line Invoice line
* @param int $percent Percentage
* @param boolean $update_price Update object price
* @return void
*/
public function update_percent($line, $percent)
public function update_percent($line, $percent, $update_price = true)
{
// phpcs:enable
global $mysoc, $user;
@ -3756,7 +3757,11 @@ class Facture extends CommonInvoice
$line->multicurrency_total_tva = $tabprice[17];
$line->multicurrency_total_ttc = $tabprice[18];
$line->update($user);
$this->update_price(1);
// sometimes it is better to not update price for each line, ie when updating situation on all lines
if ($update_price) {
$this->update_price(1);
}
}
/**
@ -4818,6 +4823,23 @@ class Facture extends CommonInvoice
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'facturedet'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Is the customer invoice delayed?
*

View File

@ -598,6 +598,9 @@ if (!empty($search_categ_cus) && $search_categ_cus != '-1') {
}
$sql .= ', '.MAIN_DB_PREFIX.'facture as f';
if ($sortfield == "f.datef") {
$sql .= $db->hintindex('idx_facture_datef');
}
if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (f.rowid = ef.fk_object)";
}
@ -846,6 +849,37 @@ $parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
$sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint;
$nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
/* This old and fast method to get and count full list returns all record so use a high amount of memory.
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
*/
/* The fast and low memory method to get and count full list converts the sql into a sql count */
if ($sall || $search_product_category > 0 || $search_user > 0) {
$sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(DISTINCT f.rowid) as nbtotalofrecords FROM', $sql);
} else {
$sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(f.rowid) as nbtotalofrecords FROM', $sql);
$sqlforcount = preg_replace('/LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON pf.fk_facture = f.rowid/', '', $sqlforcount);
}
$sqlforcount = preg_replace('/GROUP BY.*$/', '', $sqlforcount);
$resql = $db->query($sqlforcount);
if ($resql) {
$objforcount = $db->fetch_object($resql);
$nbtotalofrecords = $objforcount->nbtotalofrecords;
} else {
dol_print_error($db);
}
if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0
$page = 0;
$offset = 0;
}
$db->free($resql);
}
// Complete request and execute it with limit
$sql .= ' ORDER BY ';
$listfield = explode(',', $sortfield);
$listorder = explode(',', $sortorder);
@ -853,19 +887,10 @@ foreach ($listfield as $key => $value) {
$sql .= $listfield[$key].' '.($listorder[$key] ? $listorder[$key] : 'DESC').',';
}
$sql .= ' f.rowid DESC ';
$nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
$page = 0;
$offset = 0;
}
if ($limit) {
$sql .= $db->plimit($limit + 1, $offset);
}
$sql .= $db->plimit($limit + 1, $offset);
$resql = $db->query($sql);
if ($resql) {

View File

@ -624,7 +624,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
*/
$object->canvas = $canvas;
$object->state_id = GETPOST("state_id");
$object->state_id = GETPOST("state_id", "int");
// We set country_id, country_code and label for the selected country
$object->country_id = GETPOST("country_id") ? GETPOST("country_id", "int") : (empty($objsoc->country_id) ? $mysoc->country_id : $objsoc->country_id);
@ -697,7 +697,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print '</td></tr>';
} else {
print '<tr><td><label for="socid">'.$langs->trans("ThirdParty").'</label></td><td colspan="3" class="maxwidthonsmartphone">';
print img_picto('', 'company').$form->select_company($socid, 'socid', '', 'SelectThirdParty');
print img_picto('', 'company').$form->select_company($socid, 'socid', '', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx');
print '</td></tr>';
}
}

View File

@ -2474,6 +2474,23 @@ class Contrat extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'contratdet'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Load an object from its id and create a new one in database
*

View File

@ -338,18 +338,24 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) {
}
}
// Add where from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters); // Note that $action and $object may have been modified by hook
$parameters = array('search_dfyear' => $search_dfyear, 'search_op2df'=>$search_op2df);
$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook
$sql .= $hookmanager->resPrint;
if ($search_dfyear > 0 && $search_op2df) {
if ($search_op2df == '<=') {
$sql .= " HAVING MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") <= '".$db->idate(dol_get_last_day($search_dfyear, $search_dfmonth, false))."'";
} elseif ($search_op2df == '>=') {
$sql .= " HAVING MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") >= '".$db->idate(dol_get_first_day($search_dfyear, $search_dfmonth, false))."'";
} else {
$sql .= " HAVING MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") <= '".$db->idate(dol_get_last_day($search_dfyear, $search_dfmonth, false))."' AND MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") >= '".$db->idate(dol_get_first_day($search_dfyear, $search_dfmonth, false))."'";
// Add HAVING from hooks
$parameters = array('search_dfyear' => $search_dfyear, 'search_op2df'=>$search_op2df);
$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook
if (empty($reshook)) {
if ($search_dfyear > 0 && $search_op2df) {
if ($search_op2df == '<=') {
$sql .= " HAVING MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") <= '".$db->idate(dol_get_last_day($search_dfyear, $search_dfmonth, false))."'";
} elseif ($search_op2df == '>=') {
$sql .= " HAVING MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") >= '".$db->idate(dol_get_first_day($search_dfyear, $search_dfmonth, false))."'";
} else {
$sql .= " HAVING MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") <= '".$db->idate(dol_get_last_day($search_dfyear, $search_dfmonth, false))."' AND MIN(".$db->ifsql("cd.statut=4", "cd.date_fin_validite", "null").") >= '".$db->idate(dol_get_first_day($search_dfyear, $search_dfmonth, false))."'";
}
}
}
$sql .= $hookmanager->resPrint;
$nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {

View File

@ -326,25 +326,25 @@ if (!empty($filter_opouvertureprevue) && $filter_opouvertureprevue != -1 && $fil
$sql .= " AND cd.date_ouverture_prevue ".$filter_opouvertureprevue." '".$db->idate($filter_dateouvertureprevue_start)."'";
}
if (!empty($filter_opouvertureprevue) && $filter_opouvertureprevue == ' BETWEEN ') {
$sql .= " AND '".$db->idate($filter_dateouvertureprevue_end)."'";
$sql .= " AND cd.date_ouverture_prevue ".$filter_opouvertureprevue." '".$db->idate($filter_dateouvertureprevue_start)."' AND '".$db->idate($filter_dateouvertureprevue_end)."'";
}
if (!empty($filter_op1) && $filter_op1 != -1 && $filter_op1 != ' BETWEEN ' && $filter_date1_start != '') {
$sql .= " AND cd.date_ouverture ".$filter_op1." '".$db->idate($filter_date1_start)."'";
}
if (!empty($filter_op1) && $filter_op1 == ' BETWEEN ') {
$sql .= " AND '".$db->idate($filter_date1_end)."'";
$sql .= " AND cd.date_ouverture ".$filter_op1." '".$db->idate($filter_date1_start)."' AND '".$db->idate($filter_date1_end)."'";
}
if (!empty($filter_op2) && $filter_op2 != -1 && $filter_op2 != ' BETWEEN ' && $filter_date2_start != '') {
$sql .= " AND cd.date_fin_validite ".$filter_op2." '".$db->idate($filter_date2_start)."'";
}
if (!empty($filter_op2) && $filter_op2 == ' BETWEEN ') {
$sql .= " AND '".$db->idate($filter_date2_end)."'";
$sql .= " AND cd.date_fin_validite ".$filter_op2." '".$db->idate($filter_date2_start)."' AND '".$db->idate($filter_date2_end)."'";
}
if (!empty($filter_opcloture) && $filter_opcloture != ' BETWEEN ' && $filter_opcloture != -1 && $filter_datecloture_start != '') {
$sql .= " AND cd.date_cloture ".$filter_opcloture." '".$db->idate($filter_datecloture_start)."'";
}
if (!empty($filter_opcloture) && $filter_opcloture == ' BETWEEN ') {
$sql .= " AND '".$db->idate($filter_datecloture_end)."'";
$sql .= " AND cd.date_cloture ".$filter_opcloture." '".$db->idate($filter_datecloture_start)."' AND '".$db->idate($filter_datecloture_end)."'";
}
// Add where from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';

View File

@ -109,7 +109,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO
}
$subject = '';
$actionmsg = '';
//$actionmsg = '';
$actionmsg2 = '';
$langs->load('mails');
@ -317,7 +317,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO
if ($action == 'send' || $action == 'relance') {
$actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '.CMailFile::getValidAddress($sendto, 4, 0, 1);
if ($message) {
/*if ($message) {
$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
if ($sendtocc) {
@ -326,7 +326,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
$actionmsg = dol_concatdesc($actionmsg, $message);
}
}*/
}
// Create form object
@ -376,7 +376,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO
$object->socid = $sendtosocid; // To link to a company
$object->sendtoid = $sendtoid; // To link to contact-addresses. This is an array.
$object->actiontypecode = $actiontypecode; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
$object->actionmsg = $actionmsg; // Long text (@todo Replace this with $message, we already have details of email in dedicated properties)
$object->actionmsg = $message; // Long text
$object->actionmsg2 = $actionmsg2; // Short text ($langs->transnoentities('MailSentBy')...);
$object->trackid = $trackid;

View File

@ -93,6 +93,14 @@ abstract class CommonInvoice extends CommonObject
const STATUS_ABANDONED = 3;
public $sumpayed;
public $sumpayed_multicurrency;
public $sumdeposit;
public $sumdeposit_multicurrency;
public $sumcreditnote;
public $sumcreditnote_multicurrency;
/**
* Return remain amount to pay. Property ->id and ->total_ttc must be set.
* This does not include open direct debit requests.
@ -118,8 +126,8 @@ abstract class CommonInvoice extends CommonObject
* Return amount of payments already done. This must include ONLY the record into the payment table.
* Payments dones using discounts, credit notes, etc are not included.
*
* @param int $multicurrency Return multicurrency_amount instead of amount
* @return float Amount of payment already done, <0 if KO
* @param int $multicurrency Return multicurrency_amount instead of amount
* @return float Amount of payment already done, <0 and set ->error if KO
*/
public function getSommePaiement($multicurrency = 0)
{
@ -138,10 +146,13 @@ abstract class CommonInvoice extends CommonObject
$resql = $this->db->query($sql);
if ($resql) {
$obj = $this->db->fetch_object($resql);
$this->db->free($resql);
if ($multicurrency) {
$this->sumpayed_multicurrency = $obj->multicurrency_amount;
return $obj->multicurrency_amount;
} else {
$this->sumpayed = $obj->amount;
return $obj->amount;
}
} else {
@ -154,13 +165,13 @@ abstract class CommonInvoice extends CommonObject
* Return amount (with tax) of all deposits invoices used by invoice.
* Should always be empty, except if option FACTURE_DEPOSITS_ARE_JUST_PAYMENTS is on (not recommended).
*
* @param int $multicurrency Return multicurrency_amount instead of amount
* @return float <0 if KO, Sum of deposits amount otherwise
* @param int $multicurrency Return multicurrency_amount instead of amount
* @return float <0 and set ->error if KO, Sum of deposits amount otherwise
*/
public function getSumDepositsUsed($multicurrency = 0)
{
if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') {
// TODO
// FACTURE_DEPOSITS_ARE_JUST_PAYMENTS was never supported for purchase invoice, so we can return 0 with no need of SQL for this case.
return 0.0;
}
@ -170,6 +181,12 @@ abstract class CommonInvoice extends CommonObject
$result = $discountstatic->getSumDepositsUsed($this, $multicurrency);
if ($result >= 0) {
if ($multicurrency) {
$this->sumdeposit_multicurrency = $result;
} else {
$this->sumdeposit = $result;
}
return $result;
} else {
$this->error = $discountstatic->error;
@ -180,8 +197,8 @@ abstract class CommonInvoice extends CommonObject
/**
* Return amount (with tax) of all credit notes invoices + excess received used by invoice
*
* @param int $multicurrency Return multicurrency_amount instead of amount
* @return float <0 if KO, Sum of credit notes and deposits amount otherwise
* @param int $multicurrency Return multicurrency_amount instead of amount
* @return float <0 and set ->error if KO, Sum of credit notes and deposits amount otherwise
*/
public function getSumCreditNotesUsed($multicurrency = 0)
{
@ -190,6 +207,12 @@ abstract class CommonInvoice extends CommonObject
$discountstatic = new DiscountAbsolute($this->db);
$result = $discountstatic->getSumCreditNotesUsed($this, $multicurrency);
if ($result >= 0) {
if ($multicurrency) {
$this->sumcreditnote_multicurrency = $result;
} else {
$this->sumcreditnote = $result;
}
return $result;
} else {
$this->error = $discountstatic->error;

View File

@ -15,6 +15,7 @@
* Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2018 Josep Lluís Amador <joseplluis@lliuretic.cat>
* Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
* Copyright (C) 2021 Grégory Blémand <gregory.blemand@atm-consulting.fr>
*
* 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
@ -42,6 +43,7 @@
*/
abstract class CommonObject
{
const TRIGGER_PREFIX = ''; // to be overriden in child class implementations, i.e. 'BILL', 'TASK', 'PROPAL', etc.
/**
* @var DoliDb Database handler (result of a new DoliDB)
*/
@ -123,6 +125,12 @@ abstract class CommonObject
*/
public $linkedObjects;
/**
* @var boolean is linkedObjects full loaded. Loaded by ->fetchObjectLinked
* important for pdf generation time reduction
*/
public $linkedObjectsFullLoaded = false;
/**
* @var Object To store a cloned copy of object before to edit it and keep track of old properties
*/
@ -3773,6 +3781,10 @@ abstract class CommonObject
{
global $conf, $hookmanager, $action;
// important for pdf generation time reduction
// this boolean is true if $this->linkedObjects has already been loaded with all objects linked without filter
if ($this->linkedObjectsFullLoaded) return 1;
$this->linkedObjectsIds = array();
$this->linkedObjects = array();
@ -3834,6 +3846,9 @@ abstract class CommonObject
} else {
$sql .= "(fk_source = ".((int) $sourceid)." AND sourcetype = '".$this->db->escape($sourcetype)."')";
$sql .= " ".$clause." (fk_target = ".((int) $targetid)." AND targettype = '".$this->db->escape($targettype)."')";
if ($sourceid == $this->id && $sourcetype == $this->element && $targetid == $this->id && $targettype == $this->element && $clause == 'OR') {
$this->linkedObjectsFullLoaded = true;
}
}
$sql .= " ORDER BY ".$orderby;
@ -4948,6 +4963,7 @@ abstract class CommonObject
print '<td class="left">'.$langs->trans('Unit').'</td>';
}
print '<td class="right">'.$langs->trans('ReductionShort').'</td>';
print '<td class="linecolht right">'.$langs->trans('TotalHT').'</td>';
print '<td class="center">'.$form->showCheckAddButtons('checkforselect', 1).'</td>';
print '</tr>';
$i = 0;
@ -5078,6 +5094,7 @@ abstract class CommonObject
}
$this->tpl['price'] = price($line->subprice);
$this->tpl['total_ht'] = price($line->total_ht);
$this->tpl['multicurrency_price'] = price($line->multicurrency_subprice);
$this->tpl['qty'] = (($line->info_bits & 2) != 2) ? $line->qty : '&nbsp;';
if (!empty($conf->global->PRODUCT_USE_UNITS)) {
@ -5602,7 +5619,10 @@ abstract class CommonObject
{
// phpcs:enable
global $langs, $conf;
if (!empty(self::TRIGGER_PREFIX) && strpos($triggerName, self::TRIGGER_PREFIX . '_') !== 0) {
dol_print_error('', 'The trigger "' . $triggerName . '" does not start with "' . self::TRIGGER_PREFIX . '_" as required.');
exit;
}
if (!is_object($langs)) { // If lang was not defined, we set it. It is required by run_triggers.
include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
$langs = new Translate('', $conf);
@ -8104,7 +8124,7 @@ abstract class CommonObject
/**
* Function used to replace a thirdparty id with another one.
* This function is meant to be called from replaceThirdparty with the appropiate tables
* This function is meant to be called from replaceThirdparty with the appropriate tables
* Column name fk_soc MUST be used to identify thirdparties
*
* @param DoliDB $db Database handler
@ -8121,7 +8141,36 @@ abstract class CommonObject
if (!$db->query($sql)) {
if ($ignoreerrors) {
return true; // TODO Not enough. If there is A-B on kept thirdarty and B-C on old one, we must get A-B-C after merge. Not A-B.
return true; // TODO Not enough. If there is A-B on kept thirdparty and B-C on old one, we must get A-B-C after merge. Not A-B.
}
//$this->errors = $db->lasterror();
return false;
}
}
return true;
}
/**
* Function used to replace a product id with another one.
* This function is meant to be called from replaceProduct with the appropriate tables
* Column name fk_product MUST be used to identify products
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id (the product to delete)
* @param int $dest_id New product id (the product that will received element of the other)
* @param string[] $tables Tables that need to be changed
* @param int $ignoreerrors Ignore errors. Return true even if errors. We need this when replacement can fails like for categories (categorie of old product may already exists on new one)
* @return bool True if success, False if error
*/
public static function commonReplaceProduct(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors = 0)
{
foreach ($tables as $table) {
$sql = 'UPDATE '.MAIN_DB_PREFIX.$table.' SET fk_product = '.((int) $dest_id).' WHERE fk_product = '.((int) $origin_id);
if (!$db->query($sql)) {
if ($ignoreerrors) {
return true; // TODO Not enough. If there is A-B on kept product and B-C on old one, we must get A-B-C after merge. Not A-B.
}
//$this->errors = $db->lasterror();
return false;

View File

@ -562,7 +562,7 @@ class DiscountAbsolute
* Should always be empty, except if option FACTURE_DEPOSITS_ARE_JUST_PAYMENTS is on (not recommended).
*
* @param CommonInvoice $invoice Object invoice (customer of supplier)
* @param int $multicurrency 1=Return multicurrency_amount instead of amount
* @param int $multicurrency 1=Return multicurrency_amount instead of amount. TODO Add a mode multicurrency = -1 to return array with amount + multicurrency amount
* @return int <0 if KO, Sum of credit notes and deposits amount otherwise
*/
public function getSumDepositsUsed($invoice, $multicurrency = 0)
@ -603,7 +603,7 @@ class DiscountAbsolute
* Return amount (with tax) of all credit notes invoices + excess received used by invoice as a payment
*
* @param CommonInvoice $invoice Object invoice
* @param int $multicurrency 1=Return multicurrency_amount instead of amount
* @param int $multicurrency 1=Return multicurrency_amount instead of amount. TODO Add a mode multicurrency = -1 to return array with amount + multicurrency amount
* @return int <0 if KO, Sum of credit notes and excess received amount otherwise
*/
public function getSumCreditNotesUsed($invoice, $multicurrency = 0)
@ -643,7 +643,7 @@ class DiscountAbsolute
* Return amount (with tax) of all converted amount for this credit note
*
* @param CommonInvoice $invoice Object invoice
* @param int $multicurrency Return multicurrency_amount instead of amount
* @param int $multicurrency Return multicurrency_amount instead of amount. TODO Add a mode multicurrency = -1 to return array with amount + multicurrency amount
* @return int <0 if KO, Sum of credit notes and deposits amount otherwise
*/
public function getSumFromThisCreditNotesNotUsed($invoice, $multicurrency = 0)

View File

@ -1303,11 +1303,13 @@ class DolGraph
$this->stringtoshow .= $xaxis;
/* For Chartjs v2.9 */
/*
if (empty($showlegend)) {
$this->stringtoshow .= 'legend: { display: false }, '."\n";
} else {
$this->stringtoshow .= 'legend: { maxWidth: '.round($this->width / 2).', labels: { boxWidth: 15 }, position: \'' . ($showlegend == 2 ? 'right' : 'top') . '\' }, '."\n";
}
*/
/* For Chartjs v3.5 */
$this->stringtoshow .= 'plugins: { '."\n";
@ -1318,7 +1320,9 @@ class DolGraph
}
$this->stringtoshow .= "}, \n";
$this->stringtoshow .= 'scales: { xAxes: [{ ';
/* For Chartjs v2.9 */
/*
$this->stringtoshow .= 'scales: { xAxis: [{ ';
if ($this->hideXValues) {
$this->stringtoshow .= ' ticks: { display: false }, display: true,';
}
@ -1328,11 +1332,12 @@ class DolGraph
$this->stringtoshow .= ', stacked: true';
}
$this->stringtoshow .= ' }]';
$this->stringtoshow .= ', yAxes: [{ ticks: { beginAtZero: true }';
$this->stringtoshow .= ', yAxis: [{ ticks: { beginAtZero: true }';
if ($type == 'bar' && count($arrayofgroupslegend) > 0) {
$this->stringtoshow .= ', stacked: true';
}
$this->stringtoshow .= ' }] }';
*/
// Add a callback to change label to show only positive value
if (is_array($this->tooltipsLabels) || is_array($this->tooltipsTitles)) {

View File

@ -195,6 +195,7 @@ class HookManager
'getFormatedSupplierRef',
'getIdProfUrl',
'getInputIdProf',
'menuDropdownQuickaddItems',
'menuLeftMenuItems',
'moveUploadedFile',
'moreHtmlStatus',

View File

@ -406,7 +406,7 @@ class FormCompany extends Form
// Show break
$key = $langs->trans("Country".strtoupper($obj->country_code));
$valuetoshow = ($key != "Country".strtoupper($obj->country_code)) ? $obj->country_code." - ".$key : $obj->country;
print '<option value="-1" disabled>----- '.$valuetoshow." -----</option>\n";
print '<option value="-2" disabled>----- '.$valuetoshow." -----</option>\n";
$country = $obj->country;
}

View File

@ -96,6 +96,17 @@ abstract class DoliDB implements Database
return '(CASE WHEN '.$test.' THEN '.$resok.' ELSE '.$resko.' END)';
}
/**
* Return SQL string to force an index
*
* @param string $nameofindex Name of index
* @return string SQL string
*/
public function hintindex($nameofindex)
{
return '';
}
/**
* Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field.
* Function to use to build INSERT, UPDATE or WHERE predica

View File

@ -168,6 +168,18 @@ class DoliDBMysqli extends DoliDB
}
/**
* Return SQL string to force an index
*
* @param string $nameofindex Name of index
* @return string SQL string
*/
public function hintindex($nameofindex)
{
return " FORCE INDEX(".preg_replace('/[^a-z0-9_]/', '', $nameofindex).")";
}
/**
* Convert a SQL request in Mysql syntax to native syntax
*
@ -180,6 +192,7 @@ class DoliDBMysqli extends DoliDB
return $line;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Select a database

View File

@ -1198,4 +1198,22 @@ $(document).ready(function() {
}
});
/*
* Hacky fix for a bug in select2 with jQuery 3.6.0's new nested-focus "protection"
* see: https://github.com/select2/select2/issues/5993
* see: https://github.com/jquery/jquery/issues/4382
*
* TODO: Recheck with the select2 GH issue and remove once this is fixed on their side
*/
$(document).on('select2:open', () => {
console.log("Execute the focus (click on combo or use space when on component");
let allFound = document.querySelectorAll('.select2-container--open .select2-search__field');
$(this).one('mouseup keyup',()=>{
setTimeout(()=>{
allFound[allFound.length - 1].focus();
},0);
});
});
// End of lib_head.js.php

View File

@ -93,7 +93,7 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
print $form->select_dolgroups($usergroupid, 'usergroup', 1, '', !$canedit, '', '', '0', false, 'minwidth100 maxwidth500 widthcentpercentminusxx');
print '</div>';
if ($conf->resource->enabled) {
if (!empty($conf->resource->enabled)) {
include_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
$formresource = new FormResource($db);
@ -105,14 +105,14 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
}
}
if (!empty($conf->societe->enabled) && $user->rights->societe->lire) {
if (!empty($conf->societe->enabled) && !empty($user->rights->societe->lire)) {
print '<div class="divsearchfield">';
print img_picto($langs->trans("ThirdParty"), 'company', 'class="fawidth30 inline-block"');
print $form->select_company($socid, 'search_socid', '', '&nbsp;', 0, 0, null, 0, 'minwidth100 maxwidth500');
print '</div>';
}
if (!empty($conf->projet->enabled) && $user->rights->projet->lire) {
if (!empty($conf->projet->enabled) && !empty($user->rights->projet->lire)) {
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
$formproject = new FormProjets($db);

View File

@ -180,7 +180,7 @@ function societe_prepare_head(Societe $object)
// Related items
if ((!empty($conf->commande->enabled) || !empty($conf->propal->enabled) || !empty($conf->facture->enabled) || !empty($conf->ficheinter->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))
&& empty($conf->global->THIRPARTIES_DISABLE_RELATED_OBJECT_TAB)) {
&& empty($conf->global->THIRDPARTIES_DISABLE_RELATED_OBJECT_TAB)) {
$head[$h][0] = DOL_URL_ROOT.'/societe/consumption.php?socid='.$object->id;
$head[$h][1] = $langs->trans("Referers");
$head[$h][2] = 'consumption';

View File

@ -7470,13 +7470,23 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray['__DATE_YMD__'] = is_object($object) ? (isset($object->date) ? dol_print_date($object->date, 'day', 0, $outputlangs) : null) : '';
$substitutionarray['__DATE_DUE_YMD__'] = is_object($object) ? (isset($object->date_lim_reglement) ? dol_print_date($object->date_lim_reglement, 'day', 0, $outputlangs) : null) : '';
$already_payed_all = 0;
if (is_object($object) && ($object instanceof Facture)) {
$already_payed_all = $object->sumpayed + $object->sumdeposit + $object->sumcreditnote;
}
$substitutionarray['__AMOUNT_EXCL_TAX__'] = is_object($object) ? $object->total_ht : '';
$substitutionarray['__AMOUNT__'] = is_object($object) ? $object->total_ttc : '';
$substitutionarray['__AMOUNT_TEXT__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, '', true) : '';
$substitutionarray['__AMOUNT_TEXTCURRENCY__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, $conf->currency, true) : '';
$substitutionarray['__AMOUNT_EXCL_TAX__'] = is_object($object) ? $object->total_ht : '';
$substitutionarray['__AMOUNT_REMAIN__'] = is_object($object) ? $object->total_ttc - $already_payed_all : '';
$substitutionarray['__AMOUNT_VAT__'] = is_object($object) ? (isset($object->total_vat) ? $object->total_vat : $object->total_tva) : '';
$substitutionarray['__AMOUNT_VAT_TEXT__'] = is_object($object) ? (isset($object->total_vat) ? dol_convertToWord($object->total_vat, $outputlangs, '', true) : dol_convertToWord($object->total_tva, $outputlangs, '', true)) : '';
$substitutionarray['__AMOUNT_VAT_TEXTCURRENCY__'] = is_object($object) ? (isset($object->total_vat) ? dol_convertToWord($object->total_vat, $outputlangs, $conf->currency, true) : dol_convertToWord($object->total_tva, $outputlangs, $conf->currency, true)) : '';
if ($onlykey != 2 || $mysoc->useLocalTax(1)) {
$substitutionarray['__AMOUNT_TAX2__'] = is_object($object) ? $object->total_localtax1 : '';
}
@ -7484,8 +7494,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
$substitutionarray['__AMOUNT_TAX3__'] = is_object($object) ? $object->total_localtax2 : '';
}
$substitutionarray['__AMOUNT_FORMATED__'] = is_object($object) ? ($object->total_ttc ? price($object->total_ttc, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : '';
// Amount keys formated in a currency
$substitutionarray['__AMOUNT_EXCL_TAX_FORMATED__'] = is_object($object) ? ($object->total_ht ? price($object->total_ht, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : '';
$substitutionarray['__AMOUNT_FORMATED__'] = is_object($object) ? ($object->total_ttc ? price($object->total_ttc, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : '';
$substitutionarray['__AMOUNT_REMAIN_FORMATED__'] = is_object($object) ? ($object->total_ttc ? price($object->total_ttc - $already_payed_all, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : '';
$substitutionarray['__AMOUNT_VAT_FORMATED__'] = is_object($object) ? (isset($object->total_vat) ? price($object->total_vat, 0, $outputlangs, 0, -1, -1, $conf->currency) : ($object->total_tva ? price($object->total_tva, 0, $outputlangs, 0, -1, -1, $conf->currency) : null)) : '';
if ($onlykey != 2 || $mysoc->useLocalTax(1)) {
$substitutionarray['__AMOUNT_TAX2_FORMATED__'] = is_object($object) ? ($object->total_localtax1 ? price($object->total_localtax1, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : '';

View File

@ -1130,6 +1130,11 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_
$pdf->SetFont('', '', 7);
$pdf->SetDrawColor(224, 224, 224);
// Option for footer text color
if (!empty($conf->global->PDF_FOOTER_TEXT_COLOR)) {
list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_TEXT_COLOR, '%d, %d, %d');
$pdf->SetTextColor($r, $g, $b);
}
// The start of the bottom of this page footer is positioned according to # of lines
$freetextheight = 0;
@ -1161,6 +1166,14 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_
$marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
$posy = $marginwithfooter + 0;
// Option for footer background color (without freetext zone)
if (!empty($conf->global->PDF_FOOTER_BACKGROUND_COLOR)) {
list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
$pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
$pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
$pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
}
if ($line) { // Free text
$pdf->SetXY($dims['lm'], -$posy);
if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT)) { // by default
@ -1172,10 +1185,20 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_
}
$pdf->SetY(-$posy);
$pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
$posy--;
$pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $freetextheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
// Hide footer line if footer background color is set
if (empty($conf->global->PDF_FOOTER_BACKGROUND_COLOR)) {
$pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
}
// Option for set top margin height of footer after freetext
if (!empty($conf->global->PDF_FOOTER_TOP_MARGIN) || ($conf->global->PDF_FOOTER_TOP_MARGIN === '0')) {
$posy -= $conf->global->PDF_FOOTER_TOP_MARGIN;
} else { $posy--; }
if ($conf->global->PDF_FOOTER_DISABLE_PAGEBREAK === '1') { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
$pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
if ($conf->global->PDF_FOOTER_DISABLE_PAGEBREAK === '1') { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
$posy -= $mycustomfooterheight - 3;
} else {
@ -1183,6 +1206,14 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_
$marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
$posy = $marginwithfooter + 0;
// Option for footer background color (without freetext zone)
if (!empty($conf->global->PDF_FOOTER_BACKGROUND_COLOR)) {
list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
$pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
$pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
$pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
}
if ($line) { // Free text
$pdf->SetXY($dims['lm'], -$posy);
if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT)) { // by default
@ -1194,8 +1225,16 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_
}
$pdf->SetY(-$posy);
$pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
$posy--;
// Hide footer line if footer background color is set
if (empty($conf->global->PDF_FOOTER_BACKGROUND_COLOR)) {
$pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
}
// Option for set top margin height of footer after freetext
if (!empty($conf->global->PDF_FOOTER_TOP_MARGIN) || ($conf->global->PDF_FOOTER_TOP_MARGIN === '0')) {
$posy -= $conf->global->PDF_FOOTER_TOP_MARGIN;
} else { $posy--; }
if (!empty($line1)) {
$pdf->SetFont('', 'B', 7);

View File

@ -143,7 +143,11 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes
$ret = $mc->checkRight($obj->rowid, $entitytotest);
if ($ret < 0) {
dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO entity '".$entitytotest."' not allowed for user '".$obj->rowid."'", LOG_NOTICE);
$login = ''; // force authentication failure
if ($mc->db->lasterror()) {
$_SESSION["dol_loginmesg"] = $mc->db->lasterror();
}
}
}
}

View File

@ -113,7 +113,7 @@ class modFacture extends DolibarrModules
$datestart = dol_mktime(23, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']);
$this->cronjobs = array(
0 => array(
'label'=>'RecurringInvoices',
'label'=>'RecurringInvoicesJob',
'jobtype'=>'method',
'class'=>'compta/facture/class/facture-rec.class.php',
'objectname'=>'FactureRec',
@ -122,7 +122,7 @@ class modFacture extends DolibarrModules
'comment'=>'Generate recurring invoices',
'frequency'=>1,
'unitfrequency'=>3600 * 24,
'priority'=>50,
'priority'=>51,
'status'=>1,
'test'=>'$conf->facture->enabled',
'datestart'=>$datestart

View File

@ -133,7 +133,7 @@ class modFournisseur extends DolibarrModules
$datestart = dol_mktime(23, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']);
$this->cronjobs = array(
0 => array(
'label'=>'RecurringSupplierInvoices',
'label'=>'RecurringSupplierInvoicesJob',
'jobtype'=>'method',
'class'=>'fourn/class/fournisseur.facture-rec.class.php',
'objectname'=>'FactureFournisseurRec',
@ -142,7 +142,7 @@ class modFournisseur extends DolibarrModules
'comment'=>'Generate recurring supplier invoices',
'frequency'=>1,
'unitfrequency'=>3600 * 24,
'priority'=>50,
'priority'=>51,
'status'=>1,
'datestart'=>$datestart
));

View File

@ -259,7 +259,7 @@ $arrayfields = array(
'rowid' => array('label'=>$langs->trans("Id"), 'checked'=>1),
'nature' => array('label'=>$langs->trans("NatureOfContact"), 'checked'=>1),
'thirdparty' => array('label'=>$langs->trans("ThirdParty"), 'checked'=>1),
'contact' => array('label'=>$langs->trans("Users").'/'.$langs->trans("Contacts"), 'checked'=>1),
'contact' => array('label'=>$langs->trans("Users").' | '.$langs->trans("Contacts"), 'checked'=>1),
'type' => array('label'=>$langs->trans("ContactType"), 'checked'=>1),
'status' => array('label'=>$langs->trans("Status"), 'checked'=>1),
'link' => array('label'=>$langs->trans("Link"), 'checked'=>1),

View File

@ -14,7 +14,7 @@ if (isset($totalarray['pos'])) {
$i++;
if (!empty($totalarray['pos'][$i])) {
print '<td class="right">';
if ($totalarray['type'][$i] == 'duration') {
if (isset($totalarray['type']) && $totalarray['type'][$i] == 'duration') {
print (!empty($totalarray['val'][$totalarray['pos'][$i]])?convertSecondToTime($totalarray['val'][$totalarray['pos'][$i]], 'allhourmin'):0);
} else {
print price(!empty($totalarray['val'][$totalarray['pos'][$i]])?$totalarray['val'][$totalarray['pos'][$i]]:0);

View File

@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2017 Charlie Benke <charlie@patas-monkey.com>
* Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
*
* 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
@ -26,7 +27,7 @@ if (empty($conf) || !is_object($conf)) {
<!-- BEGIN PHP TEMPLATE originproductline.tpl.php -->
<?php
print '<tr class="oddeven'.(empty($this->tpl['strike']) ? '' : ' strikefordisabled').'">';
print '<tr data-id="'.$this->tpl['id'].'" class="oddeven'.(empty($this->tpl['strike']) ? '' : ' strikefordisabled').'">';
print '<td>'.$this->tpl['label'].'</td>';
print '<td>'.$this->tpl['description'].'</td>';
print '<td class="right">'.$this->tpl['vat_rate'].'</td>';
@ -41,6 +42,7 @@ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
}
print '<td class="right">'.$this->tpl['remise_percent'].'</td>';
print '<td class="linecolht right">'.$this->tpl['total_ht'].'</td>';
$selected = 1;
if (!empty($selectedLines) && !in_array($this->tpl['id'], $selectedLines)) {

View File

@ -13,9 +13,11 @@ require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
$form = new Form($db);
$formresources = new FormResource($db);
$out = '<div class="tagtable centpercent noborder borderbottom allwidth nohover">';
$out = '';
$out .= '<form class="tagtr nohover '.($var == true ? 'pair' : 'impair').'" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
$out .= '<div class="centpercent allwidth nohover">';
$out .= '<form class="nohover '.($var == true ? 'pair' : 'impair').'" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
$out .= '<input type="hidden" name="token" value="'.newToken().'">';
$out .= '<input type="hidden" name="action" value="add_element_resource">';
$out .= '<input type="hidden" name="element" value="'.$element.'">';
@ -23,21 +25,30 @@ $out .= '<input type="hidden" name="element_id" value="'.$element_id.'">';
$out .= '<input type="hidden" name="ref" value="'.$element_ref.'">';
$out .= '<input type="hidden" name="resource_type" value="'.(empty($resource_type) ? 'dolresource' : $resource_type).'">';
$out .= '<div class="noborder borderbottom">';
// Place
$out .= '<div class="tagtd">'.$langs->trans("SelectResource").'</div>';
$out .= '<div class="tagtd">';
$out .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">'.$langs->trans("SelectResource").'</div>';
$out .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
$events = array();
$out .= $formresources->select_resource_list('', 'fk_resource', '', 1, 1, 0, $events, '', 2, null);
$out .= '</div>';
$out .= '<div class="tagtd"><label>'.$langs->trans('Busy').'</label> '.$form->selectyesno('busy', (GETPOSTISSET('busy') ? GETPOST('busy') : 1), 1).'</div>';
$out .= '<div class="tagtd"><label>'.$langs->trans('Mandatory').'</label> '.$form->selectyesno('mandatory', (GETPOSTISSET('mandatory') ? GETPOST('mandatory') : 0), 1).'</div>';
$out .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block marginleftonly"><label for="resbusy">'.$langs->trans('Busy').'</label> ';
//$out .= $form->selectyesno('busy', (GETPOSTISSET('busy') ? GETPOST('busy') : 1), 1);
$out .= '<input type="checkbox" id="resbusy" name="busy" value="1"'.(GETPOSTISSET('fk_resource') ? (GETPOST('busy') ? ' checked' : '') : ' checked').'>';
$out .= '</div>';
$out .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block marginleftonly"><label for="resmandatory">'.$langs->trans('Mandatory').'</label> ';
//$out .= $form->selectyesno('mandatory', (GETPOSTISSET('mandatory') ? GETPOST('mandatory') : 0), 1);
$out .= '<input type="checkbox" id="resmandatory" name="mandatory" value="1"'.(GETPOSTISSET('fk_resource') ? (GETPOST('mandatory') ? ' checked' : '') : ' checked').'>';
$out .= '</div>';
$out .= '<div class="tagtd right">';
$out .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block right">';
$out .= '<input type="submit" id="add-resource-place" class="button button-add" value="'.$langs->trans("Add").'"/>';
$out .= '</div>';
$out .= '</div>';
$out .= '</form>';
$out .= '</div>';

View File

@ -958,11 +958,13 @@ class InterfaceActionsAuto extends DolibarrTriggers
}
}
/* Seems no more required: We have the data in dedicated field now.
if (!empty($user->login)) {
$object->actionmsg = dol_concatdesc($langs->transnoentities("Author").': '.$user->login, $object->actionmsg);
} elseif (isset($object->origin_email)) {
$object->actionmsg = dol_concatdesc($langs->transnoentities("Author").': '.$object->origin_email, $object->actionmsg);
}
*/
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
@ -1019,7 +1021,7 @@ class InterfaceActionsAuto extends DolibarrTriggers
$actioncomm->type_code = $object->actiontypecode; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
$actioncomm->code = 'AC_'.$action;
$actioncomm->label = $object->actionmsg2;
$actioncomm->note_private = $object->actionmsg; // TODO Replace with ($actioncomm->email_msgid ? $object->email_content : $object->actionmsg)
$actioncomm->note_private = $object->actionmsg;
$actioncomm->fk_project = $projectid;
$actioncomm->datep = $now;
$actioncomm->datef = $now;

View File

@ -183,7 +183,7 @@ class InterfaceStripe extends DolibarrTriggers
if ($action == 'COMPANY_DELETE') {
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
if (!empty($conf->global->STRIPE_DELETE_STRIPE_ACCOUNT_WHEN_DELETING_THIRPARTY)) {
if (!empty($conf->global->STRIPE_DELETE_STRIPE_ACCOUNT_WHEN_DELETING_THIRDPARTY)) {
// By default, we do not delete the stripe account. We may need to reuse it with its payment_intent, for example if delete is for a merge of thirdparties.
$stripeacc = $stripe->getStripeAccount($service); // No need of network access for this. May return '' if no Oauth defined.

View File

@ -1,5 +1,7 @@
DataPolicy
==========
This module provides features to be compliant with data privacy rules of your country.
A schedlued job is installed to automatically clean old record in your database. You defined what to delete and when in the setup of module.
A scheduled job is installed to automatically delete old records in your database.
In the setup of the module you define what should be deleted and when.

View File

@ -1092,6 +1092,23 @@ class Delivery extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'deliverydet'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
}

View File

@ -1003,11 +1003,13 @@ if ($action == 'create') {
$title = $langs->trans('Services');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList(empty($conf->global->FICHINTER_PRINT_PRODUCTS) ? 'services' : ''); // Show only service, except if option FICHINTER_PRINT_PRODUCTS is on
print '</table>';
print '</div>';
}
print '</form>';

View File

@ -40,7 +40,7 @@ class FichinterRec extends Fichinter
{
public $element = 'fichinterrec';
public $table_element = 'fichinter_rec';
public $table_element_line = 'fichinter_rec';
public $table_element_line = 'fichinterdet_rec';
/**
* @var string Fieldname with ID of parent key if this field has a parent
@ -706,6 +706,22 @@ class FichinterRec extends Fichinter
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'fichinterdet_rec'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Update frequency and unit

View File

@ -3249,6 +3249,23 @@ class CommandeFournisseur extends CommonOrder
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'commande_fournisseurdet'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Is the supplier order delayed?
* We suppose a purchase ordered as late if a the purchase order has been sent and the delivery date is set and before the delay.

View File

@ -79,8 +79,19 @@ class FactureFournisseurRec extends CommonInvoice
public $suspended;
public $libelle;
public $label;
/**
* @var double $amount
* @deprecated
*/
public $amount;
/**
* @var double $remise
* @deprecated
*/
public $remise;
public $vat_src_code;
public $localtax1;
public $localtax2;
@ -168,8 +179,6 @@ class FactureFournisseurRec extends CommonInvoice
'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>40),
'suspended' =>array('type'=>'integer', 'label'=>'Suspended', 'enabled'=>1, 'visible'=>-1, 'position'=>225),
'libelle' =>array('type'=>'varchar(100)', 'label'=>'Libelle', 'enabled'=>1, 'showoncombobox' => 0, 'visible'=>-1, 'position'=>15),
'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35),
'remise' =>array('type'=>'double', 'label'=>'Remise', 'enabled'=>1, 'visible'=>-1, 'position'=>40),
'localtax1' =>array('type'=>'double(24,8)', 'label'=>'Localtax1', 'enabled'=>1, 'visible'=>-1, 'position'=>60, 'isameasure'=>1),
'localtax2' =>array('type'=>'double(24,8)', 'label'=>'Localtax2', 'enabled'=>1, 'visible'=>-1, 'position'=>65, 'isameasure'=>1),
@ -273,8 +282,7 @@ class FactureFournisseurRec extends CommonInvoice
$sql .= ', datec';
$sql .= ', suspended';
$sql .= ', libelle';
$sql .= ', amount';
$sql .= ', remise';
$sql .= ', total_ttc';
$sql .= ', fk_user_author';
$sql .= ', fk_projet';
$sql .= ', fk_account';
@ -305,7 +313,6 @@ class FactureFournisseurRec extends CommonInvoice
$sql .= ", ".((int) $this->suspended);
$sql .= ", '".$this->db->escape($this->libelle)."'";
$sql .= ", " .(!empty($facfourn_src->total_ttc) ? (float) $facfourn_src->total_ttc : '0'); // amount
$sql .= ", " .(!empty($facfourn_src->remise) ? (float) $facfourn_src->remise : '0');
$sql .= ", " .((int) $user->id);
$sql .= ", " .(!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL');
$sql .= ", " .(!empty($facfourn_src->fk_account) ? ((int) $facfourn_src->fk_account) : 'NULL');
@ -475,8 +482,6 @@ class FactureFournisseurRec extends CommonInvoice
if ($this->fk_soc > 0) $sql .= " fk_soc = ". (int) $this->fk_soc. ',';
$sql .= " suspended = ". (!empty($this->suspended) ? ((int) $this->suspended) : 0) . ',';
$sql .= " libelle = ". (!empty($this->libelle) ? "'".$this->db->escape($this->libelle)."'" : 'NULL') . ",";
$sql .= " amount = ". (!empty($this->amount) ? ((float) $this->amount) : 0.00) . ',';
$sql .= " remise = ". (!empty($this->remise) ? ((float) $this->remise) : 'NULL') . ',';
$sql .= " vat_src_code = ". (!empty($this->vat_src_code) ? "'".$this->db->escape($this->vat_src_code)."'" : 'NULL') . ',';
$sql .= " localtax1 = ". (!empty($this->localtax1) ? ((float) $this->localtax1) : 0.00) . ',';
$sql .= " localtax2 = ". (!empty($this->localtax2) ? ((float) $this->localtax2) : 0.00) . ',';
@ -548,7 +553,7 @@ class FactureFournisseurRec extends CommonInvoice
{
$sql = 'SELECT f.rowid, f.titre, f.ref_supplier, f.entity, f.fk_soc';
$sql .= ', f.datec, f.tms, f.suspended';
$sql .= ', f.libelle, f.amount, f.remise';
$sql .= ', f.libelle as label';
$sql .= ', f.vat_src_code, f.localtax1, f.localtax2';
$sql .= ', f.total_tva, f.total_ht, f.total_ttc';
$sql .= ', f.fk_user_author, f.fk_user_modif';
@ -588,9 +593,8 @@ class FactureFournisseurRec extends CommonInvoice
$this->date_creation = $obj->datec;
$this->date_modification = $obj->tms;
$this->suspended = $obj->suspended;
$this->libelle = $obj->libelle;
$this->amount = $obj->amount;
$this->remise = $obj->remise;
$this->libelle = $obj->label;
$this->label = $obj->label;
$this->vat_src_code = $obj->vat_src_code;
$this->total_localtax1 = $obj->localtax1;
$this->total_localtax2 = $obj->localtax2;

View File

@ -181,7 +181,15 @@ class FactureFournisseur extends CommonInvoice
*/
public $date_echeance;
/**
* @var double $amount
* @deprecated
*/
public $amount = 0;
/**
* @var double $remise
* @deprecated
*/
public $remise = 0;
/**
@ -400,11 +408,6 @@ class FactureFournisseur extends CommonInvoice
$this->date = $now;
}
$socid = $this->socid;
$ref_supplier = $this->ref_supplier;
$amount = $this->amount;
$remise = $this->remise;
// Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate)
if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date);
@ -452,7 +455,6 @@ class FactureFournisseur extends CommonInvoice
$this->total_ttc = $_facrec->total_ttc;
// Fields always coming from template
$this->remise = $_facrec->remise;
$this->fk_incoterms = $_facrec->fk_incoterms;
$this->location_incoterms = $_facrec->location_incoterms;
@ -471,7 +473,6 @@ class FactureFournisseur extends CommonInvoice
$this->array_options = $_facrec->array_options;
//if (! $this->remise) $this->remise = 0;
if (! $this->mode_reglement_id) {
$this->mode_reglement_id = 0;
}
@ -541,10 +542,6 @@ class FactureFournisseur extends CommonInvoice
$this->date_echeance = $forceduedate;
}
if (!$remise) {
$remise = 0;
}
$sql = "INSERT INTO ".MAIN_DB_PREFIX."facture_fourn (";
$sql .= "ref";
$sql .= ", ref_supplier";
@ -878,8 +875,6 @@ class FactureFournisseur extends CommonInvoice
$sql .= " t.tms,";
$sql .= " t.libelle as label,";
$sql .= " t.paye,";
$sql .= " t.amount,";
$sql .= " t.remise,";
$sql .= " t.close_code,";
$sql .= " t.close_note,";
$sql .= " t.tva,";
@ -944,11 +939,8 @@ class FactureFournisseur extends CommonInvoice
$this->label = $obj->label;
$this->paye = $obj->paye;
$this->paid = $obj->paye;
$this->amount = $obj->amount;
$this->remise = $obj->remise;
$this->close_code = $obj->close_code;
$this->close_note = $obj->close_note;
//$this->tva = $obj->tva;
$this->total_localtax1 = $obj->localtax1;
$this->total_localtax2 = $obj->localtax2;
$this->total_ht = $obj->total_ht;
@ -1173,21 +1165,12 @@ class FactureFournisseur extends CommonInvoice
if (isset($this->paye)) {
$this->paye = trim($this->paye);
}
if (isset($this->amount)) {
$this->amount = trim($this->amount);
}
if (isset($this->remise)) {
$this->remise = trim($this->remise);
}
if (isset($this->close_code)) {
$this->close_code = trim($this->close_code);
}
if (isset($this->close_note)) {
$this->close_note = trim($this->close_note);
}
/*if (isset($this->tva)) {
$this->tva = trim($this->tva);
}*/
if (isset($this->localtax1)) {
$this->localtax1 = trim($this->localtax1);
}
@ -1221,7 +1204,8 @@ class FactureFournisseur extends CommonInvoice
$this->fk_facture_source = trim($this->fk_facture_source);
}
if (isset($this->fk_project)) {
$this->fk_project = trim($this->fk_project);
if (empty($this->fk_project)) $this->fk_project = null;
else $this->fk_project = intval($this->fk_project);
}
if (isset($this->cond_reglement_id)) {
$this->cond_reglement_id = trim($this->cond_reglement_id);
@ -1258,8 +1242,6 @@ class FactureFournisseur extends CommonInvoice
}
$sql .= " libelle=".(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").",";
$sql .= " paye=".(isset($this->paye) ? $this->paye : "null").",";
$sql .= " amount=".(isset($this->amount) ? $this->amount : "null").",";
$sql .= " remise=".(isset($this->remise) ? $this->remise : "null").",";
$sql .= " close_code=".(isset($this->close_code) ? "'".$this->db->escape($this->close_code)."'" : "null").",";
$sql .= " close_note=".(isset($this->close_note) ? "'".$this->db->escape($this->close_note)."'" : "null").",";
//$sql .= " tva=".(isset($this->tva) ? $this->tva : "null").",";
@ -2446,7 +2428,7 @@ class FactureFournisseur extends CommonInvoice
$this->db->begin();
// Libere remise liee a ligne de facture
// Free the discount linked to a line of invoice
$sql = 'UPDATE '.MAIN_DB_PREFIX.'societe_remise_except';
$sql .= ' SET fk_invoice_supplier_line = NULL';
$sql .= ' WHERE fk_invoice_supplier_line = '.((int) $rowid);
@ -2645,7 +2627,7 @@ class FactureFournisseur extends CommonInvoice
// phpcs:enable
global $conf, $langs;
$sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin, ff.fk_statut as status';
$sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin, ff.fk_statut as status, ff.total_ht, ff.total_ttc';
$sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as ff';
if (empty($user->rights->societe->client->voir) && !$user->socid) {
$sql .= " JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ff.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
@ -3171,6 +3153,23 @@ class FactureFournisseur extends CommonInvoice
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'facture_fourn_det'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* Is the payment of the supplier invoice having a delay?
*

View File

@ -972,6 +972,23 @@ class ProductFournisseur extends Product
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'product_fournisseur_price'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
/**
* List supplier prices log of a supplier price
*

View File

@ -1840,11 +1840,13 @@ if ($action == 'create') {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList('', $selectedLines);
print '</table>';
print '</div>';
}
print "</form>\n";
} elseif (!empty($object->id)) {

View File

@ -76,7 +76,7 @@ $lineid = GETPOST('lineid', 'int');
$projectid = GETPOST('projectid', 'int');
$origin = GETPOST('origin', 'alpha');
$originid = GETPOST('originid', 'int');
$fac_rec = GETPOST('fac_rec', 'int');
$fac_recid = GETPOST('fac_rec', 'int');
// PDF
$hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
@ -882,10 +882,8 @@ if (empty($reshook)) {
}
}
}
}
// Standard invoice or Deposit invoice, created from a Predefined template invoice
if ((GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT) && GETPOST('fac_rec', 'int') > 0) {
} elseif ($fac_recid > 0 && (GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT)) {
// Standard invoice or Deposit invoice, created from a Predefined template invoice
if (empty($dateinvoice)) {
$error++;
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
@ -903,7 +901,7 @@ if (empty($reshook)) {
$object->date = $dateinvoice;
$object->note_public = trim(GETPOST('note_public', 'restricthtml'));
$object->note_private = trim(GETPOST('note_private', 'restricthtml'));
$object->ref_client = GETPOST('ref_client');
$object->ref_supplier = GETPOST('ref_supplier', 'nohtml');
$object->model_pdf = GETPOST('model');
$object->fk_project = GETPOST('projectid', 'int');
$object->cond_reglement_id = (GETPOST('type') == 3 ? 1 : GETPOST('cond_reglement_id'));
@ -918,7 +916,7 @@ if (empty($reshook)) {
$object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
// Source facture
$object->fac_rec = GETPOST('fac_rec', 'int');
$object->fac_rec = $fac_recid;
$fac_rec = new FactureFournisseurRec($db);
$fac_rec->fetch($object->fac_rec);
$fac_rec->fetch_lines();
@ -926,10 +924,8 @@ if (empty($reshook)) {
$id = $object->create($user); // This include recopy of links from recurring invoice and recurring invoice lines
}
}
// Standard invoice or Deposit invoice, not from a Predefined template invoice
if (GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT && GETPOST('fac_rec') <= 0) {
} elseif ($fac_recid <= 0 && (GETPOST('type') == FactureFournisseur::TYPE_STANDARD || GETPOST('type') == FactureFournisseur::TYPE_DEPOSIT)) {
// Standard invoice or Deposit invoice, not from a Predefined template invoice
if (GETPOST('socid', 'int') < 1) {
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Supplier')), null, 'errors');
$action = 'create';
@ -2024,15 +2020,15 @@ if ($action == 'create') {
$exampletemplateinvoice = new FactureFournisseurRec($db);
$invoice_predefined = new FactureFournisseurRec($db);
if (empty($origin) && empty($originid) && GETPOST('fac_rec', 'int') > 0) {
$invoice_predefined->fetch(GETPOST('fac_rec', 'int'));
if (empty($origin) && empty($originid) && $fac_recid > 0) {
$invoice_predefined->fetch($fac_recid);
}
// Third party
print '<tr><td class="fieldrequired">'.$langs->trans('Supplier').'</td>';
print '<td>';
if ($societe->id > 0 && (!GETPOST('fac_rec', 'int') || !empty($invoice_predefined->frequency))) {
if ($societe->id > 0 && ($fac_recid <= 0 || !empty($invoice_predefined->frequency))) {
$absolute_discount = $societe->getAvailableDiscounts('', '', 0, 1);
print $societe->getNomUrl(1, 'supplier');
print '<input type="hidden" name="socid" value="'.$societe->id.'">';
@ -2050,15 +2046,15 @@ if ($action == 'create') {
});
</script>';
}
if (!GETPOST('fac_rec', 'int')) {
if ($fac_recid <= 0) {
print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=0&fournisseur=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
}
}
print '</td></tr>';
// Overwrite some values if creation of invoice is from a predefined invoice
if (empty($origin) && empty($originid) && GETPOST('fac_rec', 'int') > 0) {
$invoice_predefined->fetch(GETPOST('fac_rec', 'int'));
if (empty($origin) && empty($originid) && $fac_recid > 0) {
$invoice_predefined->fetch($fac_recid);
$dateinvoice = $invoice_predefined->date_when; // To use next gen date by default later
if (empty($projectid)) {
@ -2088,15 +2084,15 @@ if ($action == 'create') {
if ($num > 0) {
print '<tr><td>'.$langs->trans('CreateFromRepeatableInvoice').'</td><td>';
//print '<input type="hidden" name="fac_rec" id="fac_rec" value="'.GETPOST('fac_rec', 'int').'">';
//print '<input type="hidden" name="fac_rec" id="fac_rec" value="'.$fac_recid.'">';
print '<select class="flat" id="fac_rec" name="fac_rec">'; // We may want to change the template to use
print '<option value="0" selected></option>';
while ($i < $num) {
$objp = $db->fetch_object($resql);
print '<option value="'.$objp->rowid.'"';
if (GETPOST('fac_rec', 'int') == $objp->rowid) {
if ($fac_recid == $objp->rowid) {
print ' selected';
$exampletemplateinvoice->fetch(GETPOST('fac_rec', 'int'));
$exampletemplateinvoice->fetch($fac_recid);
}
print '>'.$objp->title.' ('.price($objp->total_ttc).' '.$langs->trans("TTC").')</option>';
$i++;
@ -2408,7 +2404,7 @@ if ($action == 'create') {
$langs->load('projects');
print '<tr><td>'.$langs->trans('Project').'</td><td>';
print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $societe->id : -1), $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500 widthcentpercentminusxx');
print ' <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$soc->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id.($fac_rec ? '&fac_rec='.$fac_rec : '')).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
print ' <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$soc->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id.($fac_recid > 0 ? '&fac_rec='.$fac_recid : '')).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
print '</td></tr>';
}
@ -2432,7 +2428,7 @@ if ($action == 'create') {
// Help of substitution key
$htmltext = '';
if (GETPOST('fac_rec', 'int') > 0) {
if ($fac_recid > 0) {
$dateexample = $newdateinvoice ? $newdateinvoice : $dateinvoice;
if (empty($dateexample)) {
$dateexample = dol_now();
@ -2557,11 +2553,13 @@ if ($action == 'create') {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList('', $selectedLines);
print '</table>';
print '</div>';
}
print "</form>\n";

View File

@ -721,7 +721,7 @@ if ($resql) {
if (!empty($arrayfields['cp.statut']['checked'])) {
print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "cp.statut", "", $param, '', $sortfield, $sortorder, 'right ');
}
print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch ');
print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'maxwidthsearch center ');
print "</tr>\n";
$listhalfday = array('morning'=>$langs->trans("Morning"), "afternoon"=>$langs->trans("Afternoon"));
@ -789,21 +789,23 @@ if ($resql) {
}
}
if (!empty($arrayfields['cp.fk_user']['checked'])) {
print '<td class="tdoverflowmax150">'.$userstatic->getNomUrl(-1, 'leave').'</td>';
print '<td class="tdoverflowmax125">'.$userstatic->getNomUrl(-1, 'leave').'</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
if (!empty($arrayfields['cp.fk_validator']['checked'])) {
print '<td class="tdoverflowmax150">'.$approbatorstatic->getNomUrl(-1).'</td>';
print '<td class="tdoverflowmax125">'.$approbatorstatic->getNomUrl(-1).'</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
if (!empty($arrayfields['cp.fk_type']['checked'])) {
print '<td class="minwidth100">';
$labeltypeleavetoshow = ($langs->trans($typeleaves[$obj->fk_type]['code']) != $typeleaves[$obj->fk_type]['code'] ? $langs->trans($typeleaves[$obj->fk_type]['code']) : $typeleaves[$obj->fk_type]['label']);
print empty($typeleaves[$obj->fk_type]['label']) ? $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type) : $labeltypeleavetoshow;
$labeltypeleavetoshow = empty($typeleaves[$obj->fk_type]['label']) ? $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type) : $labeltypeleavetoshow;
print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($labeltypeleavetoshow).'">';
print $labeltypeleavetoshow;
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
@ -813,7 +815,8 @@ if ($resql) {
print '<td class="right">';
$nbopenedday = num_open_day($db->jdate($obj->date_debut, 1), $db->jdate($obj->date_fin, 1), 0, 1, $obj->halfday); // user jdate(..., 1) because num_open_day need UTC dates
$totalduration += $nbopenedday;
print $nbopenedday.' '.$langs->trans('DurationDays');
print $nbopenedday;
//print ' '.$langs->trans('DurationDays');
print '</td>';
if (!$i) {
$totalarray['nbfield']++;

View File

@ -34,17 +34,17 @@ require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php';
if ($conf->deplacement->enabled) {
if (!empty($conf->deplacement->enabled)) {
require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php';
}
if ($conf->expensereport->enabled) {
if (!empty($conf->expensereport->enabled)) {
require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
}
if ($conf->recruitment->enabled) {
if (!empty($conf->recruitment->enabled)) {
require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentcandidature.class.php';
require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php';
}
if ($conf->holiday->enabled) {
if (!empty($conf->holiday->enabled)) {
require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
}
@ -235,8 +235,10 @@ if (!empty($conf->holiday->enabled) && $user->rights->holiday->read) {
print '<tr class="oddeven">';
print '<td class="nowraponall">'.$holidaystatic->getNomUrl(1).'</td>';
print '<td class="tdoverflowmax125">'.$userstatic->getNomUrl(-1, 'leave').'</td>';
print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($langs->trans($typeleaves[$obj->fk_type]['code'])).'">'.dol_escape_htmltag($langs->trans($typeleaves[$obj->fk_type]['code'])).'</td>';
print '<td class="tdoverflowmax100">'.$userstatic->getNomUrl(-1, 'leave').'</td>';
$leavecode = empty($typeleaves[$obj->fk_type]) ? 'Undefined' : $typeleaves[$obj->fk_type]['code'];
print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($langs->trans($leavecode)).'">'.dol_escape_htmltag($langs->trans($leavecode)).'</td>';
$starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning';
$endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon';

View File

@ -30,18 +30,22 @@
-- Types paiement
--
-- Payment modes
insert into llx_c_paiement (id,code,libelle,type,active) values ( 1, 'TIP', 'TIP', 2, 0);
insert into llx_c_paiement (id,code,libelle,type,active) values ( 2, 'VIR', 'Transfer', 2, 1);
insert into llx_c_paiement (id,code,libelle,type,active) values ( 3, 'PRE', 'Debit order', 2, 1);
insert into llx_c_paiement (id,code,libelle,type,active) values ( 4, 'LIQ', 'Cash', 2, 1);
insert into llx_c_paiement (id,code,libelle,type,active) values ( 6, 'CB', 'Credit card', 2, 1);
insert into llx_c_paiement (id,code,libelle,type,active) values ( 7, 'CHQ', 'Cheque', 2, 1);
-- Alternative not common payment modes
insert into llx_c_paiement (id,code,libelle,type,active) values (50, 'VAD', 'Online payment', 2, 0);
insert into llx_c_paiement (id,code,libelle,type,active) values (51, 'TRA', 'Traite', 2, 0);
insert into llx_c_paiement (id,code,libelle,type,active) values (52, 'LCR', 'LCR', 2, 0);
insert into llx_c_paiement (id,code,libelle,type,active) values (53, 'FAC', 'Factor', 2, 0);
-- Payment services
INSERT INTO llx_c_paiement (id,code,libelle,type,active) values (100, 'KLA', 'Klarna', 1, 0);
INSERT INTO llx_c_paiement (id,code,libelle,type,active) values (101, 'SOF', 'Sofort', 1, 0);
INSERT INTO llx_c_paiement (id,code,libelle,type,active) values (102, 'BAN', 'Bancontact', 1, 0);
INSERT INTO llx_c_paiement (id,code,libelle,type,active) values (103, 'IDE', 'iDeal', 1, 0);
INSERT INTO llx_c_paiement (id,code,libelle,type,active) values (104, 'GIR', 'Giropay', 1, 0);
INSERT INTO llx_c_paiement (id,code,libelle,type,active) values (105, 'PPL', 'PayPal', 1, 0);

View File

@ -99,6 +99,9 @@ ALTER TABLE llx_partnership ADD UNIQUE INDEX uk_fk_type_fk_member (fk_type, fk_m
-- v16
UPDATE llx_cronjob set label = 'RecurringInvoicesJob' where label = 'RecurringInvoices';
UPDATE llx_cronjob set label = 'RecurringSupplierInvoicesJob' where label = 'RecurringSupplierInvoices';
ALTER TABLE llx_facture ADD INDEX idx_facture_datef (datef);
ALTER TABLE llx_projet_task_time ADD COLUMN fk_product integer NULL;
@ -285,9 +288,16 @@ ALTER TABLE llx_bank_account ADD COLUMN pti_in_ctti smallint DEFAULT 0 AFTER dom
-- Set default ticket type to OTHER if no default exists
UPDATE llx_c_ticket_type SET use_default=1 WHERE code='OTHER' AND NOT EXISTS(SELECT * FROM (SELECT * FROM llx_c_ticket_type) AS t WHERE use_default=1);
ALTER TABLE llx_user ADD COLUMN ref_employee varchar(50) DEFAULT NULL;
ALTER TABLE llx_user DROP COLUMN webcal_login;
ALTER TABLE llx_user DROP COLUMN module_comm;
ALTER TABLE llx_user DROP COLUMN module_compta;
ALTER TABLE llx_user DROP COLUMN ref_int;
ALTER TABLE llx_user ADD COLUMN ref_employee varchar(50) DEFAULT NULL AFTER entity;
ALTER TABLE llx_user ADD COLUMN national_registration_number varchar(50) DEFAULT NULL;
ALTER TABLE llx_propal ADD last_main_doc VARCHAR(255) NULL AFTER model_pdf;
UPDATE llx_c_country SET eec=0 WHERE eec IS NULL;
@ -309,3 +319,8 @@ UPDATE llx_c_availability SET type_duration = 'w', qty = 4 WHERE code = 'AV_4W';
ALTER TABLE llx_boxes_def ADD COLUMN fk_user integer DEFAULT 0 NOT NULL;
ALTER TABLE llx_contratdet ADD COLUMN rang integer DEFAULT 0 AFTER info_bits;
ALTER TABLE llx_actioncomm MODIFY COLUMN note mediumtext;
DELETE FROM llx_boxes WHERE box_id IN (select rowid FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php'));
DELETE FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php');

View File

@ -55,7 +55,7 @@ create table llx_actioncomm
durationp real, -- planed duration
label varchar(255) NOT NULL, -- label/title of event or topic of email
note text, -- private note of event or content of email
note mediumtext, -- private note of event or content of email
calling_duration integer, -- when event is a phone call, duration of phone call

View File

@ -22,8 +22,8 @@ create table llx_user
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
ref_employee varchar(50),
ref_ext varchar(50), -- reference into an external system (not used by dolibarr)
ref_int varchar(50), -- reference into an internal system (deprecated)
admin smallint DEFAULT 0, -- user has admin profile
@ -108,7 +108,6 @@ create table llx_user
import_key varchar(14), -- import key
default_range integer,
default_c_exp_tax_cat integer,
employee_number varchar(50),
national_registration_number varchar(50),
fk_warehouse integer -- default warehouse os user
)ENGINE=innodb;

View File

@ -94,8 +94,8 @@ print 'Option repair_link_dispatch_lines_supplier_order_lines, (\'test\' or \'co
// Init data
print 'Option set_empty_time_spent_amount (\'test\' or \'confirmed\') is '.(GETPOST('set_empty_time_spent_amount', 'alpha') ?GETPOST('set_empty_time_spent_amount', 'alpha') : 'undefined').'<br>'."\n";
// Structure
print 'Option force_utf8_on_tables, for mysql/mariadb only (\'test\' or \'confirmed\') is '.(GETPOST('force_utf8_on_tables', 'alpha') ?GETPOST('force_utf8_on_tables', 'alpha') : 'undefined').'<br>'."\n";
print "Option force_utf8mb4_on_tables (EXPERIMENTAL!), for mysql/mariadb only ('test' or 'confirmed') is ".(GETPOST('force_utf8mb4_on_tables', 'alpha') ? GETPOST('force_utf8mb4_on_tables', 'alpha') : 'undefined')."<br>\n";
print 'Option force_utf8_on_tables (force utf8 + row=dynamic), for mysql/mariadb only (\'test\' or \'confirmed\') is '.(GETPOST('force_utf8_on_tables', 'alpha') ?GETPOST('force_utf8_on_tables', 'alpha') : 'undefined').'<br>'."\n";
print "Option force_utf8mb4_on_tables (force utf8mb4 + row=dynamic, EXPERIMENTAL!), for mysql/mariadb only ('test' or 'confirmed') is ".(GETPOST('force_utf8mb4_on_tables', 'alpha') ? GETPOST('force_utf8mb4_on_tables', 'alpha') : 'undefined')."<br>\n";
// Rebuild sequence
print 'Option rebuild_sequences, for postgresql only (\'test\' or \'confirmed\') is '.(GETPOST('rebuild_sequences', 'alpha') ?GETPOST('rebuild_sequences', 'alpha') : 'undefined').'<br>'."\n";
print '<br>';
@ -176,7 +176,8 @@ $oneoptionset = 0;
$oneoptionset = (GETPOST('standard', 'alpha') || GETPOST('restore_thirdparties_logos', 'alpha') || GETPOST('clean_linked_elements', 'alpha') || GETPOST('clean_menus', 'alpha')
|| GETPOST('clean_orphelin_dir', 'alpha') || GETPOST('clean_product_stock_batch', 'alpha') || GETPOST('set_empty_time_spent_amount', 'alpha') || GETPOST('rebuild_product_thumbs', 'alpha')
|| GETPOST('clean_perm_table', 'alpha')
|| GETPOST('force_disable_of_modules_not_found', 'alpha') || GETPOST('force_utf8_on_tables', 'alpha')
|| GETPOST('force_disable_of_modules_not_found', 'alpha')
|| GETPOST('force_utf8_on_tables', 'alpha') || GETPOST('force_utf8mb4_on_tables', 'alpha')
|| GETPOST('rebuild_sequences', 'alpha'));
if ($ok && $oneoptionset) {
@ -1218,7 +1219,7 @@ if ($ok && GETPOST('clean_perm_table', 'alpha')) {
// force utf8 on tables
if ($ok && GETPOST('force_utf8_on_tables', 'alpha')) {
print '<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8/utf8_unicode_ci (for mysql/mariadb only)</td></tr>';
print '<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8/utf8_unicode_ci and row_format=dynamic (for mysql/mariadb only)</td></tr>';
if ($db->type == "mysql" || $db->type == "mysqli") {
$force_utf8_on_tables = GETPOST('force_utf8_on_tables', 'alpha');
@ -1240,11 +1241,18 @@ if ($ok && GETPOST('force_utf8_on_tables', 'alpha')) {
print '<tr><td colspan="2">';
print $table;
$sql = "ALTER TABLE ".$table." CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci";
print '<!-- '.$sql.' -->';
$sql1 = "ALTER TABLE ".$table." ROW_FORMAT=dynamic";
$sql2 = "ALTER TABLE ".$table." CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci";
print '<!-- '.$sql1.' -->';
print '<!-- '.$sql2.' -->';
if ($force_utf8_on_tables == 'confirmed') {
$resql = $db->query($sql);
print ' - Done ('.($resql ? 'OK' : 'KO').')';
$resql1 = $db->query($sql1);
if ($resql1) {
$resql2 = $db->query($sql2);
} else {
$resql2 = false;
}
print ' - Done ('.(($resql1 && $resql2) ? 'OK' : 'KO').')';
} else {
print ' - Disabled';
}

View File

@ -283,6 +283,8 @@ RecurringInvoices=Recurring invoices
RecurringInvoice=Recurring invoice
RepeatableInvoice=Template invoice
RepeatableInvoices=Template invoices
RecurringInvoicesJob=Generation of recurring invoices (sales invoices)
RecurringSupplierInvoicesJob=Generation of recurring invoices (purchase invoices)
Repeatable=Template
Repeatables=Templates
ChangeIntoRepeatableInvoice=Convert into template invoice

View File

@ -361,7 +361,7 @@ ListOfThirdParties=List of Third Parties
ShowCompany=Third Party
ShowContact=Contact-Address
ContactsAllShort=All (No filter)
ContactType=Contact type
ContactType=Contact role
ContactForOrders=Order's contact
ContactForOrdersOrShipments=Order's or shipment's contact
ContactForProposals=Proposal's contact

View File

@ -409,6 +409,11 @@ mandatoryHelper=Check this if you want a message to the user when creating / val
DefaultBOM=Default BOM
DefaultBOMDesc=The default BOM recommended to use to manufacture this product. This field can be set only if nature of product is '%s'.
Rank=Rank
MergeOriginProduct=Duplicate product (product you want to delete)
MergeProducts=Merge products
ConfirmMergeProducts=Are you sure you want to merge the chosen product with the current one? All linked objects (invoices, orders, ...) will be moved to the current product, after which the chosen product will be deleted.
ProductsMergeSuccess=Products have been merged
ErrorsProductsMerge=Errors in products merge
SwitchOnSaleStatus=Switch on sale status
SwitchOnPurchaseStatus=Switch on purchase status
StockMouvementExtraFields= Extra Fields (stock mouvement)

View File

@ -756,6 +756,8 @@ if (!defined('NOLOGIN')) {
$login = '';
}
$dol_authmode = '';
if ($login) {
$dol_authmode = $conf->authmode; // This properties is defined only when logged, to say what mode was successfully used
$dol_tz = $_POST["tz"];
@ -2313,185 +2315,16 @@ function top_menu_user($hideloginname = 0, $urllogout = '')
*/
function top_menu_quickadd()
{
global $langs, $conf, $db, $hookmanager, $user;
global $menumanager;
global $langs;
$html = '';
// Define $dropDownQuickAddHtml
$dropDownQuickAddHtml = '<div class="dropdown-header bookmark-header center">';
$dropDownQuickAddHtml .= $langs->trans('QuickAdd');
$dropDownQuickAddHtml .= '</div>';
$dropDownQuickAddHtml .= '<div class="quickadd-body dropdown-body">';
$dropDownQuickAddHtml .= '<div class="quickadd">';
if (!empty($conf->societe->enabled) && $user->rights->societe->creer) {
$langs->load("companies");
$dropDownQuickAddHtml .= '
<!-- Thirdparty link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/societe/card.php?action=create" title="'.$langs->trans("MenuNewThirdParty").'">
'. img_picto('', 'object_company').'<br>'.$langs->trans("ThirdParty").'</a>
</div>
';
}
if (!empty($conf->societe->enabled) && $user->rights->societe->contact->creer) {
$langs->load("companies");
$dropDownQuickAddHtml .= '
<!-- Contact link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/contact/card.php?action=create" title="'.$langs->trans("NewContactAddress").'">
'. img_picto('', 'object_contact').'<br>'.$langs->trans("Contact").'</a>
</div>
';
}
if (!empty($conf->propal->enabled) && $user->rights->propale->creer) {
$langs->load("propal");
$dropDownQuickAddHtml .= '
<!-- Propal link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/comm/propal/card.php?action=create" title="'.$langs->trans("NewPropal").'">
'. img_picto('', 'object_propal').'<br>'.$langs->trans("Proposal").'</a>
</div>
';
}
if (!empty($conf->commande->enabled) && $user->rights->commande->creer) {
$langs->load("orders");
$dropDownQuickAddHtml .= '
<!-- Order link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/commande/card.php?action=create" title="'.$langs->trans("NewOrder").'">
'. img_picto('', 'object_order').'<br>'.$langs->trans("Order").'</a>
</div>
';
}
if (!empty($conf->facture->enabled) && $user->rights->facture->creer) {
$langs->load("bills");
$dropDownQuickAddHtml .= '
<!-- Invoice link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create" title="'.$langs->trans("NewBill").'">
'. img_picto('', 'object_bill').'<br>'.$langs->trans("Bill").'</a>
</div>
';
}
if (!empty($conf->contrat->enabled) && $user->rights->contrat->creer) {
$langs->load("contracts");
$dropDownQuickAddHtml .= '
<!-- Contract link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create" title="'.$langs->trans("NewContractSubscription").'">
'. img_picto('', 'object_contract').'<br>'.$langs->trans("Contract").'</a>
</div>
';
}
if (!empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->creer) {
$langs->load("supplier_proposal");
$dropDownQuickAddHtml .= '
<!-- Supplier proposal link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/supplier_proposal/card.php?action=create" title="'.$langs->trans("NewAskPrice").'">
'. img_picto('', 'object_propal').'<br>'.$langs->trans("AskPrice").'</a>
</div>
';
}
if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->creer) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->creer)) {
$langs->load("orders");
$dropDownQuickAddHtml .= '
<!-- Supplier order link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?action=create" title="'.$langs->trans("NewSupplierOrderShort").'">
'. img_picto('', 'object_order').'<br>'.$langs->trans("SupplierOrder").'</a>
</div>
';
}
if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->creer) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->creer)) {
$langs->load("bills");
$dropDownQuickAddHtml .= '
<!-- Supplier invoice link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create" title="'.$langs->trans("NewBill").'">
'. img_picto('', 'object_bill').'<br>'.$langs->trans("SupplierBill").'</a>
</div>
';
}
if (!empty($conf->product->enabled) && $user->rights->produit->creer) {
$langs->load("products");
$dropDownQuickAddHtml .= '
<!-- Product link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/product/card.php?action=create&amp;type=0" title="'.$langs->trans("NewProduct").'">
'. img_picto('', 'object_product').'<br>'.$langs->trans("Product").'</a>
</div>
';
}
if (!empty($conf->service->enabled) && $user->rights->service->creer) {
$langs->load("products");
$dropDownQuickAddHtml .= '
<!-- Service link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/product/card.php?action=create&amp;type=1" title="'.$langs->trans("NewService").'">
'. img_picto('', 'object_service').'<br>'.$langs->trans("Service").'</a>
</div>
';
}
if (!empty($conf->expensereport->enabled) && $user->rights->expensereport->creer) {
$langs->load("trips");
$dropDownQuickAddHtml .= '
<!-- Expense report link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/expensereport/card.php?action=create&fk_user_author='.$user->id.'" title="'.$langs->trans("AddTrip").'">
'. img_picto('', 'object_trip').'<br>'.$langs->trans("ExpenseReport").'</a>
</div>
';
}
if (!empty($conf->holiday->enabled) && $user->rights->holiday->write) {
$langs->load("holiday");
$dropDownQuickAddHtml .= '
<!-- Holiday link -->
<div class="quickaddblock center">
<a class="quickadddropdown-icon-link" href="'.DOL_URL_ROOT.'/holiday/card.php?action=create&fuserid='.$user->id.'" title="'.$langs->trans("AddCP").'">
'. img_picto('', 'object_holiday').'<br>'.$langs->trans("Holidays").'</a>
</div>
';
}
// Execute hook printTopRightMenu (hooks should output string like '<div class="login"><a href="">mylink</a></div>')
$parameters = array();
$result = $hookmanager->executeHooks('printQuickAddBlock', $parameters); // Note that $action and $object may have been modified by some hooks
if (is_numeric($result)) {
if ($result == 0) {
$dropDownQuickAddHtml .= $hookmanager->resPrint; // add
} else {
$dropDownQuickAddHtml = $hookmanager->resPrint; // replace
}
} else {
$dropDownQuickAddHtml .= $result; // For backward compatibility
}
$dropDownQuickAddHtml .= '</div>';
$dropDownQuickAddHtml .= '</div>';
$html .= '<!-- div for quick add link -->
<div id="topmenu-quickadd-dropdown" class="atoplogin dropdown inline-block">
<a class="dropdown-toggle login-dropdown-a" data-toggle="dropdown" href="#" title="'.$langs->trans('QuickAdd').' ('.$langs->trans('QuickAddMenuShortCut').')">
<i class="fa fa-plus-circle" ></i>
</a>
<div class="dropdown-menu">
'.$dropDownQuickAddHtml.'
</div>
<div class="dropdown-menu">'.printDropdownQuickadd().'</div>
</div>';
$html .= '
<!-- Code to show/hide the user drop-down -->
@ -2526,6 +2359,152 @@ function top_menu_quickadd()
return $html;
}
/**
* Generate list of quickadd items
*
* @return string HTML output
*/
function printDropdownQuickadd()
{
global $conf, $user, $langs, $hookmanager;
$items = array(
'items' => array(
array(
"url" => "/societe/card.php?action=create",
"title" => "MenuNewThirdParty@companies",
"name" => "ThirdParty@companies",
"picto" => "object_company",
"activation" => !empty($conf->societe->enabled) && $user->rights->societe->creer, // vs hooking
"position" => 10,
),
array(
"url" => "/contact/card.php?action=create",
"title" => "NewContactAddress@companies",
"name" => "Contact@companies",
"picto" => "object_contact",
"activation" => !empty($conf->societe->enabled) && $user->rights->societe->contact->creer, // vs hooking
"position" => 20,
),
array(
"url" => "/comm/propal/card.php?action=create",
"title" => "NewPropal@propal",
"name" => "Proposal@propal",
"picto" => "object_propal",
"activation" => !empty($conf->propal->enabled) && $user->rights->propale->creer, // vs hooking
"position" => 30,
),
array(
"url" => "/commande/card.php?action=create",
"title" => "NewOrder@orders",
"name" => "Order@orders",
"picto" => "object_order",
"activation" => !empty($conf->commande->enabled) && $user->rights->commande->creer, // vs hooking
"position" => 40,
),
array(
"url" => "/compta/facture/card.php?action=create",
"title" => "NewBill@bills",
"name" => "Bill@bills",
"picto" => "object_bill",
"activation" => !empty($conf->facture->enabled) && $user->rights->facture->creer, // vs hooking
"position" => 50,
),
array(
"url" => "/contrat/card.php?action=create",
"title" => "NewContractSubscription@contracts",
"name" => "Contract@contracts",
"picto" => "object_contract",
"activation" => !empty($conf->contrat->enabled) && $user->rights->contrat->creer, // vs hooking
"position" => 60,
),
array(
"url" => "/supplier_proposal/card.php?action=create",
"title" => "SupplierProposalNew@supplier_proposal",
"name" => "SupplierProposal@supplier_proposal",
"picto" => "object_propal",
"activation" => !empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->creer, // vs hooking
"position" => 70,
),
array(
"url" => "/fourn/commande/card.php?action=create",
"title" => "NewSupplierOrderShort@orders",
"name" => "SupplierOrder@orders",
"picto" => "object_order",
"activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->creer) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->creer), // vs hooking
"position" => 80,
),
array(
"url" => "/fourn/facture/card.php?action=create",
"title" => "NewBill@bills",
"name" => "SupplierBill@bills",
"picto" => "object_bill",
"activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->creer) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->creer), // vs hooking
"position" => 90,
),
array(
"url" => "/product/card.php?action=create&amp;type=0",
"title" => "NewProduct@products",
"name" => "Product@products",
"picto" => "object_product",
"activation" => !empty($conf->product->enabled) && $user->rights->produit->creer, // vs hooking
"position" => 100,
),
array(
"url" => "/product/card.php?action=create&amp;type=1",
"title" => "NewService@products",
"name" => "Service@products",
"picto" => "object_service",
"activation" => !empty($conf->service->enabled) && $user->rights->service->creer, // vs hooking
"position" => 110,
),
),
);
$dropDownQuickAddHtml = '';
// Define $dropDownQuickAddHtml
$dropDownQuickAddHtml .= '<div class="quickadd-body dropdown-body">';
$dropDownQuickAddHtml .= '<div class="dropdown-quickadd-list">';
// Allow the $items of the menu to be manipulated by modules
$parameters = array();
$hook_items = $items;
$reshook = $hookmanager->executeHooks('menuDropdownQuickaddItems', $parameters, $hook_items); // Note that $action and $object may have been modified by some hooks
if (is_numeric($reshook) && is_array($hookmanager->results)) {
if ($reshook == 0) {
$items['items'] = array_merge($items['items'], $hookmanager->results); // add
} else {
$items = $hookmanager->results; // replace
}
// Sort menu items by 'position' value
$position = array();
foreach ($items['items'] as $key => $row) {
$position[$key] = $row['position'];
}
array_multisort($position, SORT_ASC, $items['items']);
}
foreach ($items['items'] as $item) {
if (!$item['activation']) {
continue;
}
$langs->load(explode('@', $item['title'])[1]);
$langs->load(explode('@', $item['name'])[1]);
$dropDownQuickAddHtml .= '
<a class="dropdown-item quickadd-item" href="'.DOL_URL_ROOT.$item['url'].'" title="'.$langs->trans(explode('@', $item['title'])[0]).'">
'. img_picto('', $item['picto'], 'style="width:18px;"') . ' ' . $langs->trans(explode('@', $item['name'])[0]) . '</a>
';
}
$dropDownQuickAddHtml .= '</div>';
$dropDownQuickAddHtml .= '</div>';
return $dropDownQuickAddHtml;
}
/**
* Build the tooltip on top menu bookmark
*

View File

@ -226,6 +226,174 @@ if (empty($reshook)) {
}
$action = '';
}
// merge products
if ($action == 'confirm_merge' && $confirm == 'yes' && $user->rights->societe->creer) {
$error = 0;
$productOriginId = GETPOST('product_origin', 'int');
$productOrigin = new Product($db);
if ($productOriginId <= 0) {
$langs->load('errors');
setEventMessages($langs->trans('ErrorProductIdIsMandatory', $langs->transnoentitiesnoconv('MergeOriginProduct')), null, 'errors');
} else {
if (!$error && $productOrigin->fetch($productOriginId) < 1) {
setEventMessages($langs->trans('ErrorRecordNotFound'), null, 'errors');
$error++;
}
if (!$error) {
// TODO Move the merge function into class of object.
$db->begin();
// Recopy some data
$listofproperties = array(
'ref',
'ref_ext',
'label',
'description',
'url',
'barcode',
'fk_barcode_type',
'import_key',
'mandatory_period',
'accountancy_code_buy',
'accountancy_code_buy_intra',
'accountancy_code_buy_export',
'accountancy_code_sell',
'accountancy_code_sell_intra',
'accountancy_code_sell_export'
);
foreach ($listofproperties as $property) {
if (empty($object->$property)) {
$object->$property = $productOrigin->$property;
}
}
// Concat some data
$listofproperties = array(
'note_public', 'note_private'
);
foreach ($listofproperties as $property) {
$object->$property = dol_concatdesc($object->$property, $productOrigin->$property);
}
// Merge extrafields
if (is_array($productOrigin->array_options)) {
foreach ($productOrigin->array_options as $key => $val) {
if (empty($object->array_options[$key])) {
$object->array_options[$key] = $val;
}
}
}
// Merge categories
$static_cat = new Categorie($db);
$custcats_ori = $static_cat->containing($productOrigin->id, 'product', 'id');
$custcats = $static_cat->containing($object->id, 'product', 'id');
$custcats = array_merge($custcats, $custcats_ori);
$object->setCategories($custcats);
// If product has a new code that is same than origin, we clean origin code to avoid duplicate key from database unique keys.
if ($productOrigin->barcode == $object->barcode) {
dol_syslog("We clean customer and supplier code so we will be able to make the update of target");
$productOrigin->barcode = '';
//$productOrigin->update($productOrigin->id, $user, 0, 'merge');
}
// Update
$result = $object->update($object->id, $user, 0, 'merge');
if ($result <= 0) {
setEventMessages($object->error, $object->errors, 'errors');
$error++;
}
// Move links
if (!$error) {
// TODO add this functionality into the api_products.class.php
// TODO Mutualise the list into object product.class.php
$objects = array(
'ActionComm' => '/comm/action/class/actioncomm.class.php',
'Bom' => '/bom/class/bom.class.php',
// do not use Categorie, it cause foreign key error, merge is done before
//'Categorie' => '/categories/class/categorie.class.php',
'Commande' => '/commande/class/commande.class.php',
'CommandeFournisseur' => '/fourn/class/fournisseur.commande.class.php',
'Contrat' => '/contrat/class/contrat.class.php',
'Delivery' => '/delivery/class/delivery.class.php',
'Facture' => '/compta/facture/class/facture.class.php',
'FactureFournisseur' => '/fourn/class/fournisseur.facture.class.php',
'FactureRec' => '/compta/facture/class/facture-rec.class.php',
'FichinterRec' => '/fichinter/class/fichinterrec.class.php',
'ProductFournisseur' => '/fourn/class/fournisseur.product.class.php',
'Propal' => '/comm/propal/class/propal.class.php',
'Reception' => '/reception/class/reception.class.php',
'SupplierProposal' => '/supplier_proposal/class/supplier_proposal.class.php',
);
//First, all core objects must update their tables
foreach ($objects as $object_name => $object_file) {
require_once DOL_DOCUMENT_ROOT.$object_file;
if (!$error && !$object_name::replaceProduct($db, $productOrigin->id, $object->id)) {
$error++;
setEventMessages($db->lasterror(), null, 'errors');
break;
}
}
}
// External modules should update their ones too
if (!$error) {
$reshook = $hookmanager->executeHooks(
'replaceProduct',
array(
'soc_origin' => $productOrigin->id,
'soc_dest' => $object->id,
),
$object,
$action
);
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
$error++;
}
}
if (!$error) {
$object->context = array(
'merge' => 1,
'mergefromid' => $productOrigin->id,
);
// Call trigger
$result = $object->call_trigger('PRODUCT_MODIFY', $user);
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
$error++;
}
// End call triggers
}
if (!$error) {
// We finally remove the old product
// TODO merge attached files from old product into new one before delete
if ($productOrigin->delete($user) < 1) {
$error++;
}
}
if (!$error) {
setEventMessages($langs->trans('ProductsMergeSuccess'), null, 'mesgs');
$db->commit();
} else {
$langs->load("errors");
setEventMessages($langs->trans('ErrorsProductsMerge'), null, 'errors');
$db->rollback();
}
}
}
}
// Type
if ($action == 'setfk_product_type' && $usercancreate) {
@ -2502,6 +2670,17 @@ if (($action == 'delete' && (empty($conf->use_javascript_ajax) || !empty($conf->
|| (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) { // Always output when not jmobile nor js
$formconfirm = $form->formconfirm("card.php?id=".$object->id, $langs->trans("DeleteProduct"), $langs->trans("ConfirmDeleteProduct"), "confirm_delete", '', 0, "action-delete");
}
if ($action == 'merge') {
$formquestion = array(
array(
'name' => 'product_origin',
'label' => $langs->trans('MergeOriginProduct'),
'type' => 'other',
'value' => $form->select_produits('', 'product_origin', '', 0, 0, 1, 2, '', 1, array(), 0, 1, 0, 'minwidth200', 0, '', null, 1),
)
);
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("MergeProducts"), $langs->trans("ConfirmMergeProducts"), "confirm_merge", $formquestion, 'no', 1, 250);
}
// Clone confirmation
if (($action == 'clone' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js
@ -2572,6 +2751,9 @@ if ($action != 'create' && $action != 'edit') {
} else {
print dolGetButtonAction($langs->trans("ProductIsUsed"), $langs->trans('Delete'), 'delete', '#', '', false);
}
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') > 1) {
print '<a class="butActionDelete" href="card.php?action=merge&id='.$object->id.'" title="'.dol_escape_htmltag($langs->trans("MergeProducts")).'">'.$langs->trans('Merge').'</a>'."\n";
}
} else {
print dolGetButtonAction($langs->trans("NotEnoughPermissions"), $langs->trans('Delete'), 'delete', '#', '', false);
}

View File

@ -491,8 +491,7 @@ class Product extends CommonObject
'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'index'=>0, 'position'=>1000),
//'tosell' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>1000, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Active', -1=>'Cancel')),
//'tobuy' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>1000, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Active', -1=>'Cancel')),
'mandatory_period' =>array('type'=>'integer', 'label'=>'mandatory_period', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>1000),
'mandatory_period' => array('type'=>'integer', 'label'=>'mandatory_period', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>1000),
);
/**

View File

@ -3,7 +3,7 @@
* Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2018 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2018-2019 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2018-2021 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2021 Waël Almoman <info@almoman.com>
* Copyright (C) 2021 Dorian Vabre <dorian.vabre@gmail.com>
*
@ -2252,7 +2252,7 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme
//if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) || ! empty($paymentintent))
//{
print '
<table id="dolpaymenttable" summary="Payment form" class="center">
<table id="dolpaymenttable" summary="Payment form" class="center" width="100%">
<tbody><tr><td class="textpublicpayment">';
if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
@ -2260,18 +2260,14 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme
}
print '<div class="form-row left">';
print '<label for="card-element">'.$langs->trans("CreditOrDebitCard").'</label>';
//print '<label for="payment-element">'.$langs->trans("CreditOrDebitCard").'</label>';
if (!empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) {
print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" autofocus required>';
//print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" autofocus required>';
}
print '<div id="card-element">
print '<div id="payment-element">
<!-- a Stripe Element will be inserted here. -->
</div>';
print '<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
</div>';
print '<br>';
@ -2418,9 +2414,12 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme
// Create a Stripe client.
var stripe = Stripe('<?php echo $stripearrayofkeys['publishable_key']; // Defined into config.php ?>');
var cardButton = document.getElementById('buttontopay');
var clientSecret = cardButton.dataset.secret;
var options = { clientSecret: clientSecret,};
// Create an instance of Elements
var elements = stripe.elements();
var elements = stripe.elements(options);
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
@ -2441,49 +2440,28 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme
}
};
var cardElement = elements.create('card', {style: style});
var paymentElement = elements.create("payment");
// Add an instance of the card Element into the `card-element` <div>
cardElement.mount('#card-element');
// Handle real-time validation errors from the card Element.
cardElement.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
console.log("Show event error (like 'Incorrect card number', ...)");
displayError.textContent = event.error.message;
} else {
console.log("Reset error message");
displayError.textContent = '';
}
});
paymentElement.mount("#payment-element");
// Handle form submission
var cardholderName = document.getElementById('cardholder-name');
var cardButton = document.getElementById('buttontopay');
var clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', function(event) {
console.log("We click on buttontopay");
event.preventDefault();
if (cardholderName.value == '')
{
console.log("Field Card holder is empty");
var displayError = document.getElementById('card-errors');
displayError.textContent = '<?php print dol_escape_js($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CardOwner"))); ?>';
}
else
{
/* Disable button to pay and show hourglass cursor */
jQuery('#hourglasstopay').show();
jQuery('#buttontopay').hide();
stripe.handleCardPayment(
clientSecret, cardElement, {
stripe.confirmPayment({
elements,confirmParams: {
return_url: '<?php echo $urlok; ?>',
payment_method_data: {
billing_details: {
name: cardholderName.value
name: 'test'
<?php if (GETPOST('email', 'alpha') || (is_object($object) && is_object($object->thirdparty) && !empty($object->thirdparty->email))) {
?>, email: '<?php echo dol_escape_js(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $object->thirdparty->email); ?>'<?php
} ?>
@ -2507,6 +2485,7 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme
} else {
print 'false';
} ?> /* true when a customer was provided when creating payment intent. true ask to save the card */
},
}
).then(function(result) {
console.log(result);
@ -2527,7 +2506,7 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme
jQuery('#payment-form').submit();
}
});
}
});
<?php

View File

@ -2078,4 +2078,21 @@ class Reception extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'commande_fournisseur_dispatch'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
}

View File

@ -46,10 +46,6 @@ $sortfield = GETPOST('sortfield','alpha');
$page = GETPOST('page','int');
*/
if (!$user->rights->resource->read) {
accessforbidden();
}
$object = new Dolresource($db);
$hookmanager->initHooks(array('element_resource'));
@ -71,11 +67,22 @@ $cancel = GETPOST('cancel', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$socid = GETPOST('socid', 'int');
if (empty($mandatory)) {
$mandatory = 0;
}
if (empty($busy)) {
$busy = 0;
}
if ($socid > 0) { // Special for thirdparty
$element_id = $socid;
$element = 'societe';
}
if (!$user->rights->resource->read) {
accessforbidden();
}
// Permission is not permission on resources. We just make link here on objects.
if ($element == 'action') {
$result = restrictedArea($user, 'agenda', $element_id, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id');
@ -365,7 +372,7 @@ if (!$ret) {
print '<div class="underbanner clearboth"></div>';
print '<table class="border tableforfield" width="100%">';
print '<table class="border tableforfield centpercent">';
// Type
if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) {

View File

@ -1180,13 +1180,15 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
document.formsoc.private.value=1;
});
var canHaveCategoryIfNotCustomerProspectSupplier = ' . (empty($conf->global->THIRDPARTY_CAN_HAVE_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT) ? '0' : '1') . ';
init_customer_categ();
$("#customerprospect").change(function() {
init_customer_categ();
});
function init_customer_categ() {
console.log("is customer or prospect = "+jQuery("#customerprospect").val());
if (jQuery("#customerprospect").val() == 0 && (jQuery("#fournisseur").val() == 0 || ' . (empty($conf->global->THIRDPARTY_CAN_HAVE_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT_SUPPLIER) ? '1' : '0').'))
if (jQuery("#customerprospect").val() == 0 && !canHaveCategoryIfNotCustomerProspectSupplier)
{
jQuery(".visibleifcustomer").hide();
}
@ -1318,16 +1320,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print '<tr id="name_alias"><td><label for="name_alias_input">'.$langs->trans('AliasNames').'</label></td>';
print '<td colspan="3"><input type="text" class="minwidth300" name="name_alias" id="name_alias_input" value="'.dol_escape_htmltag($object->name_alias).'"></td></tr>';
// Parent company
if (empty($conf->global->SOCIETE_DISABLE_PARENTCOMPANY)) {
print '<tr>';
print '<td>'.$langs->trans('ParentCompany').'</td>';
print '<td colspan="3" class="maxwidthonsmartphone">';
print img_picto('', 'company', 'class="paddingrightonly"');
print $form->select_thirdparty_list('', 'parent_company_id', '', $langs->trans("ThirdParty"));
print '</td></tr>';
}
// Prospect/Customer
print '<tr><td class="titlefieldcreate">'.$form->editfieldkey('ProspectCustomer', 'customerprospect', '', $object, 0, 'string', '', 1).'</td>';
print '<td class="maxwidthonsmartphone">';
@ -1639,12 +1631,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$langs->load('categories');
// Customer
//if ($object->prospect || $object->client || (! $object->fournisseur && ! empty($conf->global->THIRDPARTY_CAN_HAVE_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT_SUPPLIER))) {
print '<tr class="visibleifcustomer"><td class="toptd">'.$form->editfieldkey('CustomersProspectsCategoriesShort', 'custcats', '', $object, 0).'</td><td colspan="3">';
$cate_arbo = $form->select_all_categories(Categorie::TYPE_CUSTOMER, null, 'parent', null, null, 1);
print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('custcats', $cate_arbo, GETPOST('custcats', 'array'), null, null, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
print "</td></tr>";
//}
if (!empty($conf->global->THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION)) {
print '<tr class="individualline"><td class="toptd">'.$form->editfieldkey('ContactCategoriesShort', 'contcats', '', $object, 0).'</td><td colspan="3">';
@ -1675,6 +1665,16 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$parameters = array('socid'=>$socid, 'colspan' => ' colspan="3"', 'colspanvalue' => '3');
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
// Parent company
if (empty($conf->global->SOCIETE_DISABLE_PARENTCOMPANY)) {
print '<tr>';
print '<td>'.$langs->trans('ParentCompany').'</td>';
print '<td colspan="3" class="maxwidthonsmartphone">';
print img_picto('', 'company', 'class="paddingrightonly"');
print $form->select_company(GETPOST('parent_company_id'), 'parent_company_id', '', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx');
print '</td></tr>';
}
// Assign a sale representative
print '<tr>';
print '<td>'.$form->editfieldkey('AllocateCommercial', 'commercial_id', '', $object, 0).'</td>';
@ -1914,13 +1914,15 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
}
});
var canHaveCategoryIfNotCustomerProspectSupplier = ' . (empty($conf->global->THIRDPARTY_CAN_HAVE_CUSTOMER_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT) ? '0' : '1') . ';
init_customer_categ();
$("#customerprospect").change(function() {
init_customer_categ();
});
function init_customer_categ() {
console.log("is customer or prospect = "+jQuery("#customerprospect").val());
if (jQuery("#customerprospect").val() == 0 && (jQuery("#fournisseur").val() == 0 || '.(empty($conf->global->THIRDPARTY_CAN_HAVE_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT_SUPPLIER) ? '1' : '0').'))
if (jQuery("#customerprospect").val() == 0 && !canHaveCategoryIfNotCustomerProspectSupplier)
{
jQuery(".visibleifcustomer").hide();
}
@ -2734,7 +2736,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Tags / categories
if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) {
// Customer
if ($object->prospect || $object->client || (!$object->fournisseur && !empty($conf->global->THIRDPARTY_CAN_HAVE_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT_SUPPLIER))) {
if ($object->prospect || $object->client || !empty($conf->global->THIRDPARTY_CAN_HAVE_CUSTOMER_CATEGORY_EVEN_IF_NOT_CUSTOMER_PROSPECT)) {
print '<tr><td>'.$langs->trans("CustomersCategoriesShort").'</td>';
print '<td>';
print $form->showCategories($object->id, Categorie::TYPE_CUSTOMER, 1);

View File

@ -193,8 +193,8 @@ class Societe extends CommonObject
'tva_intra' =>array('type'=>'varchar(20)', 'label'=>'Tva intra', 'enabled'=>1, 'visible'=>-1, 'position'=>210),
'capital' =>array('type'=>'double(24,8)', 'label'=>'Capital', 'enabled'=>1, 'visible'=>-1, 'position'=>215),
'fk_stcomm' =>array('type'=>'integer', 'label'=>'CommercialStatus', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>220),
'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225),
'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230),
'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225),
'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230),
'prefix_comm' =>array('type'=>'varchar(5)', 'label'=>'Prefix comm', 'enabled'=>'$conf->global->SOCIETE_USEPREFIX', 'visible'=>-1, 'position'=>235),
'client' =>array('type'=>'tinyint(4)', 'label'=>'Client', 'enabled'=>1, 'visible'=>-1, 'position'=>240),
'fournisseur' =>array('type'=>'tinyint(4)', 'label'=>'Fournisseur', 'enabled'=>1, 'visible'=>-1, 'position'=>245),

View File

@ -1425,11 +1425,13 @@ if ($action == 'create') {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
$objectsrc->printOriginLinesList();
print '</table>';
print '</div>';
}
} else {
/*

View File

@ -2697,6 +2697,23 @@ class SupplierProposal extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
/**
* Function used to replace a product id with another one.
*
* @param DoliDB $db Database handler
* @param int $origin_id Old product id
* @param int $dest_id New product id
* @return bool
*/
public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
{
$tables = array(
'supplier_proposaldet'
);
return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
}
}

View File

@ -57,7 +57,7 @@ $action = GETPOST('action', 'aZ09');
$setterminal = GETPOST('setterminal', 'int');
$setcurrency = GETPOST('setcurrency', 'aZ09');
if ($_SESSION["takeposterminal"] == "") {
if (empty($_SESSION["takeposterminal"])) {
if ($conf->global->TAKEPOS_NUM_TERMINALS == "1") {
$_SESSION["takeposterminal"] = 1; // Use terminal 1 if there is only 1 terminal
} elseif (!empty($_COOKIE["takeposterminal"])) {
@ -114,6 +114,11 @@ $result = restrictedArea($user, 'takepos', 0, '');
$form = new Form($db);
$disablejs = 0;
$disablehead = 0;
$arrayofjs = array();
$arrayofcss = array();
// Title
$title = 'TakePOS - Dolibarr '.DOL_VERSION;
if (!empty($conf->global->MAIN_APPLICATION_TITLE)) {
@ -129,22 +134,22 @@ top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
<link rel="stylesheet" href="css/pos.css.php">
<link rel="stylesheet" href="css/colorbox.css" type="text/css" media="screen" />
<?php
if ($conf->global->TAKEPOS_COLOR_THEME == 1) {
if (getDolGlobalInt('TAKEPOS_COLOR_THEME') == 1) {
print '<link rel="stylesheet" href="css/colorful.css">';
}
?>
<script type="text/javascript" src="js/jquery.colorbox-min.js"></script> <!-- TODO It seems we don't need this -->
<script type="text/javascript">
<?php
$categories = $categorie->get_full_arbo('product', (($conf->global->TAKEPOS_ROOT_CATEGORY_ID > 0) ? $conf->global->TAKEPOS_ROOT_CATEGORY_ID : 0), 1);
$categories = $categorie->get_full_arbo('product', ((getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID') > 0) ? getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID') : 0), 1);
// Search root category to know its level
//$conf->global->TAKEPOS_ROOT_CATEGORY_ID=0;
$levelofrootcategory = 0;
if ($conf->global->TAKEPOS_ROOT_CATEGORY_ID > 0) {
if (getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID') > 0) {
foreach ($categories as $key => $categorycursor) {
if ($categorycursor['id'] == $conf->global->TAKEPOS_ROOT_CATEGORY_ID) {
if ($categorycursor['id'] == getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID')) {
$levelofrootcategory = $categorycursor['level'];
break;
}
@ -311,7 +316,7 @@ function LoadProducts(position, issubcat) {
//console.log("ishow"+ishow+" idata="+idata);
console.log(data[idata]);
if (typeof (data[idata]) == "undefined") {
<?php if (!$conf->global->TAKEPOS_HIDE_PRODUCT_IMAGES) {
<?php if (!getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) {
echo '$("#prodivdesc"+ishow).hide();';
echo '$("#prodesc"+ishow).text("");';
echo '$("#proimg"+ishow).attr("title","");';
@ -333,9 +338,9 @@ function LoadProducts(position, issubcat) {
$titlestring .= " + ' - ".dol_escape_js($langs->trans("Barcode").': ')."' + data[idata]['barcode']";
?>
var titlestring = <?php echo $titlestring; ?>;
<?php if (!$conf->global->TAKEPOS_HIDE_PRODUCT_IMAGES) {
<?php if (!getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) {
echo '$("#prodivdesc"+ishow).show();';
if ($conf->global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) {
if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'ref\'].bold() + \' - \' + data[parseInt(idata)][\'label\']);';
} else {
echo '$("#prodesc"+ishow).text(data[parseInt(idata)][\'label\']);';
@ -406,7 +411,7 @@ function MoreProducts(moreorless) {
//Only show products with status=1 (for sell)
$("#prodivdesc"+ishow).show();
<?php
if ($conf->global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) { ?>
if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { ?>
$("#prodesc"+ishow).html(data[parseInt(idata)]['ref'].bold() + ' - ' + data[parseInt(idata)]['label']);
<?php } else { ?>
$("#prodesc"+ishow).text(data[parseInt(idata)]['label']);
@ -589,7 +594,7 @@ function Search2(keyCodeForEnter) {
?>
var titlestring = <?php echo $titlestring; ?>;
<?php
if ($conf->global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) { ?>
if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { ?>
$("#prodesc" + i).html(data[i]['ref'].bold() + ' - ' + data[i]['label']);
<?php } else { ?>
$("#prodesc" + i).text(data[i]['label']);
@ -749,9 +754,9 @@ function OpenDrawer(){
data: { token: 'notrequired' },
<?php
if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
echo "url: '".$conf->global->TAKEPOS_PRINT_SERVER."/printer/drawer.php',";
echo "url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER', 'localhost')."/printer/drawer.php',";
} else {
echo "url: 'http://".$conf->global->TAKEPOS_PRINT_SERVER.":8111/print',";
echo "url: 'http://".getDolGlobalString('TAKEPOS_PRINT_SERVER', 'localhost').":8111/print',";
}
?>
data: "opendrawer"
@ -940,7 +945,8 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) {
<div class="modal-body">
<button type="button" class="block" onclick="location.href='index.php?setterminal=1'"><?php print $langs->trans("Terminal"); ?> 1</button>
<?php
for ($i = 2; $i <= $conf->global->TAKEPOS_NUM_TERMINALS; $i++) {
$nbloop = getDolGlobalInt('TAKEPOS_NUM_TERMINALS');
for ($i = 2; $i <= $nbloop; $i++) {
print '<button type="button" class="block" onclick="location.href=\'index.php?setterminal='.$i.'\'">'.$langs->trans("Terminal").' '.$i.'</button>';
}
?>
@ -1098,7 +1104,7 @@ $menus[$r++] = array('title'=>'<span class="fas fa-cut paddingrightonly"></span>
// BAR RESTAURANT specific menu
if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
if ($conf->global->TAKEPOS_ORDER_PRINTERS) {
if (getDolGlobalString('TAKEPOS_ORDER_PRINTERS')) {
$menus[$r++] = array('title'=>'<span class="fa fa-blender-phone paddingrightonly"></span><div class="trunc">'.$langs->trans("Order").'</span>', 'action'=>'TakeposPrintingOrder();');
}
//Button to print receipt before payment
@ -1218,12 +1224,13 @@ if (!empty($conf->global->TAKEPOS_WEIGHING_SCALE)) {
<!-- Show categories -->
<?php
if ($conf->global->TAKEPOS_HIDE_CATEGORIES == 1) {
if (getDolGlobalInt('TAKEPOS_HIDE_CATEGORIES') == 1) {
print '<div class="div4" style= "display: none;">';
} else {
print '<div class="div4">';
}
$count = 0;
$count = 0;
while ($count < $MAXCATEG) {
?>
<div class="wrapper" <?php if ($count == ($MAXCATEG - 2)) {
@ -1260,7 +1267,7 @@ if (!empty($conf->global->TAKEPOS_WEIGHING_SCALE)) {
</div>
<!-- Show product -->
<div class="div5"<?php if ($conf->global->TAKEPOS_HIDE_CATEGORIES == 1) {
<div class="div5"<?php if (getDolGlobalInt('TAKEPOS_HIDE_CATEGORIES') == 1) {
print ' style="width:100%;"';
} ?>>
<?php

View File

@ -59,6 +59,8 @@ $action = GETPOST('action', 'aZ09');
$idproduct = GETPOST('idproduct', 'int');
$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
$placeid = 0; // $placeid is ID of invoice
$mobilepage = GETPOST('mobilepage', 'alpha');
// Terminal is stored into $_SESSION["takeposterminal"];
if (empty($user->rights->takepos->run) && !defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
@ -80,7 +82,6 @@ if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->la
exit;
}
}
$mobilepage = GETPOST('mobilepage', 'alpha');
$title = 'TakePOS - Dolibarr '.DOL_VERSION;
if (!empty($conf->global->MAIN_APPLICATION_TITLE)) {
$title = 'TakePOS - '.$conf->global->MAIN_APPLICATION_TITLE;
@ -1273,8 +1274,8 @@ if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
if ($mobilepage == "invoice" || $mobilepage == "") {
// If not on smartphone version or if it is the invoice page
//print 'mobilepage='.$mobilepage;
print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".($label ? $label : '?')."</b><br>";
print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".($floor ? $floor : '?')."</b>";
print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".(empty($label) ? '?' : $label)."</b><br>";
print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".(empty($floor) ? '?' : $floor)."</b>";
} elseif (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
print $mysoc->name;
} elseif ($mobilepage == "cats") {

View File

@ -21,8 +21,8 @@ button.dropdown-item.global-search-item {
}
#topmenu-bookmark-dropdown .dropdown-menu {
min-width: 300px;
max-width: 360px;
min-width: 360px;
max-width: 400px;
}
@ -433,7 +433,15 @@ a.top-menu-dropdown-link {
.quickadd-body.dropdown-body {
padding: unset;
padding-top: 15px;
}
.quickadd-item {
padding-top: 6px;
padding-bottom: 6px;
}
.quickadd-item:before {
content: none;
}
.quickadd-header {
@ -491,4 +499,9 @@ div.quickaddblock:focus {
margin-left: 5px;
right: 0;
}
#topmenu-bookmark-dropdown .dropdown-menu {
min-width: 280px;
max-width: 360px;
}
}

View File

@ -3612,6 +3612,13 @@ td.border, div.tagtable div div.border {
.fichehalfright table.noborder {
margin: 0px 0px 0px 0px;
}
table.liste, table.noborder:not(.paymenttable):not(.margintable):not(.tableforcontact), table.formdoc, div.noborder:not(.paymenttable):not(.margintable):not(.tableforcontact) {
<?php
if ($userborderontable) { ?>
border-left: 1px solid var(--colortopbordertitle1);
border-right: 1px solid var(--colortopbordertitle1);
<?php } ?>
}
table.liste, table.noborder, table.formdoc, div.noborder {
width: 100%;
border-collapse: separate !important;
@ -3621,11 +3628,6 @@ table.liste, table.noborder, table.formdoc, div.noborder {
border-top-style: solid;
margin: 0px 0px 20px 0px;
<?php
if ($userborderontable) { ?>
border-left: 1px solid var(--colortopbordertitle1);
border-right: 1px solid var(--colortopbordertitle1);
<?php } ?>
/*width: calc(100% - 7px);
border-collapse: separate !important;
border-spacing: 0px;

View File

@ -312,8 +312,8 @@ print 'dol_hide_topmenu='.$dol_hide_topmenu."\n";
print 'dol_hide_leftmenu='.$dol_hide_leftmenu."\n";
print 'dol_optimize_smallscreen='.$dol_optimize_smallscreen."\n";
print 'dol_no_mouse_hover='.$dol_no_mouse_hover."\n";
print 'dol_screenwidth='.$_SESSION['dol_screenwidth']."\n";
print 'dol_screenheight='.$_SESSION['dol_screenheight']."\n";
print 'dol_screenwidth='.(empty($_SESSION['dol_screenwidth']) ? '' : $_SESSION['dol_screenwidth'])."\n";
print 'dol_screenheight='.(empty($_SESSION['dol_screenheight']) ? '' : $_SESSION['dol_screenheight'])."\n";
print 'fontsize='.$fontsize."\n";
print 'nbtopmenuentries='.$nbtopmenuentries."\n";
print 'fontsizesmaller='.$fontsizesmaller."\n";

View File

@ -3681,6 +3681,17 @@ div.colorback
border-left: 1px solid #ccc;
<?php } ?>
}
table.liste, table.noborder:not(.paymenttable):not(.margintable):not(.tableforcontact), table.formdoc, div.noborder:not(.paymenttable):not(.margintable):not(.tableforcontact) {
<?php
if ($userborderontable) { ?>
border-left: 1px solid #BBB;
border-right: 1px solid #BBB;
<?php } ?>
}
table.liste, table.noborder.paymenttable, table.noborder.margintable, table.noborder.tableforcontact, table.formdoc, div.noborder.paymenttable, div.noborder.margintable, div.noborder.tableforcontact {
border-left: 1px solid #f0f0f0;
border-right: 1px solid #f0f0f0;
}
table.liste, table.noborder, table.formdoc, div.noborder {
width: calc(100% - 2px); /* -2 to fix a bug. Without, a scroll appears due to overflow-x: auto; of div-table-responsive */
@ -3695,12 +3706,6 @@ table.liste, table.noborder, table.formdoc, div.noborder {
border-bottom-color: #BBB;
border-bottom-style: solid;
<?php
if ($userborderontable) { ?>
border-right: 1px solid #ccc;
border-left: 1px solid #ccc;
<?php } ?>
margin: 0px 0px 20px 0px;
-webkit-border-radius: 0.1em;

View File

@ -357,6 +357,7 @@ class User extends CommonObject
*/
public $fk_warehouse;
public $fields = array(
'rowid'=>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'),
'lastname'=>array('type'=>'varchar(50)', 'label'=>'LastName', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>20, 'searchall'=>1),