Merge branch '15.0' of git@github.com:Dolibarr/dolibarr.git into develop
This commit is contained in:
commit
9049134556
@ -15,7 +15,7 @@ NEW: Add option to disable globaly some notifications emails.
|
||||
NEW: #18326 Workflow: Close order on shipment closing.
|
||||
NEW: #18401 Add __NEWREF__ subtitute to get new object reference.
|
||||
NEW: #18403 Add __URL_SHIPMENT__ substitute to get the URL of a shipment
|
||||
NEW: #18689 REST API module: add api key generate / modify right.
|
||||
NEW: #18689 REST API module: add api key generate / modify pemrission.
|
||||
NEW: #18663 Make "L'Annuaire des Entreprises" the default provider for SIREN verification for French thirdparties.
|
||||
NEW: #18046 Add tags on ticket/categories
|
||||
NEW: #18326 Workflow: Close order on shipment closing.
|
||||
@ -123,6 +123,7 @@ NEW: Introduce method hasRight
|
||||
NEW: Can use textarea field into a confirm popup.
|
||||
NEW: Can use the result_mode of mysqli driver. Save memory for list count
|
||||
NEW: #18319 REST API - Shipment: Add 'close' action / endpoint / POST method.
|
||||
NEW: Add API /approve and /makeOrder for purchase orders.
|
||||
NEW: add action trigger for member excluded
|
||||
NEW: add option MAIN_IBAN_IS_NEVER_MANDATORY, MAIN_IBAN_NOT_MANDATORY, PROPAL_NOT_BILLABLE, PROPAL_REOPEN_UNSIGNED_ONLY, PROPOSAL_ARE_NOT_BILLABLE, TICKETS_MESSAGE_FORCE_MAIL
|
||||
NEW: Add code codebar column on serial/lot structure
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
|
||||
div.divsearchfield {
|
||||
float: left;
|
||||
margin: 4px 12px 4px 2px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
@ -535,11 +535,11 @@ if ($mode == 'common' || $mode == 'commonkanban') {
|
||||
|
||||
//$moreforfilter .= '<div class="floatright center marginrightonly hideonsmartphone" style="padding-top: 3px"><span class="paddingright">'.$moreinfo.'</span> '.$moreinfo2.'</div>';
|
||||
|
||||
$moreforfilter .= '<div class="colorbacktimesheet float valignmiddle">';
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop">';
|
||||
$moreforfilter .= '<div class="divfilteralone colorbacktimesheet float valignmiddle">';
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
|
||||
$moreforfilter .= img_picto($langs->trans("Filter"), 'filter', 'class="paddingright opacityhigh hideonsmartphone"').'<input type="text" id="search_keyword" name="search_keyword" class="maxwidth125" value="'.dol_escape_htmltag($search_keyword).'" placeholder="'.dol_escape_htmltag($langs->trans('Keyword')).'">';
|
||||
$moreforfilter .= '</div>';
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop">';
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
|
||||
$moreforfilter .= $form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), $langs->trans('Origin'), 0, 0, '', 0, 0, 0, '', 'maxwidth250', 1);
|
||||
$moreforfilter .= '</div>';
|
||||
if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) {
|
||||
@ -553,16 +553,16 @@ if ($mode == 'common' || $mode == 'commonkanban') {
|
||||
if ($conf->global->MAIN_FEATURES_LEVEL > 1) {
|
||||
$array_version['development'] = $langs->trans("Development");
|
||||
}
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop">';
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
|
||||
$moreforfilter .= $form->selectarray('search_version', $array_version, $search_version, $langs->trans('Version'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1);
|
||||
$moreforfilter .= '</div>';
|
||||
}
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop">';
|
||||
$moreforfilter .= '<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
|
||||
$moreforfilter .= $form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, $langs->trans('Status'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1);
|
||||
$moreforfilter .= '</div>';
|
||||
$moreforfilter .= ' ';
|
||||
$moreforfilter .= '<div class="divsearchfield">';
|
||||
$moreforfilter .= '<input type="submit" name="buttonsubmit" class="button" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">';
|
||||
$moreforfilter .= '<div class="divsearchfield valignmiddle inline-block">';
|
||||
$moreforfilter .= '<input type="submit" name="buttonsubmit" class="button small" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">';
|
||||
if ($search_keyword || ($search_nature && $search_nature != '-1') || ($search_version && $search_version != '-1') || ($search_status && $search_status != '-1')) {
|
||||
$moreforfilter .= ' ';
|
||||
$moreforfilter .= '<input type="submit" name="buttonreset" class="buttonreset noborderbottom" value="'.dol_escape_htmltag($langs->trans("Reset")).'">';
|
||||
@ -1139,7 +1139,7 @@ if ($mode == 'deploy') {
|
||||
}
|
||||
|
||||
if ($allowfromweb == 1) {
|
||||
print $langs->trans("UnpackPackageInModulesRoot", $dirins).'<br>';
|
||||
print '<span class="opacitymedium">'.$langs->trans("UnpackPackageInModulesRoot", $dirins).'</span><br>';
|
||||
|
||||
print '<br>';
|
||||
|
||||
|
||||
@ -624,6 +624,9 @@ class Documents extends DolibarrApi
|
||||
} elseif ($modulepart == 'expensereport') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
|
||||
$object = new ExpenseReport($this->db);
|
||||
} elseif ($modulepart == 'fichinter') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
|
||||
$object = new Fichinter($this->db);
|
||||
} elseif ($modulepart == 'adherent' || $modulepart == 'member') {
|
||||
$modulepart = 'adherent';
|
||||
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
|
||||
|
||||
@ -1261,7 +1261,7 @@ class FormTicket
|
||||
// Zone to select its email template
|
||||
if (count($modelmail_array) > 0) {
|
||||
print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
|
||||
print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1);
|
||||
print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1, 0, "", "", 0, 0, 0, '', 'minwidth200');
|
||||
if ($user->admin) {
|
||||
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
|
||||
}
|
||||
|
||||
@ -369,6 +369,189 @@ class SupplierOrders extends DolibarrApi
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve an order
|
||||
*
|
||||
* @param int $id Order ID
|
||||
* @param int $idwarehouse Warehouse ID
|
||||
* @param int $secondlevel 1=Does not execute triggers, 0= execute triggers
|
||||
*
|
||||
* @url POST {id}/approve
|
||||
*
|
||||
* @return array
|
||||
* FIXME An error 403 is returned if the request has an empty body.
|
||||
* Error message: "Forbidden: Content type `text/plain` is not supported."
|
||||
* Workaround: send this in the body
|
||||
* {
|
||||
* "idwarehouse": 0,
|
||||
* "secondlevel": 0
|
||||
* }
|
||||
*/
|
||||
public function approve($id, $idwarehouse = 0, $secondlevel = 0)
|
||||
{
|
||||
if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->creer) && empty(DolibarrApiAccess::$user->rights->supplier_order->creer)) {
|
||||
throw new RestException(401);
|
||||
}
|
||||
$result = $this->order->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Order not found');
|
||||
}
|
||||
|
||||
if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) {
|
||||
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
$result = $this->order->approve(DolibarrApiAccess::$user, $idwarehouse, $secondlevel);
|
||||
if ($result == 0) {
|
||||
throw new RestException(304, 'Error nothing done. May be object is already approved');
|
||||
}
|
||||
if ($result < 0) {
|
||||
throw new RestException(500, 'Error when approve Order: '.$this->order->error);
|
||||
}
|
||||
|
||||
return array(
|
||||
'success' => array(
|
||||
'code' => 200,
|
||||
'message' => 'Order approved (Ref='.$this->order->ref.')'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends an order to the vendor
|
||||
*
|
||||
* @param int $id Order ID
|
||||
* @param integer $date Date (unix timestamp in sec)
|
||||
* @param int $method Method
|
||||
* @param string $comment Comment
|
||||
*
|
||||
* @url POST {id}/makeorder
|
||||
*
|
||||
* @return array
|
||||
* FIXME An error 403 is returned if the request has an empty body.
|
||||
* Error message: "Forbidden: Content type `text/plain` is not supported."
|
||||
* Workaround: send this in the body
|
||||
* {
|
||||
* "date": 0,
|
||||
* "method": 0,
|
||||
* "comment": ""
|
||||
* }
|
||||
*/
|
||||
public function makeOrder($id, $date, $method, $comment = '')
|
||||
{
|
||||
if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->creer) && empty(DolibarrApiAccess::$user->rights->supplier_order->creer)) {
|
||||
throw new RestException(401);
|
||||
}
|
||||
$result = $this->order->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Order not found');
|
||||
}
|
||||
|
||||
if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) {
|
||||
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
$result = $this->order->commande(DolibarrApiAccess::$user, $date, $method, $comment);
|
||||
if ($result == 0) {
|
||||
throw new RestException(304, 'Error nothing done. May be object is already sent');
|
||||
}
|
||||
if ($result < 0) {
|
||||
throw new RestException(500, 'Error when sending Order: '.$this->order->error);
|
||||
}
|
||||
|
||||
return array(
|
||||
'success' => array(
|
||||
'code' => 200,
|
||||
'message' => 'Order sent (Ref='.$this->order->ref.')'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives the order, dispatches products.
|
||||
*
|
||||
* Example:
|
||||
* <code> {
|
||||
* "closeopenorder": 1,
|
||||
* "comment": "",
|
||||
* "lines": [{
|
||||
* "id": 14,
|
||||
* "fk_product": 112,
|
||||
* "qty": 18,
|
||||
* "warehouse": 1,
|
||||
* "price": 114,
|
||||
* "comment": "",
|
||||
* "eatby": 0,
|
||||
* "sellby": 0,
|
||||
* "batch": 0,
|
||||
* "notrigger": 0
|
||||
* }]
|
||||
* }</code>
|
||||
*
|
||||
* @param int $id Order ID
|
||||
* @param integer $closeopenorder Close order if everything is received {@required false}
|
||||
* @param string $comment Comment {@required false}
|
||||
* @param array $lines Array of product dispatches
|
||||
*
|
||||
* @url POST {id}/receive
|
||||
*
|
||||
* @return array
|
||||
* FIXME An error 403 is returned if the request has an empty body.
|
||||
* Error message: "Forbidden: Content type `text/plain` is not supported."
|
||||
*
|
||||
*/
|
||||
public function receiveOrder($id, $closeopenorder, $comment, $lines)
|
||||
{
|
||||
if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->creer) && empty(DolibarrApiAccess::$user->rights->supplier_order->creer)) {
|
||||
throw new RestException(401);
|
||||
}
|
||||
$result = $this->order->fetch($id);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Order not found');
|
||||
}
|
||||
|
||||
if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) {
|
||||
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||
}
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$lineObj =(object) $line;
|
||||
|
||||
$result=$this->order->dispatchProduct(DolibarrApiAccess::$user,
|
||||
$lineObj->fk_product,
|
||||
$lineObj->qty,
|
||||
$lineObj->warehouse,
|
||||
$lineObj->price,
|
||||
$lineObj->comment,
|
||||
$lineObj->eatby,
|
||||
$lineObj->sellby,
|
||||
$lineObj->batch,
|
||||
$lineObj->id,
|
||||
$lineObj->notrigger);
|
||||
|
||||
if ($result < 0) {
|
||||
throw new RestException(500, 'Error dispatch order line '.$line->id.': '.$this->order->error);
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->order->calcAndSetStatusDispatch(DolibarrApiAccess::$user, $closeopenorder, $comment);
|
||||
|
||||
if ($result == 0) {
|
||||
throw new RestException(304, 'Error nothing done. May be object is already dispatched');
|
||||
}
|
||||
if ($result < 0) {
|
||||
throw new RestException(500, 'Error when receivce order: '.$this->order->error);
|
||||
}
|
||||
|
||||
return array(
|
||||
'success' => array(
|
||||
'code' => 200,
|
||||
'message' => 'Order received (Ref='.$this->order->ref.')'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
|
||||
/**
|
||||
* Clean sensible object datas
|
||||
|
||||
@ -343,7 +343,7 @@ StepNb=Step %s
|
||||
FindPackageFromWebSite=Find a package that provides the features you need (for example on the official web site %s).
|
||||
DownloadPackageFromWebSite=Download package (for example from the official web site %s).
|
||||
UnpackPackageInDolibarrRoot=Unpack/unzip the packaged files into your Dolibarr server directory: <b>%s</b>
|
||||
UnpackPackageInModulesRoot=To deploy/install an external module, unpack/unzip the packaged files into the server directory dedicated to external modules:<br><b>%s</b>
|
||||
UnpackPackageInModulesRoot=To deploy/install an external module, you must unpack/unzip the archive file into the server directory dedicated to external modules:<br><b>%s</b>
|
||||
SetupIsReadyForUse=Module deployment is finished. You must however enable and setup the module in your application by going to the page setup modules: <a href="%s">%s</a>.
|
||||
NotExistsDirect=The alternative root directory is not defined to an existing directory.<br>
|
||||
InfDirAlt=Since version 3, it is possible to define an alternative root directory. This allows you to store, into a dedicated directory, plug-ins and custom templates.<br>Just create a directory at the root of Dolibarr (eg: custom).<br>
|
||||
|
||||
@ -7,6 +7,11 @@ if (!defined('ISLOADEDBYSTEELSHEET')) {
|
||||
* Dropdown of user popup
|
||||
*/
|
||||
|
||||
.bookmark-footer a.top-menu-dropdown-link {
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
button.dropdown-item.global-search-item {
|
||||
outline: none;
|
||||
}
|
||||
@ -15,6 +20,12 @@ button.dropdown-item.global-search-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#topmenu-bookmark-dropdown .dropdown-menu {
|
||||
min-width: 300px;
|
||||
max-width: 360px;
|
||||
}
|
||||
|
||||
|
||||
.dropdown-search {
|
||||
border-color: #eee;
|
||||
|
||||
|
||||
@ -261,7 +261,7 @@ input:invalid, select:invalid, input.--error , select.--error {
|
||||
div.tabBar textarea:focus {
|
||||
border: 1px solid #aaa !important;
|
||||
}
|
||||
input:focus:not(.select2-search__field), select:focus, .select2-container--open .select2-selection--single {
|
||||
input:focus:not(.button):not(.select2-search__field):not(#top-bookmark-search-input), select:focus, .select2-container--open .select2-selection--single {
|
||||
/* div.tabBar input:focus, div.tabBar select:focus { */
|
||||
border-bottom: 1px solid #666 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
@ -985,12 +985,18 @@ span.fa.fa-plus-circle.paddingleft {
|
||||
padding-<?php print $right; ?>: 20px;
|
||||
}
|
||||
div.divsearchfield {
|
||||
float: <?php print $left; ?>;
|
||||
/* float: <?php print $left; ?>; */
|
||||
display: inline-block;
|
||||
margin-<?php print $right; ?>: 12px;
|
||||
margin-<?php print $left; ?>: 2px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
padding-left: 2px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.divfilteralone {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
border-radius: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.divsearchfieldfilter {
|
||||
text-overflow: clip;
|
||||
@ -2808,8 +2814,8 @@ div.login a:hover {
|
||||
div.login_block_user {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: <?php echo $disableimages ? '25' : '50'; ?>px;
|
||||
height: <?php echo $disableimages ? '25' : '50'; ?>px;
|
||||
line-height: <?php echo $disableimages ? '25' : '52'; ?>px;
|
||||
height: <?php echo $disableimages ? '25' : '52'; ?>px;
|
||||
}
|
||||
div.login_block_other {
|
||||
display: inline-block;
|
||||
@ -3396,6 +3402,7 @@ input.buttonreset {
|
||||
padding: 8px 15px;
|
||||
text-decoration: underline;
|
||||
color: var(--colortextlink);
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
.nopaddingleft {
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
if (!defined('ISLOADEDBYSTEELSHEET')) {
|
||||
die('Must be call by steelsheet');
|
||||
} ?>
|
||||
|
||||
/* <style type="text/css" > dont remove this line it's an ide hack */
|
||||
/*
|
||||
* Dropdown of user popup
|
||||
@ -10,6 +9,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) {
|
||||
|
||||
.bookmark-footer a.top-menu-dropdown-link {
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
button.dropdown-item.global-search-item {
|
||||
@ -35,7 +35,8 @@ div#topmenu-bookmark-dropdown {
|
||||
}
|
||||
|
||||
#topmenu-bookmark-dropdown .dropdown-menu {
|
||||
width: 300px;
|
||||
min-width: 300px;
|
||||
max-width: 360px;
|
||||
}
|
||||
|
||||
button.dropdown-item.global-search-item {
|
||||
|
||||
@ -1098,13 +1098,19 @@ a.editfielda.nohover *:hover:before {
|
||||
.divsocialnetwork:not(:last-child) {
|
||||
padding-<?php print $right; ?>: 20px;
|
||||
}
|
||||
.divfilteralone {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
border-radius: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
div.divsearchfield {
|
||||
float: <?php print $left; ?>;
|
||||
/* float: <?php print $left; ?>; */
|
||||
display: inline-block;
|
||||
margin-<?php print $right; ?>: 12px;
|
||||
margin-<?php print $left; ?>: 2px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
padding-left: 2px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.divsearchfieldfilter {
|
||||
text-overflow: clip;
|
||||
@ -3442,6 +3448,7 @@ input.buttonreset {
|
||||
padding: 8px 15px;
|
||||
text-decoration: underline;
|
||||
color: var(--colortextlink);
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user