Merge remote-tracking branch 'upstream/develop' into zapier

This commit is contained in:
Frédéric FRANCE 2019-09-17 08:24:31 +02:00
commit 850b9fd52a
No known key found for this signature in database
GPG Key ID: 06809324E4B2ABC1
25 changed files with 516 additions and 92 deletions

View File

@ -127,6 +127,15 @@ print '</td>';
print '<td></td>';
print '</tr>';
print '<tr class="oddeven">';
print '<td>'.$langs->trans('EnableResourceUsedInEventCheck').'</td>';
print '<td>';
echo ajax_constantonoff('RESOURCE_USED_IN_EVENT_CHECK');
print '</td>';
print '<td></td>';
print '</tr>';
print '</table>';
print '</form>';

View File

@ -512,6 +512,65 @@ if ($action == 'update')
$ret = $extrafields->setOptionalsFromPost($extralabels, $object);
if ($ret < 0) $error++;
if (!$error) {
// check if an event resource is already in use
if (!empty($conf->global->RESOURCE_USED_IN_EVENT_CHECK) && $object->element == 'action') {
$eventDateStart = $object->datep;
$eventDateEnd = $object->datef;
$sql = "SELECT er.rowid, r.ref as r_ref, ac.id as ac_id, ac.label as ac_label";
$sql .= " FROM " . MAIN_DB_PREFIX . "element_resources as er";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "resource as r ON r.rowid = er.resource_id AND er.resource_type = 'dolresource'";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "actioncomm as ac ON ac.id = er.element_id AND er.element_type = '" . $db->escape($object->element) . "'";
$sql .= " WHERE ac.id != " . $object->id;
$sql .= " AND er.resource_id IN (";
$sql .= " SELECT resource_id FROM " . MAIN_DB_PREFIX . "element_resources";
$sql .= " WHERE element_id = " . $object->id;
$sql .= " AND element_type = '" . $db->escape($object->element) . "'";
$sql .= " AND busy = 1";
$sql .= ")";
$sql .= " AND er.busy = 1";
$sql .= " AND (";
// event date start between ac.datep and ac.datep2 (if datep2 is null we consider there is no end)
$sql .= " (ac.datep <= '" . $db->idate($eventDateStart) . "' AND (ac.datep2 IS NULL OR ac.datep2 >= '" . $db->idate($eventDateStart) . "'))";
// event date end between ac.datep and ac.datep2
if (!empty($eventDateEnd)) {
$sql .= " OR (ac.datep <= '" . $db->idate($eventDateEnd) . "' AND (ac.datep2 >= '" . $db->idate($eventDateEnd) . "'))";
}
// event date start before ac.datep and event date end after ac.datep2
$sql .= " OR (";
$sql .= "ac.datep >= '" . $db->idate($eventDateStart) . "'";
if (!empty($eventDateEnd)) {
$sql .= " AND (ac.datep2 IS NOT NULL AND ac.datep2 <= '" . $db->idate($eventDateEnd) . "')";
}
$sql .= ")";
$sql .= ")";
$resql = $db->query($sql);
if (!$resql) {
$error++;
$object->error = $db->lasterror();
$object->errors[] = $object->error;
} else {
if ($db->num_rows($resql) > 0) {
// already in use
$error++;
$object->error = $langs->trans('ErrorResourcesAlreadyInUse') . ' : ';
while ($obj = $db->fetch_object($resql)) {
$object->error .= '<br> - ' . $langs->trans('ErrorResourceUseInEvent', $obj->r_ref, $obj->ac_label . ' [' . $obj->ac_id . ']');
}
$object->errors[] = $object->error;
}
$db->free($resql);
}
if ($error) {
setEventMessages($object->error, $object->errors, 'errors');
}
}
}
if (! $error)
{
$db->begin();

View File

@ -607,9 +607,7 @@ if ($resql)
$event->fk_element=$obj->fk_element;
$event->elementtype=$obj->elementtype;
$event->societe->id=$obj->fk_soc;
$event->thirdparty_id=$obj->fk_soc;
$event->contact->id=$obj->fk_contact;
$event->contact_id=$obj->fk_contact;
// Defined date_start_in_calendar and date_end_in_calendar property
@ -1569,28 +1567,31 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa
if ($event->type_code == 'ICALEVENT') print '<br>('.dol_trunc($event->icalname, $maxnbofchar).')';
$thirdparty_id = ($event->thirdparty_id > 0 ? $event->thirdparty_id : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0));
$contact_id = ($event->contact_id > 0 ? $event->contact_id : ((is_object($event->contact) && $event->cotact->id > 0) ? $event->contact->id : 0));
// If action related to company / contact
$linerelatedto='';
if (! empty($event->societe->id) && $event->societe->id > 0)
if ($thirdparty_id > 0)
{
if (! isset($cachethirdparties[$event->societe->id]) || ! is_object($cachethirdparties[$event->societe->id]))
if (! isset($cachethirdparties[$thirdparty_id]) || ! is_object($cachethirdparties[$thirdparty_id]))
{
$thirdparty=new Societe($db);
$thirdparty->fetch($event->societe->id);
$cachethirdparties[$event->societe->id]=$thirdparty;
$thirdparty->fetch($thirdparty_id);
$cachethirdparties[$thirdparty_id]=$thirdparty;
}
else $thirdparty=$cachethirdparties[$event->societe->id];
else $thirdparty=$cachethirdparties[$thirdparty_id];
if (! empty($thirdparty->id)) $linerelatedto.=$thirdparty->getNomUrl(1, '', 0);
}
if (! empty($event->contact->id) && $event->contact->id > 0)
if (! empty($contact_id) && $contact_id > 0)
{
if (! is_object($cachecontacts[$event->contact->id]))
if (! is_object($cachecontacts[$contact_id]))
{
$contact=new Contact($db);
$contact->fetch($event->contact->id);
$cachecontacts[$event->contact->id]=$contact;
$contact->fetch($contact_id);
$cachecontacts[$contact_id]=$contact;
}
else $contact=$cachecontacts[$event->contact->id];
else $contact=$cachecontacts[$contact_id];
if ($linerelatedto) $linerelatedto.='&nbsp;';
if (! empty($contact->id)) $linerelatedto.=$contact->getNomUrl(1, '', 0);
}

View File

@ -1376,7 +1376,7 @@ if ($resql)
// Debit
if (! empty($arrayfields['b.debit']['checked']))
{
print '<td class="right">';
print '<td class="nowrap right">';
if ($objp->amount < 0)
{
print price($objp->amount * -1);
@ -1390,7 +1390,7 @@ if ($resql)
// Credit
if (! empty($arrayfields['b.credit']['checked']))
{
print '<td class="right">';
print '<td class="nowrap right">';
if ($objp->amount > 0)
{
print price($objp->amount);

View File

@ -7624,18 +7624,20 @@ abstract class CommonObject
}
// Delete cascade first
foreach($this->childtablesoncascade as $table)
{
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table.' WHERE '.$this->fk_element.' = '.$this->id;
$resql = $this->db->query($sql);
if (! $resql)
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->error;
$this->db->rollback();
return -1;
}
}
if (! empty($this->childtablesoncascade)) {
foreach($this->childtablesoncascade as $table)
{
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table.' WHERE '.$this->fk_element.' = '.$this->id;
$resql = $this->db->query($sql);
if (! $resql)
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->error;
$this->db->rollback();
return -1;
}
}
}
if (! $error) {
if (! $notrigger) {
@ -7809,4 +7811,35 @@ abstract class CommonObject
}
}
}
/**
* copy related categories to another object
*
* @param int $fromId Id object source
* @param int $toId Id object cible
* @param string $type Type of category ('product', ...)
* @return int < 0 si erreur, > 0 si ok
*/
public function cloneCategories($fromId, $toId, $type = '')
{
$this->db->begin();
if (empty($type)) $type = $this->table_element;
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
$categorystatic = new Categorie($this->db);
$sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_" . $categorystatic->MAP_CAT_TABLE[$type] . " (fk_categorie, fk_product)";
$sql.= " SELECT fk_categorie, $toId FROM ".MAIN_DB_PREFIX."categorie_" . $categorystatic->MAP_CAT_TABLE[$type];
$sql.= " WHERE fk_product = '".$fromId."'";
if (! $this->db->query($sql))
{
$this->db->rollback();die($sql);
return -1;
}
$this->db->commit();
return 1;
}
}

View File

@ -7265,7 +7265,7 @@ function printCommonFooter($zone = 'private')
{
print "\n";
print '/* JS CODE TO ENABLE to manage handler to switch left menu page (menuhider) */'."\n";
print 'jQuery(".menuhider").click(function(event) {';
print 'jQuery("li.menuhider").click(function(event) {';
print ' if (!$( "body" ).hasClass( "sidebar-collapse" )){ event.preventDefault(); }'."\n";
print ' console.log("We click on .menuhider");'."\n";
print ' $("body").toggleClass("sidebar-collapse")'."\n";

View File

@ -55,22 +55,23 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout =
$usemenuhider = 1;
// Show/Hide vertical menu
// Show/Hide vertical menu. The hamburger icon for .menuhider action.
if ($mode != 'jmobile' && $mode != 'topnb' && $usemenuhider && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
{
$showmode=1;
$classname = 'class="tmenu menuhider"';
$idsel='menu';
$menu->add('#', '', 0, $showmode, $atarget, "xxx", '', 0, $id, $idsel, $classname);
$menu->add('#', (! empty($conf->global->THEME_TOPMENU_DISABLE_IMAGE) ? '<span class="fa fa-bars"></span>' : ''), 0, $showmode, $atarget, "xxx", '', 0, $id, $idsel, $classname);
}
$menu_arr = array();
// Home
$menu_arr[] = array(
'name' => 'Home',
'link' => '/index.php?mainmenu=home&amp;leftmenu=home',
'title' => (! empty($conf->global->THEME_TOPMENU_DISABLE_IMAGE)? '&nbsp; <span class="fa fa-home"></span> &nbsp;' : "Home") ,
'title' => (! empty($conf->global->THEME_TOPMENU_DISABLE_IMAGE) ? '<span class="fa fa-home"></span>' : "Home") ,
'level' => 0,
'enabled' => $showmode = 1,
'target' => $atarget,
@ -473,8 +474,35 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout =
$menu->liste = dol_sort_array($menu->liste, 'position');
// Output menu entries
// Show logo company
if (empty($conf->global->MAIN_MENU_INVERT) && empty($noout) && ! empty($conf->global->MAIN_SHOW_LOGO) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
{
$mysoc->logo_mini=$conf->global->MAIN_INFO_SOCIETE_LOGO_MINI;
$mysoc->logo_squarred_mini=$conf->global->MAIN_INFO_SOCIETE_LOGO_SQUARRED_MINI;
if (! empty($mysoc->logo_squarred_mini) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_squarred_mini))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_squarred_mini);
}
elseif (! empty($mysoc->logo_mini) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_mini))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_mini);
}
else
{
$urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo_squarred.png';
}
$title=$langs->trans("GoIntoSetupToChangeLogo");
print "\n".'<!-- Show logo on menu -->'."\n";
print_start_menu_entry('companylogo', 'class="tmenu tmenucompanylogo"', 1);
print '<div class="center backgroundforcompanylogo"><img class="mycompany" title="'.dol_escape_htmltag($title).'" alt="" src="'.$urllogo.'" style="max-width: 100px"></div>'."\n";
print_end_menu_entry(4);
}
if (empty($noout)) {
foreach($menu->liste as $menkey => $menuval) {
foreach($menu->liste as $menuval) {
print_start_menu_entry($menuval['idsel'], $menuval['classname'], $menuval['enabled']);
print_text_menu_entry($menuval['titre'], $menuval['enabled'], (($menuval['url']!='#' && !preg_match('/^(http:\/\/|https:\/\/)/i', $menuval['url'])) ? DOL_URL_ROOT:'').$menuval['url'], $menuval['id'], $menuval['idsel'], $menuval['classname'], ($menuval['target']?$menuval['target']:$atarget));
print_end_menu_entry($menuval['enabled']);
@ -615,30 +643,6 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM
$usemenuhider = 0;
// Show logo company
if (empty($conf->global->MAIN_MENU_INVERT) && empty($noout) && ! empty($conf->global->MAIN_SHOW_LOGO) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
{
$mysoc->logo_mini=$conf->global->MAIN_INFO_SOCIETE_LOGO_MINI;
if (! empty($mysoc->logo_mini) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_mini))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_mini);
}
else
{
$urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo.png';
}
$title=$langs->trans("GoIntoSetupToChangeLogo");
print "\n".'<!-- Show logo on menu -->'."\n";
print '<div class="blockvmenuimpair blockvmenulogo">'."\n";
print '<div class="menu_titre" id="menu_titre_logo"></div>';
print '<div class="menu_top" id="menu_top_logo"></div>';
print '<div class="menu_contenu" id="menu_contenu_logo">';
print '<div class="center"><img class="mycompany" title="'.dol_escape_htmltag($title).'" alt="" src="'.$urllogo.'" style="max-width: 70%"></div>'."\n";
print '</div>';
print '<div class="menu_end" id="menu_end_logo"></div>';
print '</div>'."\n";
}
if (is_array($moredata) && ! empty($moredata['searchform'])) // searchform can contains select2 code or link to show old search form or link to switch on search page
{
print "\n";

View File

@ -316,17 +316,21 @@ class modStock extends DolibarrModules
$this->import_fields_array[$r]=array('e.ref'=>"LocationSummary*",
'e.description'=>"DescWareHouse",'e.lieu'=>"LieuWareHouse",
'e.address'=>"Address",'e.zip'=>'Zip','e.fk_pays'=>'CountryCode',
'e.statut'=>'Status'
'e.statut'=>'Status',
'e.fk_parent'=>'ParentWarehouse'
);
$this->import_convertvalue_array[$r]=array(
'e.fk_pays'=>array('rule'=>'fetchidfromcodeid','classfile'=>'/core/class/ccountry.class.php','class'=>'Ccountry','method'=>'fetch','dict'=>'DictionaryCountry')
'e.fk_pays'=>array('rule'=>'fetchidfromcodeid','classfile'=>'/core/class/ccountry.class.php','class'=>'Ccountry','method'=>'fetch','dict'=>'DictionaryCountry'),
'e.fk_parent'=>array('rule'=>'fetchidfromref','classfile'=>'/product/stock/class/entrepot.class.php','class'=>'Entrepot','method'=>'fetch','element'=>'ref')
);
$this->import_regex_array[$r]=array('e.statut'=>'^[0|1]');
$this->import_examplevalues_array[$r]=array('e.ref'=>"ALM001",
'e.description'=>"Central Warehouse",'e.lieu'=>"Central",
'e.address'=>"Route 66",'e.zip'=>'28080','e.fk_pays'=>'US',
'e.statut'=>'1');
'e.statut'=>'1',
'e.fk_parent'=>''
);
// Import stocks
$r++;

View File

@ -70,7 +70,7 @@ INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, m
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-KONEGIE', 0, 41, '', 0, 6, 1, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-26OKT', 0, 41, '', 0, 10, 26, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-TOUSSAINT', 0, 41, '', 0, 11, 1, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-IMMACULE', 0, 41, '', 0, 12 8, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-IMMACULE', 0, 41, '', 0, 12, 8, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-24DEC', 0, 41, '', 0, 12, 24, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-SAINTSTEFAN', 0, 41, '', 0, 12, 26, 1);
INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('AT-Silvester', 0, 41, '', 0, 12, 31, 1);

View File

@ -1907,6 +1907,7 @@ ResourceSetup=Configuration of Resource module
UseSearchToSelectResource=Use a search form to choose a resource (rather than a drop-down list).
DisabledResourceLinkUser=Disable feature to link a resource to users
DisabledResourceLinkContact=Disable feature to link a resource to contacts
EnableResourceUsedInEventCheck=Enable feature to check if a resource is in use in an event
ConfirmUnactivation=Confirm module reset
OnMobileOnly=On small screen (smartphone) only
DisableProspectCustomerType=Disable the "Prospect + Customer" third party type (so third party must be Prospect or Customer but can't be both)

View File

@ -153,6 +153,7 @@ RowMaterial=Raw Material
ConfirmCloneProduct=Are you sure you want to clone product or service <b>%s</b>?
CloneContentProduct=Clone all main information of product/service
ClonePricesProduct=Clone prices
CloneCategoriesProduct=Clone tags/categories linked
CloneCompositionProduct=Clone virtual product/service
CloneCombinationsProduct=Clone product variants
ProductIsUsed=This product is used

View File

@ -34,3 +34,6 @@ IdResource=Id resource
AssetNumber=Serial number
ResourceTypeCode=Resource type code
ImportDataset_resource_1=Resources
ErrorResourcesAlreadyInUse=Some resources are in use
ErrorResourceUseInEvent=%s use in %s event

View File

@ -1907,6 +1907,7 @@ ResourceSetup=Configuration du module Ressource
UseSearchToSelectResource=Utilisez un champ avec auto-complétion pour choisir les ressources (plutôt qu'une liste déroulante).
DisabledResourceLinkUser=Désactiver la fonctionnalité pour lier une ressource aux utilisateurs
DisabledResourceLinkContact=Désactiver la fonctionnalité pour lier une ressource aux contacts/adresses
EnableResourceUsedInEventCheck=Activer la fonctionnalité de vérification d'une ressource déjà réservée lors d'un évènement
ConfirmUnactivation=Confirmer réinitialisation du module
OnMobileOnly=Sur petit écran (smartphone) uniquement
DisableProspectCustomerType=Désactiver le type de tiers "Prospect + Client" (le tiers doit donc être un client potentiel ou un client, mais ne peut pas être les deux)

View File

@ -153,6 +153,8 @@ RowMaterial=Matière première
ConfirmCloneProduct=Êtes-vous sûr de vouloir cloner le produit ou service <b>%s</b> ?
CloneContentProduct=Cloner les informations générales du produit/service
ClonePricesProduct=Cloner les prix
CloneCategoriesProduct=Cloner les catégories associées
CloneCompositionProduct=Cloner le produits packagés
CloneCompositionProduct=Cloner les produits virtuels
CloneCombinationsProduct=Cloner les variantes
ProductIsUsed=Ce produit est utilisé

View File

@ -34,3 +34,6 @@ IdResource=id ressource
AssetNumber=Numéro de série
ResourceTypeCode=Code de type de ressource
ImportDataset_resource_1=Ressources
ErrorResourcesAlreadyInUse=Des ressources sont déjà occupées
ErrorResourceUseInEvent=%s occupée dans l'événement %s

View File

@ -522,6 +522,19 @@ if (empty($reshook))
}
}
if (GETPOST('clone_categories'))
{
$result = $object->cloneCategories($originalId, $id);
if ($result < 1)
{
$db->rollback();
setEventMessage($langs->trans('ErrorProductClone'), null, 'errors');
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$originalId);
exit;
}
}
// $object->clone_fournisseurs($originalId, $id);
$db->commit();
@ -1951,6 +1964,7 @@ $formquestionclone=array(
'text' => $langs->trans("ConfirmClone"),
array('type' => 'text', 'name' => 'clone_ref','label' => $langs->trans("NewRefForClone"), 'value' => empty($tmpcode) ? $langs->trans("CopyOf").' '.$object->ref : $tmpcode, 'size'=>24),
array('type' => 'checkbox', 'name' => 'clone_content','label' => $langs->trans("CloneContentProduct"), 'value' => 1),
array('type' => 'checkbox', 'name' => 'clone_categories', 'label' => $langs->trans("CloneCategoriesProduct"), 'value' => 1),
array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct").' ('.$langs->trans("FeatureNotYetAvailable").')', 'value' => 0, 'disabled' => true),
);
if (! empty($conf->global->PRODUIT_SOUSPRODUITS))

View File

@ -467,6 +467,94 @@ class Products extends DolibarrApi
);
}
/**
* List purchase prices
*
* Get a list of all purchase prices of products
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service)
* @param int $category Use this param to filter list by category of product
* @param int $supplier Use this param to filter list by supplier
* @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)"
* @return array Array of product objects
*
* @url GET purchase_prices
*/
public function getSupplierProducts($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $supplier = 0, $sqlfilters = '')
{
global $db, $conf;
$obj_ret = array();
$socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : '';
$sql = "SELECT t.rowid, t.ref, t.ref_ext";
$sql.= " FROM ".MAIN_DB_PREFIX."product as t";
if ($category > 0) {
$sql.= ", ".MAIN_DB_PREFIX."categorie_product as c";
}
$sql.= ", ".MAIN_DB_PREFIX."product_fournisseur_price as s";
$sql.= ' WHERE t.entity IN ('.getEntity('product').')';
if ($supplier > 0) {
$sql.= " AND s.fk_soc = ".$db->escape($supplier);
}
$sql.= " AND s.fk_product = t.rowid ";
// Select products of given category
if ($category > 0) {
$sql.= " AND c.fk_categorie = ".$db->escape($category);
$sql.= " AND c.fk_product = t.rowid ";
}
if ($mode == 1) {
// Show only products
$sql.= " AND t.fk_product_type = 0";
} elseif ($mode == 2) {
// Show only services
$sql.= " AND t.fk_product_type = 1";
}
// Add sql filters
if ($sqlfilters) {
if (! DolibarrApi::_checkFilters($sqlfilters)) {
throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
}
$regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
$sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
}
$sql.= $db->order($sortfield, $sortorder);
if ($limit) {
if ($page < 0) {
$page = 0;
}
$offset = $limit * $page;
$sql.= $db->plimit($limit + 1, $offset);
}
$result = $db->query($sql);
if ($result) {
$num = $db->num_rows($result);
$min = min($num, ($limit <= 0 ? $num : $limit));
$i = 0;
while ($i < $min)
{
$obj = $db->fetch_object($result);
$product_static = new Product($db);
if($product_static->fetch($obj->rowid)) {
$obj_ret[] = $this->_cleanObjectDatas($product_static);
}
$i++;
}
}
else {
throw new RestException(503, 'Error when retrieve product list : '.$db->lasterror());
}
if(! count($obj_ret)) {
throw new RestException(404, 'No product found');
}
return $obj_ret;
}
/**
* Get purchase prices for a product
*
@ -515,7 +603,7 @@ class Products extends DolibarrApi
if($result) {
$this->product = new ProductFournisseur($this->db);
$this->product->fetch($id, $ref);
$this->product->list_product_fournisseur_price($id, $sortfield, $sortorder, 0, 0);
$this->product->list_product_fournisseur_price($id, '', '', 0, 0);
}
return $this->_cleanObjectDatas($this->product);

View File

@ -87,6 +87,8 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
if (empty($reshook))
{
$error = 0;
if ($action == 'add_element_resource' && ! $cancel)
{
$res = 0;
@ -100,8 +102,68 @@ if (empty($reshook))
{
$objstat = fetchObjectByElement($element_id, $element, $element_ref);
$objstat->element = $element; // For externals module, we need to keep @xx
$res = $objstat->add_element_resource($resource_id, $resource_type, $busy, $mandatory);
// TODO : add this check at update_linked_resource and when modifying event start or end date
// check if an event resource is already in use
if (!empty($conf->global->RESOURCE_USED_IN_EVENT_CHECK) && $objstat->element=='action' && $resource_type=='dolresource' && intval($busy)==1) {
$eventDateStart = $objstat->datep;
$eventDateEnd = $objstat->datef;
$isFullDayEvent = intval($objstat->fulldayevent);
if (empty($eventDateEnd)) {
if ($isFullDayEvent) {
$eventDateStartArr = dol_getdate($eventDateStart);
$eventDateStart = dol_mktime(0, 0, 0, $eventDateStartArr['mon'], $eventDateStartArr['mday'], $eventDateStartArr['year']);
$eventDateEnd = dol_mktime(23, 59, 59, $eventDateStartArr['mon'], $eventDateStartArr['mday'], $eventDateStartArr['year']);
}
}
$sql = "SELECT er.rowid, r.ref as r_ref, ac.id as ac_id, ac.label as ac_label";
$sql .= " FROM " . MAIN_DB_PREFIX . "element_resources as er";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "resource as r ON r.rowid = er.resource_id AND er.resource_type = '" . $db->escape($resource_type) . "'";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "actioncomm as ac ON ac.id = er.element_id AND er.element_type = '" . $db->escape($objstat->element) . "'";
$sql .= " WHERE er.resource_id = " . $resource_id;
$sql .= " AND er.busy = 1";
$sql .= " AND (";
// event date start between ac.datep and ac.datep2 (if datep2 is null we consider there is no end)
$sql .= " (ac.datep <= '" . $db->idate($eventDateStart) . "' AND (ac.datep2 IS NULL OR ac.datep2 >= '" . $db->idate($eventDateStart) . "'))";
// event date end between ac.datep and ac.datep2
if (!empty($eventDateEnd)) {
$sql .= " OR (ac.datep <= '" . $db->idate($eventDateEnd) . "' AND (ac.datep2 >= '" . $db->idate($eventDateEnd) . "'))";
}
// event date start before ac.datep and event date end after ac.datep2
$sql .= " OR (";
$sql .= "ac.datep >= '" . $db->idate($eventDateStart) . "'";
if (!empty($eventDateEnd)) {
$sql .= " AND (ac.datep2 IS NOT NULL AND ac.datep2 <= '" . $db->idate($eventDateEnd) . "')";
}
$sql .= ")";
$sql .= ")";
$resql = $db->query($sql);
if (!$resql) {
$error++;
$objstat->error = $db->lasterror();
$objstat->errors[] = $objstat->error;
} else {
if ($db->num_rows($resql)>0) {
// already in use
$error++;
$objstat->error = $langs->trans('ErrorResourcesAlreadyInUse') . ' : ';
while ($obj = $db->fetch_object($resql)) {
$objstat->error .= '<br> - ' . $langs->trans('ErrorResourceUseInEvent', $obj->r_ref, $obj->ac_label . ' [' . $obj->ac_id . ']');
}
$objstat->errors[] = $objstat->error;
}
$db->free($resql);
}
}
if (!$error) {
$res = $objstat->add_element_resource($resource_id, $resource_type, $busy, $mandatory);
}
}
if (! $error && $res > 0)
{
setEventMessages($langs->trans('ResourceLinkedWithSuccess'), null, 'mesgs');
@ -123,18 +185,73 @@ if (empty($reshook))
$object->busy = $busy;
$object->mandatory = $mandatory;
$result = $object->update_element_resource($user);
if (!empty($conf->global->RESOURCE_USED_IN_EVENT_CHECK) && $object->element_type=='action' && $object->resource_type=='dolresource' && intval($object->busy)==1) {
$eventDateStart = $object->objelement->datep;
$eventDateEnd = $object->objelement->datef;
$isFullDayEvent = intval($objstat->fulldayevent);
if (empty($eventDateEnd)) {
if ($isFullDayEvent) {
$eventDateStartArr = dol_getdate($eventDateStart);
$eventDateStart = dol_mktime(0, 0, 0, $eventDateStartArr['mon'], $eventDateStartArr['mday'], $eventDateStartArr['year']);
$eventDateEnd = dol_mktime(23, 59, 59, $eventDateStartArr['mon'], $eventDateStartArr['mday'], $eventDateStartArr['year']);
}
}
if ($result >= 0)
{
$sql = "SELECT er.rowid, r.ref as r_ref, ac.id as ac_id, ac.label as ac_label";
$sql .= " FROM " . MAIN_DB_PREFIX . "element_resources as er";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "resource as r ON r.rowid = er.resource_id AND er.resource_type = '" . $db->escape($object->resource_type) . "'";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "actioncomm as ac ON ac.id = er.element_id AND er.element_type = '" . $db->escape($object->element_type) . "'";
$sql .= " WHERE er.resource_id = " . $object->resource_id;
$sql .= " AND ac.id != " . $object->element_id;
$sql .= " AND er.busy = 1";
$sql .= " AND (";
// event date start between ac.datep and ac.datep2 (if datep2 is null we consider there is no end)
$sql .= " (ac.datep <= '" . $db->idate($eventDateStart) . "' AND (ac.datep2 IS NULL OR ac.datep2 >= '" . $db->idate($eventDateStart) . "'))";
// event date end between ac.datep and ac.datep2
if (!empty($eventDateEnd)) {
$sql .= " OR (ac.datep <= '" . $db->idate($eventDateEnd) . "' AND (ac.datep2 IS NULL OR ac.datep2 >= '" . $db->idate($eventDateEnd) . "'))";
}
// event date start before ac.datep and event date end after ac.datep2
$sql .= " OR (";
$sql .= "ac.datep >= '" . $db->idate($eventDateStart) . "'";
if (!empty($eventDateEnd)) {
$sql .= " AND (ac.datep2 IS NOT NULL AND ac.datep2 <= '" . $db->idate($eventDateEnd) . "')";
}
$sql .= ")";
$sql .= ")";
$resql = $db->query($sql);
if (!$resql) {
$error++;
$object->error = $db->lasterror();
$object->errors[] = $object->error;
} else {
if ($db->num_rows($resql)>0) {
// already in use
$error++;
$object->error = $langs->trans('ErrorResourcesAlreadyInUse') . ' : ';
while ($obj = $db->fetch_object($resql)) {
$object->error .= '<br> - ' . $langs->trans('ErrorResourceUseInEvent', $obj->r_ref, $obj->ac_label . ' [' . $obj->ac_id . ']');
}
$object->errors[] = $objstat->error;
}
$db->free($resql);
}
}
if (!$error) {
$result = $object->update_element_resource($user);
if ($result < 0) $error++;
}
if ($error) {
setEventMessages($object->error, $object->errors, 'errors');
} else {
setEventMessages($langs->trans('RessourceLineSuccessfullyUpdated'), null, 'mesgs');
header("Location: ".$_SERVER['PHP_SELF']."?element=".$element."&element_id=".$element_id);
exit;
}
else
{
setEventMessages($object->error, $object->errors, 'errors');
}
}
}

View File

@ -3915,17 +3915,17 @@ class Societe extends CommonObject
while($obj=$this->db->fetch_object($resql)) {
$tmpobject->id=$obj->rowid;
if ($obj->fk_statut != Facture::STATUS_DRAFT // Not a draft
&& ! ($obj->fk_statut == Facture::STATUS_ABANDONED && $obj->close_code == 'replaced') // Not a replaced invoice
if ($obj->fk_statut != $tmpobject::STATUS_DRAFT // Not a draft
&& ! ($obj->fk_statut == $tmpobject::STATUS_ABANDONED && $obj->close_code == 'replaced') // Not a replaced invoice
)
{
$outstandingTotal+= $obj->total_ht;
$outstandingTotalIncTax+= $obj->total_ttc;
}
if ($obj->paye == 0
&& $obj->fk_statut != Facture::STATUS_DRAFT // Not a draft
&& $obj->fk_statut != Facture::STATUS_ABANDONED // Not abandonned
&& $obj->fk_statut != Facture::STATUS_CLOSED) // Not classified as paid
&& $obj->fk_statut != $tmpobject::STATUS_DRAFT // Not a draft
&& $obj->fk_statut != $tmpobject::STATUS_ABANDONED // Not abandonned
&& $obj->fk_statut != $tmpobject::STATUS_CLOSED) // Not classified as paid
//$sql .= " AND (fk_statut <> 3 OR close_code <> 'abandon')"; // Not abandonned for undefined reason
{
$paiement = $tmpobject->getSommePaiement();
@ -3936,7 +3936,11 @@ class Societe extends CommonObject
}
//if credit note is converted but not used
if($mode == 'supplier' && $obj->type == FactureFournisseur::TYPE_CREDIT_NOTE && $tmpobject->isCreditNoteUsed())$outstandingOpened-=$tmpobject->getSumFromThisCreditNotesNotUsed();
// TODO Do this also for customer ?
if($mode == 'supplier' && $obj->type == FactureFournisseur::TYPE_CREDIT_NOTE && $tmpobject->isCreditNoteUsed())
{
$outstandingOpened-=$tmpobject->getSumFromThisCreditNotesNotUsed();
}
}
return array('opened'=>$outstandingOpened, 'total_ht'=>$outstandingTotal, 'total_ttc'=>$outstandingTotalIncTax); // 'opened' is 'incl taxes'
}

View File

@ -221,7 +221,7 @@ if (empty($conf->stripeconnect->enabled))
$endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_TEST_WEBHOOK_ID);
$endpoint->enabled_events = $stripearrayofwebhookevents;
if (GETPOST('webhook', 'alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID) {
if (empty(GETPOST('status', 'alpha'))) {
if (! GETPOST('status', 'alpha')) {
$endpoint->disabled = true;
} else {
$endpoint->disabled = false;

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -1058,6 +1058,41 @@ div.blockvmenulogo
{
border-bottom: 0 !important;
}
.backgroundforcompanylogo {
margin: <?php echo $disableimages?'0':'6'; ?>px;
margin-left: 8px;
margin-right: 8px;
background-color: rgba(255,255,255,0.7);
padding: 0;
border-radius: 5px;
height: <?php echo $disableimages?'20':'32'; ?>px;
/* width: 100px; */
max-width: 100px;
vertical-align: middle;
}
.backgroundforcompanylogo img.mycompany {
object-fit: contain;
width: inherit;
height: inherit;
}
#mainmenutd_companylogo::after, #mainmenutd_menu::after {
content: unset !important;
}
li#mainmenutd_companylogo .tmenucenter {
width: unset;
}
li#mainmenutd_companylogo {
min-width: unset !important;
}
<?php if ($disableimages) { ?>
li#mainmenutd_home {
min-width: unset !important;
}
li#mainmenutd_home .tmenucenter {
width: unset;
}
<?php } ?>
div.blockvmenupair, div.blockvmenuimpair {
border-top: none !important;
border-left: none !important;
@ -1504,9 +1539,6 @@ li.tmenu, li.tmenusel {
li.menuhider:hover {
background-image: none !important;
}
li.tmenusel, li.tmenu:hover {
/* background: rgba(0, 0, 0, 0.1); */
}
li.tmenusel::after, li.tmenu:hover::after{
content: "";
@ -1559,7 +1591,7 @@ div.tmenucenter
padding-top: 2px;
height: <?php print $heightmenu; ?>px;
<?php } ?>
width: 100%;
/* width: 100%; */
}
#menu_titre_logo {
padding-top: 0;
@ -1965,8 +1997,8 @@ div.login_block_other { padding-top: 0; text-align: right; margin-right: 8px; }
float: right;
vertical-align: top;
padding: 0px 3px 0px 4px !important;
line-height: 50px;
height: 50px;
line-height: <?php echo $disableimages?'25':'50'; ?>px;
height: <?php echo $disableimages?'25':'50'; ?>px;
}
.atoplogin, .atoplogin:hover {
color: #<?php echo $colortextbackhmenu; ?> !important;
@ -2003,8 +2035,8 @@ img.login, img.printer, img.entity {
font-weight: bold;
}
.userimg.atoplogin img.userphoto, .userimgatoplogin img.userphoto { /* size for user photo in login bar */
width: 32px;
height: 32px;
width: <?php echo $disableimages?'26':'32'; ?>px;
height: <?php echo $disableimages?'26':'32'; ?>px;
border-radius: 50%;
background-size: contain;
background-size: contain;
@ -2618,7 +2650,7 @@ table.liste th, table.noborder th, table.noborder tr.liste_titre td, table.nobor
}
table.liste td, table.noborder td, div.noborder form div, table.tableforservicepart1 td, table.tableforservicepart2 td {
padding: 7px 8px 7px 8px; /* t r b l */
line-height: 22px;
/* line-height: 22px; This create trouble on cell login on list of last events of a contract*/
height: 22px;
}
div.liste_titre_bydiv .divsearchfield {
@ -5641,7 +5673,7 @@ div.tabsElem a.tab {
/* nboftopmenuentries = <?php echo $nbtopmenuentries ?>, fontsize=<?php echo is_numeric($fontsize)?$fontsize.'px':$fontsize ?> */
/* rule to reduce top menu - 1st reduction: Reduce width of top menu icons */
@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC1) ? round($nbtopmenuentries * 90, 0) + 240 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC1; ?>px) /* reduction 1 */
@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC1) ? round($nbtopmenuentries * 90, 0) + 340 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC1; ?>px) /* reduction 1 */
{
div.tmenucenter {
width: <?php echo round(52); ?>px; /* size of viewport */
@ -5674,8 +5706,11 @@ div.tabsElem a.tab {
}
}
/* rule to reduce top menu - 2nd reduction: Reduce width of top menu icons again */
@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2) ? round($nbtopmenuentries * 69, 0) + 40 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2; ?>px) /* reduction 2 */
@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2) ? round($nbtopmenuentries * 69, 0) + 140 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2; ?>px) /* reduction 2 */
{
li.tmenucompanylogo {
display: none;
}
div.mainmenu {
height: 23px;
}
@ -5698,7 +5733,7 @@ div.tabsElem a.tab {
}
}
/* rule to reduce top menu - 3rd reduction: The menu for user is on left */
@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3) ? round($nbtopmenuentries * 47, 0) + 40 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3; ?>px) /* reduction 3 */
@media only screen and (max-width: <?php echo empty($conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3) ? round($nbtopmenuentries * 47, 0) + 140 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3; ?>px) /* reduction 3 */
{
.side-nav {
z-index: 200;

View File

@ -1948,6 +1948,11 @@ foreach($mainmenuusedarray as $val)
display: none;
<?php } ?>
}
.topmenuimage {
<?php if ($disableimages) { ?>
display: none;
<?php } ?>
}
a.tmenuimage {
display: block;
}
@ -2232,6 +2237,41 @@ div.blockvmenulogo
{
border-bottom: 0 !important;
}
.backgroundforcompanylogo {
margin: <?php echo $disableimages?'0':'6'; ?>px;
margin-left: 12px;
margin-right: 6px;
background-color: rgba(255,255,255,0.7);
padding: 0;
border-radius: 5px;
height: <?php echo $disableimages?'20':'32'; ?>px;
/* width: 100px; */
max-width: 100px;
vertical-align: middle;
}
.backgroundforcompanylogo img.mycompany {
object-fit: contain;
width: inherit;
height: inherit;
}
#mainmenutd_companylogo::after {
content: unset;
}
li#mainmenutd_companylogo .tmenucenter {
width: unset;
}
li#mainmenutd_companylogo {
min-width: unset !important;
}
<?php if ($disableimages) { ?>
li#mainmenutd_home {
min-width: unset !important;
}
li#mainmenutd_home .tmenucenter {
width: unset;
}
<?php } ?>
div.blockvmenupair, div.blockvmenuimpair
{
font-family: <?php print $fontlist ?>;
@ -5624,13 +5664,13 @@ border-top-right-radius: 6px;
}
.menuhider {
width: 40px;
width: <?php echo $disableimages ? 'auto' : '40'; ?>px;
}
/* nboftopmenuentries = <?php echo $nbtopmenuentries ?>, fontsize=<?php echo $fontsize ?> */
/* disableimages = <?php echo $disableimages; ?> */
/* rule to reduce top menu - 1st reduction */
@media only screen and (max-width: <?php echo round($nbtopmenuentries * $fontsize * 7, 0) + 200; ?>px)
@media only screen and (max-width: <?php echo round($nbtopmenuentries * $fontsize * 7, 0) + 300; ?>px)
{
div.tmenucenter {
max-width: <?php echo round($fontsize * 4); ?>px; /* size of viewport */
@ -5657,8 +5697,12 @@ border-top-right-radius: 6px;
}
}
/* rule to reduce top menu - 2nd reduction */
@media only screen and (max-width: <?php echo round($nbtopmenuentries * $fontsize * 4.5, 0) + 200; ?>px)
@media only screen and (max-width: <?php echo round($nbtopmenuentries * $fontsize * 4.5, 0) + 300; ?>px)
{
li.tmenucompanylogo {
display: none;
}
div.tmenucenter {
max-width: <?php echo round($fontsize * 2); ?>px; /* size of viewport */
text-overflow: clip;

View File

@ -58,7 +58,8 @@ if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS))
$socid=0;
if (isset($user->societe_id) && $user->societe_id > 0) $socid = $user->societe_id;
$feature2 = (($socid && $user->rights->user->self->creer)?'':'user');
if ($user->id == $id && (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->user->self_advance->readperms))) // A user can always read its own card if not advanced perms enabled, or if he has advanced perms
// A user can always read its own card if not advanced perms enabled, or if he has advanced perms, except for admin
if ($user->id == $id && (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->user->self_advance->readperms) && empty($user->admin)))
{
accessforbidden();
}

View File

@ -3308,7 +3308,7 @@ if ($action == 'replacesite' || $action == 'replacesiteconfirm')
print '<tr>';
print '<td>'.$langs->trans("Container").'</td>';
print '<td>';
print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$website->ref.'&pageid='.$answerrecord->id.'">'.$answerrecord->title.'</a>';
print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$website->ref.'&pageid='.$answerrecord->id.'">'.($answerrecord->title ? $answerrecord->title : $langs->trans("NoTitle")).'</a>';
print '</td>';
print '<td class="tdoverflow100">'.$answerrecord->description;
print '</td>';