Merge
This commit is contained in:
commit
dc3f3e15e8
33 changed files with 205 additions and 72 deletions
|
|
@ -106,3 +106,4 @@ Referers
|
|||
# other
|
||||
blacklists
|
||||
confirmactionxxx
|
||||
udate
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
$sql .= " SET reponses = '0".$db->escape($obj->reponses)."'";
|
||||
$tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.od(s|t)$', '', 'name', SORT_ASC, 0);
|
||||
print '<td class="center"><a href="'.DOL_URL_ROOT.'/product/stock/product.php?dwid='.$object->id.'&id='.$objp->rowid.'&action=transfert&token='.newToken().'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$id).'">';
|
||||
$dateemail = dol_stringtotime((string) $overview[0]->udate, 'gmt');
|
||||
$dateemail = dol_stringtotime((string) $overview[0]->udate, 'gmt');
|
||||
$pice = '<i class="fas fa-briefcase inline-block"></i>';
|
||||
$typea = ($data[$j]->typea == 'birth') ? $picb : $pice;
|
||||
GETPOSTINT("mouvement"),
|
||||
dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject);
|
||||
dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject);
|
||||
jQuery("#mouvement option").removeAttr("selected").change();
|
||||
jQuery("#mouvement option[value=0]").attr("selected","selected").trigger("change");
|
||||
jQuery("#mouvement option[value=1]").attr("selected","selected").trigger("change");
|
||||
|
|
|
|||
|
|
@ -621,6 +621,7 @@ class ActionComm extends CommonObject
|
|||
$sql .= "fk_contact,";
|
||||
$sql .= "fk_user_author,";
|
||||
$sql .= "fk_user_action,";
|
||||
$sql .= "fk_task,";
|
||||
$sql .= "label,percent,priority,fulldayevent,location,";
|
||||
$sql .= "transparency,";
|
||||
$sql .= "fk_element,";
|
||||
|
|
@ -659,6 +660,7 @@ class ActionComm extends CommonObject
|
|||
$sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? ((int) $this->contact_id) : "null").", "; // deprecated, use ->socpeopleassigned
|
||||
$sql .= (isset($user->id) && $user->id > 0 ? $user->id : "null").", ";
|
||||
$sql .= ($userownerid > 0 ? $userownerid : "null").", ";
|
||||
$sql .= (!empty($this->fk_task) ? ((int) $this->fk_task) : "null").", ";
|
||||
$sql .= "'".$this->db->escape($this->label)."', ";
|
||||
$sql .= "'".$this->db->escape((string) $this->percentage)."', ";
|
||||
$sql .= "'".$this->db->escape((string) $this->priority)."', ";
|
||||
|
|
@ -891,6 +893,7 @@ class ActionComm extends CommonObject
|
|||
$sql .= " a.fk_project,";
|
||||
$sql .= " a.fk_user_author, a.fk_user_mod,";
|
||||
$sql .= " a.fk_user_action,";
|
||||
$sql .= " a.fk_task,";
|
||||
$sql .= " a.fk_contact, a.percent as percentage,";
|
||||
$sql .= " a.fk_element as elementid, a.elementtype,";
|
||||
$sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
|
||||
|
|
@ -962,6 +965,7 @@ class ActionComm extends CommonObject
|
|||
$this->usermod->id = $obj->fk_user_mod; // deprecated
|
||||
|
||||
$this->userownerid = $obj->fk_user_action;
|
||||
$this->fk_task = $obj->fk_task;
|
||||
$this->priority = $obj->priority;
|
||||
$this->fulldayevent = $obj->fulldayevent;
|
||||
$this->location = $obj->location;
|
||||
|
|
@ -1281,6 +1285,7 @@ class ActionComm extends CommonObject
|
|||
$sql .= ", transparency = '".$this->db->escape((string) $this->transparency)."'";
|
||||
$sql .= ", fk_user_mod = ".((int) $user->id);
|
||||
$sql .= ", fk_user_action = ".($userownerid > 0 ? ((int) $userownerid) : "null");
|
||||
$sql .= ", fk_task = ".(!empty($this->fk_task) ? ((int) $this->fk_task) : "null");
|
||||
if (!empty($this->fk_element)) {
|
||||
$sql .= ", fk_element=".($this->fk_element ? ((int) $this->fk_element) : "null");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1959,7 +1959,7 @@ class Propal extends CommonObject
|
|||
if ($sqlforgedfilters) {
|
||||
$sql .= $sqlforgedfilters;
|
||||
}
|
||||
$sql .= ' ORDER by d.rang';
|
||||
$sql .= ' ORDER BY d.rang, d.rowid';
|
||||
|
||||
dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
|
||||
$result = $this->db->query($sql);
|
||||
|
|
|
|||
|
|
@ -230,8 +230,8 @@ $arrayfields = array(
|
|||
'c.datec' => array('label' => "DateCreation", 'checked' => '0', 'position' => 120),
|
||||
'c.tms' => array('label' => "DateModificationShort", 'checked' => '0', 'position' => 125),
|
||||
'c.date_cloture' => array('label' => "DateClosing", 'checked' => '0', 'position' => 130),
|
||||
'c.note_public' => array('label' => 'NotePublic', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_ALLOW_PUBLIC_NOTES')), 'position' => 135),
|
||||
'c.note_private' => array('label' => 'NotePrivate', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_ALLOW_PRIVATE_NOTES')), 'position' => 140),
|
||||
'c.note_public' => array('label' => 'NotePublic', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_HIDE_PUBLIC_NOTES')), 'position' => 135),
|
||||
'c.note_private' => array('label' => 'NotePrivate', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_HIDE_PRIVATE_NOTES')), 'position' => 140),
|
||||
'shippable' => array('label' => "Shippable", 'checked' => '1','enabled' => (string) (int) (isModEnabled('shipping')), 'position' => 990),
|
||||
'c.facture' => array('label' => "Billed", 'checked' => '1', 'enabled' => (string) (int) (!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position' => 995),
|
||||
'c.import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => '1', 'visible' => -2, 'position' => 999),
|
||||
|
|
|
|||
|
|
@ -1912,7 +1912,9 @@ if ($resql) {
|
|||
}
|
||||
}
|
||||
if ($user->hasRight('banque', 'modifier')) {
|
||||
$parambis = preg_replace('/action=reconcile/', '', $param);
|
||||
// Strip the surrounding & so the leading action= we put first stays the only action= in the URL.
|
||||
// Without this the URL ends up with two action= params; PHP picks the last one and the page silently switches to 'reconcile' instead of 'delete'.
|
||||
$parambis = preg_replace('/&?action=(reconcile|confirm_deleteonreconcile)(&|$)/', '\2', $param);
|
||||
print '<a href="'.$_SERVER["PHP_SELF"].'?action='.($action == 'reconcile' ? 'confirm_deleteonreconcile&confirm=yes' : 'delete').'&token='.newToken().'&rowid='.$objp->rowid.'&page='.$page.$parambis.($sortfield ? '&sortfield='.$sortfield : '').($sortorder ? '&sortorder='.$sortorder : '').'">';
|
||||
print img_delete('', 'class="marginleftonly"');
|
||||
print '</a>';
|
||||
|
|
|
|||
|
|
@ -4726,7 +4726,7 @@ class Facture extends CommonInvoice
|
|||
$this->line->rang = $rangmax + 1;
|
||||
}
|
||||
$apply_abs_price_on_credit_note = false;
|
||||
if ($this->type == self::TYPE_CREDIT_NOTE && !getDolGlobalInt('FACTURE_ENABLE_NEGATIVE_LINES') && !getDolGlobalInt('INVOICE_KEEP_DISCOUNT_LINES_AS_IN_ORIGIN')) {
|
||||
if ($this->type == self::TYPE_CREDIT_NOTE && !(getDolGlobalInt('FACTURE_ENABLE_NEGATIVE_LINES') && getDolGlobalInt('INVOICE_KEEP_DISCOUNT_LINES_AS_IN_ORIGIN'))) {
|
||||
$apply_abs_price_on_credit_note = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -543,41 +543,47 @@ class Paiement extends CommonObject
|
|||
$discount->fk_facture_source = $invoice->id;
|
||||
|
||||
// Loop on each vat rate
|
||||
// Bucket by tva_tx and vat_src_code so the generated discount keeps the source VAT code
|
||||
$i = 0;
|
||||
foreach ($invoice->lines as $line) {
|
||||
if ($line->product_type != 9 && $line->total_ht != 0) { // no need to create discount if amount is null or is special product
|
||||
if (!array_key_exists($line->tva_tx, $amount_ht)) {
|
||||
$amount_ht[$line->tva_tx] = 0.0;
|
||||
$amount_tva[$line->tva_tx] = 0.0;
|
||||
$amount_ttc[$line->tva_tx] = 0.0;
|
||||
$multicurrency_amount_ht[$line->tva_tx] = 0.0;
|
||||
$multicurrency_amount_tva[$line->tva_tx] = 0.0;
|
||||
$multicurrency_amount_ttc[$line->tva_tx] = 0.0;
|
||||
$key = $line->tva_tx.'|'.(string) $line->vat_src_code;
|
||||
if (!array_key_exists($key, $amount_ht)) {
|
||||
$amount_ht[$key] = 0.0;
|
||||
$amount_tva[$key] = 0.0;
|
||||
$amount_ttc[$key] = 0.0;
|
||||
$multicurrency_amount_ht[$key] = 0.0;
|
||||
$multicurrency_amount_tva[$key] = 0.0;
|
||||
$multicurrency_amount_ttc[$key] = 0.0;
|
||||
}
|
||||
$amount_ht[$line->tva_tx] += $line->total_ht;
|
||||
$amount_tva[$line->tva_tx] += $line->total_tva;
|
||||
$amount_ttc[$line->tva_tx] += $line->total_ttc;
|
||||
$multicurrency_amount_ht[$line->tva_tx] += $line->multicurrency_total_ht;
|
||||
$multicurrency_amount_tva[$line->tva_tx] += $line->multicurrency_total_tva;
|
||||
$multicurrency_amount_ttc[$line->tva_tx] += $line->multicurrency_total_ttc;
|
||||
$amount_ht[$key] += $line->total_ht;
|
||||
$amount_tva[$key] += $line->total_tva;
|
||||
$amount_ttc[$key] += $line->total_ttc;
|
||||
$multicurrency_amount_ht[$key] += $line->multicurrency_total_ht;
|
||||
$multicurrency_amount_tva[$key] += $line->multicurrency_total_tva;
|
||||
$multicurrency_amount_ttc[$key] += $line->multicurrency_total_ttc;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($amount_ht as $tva_tx => $xxx) {
|
||||
$discount->amount_ht = abs($amount_ht[$tva_tx]);
|
||||
$discount->total_ht = abs($amount_ht[$tva_tx]);
|
||||
$discount->amount_tva = abs($amount_tva[$tva_tx]);
|
||||
$discount->total_tva = abs($amount_tva[$tva_tx]);
|
||||
$discount->amount_ttc = abs($amount_ttc[$tva_tx]);
|
||||
$discount->total_ttc = abs($amount_ttc[$tva_tx]);
|
||||
$discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$tva_tx]);
|
||||
$discount->multicurrency_total_ht = abs($multicurrency_amount_ht[$tva_tx]);
|
||||
$discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$tva_tx]);
|
||||
$discount->multicurrency_total_tva = abs($multicurrency_amount_tva[$tva_tx]);
|
||||
$discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
|
||||
$discount->multicurrency_total_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
|
||||
foreach ($amount_ht as $key => $xxx) {
|
||||
$parts = explode('|', (string) $key, 2);
|
||||
$tva_tx = $parts[0];
|
||||
$vat_src_code = isset($parts[1]) ? $parts[1] : '';
|
||||
$discount->amount_ht = abs($amount_ht[$key]);
|
||||
$discount->total_ht = abs($amount_ht[$key]);
|
||||
$discount->amount_tva = abs($amount_tva[$key]);
|
||||
$discount->total_tva = abs($amount_tva[$key]);
|
||||
$discount->amount_ttc = abs($amount_ttc[$key]);
|
||||
$discount->total_ttc = abs($amount_ttc[$key]);
|
||||
$discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$key]);
|
||||
$discount->multicurrency_total_ht = abs($multicurrency_amount_ht[$key]);
|
||||
$discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$key]);
|
||||
$discount->multicurrency_total_tva = abs($multicurrency_amount_tva[$key]);
|
||||
$discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$key]);
|
||||
$discount->multicurrency_total_ttc = abs($multicurrency_amount_ttc[$key]);
|
||||
$discount->tva_tx = abs((float) $tva_tx);
|
||||
$discount->vat_src_code = $vat_src_code;
|
||||
|
||||
$result = $discount->create($user);
|
||||
if ($result < 0) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ if (isModEnabled('project')) {
|
|||
// Load translation files required by the page
|
||||
$langs->loadLangs(array('bills', 'banks', 'companies', 'suppliers', 'other'));
|
||||
|
||||
$hookmanager->initHooks(array('paymentdocument', 'globalcard'));
|
||||
|
||||
$id = GETPOSTINT('id');
|
||||
$ref = GETPOST('ref', 'alpha');
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
|
|
|
|||
|
|
@ -1186,15 +1186,16 @@ if ($modecompta == 'BOOKKEEPING') {
|
|||
$total_ht_outcome += $obj->amount;
|
||||
$total_ttc_outcome += $obj->amount;
|
||||
}
|
||||
$debit_amount = isset($obj->amount) ? $obj->amount : 0;
|
||||
print '<tr class="oddeven">';
|
||||
print '<td> </td>';
|
||||
print "<td>".$langs->trans("AccountingDebit")."</td>\n";
|
||||
print '<td class="right">';
|
||||
if ($modecompta == 'CREANCES-DETTES') {
|
||||
print '<span class="amount">'.price(-$obj->amount).'</span>';
|
||||
print '<span class="amount">'.price(-$debit_amount).'</span>';
|
||||
}
|
||||
print '</td>';
|
||||
print '<td class="right"><span class="amount">'.price(-$obj->amount)."</span></td>\n";
|
||||
print '<td class="right"><span class="amount">'.price(-$debit_amount)."</span></td>\n";
|
||||
print "</tr>\n";
|
||||
|
||||
// Credit (payment received from customer for example)
|
||||
|
|
@ -1206,14 +1207,15 @@ if ($modecompta == 'BOOKKEEPING') {
|
|||
$total_ht_income += $obj->amount;
|
||||
$total_ttc_income += $obj->amount;
|
||||
}
|
||||
$credit_amount = isset($obj->amount) ? $obj->amount : 0;
|
||||
print '<tr class="oddeven"><td> </td>';
|
||||
print "<td>".$langs->trans("AccountingCredit")."</td>\n";
|
||||
print '<td class="right">';
|
||||
if ($modecompta == 'CREANCES-DETTES') {
|
||||
print '<span class="amount">'.price($obj->amount).'</span>';
|
||||
print '<span class="amount">'.price($credit_amount).'</span>';
|
||||
}
|
||||
print '</td>';
|
||||
print '<td class="right"><span class="amount">'.price($obj->amount)."</span></td>\n";
|
||||
print '<td class="right"><span class="amount">'.price($credit_amount)."</span></td>\n";
|
||||
print "</tr>\n";
|
||||
|
||||
// Total
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ if ($action == "update_extras" && GETPOSTINT('id') > 0 && !empty($permissiontoed
|
|||
}
|
||||
|
||||
// Action to delete
|
||||
if ($action == 'confirm_delete' && !empty($permissiontodelete)) {
|
||||
if ($action == 'confirm_delete' && $confirm == 'yes' && !empty($permissiontodelete)) {
|
||||
if (!($object->id > 0)) {
|
||||
dol_print_error(null, 'Error, object must be fetched before being deleted');
|
||||
exit;
|
||||
|
|
|
|||
|
|
@ -664,6 +664,13 @@ if ($action == "importSignature") {
|
|||
if ($last_modelpdf == 'sepamandate') {
|
||||
$newpdffilename = $upload_dir . $langs->transnoentitiesnoconv("SepaMandateShort") . ' ' . dol_sanitizeFileName($object->ref) . "-" . dol_sanitizeFileName($object->rum) . "_signed-" . $date . ".pdf";
|
||||
$sourcefile = $upload_dir . $langs->transnoentitiesnoconv("SepaMandateShort") . ' ' . dol_sanitizeFileName($object->ref) . "-" . dol_sanitizeFileName($object->rum) . ".pdf";
|
||||
} else {
|
||||
// Fallback for setups using a non-default bank PDF model (eg. "ban"): take the last
|
||||
// generated main document as source and append "_signed-<date>" before the extension.
|
||||
// Without this the signed PDF is never built and the download link keeps pointing at
|
||||
// the unsigned original.
|
||||
$sourcefile = DOL_DATA_ROOT . '/' . $last_main_doc_file;
|
||||
$newpdffilename = preg_replace('/\.pdf$/i', '_signed-' . $date . '.pdf', $sourcefile);
|
||||
}
|
||||
if (dol_is_file($sourcefile)) {
|
||||
$parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class box_actions_future extends ModeleBoxes
|
|||
$sql .= " AND s.rowid = ".((int) $user->socid);
|
||||
}
|
||||
if (!$user->hasRight('agenda', 'allactions', 'read')) {
|
||||
$sql .= " AND (a.fk_user_author = ".((int) $user->id)." OR a.fk_user_action = ".((int) $user->id)." OR a.fk_user_done = ".((int) $user->id).")";
|
||||
$sql .= " AND (a.fk_user_author = ".((int) $user->id)." OR a.fk_user_action = ".((int) $user->id).")";
|
||||
}
|
||||
$sql .= " AND a.datep > '".$this->db->idate($now)."'";
|
||||
$sql .= " ORDER BY a.datep ASC";
|
||||
|
|
|
|||
|
|
@ -9596,7 +9596,7 @@ abstract class CommonObject
|
|||
} elseif (($mode == 'edit') && !in_array(abs($visibility), array(1, 3, 4))) {
|
||||
// We need to make sure, that the values of hidden extrafields are also part of $_POST. Otherwise, they would be empty after an update of the object. See also getOptionalsFromPost
|
||||
$ef_name = 'options_' . $key;
|
||||
$ef_value = $this->array_options[$ef_name];
|
||||
$ef_value = $this->array_options[$ef_name]??'';
|
||||
$out .= '<input type="hidden" name="' . $ef_name . '" id="' . $ef_name . '" value="' . $ef_value . '" />' . "\n";
|
||||
continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list and <> 4 = not visible at the creation
|
||||
} elseif ($mode == 'view' && empty($visibility)) {
|
||||
|
|
|
|||
|
|
@ -1229,9 +1229,10 @@ class DolGraph
|
|||
$legends[$x] = (array_key_exists('label', $valarray) ? $valarray['label'] : $valarray[0]);
|
||||
$array_of_ykeys = array_keys($valarray);
|
||||
$alabelexists = 1;
|
||||
$tmpykey = explode('_', (string) ($array_of_ykeys[$i + ($alabelexists ? 1 : 0)]), 3);
|
||||
$ykeyindex = $i + ($alabelexists ? 1 : 0);
|
||||
$tmpykey = isset($array_of_ykeys[$ykeyindex]) ? explode('_', (string) $array_of_ykeys[$ykeyindex], 3) : array();
|
||||
if (isset($tmpykey[2]) && (!empty($tmpykey[2]) || $tmpykey[2] == '0')) { // This is a 'Group by' array
|
||||
$tmpvalue = (array_key_exists('y_' . $tmpykey[1] . '_' . $tmpykey[2], $valarray) ? $valarray['y_' . $tmpykey[1] . '_' . $tmpykey[2]] : $valarray[$i + 1]);
|
||||
$tmpvalue = (array_key_exists('y_' . $tmpykey[1] . '_' . $tmpykey[2], $valarray) ? $valarray['y_' . $tmpykey[1] . '_' . $tmpykey[2]] : ($valarray[$i + 1] ?? null));
|
||||
$values[$x] = (is_numeric($tmpvalue) ? $tmpvalue : null);
|
||||
$arrayofgroupslegend[$i] = array(
|
||||
'stacknum' => (int) $tmpykey[1],
|
||||
|
|
@ -1239,7 +1240,7 @@ class DolGraph
|
|||
'legendwithgroup' => ($this->Legend[$tmpykey[1]] ?? '') . ' - ' . $tmpykey[2]
|
||||
);
|
||||
} else {
|
||||
$tmpvalue = (array_key_exists('y_' . $i, $valarray) ? $valarray['y_' . $i] : $valarray[$i + 1]);
|
||||
$tmpvalue = (array_key_exists('y_' . $i, $valarray) ? $valarray['y_' . $i] : ($valarray[$i + 1] ?? null));
|
||||
//var_dump($i.'_'.$x.'_'.$tmpvalue);
|
||||
$values[$x] = (is_numeric($tmpvalue) ? $tmpvalue : null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3020,7 +3020,7 @@ class ExtraFields
|
|||
} elseif (in_array($key_type, array('price', 'double'))) {
|
||||
$value_arr = GETPOST("options_".$key, 'alpha');
|
||||
$value_key = price2num($value_arr);
|
||||
} elseif (in_array($key_type, array('pricecy', 'double'))) {
|
||||
} elseif (in_array($key_type, array('pricecy'))) {
|
||||
$value_key = price2num(GETPOST("options_".$key, 'alpha')).':'.GETPOST("options_".$key."currency_id", 'alpha');
|
||||
} elseif (in_array($key_type, array('html'))) {
|
||||
$value_key = GETPOST("options_".$key, 'restricthtml');
|
||||
|
|
@ -3185,6 +3185,16 @@ class ExtraFields
|
|||
// Make sure we get an array even if there's only one checkbox
|
||||
$value_arr = (array) $value_arr;
|
||||
$value_key = implode(',', $value_arr);
|
||||
} elseif (in_array($key_type, array('pricecy'))) {
|
||||
if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
|
||||
continue; // Value was not provided, we should not set it.
|
||||
}
|
||||
$value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
|
||||
if ($keyprefix != 'search_') { // If value is for a search, we must keep complex string like '>100 <=150'
|
||||
$value_key = price2num($value_arr).':'.GETPOST($keyprefix."options_".$key.$keysuffix."currency_id", 'alpha');
|
||||
} else {
|
||||
$value_key = $value_arr;
|
||||
}
|
||||
} elseif (in_array($key_type, array('price', 'double', 'int'))) {
|
||||
if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
|
||||
continue; // Value was not provided, we should not set it.
|
||||
|
|
|
|||
|
|
@ -7211,7 +7211,11 @@ class Form
|
|||
} else {
|
||||
if ($selected) {
|
||||
$this->load_cache_availability();
|
||||
print $this->cache_availability[$selected]['label'];
|
||||
if (isset($this->cache_availability[$selected])) {
|
||||
print $this->cache_availability[$selected]['label'];
|
||||
} else {
|
||||
print " ";
|
||||
}
|
||||
} else {
|
||||
print " ";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -747,9 +747,9 @@ class FormMail extends Form
|
|||
'global_aliases' => getDolGlobalString('MAIN_INFO_SOCIETE_MAIL_ALIASES'),
|
||||
);
|
||||
|
||||
if (!empty($arraydefaultmessage->email_from)) {
|
||||
if (!empty($arraydefaultmessage->email_from) && !empty($arraydefaultmessage->id)) {
|
||||
$templatemailfrom = ' <'.$arraydefaultmessage->email_from.'>';
|
||||
$liste['from_template_'.$arraydefaultmessage->id] = array('label' => $templatemailfrom, 'data-html' => $templatemailfrom);
|
||||
$liste['from_template_'.((int) $arraydefaultmessage->id)] = array('label' => $templatemailfrom, 'data-html' => $templatemailfrom);
|
||||
}
|
||||
|
||||
// Also add robot email
|
||||
|
|
@ -808,7 +808,7 @@ class FormMail extends Form
|
|||
$liste[$key]['data-html'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $liste[$key]['data-html']);
|
||||
}
|
||||
}
|
||||
$out .= ' '.$form->selectarray('fromtype', $liste, empty($arraydefaultmessage->email_from) ? $this->fromtype : 'from_template_'.$arraydefaultmessage->id, 0, 0, 0, '', 0, 0, 0, '', 'fromforsendingprofile maxwidth200onsmartphone', 1, '', $disablebademails);
|
||||
$out .= ' '.$form->selectarray('fromtype', $liste, (empty($arraydefaultmessage->email_from) || empty($arraydefaultmessage->id)) ? $this->fromtype : 'from_template_'.((int) $arraydefaultmessage->id), 0, 0, 0, '', 0, 0, 0, '', 'fromforsendingprofile maxwidth200onsmartphone', 1, '', $disablebademails);
|
||||
}
|
||||
|
||||
$out .= "</td></tr>\n";
|
||||
|
|
|
|||
|
|
@ -1637,6 +1637,14 @@ function showOptions(child_list, parent_list) {
|
|||
function setListDependencies() {
|
||||
console.log("setListDependencies");
|
||||
jQuery("select option[parent]").parent().each(function() {
|
||||
/* Skip selects inside line item extrafield containers — those are
|
||||
* handled by setListDependencies_extra() generated by getJSListDependancies().
|
||||
* Both handlers binding on the same select would race showOptions()
|
||||
* (prop disabled) against showOptions_extra() (clone/remove/append)
|
||||
* and leave the child options permanently disabled. See #36880. */
|
||||
if ($(this).closest('[id^="extrafield_lines_area"]').length > 0) {
|
||||
return;
|
||||
}
|
||||
var child_list = $(this).attr("name");
|
||||
var parent = $(this).find("option[parent]:first").attr("parent");
|
||||
var infos = parent.split(":");
|
||||
|
|
|
|||
|
|
@ -11883,6 +11883,12 @@ function dol_getIdFromCode($db, $key, $tablename, $fieldkey = 'code', $fieldid =
|
|||
*/
|
||||
function isStringVarMatching($var, $regextext, $matchrule = 1)
|
||||
{
|
||||
// Tolerate callers (custom modules, older code) that already pass a full regex with delimiters
|
||||
// like '/^(aaa|bbb)/' instead of the bare body. Without this, the function would build
|
||||
// '/^/^(aaa|bbb)//' which trips preg_match() with 'Unknown modifier ^'.
|
||||
$regextext = preg_replace('#^/\^?#', '', (string) $regextext);
|
||||
$regextext = preg_replace('#\$?/[imsxuADSUXJ]*$#', '', $regextext);
|
||||
|
||||
if ($matchrule == 1) {
|
||||
if ($var == 'mainmenu') {
|
||||
global $mainmenu;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,23 @@ class printing_printipp extends PrintingDriver
|
|||
|
||||
$fileprint = getMultidirOutput(null, $module) . '/' . $file;
|
||||
$ipp->setData($fileprint);
|
||||
// Tell CUPS what we are sending so it picks the right filter chain (otherwise ODT/PDF arrive as raw and print as ASCII garbage).
|
||||
$extension = strtolower(pathinfo($fileprint, PATHINFO_EXTENSION));
|
||||
$mimebyext = array(
|
||||
'pdf' => 'application/pdf',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'ps' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'txt' => 'text/plain',
|
||||
'png' => 'image/png',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
);
|
||||
if (isset($mimebyext[$extension])) {
|
||||
$ipp->setMimeMediaType($mimebyext[$extension]);
|
||||
}
|
||||
try {
|
||||
$ipp->printJob();
|
||||
} catch (Exception $e) {
|
||||
|
|
|
|||
|
|
@ -877,9 +877,13 @@ class doc_generic_project_odt extends ModelePDFProjects
|
|||
}
|
||||
$odfHandler->mergeSegment($listlines);
|
||||
} catch (OdfException $e) {
|
||||
$this->error = $e->getMessage();
|
||||
dol_syslog($this->error, LOG_WARNING);
|
||||
return -1;
|
||||
$ExceptionTrace = $e->getTrace();
|
||||
// no segment defined on ODT is not an error
|
||||
if ($ExceptionTrace[0]['function'] != 'setSegment') {
|
||||
$this->error = $e->getMessage();
|
||||
dol_syslog($this->error, LOG_WARNING);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace tags of lines for contacts
|
||||
|
|
@ -926,9 +930,13 @@ class doc_generic_project_odt extends ModelePDFProjects
|
|||
}
|
||||
$odfHandler->mergeSegment($listlines);
|
||||
} catch (OdfException $e) {
|
||||
$this->error = $e->getMessage();
|
||||
dol_syslog($this->error, LOG_WARNING);
|
||||
return -1;
|
||||
$ExceptionTrace = $e->getTrace();
|
||||
// no segment defined on ODT is not an error
|
||||
if ($ExceptionTrace[0]['function'] != 'setSegment') {
|
||||
$this->error = $e->getMessage();
|
||||
dol_syslog($this->error, LOG_WARNING);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1278,11 +1278,27 @@ if (!empty($object->thirdparty)) {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
// Execute js context Dolibarr Hooks
|
||||
if (typeof Dolibarr != 'undefined') {
|
||||
Dolibarr.executeHook('objectLineCreate:GetSupplierPrices', {'idprod': idProd, ajaxResultData : data, jsConf});
|
||||
}
|
||||
|
||||
<?php if (getDolGlobalString('PRODUCT_USE_UNITS')) { ?>
|
||||
// Sync the measuring unit dropdown with the product's default fk_unit
|
||||
// for the supplier-side line picker (issue #38636), mirroring the
|
||||
// customer-side behaviour from issue #34610. Look at the first
|
||||
// non-pmp/non-cost row of the AJAX response (all rows for a given
|
||||
// product carry the same fk_unit since it comes from llx_product).
|
||||
var firstFkUnit = null;
|
||||
$(data).each(function() {
|
||||
if (this.id != 'pmpprice' && this.id != 'costprice' && typeof this.fk_unit != 'undefined' && this.fk_unit != null && firstFkUnit === null) {
|
||||
firstFkUnit = this.fk_unit;
|
||||
}
|
||||
});
|
||||
if (firstFkUnit !== null && $("#units").length) {
|
||||
$("#units").val(firstFkUnit).trigger('change');
|
||||
}
|
||||
<?php } ?>
|
||||
}
|
||||
},
|
||||
'json');
|
||||
|
|
|
|||
|
|
@ -156,8 +156,8 @@ $arrayfields = array(
|
|||
'l.ref' => array('label' => $langs->trans("DeliveryRef"), 'checked' => '1', 'position' => 1010, 'enabled' => (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') ? '1' : '0')),
|
||||
'l.date_delivery' => array('label' => $langs->trans("DateReceived"), 'position' => 1020, 'checked' => '1', 'enabled' => (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') ? '1' : '0')),
|
||||
'e.billed' => array('label' => $langs->trans("Billed"), 'checked' => '1', 'position' => 1100, 'enabled' => 'getDolGlobalString("WORKFLOW_BILL_ON_SHIPMENT") !== "0"'),
|
||||
'e.note_public' => array('label' => 'NotePublic', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_ALLOW_PUBLIC_NOTES')), 'position' => 135),
|
||||
'e.note_private' => array('label' => 'NotePrivate', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_ALLOW_PRIVATE_NOTES')), 'position' => 140),
|
||||
'e.note_public' => array('label' => 'NotePublic', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_HIDE_PUBLIC_NOTES')), 'position' => 135),
|
||||
'e.note_private' => array('label' => 'NotePrivate', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_HIDE_PRIVATE_NOTES')), 'position' => 140),
|
||||
);
|
||||
|
||||
// Extra fields
|
||||
|
|
|
|||
|
|
@ -2658,11 +2658,12 @@ class ExpenseReport extends CommonObject
|
|||
}
|
||||
|
||||
$now = dol_now();
|
||||
if ($option == 'toapprove') {
|
||||
return (!empty($this->datevalid) ? $this->datevalid : $this->date_valid) < ($now - $conf->expensereport->approve->warning_delay);
|
||||
} else {
|
||||
return (!empty($this->datevalid) ? $this->datevalid : $this->date_valid) < ($now - $conf->expensereport->payment->warning_delay);
|
||||
$warning_delay = (int) ($option == 'toapprove' ? $conf->expensereport->approve->warning_delay : $conf->expensereport->payment->warning_delay);
|
||||
if ($warning_delay <= 0) {
|
||||
// No delay configured (MAIN_DELAY_EXPENSEREPORTS / MIN_DELAY_EXPENSEREPORTS_TO_PAY not set), so nothing is late.
|
||||
return false;
|
||||
}
|
||||
return (!empty($this->datevalid) ? $this->datevalid : $this->date_valid) < ($now - $warning_delay);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ if ($idprod > 0) {
|
|||
|
||||
$prices[] = array(
|
||||
"id" => $productSupplier->product_fourn_price_id,
|
||||
"price" => price2num($price, '', 0),
|
||||
"price" => price2num($price, '', 0), // For price field, we must use price2num(), for label or title, price()
|
||||
"label" => $label,
|
||||
"title" => $title,
|
||||
|
||||
|
|
@ -142,8 +142,13 @@ if ($idprod > 0) {
|
|||
'reputation' => $productSupplier->supplier_reputation,
|
||||
'dateCreation' => $productSupplier->fourn_date_creation,
|
||||
'deliveryTimeDays' => $productSupplier->delivery_time_days,
|
||||
]
|
||||
); // For price field, we must use price2num(), for label or title, price()
|
||||
// Carry the product's default unit so the line form can preselect
|
||||
// #units like the customer side already does for idprod (see
|
||||
// issues #34610 for the customer side and #38636 for the
|
||||
// supplier side).
|
||||
"fk_unit" => $productSupplier->fk_unit
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -832,7 +832,7 @@ class ProductFournisseur extends Product
|
|||
public function list_product_fournisseur_price($prodid, $sortfield = '', $sortorder = '', $limit = 0, $offset = 0, $socid = 0)
|
||||
{
|
||||
// phpcs:enable
|
||||
$sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id, p.ref as product_ref, p.tosell as status, p.tobuy as status_buy, p.tobatch as status_batch,";
|
||||
$sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id, p.ref as product_ref, p.tosell as status, p.tobuy as status_buy, p.tobatch as status_batch, p.fk_unit as product_fk_unit,";
|
||||
$sql .= " pfp.rowid as product_fourn_pri_id, pfp.entity, pfp.ref_fourn, pfp.desc_fourn, pfp.fk_product as product_fourn_id, pfp.fk_supplier_price_expression,";
|
||||
$sql .= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.info_bits, pfp.delivery_time_days, pfp.supplier_reputation,";
|
||||
$sql .= " pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code, pfp.datec, pfp.tms,";
|
||||
|
|
@ -886,6 +886,11 @@ class ProductFournisseur extends Product
|
|||
$prodfourn->supplier_reputation = $record["supplier_reputation"];
|
||||
$prodfourn->fourn_date_creation = $this->db->jdate($record['datec']);
|
||||
$prodfourn->fourn_date_modification = $this->db->jdate($record['tms']);
|
||||
// Carry the product's default measuring unit so the AJAX caller
|
||||
// (getSupplierPrices.php) can return it to the line form, which
|
||||
// then preselects #units like the customer side already does for
|
||||
// idprod (see issues #34610 client-side and #38636 supplier-side).
|
||||
$prodfourn->fk_unit = $record["product_fk_unit"];
|
||||
|
||||
$prodfourn->fourn_multicurrency_price = $record["multicurrency_price"];
|
||||
$prodfourn->fourn_multicurrency_unitprice = $record["multicurrency_unitprice"];
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ if (isModEnabled('project')) {
|
|||
// Load translation files required by the page
|
||||
$langs->loadLangs(array('banks', 'bills', 'companies', 'suppliers', 'other'));
|
||||
|
||||
$hookmanager->initHooks(array('paymentsupplierdocument', 'globalcard'));
|
||||
|
||||
|
||||
// Get Parameters
|
||||
$id = GETPOSTINT('id');
|
||||
|
|
|
|||
|
|
@ -440,4 +440,15 @@ INSERT INTO llx_accounting_system (fk_country, pcg_version, label, active) VALUE
|
|||
-- Rename OIDC enable constant: openidconnect was converted from a module to a config-level feature (#36051)
|
||||
UPDATE llx_const SET name = 'MAIN_AUTHENTICATION_OIDC_ON' WHERE name = 'MAIN_MODULE_OPENIDCONNECT';
|
||||
|
||||
-- this table was created only during fresh install
|
||||
CREATE llx_workstation_workstation_extrafields
|
||||
(
|
||||
rowid integer AUTO_INCREMENT PRIMARY KEY,
|
||||
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_object integer NOT NULL,
|
||||
import_key varchar(14) -- import key
|
||||
) ENGINE=innodb;
|
||||
|
||||
ALTER TABLE llx_workstation_workstation_extrafields ADD INDEX idx_workstation_workstation_extrafields (fk_object);
|
||||
|
||||
-- end of migration
|
||||
|
|
|
|||
|
|
@ -1535,8 +1535,11 @@ class Product extends CommonObject
|
|||
|
||||
if ($result >= 0) {
|
||||
// $this->oldcopy should have been set by the caller of update (here properties were already modified)
|
||||
// Note that this->oldcopy must be object and not stdClass, if not the method hasbatch() will not work.
|
||||
if (is_null($this->oldcopy) || (is_object($this->oldcopy) && empty($this->oldcopy->id))) {
|
||||
// Note that this->oldcopy must be a Product instance (not stdClass), otherwise the method
|
||||
// hasbatch() called below will fatal. Callers may set oldcopy via dol_clone($obj, 2) (which
|
||||
// returns a stdClass with scalar properties only) and then we cannot call methods on it,
|
||||
// so re-clone with native=1 in that case (see issues #38663, #38638).
|
||||
if (is_null($this->oldcopy) || (is_object($this->oldcopy) && empty($this->oldcopy->id)) || !($this->oldcopy instanceof Product)) {
|
||||
$this->oldcopy = dol_clone($this, 1); // 1 to clone with methods to avoid fatal error with $this->oldcopy->hasbatch()
|
||||
}
|
||||
// Test if batch management is activated on existing product
|
||||
|
|
@ -1923,7 +1926,7 @@ class Product extends CommonObject
|
|||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
if (!$error && isModEnabled('variants')) {
|
||||
include_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
|
||||
include_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.class.php';
|
||||
|
||||
|
|
@ -5688,6 +5691,9 @@ class Product extends CommonObject
|
|||
public function hasVariants()
|
||||
{
|
||||
$nb = 0;
|
||||
if (!isModEnabled('variants')) {
|
||||
return $nb;
|
||||
}
|
||||
$sql = "SELECT count(rowid) as nb FROM ".$this->db->prefix()."product_attribute_combination WHERE fk_product_parent = ".((int) $this->id);
|
||||
$sql .= " AND entity IN (".getEntity('product').")";
|
||||
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ class Warehouses extends DolibarrApi
|
|||
throw new RestException(404, 'warehouse not found');
|
||||
}
|
||||
|
||||
if (!DolibarrApi::_checkAccessToResource('stock', $this->warehouse->id)) {
|
||||
if (!DolibarrApi::_checkAccessToResource('stock', $this->warehouse->id, 'entrepot')) {
|
||||
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +346,7 @@ class Warehouses extends DolibarrApi
|
|||
throw new RestException(404, 'warehouse not found');
|
||||
}
|
||||
|
||||
if (!DolibarrApi::_checkAccessToResource('stock', $this->warehouse->id)) {
|
||||
if (!DolibarrApi::_checkAccessToResource('stock', $this->warehouse->id, 'entrepot')) {
|
||||
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ class Task extends CommonObjectLine
|
|||
$sql .= ", priority";
|
||||
$sql .= ", billable";
|
||||
$sql .= ", fk_statut";
|
||||
$sql .= ", rang";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= (!empty($this->entity) ? (int) $this->entity : (int) $conf->entity);
|
||||
$sql .= ", ".((int) $this->fk_project);
|
||||
|
|
@ -472,6 +473,7 @@ class Task extends CommonObjectLine
|
|||
$sql .= ", ".(($this->priority != '' && $this->priority >= 0) ? (int) $this->priority : 'null');
|
||||
$sql .= ", ".((int) $this->billable);
|
||||
$sql .= ", ".((int) $this->status);
|
||||
$sql .= ", ".((!empty($this->rang)) ? ((int) $this->rang) : "0");
|
||||
$sql .= ")";
|
||||
|
||||
$this->db->begin();
|
||||
|
|
|
|||
|
|
@ -313,7 +313,10 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us
|
|||
$object->timespent_date = $timespent_date;
|
||||
$object->timespent_withhour = 0;
|
||||
}
|
||||
$object->timespent_fk_user = GETPOSTINT("userid_line");
|
||||
// If column "by" is hidden, no userid_line is posted; keep the existing fk_user instead of resetting it to 0.
|
||||
if (GETPOSTISSET("userid_line")) {
|
||||
$object->timespent_fk_user = GETPOSTINT("userid_line");
|
||||
}
|
||||
$object->timespent_fk_product = GETPOSTINT("fk_product");
|
||||
$object->timespent_invoiceid = GETPOSTINT("invoiceid");
|
||||
$object->timespent_invoicelineid = GETPOSTINT("invoicelineid");
|
||||
|
|
@ -348,7 +351,10 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us
|
|||
$object->timespent_withhour = 0;
|
||||
}
|
||||
|
||||
$object->timespent_fk_user = GETPOSTINT("userid_line");
|
||||
// If column "by" is hidden, no userid_line is posted; keep the existing fk_user instead of resetting it to 0.
|
||||
if (GETPOSTISSET("userid_line")) {
|
||||
$object->timespent_fk_user = GETPOSTINT("userid_line");
|
||||
}
|
||||
$object->timespent_fk_product = GETPOSTINT("fk_product");
|
||||
$object->timespent_invoiceid = GETPOSTINT("invoiceid");
|
||||
$object->timespent_invoicelineid = GETPOSTINT("invoicelineid");
|
||||
|
|
|
|||
Loading…
Reference in a new issue