Merge branch '10.0' of git@github.com:Dolibarr/dolibarr.git into develop

Conflicts:
	ChangeLog
	htdocs/langs/en_US/admin.lang
	htdocs/product/dynamic_price/class/price_parser.class.php
	htdocs/product/stats/facture.php
This commit is contained in:
Laurent Destailleur 2019-08-10 01:57:43 +02:00
commit 8647a20c18
18 changed files with 227 additions and 76 deletions

109
ChangeLog
View File

@ -17,6 +17,115 @@ Following changes may create regressions for some external modules, but were nec
* Removed the method liste_array() of project class. It was not used by core code.
***** ChangeLog for 10.0.1 compared to 10.0.0 *****
FIX: #10930
FIX: #10984
FIX: reposition on "Build backup" button
FIX: #11400
FIX: #11412
FIX: #11460
FIX: #11463
FIX: #11466
FIX: #11492
FIX: #11498
FIX: #11505
FIX: #11506
FIX: #11507
FIX: #11509
FIX: #11537
FIX: #11543
FIX: #11553
FIX: #11576
FIX: #11584
FIX: #11590
FIX: accounting mode must be taken from global conf, because there's no way to choose a mode with interface
FIX: Add message from public interface
FIX: add missing hook calls
FIX: Add warning when setup is strange
FIX: ajax call for line positioning when CSRFCHECK_WITH_TOKEN is on
FIX: API return 404 sometimes even if API exists
FIX: Attachment was lost when we validate an expense report
FIX: avoid conflict with "$classname" in card.php
FIX: Bad sql request
FIX: better compatibility with multicompany transverse mode
FIX: Better PHP compatibility
FIX: Block to link with tickets
FIX: Can't submit a ticket from public interface
FIX: categories import: prevent mismatch between category type and object type
FIX: Closing ticket from public interface
FIX: Column 'paid' missing in expense report
FIX: compatibility mysql 8. rank is reserved
FIX: Computed field were not calculated into lists.
FIX: Content of email for subscription
FIX: correct error in files with multiple spaces
FIX: CVE-2019-11199
FIX: delete of links between objects
FIX: div not balanced
FIX: do not return formatted prices in json string
FIX: duplicate on the check (TODO field $onetrtd not used ?)
FIX: element name in update_price
FIX: empty product_use_units in product configuration
FIX: expedition card: infinite loop for printObjectLine hook if return > 0
FIX: extrafield loading bug due to assumption that an object is a third party while it may be a contact if MAIN_USE_COMPANY_NAME_OF_CONTACT is set.
FIX: Fatal error on dol_htmloutput_mesg with corrupted array
FIX: Fatal situation if payment removed on expense report. Action
FIX: FEC Format - Missing date_creation in general ledger when you add a new transaction
FIX: FEC Format - Save translation of the journal label in database & nowrap on amount
FIX: floating point precision errors in the triggers of the workflow module
FIX: for #11232
FIX: format of field with type timestamp
FIX: fournrprice log for insert
FIX: help text
FIX: import filter error
FIX: __INFOS__ tag not exists
FIX: issue #9300: install error with PostgreSQL when using custom table prefix
FIX: Language key
FIX: Limit of uploaded files (max_post_size was not used)
FIX: list of balance of leaves
FIX: minor spelling issues
FIX: missing "dropdown-icon" replacement
FIX: Missing field "Conciliated" into bank transaction export
FIX: missing filter by current contact
FIX: missing token
FIX: Missing where on entity
FIX: move sql request in INNER JOIN
FIX: name was able to be in field but went back to new line
FIX: Nowrap on amount
FIX: Online payment
FIX: on shipment delete confirm dialog, a new checkbox allows the user to choose if they want their stock re-incremented after the deletion.
FIX: option EXPORT_LABEL_FOR_SELECT to restore compatibility in export
FIX: Option THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION
FIX: outdated phpdoc
FIX: Permission for BOM menu
FIX: permission to delete a draft purchase order
FIX: phpcs
FIX: Position was lost when we edit the line of template invoice
FIX: product_use_units was set to 0 each time a conf in block other was set
FIX: propal createFrom hook: undefined parameter attached
FIX: Responsive of public interface of ticket
FIX: search by phone pro
FIX: Setup of TakePos was not possible after a clean install
FIX: Show list of events on tickets
FIX: socpeople assigned list in action com list
FIX: SQL problem on donation & nowrap on amount
FIX: stock increase on shipment deletion if STOCK_CALCULATE_ON_SHIPMENT_NEW: is set
FIX: stripe webhook ID constant set
FIX: summary of time spent in preview tab of projects
FIX: the feature to bill time spent was not enabled.
FIX: The new feature to attach document on lines was not correclty
FIX: The proposed new supplier code does not work
FIX: this function can not be private
FIX: tk9877 - PDF rouget requires product.lib.php (otherwise measuring_units_string() is not defined)
FIX: Update the file index table when we validate/rename a ref.
FIX: use rounding to compare the amounts
FIX: We must save code instead of value in database for template invoice modelpdf
FIX: we need to be able to add freeline with qty between 0 & 1 in supplierorder line
FIX: We should remove property comments only for project and task api.
FIX: When saving an action it didn't save the label based on the type of event if the label is empty and the type is customized
FIX: when STOCK_CALCULATE_ON_SHIPMENT_NEW: is set, deleting a "closed" shipment now increases stock as expected
FIX: wrong path sociales/index.php doesnt exist anymore
***** ChangeLog for 10.0.0 compared to 9.0.0 *****
For Users:
NEW: Module "Ticket" is available as a stable module.

View File

@ -368,7 +368,7 @@ class Documents extends DolibarrApi
throw new RestException(404, 'Product not found');
}
$upload_dir = $conf->product->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'product');
$upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref);
}
elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event')
{

View File

@ -1227,7 +1227,7 @@ class pdf_einstein extends ModelePDFCommandes
* @param int $showaddress 0=no, 1=yes
* @param Translate $outputlangs Object lang for output
* @param string $titlekey Translation key to show as title of document
* @return void
* @return int Return topshift value
*/
protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey = "PdfOrderTitle")
{

View File

@ -67,13 +67,13 @@ class pdf_proforma extends pdf_einstein
* @param int $showaddress 0=no, 1=yes
* @param Translate $outputlangs Object lang for output
* @param string $titlekey Translation key to show as title of document
* @return void
* @return int Return topshift value
*/
protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey = "InvoiceProForma")
{
// phpcs:enable
global $conf,$langs,$hookmanager;
parent::_pagehead($pdf, $object, $showaddress, $outputlangs, $titlekey);
return parent::_pagehead($pdf, $object, $showaddress, $outputlangs, $titlekey);
}
}

View File

@ -130,7 +130,8 @@ class InterfaceWorkflowManager extends DolibarrTriggers
if ($action == 'BILL_VALIDATE')
{
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
$ret = 0;
// First classify billed the order to allow the proposal classify process
if (! empty($conf->commande->enabled) && ! empty($conf->workflow->enabled) && ! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER))
{
@ -151,7 +152,6 @@ class InterfaceWorkflowManager extends DolibarrTriggers
}
}
}
return $ret;
}
// Second classify billed the proposal.
@ -174,8 +174,9 @@ class InterfaceWorkflowManager extends DolibarrTriggers
}
}
}
return $ret;
}
return $ret;
}
// classify billed order & billed propososal

View File

@ -1024,6 +1024,34 @@ if (empty($reshook))
}
}
if ($action == 'set_unpaid' && $id > 0 && $user->rights->expensereport->to_paid)
{
$object = new ExpenseReport($db);
$object->fetch($id);
$result = $object->set_unpaid($user);
if ($result > 0)
{
// Define output language
if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
{
$outputlangs = $langs;
$newlang = '';
if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09');
if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
if (! empty($newlang)) {
$outputlangs = new Translate("", $conf);
$outputlangs->setDefaultLang($newlang);
}
$model=$object->modelpdf;
$ret = $object->fetch($id); // Reload to get new records
$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
}
}
}
if ($action == 'set_paid' && $id > 0 && $user->rights->expensereport->to_paid)
{
$object = new ExpenseReport($db);

View File

@ -400,6 +400,7 @@ OldVATRates=Old VAT rate
NewVATRates=New VAT rate
PriceBaseTypeToChange=Modify on prices with base reference value defined on
MassConvert=Launch bulk conversion
PriceFormatInCurrentLanguage=Price Format In Current Language
String=String
TextLong=Long text
HtmlText=Html text

View File

@ -568,7 +568,7 @@ else
}
// Other attributes
if ($action = 'create_delivery') {
if ($action == 'create_delivery') {
// copy from expedition
$expeditionExtrafields = new Extrafields($db);
$expeditionExtrafieldLabels = $expeditionExtrafields->fetch_name_optionals_label($expedition->table_element);
@ -681,7 +681,7 @@ else
$mode = ($object->statut == 0) ? 'edit' : 'view';
$line = new LivraisonLigne($db);
$line->fetch_optionals($object->lines[$i]->id);
if ($action = 'create_delivery') {
if ($action == 'create_delivery') {
$srcLine = new ExpeditionLigne($db);
$expeditionLineExtrafields = new Extrafields($db);
$expeditionLineExtrafieldLabels = $expeditionLineExtrafields->fetch_name_optionals_label($srcLine->table_element);

View File

@ -556,7 +556,14 @@ if (! empty($conf->fournisseur->enabled)) $rowspan++;
print '<tr class="oddeven">';
print '<td>'.$langs->trans("PricingRule").'</td>';
if (empty($conf->multicompany->enabled))
{
print '<td>'.$langs->trans("PricingRule").'</td>';
}
else
{
print '<td>'.$form->textwithpicto($langs->trans("PricingRule"), $langs->trans("SamePriceAlsoForSharedCompanies"), 1).'</td>';
}
print '<td width="60" class="right">';
$current_rule = 'PRODUCT_PRICE_UNIQ';
if (!empty($conf->global->PRODUIT_MULTIPRICES)) $current_rule='PRODUIT_MULTIPRICES';
@ -564,10 +571,6 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) $current_rule='PRODUI
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) $current_rule='PRODUIT_CUSTOMER_PRICES';
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $current_rule='PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES';
print $form->selectarray("princingrule", $select_pricing_rules, $current_rule);
if ( empty($conf->multicompany->enabled))
{
print $langs->trans("SamePriceAlsoForSharedCompanies");
}
print '</td><td rowspan="'.$rowspan.'" class="nohover right">';
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</td>';

View File

@ -1028,7 +1028,7 @@ else
if ($type == 1)
{
print '<tr><td>'.$langs->trans("Duration").'</td><td colspan="3">';
print '<input name="surface" size="4" value="'.GETPOST('duration_value', 'int').'">';
print '<input name="duration_value" size="4" value="'.GETPOST('duration_value', 'int').'">';
print $formproduct->selectMeasuringUnits("duration_unit", "time", GETPOST('duration_value', 'alpha'), 0, 1);
print '</td></tr>';
}

View File

@ -262,26 +262,29 @@ class PriceParser
return -1;
}
//Get the supplier min
$productFournisseur = new ProductFournisseur($this->db);
if ($productFournisseur->find_min_price_product_fournisseur($product->id, 0, 0) > 0) {
$supplier_min_price = $productFournisseur->fourn_unitprice;
}
//Get the supplier min price
$productFournisseur = new ProductFournisseur($this->db);
$res = $productFournisseur->find_min_price_product_fournisseur($product->id, 0, 0);
if ($res < 1) {
$this->error_parser = array(25, null);
return -1;
}
$supplier_min_price = $productFournisseur->fourn_unitprice;
//Accessible values by expressions
$extra_values = array_merge($extra_values, array(
"supplier_min_price" => $supplier_min_price,
));
//Accessible values by expressions
$extra_values = array_merge($extra_values, array(
"supplier_min_price" => $supplier_min_price,
));
//Parse the expression and return the price, if not error occurred check if price is higher than min
$result = $this->parseExpression($product, $price_expression->expression, $extra_values);
if (empty($this->error_parser)) {
if ($result < $product->price_min) {
$result = $product->price_min;
}
}
return $result;
}
//Parse the expression and return the price, if not error occurred check if price is higher than min
$result = $this->parseExpression($product, $price_expression->expression, $extra_values);
if (empty($this->error_parser)) {
if ($result < $product->price_min) {
$result = $product->price_min;
}
}
return $result;
}
/**
* Calculates supplier product price based on product supplier price and associated expression

View File

@ -236,7 +236,8 @@ if ($id > 0 || ! empty($ref))
$objp = $db->fetch_object($result);
if ($objp->type == Facture::TYPE_CREDIT_NOTE) $objp->qty=-($objp->qty);
$total_ht+=$objp->total_ht;
$total_ht+=$objp->total_ht;
$total_qty+=$objp->qty;
$invoicestatic->id=$objp->facid;

View File

@ -826,7 +826,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
print '<br>';
// List of Stripe payment modes
if (! (empty($conf->stripe->enabled)))
if (! (empty($conf->stripe->enabled)) && $object->client)
{
$morehtmlright='';
if (! empty($conf->global->STRIPE_ALLOW_LOCAL_CARD))
@ -1188,11 +1188,10 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard'
}
print "</table>";
print "</div>";
print '<br>';
}
// List of bank accounts
print '<br>';
$morehtmlright= dolGetButtonTitle($langs->trans('Add'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"].'?socid='.$object->id.'&amp;action=create');

View File

@ -254,7 +254,7 @@ if (empty($conf->stripeconnect->enabled))
print price($conf->global->STRIPE_APPLICATION_FEE_PERCENT);
print '% + ';
print price($conf->global->STRIPE_APPLICATION_FEE);
print ' '.$langs->getCurrencySymbol($conf->currency).' '.$langs->trans("minimum").' '.price($conf->global->STRIPE_APPLICATION_FEE_MINIMAL).' '.$langs->getCurrencySymbol($conf->currency).' </td></tr>';
print ' '.$langs->getCurrencySymbol($conf->currency).' '.$langs->trans("minimum").' '.price($conf->global->STRIPE_APPLICATION_FEE_MINIMAL).' '.$langs->getCurrencySymbol($conf->currency);
print '</td><td></td></tr>';
}

View File

@ -121,6 +121,30 @@ if (!$rowid)
//print $list;
foreach ($list->data as $charge)
{
if ($charge->refunded=='1'){
$status = img_picto($langs->trans("refunded"), 'statut6');
} elseif ($charge->paid=='1'){
$status = img_picto($langs->trans("".$charge->status.""), 'statut4');
} else {
$label="Message: ".$charge->failure_message."<br>";
$label.="Réseau: ".$charge->outcome->network_status."<br>";
$label.="Statut: ".$langs->trans("".$charge->outcome->seller_message."");
$status = $form->textwithpicto(img_picto($langs->trans("".$charge->status.""), 'statut8'), $label, 1);
}
if ($charge->payment_method_details->type=='card')
{
$type = $langs->trans("card");
} elseif ($charge->source->type=='card'){
$type = $langs->trans("card");
} elseif ($charge->payment_method_details->type=='three_d_secure'){
$type = $langs->trans("card3DS");
}
if (! empty($charge->payment_intent)) {
$charge = \Stripe\PaymentIntent::retrieve($charge->payment_intent);
}
// The metadata FULLTAG is defined by the online payment page
$FULLTAG=$charge->metadata->FULLTAG;
@ -205,31 +229,13 @@ if (!$rowid)
print '<td class="center">'.dol_print_date($charge->created, '%d/%m/%Y %H:%M')."</td>\n";
// Type
print '<td>';
if ($charge->source->object=='card')
{
print $langs->trans("card");
}
elseif ($charge->source->type=='card'){
print $langs->trans("card");
} elseif ($charge->source->type=='three_d_secure'){
print $langs->trans("card3DS");
}
print $type;
print '</td>';
// Amount
print '<td class="right">'.price(($charge->amount-$charge->amount_refunded)/100, 0, '', 1, - 1, - 1, strtoupper($charge->currency))."</td>";
// Status
print '<td class="right">';
if ($charge->refunded=='1'){
print img_picto($langs->trans("refunded"), 'statut6');
} elseif ($charge->paid=='1'){
print img_picto($langs->trans("".$charge->status.""), 'statut4');
} else {
$label="Message: ".$charge->failure_message."<br>";
$label.="Réseau: ".$charge->outcome->network_status."<br>";
$label.="Statut: ".$langs->trans("".$charge->outcome->seller_message."");
print $form->textwithpicto(img_picto($langs->trans("".$charge->status.""), 'statut8'), $label, 1);
}
print $status;
print "</td>\n";
print "</tr>\n";

View File

@ -321,14 +321,14 @@ class Stripe extends CommonObject
if (! in_array($currency_code, $arrayzerounitcurrency)) $stripeamount = $amount * 100;
else $stripeamount = $amount;
$fee = round($amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE);
$fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
$fee = round($conf->global->STRIPE_APPLICATION_FEE_MAXIMAL);
$fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
} elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
$fee = round($conf->global->STRIPE_APPLICATION_FEE_MINIMAL);
$fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
}
if (! in_array($currency_code, $arrayzerounitcurrency)) $stripefee = $fee * 100;
else $stripefee = $fee;
if (! in_array($currency, $arrayzerounitcurrency)) $stripefee = round($fee * 100);
else $stripefee = round($fee);
$paymentintent = null;
@ -710,15 +710,14 @@ class Stripe extends CommonObject
$charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description"));
}
} else {
$fee = round($amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE);
if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
$fee = round($conf->global->STRIPE_APPLICATION_FEE_MAXIMAL);
}
elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
$fee = round($conf->global->STRIPE_APPLICATION_FEE_MINIMAL);
}
if (! in_array($currency, $arrayzerounitcurrency)) $stripefee = $fee * 100;
else $stripefee = $fee;
$fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
$fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
} elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
$fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
}
if (! in_array($currency, $arrayzerounitcurrency)) $stripefee = round($fee * 100);
else $stripefee = round($fee);
$paymentarray = array(
"amount" => "$stripeamount",

View File

@ -55,4 +55,4 @@ else
\Stripe\Stripe::setApiKey($stripearrayofkeys['secret_key']);
\Stripe\Stripe::setAppInfo("Dolibarr Stripe", DOL_VERSION, "https://www.dolibarr.org"); // add dolibarr version
\Stripe\Stripe::setApiVersion("2019-03-14"); // force version API
\Stripe\Stripe::setApiVersion("2019-05-16"); // force version API

View File

@ -160,15 +160,15 @@ class Tickets extends DolibarrApi
$num = count($this->ticket->cache_msgs_ticket);
$i = 0;
while ($i < $num) {
if ($this->ticket->cache_msgs_ticket[$i]['fk_user_action'] > 0) {
if ($this->ticket->cache_msgs_ticket[$i]['fk_user_author'] > 0) {
$user_action = new User($this->db);
$user_action->fetch($this->ticket->cache_msgs_ticket[$i]['fk_user_action']);
$user_action->fetch($this->ticket->cache_msgs_ticket[$i]['fk_user_author']);
}
// Now define messages
$messages[] = array(
'id' => $this->ticket->cache_msgs_ticket[$i]['id'],
'fk_user_action' => $this->ticket->cache_msgs_ticket[$i]['fk_user_action'],
'fk_user_action' => $this->ticket->cache_msgs_ticket[$i]['fk_user_author'],
'fk_user_action_socid' => $user_action->socid,
'fk_user_action_string' => dolGetFirstLastname($user_action->firstname, $user_action->lastname),
'message' => $this->ticket->cache_msgs_ticket[$i]['message'],
@ -195,6 +195,7 @@ class Tickets extends DolibarrApi
// Now define messages
$history[] = array(
'id' => $this->ticket->cache_logs_ticket[$i]['id'],
'fk_user_author' => $this->ticket->cache_msgs_ticket[$i]['fk_user_author'],
'fk_user_action' => $this->ticket->cache_logs_ticket[$i]['fk_user_create'],
'fk_user_action_string' => dolGetFirstLastname($user_action->firstname, $user_action->lastname),
'message' => $this->ticket->cache_logs_ticket[$i]['message'],