Merge remote-tracking branch 'dolibarr/develop' into develop_origin

Conflicts:
	htdocs/societe/class/societe.class.php

Change-Id: I760cee3a4d7a59d6625efed8aa5dc16c9df043bb
This commit is contained in:
Regis Houssin 2016-07-28 09:53:10 +02:00
commit 6bf655c882
818 changed files with 10225 additions and 4748 deletions

View File

@ -52,7 +52,7 @@ jQuery Mobile 1.3.0 GPL and MIT License Yes
jQuery TableDnD 0.6 GPL and MIT License Yes JS library plugin TableDnD (to reorder table rows)
jQuery Timepicker 1.1.0 GPL and MIT License Yes JS library Timepicker addon for Datepicker
jQuery Tiptip 1.3 GPL and MIT License Yes JS library for tooltips
jsGantt 1.2 BSD License Yes JS library (to build Gantt reports)
jsGanttImproved 1.7.5.2 BSD License Yes JS library (to build Gantt reports)
JsTimezoneDetect 1.0.6 MIT License Yes JS library to detect user timezone
For licenses compatibility informations:

View File

@ -12,9 +12,23 @@ Upgrading to any other version or any other database system is abolutely require
make a Dolibarr upgrade.
***** ChangeLog for 5.0.0 compared to 4.0.* *****
For users:
...
WARNING:
Following changes may create regression for some external modules, but were necessary to make
Dolibarr better:
- Function delete of class Facture (invoice) need the object $user as first parameter. Also you must
check you make a fetch on object before calling the delete.
***** ChangeLog for 4.0.0 compared to 3.9.* *****
For users:
NEW: Add reccuring invoice feature and automatic generation of invoices.
NEW: Add module "Loan" as stable.
NEW: Add module "Supplier commercial proposal" (price request) is set to stable status.
@ -121,7 +135,6 @@ NEW: When emailing is not sent completely, show progression.
NEW: Add entity field in llx_societe_remise_except and llx_societe_remise
For developers:
NEW: Add a css class style called 'reposition', so when clicking on a link with this class will move scrollbarr to be placed at same page location.
NEW: TimeZone can be supplied to mktime
NEW: hook in shipment card

View File

@ -1,3 +1,5 @@
# Remove warning, we want to keep both standard and minified sources.
dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/*
dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jquery/*
dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jquery/*
# This is a textual data file
source-is-missing htdocs/includes/mobiledetect/mobiledetectlib/Mobile_Detect.json

View File

@ -187,7 +187,9 @@
<severity>0</severity>
</rule>
<rule ref="PEAR.Commenting.ClassComment.MissingTag" />
<rule ref="PEAR.Commenting.ClassComment.MissingTag">
<severity>0</severity>
</rule>
<rule ref="PEAR.Commenting.ClassComment.MissingAuthorTag">
<severity>0</severity>

View File

@ -35,6 +35,7 @@ require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
* Class Skeleton_Class
*
* Put here description of your class
*
* @see CommonObject
*/
class Skeleton_Class extends CommonObject
@ -228,7 +229,7 @@ class Skeleton_Class extends CommonObject
if (count($sqlwhere) > 0) {
$sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere);
}
if (!empty($sortfield)) {
$sql .= $this->db->order($sortfield,$sortorder);
}
@ -463,7 +464,7 @@ class Skeleton_Class extends CommonObject
$result.= $link . $this->ref . $linkend;
return $result;
}
/**
* Retourne le libelle du status d'un user (actif, inactif)
*
@ -518,8 +519,8 @@ class Skeleton_Class extends CommonObject
if ($status == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5');
}
}
/**
* Initialise object with example values
* Id must be 0 if object instance is a specimen

View File

@ -298,6 +298,8 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a
// boxes.lang
if (preg_match('/^BoxTitleLast/', $value)) $qualifiedforclean=0;
if (preg_match('/^BoxTitleLatest/', $value)) $qualifiedforclean=0;
// install.lang
if (preg_match('/^KeepDefaultValues/', $value)) $qualifiedforclean=0;
// main.lang
if (preg_match('/^Duration/', $value)) $qualifiedforclean=0;
if (preg_match('/^FormatDate/', $value)) $qualifiedforclean=0;
@ -342,7 +344,7 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a
}
//$search = '\'trans("'.$value.'")\'';
$search = '-e "\''.$value.'\'" -e \'"'.$value.'"\' -e "('.$value.')"';
$search = '-e "\''.$value.'\'" -e \'"'.$value.'"\' -e "('.$value.')" -e "('.$value.',"';
$string = 'grep -R -m 1 -F --exclude=includes/* --include=*.php '.$search.' '.$htdocs.'* '.$scripts.'*';
//print $string."<br>\n";
exec($string,$output);

View File

@ -5,7 +5,7 @@
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2012 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2012-2016 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2015 Alexandre Spangaro <aspangaro.dolibarr@gmail.com>
* Copyright (C) 2015-2016 Alexandre Spangaro <aspangaro.dolibarr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1418,11 +1418,11 @@ else
// Login
if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
{
print '<tr><td>'.$langs->trans("Login").' / '.$langs->trans("Id").'</td><td class="valeur">'.$object->login.'&nbsp;</td></tr>';
print '<tr><td class="titlefield">'.$langs->trans("Login").' / '.$langs->trans("Id").'</td><td class="valeur">'.$object->login.'&nbsp;</td></tr>';
}
// Type
print '<tr><td>'.$langs->trans("Type").'</td><td class="valeur">'.$adht->getNomUrl(1)."</td></tr>\n";
print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td class="valeur">'.$adht->getNomUrl(1)."</td></tr>\n";
// Morphy
print '<tr><td>'.$langs->trans("Nature").'</td><td class="valeur" >'.$object->getmorphylib().'</td>';
@ -1463,7 +1463,7 @@ else
print '<table class="border tableforfield" width="100%">';
// Birthday
print '<tr><td>'.$langs->trans("Birthday").'</td><td class="valeur">'.dol_print_date($object->birth,'day').'</td></tr>';
print '<tr><td class="titlefield">'.$langs->trans("Birthday").'</td><td class="valeur">'.dol_print_date($object->birth,'day').'</td></tr>';
// Public
print '<tr><td>'.$langs->trans("Public").'</td><td class="valeur">'.yn($object->public).'</td></tr>';

View File

@ -591,11 +591,11 @@ if ($rowid > 0)
// Login
if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
{
print '<tr><td>'.$langs->trans("Login").' / '.$langs->trans("Id").'</td><td class="valeur">'.$object->login.'&nbsp;</td></tr>';
print '<tr><td class="titlefield">'.$langs->trans("Login").' / '.$langs->trans("Id").'</td><td class="valeur">'.$object->login.'&nbsp;</td></tr>';
}
// Type
print '<tr><td>'.$langs->trans("Type").'</td><td class="valeur">'.$adht->getNomUrl(1)."</td></tr>\n";
print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td class="valeur">'.$adht->getNomUrl(1)."</td></tr>\n";
// Morphy
print '<tr><td>'.$langs->trans("Nature").'</td><td class="valeur" >'.$object->getmorphylib().'</td>';
@ -630,7 +630,7 @@ if ($rowid > 0)
print '<table class="border tableforfield" width="100%">';
// Birthday
print '<tr><td>'.$langs->trans("Birthday").'</td><td class="valeur">'.dol_print_date($object->birth,'day').'</td></tr>';
print '<tr><td class="titlefield">'.$langs->trans("Birthday").'</td><td class="valeur">'.dol_print_date($object->birth,'day').'</td></tr>';
// Public
print '<tr><td>'.$langs->trans("Public").'</td><td class="valeur">'.yn($object->public).'</td></tr>';

View File

@ -54,7 +54,7 @@ $langs->load("companies");
$memberstatic=new Adherent($db);
llxHeader('',$langs->trans("MembersStatisticsByProperties"),'','',0,0,array('http://www.google.com/jsapi'));
llxHeader('',$langs->trans("MembersStatisticsByProperties"),'','',0,0,array('https://www.google.com/jsapi'));
$title=$langs->trans("MembersStatisticsByProperties");

View File

@ -53,7 +53,7 @@ $langs->load("companies");
* View
*/
$arrayjs=array('http://www.google.com/jsapi');
$arrayjs=array('https://www.google.com/jsapi');
if (! empty($conf->dol_use_jmobile)) $arrayjs=array();
$title=$langs->trans("Statistics");

View File

@ -1,8 +1,9 @@
<?php
/* Copyright (C) 2008-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2011-2013 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
/* Copyright (C) 2008-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2011-2013 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
* Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -36,7 +37,11 @@ $langs->load("admin");
$langs->load("other");
$action = GETPOST('action','alpha');
$value = GETPOST('value','alpha');
$param = GETPOST('param','alpha');
$cancel = GETPOST('cancel','alpha');
$scandir = GETPOST('scandir','alpha');
$type = 'action';
/*
@ -71,7 +76,21 @@ if (preg_match('/del_(.*)/',$action,$reg))
dol_print_error($db);
}
}
// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
if ($action == 'setModuleOptions')
{
if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
if (! $res > 0) $error++;
if (! $error)
{
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
}
else
{
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
if ($action == 'set')
{
dolibarr_set_const($db, 'AGENDA_USE_EVENT_TYPE_DEFAULT', GETPOST('AGENDA_USE_EVENT_TYPE_DEFAULT'), 'chaine', 0, '', $conf->entity);
@ -79,6 +98,85 @@ if ($action == 'set')
dolibarr_set_const($db, 'AGENDA_DEFAULT_FILTER_STATUS', GETPOST('AGENDA_DEFAULT_FILTER_STATUS'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'AGENDA_DEFAULT_VIEW', GETPOST('AGENDA_DEFAULT_VIEW'), 'chaine', 0, '', $conf->entity);
}
else if ($action == 'specimen') // For orders
{
$modele=GETPOST('module','alpha');
$commande = new CommandeFournisseur($db);
$commande->initAsSpecimen();
$commande->thirdparty=$specimenthirdparty;
// Search template files
$file=''; $classname=''; $filefound=0;
$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
foreach($dirmodels as $reldir)
{
$file=dol_buildpath($reldir."core/modules/action/doc/pdf_".$modele.".modules.php",0);
if (file_exists($file))
{
$filefound=1;
$classname = "pdf_".$modele;
break;
}
}
if ($filefound)
{
require_once $file;
$module = new $classname($db,$commande);
if ($module->write_file($commande,$langs) > 0)
{
header("Location: ".DOL_URL_ROOT."/document.php?modulepart=action&file=SPECIMEN.pdf");
return;
}
else
{
setEventMessages($module->error, $module->errors, 'errors');
dol_syslog($module->error, LOG_ERR);
}
}
else
{
setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
}
}
// Activate a model
else if ($action == 'setmodel')
{
print "sssd".$value;
$ret = addDocumentModel($value, $type, $label, $scandir);
}
else if ($action == 'del')
{
$ret = delDocumentModel($value, $type);
if ($ret > 0)
{
if ($conf->global->ACTION_EVENT_ADDON_PDF == "$value") dolibarr_del_const($db, 'ACTION_EVENT_ADDON_PDF',$conf->entity);
}
}
// Set default model
else if ($action == 'setdoc')
{
if (dolibarr_set_const($db, "ACTION_EVENT_ADDON_PDF",$value,'chaine',0,'',$conf->entity))
{
// La constante qui a ete lue en avant du nouveau set
// on passe donc par une variable pour avoir un affichage coherent
$conf->global->ACTION_EVENT_ADDON_PDF = $value;
}
// On active le modele
$ret = delDocumentModel($value, $type);
if ($ret > 0)
{
$ret = addDocumentModel($value, $type, $label, $scandir);
}
}
/**
@ -86,7 +184,7 @@ if ($action == 'set')
*/
$formactions=new FormActions($db);
$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
llxHeader();
$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
@ -95,14 +193,151 @@ print "<br>\n";
print '<form action="'.$_SERVER["PHP_SELF"].'" name="agenda">';
print '<input type="hidden" name="action" value="set">';
$head=agenda_prepare_head();
dol_fiche_head($head, 'other', $langs->trans("Agenda"), 0, 'action');
/*
* Documents models for supplier orders
*/
print load_fiche_titre($langs->trans("AgendaModelModule"),'','');
// Define array def of models
$def = array();
$sql = "SELECT nom";
$sql.= " FROM ".MAIN_DB_PREFIX."document_model";
$sql.= " WHERE type = 'action'";
$sql.= " AND entity = ".$conf->entity;
$resql=$db->query($sql);
if ($resql)
{
$i = 0;
$num_rows=$db->num_rows($resql);
while ($i < $num_rows)
{
$array = $db->fetch_array($resql);
array_push($def, $array[0]);
$i++;
}
}
else
{
dol_print_error($db);
}
print '<table class="noborder" width="100%">'."\n";
print '<tr class="liste_titre">'."\n";
print '<td width="100">'.$langs->trans("Name").'</td>'."\n";
print '<td>'.$langs->trans("Description").'</td>'."\n";
print '<td align="center" width="60">'.$langs->trans("Status").'</td>'."\n";
print '<td align="center" width="60">'.$langs->trans("Default").'</td>'."\n";
print '<td align="center" width="40">'.$langs->trans("ShortInfo").'</td>';
print '<td align="center" width="40">'.$langs->trans("Preview").'</td>';
print '</tr>'."\n";
clearstatcache();
$var=true;
foreach ($dirmodels as $reldir)
{
$dir = dol_buildpath($reldir."core/modules/action/doc/");
if (is_dir($dir))
{
$handle=opendir($dir);
if (is_resource($handle))
{
while (($file = readdir($handle))!==false)
{
if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file))
{
$name = substr($file, 4, dol_strlen($file) -16);
$classname = substr($file, 0, dol_strlen($file) -12);
require_once $dir.'/'.$file;
$module = new $classname($db, new ActionComm($db));
$var=!$var;
print "<tr ".$bc[$var].">\n";
print "<td>";
print (empty($module->name)?$name:$module->name);
print "</td>\n";
print "<td>\n";
require_once $dir.$file;
$module = new $classname($db,$specimenthirdparty);
if (method_exists($module,'info'))
print $module->info($langs);
else
print $module->description;
print "</td>\n";
// Active
if (in_array($name, $def))
{
print '<td align="center">'."\n";
if ($conf->global->ACTION_EVENT_ADDON_PDF != "$name")
{
print '<a href="'.$_SERVER["PHP_SELF"].'?action=del&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type=action">';
print img_picto($langs->trans("Enabled"),'switch_on');
print '</a>';
}
else
{
print img_picto($langs->trans("Enabled"),'switch_on');
}
print "</td>";
}
else
{
print '<td align="center">'."\n";
print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmodel&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type=action">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
print "</td>";
}
// Default
print '<td align="center">';
if ($conf->global->ACTION_EVENT_ADDON_PDF == "$name")
{
print img_picto($langs->trans("Default"),'on');
}
else
{
print '<a href="'.$_SERVER["PHP_SELF"].'?action=setdoc&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type=action"" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').'</a>';
}
print '</td>';
// Info
$htmltooltip = ''.$langs->trans("Name").': '.$module->name;
$htmltooltip.='<br>'.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown"));
$htmltooltip.='<br>'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur;
$htmltooltip.='<br><br><u>'.$langs->trans("FeaturesSupported").':</u>';
$htmltooltip.='<br>'.$langs->trans("Logo").': '.yn($module->option_logo,1,1);
print '<td align="center">';
print $form->textwithpicto('',$htmltooltip,1,0);
print '</td>';
print '<td align="center">';
print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimen&amp;module='.$name.'">'.img_object($langs->trans("Preview"),'order').'</a>';
print '</td>';
print "</tr>\n";
}
}
closedir($handle);
}
}
}
print '</table><br>';
$var=true;
print '<form action="'.$_SERVER["PHP_SELF"].'" name="agenda">';
print '<input type="hidden" name="action" value="set">';
print '<table class="noborder allwidth">'."\n";
print '<tr class="liste_titre">'."\n";

View File

@ -232,6 +232,20 @@ elseif ($action == 'set_FICHINTER_PRINT_PRODUCTS')
{
setEventMessages($langs->trans("Error"), null, 'errors');
}
} elseif ($action == 'set_FICHINTER_USE_SERVICE_DURATION') {
$val = GETPOST('FICHINTER_USE_SERVICE_DURATION', 'alpha');
$res = dolibarr_set_const($db, "FICHINTER_USE_SERVICE_DURATION", ($val == 'on' ? 1 : 0), 'bool', 0, '',
$conf->entity);
if (!$res > 0) {
$error++;
}
if (!$error) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
@ -568,7 +582,22 @@ print '/>';
print '</td><td align="right">';
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print "</td></tr>\n";
// Use services duration
$var = !$var;
print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">';
print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
print '<input type="hidden" name="action" value="set_FICHINTER_USE_SERVICE_DURATION">';
print '<tr ' . $bc[$var] . '>';
print '<td>';
print $langs->trans("UseServicesDurationOnFichinter");
print '</td>';
print '<td align="center">';
print '<input type="checkbox" name="FICHINTER_USE_SERVICE_DURATION"' . ($conf->global->FICHINTER_USE_SERVICE_DURATION?' checked':'') . '>';
print '</td>';
print '<td align="right">';
print '<input type="submit" class="button" value="' . $langs->trans("Modify") . '">';
print '</td>';
print '</tr>';
print '</form>';

View File

@ -237,7 +237,7 @@ else
{
print '<input size="25" type="text" name="pass" value="'.$conf->global->LDAP_ADMIN_PASS.'">';
}
print '</td><td>secret</td></tr>';
print '</td><td>'.$langs->trans('Password').' (ex: secret)</td></tr>';
print '</table>';

View File

@ -304,7 +304,7 @@ $h++;
print "<br>\n";
dol_fiche_head($head, $mode, $langs->trans("Modules"));
dol_fiche_head($head, $mode, '');
$var=true;
@ -443,11 +443,11 @@ if ($mode != 'marketplace')
if ($familykey!=$oldfamily)
{
print '<tr class="liste_titre">'."\n";
print '<td colspan="6">';
print '<td colspan="5">';
$familytext=empty($familyinfo[$familykey]['label'])?$familykey:$familyinfo[$familykey]['label'];
print $familytext;
print "</td>\n";
print '<td align="right">'.$langs->trans("SetupShort").'</td>'."\n";
print '<td colspan="2" align="right">'.$langs->trans("SetupShort").'</td>'."\n";
print "</tr>\n";
$atleastoneforfamily=0;
//print "<tr><td>yy".$oldfamily."-".$familykey."-".$atleastoneforfamily."<br></td><tr>";

View File

@ -200,13 +200,13 @@ if ($result)
{
print img_picto($langs->trans("Active"),'tick');
print '</td><td>';
print '<a href="perms.php?pid='.$obj->id.'&amp;action=remove#'.$objMod->getName().'">'.img_edit_remove().'</a>';
print '<a class="reposition" href="perms.php?pid='.$obj->id.'&amp;action=remove">'.img_edit_remove().'</a>';
}
else
{
print '&nbsp;';
print '</td><td>';
print '<a href="perms.php?pid='.$obj->id.'&amp;action=add#'.$objMod->getName().'">'.img_edit_add().'</a>';
print '<a class="reposition" href="perms.php?pid='.$obj->id.'&amp;action=add">'.img_edit_add().'</a>';
}
print '</td></tr>';

View File

@ -168,36 +168,39 @@ print load_fiche_titre($langs->trans("Upgrade"),'','title_setup');
print $langs->trans("CurrentVersion").' : <b>'.DOL_VERSION.'</b><br>';
$result = getURLContent('http://sourceforge.net/projects/dolibarr/rss');
//var_dump($result['content']);
$sfurl = simplexml_load_string($result['content']);
if ($sfurl)
if (function_exists('curl_init'))
{
$i=0;
$version='0.0';
while (! empty($sfurl->channel[0]->item[$i]->title) && $i < 10000)
$result = getURLContent('http://sourceforge.net/projects/dolibarr/rss');
//var_dump($result['content']);
$sfurl = simplexml_load_string($result['content']);
if ($sfurl)
{
$title=$sfurl->channel[0]->item[$i]->title;
if (preg_match('/([0-9]+\.([0-9\.]+))/', $title, $reg))
$i=0;
$version='0.0';
while (! empty($sfurl->channel[0]->item[$i]->title) && $i < 10000)
{
$newversion=$reg[1];
$newversionarray=explode('.',$newversion);
$versionarray=explode('.',$version);
//var_dump($newversionarray);var_dump($versionarray);
if (versioncompare($newversionarray, $versionarray) > 0) $version=$newversion;
$title=$sfurl->channel[0]->item[$i]->title;
if (preg_match('/([0-9]+\.([0-9\.]+))/', $title, $reg))
{
$newversion=$reg[1];
$newversionarray=explode('.',$newversion);
$versionarray=explode('.',$version);
//var_dump($newversionarray);var_dump($versionarray);
if (versioncompare($newversionarray, $versionarray) > 0) $version=$newversion;
}
$i++;
}
$i++;
// Show version
print $langs->trans("LastStableVersion").' : <b>'. (($version != '0.0')?$version:$langs->trans("Unknown")) .'</b><br>';
}
else
{
print $langs->trans("LastStableVersion").' : <b>' .$langs->trans("UpdateServerOffline").'</b><br>';
}
// Show version
print $langs->trans("LastStableVersion").' : <b>'. (($version != '0.0')?$version:$langs->trans("Unknown")) .'</b><br>';
}
else
{
print $langs->trans("LastStableVersion").' : <b>' .$langs->trans("UpdateServerOffline").'</b><br>';
}
print '<br>';
print '<br>';
// Upgrade
print $langs->trans("Upgrade").'<br>';

View File

@ -28,6 +28,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php';
require_once DOL_DOCUMENT_ROOT.'/api/class/api_access.class.php';
$langs->load("admin");
/*
* View
@ -36,7 +38,6 @@ require_once DOL_DOCUMENT_ROOT.'/api/class/api_access.class.php';
// Enable and test if module Api is enabled
if (empty($conf->global->MAIN_MODULE_API))
{
$langs->load("admin");
dol_syslog("Call Dolibarr API interfaces with module REST disabled");
print $langs->trans("WarningModuleNotActive",'Api').'.<br><br>';
print $langs->trans("ToActivateModule");
@ -103,17 +104,43 @@ foreach ($modulesdir as $dir)
{
while (($file_searched = readdir($handle_part))!==false)
{
// Support of the deprecated API.
if (is_readable($dir_part.$file_searched) && preg_match("/^api_deprecated_(.*)\.class\.php$/i",$file_searched,$reg))
{
$classname = ucwords($reg[1]).'Api';
require_once $dir_part.$file_searched;
if (class_exists($classname))
{
dol_syslog("Found deprecated API classname=".$classname);
$api->r->addAPIClass($classname, '');
}
}
elseif (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i",$file_searched,$reg))
{
$classname = ucwords($reg[1]);
require_once $dir_part.$file_searched;
if (class_exists($classname))
{
dol_syslog("Found API classname=".$classname);
$listofapis[] = $classname;
}
}
/*
if (is_readable($dir_part.$file_searched) && preg_match("/^(api_.*)\.class\.php$/i",$file_searched,$reg))
{
$classname=$reg[1];
$classname = str_replace('Api_','',ucwords($reg[1])).'Api';
//$classname = str_replace('Api_','',ucwords($reg[1]));
$classname = ucfirst($classname);
require_once $dir_part.$file_searched;
if (class_exists($classname))
{
dol_syslog("Found API classname=".$classname);
$api->r->addAPIClass($classname,'');
/*
require_once DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/Routes.php';
$tmpclass = new ReflectionClass($classname);
@ -124,8 +151,9 @@ foreach ($modulesdir as $dir)
}*/
//$listofapis[]=array('classname'=>$classname, 'fullpath'=>$file_searched);
}
}
/* }
}*/
}
}
}
@ -134,8 +162,8 @@ foreach ($modulesdir as $dir)
}
}
$listofapis=Routes::toArray();
//var_dump($listofapis);
$listofapis=Routes::toArray(); // TODO api for "status" is lost here
//var_dump($listofapis);
@ -165,6 +193,7 @@ print $langs->trans("ListOfAvailableAPIs").':<br>';
foreach($listofapis['v1'] as $key => $val)
{
if ($key == 'login') continue;
if ($key == 'index') continue;
if ($key)
{

View File

@ -95,9 +95,23 @@ print '</tr>';
print '</table>';
print '<br><br>';
// Define $urlwithroot
$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
// Show message
$message='';
$url='<a href="'.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword" target="_blank">'.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword[&reset=1]</a>';
$message.=$langs->trans("UrlToGetKeyToUseAPIs").':<br>';
$message.=img_picto('','object_globe.png').' '.$url;
print $message;
print '<br>';
print '<br>';
// Explorer
print '<u>'.$langs->trans("ApiExporerIs").':</u><br>';
$url=DOL_MAIN_URL_ROOT.'/api/admin/explorer.php';
$url=DOL_MAIN_URL_ROOT.'/api/index.php/explorer';
print img_picto('','object_globe.png').' <a href="'.$url.'" target="_blank">'.$url."</a><br>\n";

View File

@ -88,6 +88,17 @@ class DolibarrApi
// Remove $db object property for object
unset($object->db);
// Remove the $oldcopy property because it is not supported by the JSON
// encoder. The following error is generated when trying to serialize
// it: "Error encoding/decoding JSON: Type is not supported"
// Note: Event if this property was correctly handled by the JSON
// encoder, it should be ignored because keeping it would let the API
// have a very strange behavior: calling PUT and then GET on the same
// resource would give different results:
// PUT /objects/{id} -> returns object with oldcopy = previous version of the object
// GET /objects/{id} -> returns object with oldcopy empty
unset($object->oldcopy);
// If object has lines, remove $db property
if(isset($object->lines) && count($object->lines) > 0) {
$nboflines = count($object->lines);

View File

@ -18,14 +18,11 @@
use Luracast\Restler\RestException;
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php';
/**
* API generic (login, status, ...)
*
* API that allows to log in with an user account.
*/
class GenericApi extends DolibarrApi
class Login
{
function __construct() {
@ -46,7 +43,7 @@ class GenericApi extends DolibarrApi
*
* @throws RestException
*/
public function login($login, $password, $entity=0, $reset=0) {
public function index($login, $password, $entity=0, $reset=0) {
global $conf, $dolibarr_main_authentication, $dolibarr_auto_user;
@ -103,20 +100,4 @@ class GenericApi extends DolibarrApi
)
);
}
/**
* Get status (Dolibarr version)
*
* @access protected
* @class DolibarrApiAccess {@requires admin}
*/
function status() {
require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php';
return array(
'success' => array(
'code' => 200,
'dolibarr_version' => DOL_VERSION
)
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php';
/**
* API that gives the status of the Dolibarr instance.
*
* @access protected
* @class DolibarrApiAccess {@requires user,external}
*/
class Status
{
/**
* Get status (Dolibarr version)
*/
function index() {
return array(
'success' => array(
'code' => 200,
'dolibarr_version' => DOL_VERSION
)
);
}
}

View File

@ -58,7 +58,10 @@ if (empty($conf->global->MAIN_MODULE_API))
$api = new DolibarrApi($db);
$api->r->addAPIClass('Luracast\\Restler\\Resources'); //this creates resources.json at API Root
// Enable the Restler API Explorer.
// See https://github.com/Luracast/Restler-API-Explorer for more info.
$api->r->addAPIClass('Luracast\\Restler\\Explorer');
$api->r->setSupportedFormats('JsonFormat', 'XmlFormat');
$api->r->addAuthenticationClass('DolibarrApiAccess','');
@ -77,25 +80,19 @@ foreach ($modulesdir as $dir)
{
while (($file = readdir($handle))!==false)
{
if (is_readable($dir.$file) && preg_match("/^(mod.*)\.class\.php$/i",$file,$reg))
if (is_readable($dir.$file) && preg_match("/^mod(.*)\.class\.php$/i",$file,$reg))
{
$modulename=$reg[1];
$module = $part = strtolower($reg[1]);
// Defined if module is enabled
$enabled=true;
$module=$part=$obj=strtolower(preg_replace('/^mod/i','',$modulename));
//if ($part == 'propale') $part='propal';
if ($module == 'societe') {
$obj = 'thirdparty';
}
if ($module == 'categorie') {
$part = 'categories';
$obj = 'category';
}
if ($module == 'facture') {
$part = 'compta/facture';
$obj = 'facture';
}
// Defined if module is enabled
$enabled=true;
if (empty($conf->$module->enabled)) $enabled=false;
if ($enabled)
@ -115,17 +112,25 @@ foreach ($modulesdir as $dir)
{
while (($file_searched = readdir($handle_part))!==false)
{
if (is_readable($dir_part.$file_searched) && preg_match("/^(api_.*)\.class\.php$/i",$file_searched,$reg))
// Support of the deprecated API.
if (is_readable($dir_part.$file_searched) && preg_match("/^api_deprecated_(.*)\.class\.php$/i",$file_searched,$reg))
{
$classname=$reg[1];
$classname = str_replace('Api_','',ucwords($reg[1])).'Api';
$classname = ucfirst($classname);
$classname = ucwords($reg[1]).'Api';
require_once $dir_part.$file_searched;
if (class_exists($classname))
if (class_exists($classname))
{
dol_syslog("Found API classname=".$classname);
$api->r->addAPIClass($classname,'');
$listofapis[]=array('classname'=>$classname, 'fullpath'=>$file_searched);
dol_syslog("Found deprecated API classname=".$classname);
$api->r->addAPIClass($classname, '');
}
}
elseif (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i",$file_searched,$reg))
{
$classname = ucwords($reg[1]);
require_once $dir_part.$file_searched;
if (class_exists($classname))
{
dol_syslog("Found API classname=".$classname);
$listofapis[] = $classname;
}
}
}
@ -136,6 +141,14 @@ foreach ($modulesdir as $dir)
}
}
// Sort the classes before adding them to Restler. The Restler API Explorer
// shows the classes in the order they are added and it's a mess if they are
// not sorted.
sort($listofapis);
foreach ($listofapis as $classname)
{
$api->r->addAPIClass($classname);
}
// TODO If not found, redirect to explorer

View File

@ -0,0 +1,355 @@
<?php
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use Luracast\Restler\RestException;
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php';
/**
* API class for categories
*
* @access protected
* @class DolibarrApiAccess {@requires user,external}
*/
class Categories extends DolibarrApi
{
/**
* @var array $FIELDS Mandatory fields, checked when create and update object
*/
static $FIELDS = array(
'label',
'type'
);
static $TYPES = array(
0 => 'product',
1 => 'supplier',
2 => 'customer',
3 => 'member',
4 => 'contact',
5 => 'account',
);
/**
* @var Categorie $category {@type Categorie}
*/
public $category;
/**
* Constructor
*/
function __construct()
{
global $db, $conf;
$this->db = $db;
$this->category = new Categorie($this->db);
}
/**
* Get properties of a category object
*
* Return an array with category informations
*
* @param int $id ID of category
* @return array|mixed data without useless information
*
* @throws RestException
*/
function get($id)
{
if(! DolibarrApiAccess::$user->rights->categorie->lire) {
throw new RestException(401);
}
$result = $this->category->fetch($id);
if( ! $result ) {
throw new RestException(404, 'category not found');
}
if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
return $this->_cleanObjectDatas($this->category);
}
/**
* List categories
*
* Get a list of categories
*
* @param string $type Type of category ('member', 'customer', 'supplier', 'product', 'contact')
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @return array Array of category objects
*
* @throws RestException
*/
function index($type = '', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) {
global $db, $conf;
$obj_ret = array();
if(! DolibarrApiAccess::$user->rights->categorie->lire) {
throw new RestException(401);
}
$sql = "SELECT s.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."categorie as s";
$sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')';
if (!empty($type))
{
$sql.= ' AND s.type='.array_search($type,Categories::$TYPES);
}
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
}
$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)
{
$i=0;
$num = $db->num_rows($result);
while ($i < $num)
{
$obj = $db->fetch_object($result);
$category_static = new Categorie($db);
if($category_static->fetch($obj->rowid)) {
$obj_ret[] = parent::_cleanObjectDatas($category_static);
}
$i++;
}
}
else {
throw new RestException(503, 'Error when retrieve category list : '.$category_static->error);
}
if( ! count($obj_ret)) {
throw new RestException(404, 'No category found');
}
return $obj_ret;
}
/**
* List categories of an entity
*
* Note: This method is not directly exposed in the API, it is used
* in the GET /xxx/{id}/categories requests.
*
* @param string $type Type of category ('member', 'customer', 'supplier', 'product', 'contact')
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @param int $item Id of the item to get categories for
* @return array Array of category objects
*
* @access private
*/
function getListForItem($type, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $item = 0) {
global $db, $conf;
$obj_ret = array();
if(! DolibarrApiAccess::$user->rights->categorie->lire) {
throw new RestException(401);
}
//if ($type == "") {
//$type="product";
//}
$sub_type = $type;
$subcol_name = "fk_".$type;
if ($type=="customer" || $type=="supplier") {
$sub_type="societe";
$subcol_name="fk_soc";
}
if ($type=="contact") {
$subcol_name="fk_socpeople";
}
$sql = "SELECT s.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."categorie as s";
$sql.= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub ";
$sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')';
$sql.= ' AND s.type='.array_search($type,Categories::$TYPES);
$sql.= ' AND s.rowid = sub.fk_categorie';
$sql.= ' AND sub.'.$subcol_name.' = '.$item;
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
}
$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)
{
$i=0;
$num = $db->num_rows($result);
while ($i < $num)
{
$obj = $db->fetch_object($result);
$category_static = new Categorie($db);
if($category_static->fetch($obj->rowid)) {
$obj_ret[] = parent::_cleanObjectDatas($category_static);
}
$i++;
}
}
else {
throw new RestException(503, 'Error when retrieve category list : '.$category_static->error);
}
if( ! count($obj_ret)) {
throw new RestException(404, 'No category found');
}
return $obj_ret;
}
/**
* Create category object
*
* @param array $request_data Request data
* @return int ID of category
*/
function post($request_data = NULL)
{
if(! DolibarrApiAccess::$user->rights->categorie->creer) {
throw new RestException(401);
}
// Check mandatory fields
$result = $this->_validate($request_data);
foreach($request_data as $field => $value) {
$this->category->$field = $value;
}
if($this->category->create(DolibarrApiAccess::$user) < 0) {
throw new RestException(503, 'Error when create category : '.$this->category->error);
}
return $this->category->id;
}
/**
* Update category
*
* @param int $id Id of category to update
* @param array $request_data Datas
* @return int
*/
function put($id, $request_data = NULL)
{
if(! DolibarrApiAccess::$user->rights->categorie->creer) {
throw new RestException(401);
}
$result = $this->category->fetch($id);
if( ! $result ) {
throw new RestException(404, 'category not found');
}
if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
foreach($request_data as $field => $value) {
$this->category->$field = $value;
}
if($this->category->update(DolibarrApiAccess::$user))
return $this->get ($id);
return false;
}
/**
* Delete category
*
* @param int $id Category ID
* @return array
*/
function delete($id)
{
if(! DolibarrApiAccess::$user->rights->categorie->supprimer) {
throw new RestException(401);
}
$result = $this->category->fetch($id);
if( ! $result ) {
throw new RestException(404, 'category not found');
}
if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if (! $this->category->delete(DolibarrApiAccess::$user)) {
throw new RestException(401,'error when delete category');
}
return array(
'success' => array(
'code' => 200,
'message' => 'Category deleted'
)
);
}
/**
* Validate fields before create or update object
*
* @param array $data Data to validate
* @return array
*
* @throws RestException
*/
function _validate($data)
{
$category = array();
foreach (Categories::$FIELDS as $field) {
if (!isset($data[$field]))
throw new RestException(400, "$field field missing");
$category[$field] = $data[$field];
}
return $category;
}
}

View File

@ -27,7 +27,7 @@
* @access protected
* @class DolibarrApiAccess {@requires user,external}
*
*
* @deprecated Use Categories instead (defined in api_categories.class.php)
*/
class CategoryApi extends DolibarrApi
{
@ -54,7 +54,7 @@ class CategoryApi extends DolibarrApi
public $category;
/**
* Constructor
* Constructor <b>Warning: Deprecated</b>
*
* @url GET category/
*
@ -68,7 +68,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Get properties of a category object
* Get properties of a category object <b>Warning: Deprecated</b>
*
* Return an array with category informations
*
@ -97,7 +97,7 @@ class CategoryApi extends DolibarrApi
}
/**
* List categories
* List categories <b>Warning: Deprecated</b>
*
* Get a list of categories
*
@ -166,7 +166,7 @@ class CategoryApi extends DolibarrApi
return $obj_ret;
}
/**
* List categories of an entity
* List categories of an entity <b>Warning: Deprecated</b>
*
* Get a list of categories
*
@ -248,7 +248,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Get member categories list
* Get member categories list <b>Warning: Deprecated</b>
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
@ -263,7 +263,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Get customer categories list
* Get customer categories list <b>Warning: Deprecated</b>
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
@ -278,7 +278,7 @@ class CategoryApi extends DolibarrApi
return $this->getList('customer', $sortfield, $sortorder, $limit, $page);
}
/**
* Get categories for a customer
* Get categories for a customer <b>Warning: Deprecated</b>
*
* @param int $cusid Customer id filter
* @param string $sortfield Sort field
@ -295,7 +295,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Add category to customer
* Add category to customer <b>Warning: Deprecated</b>
*
* @param int $cusid Id of customer
* @param int $catid Id of category
@ -329,7 +329,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Get supplier categories list
* Get supplier categories list <b>Warning: Deprecated</b>
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
@ -345,7 +345,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Get product categories list
* Get product categories list <b>Warning: Deprecated</b>
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
@ -361,7 +361,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Get contact categories list
* Get contact categories list <b>Warning: Deprecated</b>
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
@ -376,7 +376,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Create category object
* Create category object <b>Warning: Deprecated</b>
*
* @param array $request_data Request data
* @return int ID of category
@ -401,7 +401,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Update category
* Update category <b>Warning: Deprecated</b>
*
* @param int $id Id of category to update
* @param array $request_data Datas
@ -435,7 +435,7 @@ class CategoryApi extends DolibarrApi
}
/**
* Delete category
* Delete category <b>Warning: Deprecated</b>
*
* @param int $id Category ID
* @return array

View File

@ -996,7 +996,7 @@ class ActionComm extends CommonObject
}
$this->date_creation = $this->db->jdate($obj->datec);
$this->date_modification = $this->db->jdate($obj->datem);
if (! empty($obj->fk_user_mod)) $this->date_modification = $this->db->jdate($obj->datem);
}
$this->db->free($result);
}

View File

@ -1472,7 +1472,7 @@ if ($action == 'create' && $user->rights->commande->creer)
print '</td>';
} else {
print '<td colspan="2">';
print $form->select_company('', 'socid', 's.client = 1 OR s.client = 3', 1);
print $form->select_company('', 'socid', 's.client = 1 OR s.client = 3', 'SelectThirdParty');
// reload page to retrieve customer informations
if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
{

View File

@ -29,7 +29,7 @@
* @category Api
* @package Api
*
*
* @deprecated Use Orders instead (defined in api_orders.class.php)
*/
class CommandeApi extends DolibarrApi
{
@ -47,7 +47,7 @@ class CommandeApi extends DolibarrApi
public $commande;
/**
* Constructor
* Constructor <b>Warning: Deprecated</b>
*
* @url GET order/
*
@ -60,7 +60,7 @@ class CommandeApi extends DolibarrApi
}
/**
* Get properties of a commande object
* Get properties of a commande object <b>Warning: Deprecated</b>
*
* Return an array with commande informations
*
@ -93,7 +93,7 @@ class CommandeApi extends DolibarrApi
}
/**
* List orders
* List orders <b>Warning: Deprecated</b>
*
* Get a list of orders
*
@ -181,7 +181,7 @@ class CommandeApi extends DolibarrApi
}
/**
* List orders for specific thirdparty
* List orders for specific thirdparty <b>Warning: Deprecated</b>
*
* Get a list of orders
*
@ -197,7 +197,7 @@ class CommandeApi extends DolibarrApi
/**
* Create order object
* Create order object <b>Warning: Deprecated</b>
*
* @param array $request_data Request datas
*
@ -230,7 +230,7 @@ class CommandeApi extends DolibarrApi
return $this->commande->id;
}
/**
* Get lines of an order
* Get lines of an order <b>Warning: Deprecated</b>
*
*
* @param int $id Id of order
@ -260,7 +260,7 @@ class CommandeApi extends DolibarrApi
return $result;
}
/**
* Add a line to given order
* Add a line to given order <b>Warning: Deprecated</b>
*
*
* @param int $id Id of commande to update
@ -319,7 +319,7 @@ class CommandeApi extends DolibarrApi
return false;
}
/**
* Update a line to given order
* Update a line to given order <b>Warning: Deprecated</b>
*
*
* @param int $id Id of commande to update
@ -376,7 +376,7 @@ class CommandeApi extends DolibarrApi
return false;
}
/**
* Delete a line to given order
* Delete a line to given order <b>Warning: Deprecated</b>
*
*
* @param int $id Id of commande to update
@ -408,7 +408,7 @@ class CommandeApi extends DolibarrApi
}
/**
* Update order general fields (won't touch lines of order)
* Update order general fields (won't touch lines of order) <b>Warning: Deprecated</b>
*
* @param int $id Id of commande to update
* @param array $request_data Datas
@ -441,7 +441,7 @@ class CommandeApi extends DolibarrApi
}
/**
* Delete order
* Delete order <b>Warning: Deprecated</b>
*
* @param int $id Order ID
*
@ -477,7 +477,7 @@ class CommandeApi extends DolibarrApi
}
/**
* Validate an order
* Validate an order <b>Warning: Deprecated</b>
*
* @param int $id Order ID
* @param int $idwarehouse Warehouse ID

View File

@ -0,0 +1,498 @@
<?php
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use Luracast\Restler\RestException;
require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
/**
* API class for orders
*
* @access protected
* @class DolibarrApiAccess {@requires user,external}
*/
class Orders extends DolibarrApi
{
/**
* @var array $FIELDS Mandatory fields, checked when create and update object
*/
static $FIELDS = array(
'socid'
);
/**
* @var Commande $commande {@type Commande}
*/
public $commande;
/**
* Constructor
*/
function __construct()
{
global $db, $conf;
$this->db = $db;
$this->commande = new Commande($this->db);
}
/**
* Get properties of a commande object
*
* Return an array with commande informations
*
* @param int $id ID of order
* @return array|mixed data without useless information
*
* @throws RestException
*/
function get($id)
{
if(! DolibarrApiAccess::$user->rights->commande->lire) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Order not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$this->commande->fetchObjectLinked();
return $this->_cleanObjectDatas($this->commande);
}
/**
* List orders
*
* Get a list of orders
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @param string $societe Societe filter field
*
* @return array Array of order objects
*/
function index($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $societe = 0) {
global $db, $conf;
$obj_ret = array();
// case of external user, $societe param is ignored and replaced by user's socid
$socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $societe;
// If the internal user must only see his customers, force searching by him
if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id;
$sql = "SELECT s.rowid";
if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
$sql.= " FROM ".MAIN_DB_PREFIX."commande as s";
if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
$sql.= ' WHERE s.entity IN ('.getEntity('commande', 1).')';
if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND s.fk_soc = sc.fk_soc";
if ($socid) $sql.= " AND s.fk_soc = ".$socid;
if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
// Insert sale filter
if ($search_sale > 0)
{
$sql .= " AND sc.fk_user = ".$search_sale;
}
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
}
$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);
while ($i < $num)
{
$obj = $db->fetch_object($result);
$commande_static = new Commande($db);
if($commande_static->fetch($obj->rowid)) {
$obj_ret[] = parent::_cleanObjectDatas($commande_static);
}
$i++;
}
}
else {
throw new RestException(503, 'Error when retrieve commande list');
}
if( ! count($obj_ret)) {
throw new RestException(404, 'No commande found');
}
return $obj_ret;
}
/**
* Create order object
*
* @param array $request_data Request data
* @return int ID of commande
*/
function post($request_data = NULL)
{
if(! DolibarrApiAccess::$user->rights->commande->creer) {
throw new RestException(401, "Insuffisant rights");
}
// Check mandatory fields
$result = $this->_validate($request_data);
foreach($request_data as $field => $value) {
$this->commande->$field = $value;
}
if (isset($request_data["lines"])) {
$lines = array();
foreach ($request_data["lines"] as $line) {
array_push($lines, (object) $line);
}
$this->commande->lines = $lines;
}
if(! $this->commande->create(DolibarrApiAccess::$user) ) {
throw new RestException(500, "Error while creating order");
}
return $this->commande->id;
}
/**
* Get lines of an order
*
* @param int $id Id of order
*
* @url GET {id}/lines
*
* @return int
*/
function getLines($id) {
if(! DolibarrApiAccess::$user->rights->commande->lire) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Commande not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$this->commande->getLinesArray();
$result = array();
foreach ($this->commande->lines as $line) {
array_push($result,$this->_cleanObjectDatas($line));
}
return $result;
}
/**
* Add a line to given order
*
* @param int $id Id of commande to update
* @param array $request_data Orderline data
*
* @url POST {id}/lines
*
* @return int
*/
function postLine($id, $request_data = NULL) {
if(! DolibarrApiAccess::$user->rights->commande->creer) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Commande not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$request_data = (object) $request_data;
$updateRes = $this->commande->addline(
$request_data->desc,
$request_data->subprice,
$request_data->qty,
$request_data->tva_tx,
$request_data->localtax1_tx,
$request_data->localtax2_tx,
$request_data->fk_product,
$request_data->remise_percent,
$request_data->info_bits,
$request_data->fk_remise_except,
'HT',
0,
$request_data->date_start,
$request_data->date_end,
$request_data->product_type,
$request_data->rang,
$request_data->special_code,
$fk_parent_line,
$request_data->fk_fournprice,
$request_data->pa_ht,
$request_data->label,
$request_data->array_options,
$request_data->fk_unit,
$this->element,
$request_data->id
);
if ($updateRes > 0) {
return $this->get($id)->line->rowid;
}
return false;
}
/**
* Update a line to given order
*
* @param int $id Id of commande to update
* @param int $lineid Id of line to update
* @param array $request_data Orderline data
*
* @url PUT {id}/lines/{lineid}
*
* @return object
*/
function putLine($id, $lineid, $request_data = NULL) {
if(! DolibarrApiAccess::$user->rights->commande->creer) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Commande not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$request_data = (object) $request_data;
$updateRes = $this->commande->updateline(
$lineid,
$request_data->desc,
$request_data->subprice,
$request_data->qty,
$request_data->remise_percent,
$request_data->tva_tx,
$request_data->localtax1_tx,
$request_data->localtax2_tx,
'HT',
$request_data->info_bits,
$request_data->date_start,
$request_data->date_end,
$request_data->product_type,
$request_data->fk_parent_line,
0,
$request_data->fk_fournprice,
$request_data->pa_ht,
$request_data->label,
$request_data->special_code,
$request_data->array_options,
$request_data->fk_unit
);
if ($updateRes > 0) {
$result = $this->get($id);
unset($result->line);
return $this->_cleanObjectDatas($result);
}
return false;
}
/**
* Delete a line to given order
*
*
* @param int $id Id of commande to update
* @param int $lineid Id of line to delete
*
* @url DELETE {id}/lines/{lineid}
*
* @return int
*/
function delLine($id, $lineid) {
if(! DolibarrApiAccess::$user->rights->commande->creer) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Commande not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$request_data = (object) $request_data;
$updateRes = $this->commande->deleteline($lineid);
if ($updateRes == 1) {
return $this->get($id);
}
return false;
}
/**
* Update order general fields (won't touch lines of order)
*
* @param int $id Id of commande to update
* @param array $request_data Datas
*
* @return int
*/
function put($id, $request_data = NULL) {
if(! DolibarrApiAccess::$user->rights->commande->creer) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Commande not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
foreach($request_data as $field => $value) {
$this->commande->$field = $value;
}
if($this->commande->update($id, DolibarrApiAccess::$user,1,'','','update'))
return $this->get($id);
return false;
}
/**
* Delete order
*
* @param int $id Order ID
*
* @return array
*/
function delete($id)
{
if(! DolibarrApiAccess::$user->rights->commande->supprimer) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Order not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if( ! $this->commande->delete(DolibarrApiAccess::$user)) {
throw new RestException(500, 'Error when delete order : '.$this->commande->error);
}
return array(
'success' => array(
'code' => 200,
'message' => 'Order deleted'
)
);
}
/**
* Validate an order
*
* @param int $id Order ID
* @param int $idwarehouse Warehouse ID
*
* @url POST {id}/validate
*
* @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
* }
*/
function validate($id, $idwarehouse=0)
{
if(! DolibarrApiAccess::$user->rights->commande->creer) {
throw new RestException(401);
}
$result = $this->commande->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Order not found');
}
if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if( ! $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse)) {
throw new RestException(500, 'Error when validate order');
}
return array(
'success' => array(
'code' => 200,
'message' => 'Order validated'
)
);
}
/**
* Validate fields before create or update object
*
* @param array $data Array with data to verify
* @return array
* @throws RestException
*/
function _validate($data)
{
$commande = array();
foreach (Orders::$FIELDS as $field) {
if (!isset($data[$field]))
throw new RestException(400, "$field field missing");
$commande[$field] = $data[$field];
}
return $commande;
}
}

View File

@ -50,6 +50,10 @@ $langs->load('bills');
$action=GETPOST('action','alpha');
$massaction=GETPOST('massaction','alpha');
$show_files=GETPOST('show_files','int');
$confirm=GETPOST('confirm','alpha');
$toselect = GETPOST('toselect', 'array');
$orderyear=GETPOST("orderyear","int");
$ordermonth=GETPOST("ordermonth","int");
$orderday=GETPOST("orderday","int");
@ -72,7 +76,6 @@ $search_sale=GETPOST('search_sale','int');
$search_total_ht=GETPOST('search_total_ht','alpha');
$optioncss = GETPOST('optioncss','alpha');
$billed = GETPOST('billed','int');
$toselect = GETPOST('toselect', 'array');
// Security check
$id = (GETPOST('orderid')?GETPOST('orderid','int'):GETPOST('id','int'));
@ -151,7 +154,7 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab
*/
if (GETPOST('cancel')) { $action='list'; $massaction=''; }
if (! GETPOST('confirmmassaction')) { $massaction=''; }
if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; }
$parameters=array('socid'=>$socid);
$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
@ -192,161 +195,11 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
if (empty($reshook))
{
// Mass actions. Controls on number of lines checked
$maxformassaction=1000;
if (! empty($massaction) && count($toselect) < 1)
{
$error++;
setEventMessages($langs->trans("NoLineChecked"), null, "warnings");
}
if (! $error && count($toselect) > $maxformassaction)
{
setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
$error++;
}
// TODO Use a common inc.php file
if (! $error && $massaction == 'delete' && $user->rights->commande->supprimer)
{
$db->begin();
$objecttmp=new Commande($db);
$nbok = 0;
foreach($toselect as $toselectid)
{
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$result = $objecttmp->delete($user);
if ($result <= 0)
{
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
}
else $nbok++;
}
else
{
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
}
}
if (! $error)
{
if ($nbok > 1) setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
else setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
$db->commit();
}
else
{
$db->rollback();
}
//var_dump($listofobjectthirdparties);exit;
}
if (! $error && $massaction == "builddoc" && $user->rights->commande->lire && ! GETPOST('button_search'))
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$objecttmp=new Commande($db);
$listofobjectid=array();
$listofobjectthirdparties=array();
$listofobjectref=array();
foreach($toselect as $toselectid)
{
$objecttmp=new Commande($db); // must create new instance because instance is saved into $listofobjectref array for future use
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$listoinvoicesid[$toselectid]=$toselectid;
$thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
$listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
$listofobjectref[$toselectid]=$objecttmp->ref;
}
}
$arrayofinclusion=array();
foreach($listofobjectref as $tmppdf) $arrayofinclusion[]=preg_quote($tmppdf.'.pdf','/');
$listoffiles = dol_dir_list($conf->commande->dir_output,'all',1,implode('|',$arrayofinclusion),'\.meta$|\.png','date',SORT_DESC,0,true);
// build list of files with full path
$files = array();
foreach($listofobjectref as $basename)
{
foreach($listoffiles as $filefound)
{
if (strstr($filefound["name"],$basename))
{
$files[] = $conf->commande->dir_output.'/'.$basename.'/'.$filefound["name"];
break;
}
}
}
// Define output language (Here it is not used because we do only merging existing PDF)
$outputlangs = $langs;
$newlang='';
if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang=GETPOST('lang_id');
if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->thirdparty->default_lang;
if (! empty($newlang))
{
$outputlangs = new Translate("",$conf);
$outputlangs->setDefaultLang($newlang);
}
// Create empty PDF
$pdf=pdf_getInstance();
if (class_exists('TCPDF'))
{
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
}
$pdf->SetFont(pdf_getPDFFont($outputlangs));
if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
// Add all others
foreach($files as $file)
{
// Charge un document PDF depuis un fichier.
$pagecount = $pdf->setSourceFile($file);
for ($i = 1; $i <= $pagecount; $i++)
{
$tplidx = $pdf->importPage($i);
$s = $pdf->getTemplatesize($tplidx);
$pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
$pdf->useTemplate($tplidx);
}
}
// Create output dir if not exists
dol_mkdir($diroutputmassaction);
// Save merged file
$filename=strtolower(dol_sanitizeFileName($langs->transnoentities("Orders")));
if ($year) $filename.='_'.$year;
if ($month) $filename.='_'.$month;
if ($pagecount)
{
$now=dol_now();
$file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
$pdf->Output($file,'F');
if (! empty($conf->global->MAIN_UMASK))
@chmod($file, octdec($conf->global->MAIN_UMASK));
$langs->load("exports");
setEventMessages($langs->trans('FileSuccessfullyBuilt',$filename.'_'.dol_print_date($now,'dayhourlog')), null, 'mesgs');
}
else
{
setEventMessages($langs->trans('NoPDFAvailableForDocGenAmongChecked'), null, 'errors');
}
}
$objectclass='Commande';
$permtoread = $user->rights->commande->lire;
$permtodelete = $user->rights->commande->supprimer;
$uploaddir = $conf->commande->dir_output;
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
}
@ -547,7 +400,8 @@ if ($resql)
if ($search_total_ht != '') $param.='&search_total_ht='.$search_total_ht;
if ($search_total_vat != '') $param.='&search_total_vat='.$search_total_vat;
if ($search_total_ttc != '') $param.='&search_total_ttc='.$search_total_ttc;
if ($optioncss != '') $param.='&optioncss='.$optioncss;
if ($show_files) $param.='&show_files=' .$show_files;
if ($optioncss != '') $param.='&optioncss='.$optioncss;
// Add $param from extra fields
foreach ($search_array_options as $key => $val)
{
@ -557,8 +411,8 @@ if ($resql)
}
$arrayofmassactions = array(
//'presend'=>$langs->trans("SendByMail"),
//'builddoc'=>$langs->trans("PDFMerge"),
'presend'=>$langs->trans("SendByMail"),
'builddoc'=>$langs->trans("PDFMerge"),
);
if ($user->rights->commande->supprimer) $arrayofmassactions['delete']=$langs->trans("Delete");
if ($massaction == 'presend') $arrayofmassactions=array();
@ -576,6 +430,102 @@ if ($resql)
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_commercial.png', 0, '', '', $limit);
if ($massaction == 'presend')
{
$langs->load("mails");
if (! GETPOST('cancel'))
{
$objecttmp=new Commande($db);
$listofselectedid=array();
$listofselectedthirdparties=array();
$listofselectedref=array();
foreach($arrayofselected as $toselectid)
{
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$listofselectedid[$toselectid]=$toselectid;
$thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
$listofselectedthirdparties[$thirdpartyid]=$thirdpartyid;
$listofselectedref[$thirdpartyid][$toselectid]=$objecttmp->ref;
}
}
}
print '<input type="hidden" name="massaction" value="confirm_presend">';
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db);
dol_fiche_head(null, '', '');
$topicmail="SendOrderRef";
$modelmail="order_send";
// Cree l'objet formulaire mail
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db);
$formmail->withform=-1;
$formmail->fromtype = 'user';
$formmail->fromid = $user->id;
$formmail->fromname = $user->getFullName($langs);
$formmail->frommail = $user->email;
if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 1)) // If bit 1 is set
{
$formmail->trackid='ord'.$object->id;
}
if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2)) // If bit 2 is set
{
include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
$formmail->frommail=dolAddEmailTrackId($formmail->frommail, 'ord'.$object->id);
}
$formmail->withfrom=1;
$liste=$langs->trans("AllRecipientSelected");
if (count($listofselectedthirdparties) == 1)
{
$liste=array();
$thirdpartyid=array_shift($listofselectedthirdparties);
$soc=new Societe($db);
$soc->fetch($thirdpartyid);
foreach ($soc->thirdparty_and_contact_email_array(1) as $key=>$value)
{
$liste[$key]=$value;
}
$formmail->withtoreadonly=0;
}
else
{
$formmail->withtoreadonly=1;
}
$formmail->withto=$liste;
$formmail->withtofree=0;
$formmail->withtocc=1;
$formmail->withtoccc=$conf->global->MAIN_EMAIL_USECCC;
$formmail->withtopic=$langs->transnoentities($topicmail, '__REF__', '__REFCLIENT__');
$formmail->withfile=$langs->trans("OnlyPDFattachmentSupported");
$formmail->withbody=1;
$formmail->withdeliveryreceipt=1;
$formmail->withcancel=1;
// Tableau des substitutions
$formmail->substit['__REF__']='__REF__'; // We want to keep the tag
$formmail->substit['__SIGNATURE__']=$user->signature;
$formmail->substit['__REFCLIENT__']='__REFCLIENT__'; // We want to keep the tag
$formmail->substit['__PERSONALIZED__']='';
$formmail->substit['__CONTACTCIVNAME__']='';
// Tableau des parametres complementaires du post
$formmail->param['action']=$action;
$formmail->param['models']=$modelmail;
$formmail->param['models_id']=GETPOST('modelmailselected','int');
$formmail->param['id']=join(',',$arrayofselected);
//$formmail->param['returnurl']=$_SERVER["PHP_SELF"].'?id='.$object->id;
print $formmail->get_form();
dol_fiche_end();
}
if ($sall)
{
foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val);
@ -1156,7 +1106,7 @@ if ($resql)
// Action column
print '<td class="nowrap" align="center">';
if ($massactionbutton)
if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
{
$selected=0;
if (in_array($obj->rowid, $arrayofselected)) $selected=1;
@ -1204,6 +1154,30 @@ if ($resql)
print '</form>'."\n";
print '<br>'.img_help(1,'').' '.$langs->trans("ToBillSeveralOrderSelectCustomer", $langs->transnoentitiesnoconv("CreateInvoiceForThisCustomer")).'<br>';
if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files)
{
/*
* Show list of available documents
*/
$urlsource=$_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
$urlsource.=str_replace('&amp;','&',$param);
$filedir=$diroutputmassaction;
$genallowed=$user->rights->facture->lire;
$delallowed=$user->rights->facture->lire;
print '<br><a name="show_files"></a>';
$paramwithoutshowfiles=preg_replace('/show_files=1&?/','',$param);
$title=$langs->trans("MassFilesArea").' <a href="'.$_SERVER["PHP_SELF"].'?'.$paramwithoutshowfiles.'">('.$langs->trans("Hide").')</a>';
print $formfile->showdocuments('massfilesarea_orders','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,'');
}
else
{
print '<br><a name="show_files"></a><a href="'.$_SERVER["PHP_SELF"].'?show_files=1'.$param.'#show_files">'.$langs->trans("ShowTempMassFilesArea").'</a>';
}
}
else
{

View File

@ -258,6 +258,10 @@ class Account extends CommonObject
$string .= $this->code_guichet.' ';
} elseif ($val == 'BankAccountNumberKey') {
$string .= $this->cle_rib.' ';
}elseif ($val == 'BIC') {
$string .= $this->bic.' ';
}elseif ($val == 'IBAN') {
$string .= $this->iban.' ';
}
}
@ -1151,9 +1155,9 @@ class Account extends CommonObject
if ($user->societe_id) {
return 0;
}
$nb=0;
$sql = "SELECT COUNT(ba.rowid) as nb";
$sql.= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
$sql.= " WHERE ba.rappro > 0 and ba.clos = 0";
@ -1169,7 +1173,7 @@ class Account extends CommonObject
return $nb;
}
/**
* Return clicable name (with picto eventually)
*
@ -1204,7 +1208,7 @@ class Account extends CommonObject
$link = '<a href="'.DOL_URL_ROOT.'/compta/bank/releve.php?account='.$this->id.$linkclose;
$linkend='</a>';
}
if ($withpicto) $result.=($link.img_object($label, 'account', 'class="classfortooltip"').$linkend.' ');
$result.=$link.$this->label.$linkend;
return $result;
@ -1293,6 +1297,55 @@ class Account extends CommonObject
return 0;
}
/**
* Return 1 is IBAN is need for UE country
*
* @return int 1 yes / 0 No
*/
function needIBAN()
{
$country_code=$this->getCountryCode();
$country_code_in_EEC=array(
'AT', // Austria
'BE', // Belgium
'BG', // Bulgaria
'CY', // Cyprus
'CZ', // Czech republic
'DE', // Germany
'DK', // Danemark
'EE', // Estonia
'ES', // Spain
'FI', // Finland
'FR', // France
'GB', // United Kingdom
'GR', // Greece
'HR', // Croatia
'NL', // Holland
'HU', // Hungary
'IE', // Ireland
'IM', // Isle of Man - Included in UK
'IT', // Italy
'LT', // Lithuania
'LU', // Luxembourg
'LV', // Latvia
'MC', // Monaco - Included in France
'MT', // Malta
//'NO', // Norway
'PL', // Poland
'PT', // Portugal
'RO', // Romania
'SE', // Sweden
'SK', // Slovakia
'SI', // Slovenia
'UK', // United Kingdom
//'CH', // Switzerland - No. Swizerland in not in EEC
);
if (in_array($country_code,$country_code_in_EEC)) return 1; // France, Spain, Gabon, ...
return 0;
}
/**
* Load miscellaneous information for tab "Info"
*
@ -1323,18 +1376,26 @@ class Account extends CommonObject
$detailedBBAN = $this->useDetailedBBAN();
if ($detailedBBAN == 0) {
return array(
'BankAccountNumber'
$fieldarray= array(
'BankAccountNumber'
);
} elseif ($detailedBBAN == 2) {
return array(
'BankCode',
'BankAccountNumber'
$fieldarray= array(
'BankCode',
'BankAccountNumber'
);
} else {
$fieldarray=self::getAccountNumberOrder();
}
if ($this->needIBAN()) {
$fieldarray[]='IBAN';
$fieldarray[]='BIC';
}
//Get the order the properties are shown
return self::getAccountNumberOrder();
return $fieldarray;
}
/**
@ -1352,10 +1413,10 @@ class Account extends CommonObject
global $conf;
$fieldlists = array(
'BankCode',
'DeskCode',
'BankAccountNumber',
'BankAccountNumberKey'
'BankCode',
'DeskCode',
'BankAccountNumber',
'BankAccountNumberKey'
);
if (!empty($conf->global->BANK_SHOW_ORDER_OPTION)) {

View File

@ -188,7 +188,7 @@ if (empty($reshook))
$qualified_for_stock_change = $object->hasProductsOrServices(1);
}
$result = $object->delete(0, 0, $idwarehouse);
$result = $object->delete($user, 0, $idwarehouse);
if ($result > 0) {
header('Location: ' . DOL_URL_ROOT . '/compta/facture/list.php');
exit();

View File

@ -25,7 +25,7 @@
* @smart-auto-routing false
* @access protected
* @class DolibarrApiAccess {@requires user,external}
*
* @deprecated Use Invoices instead (defined in api_invoices.class.php)
*/
class InvoiceApi extends DolibarrApi
{
@ -43,7 +43,7 @@ class InvoiceApi extends DolibarrApi
public $invoice;
/**
* Constructor
* Constructor <b>Warning: Deprecated</b>
*
* @url GET invoice/
*
@ -56,7 +56,7 @@ class InvoiceApi extends DolibarrApi
}
/**
* Get properties of a invoice object
* Get properties of a invoice object <b>Warning: Deprecated</b>
*
* Return an array with invoice informations
*
@ -85,7 +85,7 @@ class InvoiceApi extends DolibarrApi
}
/**
* List invoices
* List invoices <b>Warning: Deprecated</b>
*
* Get a list of invoices
*
@ -179,7 +179,7 @@ class InvoiceApi extends DolibarrApi
}
/**
* Create invoice object
* Create invoice object <b>Warning: Deprecated</b>
*
* @param array $request_data Request datas
* @return int ID of invoice
@ -207,7 +207,7 @@ class InvoiceApi extends DolibarrApi
}
/**
* Update invoice
* Update invoice <b>Warning: Deprecated</b>
*
* @param int $id Id of invoice to update
* @param array $request_data Datas
@ -241,7 +241,7 @@ class InvoiceApi extends DolibarrApi
}
/**
* Delete invoice
* Delete invoice <b>Warning: Deprecated</b>
*
* @param int $id Invoice ID
* @return type
@ -262,7 +262,7 @@ class InvoiceApi extends DolibarrApi
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if( !$this->invoice->delete($id))
if( !$this->invoice->delete(DolibarrApiAccess::$user))
{
throw new RestException(500);
}

View File

@ -0,0 +1,281 @@
<?php
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use Luracast\Restler\RestException;
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
/**
* API class for invoices
*
* @access protected
* @class DolibarrApiAccess {@requires user,external}
*/
class Invoices extends DolibarrApi
{
/**
*
* @var array $FIELDS Mandatory fields, checked when create and update object
*/
static $FIELDS = array(
'socid'
);
/**
* @var Facture $invoice {@type Facture}
*/
public $invoice;
/**
* Constructor
*/
function __construct()
{
global $db, $conf;
$this->db = $db;
$this->invoice = new Facture($this->db);
}
/**
* Get properties of a invoice object
*
* Return an array with invoice informations
*
* @param int $id ID of invoice
* @return array|mixed data without useless information
*
* @throws RestException
*/
function get($id)
{
if(! DolibarrApiAccess::$user->rights->facture->lire) {
throw new RestException(401);
}
$result = $this->invoice->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Facture not found');
}
if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
return $this->_cleanObjectDatas($this->invoice);
}
/**
* List invoices
*
* Get a list of invoices
*
* FIXME this parameter is overwritten in the code and thus ignored
* @param int $socid Filter list with thirdparty ID
* @param string $status Filter by invoice status : draft | unpaid | paid | cancelled
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @return array Array of invoice objects
*
* @throws RestException
*/
function index($socid=0, $status='', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) {
global $db, $conf;
$obj_ret = array();
$socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : '';
// If the internal user must only see his customers, force searching by him
if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id;
$sql = "SELECT s.rowid";
if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
$sql.= " FROM ".MAIN_DB_PREFIX."facture as s";
if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
$sql.= ' WHERE s.entity IN ('.getEntity('facture', 1).')';
if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND s.fk_soc = sc.fk_soc";
if ($socid) $sql.= " AND s.fk_soc = ".$socid;
if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
// Filter by status
if ($status == 'draft') $sql.= " AND s.fk_statut IN (0)";
if ($status == 'unpaid') $sql.= " AND s.fk_statut IN (1)";
if ($status == 'paid') $sql.= " AND s.fk_statut IN (2)";
if ($status == 'cancelled') $sql.= " AND s.fk_statut IN (3)";
// Insert sale filter
if ($search_sale > 0)
{
$sql .= " AND sc.fk_user = ".$search_sale;
}
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
$result = $db->query($sql);
$nbtotalofrecords = $db->num_rows($result);
}
$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);
while ($i < $num)
{
$obj = $db->fetch_object($result);
$invoice_static = new Facture($db);
if($invoice_static->fetch($obj->rowid)) {
$obj_ret[] = parent::_cleanObjectDatas($invoice_static);
}
$i++;
}
}
else {
throw new RestException(503, 'Error when retrieve invoice list');
}
if( ! count($obj_ret)) {
throw new RestException(404, 'No invoice found');
}
return $obj_ret;
}
/**
* Create invoice object
*
* @param array $request_data Request datas
* @return int ID of invoice
*/
function post($request_data = NULL)
{
if(! DolibarrApiAccess::$user->rights->facture->creer) {
throw new RestException(401);
}
// Check mandatory fields
$result = $this->_validate($request_data);
foreach($request_data as $field => $value) {
$this->invoice->$field = $value;
}
if(! array_keys($request_data,'date')) {
$this->invoice->date = dol_now();
}
if( ! $this->invoice->create(DolibarrApiAccess::$user)) {
throw new RestException(500);
}
return $this->invoice->id;
}
/**
* Update invoice
*
* @param int $id Id of invoice to update
* @param array $request_data Datas
* @return int
*/
function put($id, $request_data = NULL)
{
if(! DolibarrApiAccess::$user->rights->facture->creer) {
throw new RestException(401);
}
$result = $this->invoice->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Facture not found');
}
if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
foreach($request_data as $field => $value) {
$this->invoice->$field = $value;
}
if($this->invoice->update($id, DolibarrApiAccess::$user))
return $this->get ($id);
return false;
}
/**
* Delete invoice
*
* @param int $id Invoice ID
* @return type
*/
function delete($id)
{
if(! DolibarrApiAccess::$user->rights->facture->supprimer) {
throw new RestException(401);
}
$result = $this->invoice->fetch($id);
if( ! $result ) {
throw new RestException(404, 'Facture not found');
}
if( ! DolibarrApi::_checkAccessToResource('facture',$this->facture->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if( $this->invoice->delete($id) < 0)
{
throw new RestException(500);
}
return array(
'success' => array(
'code' => 200,
'message' => 'Facture deleted'
)
);
}
/**
* Validate fields before create or update object
*
* @param array $data Datas to validate
* @return array
*
* @throws RestException
*/
function _validate($data)
{
$invoice = array();
foreach (Invoices::$FIELDS as $field) {
if (!isset($data[$field]))
throw new RestException(400, "$field field missing");
$invoice[$field] = $data[$field];
}
return $invoice;
}
}

View File

@ -1548,14 +1548,14 @@ class Facture extends CommonInvoice
/**
* Delete invoice
*
* @param int $rowid Id of invoice to delete. If empty, we delete current instance of invoice
* @param User $user User to delete.
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers
* @param int $idwarehouse Id warehouse to use for stock change.
* @return int <0 if KO, >0 if OK
*/
function delete($rowid=0, $notrigger=0, $idwarehouse=-1)
function delete($user, $notrigger=0, $idwarehouse=-1)
{
global $user,$langs,$conf;
global $langs,$conf;
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
if (empty($rowid)) $rowid=$this->id;

View File

@ -206,7 +206,7 @@ if ($action == 'add')
$result = $object->create($user, $oldinvoice->id);
if ($result > 0)
{
$result=$oldinvoice->delete(0, 1);
$result=$oldinvoice->delete($user, 1);
if ($result < 0)
{
$error++;
@ -242,7 +242,7 @@ if ($action == 'add')
// Delete
if ($action == 'delete' && $user->rights->facture->supprimer)
{
$object->delete();
$object->delete($user);
header("Location: " . $_SERVER['PHP_SELF'] );
exit;
}

View File

@ -58,10 +58,13 @@ $projectid=(GETPOST('projectid')?GETPOST('projectid','int'):0);
$id=(GETPOST('id','int')?GETPOST('id','int'):GETPOST('facid','int')); // For backward compatibility
$ref=GETPOST('ref','alpha');
$socid=GETPOST('socid','int');
$action=GETPOST('action','alpha');
$massaction=GETPOST('massaction','alpha');
$show_files=GETPOST('show_files','int');
$confirm=GETPOST('confirm','alpha');
$toselect = GETPOST('toselect', 'array');
$lineid=GETPOST('lineid','int');
$userid=GETPOST('userid','int');
$search_product_category=GETPOST('search_product_category','int');
@ -86,7 +89,6 @@ $year = GETPOST('year','int');
$day_lim = GETPOST('day_lim','int');
$month_lim = GETPOST('month_lim','int');
$year_lim = GETPOST('year_lim','int');
$toselect = GETPOST('toselect', 'array');
$option = GETPOST('option');
if ($option == 'late') $filter = 'paye:0';
@ -173,7 +175,7 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab
*/
if (GETPOST('cancel')) { $action='list'; $massaction=''; }
if (! GETPOST('confirmmassaction')) { $massaction=''; }
if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; }
$parameters=array('socid'=>$socid);
$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
@ -216,408 +218,11 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter") || GETPOS
if (empty($reshook))
{
// Mass actions. Controls on number of lines checked
$maxformassaction=1000;
if (! empty($massaction) && count($toselect) < 1)
{
$error++;
setEventMessages($langs->trans("NoLineChecked"), null, "warnings");
}
if (! $error && count($toselect) > $maxformassaction)
{
setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
$error++;
}
// TODO Use a common inc.php file
if (! $error && $massaction == 'confirm_presend')
{
$resaction = '';
$nbsent = 0;
$nbignored = 0;
$langs->load("mails");
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
if (!$error && !isset($user->email))
{
$error++;
setEventMessages($langs->trans("NoSenderEmailDefined"), null, 'warnings');
}
if (! $error)
{
$thirdparty=new Societe($db);
$objecttmp=new Facture($db);
$listofobjectid=array();
$listofobjectthirdparties=array();
$listofobjectref=array();
foreach($toselect as $toselectid)
{
$objecttmp=new Facture($db); // must create new instance because instance is saved into $listofobjectref array for future use
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$listoinvoicesid[$toselectid]=$toselectid;
$thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
$listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
$listofobjectref[$thirdpartyid][$toselectid]=$objecttmp;
}
}
//var_dump($listofobjectthirdparties);exit;
foreach ($listofobjectthirdparties as $thirdpartyid)
{
$result = $thirdparty->fetch($thirdpartyid);
if ($result < 0)
{
dol_print_error($db);
exit;
}
// Define recipient $sendto and $sendtocc
if (trim($_POST['sendto']))
{
// Recipient is provided into free text
$sendto = trim($_POST['sendto']);
$sendtoid = 0;
}
elseif ($_POST['receiver'] != '-1')
{
// Recipient was provided from combo list
if ($_POST['receiver'] == 'thirdparty') // Id of third party
{
$sendto = $thirdparty->email;
$sendtoid = 0;
}
else // Id du contact
{
$sendto = $thirdparty->contact_get_property((int) $_POST['receiver'],'email');
$sendtoid = $_POST['receiver'];
}
}
if (trim($_POST['sendtocc']))
{
$sendtocc = trim($_POST['sendtocc']);
}
elseif ($_POST['receivercc'] != '-1')
{
// Recipient was provided from combo list
if ($_POST['receivercc'] == 'thirdparty') // Id of third party
{
$sendtocc = $thirdparty->email;
}
else // Id du contact
{
$sendtocc = $thirdparty->contact_get_property((int) $_POST['receivercc'],'email');
}
}
//var_dump($listofobjectref[$thirdpartyid]); // Array of invoice for this thirdparty
$attachedfiles=array('paths'=>array(), 'names'=>array(), 'mimes'=>array());
$listofqualifiedinvoice=array();
$listofqualifiedref=array();
foreach($listofobjectref[$thirdpartyid] as $objectid => $object)
{
//var_dump($object);
//var_dump($thirdpartyid.' - '.$objectid.' - '.$object->statut);
if ($object->statut != Facture::STATUS_VALIDATED)
{
$nbignored++;
continue; // Payment done or started or canceled
}
// Read document
// TODO Use future field $object->fullpathdoc to know where is stored default file
// TODO If not defined, use $object->modelpdf (or defaut invoice config) to know what is template to use to regenerate doc.
$filename=dol_sanitizeFileName($object->ref).'.pdf';
$filedir=$conf->facture->dir_output . '/' . dol_sanitizeFileName($object->ref);
$file = $filedir . '/' . $filename;
$mime = dol_mimetype($file);
if (dol_is_file($file))
{
if (empty($sendto)) // For the case, no recipient were set (multi thirdparties send)
{
$object->fetch_thirdparty();
$sendto = $object->thirdparty->email;
}
if (empty($sendto))
{
//print "No recipient for thirdparty ".$object->thirdparty->name;
$nbignored++;
continue;
}
if (dol_strlen($sendto))
{
// Create form object
$attachedfiles=array(
'paths'=>array_merge($attachedfiles['paths'],array($file)),
'names'=>array_merge($attachedfiles['names'],array($filename)),
'mimes'=>array_merge($attachedfiles['mimes'],array($mime))
);
}
$listofqualifiedinvoice[$objectid]=$object;
$listofqualifiedref[$objectid]=$object->ref;
}
else
{
$nbignored++;
$langs->load("other");
$resaction.='<div class="error">'.$langs->trans('ErrorCantReadFile',$file).'</div>';
dol_syslog('Failed to read file: '.$file, LOG_WARNING);
continue;
}
//var_dump($listofqualifiedref);
}
if (count($listofqualifiedinvoice) > 0)
{
$langs->load("commercial");
$from = $user->getFullName($langs) . ' <' . $user->email .'>';
$replyto = $from;
$subject = GETPOST('subject');
$message = GETPOST('message');
$sendtocc = GETPOST('sentocc');
$sendtobcc = (empty($conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO)?'':$conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO);
$substitutionarray=array(
'__ID__' => join(', ',array_keys($listofqualifiedinvoice)),
'__EMAIL__' => $thirdparty->email,
'__CHECK_READ__' => '<img src="'.DOL_MAIN_URL_ROOT.'/public/emailing/mailing-read.php?tag='.$thirdparty->tag.'&securitykey='.urlencode($conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY).'" width="1" height="1" style="width:1px;height:1px" border="0"/>',
//'__LASTNAME__' => $obj2->lastname,
//'__FIRSTNAME__' => $obj2->firstname,
'__FACREF__' => join(', ',$listofqualifiedref), // For backward compatibility
'__REF__' => join(', ',$listofqualifiedref),
'__REFCLIENT__' => $thirdparty->name
);
$subject=make_substitutions($subject, $substitutionarray);
$message=make_substitutions($message, $substitutionarray);
$filepath = $attachedfiles['paths'];
$filename = $attachedfiles['names'];
$mimetype = $attachedfiles['mimes'];
//var_dump($filepath);
// Send mail
require_once(DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php');
$mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1);
if ($mailfile->error)
{
$resaction.='<div class="error">'.$mailfile->error.'</div>';
}
else
{
$result=$mailfile->sendfile();
if ($result)
{
$resaction.=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($from,2),$mailfile->getValidAddress($sendto,2)).'<br>'; // Must not contain "
$error=0;
// Insert logs into agenda
foreach($listofqualifiedinvoice as $invid => $object)
{
$actiontypecode='AC_FAC';
$actionmsg=$langs->transnoentities('MailSentBy').' '.$from.' '.$langs->transnoentities('To').' '.$sendto;
if ($message)
{
if ($sendtocc) $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc') . ": " . $sendtocc);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subject);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
$actionmsg = dol_concatdesc($actionmsg, $message);
}
// Initialisation donnees
$object->sendtoid = 0;
$object->actiontypecode = $actiontypecode;
$object->actionmsg = $actionmsg; // Long text
$object->actionmsg2 = $actionmsg2; // Short text
$object->fk_element = $invid;
$object->elementtype = $object->element;
// Appel des triggers
include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php");
$interface=new Interfaces($db);
$result=$interface->run_triggers('BILL_SENTBYMAIL',$object,$user,$langs,$conf);
if ($result < 0) { $error++; $errors=$interface->errors; }
// Fin appel triggers
if ($error)
{
setEventMessages($db->lasterror(), $errors, 'errors');
dol_syslog("Error in trigger BILL_SENTBYMAIL ".$db->lasterror(), LOG_ERR);
}
$nbsent++;
}
}
else
{
$langs->load("other");
if ($mailfile->error)
{
$resaction.=$langs->trans('ErrorFailedToSendMail',$from,$sendto);
$resaction.='<br><div class="error">'.$mailfile->error.'</div>';
}
else
{
$resaction.='<div class="warning">No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS</div>';
}
}
}
}
}
$resaction.=($resaction?'<br>':$resaction);
$resaction.='<strong>'.$langs->trans("ResultOfMailSending").':</strong><br>'."\n";
$resaction.=$langs->trans("NbSelected").': '.count($toselect)."\n<br>";
$resaction.=$langs->trans("NbIgnored").': '.($nbignored?$nbignored:0)."\n<br>";
$resaction.=$langs->trans("NbSent").': '.($nbsent?$nbsent:0)."\n<br>";
if ($nbsent)
{
$action=''; // Do not show form post if there was at least one successfull sent
setEventMessages($langs->trans("EMailSentToNRecipients", $nbsent.'/'.count($toselect)), null, 'mesgs');
setEventMessages($resaction, null, 'mesgs');
}
else
{
//setEventMessages($langs->trans("EMailSentToNRecipients", 0), null, 'warnings'); // May be object has no generated PDF file
setEventMessages($resaction, null, 'warnings');
}
}
$action='list';
$massaction='';
}
if (! $error && $massaction == "builddoc" && $user->rights->facture->lire && ! GETPOST('button_search'))
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$objecttmp=new Facture($db);
$listofobjectid=array();
$listofobjectthirdparties=array();
$listofobjectref=array();
foreach($toselect as $toselectid)
{
$objecttmp=new Facture($db); // must create new instance because instance is saved into $listofobjectref array for future use
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$listoinvoicesid[$toselectid]=$toselectid;
$thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
$listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
$listofobjectref[$toselectid]=$objecttmp->ref;
}
}
$arrayofinclusion=array();
foreach($listofobjectref as $tmppdf) $arrayofinclusion[]=preg_quote($tmppdf.'.pdf','/');
$listoffiles = dol_dir_list($conf->facture->dir_output,'all',1,implode('|',$arrayofinclusion),'\.meta$|\.png','date',SORT_DESC,0,true);
// build list of files with full path
$files = array();
foreach($listofobjectref as $basename)
{
foreach($listoffiles as $filefound)
{
if (strstr($filefound["name"],$basename))
{
$files[] = $conf->facture->dir_output.'/'.$basename.'/'.$filefound["name"];
break;
}
}
}
// Define output language (Here it is not used because we do only merging existing PDF)
$outputlangs = $langs;
$newlang='';
if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang=GETPOST('lang_id');
if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->thirdparty->default_lang;
if (! empty($newlang))
{
$outputlangs = new Translate("",$conf);
$outputlangs->setDefaultLang($newlang);
}
// Create empty PDF
$pdf=pdf_getInstance();
if (class_exists('TCPDF'))
{
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
}
$pdf->SetFont(pdf_getPDFFont($outputlangs));
if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
// Add all others
foreach($files as $file)
{
// Charge un document PDF depuis un fichier.
$pagecount = $pdf->setSourceFile($file);
for ($i = 1; $i <= $pagecount; $i++)
{
$tplidx = $pdf->importPage($i);
$s = $pdf->getTemplatesize($tplidx);
$pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
$pdf->useTemplate($tplidx);
}
}
// Create output dir if not exists
dol_mkdir($diroutputmassaction);
// Save merged file
$filename=strtolower(dol_sanitizeFileName($langs->transnoentities("Invoices")));
if ($filter=='paye:0')
{
if ($option=='late') $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid"))).'_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Late")));
else $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid")));
}
if ($year) $filename.='_'.$year;
if ($month) $filename.='_'.$month;
if ($pagecount)
{
$now=dol_now();
$file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
$pdf->Output($file,'F');
if (! empty($conf->global->MAIN_UMASK))
@chmod($file, octdec($conf->global->MAIN_UMASK));
$langs->load("exports");
setEventMessages($langs->trans('FileSuccessfullyBuilt',$filename.'_'.dol_print_date($now,'dayhourlog')), null, 'mesgs');
}
else
{
setEventMessages($langs->trans('NoPDFAvailableForDocGenAmongChecked'), null, 'errors');
}
}
// Remove file
if ($action == 'remove_file')
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$langs->load("other");
$upload_dir = $diroutputmassaction;
$file = $upload_dir . '/' . GETPOST('file');
$ret=dol_delete_file($file);
if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
$action='';
}
$objectclass='Facture';
$permtoread = $user->rights->facture->lire;
$permtodelete = $user->rights->facture->supprimer;
$uploaddir = $conf->facture->dir_output;
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
}
@ -836,6 +441,18 @@ if ($resql)
'presend'=>$langs->trans("SendByMail"),
'builddoc'=>$langs->trans("PDFMerge")
);
if ($user->rights->facture->supprimer)
{
//if (! empty($conf->global->STOCK_CALCULATE_ON_BILL) || empty($conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED))
if (empty($conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED))
{
// mass deletion never possible on invoices on such situation
}
else
{
$arrayofmassactions['delete']=$langs->trans("Delete");
}
}
if ($massaction == 'presend') $arrayofmassactions=array();
$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
@ -940,6 +557,7 @@ if ($resql)
$formmail->param['models']=$modelmail;
$formmail->param['models_id']=GETPOST('modelmailselected','int');
$formmail->param['facid']=join(',',$arrayofselected);
// TODO We should use $formmail->param['id']=join(',',$arrayofselected);
//$formmail->param['returnurl']=$_SERVER["PHP_SELF"].'?id='.$object->id;
print $formmail->get_form();
@ -1429,7 +1047,7 @@ if ($resql)
// Action column
print '<td class="nowrap" align="center">';
if ($massactionbutton)
if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
{
$selected=0;
if (in_array($obj->facid, $arrayofselected)) $selected=1;
@ -1494,7 +1112,7 @@ if ($resql)
$paramwithoutshowfiles=preg_replace('/show_files=1&?/','',$param);
$title=$langs->trans("MassFilesArea").' <a href="'.$_SERVER["PHP_SELF"].'?'.$paramwithoutshowfiles.'">('.$langs->trans("Hide").')</a>';
print $formfile->showdocuments('massfilesarea_facture','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,'');
print $formfile->showdocuments('massfilesarea_invoices','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,'');
}
else
{

View File

@ -529,7 +529,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
$sql.= ' WHERE f.entity = '.$conf->entity;
$sql.= ' AND (f.fk_soc = '.$facture->socid;
if(!empty($conf->global->FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS)) {
if(!empty($conf->global->FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS) && !empty($facture->thirdparty->parent)) {
$sql.= ' OR f.fk_soc IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'societe WHERE parent = '.$facture->thirdparty->parent.')';
}

View File

@ -1117,7 +1117,7 @@ if ($action == 'create')
else
{
print '<td colspan="2">';
print $form->select_company('','socid','',1,1);
print $form->select_company('','socid','','SelectThirdParty',1);
print '</td>';
}
print '</tr>'."\n";

View File

@ -273,7 +273,7 @@ if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire)
}
else
{
print '<tr '.$bc[$var].'><td colspan="3">'.$langs->trans("NoContracts").'</td></tr>';
print '<tr '.$bc[$var].' class><td colspan="3" class="opacitymedium">'.$langs->trans("NoContracts").'</td></tr>';
}
print "</table><br>";
$db->free($resql);

View File

@ -0,0 +1,499 @@
<?php
/* Copyright (C) 2015 Laurent Destailleur <eldy@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* or see http://www.gnu.org/
*/
/**
* \file htdocs/core/actions_massactions.inc.php
* \brief Code for actions done with massaction button (send by email, merge pdf, delete, ...)
*/
// $massaction must be defined
// $objectclass must be defined
// $uploaddir (example $conf->projet->dir_output . "/";)
// $toselect may be defined
// Protection
if (empty($objectclass) || empty($uploaddir))
{
dol_print_error(null, 'include of actions_massactions.inc.php is done but var $massaction or $objectclass or $uploaddir was not defined');
exit;
}
// Mass actions. Controls on number of lines checked
$maxformassaction=1000;
if (! empty($massaction) && count($toselect) < 1)
{
$error++;
setEventMessages($langs->trans("NoLineChecked"), null, "warnings");
}
if (! $error && count($toselect) > $maxformassaction)
{
setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
$error++;
}
if (! $error && $massaction == 'confirm_presend')
{
$resaction = '';
$nbsent = 0;
$nbignored = 0;
$langs->load("mails");
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
if (!$error && !isset($user->email))
{
$error++;
setEventMessages($langs->trans("NoSenderEmailDefined"), null, 'warnings');
}
if (! $error)
{
$thirdparty=new Societe($db);
$objecttmp=new $objectclass($db);
$listofobjectid=array();
$listofobjectthirdparties=array();
$listofobjectref=array();
foreach($toselect as $toselectid)
{
$objecttmp=new $objectclass($db); // must create new instance because instance is saved into $listofobjectref array for future use
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$listoinvoicesid[$toselectid]=$toselectid;
$thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
$listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
$listofobjectref[$thirdpartyid][$toselectid]=$objecttmp;
}
}
//var_dump($listofobjectthirdparties);exit;
foreach ($listofobjectthirdparties as $thirdpartyid)
{
$result = $thirdparty->fetch($thirdpartyid);
if ($result < 0)
{
dol_print_error($db);
exit;
}
// Define recipient $sendto and $sendtocc
if (trim($_POST['sendto']))
{
// Recipient is provided into free text
$sendto = trim($_POST['sendto']);
$sendtoid = 0;
}
elseif ($_POST['receiver'] != '-1')
{
// Recipient was provided from combo list
if ($_POST['receiver'] == 'thirdparty') // Id of third party
{
$sendto = $thirdparty->email;
$sendtoid = 0;
}
else // Id du contact
{
$sendto = $thirdparty->contact_get_property((int) $_POST['receiver'],'email');
$sendtoid = $_POST['receiver'];
}
}
if (trim($_POST['sendtocc']))
{
$sendtocc = trim($_POST['sendtocc']);
}
elseif ($_POST['receivercc'] != '-1')
{
// Recipient was provided from combo list
if ($_POST['receivercc'] == 'thirdparty') // Id of third party
{
$sendtocc = $thirdparty->email;
}
else // Id du contact
{
$sendtocc = $thirdparty->contact_get_property((int) $_POST['receivercc'],'email');
}
}
//var_dump($listofobjectref[$thirdpartyid]); // Array of invoice for this thirdparty
$attachedfiles=array('paths'=>array(), 'names'=>array(), 'mimes'=>array());
$listofqualifiedinvoice=array();
$listofqualifiedref=array();
foreach($listofobjectref[$thirdpartyid] as $objectid => $object)
{
//var_dump($object);
//var_dump($thirdpartyid.' - '.$objectid.' - '.$object->statut);
if ($objectclass == 'Facture' && $object->statut != Facture::STATUS_VALIDATED)
{
$nbignored++;
$resaction.='<div class="error">'.$langs->trans('ErrorOnlyInvoiceValidatedCanBeSentInMassAction',$object->ref).'</div><br>';
continue; // Payment done or started or canceled
}
if ($objectclass == 'Commande' && $object->statut == Commande::STATUS_DRAFT)
{
$nbignored++;
$resaction.='<div class="error">'.$langs->trans('ErrorOnlyOrderNotDraftCanBeSentInMassAction',$object->ref).'</div><br>';
continue;
}
// Read document
// TODO Use future field $object->fullpathdoc to know where is stored default file
// TODO If not defined, use $object->modelpdf (or defaut invoice config) to know what is template to use to regenerate doc.
$filename=dol_sanitizeFileName($object->ref).'.pdf';
$filedir=$uploaddir . '/' . dol_sanitizeFileName($object->ref);
$file = $filedir . '/' . $filename;
$mime = dol_mimetype($file);
if (dol_is_file($file))
{
if (empty($sendto)) // For the case, no recipient were set (multi thirdparties send)
{
$object->fetch_thirdparty();
$sendto = $object->thirdparty->email;
}
if (empty($sendto))
{
//print "No recipient for thirdparty ".$object->thirdparty->name;
$nbignored++;
continue;
}
if (dol_strlen($sendto))
{
// Create form object
$attachedfiles=array(
'paths'=>array_merge($attachedfiles['paths'],array($file)),
'names'=>array_merge($attachedfiles['names'],array($filename)),
'mimes'=>array_merge($attachedfiles['mimes'],array($mime))
);
}
$listofqualifiedinvoice[$objectid]=$object;
$listofqualifiedref[$objectid]=$object->ref;
}
else
{
$nbignored++;
$langs->load("errors");
$resaction.='<div class="error">'.$langs->trans('ErrorCantReadFile',$file).'</div><br>';
dol_syslog('Failed to read file: '.$file, LOG_WARNING);
continue;
}
//var_dump($listofqualifiedref);
}
if (count($listofqualifiedinvoice) > 0)
{
$langs->load("commercial");
$from = $user->getFullName($langs) . ' <' . $user->email .'>';
$replyto = $from;
$subject = GETPOST('subject');
$message = GETPOST('message');
$sendtocc = GETPOST('sentocc');
$sendtobcc = (empty($conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO)?'':$conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO);
$substitutionarray=array(
'__ID__' => join(', ',array_keys($listofqualifiedinvoice)),
'__EMAIL__' => $thirdparty->email,
'__CHECK_READ__' => '<img src="'.DOL_MAIN_URL_ROOT.'/public/emailing/mailing-read.php?tag='.$thirdparty->tag.'&securitykey='.urlencode($conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY).'" width="1" height="1" style="width:1px;height:1px" border="0"/>',
'__FACREF__' => join(', ',$listofqualifiedref), // For backward compatibility
'__ORDERREF__' => join(', ',$listofqualifiedref), // For backward compatibility
'__PROPREF__' => join(', ',$listofqualifiedref), // For backward compatibility
'__REF__' => join(', ',$listofqualifiedref),
'__REFCLIENT__' => $thirdparty->name
);
$subject=make_substitutions($subject, $substitutionarray);
$message=make_substitutions($message, $substitutionarray);
$filepath = $attachedfiles['paths'];
$filename = $attachedfiles['names'];
$mimetype = $attachedfiles['mimes'];
//var_dump($filepath);
// Send mail
require_once(DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php');
$mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1);
if ($mailfile->error)
{
$resaction.='<div class="error">'.$mailfile->error.'</div>';
}
else
{
$result=$mailfile->sendfile();
if ($result)
{
$resaction.=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($from,2),$mailfile->getValidAddress($sendto,2)).'<br>'; // Must not contain "
$error=0;
// Insert logs into agenda
foreach($listofqualifiedinvoice as $invid => $object)
{
if ($objectclass == 'Propale') $actiontypecode='AC_PROP';
if ($objectclass == 'Commande') $actiontypecode='AC_COM';
if ($objectclass == 'Facture') $actiontypecode='AC_FAC';
if ($objectclass == 'Supplier_Proposal') $actiontypecode='AC_SUP_PRO';
if ($objectclass == 'CommandeFournisseur') $actiontypecode='AC_SUP_ORD';
if ($objectclass == 'FactureFournisseur') $actiontypecode='AC_SUP_INV';
$actionmsg=$langs->transnoentities('MailSentBy').' '.$from.' '.$langs->transnoentities('To').' '.$sendto;
if ($message)
{
if ($sendtocc) $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc') . ": " . $sendtocc);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subject);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
$actionmsg = dol_concatdesc($actionmsg, $message);
}
// Initialisation donnees
$object->sendtoid = 0;
$object->actiontypecode = $actiontypecode;
$object->actionmsg = $actionmsg; // Long text
$object->actionmsg2 = $actionmsg2; // Short text
$object->fk_element = $invid;
$object->elementtype = $object->element;
// Appel des triggers
include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php");
$interface=new Interfaces($db);
$result=$interface->run_triggers('BILL_SENTBYMAIL',$object,$user,$langs,$conf);
if ($result < 0) { $error++; $errors=$interface->errors; }
// Fin appel triggers
if ($error)
{
setEventMessages($db->lasterror(), $errors, 'errors');
dol_syslog("Error in trigger BILL_SENTBYMAIL ".$db->lasterror(), LOG_ERR);
}
$nbsent++;
}
}
else
{
$langs->load("other");
if ($mailfile->error)
{
$resaction.=$langs->trans('ErrorFailedToSendMail',$from,$sendto);
$resaction.='<br><div class="error">'.$mailfile->error.'</div>';
}
else
{
$resaction.='<div class="warning">No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS</div>';
}
}
}
}
}
$resaction.=($resaction?'<br>':$resaction);
$resaction.='<strong>'.$langs->trans("ResultOfMailSending").':</strong><br>'."\n";
$resaction.=$langs->trans("NbSelected").': '.count($toselect)."\n<br>";
$resaction.=$langs->trans("NbIgnored").': '.($nbignored?$nbignored:0)."\n<br>";
$resaction.=$langs->trans("NbSent").': '.($nbsent?$nbsent:0)."\n<br>";
if ($nbsent)
{
$action=''; // Do not show form post if there was at least one successfull sent
//setEventMessages($langs->trans("EMailSentToNRecipients", $nbsent.'/'.count($toselect)), null, 'mesgs');
setEventMessages($langs->trans("EMailSentForNElements", $nbsent.'/'.count($toselect)), null, 'mesgs');
setEventMessages($resaction, null, 'mesgs');
}
else
{
//setEventMessages($langs->trans("EMailSentToNRecipients", 0), null, 'warnings'); // May be object has no generated PDF file
setEventMessages($resaction, null, 'warnings');
}
}
$action='list';
$massaction='';
}
if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_search'))
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$objecttmp=new $objectclass($db);
$listofobjectid=array();
$listofobjectthirdparties=array();
$listofobjectref=array();
foreach($toselect as $toselectid)
{
$objecttmp=new $objectclass($db); // must create new instance because instance is saved into $listofobjectref array for future use
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$listoinvoicesid[$toselectid]=$toselectid;
$thirdpartyid=$objecttmp->fk_soc?$objecttmp->fk_soc:$objecttmp->socid;
$listofobjectthirdparties[$thirdpartyid]=$thirdpartyid;
$listofobjectref[$toselectid]=$objecttmp->ref;
}
}
$arrayofinclusion=array();
foreach($listofobjectref as $tmppdf) $arrayofinclusion[]=preg_quote($tmppdf.'.pdf','/');
$listoffiles = dol_dir_list($uploaddir,'all',1,implode('|',$arrayofinclusion),'\.meta$|\.png','date',SORT_DESC,0,true);
// build list of files with full path
$files = array();
foreach($listofobjectref as $basename)
{
foreach($listoffiles as $filefound)
{
if (strstr($filefound["name"],$basename))
{
$files[] = $uploaddir.'/'.$basename.'/'.$filefound["name"];
break;
}
}
}
// Define output language (Here it is not used because we do only merging existing PDF)
$outputlangs = $langs;
$newlang='';
if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang=GETPOST('lang_id');
if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->thirdparty->default_lang;
if (! empty($newlang))
{
$outputlangs = new Translate("",$conf);
$outputlangs->setDefaultLang($newlang);
}
// Create empty PDF
$pdf=pdf_getInstance();
if (class_exists('TCPDF'))
{
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
}
$pdf->SetFont(pdf_getPDFFont($outputlangs));
if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
// Add all others
foreach($files as $file)
{
// Charge un document PDF depuis un fichier.
$pagecount = $pdf->setSourceFile($file);
for ($i = 1; $i <= $pagecount; $i++)
{
$tplidx = $pdf->importPage($i);
$s = $pdf->getTemplatesize($tplidx);
$pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
$pdf->useTemplate($tplidx);
}
}
// Create output dir if not exists
dol_mkdir($diroutputmassaction);
// Save merged file
$filename=strtolower(dol_sanitizeFileName($langs->transnoentities("Invoices")));
if ($filter=='paye:0')
{
if ($option=='late') $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid"))).'_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Late")));
else $filename.='_'.strtolower(dol_sanitizeFileName($langs->transnoentities("Unpaid")));
}
if ($year) $filename.='_'.$year;
if ($month) $filename.='_'.$month;
if ($pagecount)
{
$now=dol_now();
$file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
$pdf->Output($file,'F');
if (! empty($conf->global->MAIN_UMASK))
@chmod($file, octdec($conf->global->MAIN_UMASK));
$langs->load("exports");
setEventMessages($langs->trans('FileSuccessfullyBuilt',$filename.'_'.dol_print_date($now,'dayhourlog')), null, 'mesgs');
}
else
{
setEventMessages($langs->trans('NoPDFAvailableForDocGenAmongChecked'), null, 'errors');
}
}
// Remove a file from massaction area
if ($action == 'remove_file')
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$langs->load("other");
$upload_dir = $diroutputmassaction;
$file = $upload_dir . '/' . GETPOST('file');
$ret=dol_delete_file($file);
if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
$action='';
}
// Delete records
if (! $error && $massaction == 'delete' && $permtodelete)
{
$db->begin();
$objecttmp=new $objectclass($db);
$nbok = 0;
foreach($toselect as $toselectid)
{
$result=$objecttmp->fetch($toselectid);
if ($result > 0)
{
$result = $objecttmp->delete($user);
if ($result <= 0)
{
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
}
else $nbok++;
}
else
{
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
$error++;
break;
}
}
if (! $error)
{
if ($nbok > 1) setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
else setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
$db->commit();
}
else
{
$db->rollback();
}
//var_dump($listofobjectthirdparties);exit;
}

View File

@ -20,9 +20,9 @@
*/
/**
* \file htdocs/core/boxes/box_clients.php
* \file htdocs/core/boxes/box_goodcustomers.php
* \ingroup societes
* \brief Module de generation de l'affichage de la box clients
* \brief Module to generated widget of best customers (the most invoiced)
*/
include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
@ -59,6 +59,7 @@ class box_goodcustomers extends ModeleBoxes
// disable box for such cases
if (! empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) $this->enabled=0; // disabled by this option
if (empty($conf->global->MAIN_BOX_ENABLE_BEST_CUSTOMERS)) $this->enabled=0; // not enabled by default. Very slow on large database
}
/**

View File

@ -322,7 +322,7 @@ abstract class CommonDocGenerator
*
* @param Object $object Main object to use as data source
* @param Translate $outputlangs Lang object to use for output
* @param array_key $array_key Name of the key for return array
* @param string $array_key Name of the key for return array
* @return array Array of substitution
*/
function get_substitutionarray_object($object,$outputlangs,$array_key='object')

View File

@ -460,11 +460,20 @@ class FormFile
$modellist=ModeleDon::liste_modeles($this->db);
}
}
elseif ($modulepart == 'agenda')
{
if (is_array($genallowed)) $modellist=$genallowed;
else
{
include_once DOL_DOCUMENT_ROOT.'/core/modules/action/modules_action.php';
$modellist=ModeleAction::liste_modeles($this->db);
}
}
else if ($modulepart == 'unpaid')
{
$modellist='';
}
else if ($modulepart != 'agenda')
else //if ($modulepart != 'agenda')
{
// For normalized standard modules
$file=dol_buildpath('/core/modules/'.$modulepart.'/modules_'.$modulepart.'.php',0);

View File

@ -1012,6 +1012,9 @@ function getParameterByName(name, valueifnotfound)
}
})();
// Another solution, easier, to build a javascript rounding function
function dolroundjs(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); }
/**
* Function similar to PHP price2num()
@ -1024,7 +1027,7 @@ function price2numjs(amount) {
if (amount == '') return '';
<?php
$dec = ',';
$dec = ',';
$thousand = ' ';
if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
$dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
@ -1032,6 +1035,7 @@ function price2numjs(amount) {
if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
$thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
}
if ($thousand == 'Space') $thousand=' ';
print "var dec='" . dol_escape_js($dec) . "'; var thousand='" . dol_escape_js($thousand) . "';\n"; // Set var in javascript
?>
@ -1050,11 +1054,15 @@ function price2numjs(amount) {
if (nbdec > rounding) rounding = nbdec;
// If rounding higher than max shown
if (rounding > main_max_dec_shown) rounding = main_max_dec_shown;
if (thousand != ',' && thousand != '.') amount = amount.replace(',', '.');
amount = amount.replace(' ', ''); // To avoid spaces
amount = amount.replace(thousand, ''); // Replace of thousand before replace of dec to avoid pb if thousand is .
amount = amount.replace(dec, '.');
return Math.round10(amount, rounding);
//console.log("amount before="+amount+" rouding="+rounding)
var res = Math.round10(amount, - rounding);
// Other solution is
// var res = dolroundjs(amount, rounding)
console.log("res="+res)
return res;
}

View File

@ -1990,8 +1990,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
$original_file=$conf->facture->dir_output.'/'.$original_file;
$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
}
else if ($modulepart == 'massfilesarea')
else if ($modulepart == 'massfilesarea_invoices')
{
if ($fuser->rights->facture->lire || preg_match('/^specimen/i',$original_file))
{
@ -1999,7 +1998,15 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
}
$original_file=$conf->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
}
else if ($modulepart == 'massfilesarea_orders')
{
if ($fuser->rights->commande->lire || preg_match('/^specimen/i',$original_file))
{
$accessallowed=1;
}
$original_file=$conf->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
}
// Wrapping pour les fiches intervention
else if ($modulepart == 'ficheinter')
{

View File

@ -2668,10 +2668,10 @@ function img_searchclear($titlealt = 'default', $other = '')
* @param string $text Text info
* @param integer $infoonimgalt Info is shown only on alt of star picto, otherwise it is show on output after the star picto
* @param int $nodiv No div
* @param int $admin 1=Info for admin users. 0=Info for standard users (change only the look)
* @param string $admin '1'=Info for admin users. '0'=Info for standard users (change only the look), 'xxx'=Other
* @return string String with info text
*/
function info_admin($text, $infoonimgalt = 0, $nodiv=0, $admin=1)
function info_admin($text, $infoonimgalt = 0, $nodiv=0, $admin='1')
{
global $conf, $langs;
@ -2680,7 +2680,7 @@ function info_admin($text, $infoonimgalt = 0, $nodiv=0, $admin=1)
return img_picto($text, 'info', 'class="hideonsmartphone"');
}
return ($nodiv?'':'<div class="'.($admin?'info':'').' hideonsmartphone">').img_picto($admin?$langs->trans('InfoAdmin'):$langs->trans('Note'), ($nodiv?'info':'info_black'), 'class="hideonsmartphone"').' '.$text.($nodiv?'':'</div>');
return ($nodiv?'':'<div class="'.(empty($admin)?'':($admin=='1'?'info':$admin)).' hideonsmartphone">').img_picto($admin?$langs->trans('InfoAdmin'):$langs->trans('Note'), ($nodiv?'info':'info_black'), 'class="hideonsmartphone"').' '.$text.($nodiv?'':'</div>');
}
@ -4546,7 +4546,7 @@ function dol_textishtml($msg,$option=0)
{
if (preg_match('/<html/i',$msg)) return true;
elseif (preg_match('/<body/i',$msg)) return true;
elseif (preg_match('/<(b|em|i)>/i',$msg)) return true;
elseif (preg_match('/<(b|em|i|u)>/i',$msg)) return true;
elseif (preg_match('/<(br|div|font|li|p|span|strong|table)>/i',$msg)) return true;
elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*>/i',$msg)) return true;
elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*\/>/i',$msg)) return true;

View File

@ -292,7 +292,7 @@ function pdf_getHeightForLogo($logo, $url = false)
/**
* Function to try to calculate height of a HTML Content
*
*
* @param TCPDF $pdf PDF initialized object
* @param string $htmlcontent HTML Contect
* @see getStringHeight
@ -315,7 +315,7 @@ function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
if ($end_page == $start_page) {
$height = $end_y - $start_y;
}
else
else
{
for ($page=$start_page; $page <= $end_page; ++$page) {
$pdf->setPage($page);
@ -331,7 +331,7 @@ function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
}
}
// restore previous object
$pdf = $pdf->rollbackTransaction();
$pdf = $pdf->rollbackTransaction();
return $height;
}
@ -404,9 +404,9 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
{
$withCountry = 0;
if (!empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) $withCountry = 1;
$stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs))."\n";
if (empty($conf->global->MAIN_PDF_DISABLESOURCEDETAILS))
{
// Phone
@ -419,13 +419,13 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
if ($sourcecompany->url) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
}
}
if ($mode == 'target' || preg_match('/targetwithdetails/',$mode))
{
if ($usecontact)
{
$stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs,1));
if (!empty($targetcontact->address)) {
$stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
}else {
@ -438,7 +438,7 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
else if (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
$stringaddress.=$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code))."\n";
}
if (! empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/',$mode))
{
// Phone
@ -471,7 +471,7 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
$stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($targetcompany))."\n";
// Country
if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) $stringaddress.=$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code))."\n";
if (! empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/',$mode))
{
// Phone
@ -499,13 +499,13 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
}
}
}
// Intra VAT
if (empty($conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS))
{
if ($targetcompany->tva_intra) $stringaddress.="\n".$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
}
// Professionnal Ids
if (! empty($conf->global->MAIN_PROFID1_IN_ADDRESS) && ! empty($targetcompany->idprof1))
{
@ -543,7 +543,7 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
if (preg_match('/\((.+)\)/',$tmp,$reg)) $tmp=$reg[1];
$stringaddress.="\n".$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
}
// Public note
if (! empty($conf->global->MAIN_PUBLIC_NOTE_IN_ADDRESS))
{
@ -558,7 +558,7 @@ function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$target
}
}
}
return $stringaddress;
}
@ -641,7 +641,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default
global $mysoc, $conf;
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
$diffsizetitle=(empty($conf->global->PDF_DIFFSIZE_TITLE)?3:$conf->global->PDF_DIFFSIZE_TITLE);
$diffsizecontent=(empty($conf->global->PDF_DIFFSIZE_CONTENT)?4:$conf->global->PDF_DIFFSIZE_CONTENT);
$pdf->SetXY($curx, $cury);
@ -683,7 +683,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default
// number = account number
// key = check control key used only when $usedetailedbban = 1
if (empty($onlynumber)) $pdf->line($curx+1, $cury+1, $curx+1, $cury+6);
foreach ($account->getFieldsToShow() as $val)
{
@ -706,8 +706,12 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default
// Key
$tmplength = 13;
$content = $account->cle_rib;
}elseif ($val == 'IBAN' || $val == 'BIC') {
// Key
$tmplength = 0;
$content = '';
} else {
dol_print_error($this->db, 'Unexpected value for getFieldsToShow: '.$val);
dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
break;
}
@ -720,7 +724,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default
$pdf->line($curx, $cury + 1, $curx, $cury + 7);
}
}
$curx=$savcurx;
$cury+=8;
}
@ -1054,7 +1058,7 @@ function pdf_writeLinkedObjects(&$pdf,$object,$outputlangs,$posx,$posy,$w,$h,$al
{
$reftoshow .= ' / '.$linkedobject["date_value"];
}
$posy+=3;
$pdf->SetXY($posx,$posy);
$pdf->SetFont('','', $default_font_size - 2);
@ -1095,7 +1099,7 @@ function pdf_writelinedesc(&$pdf,$object,$i,$outputlangs,$w,$h,$posx,$posy,$hide
$parameters = array('pdf'=>$pdf,'i'=>$i,'outputlangs'=>$outputlangs,'w'=>$w,'h'=>$h,'posx'=>$posx,'posy'=>$posy,'hideref'=>$hideref,'hidedesc'=>$hidedesc,'issupplierline'=>$issupplierline,'special_code'=>$special_code);
$action='';
$reshook=$hookmanager->executeHooks('pdf_writelinedesc',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if (!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1415,7 +1419,7 @@ function pdf_getlinevatrate($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlinevatrate',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if (!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1451,12 +1455,12 @@ function pdf_getlineupexcltax($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineupexcltax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if (!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
{
if (empty($hidedetails) || $hidedetails > 1)
if (empty($hidedetails) || $hidedetails > 1)
{
$subprice = ($conf->multicurrency->enabled && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
$result.=price($sign * $subprice, 0, $outputlangs);
@ -1491,7 +1495,7 @@ function pdf_getlineupwithtax($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineupwithtax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if (!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1524,7 +1528,7 @@ function pdf_getlineqty($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineqty',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1558,7 +1562,7 @@ function pdf_getlineqty_asked($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineqty_asked',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if (!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1592,7 +1596,7 @@ function pdf_getlineqty_shipped($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1626,7 +1630,7 @@ function pdf_getlineqty_keeptoship($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1650,7 +1654,7 @@ function pdf_getlineqty_keeptoship($object,$i,$outputlangs,$hidedetails=0)
function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = false)
{
global $langs;
$reshook=0;
$result='';
//if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
@ -1668,7 +1672,7 @@ function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanag
);
$action = '';
$reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1705,7 +1709,7 @@ function pdf_getlineremisepercent($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlineremisepercent',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1738,7 +1742,7 @@ function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookm
$parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
$action = '';
$reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
}
if (empty($reshook))
@ -1775,7 +1779,7 @@ function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code, 'sign'=>$sign);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1819,7 +1823,7 @@ function pdf_getlinetotalwithtax($object,$i,$outputlangs,$hidedetails=0)
$parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
$action='';
$reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
}
if (empty($reshook))
@ -1895,7 +1899,7 @@ function pdf_getLinkedObjects($object,$outputlangs)
$linkedobjects=array();
$object->fetchObjectLinked();
foreach($object->linkedObjects as $objecttype => $objects)
{
if ($objecttype == 'facture')
@ -1955,7 +1959,7 @@ function pdf_getLinkedObjects($object,$outputlangs)
if (! empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'].=' / ';
$linkedobjects[$objecttype]['ref_value'].= $outputlangs->transnoentities($elementobject->ref);
//$linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateShipment");
//if (! empty($linkedobjects[$objecttype]['date_value'])) $linkedobjects[$objecttype]['date_value'].=' / ';
//if (! empty($linkedobjects[$objecttype]['date_value'])) $linkedobjects[$objecttype]['date_value'].=' / ';
//$linkedobjects[$objecttype]['date_value'].= dol_print_date($elementobject->date_delivery,'day','',$outputlangs);
}
else

View File

@ -17,7 +17,7 @@ insert into llx_menu (module, enabled, rowid, menu_handler, type, mainmenu, left
insert into llx_menu (module, enabled, rowid, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('projet', '$conf->projet->enabled', 7__+MAX_llx_menu__, __HANDLER__, 'top', 'project', '', 0, '/projet/index.php?mainmenu=project&amp;leftmenu=', 'Projects', -1, 'projects', '$user->rights->projet->lire', '', 2, 70, __ENTITY__);
insert into llx_menu (module, enabled, rowid, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('mailing|export|import|opensurvey', '$conf->mailing->enabled || $conf->export->enabled || $conf->import->enabled || $conf->opensurvey->enabled', 8__+MAX_llx_menu__, __HANDLER__, 'top', 'tools', '', 0, '/core/tools.php?mainmenu=tools&amp;leftmenu=', 'Tools', -1, 'other', '$user->rights->mailing->lire || $user->rights->export->lire || $user->rights->import->run || $user->rights->opensurvey->read', '', 2, 90, __ENTITY__);
insert into llx_menu (module, enabled, rowid, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('adherent', '$conf->adherent->enabled', 13__+MAX_llx_menu__, __HANDLER__, 'top', 'members', '', 0, '/adherents/index.php?mainmenu=members&amp;leftmenu=', 'Members', -1, 'members', '$user->rights->adherent->lire', '', 2, 110, __ENTITY__);
insert into llx_menu (module, enabled, rowid, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('hrm|holiday|deplacement|expensereport', '$conf->hrm->enabled || $conf->holiday->enabled || $conf->deplacement->enabled || $conf->expensereport->enabled', 15__+MAX_llx_menu__, __HANDLER__, 'top', 'hrm', '', 0, '/hrm/hrm.php?mainmenu=hrm&amp;leftmenu=', 'HRM', -1, 'holiday', '$user->rights->hrm->employee->read || $user->rights->holiday->write || $user->rights->deplacement->lire || $user->rights->expensereport->lire', '', 0, 80, __ENTITY__);
insert into llx_menu (module, enabled, rowid, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('hrm|holiday|deplacement|expensereport', '$conf->hrm->enabled || $conf->holiday->enabled || $conf->deplacement->enabled || $conf->expensereport->enabled', 15__+MAX_llx_menu__, __HANDLER__, 'top', 'hrm', '', 0, '/hrm/index.php?mainmenu=hrm&amp;leftmenu=', 'HRM', -1, 'holiday', '$user->rights->hrm->employee->read || $user->rights->holiday->write || $user->rights->deplacement->lire || $user->rights->expensereport->lire', '', 0, 80, __ENTITY__);
-- Home - Dashboard
insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '1', __HANDLER__, 'left', 90__+MAX_llx_menu__, 'home', '', 1__+MAX_llx_menu__, '/index.php', 'Dashboard', 0, '', '', '', 2, 0, __ENTITY__);

View File

@ -237,9 +237,9 @@ function print_eldy_menu($db,$atarget,$type_user,&$tabMenu,&$menu,$noout=0,$mode
$idsel='hrm';
if (empty($noout)) print_start_menu_entry($idsel,$classname,$showmode);
if (empty($noout)) print_text_menu_entry($langs->trans("HRM"), $showmode, DOL_URL_ROOT.'/hrm/hrm.php?mainmenu=hrm&amp;leftmenu=', $id, $idsel, $classname, $atarget);
if (empty($noout)) print_text_menu_entry($langs->trans("HRM"), $showmode, DOL_URL_ROOT.'/hrm/index.php?mainmenu=hrm&amp;leftmenu=', $id, $idsel, $classname, $atarget);
if (empty($noout)) print_end_menu_entry($showmode);
$menu->add('/hrm/hrm.php?mainmenu=hrm&amp;leftmenu=', $langs->trans("HRM"), 0, $showmode, $atarget, "hrm", '');
$menu->add('/hrm/index.php?mainmenu=hrm&amp;leftmenu=', $langs->trans("HRM"), 0, $showmode, $atarget, "hrm", '');
}
@ -527,7 +527,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu
$newmenu->add("/admin/menus.php?mainmenu=home", $langs->trans("Menus"),1);
$newmenu->add("/admin/ihm.php?mainmenu=home", $langs->trans("GUISetup"),1);
$newmenu->add("/admin/translation.php", $langs->trans("Translation"),1);
$newmenu->add("/admin/translation.php?mainmenu=home", $langs->trans("Translation"),1);
$newmenu->add("/admin/boxes.php?mainmenu=home", $langs->trans("Boxes"),1);
$newmenu->add("/admin/delais.php?mainmenu=home",$langs->trans("Alerts"),1);
$newmenu->add("/admin/security_other.php?mainmenu=home", $langs->trans("Security"),1);

View File

@ -0,0 +1,149 @@
<?php
/* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2010 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* or see http://www.gnu.org/
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php';
/**
* \class ModeleAction
* \brief Parent class for product models of doc generators
*/
abstract class ModeleAction extends CommonDocGenerator
{
var $error='';
/**
* Return list of active generation modules
*
* @param DoliDB $db Database handler
* @param integer $maxfilenamelength Max length of value to show
* @return array List of templates
*/
static function liste_modeles($db,$maxfilenamelength=0)
{
global $conf;
$type='action';
$liste=array();
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
$liste=getListOfModels($db,$type,$maxfilenamelength);
return $liste;
}
}
/**
* Create an product document on disk using template defined into PRODUCT_ADDON_PDF
*
* @param DoliDB $db objet base de donnee
* @param Object $object Object fichinter
* @param string $modele force le modele a utiliser ('' par defaut)
* @param Translate $outputlangs objet lang a utiliser pour traduction
* @param int $hidedetails Hide details of lines
* @param int $hidedesc Hide description
* @param int $hideref Hide ref
* @return int 0 if KO, 1 if OK
*/
function action_create($db, $object, $modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
{
global $conf,$langs,$user;
$langs->load("action");
$error=0;
$srctemplatepath='';
// Positionne modele sur le nom du modele de fichinter a utiliser
if (! dol_strlen($modele))
{
if (! empty($conf->global->ACTION_EVENT_ADDON_PDF))
{
$modele = $conf->global->ACTION_EVENT_ADDON_PDF;
}
else
{
$modele = 'soleil';
}
}
// If selected modele is a filename template (then $modele="modelname:filename")
$tmp=explode(':',$modele,2);
if (! empty($tmp[1]))
{
$modele=$tmp[0];
$srctemplatepath=$tmp[1];
}
// Search template files
$file=''; $classname=''; $filefound=0;
$dirmodels=array('/');
if (is_array($conf->modules_parts['models'])) $dirmodels=array_merge($dirmodels,$conf->modules_parts['models']);
foreach($dirmodels as $reldir)
{
foreach(array('doc','pdf') as $prefix)
{
$file = $prefix."_".$modele.".modules.php";
// On verifie l'emplacement du modele
$file=dol_buildpath($reldir."core/modules/action/doc/".$file,0);
if (file_exists($file))
{
$filefound=1;
$classname=$prefix.'_'.$modele;
break;
}
}
if ($filefound) break;
}
// Charge le modele
if ($filefound)
{
require_once $file;
$obj = new $classname($db);
// We save charset_output to restore it because write_file can change it if needed for
// output format that does not support UTF8.
$sav_charset_output=$outputlangs->charset_output;
if ($obj->write_file($object, $outputlangs, $srctemplatepath, $hidedetails, $hidedesc, $hideref) > 0)
{
$outputlangs->charset_output=$sav_charset_output;
// We delete old preview
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
dol_delete_preview($object);
return 1;
}
else
{
$outputlangs->charset_output=$sav_charset_output;
dol_print_error($db,"action_pdf_create Error: ".$obj->error);
return 0;
}
}
else
{
print $langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists",$file);
return 0;
}
}

View File

@ -130,7 +130,7 @@ class mod_barcode_product_standard extends ModeleNumRefBarCode
* @param string $type type of barcode (EAN, ISBN, ...)
* @return string Value if OK, '' if module not configured, <0 if KO
*/
function getNextValue($objproduct,$type='')
function getNextValue($objproduct=null,$type='')
{
global $db,$conf;

View File

@ -91,7 +91,7 @@ abstract class ModeleNumRefBarCode
* @param int $type Type
* @return string Value
*/
function getNextValue($objsoc=0,$type=-1)
function getNextValue($objsoc=null,$type=-1)
{
global $langs;
return $langs->trans("Function_getNextValue_InModuleNotWorking");

View File

@ -200,7 +200,7 @@ class mailing_advthirdparties extends MailingTargets
* For example if this selector is used to extract 500 different
* emails from a text file, this function must return 500.
*
* @param string $sql Sql request to use
* @param string $sql Not use here
* @return int Nb of recipients
*/
function getNbOfRecipients($sql='')

View File

@ -392,14 +392,14 @@ class modAgenda extends DolibarrModules
$this->export_sql_start[$r]='SELECT DISTINCT ';
$this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'actioncomm as ac';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_actioncomm as cac on ac.fk_action = cac.id';
if(!$user->rights->agenda->allactions->read) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_resources acr on ac.id = acr.fk_actioncomm';
if (empty($user->rights->agenda->allactions->read)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_resources acr on ac.id = acr.fk_actioncomm';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'socpeople as sp on ac.fk_contact = sp.rowid';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s on ac.fk_soc = s.rowid';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as co on s.fk_pays = co.rowid';
$this->export_sql_end[$r] .=' WHERE ac.entity IN ('.getEntity('agenda',1).')';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' AND (sc.fk_user = '.$user->id.' OR ac.fk_soc IS NULL)';
if(!$user->rights->agenda->allactions->read) $this->export_sql_end[$r] .=' AND acr.fk_element = '.$user->id;
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' AND (sc.fk_user = '.$user->id.' OR ac.fk_soc IS NULL)';
if (empty($user->rights->agenda->allactions->read)) $this->export_sql_end[$r] .=' AND acr.fk_element = '.$user->id;
$this->export_sql_end[$r] .=' ORDER BY ac.datep';
}

View File

@ -191,7 +191,7 @@ class modCommande extends DolibarrModules
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$this->export_sql_start[$r]='SELECT DISTINCT ';
$this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'societe as s';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON s.fk_departement = d.rowid';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as co ON s.fk_pays = co.rowid,';
$this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'commande as c';
@ -205,7 +205,7 @@ class modCommande extends DolibarrModules
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra3 on p.rowid = extra3.fk_object';
$this->export_sql_end[$r] .=' WHERE c.fk_soc = s.rowid AND c.rowid = cd.fk_commande';
$this->export_sql_end[$r] .=' AND c.entity IN ('.getEntity('commande',1).')';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' AND sc.fk_user = '.$user->id;
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' AND sc.fk_user = '.$user->id;
}

View File

@ -127,13 +127,12 @@ class modDeplacement extends DolibarrModules
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
$this->export_sql_end[$r] .=' WHERE d.fk_user = u.rowid';
$this->export_sql_end[$r] .=' AND d.entity IN ('.getEntity('deplacement',1).')';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' AND (sc.fk_user = '.$user->id.' OR d.fk_soc IS NULL)';
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' AND (sc.fk_user = '.$user->id.' OR d.fk_soc IS NULL)';
$childids = $user->getAllChildIds();
$childids[]=$user->id;
if (!$user->rights->deplacement->readall && !$user->rights->deplacement->lire_tous) $sql.=' AND d.fk_user IN ('.join(',',$childids).')';
if (empty($user->rights->deplacement->readall) && empty($user->rights->deplacement->lire_tous)) $sql.=' AND d.fk_user IN ('.join(',',$childids).')';
}

View File

@ -205,7 +205,7 @@ class modFacture extends DolibarrModules
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$this->export_sql_start[$r]='SELECT DISTINCT ';
$this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'societe as s';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c on s.fk_pays = c.rowid,';
$this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'facture as f';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'projet as pj ON f.fk_projet = pj.rowid';
@ -234,7 +234,7 @@ class modFacture extends DolibarrModules
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$this->export_sql_start[$r]='SELECT DISTINCT ';
$this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'societe as s';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c on s.fk_pays = c.rowid,';
$this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'facture as f';
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'projet as pj ON f.fk_projet = pj.rowid';
@ -248,7 +248,7 @@ class modFacture extends DolibarrModules
$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'bank_account as ba ON ba.rowid = b.fk_account';
$this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid';
$this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('facture',1).')';
if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' AND sc.fk_user = '.$user->id;
if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' AND sc.fk_user = '.$user->id;
$r++;
}

View File

@ -81,7 +81,7 @@ class modMargin extends DolibarrModules
// Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',1),
// 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1)
// );
$this->const = array(0=>array('MARGIN_TYPE','chaine','1','Rule for margin calculation by default',0,'current',0)); // List of particular constants to add when module is enabled
$this->const = array(0=>array('MARGIN_TYPE','chaine','costprice','Rule for margin calculation by default',0,'current',0)); // List of particular constants to add when module is enabled
// New pages on tabs
$this->tabs = array(

View File

@ -108,8 +108,7 @@ class modPrinting extends DolibarrModules
$this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=home,fk_leftmenu=admintools', // Put 0 if this is a top menu
'type'=>'left', // This is a Top menu entry
'titre'=>'MenuDirectPrinting',
'mainmenu'=>'printing',
'url'=>'/printing/index.php',
'url'=>'/printing/index.php?mainmenu=home&leftmenu=admintools',
'langs'=>'printing', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
'position'=>300,
'enabled'=>'$conf->printing->enabled && $leftmenu==\'admintools\'',

View File

@ -108,25 +108,26 @@ class doc_generic_project_odt extends ModelePDFProjects
*
* @param Project $object Main object to use as data source
* @param Translate $outputlangs Lang object to use for output
* @param string $array_key Name of the key for return array
* @return array Array of substitution
*/
function get_substitutionarray_object($object,$outputlangs)
function get_substitutionarray_object($object,$outputlangs,$array_key='object')
{
global $conf;
$resarray=array(
'object_id'=>$object->id,
'object_ref'=>$object->ref,
'object_title'=>$object->title,
'object_description'=>$object->description,
'object_date_creation'=>dol_print_date($object->date_c,'day'),
'object_date_modification'=>dol_print_date($object->date_m,'day'),
'object_date_start'=>dol_print_date($object->date_start,'day'),
'object_date_end'=>dol_print_date($object->date_end,'day'),
'object_note_private'=>$object->note_private,
'object_note_public'=>$object->note_public,
'object_public'=>$object->public,
'object_statut'=>$object->getLibStatut()
$array_key.'_id'=>$object->id,
$array_key.'_ref'=>$object->ref,
$array_key.'_title'=>$object->title,
$array_key.'_description'=>$object->description,
$array_key.'_date_creation'=>dol_print_date($object->date_c,'day'),
$array_key.'_date_modification'=>dol_print_date($object->date_m,'day'),
$array_key.'_date_start'=>dol_print_date($object->date_start,'day'),
$array_key.'_date_end'=>dol_print_date($object->date_end,'day'),
$array_key.'_note_private'=>$object->note_private,
$array_key.'_note_public'=>$object->note_public,
$array_key.'_public'=>$object->public,
$array_key.'_statut'=>$object->getLibStatut()
);
// Retrieve extrafields

View File

@ -109,25 +109,26 @@ class doc_generic_task_odt extends ModelePDFTask
*
* @param Project $object Main object to use as data source
* @param Translate $outputlangs Lang object to use for output
* @param string $array_key Name of the key for return array
* @return array Array of substitution
*/
function get_substitutionarray_object($object,$outputlangs)
function get_substitutionarray_object($object,$outputlangs,$array_key='object')
{
global $conf;
$resarray=array(
'object_id'=>$object->id,
'object_ref'=>$object->ref,
'object_title'=>$object->title,
'object_description'=>$object->description,
'object_date_creation'=>dol_print_date($object->date_c,'day'),
'object_date_modification'=>dol_print_date($object->date_m,'day'),
'object_date_start'=>dol_print_date($object->date_start,'day'),
'object_date_end'=>dol_print_date($object->date_end,'day'),
'object_note_private'=>$object->note_private,
'object_note_public'=>$object->note_public,
'object_public'=>$object->public,
'object_statut'=>$object->getLibStatut()
$array_key.'_id'=>$object->id,
$array_key.'_ref'=>$object->ref,
$array_key.'_title'=>$object->title,
$array_key.'_description'=>$object->description,
$array_key.'_date_creation'=>dol_print_date($object->date_c,'day'),
$array_key.'_date_modification'=>dol_print_date($object->date_m,'day'),
$array_key.'_date_start'=>dol_print_date($object->date_start,'day'),
$array_key.'_date_end'=>dol_print_date($object->date_end,'day'),
$array_key.'_note_private'=>$object->note_private,
$array_key.'_note_public'=>$object->note_public,
$array_key.'_public'=>$object->public,
$array_key.'_statut'=>$object->getLibStatut()
);
// Retrieve extrafields

View File

@ -106,11 +106,14 @@ abstract class ModeleNumRefSuppliersInvoices
return true;
}
/** Returns next value assigned
*
* @return string Valeur
*/
function getNextValue()
/** Returns next value assigned
*
* @param Societe $objsoc Object third party
* @param Object $object Object
* @param string $mode 'next' for next value or 'last' for last value
* @return string Value if OK, 0 if KO
*/
function getNextValue($objsoc,$object,$mode)
{
global $langs;
return $langs->trans("NotAvailable");

View File

@ -63,7 +63,8 @@ class InterfaceLogevents extends DolibarrTriggers
if ($action == 'USER_LOGIN')
{
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
$langs->load("users");
// Initialisation donnees (date,duree,texte,desc)
$text="(UserLogged,".$object->login.")";
$text.=(empty($object->trigger_mesg)?'':' - '.$object->trigger_mesg);
@ -82,6 +83,7 @@ class InterfaceLogevents extends DolibarrTriggers
{
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
$langs->load("users");
// Initialisation donnees (date,duree,texte,desc)
$text="(UserLogoff,".$object->login.")";
$desc="(UserLogoff,".$object->login.")";

View File

@ -280,68 +280,82 @@ if (empty($reshook))
for ($i=0;$i<$num;$i++)
{
$product_type=($lines[$i]->product_type?$lines[$i]->product_type:0);
$product_type=($lines[$i]->product_type?$lines[$i]->product_type:Product::TYPE_PRODUCT);
if ($product_type == 1 || !empty($conf->global->FICHINTER_PRINT_PRODUCTS)) { //only services except if config includes products
// service prédéfini
if ($product_type == Product::TYPE_SERVICE || !empty($conf->global->FICHINTER_PRINT_PRODUCTS)) { //only services except if config includes products
$duration = 3600; // Default to one hour
// Predefined products & services
if ($lines[$i]->fk_product > 0)
{
$prod = new Product($db);
$prod->id = $lines[$i]->fk_product;
// Define output language
if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
{
$prod = new Product($db);
$prod->id=$lines[$i]->fk_product;
if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
$prod->getMultiLangs();
// We show if duration is present on service (so we get it)
$prod->fetch($lines[$i]->fk_product);
if ($prod->duration_value && $prod->duration_unit == 'h' && $conf->global->FICHINTER_USE_SERVICE_DURATION)
{
$durationproduct=$prod->duration_value * 3600 * $lines[$i]->qty;
}
else
$durationproduct=3600;
$outputlangs = $langs;
$newlang='';
if (empty($newlang) && GETPOST('lang_id')) $newlang=GETPOST('lang_id');
if (empty($newlang)) $newlang=$srcobject->client->default_lang;
if (! empty($newlang))
{
if (! empty($newlang)) {
$outputlangs = new Translate("",$conf);
$outputlangs->setDefaultLang($newlang);
}
$label = (! empty($prod->multilangs[$outputlangs->defaultlang]["libelle"])) ? $prod->multilangs[$outputlangs->defaultlang]["libelle"] : $lines[$i]->product_label;
}
else
{
$label = $lines[$i]->product_label;
} else {
$prod->fetch($lines[$i]->fk_product);
$label .= $lines[$i]->product_label;
}
$desc = $label;
$desc .= ' ('.$langs->trans('Quantity').': '.$lines[$i]->qty.')';
}
else {
$desc = dol_htmlentitiesbr($lines[$i]->desc);
$desc .= ' ('.$langs->trans('Quantity').': '.$lines[$i]->qty.')';
if ($prod->duration_value && $conf->global->FICHINTER_USE_SERVICE_DURATION) {
switch ($prod->duration_unit) {
default:
case 'h':
$mult = 3600;
break;
case 'd':
$mult = 3600 * 24;
break;
case 'w':
$mult = 3600 * 24 * 7;
break;
case 'm':
$mult = (int) 3600 * 24 * (365 / 12); // Average month duration
break;
case 'y':
$mult = 3600 * 24 * 365;
break;
}
$duration = $prod->duration_value * $mult * $lines[$i]->qty;
}
$desc = $lines[$i]->product_ref;
$desc .= ' - ';
$desc .= $label;
$desc .= '<br>';
}
// Common part (predefined or free line)
$desc .= dol_htmlentitiesbr($lines[$i]->desc);
$desc .= '<br>';
$desc .= ' (' . $langs->trans('Quantity') . ': ' . $lines[$i]->qty . ')';
$timearray=dol_getdate(mktime());
$date_intervention=dol_mktime(0,0,0,$timearray['mon'],$timearray['mday'],$timearray['year']);
if ($product_type == 1)
{ //service
$duration = $durationproduct;
}
else
{ //product
if ($product_type == Product::TYPE_PRODUCT) {
$duration = 0;
}
$predef = '';
// Extrafields
$extrafieldsline = new ExtraFields($db);
$extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
$array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline, $predef);
$result = $object->addline(
$user,
$id,
@ -1046,7 +1060,7 @@ if ($action == 'create')
print '<form name="fichinter" action="'.$_SERVER['PHP_SELF'].'" method="POST">';
print '<table class="border" width="100%">';
print '<tr><td class="fieldrequired">'.$langs->trans("ThirdParty").'</td><td>';
print $form->select_company('','socid','',1,1);
print $form->select_company('','socid','','SelectThirdParty',1);
print '</td></tr>';
print '</table>';

View File

@ -87,19 +87,37 @@ $result=@include_once $conffile; // Keep @ because with some error reporting thi
if (! $result && ! empty($_SERVER["GATEWAY_INTERFACE"])) // If install not done and we are in a web session
{
// Note: If calling page was not into htdocs (index.php, ...), then this redirect will fails.
// There is no real solution, because the only way to know the apache url relative path is to have into conf file.
$TDir = explode('/', $_SERVER['PHP_SELF']);
$path = '';
$i = count($TDir);
while ($i--)
{
if (empty($TDir[$i]) || $TDir[$i] == 'htdocs') break;
if (substr($TDir[$i], -4, 4) == '.php') continue;
$path .= '../';
}
if (! empty($_SERVER["CONTEXT_PREFIX"])) // CONTEXT_PREFIX and CONTEXT_DOCUMENT_ROOT are not defined on all apache versions
{
$path=$_SERVER["CONTEXT_PREFIX"]; // example '/dolibarr/' when using an apache alias.
if (! preg_match('/\/$/', $path)) $path.='/';
}
else if (preg_match('/index\.php', $_SERVER['PHP_SELF']))
{
// When we ask index.php, we MUST BE SURE that $path is '' at the end. This is required to make install process
// when using apache alias like '/dolibarr/' that point to htdocs.
// Note: If calling page was an index.php not into htdocs (ie comm/index.php, ...), then this redirect will fails,
// but we don't want to change this because when URL is correct, we must be sure the redirect to install/index.php will be correct.
$path='';
}
else
{
// If what we look is not index.php, we can try to guess location of root. May not work all the time.
// There is no real solution, because the only way to know the apache url relative path is to have it into conf file.
// If it fails to find correct $path, then only solution is to ask user to enter the correct URL to index.php or install/index.php
$TDir = explode('/', $_SERVER['PHP_SELF']);
$path = '';
$i = count($TDir);
while ($i--)
{
if (empty($TDir[$i]) || $TDir[$i] == 'htdocs') break;
if ($TDir[$i] == 'dolibarr') break;
if (substr($TDir[$i], -4, 4) == '.php') continue;
$path .= '../';
}
}
header("Location: ".$path."install/index.php");
exit;
}

View File

@ -19,7 +19,7 @@
*/
/**
* \file htdocs/hrm/hrm.php
* \file htdocs/hrm/index.php
* \ingroup hrm
* \brief Home page for HRM area.
*/

View File

@ -1,53 +1,242 @@
/* Sample CSS for jsGanttImproved v1.7.3 */
div.gantt { font-family:tahoma, arial, verdana, Sans-serif; font-size:10px; color: #2F2F2F; }
// These are the class/styles used by various objects in GanttChart. However, Firefox has problems deciphering class style when DIVs are embedded in other DIVs.
.gantt table { border-collapse: collapse; }
.gantt td { padding: 0px; }
// GanttChart makes heavy use of embedded DIVS, thus the style are often embedded directly in the objects html. If this could be resolved with Firefox, it would
/* cell defaults */
.gmajorheading,
.gminorheading,
.gminorheadingwkend,
.gtaskcell,
.gtaskcellwkend { height: 19px; font-size: 12px; border: #efefef 1px solid; text-align: center; cursor: default }
.gtasklist { height: 19px; min-width: 5px; max-width: 5px; width: 5px; border: #efefef 1px solid; border-right: none; } /* all three width values set just to make sure - helps resizing code */
// make alot of the code look simpleer/cleaner without all the embedded styles
/* Additional values for some cell elements */
.gtaskheading,
.gmajorheading,
.gminorheading { background-color: #ffffff; font-weight: bold; font-size: 9px; white-space: nowrap; }
.gtaskcellwkend,
.gminorheadingwkend { background-color: #f7f7f7; font-weight: bold; font-size: 9px; white-space: nowrap; }
td.gtaskcell { text-align: left }
td.gspanning { border-left: none; border-right: none; }
.gtaskcelldiv { position: relative; }
/* Task list defaults */
.gtaskheading,
.gname,
.gtaskname,
.gresource,
.gduration,
.gpccomplete,
.gstartdate,
.genddate { height: 18px; white-space: nowrap; border: #efefef 1px solid; }
/* Additional values for some task list elements */
.gresource,
.gduration,
.gpccomplete,
.gstartdate div, /* needed for IE8 */
.gstartdate { text-align: center; min-width: 70px; max-width: 70px; width: 70px; font-size: 10px; }
.genddate div, /* needed for IE8 */
.genddate { text-align: center; min-width: 70px; max-width: 70px; width: 70px; font-size: 10px; }
.gtaskheading { text-align: center; }
.gtaskname div, /* needed for IE8 */
.gtaskname { min-width: 170px; max-width: 170px; width: 170px;/* font-size: 9px;*/ border-left: none; }
.gselector { text-align: left; white-space: nowrap; min-width: 170px; max-width: 170px; width: 170px; }
.gformlabel { position:relative; top:0px; cursor:pointer; border: #ffffff 1px solid; margin-left: 2px; padding-left: 2px; padding-right: 2px; }
span.gformlabel:hover,
span.gselected { background-color: #dbecff; border: #cccccc 1px solid;}
span.gfoldercollapse { color:#000000; cursor:pointer; font-weight:bold; font-size: 12px; font-family: Courier, "Courier New", monospace; }
.gtasktableh,
.gtasktable { border-right: #efefef 1px solid; }
.gcharttable { border: #efefef 1px solid; } /* for some reason firefox needs this */
/* Differentiate Group, Milestone and Ordinary task items (applied to row) */
.ggroupitem { background-color: #fbfbfb; font-weight: bold; }
.gmileitem,
.glineitem { background-color: #ffffff; }
/* highlight row (applied to row) */
.gitemhighlight td { background-image: none; background-color: #fffaaa;}
/* task bar caption text styles */
.gmilecaption,
.ggroupcaption,
.gcaption { font-weight: normal; font-size: 9px; text-align: left; white-space: nowrap; top:1px; position: absolute; top:2px; }
.ggroupcaption,
.gcaption { right: -126px; }
/* Task complete %age bar shared attributes */
.gtaskcomplete { float:left; overflow: hidden; }
/* Task complete %age bar */
.gtaskcomplete { height:5px; background-color:#000000; margin-top:4px; opacity:0.4; filter: alpha(opacity=40); }
/* Milestones */
.gmilestone { font-size: 14px; position: absolute; top: -2px; }
.gmdtop { top: 2px; overflow: hidden; width:0px; height:0px; border-bottom: 5px solid black; border-left: 5px solid transparent; border-top: 5px solid transparent; border-right: 5px solid transparent;}
.gmdbottom { top: 2px; overflow: hidden; width:0px; height:0px; border-top: 5px solid black; border-left: 5px solid transparent; border-bottom: 5px solid transparent; border-right: 5px solid transparent;}
/* Task bar shared attributes */
.ggroupblack,
.gtaskblue,
.gtaskred,
.gtaskgreen,
.gtaskyellow,
.gtaskpurple,
.gtaskpink { height: 13px; filter: alpha(opacity=90); opacity:0.9; margin-top: 1px; }
/* Task bars - ggroupblack is set as the default class on the task if it is undefined */
.ggroupblack { height: 7px; background: #000000; margin-top: 2px; }
.ggroupblackendpointleft { overflow: hidden; width:0px; height:0px; top: 2px; border-top: 4px solid black; border-left: 4px solid transparent; border-bottom: 4px solid transparent; border-right: 4px solid transparent; float: left; }
.ggroupblackendpointright { overflow: hidden; width:0px; height:0px; top: 2px; border-top: 4px solid black; border-left: 4px solid transparent; border-bottom: 4px solid transparent; border-right: 4px solid transparent; float: right; }
.ggroupblackcomplete { float:left; overflow: hidden; height:3px; filter: alpha(opacity=80); opacity:0.8; background-color:#777777; margin-top:2px; margin-bottom: 2px; }
.gtaskblue {
background: rgb(58,132,195); /* Old browsers */
background: linear-gradient(to bottom, rgba(58,132,195,1) 0%,rgba(65,154,214,1) 20%,rgba(75,184,240,1) 40%,rgba(58,139,194,1) 70%,rgba(38,85,139,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4bb8f0', endColorstr='#3a84c3',GradientType=0 ); /* IE6-9 */
}
.gtaskred {
background: rgb(196,58,58); /* Old browsers */
background: linear-gradient(to bottom, rgba(196,58,58,1) 0%,rgba(211,65,65,1) 20%,rgba(239,76,76,1) 40%,rgba(196,58,58,1) 70%,rgba(135,37,37,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4c4c', endColorstr='#c43a3a',GradientType=0 ); /* IE6-9 */
}
.gtaskgreen {
background: rgb(80,193,58); /* Old browsers */
background: linear-gradient(to bottom, rgba(80,193,58,1) 0%,rgba(88,209,64,1) 20%,rgba(102,237,75,1) 40%,rgba(80,193,58,1) 70%,rgba(53,132,37,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#66ED4B', endColorstr='#50c13a',GradientType=0 ); /* IE6-9 */
}
.gtaskyellow {
background: rgb(247,228,56); /* Old browsers */
background: linear-gradient(to bottom, rgba(247,228,56,1) 0%,rgba(239,239,55,1) 20%,rgba(255,255,58,1) 40%,rgba(242,236,55,1) 70%,rgba(241,218,54,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffff3a', endColorstr='#f7e438',GradientType=0 ); /* IE6-9 */
}
.gtaskpurple {
background: rgb(193,58,193); /* Old browsers */
background: linear-gradient(to bottom, rgba(193,58,193,1) 0%,rgba(211,65,211,1) 20%,rgba(239,76,239,1) 40%,rgba(193,58,193,1) 70%,rgba(137,38,137,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4cef', endColorstr='#892689',GradientType=0 ); /* IE6-9 */
}
.gtaskpink {
background: rgb(249,177,245); /* Old browsers */
background: linear-gradient(to bottom, rgba(249,177,245,1) 0%,rgba(247,192,243,1) 20%,rgba(247,202,244,1) 40%,rgba(249,192,246,1) 70%,rgba(252,174,247,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7caf4', endColorstr='#fcaef7',GradientType=0 ); /* IE6-9 */
}
.gtaskbluecomplete,
.gtaskredcomplete,
.gtaskgreencomplete,
.gtaskyellowcomplete,
.gtaskpurplecomplete,
.gtaskpinkcomplete { float:left; overflow: hidden; height:5px; filter: alpha(opacity=40); opacity:0.4; background-color: #000000; margin-top:4px; }
/* Printer friendly styles - we could use these all the time but they are not as pretty! */
/* note that "@media print" is not supported in IE6 or 7. Fully patched IE8 should be OK */
@media print {
.ggroupblack { height:0px; border-top: 7px solid; border-color: #000000; }
.gtaskblue { height:0px; border-top: 13px solid; border-color: rgb(58,132,195); }
.gtaskred { height:0px; border-top: 13px solid; border-color: rgb(196,58,58); }
.gtaskgreen { height:0px; border-top: 13px solid; border-color: rgb(80,193,58); }
.gtaskyellow { height:0px; border-top: 13px solid; border-color: rgb(247,228,56); }
.gtaskpurple { height:0px; border-top: 13px solid; border-color: rgb(193,58,193); }
.gtaskpink { height:0px; border-top: 13px solid; border-color: rgb(249,177,245); }
.gtaskbluecomplete,
.gtaskredcomplete,
.gtaskgreencomplete,
.gtaskyellowcomplete,
.gtaskpurplecomplete,
.gtaskpinkcomplete { height:0px; filter: alpha(opacity=40); opacity:0.4; margin-top: -9px; border-top: 5px solid; border-color: #000000; }
.ggroupblackcomplete { height: 0px; filter: alpha(opacity=80); opacity:0.8; margin-top:-5px; border-top:3px solid; border-color:#777777; }
}
/* END Task bar styles */
.glinev { border-left: 1px solid; width: 0px; }
.glineh { border-top: 1px solid; height: 0px; }
.gDepFS,
.gDepSS,
.gDepSF,
.gDepFF { border-color: #26558b; }
.gDepFSArw,
.gDepSSArw { overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid #26558b; border-top: 4px solid transparent; border-right: 4px solid transparent;}
.gDepFFArw,
.gDepSFArw { overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid transparent; border-top: 4px solid transparent; border-right: 4px solid #26558b;}
.gCurDate { border-color: #0000ff; }
div.gtaskbarcontainer { z-index: 1; position: absolute; top: 0px }
..gantt { font-family:tahoma, arial, verdana; font-size:10px;}
.JSGanttToolTip {position: absolute; display: block; z-index: 2;}
.JSGanttToolTipcont {font-family: tahoma, arial, verdana; font-size: 10px; display: block; background: #ffffff; color: #656565}
.gTaskInfo {background: #dbecff; width: 400px; border: #656565 1px solid; border-radius: 10px; padding: 4px 6px 4px 6px; float: left;}
.gTtTitle {display: block; font-size: 12px; font-weight: bold; color: #404040; margin-left: 4px; margin-bottom: 1em;}
.gTaskLabel {font-size: 11px; font-weight: bold; color: #656565; margin-left: 4px;}
.gTaskText {position:absolute; left: 90px; padding-top: 1px; font-size: 10px; font-weight: normal; color: #656565;}
.gTaskNotes {font-size: 11px; font-weight: normal; color: #323232; padding: 0 15px; display: block;}
.gTIn {padding-top: 10px;}
..gdatehead { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #efefef 1px solid; HEIGHT: 18px }
.gantt { min-width: 1064px; /* 2x LC width */ }
.gchartcontainer { padding-left: 532px; /* LC width */ }
.gcontainercol { position: relative; float: left; } /* Add a max-height value here if wanted */
.glistgrid { width: 532px; /* LC width */ margin-left: -100%; right: 532px; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; }
.glistlbl { width: 532px; /* LC width */ margin-left: -100%; right: 532px; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; }
.glabelfooter { clear: both; }
.ggridfooter { clear: both; }
..ghead { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #efefef 1px solid; WIDTH: 24px; HEIGHT: 20px }
/*.rhscrpad { width: 150px; position: absolute; top: 0px; height: 1px; }*/
..gname { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; WIDTH: 18px; HEIGHT: 18px }
.gchartgrid { width: 100%; padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: auto; min-height: 0%; }
.gchartlbl { width: 100%; padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: hidden; }
..ghead A { FONT-SIZE: 10px; COLOR: #000000; TEXT-DECORATION: none }
/* Old Internet Explorer version hacks */
.gantt { _height: 100% } /* otherwise the chart disappears! */
div .gantt { _width: 1064px; } /* ie6 fixed width */
div.gchartlbl,
div.gchartgrid { _width: 532px; } /* ie6 fixed width */
div.glistlbl,
div.glistgrid {
*right: 0px; /* ie7 pulls the content too far left with the negative margin */
_right: 532px; /* but ie6 fixed width needs this */
_margin-left: -532px; /* ie6 fixed width */
}
div.gchartgrid { *padding-bottom: 20px; *overflow-y: hidden; } /* variable height design, no need for vertical scroll */
td.gmajorheading div { *overflow: hidden; } /* stops resizing fixed width columns if the text is too wide */
td.gspanning div { *overflow: hidden; } /* stops resizing fixed width columns if the text is too wide */
..gheadwkend A { FONT-SIZE: 10px; COLOR: #000000; TEXT-DECORATION: none }
/* border transparency tricks */
.ggroupblackendpointleft { _border-top: 4px solid black; _border-left: 4px solid pink; _border-bottom: 4px solid pink; _border-right: 4px solid pink; _filter: chroma(color=pink); }
.ggroupblackendpointright { _border-top: 4px solid black; _border-left: 4px solid pink; _border-bottom: 4px solid pink; _border-right: 4px solid pink;_filter: chroma(color=pink); }
..gheadwkend { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #efefef 1px solid; WIDTH: 24px; HEIGHT: 20px; background-color: #cfcfcf }
.gmdtop { _border-left: 5px solid pink; _border-top: 5px solid pink; _border-right: 5px solid pink; _filter: chroma(color=pink);}
.gmdbottom { _border-left: 5px solid pink; _border-bottom: 5px solid pink; _border-right: 5px solid pink; _filter: chroma(color=pink);}
..gfiller { BORDER-TOP: #efefef 1px solid; BORDER-LEFT: #efefef 1px solid; WIDTH: 18px; HEIGHT: 18px }
.gDepFSArw,
.gDepSSArw { _border-bottom: 4px solid pink; _border-top: 4px solid pink; _border-right: 4px solid pink; _filter: chroma(color=pink);}
.gDepFFArw,
.gDepSFArw { _border-bottom: 4px solid pink; _border-left: 4px solid pink; _border-top: 4px solid pink; _filter: chroma(color=pink);}
..gfillerwkend { BORDER-LEFT: #efefef 1px solid; WIDTH: 18px; HEIGHT: 18px; BACKGROUND-COLOR: #cfcfcf }
..gitem { BORDER-TOP: #cccccc 1px solid; WIDTH: 18px; HEIGHT: 18px }
..gitemwkend { BORDER-TOP: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; WIDTH: 18px; HEIGHT: 18px }
..gmilestone { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 14px; OVERFLOW: hidden; BORDER-LEFT: #efefef 1px solid; WIDTH: 18px; HEIGHT: 18px}
..gmilestonewkend { BORDER-TOP: #efefef 1px solid; BORDER-LEFT: #cccccc 1px solid; WIDTH: 18px; HEIGHT: 18px}
..btn { BORDER-RIGHT: #ffffff; BORDER-TOP: #ffffff; FONT-WEIGHT: bold; FONT-SIZE: 10px; BORDER-LEFT: #ffffff; WIDTH: 12px; COLOR: #cccccc; BORDER-BOTTOM: #ffffff; BACKGROUND-COLOR: #ffffff }
..hrcomplete { BORDER-RIGHT: #000000 2px solid; PADDING-RIGHT: 0px; BORDER-TOP: #000000 2px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: #000000 2px solid; WIDTH: 20px; COLOR: #000000; PADDING-TOP: 0px; BORDER-BOTTOM: #000000 2px solid; HEIGHT: 4px }
..hrhalfcomplete { BORDER-RIGHT: #000000 2px solid; BORDER-TOP: #000000 2px solid; BORDER-LEFT: #000000 2px solid; WIDTH: 9px; COLOR: #000000; BORDER-BOTTOM: #000000 2px solid; HEIGHT: 4px }
..gweekend { font-family:tahoma, arial, verdana; font-size:11px; background-color:#EEEEEE; text-align:center; }
..gtask { font-family:tahoma, arial, verdana; font-size:11px; background-color:#00FF00; text-align:center; }
..gday { font-family:tahoma, arial, verdana; font-size:11px; text-align:center; }
..gcomplete { background-color:black; height:5px; overflow: auto; margin-top:4px; }
DIV.scroll { BORDER-RIGHT: #efefef 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #efefef 1px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; OVERFLOW: hidden; BORDER-LEFT: #efefef 1px solid; WIDTH: 420px; PADDING-TOP: 0px; BORDER-BOTTOM: #efefef 1px solid; BACKGROUND-COLOR: #ffffff }
DIV.scroll2 { position:relative; PADDING-RIGHT: 0px; overflow:auto ;overflow-x:scroll;overflow-y:hidden; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; WIDTH: 482px; PADDING-TOP: 0px; BACKGROUND-COLOR: #ffffff }
/* Workaround for odd bug in old versions of Opera - no other browser needs this */
.glinediv {position: absolute; top: 0px; left: 0px;}
/* if using setUseSingleCell(1) the following is a suggested set of CSS3 styles to recreate the table grid - won't work on old browsers
.ggrouphour td,
.gmilehour td,
.gitemhour td { background-size: 19px 1px; background-image: linear-gradient(to left, #efefef, transparent 1px, transparent 18px); width: 100%; height: 19px; }
.ggroupday td,
.gmileday td,
.gitemday td { background-size: 19px 1px, 133px 1px; background-image: linear-gradient(to left, #efefef, transparent 1px, transparent 18px), linear-gradient(to left, #f7f7f7 39px, transparent 1px, transparent 92px); width: 100%; height: 19px; }
.ggroupweek td,
.gmileweek td,
.gitemweek td { background-size: 37px 1px; background-image: linear-gradient(to left, #efefef, transparent 1px, transparent 36px); width: 100%; height: 19px; }
.ggroupmonth td,
.gmilemonth td,
.gitemmonth td { background-size: 37px 1px; background-image: linear-gradient(to left, #efefef, transparent 1px, transparent 36px); width: 100%; height: 19px; }
.ggroupquarter td,
.gmilequarter td,
.gitemquarter td { background-size: 19px 1px; background-image: linear-gradient(to left, #efefef, transparent 1px, transparent 18px); width: 100%; height: 19px; }
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -47,7 +47,11 @@ if (!isset($conf->global->MAIN_INFO_SOCIETE_NOM) || empty($conf->global->MAIN_IN
header("Location: ".DOL_URL_ROOT."/admin/index.php?mainmenu=home&leftmenu=setup&mesg=setupnotcomplete");
exit;
}
if (count($conf->modules) <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)?1:$conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) // If only user module enabled
{
header("Location: ".DOL_URL_ROOT."/admin/index.php?mainmenu=home&leftmenu=setup&mesg=setupnotcomplete");
exit;
}
if (GETPOST('addbox')) // Add box (when submit is done from a form when ajax disabled)
{
require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php';

View File

@ -80,12 +80,12 @@ $arrayphpminversionerror = array(5,3,0);
$arrayphpminversionwarning = array(5,3,0);
if (versioncompare(versionphparray(),$arrayphpminversionerror) < 0) // Minimum to use (error if lower)
{
print '<img src="../theme/eldy/img/error.png" alt="Error"> '.$langs->trans("ErrorPHPVersionTooLow",'5.2.3');
print '<img src="../theme/eldy/img/error.png" alt="Error"> '.$langs->trans("ErrorPHPVersionTooLow", versiontostring($arrayphpminversionerror));
$checksok=0; // 0=error, 1=warning
}
else if (versioncompare(versionphparray(),$arrayphpminversionwarning) < 0) // Minimum supported (warning if lower)
{
print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPVersionTooLow",'5.3.0');
print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPVersionTooLow",versiontostring($arrayphpminversionwarning));
$checksok=0; // 0=error, 1=warning
}
else
@ -123,7 +123,7 @@ else
// Check if GD supported
if (! function_exists("imagecreate"))
/*if (! function_exists("imagecreate"))
{
$langs->load("errors");
print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPDoesNotSupportGD")."<br>\n";
@ -132,6 +132,19 @@ if (! function_exists("imagecreate"))
else
{
print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPSupportGD")."<br>\n";
}*/
// Check if Curl supported
if (! function_exists("curl_init"))
{
$langs->load("errors");
print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPDoesNotSupportCurl")."<br>\n";
// $checksok=0; // If image ko, just warning. So check must still be 1 (otherwise no way to install)
}
else
{
print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPSupportCurl")."<br>\n";
}

View File

@ -385,6 +385,9 @@ NoDetails=No more details in footer
DisplayCompanyInfo=Display company address
DisplayCompanyInfoAndManagers=Display company and manager names
EnableAndSetupModuleCron=If you want to have this recurring invoice beeing generated automatically, module *%s* must be enabled and correctly setup. Otherwise, generation of invoices must be done manually from this template with button *Create*. Note that even if you enabled automatic generation, you can still safely launch manual generation. Duplicates generation for same period are not possible.
ModuleCompanyCodeAquarium=Return an accountancy code built by:<br>%s followed by third party supplier code for a supplier accountancy code,<br>%s followed by third party customer code for a customer accountancy code.
ModuleCompanyCodePanicum=Return an empty accountancy code.
ModuleCompanyCodeDigitaria=Accountancy code depends on third party code. The code is composed of the character "C" in the first position followed by the first 5 characters of the third party code.
# Modules
Module0Name=& مجموعات المستخدمين
@ -468,7 +471,7 @@ Module510Desc=إدارة رواتب الموظفين والمدفوعات
Module520Name=قرض
Module520Desc=إدارة القروض
Module600Name=الإخطارات
Module600Desc=Send EMail notifications (triggered by some business events) to third-party contacts (setup defined on each thirdparty) or fixed emails
Module600Desc=Send EMail notifications (triggered by some business events) to users (setup defined on each user), third-party contacts (setup defined on each thirdparty) or fixed emails
Module700Name=التبرعات
Module700Desc=التبرعات إدارة
Module770Name=تقارير المصاريف
@ -1067,7 +1070,10 @@ HRMSetup=HRM وحدة الإعداد
CompanySetup=وحدة الإعداد للشركات
CompanyCodeChecker=نموذج للجيل الثالث لقانون الأحزاب ومراجعة (عميل أو مورد)
AccountCodeManager=رمز وحدة لتوليد المحاسبة (عميل أو مورد)
NotificationsDesc=رسائل البريد الإلكتروني ميزة الإخطارات يسمح لك بصمت لإرسال البريد الآلي، لبعض الأحداث Dolibarr. أهداف الإخطارات يمكن تعريفها: <br> * في ثلث الأطراف الاتصالات (العملاء أو الموردين)، اتصل واحد في وقت و. <br> * أو عن طريق وضع عناوين البريد الإلكتروني المستهدفة العالمية في صفحة إعداد حدة.
NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:
NotificationsDescUser=* per users, one user at time.
NotificationsDescContact=* per third parties contacts (customers or suppliers), one contact at time.
NotificationsDescGlobal=* or by setting global target emails in module setup page.
ModelModules=وثائق قوالب
DocumentModelOdt=توليد وثائق من OpenDocuments القوالب (.ODT أو .ODS ملفات أوفيس، كي أوفيس، برنامج TextEdit، ...)
WatermarkOnDraft=علامة مائية على مشروع الوثيقة
@ -1518,8 +1524,10 @@ ExpenseReportsSetup=إعداد تقارير المصروفات وحدة
TemplatePDFExpenseReports=قوالب المستند لتوليد حساب ثيقة تقرير
NoModueToManageStockIncrease=تم تفعيل أي وحدة قادرة على إدارة زيادة المخزون التلقائي. وسوف يتم زيادة الأسهم على الإدخال اليدوي فقط.
YouMayFindNotificationsFeaturesIntoModuleNotification=قد تجد خيارات لاشعارات بالبريد الالكتروني من خلال تمكين وتكوين وحدة "الإخطار".
ListOfNotificationsPerContact=قائمة الإشعارات لكل اسم *
ListOfNotificationsPerUser=List of notifications per user*
ListOfNotificationsPerUserOrContact=List of notifications per user* or per contact**
ListOfFixedNotifications=قائمة الإشعارات ثابت
GoOntoUserCardToAddMore=Go on the tab "Notifications" of a user to add or remove notifications for users
GoOntoContactCardToAddMore=الذهاب على علامة التبويب "التبليغات" من جهة اتصال مرشحين عن إضافة أو إزالة إخطارات للاتصالات / عناوين
Threshold=عتبة
BackupDumpWizard=المعالج لبناء قاعدة بيانات النسخ الاحتياطي ملف تفريغ

View File

@ -312,6 +312,7 @@ LatestRelatedBill=أحدث فاتورة ذات الصلة
WarningBillExist=تحذير، واحد أو أكثر من فاتورة موجودة بالفعل
MergingPDFTool=دمج أداة PDF
AmountPaymentDistributedOnInvoice=Payment amount distributed on invoice
PaymentOnDifferentThirdBills=Allow payments on different thirdparties bills but same parent company
PaymentNote=Payment note
ListOfPreviousSituationInvoices=List of previous situation invoices
ListOfNextSituationInvoices=List of next situation invoices

View File

@ -74,6 +74,7 @@ DefaultLang=اللغة افتراضيا
VATIsUsed=وتستخدم ضريبة القيمة المضافة
VATIsNotUsed=ضريبة القيمة المضافة لا يستخدم
CopyAddressFromSoc=ملء العنوان مع عنوان مرشحين عن
ThirdpartyNotCustomerNotSupplierSoNoRef=Thirdparty neither customer nor supplier, no available refering objects
##### Local Taxes #####
LocalTax1IsUsed=استخدام الضرائب الثانية
LocalTax1IsUsedES= يتم استخدام الطاقة المتجددة
@ -368,7 +369,8 @@ AllocateCommercial=Assigned to sales representative
Organization=المنظمة
FiscalYearInformation=معلومات عن السنة المالية
FiscalMonthStart=ابتداء من شهر من السنة المالية
YouMustCreateContactFirst=To be able to add email notifications, you must first insert email contacts for the third party
YouMustAssignUserMailFirst=You must create email for this user first to be able to add emails notifications for him.
YouMustCreateContactFirst=To be able to add email notifications, you must first define contacts with valid emails for the third party
ListSuppliersShort=قائمة الموردين
ListProspectsShort=قائمة التوقعات
ListCustomersShort=قائمة العملاء

View File

@ -14,6 +14,7 @@ ServiceStatusNotLateShort=لا تنتهي
ServiceStatusLate=على التوالي ، وانتهت
ServiceStatusLateShort=انتهى
ServiceStatusClosed=مغلقة
ShowContractOfService=Show contract of service
Contracts=عقود
ContractsSubscriptions=العقود / الاشتراكات
ContractsAndLine=العقود وخط عقود

View File

@ -192,5 +192,5 @@ WarningClickToDialUserSetupNotComplete=إعداد المعلومات ClickToDial
WarningFeatureDisabledWithDisplayOptimizedForBlindNoJs=ميزة تعطيل عندما تم تحسين عرض الإعداد لالعمياء شخص أو النص المتصفحات.
WarningPaymentDateLowerThanInvoiceDate=تاريخ الدفع (٪ ق) هو أقدم من تاريخ الفاتورة (٪ ق) لفاتورة%s.
WarningTooManyDataPleaseUseMoreFilters=عدد كبير جدا من البيانات (أكثر من خطوط%s). يرجى استخدام المزيد من المرشحات أو تعيين ثابت٪ الصورة إلى حد أعلى.
WarningSomeLinesWithNullHourlyRate=وسجلت بعض الأوقات من قبل المستخدمين عندما لم يتم تعريف معدل في الساعة. وقد استخدم قيمة 0 ولكن هذا قد يؤدي إلى تقييم خاطئ من الوقت الذي يقضيه.
WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent.
WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action.

View File

@ -86,6 +86,7 @@ DirectoryRecommendation=وrecommanded به لاستخدام دليل خارج ا
LoginAlreadyExists=موجود بالفعل
DolibarrAdminLogin=ادخل Dolibarr مشرف
AdminLoginAlreadyExists=Dolibarr حساب مشرف <b>'٪ ق'</b> موجود بالفعل.
FailedToCreateAdminLogin=Failed to create Dolibarr administrator account.
WarningRemoveInstallDir=تحذير ، لأسباب أمنية ، بعد تثبيت أو تحديث كاملة ، يجب إزالة <b>تثبيت أو إعادة تسمية الدليل على install.lock من أجل تجنب استخدام الخبيثة.</b>
FunctionNotAvailableInThisPHP=لا تتوفر على هذا PHP
ChoosedMigrateScript=اختار الهجرة سكريبت

View File

@ -111,7 +111,7 @@ NoNotificationsWillBeSent=إشعارات البريد الإلكتروني لا
ANotificationsWillBeSent=1 سيتم إرسال الإشعار عن طريق البريد الإلكتروني
SomeNotificationsWillBeSent=ق ٪ سوف يتم إرسال الإخطارات عبر البريد الإلكتروني
AddNewNotification=تفعيل هدفا إشعار البريد الإلكتروني الجديد
ListOfActiveNotifications=قائمة جميع الأهداف إشعار البريد الإلكتروني النشطة
ListOfActiveNotifications=List all active targets for email notification
ListOfNotificationsDone=أرسلت قائمة جميع اشعارات بالبريد الالكتروني
MailSendSetupIs=وقد تم تكوين إرسال البريد الإلكتروني الإعداد ل'٪ ق'. هذا الوضع لا يمكن أن تستخدم لإرسال إرساله عبر البريد الإلكتروني الشامل.
MailSendSetupIs2=يجب عليك أولا الذهاب، مع حساب مشرف، في القائمة٪ sHome - إعداد - رسائل البريد الإلكتروني٪ s إلى تغيير المعلمة <strong>'٪ ق'</strong> لاستخدام وضع '٪ ق'. مع هذا الوضع، يمكنك إدخال الإعداد خادم SMTP المقدمة من قبل موفر خدمة الإنترنت واستخدام قداس ميزة البريد الإلكتروني.

View File

@ -84,6 +84,7 @@ SeeAbove=أنظر فوق
HomeArea=المنطقة الرئيسية
LastConnexion=آخر إتصال
PreviousConnexion=الاتصال السابق
PreviousValue=Previous value
ConnectedOnMultiCompany=إتصال على البيئة
ConnectedSince=إتصال منذ
AuthenticationMode=وضع صحة المستندات

View File

@ -11,8 +11,10 @@ SharedProject=مشاريع مشتركة
PrivateProject=Project contacts
MyProjectsDesc=ويقتصر هذا الرأي على المشاريع التي تقوم على الاتصال (كل ما هو نوع).
ProjectsPublicDesc=هذا الرأي يعرض جميع المشاريع ويسمح لك قراءة.
TasksOnProjectsPublicDesc=This view presents all tasks on projects you are allowed to read.
ProjectsPublicTaskDesc=يمثل هذا العرض جميع المشاريع والمهام يسمح لك للقراءة.
ProjectsDesc=ويعرض هذا الرأي جميع المشاريع (أذونات المستخدم الخاص أعطى الصلاحية لعرض كل شيء).
TasksOnProjectsDesc=This view presents all tasks on all projects (your user permissions grant you permission to view everything).
MyTasksDesc=ويقتصر هذا الرأي على المشروعات أو المهام التي هي الاتصال للحصول على (ما هو نوع).
OnlyOpenedProject=المشاريع المفتوحة فقط مرئية (المشاريع في مشروع أو وضع مغلقة غير مرئية).
ClosedProjectsAreHidden=Closed projects are not visible.
@ -130,6 +132,9 @@ OpportunityProbability=Opportunity probability
OpportunityProbabilityShort=Opp. probab.
OpportunityAmount=مبلغ فرصة
OpportunityAmountShort=مقابل. كمية
OpportunityAmountAverageShort=Average Opp. amount
OpportunityAmountWeigthedShort=Weighted Opp. amount
WonLostExcluded=Won/Lost excluded
##### Types de contacts #####
TypeContact_project_internal_PROJECTLEADER=مشروع زعيم
TypeContact_project_external_PROJECTLEADER=مشروع زعيم

View File

@ -114,12 +114,14 @@ RecordMovement=سجل TRANSFERT
ReceivingForSameOrder=إيصالات لهذا النظام
StockMovementRecorded=تحركات الأسهم سجلت
RuleForStockAvailability=القواعد المتعلقة بمتطلبات الأسهم
StockMustBeEnoughForInvoice=يجب أن يكون مستوى مخزون كاف لإضافة منتج / خدمة الفاتورة
StockMustBeEnoughForOrder=يجب أن يكون مستوى مخزون كاف لإضافة منتج / خدمة النظام
StockMustBeEnoughForShipment= يجب أن يكون مستوى مخزون كاف لإضافة منتج / خدمة للشحن
StockMustBeEnoughForInvoice=Stock level must be enough to add product/service to invoice (check is done on current real stock when adding a line into invoice whatever is rule for automatic stock change)
StockMustBeEnoughForOrder=Stock level must be enough to add product/service to order (check is done on current real stock when adding a line into order whatever is rule for automatic stock change)
StockMustBeEnoughForShipment= Stock level must be enough to add product/service to shipment (check is done on current real stock when adding a line into shipment whatever is rule for automatic stock change)
MovementLabel=تسمية الحركة
InventoryCode=حركة المخزون أو كود
IsInPackage=الواردة في حزمة
WarehouseAllowNegativeTransfer=Stock can be negative
qtyToTranferIsNotEnough=You don't have enough stock from your source warehouse
ShowWarehouse=مشاهدة مستودع
MovementCorrectStock=تصحيح الأسهم للمنتج٪ الصورة
MovementTransferStock=نقل الأسهم من الناتج٪ الصورة إلى مستودع آخر

View File

@ -21,3 +21,5 @@ ViewSiteInNewTab=View site in new tab
ViewPageInNewTab=View page in new tab
SetAsHomePage=Set as Home page
RealURL=Real URL
ViewWebsiteInProduction=View web site using home URLs
SetHereVirtualHost=If you can set, on your web server, a dedicated virtual host with a root directory on <strong>%s</strong>, define here the virtual hostname so the preview will be done using this direct access instead of Dolibarr URLs wrapper.

View File

@ -385,6 +385,9 @@ NoDetails=No more details in footer
DisplayCompanyInfo=Display company address
DisplayCompanyInfoAndManagers=Display company and manager names
EnableAndSetupModuleCron=If you want to have this recurring invoice beeing generated automatically, module *%s* must be enabled and correctly setup. Otherwise, generation of invoices must be done manually from this template with button *Create*. Note that even if you enabled automatic generation, you can still safely launch manual generation. Duplicates generation for same period are not possible.
ModuleCompanyCodeAquarium=Return an accountancy code built by:<br>%s followed by third party supplier code for a supplier accountancy code,<br>%s followed by third party customer code for a customer accountancy code.
ModuleCompanyCodePanicum=Return an empty accountancy code.
ModuleCompanyCodeDigitaria=Accountancy code depends on third party code. The code is composed of the character "C" in the first position followed by the first 5 characters of the third party code.
# Modules
Module0Name=Потребители и групи
@ -468,7 +471,7 @@ Module510Desc=Management of employees salaries and payments
Module520Name=Loan
Module520Desc=Management of loans
Module600Name=Известия
Module600Desc=Send EMail notifications (triggered by some business events) to third-party contacts (setup defined on each thirdparty) or fixed emails
Module600Desc=Send EMail notifications (triggered by some business events) to users (setup defined on each user), third-party contacts (setup defined on each thirdparty) or fixed emails
Module700Name=Дарения
Module700Desc=Управление на дарения
Module770Name=Expense reports
@ -1067,7 +1070,10 @@ HRMSetup=HRM module setup
CompanySetup=Фирми модул за настройка
CompanyCodeChecker=Модул за контрагенти за генериране на кода и проверка (клиент или доставчик)
AccountCodeManager=Модул за генериране на отчетност код (клиент или доставчик)
NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:<br>* per third parties contacts (customers or suppliers), one contact at time.<br>* or by setting global target email addresses in module setup page.
NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:
NotificationsDescUser=* per users, one user at time.
NotificationsDescContact=* per third parties contacts (customers or suppliers), one contact at time.
NotificationsDescGlobal=* or by setting global target emails in module setup page.
ModelModules=Документи шаблони
DocumentModelOdt=Generate documents from OpenDocuments templates (.ODT or .ODS files for OpenOffice, KOffice, TextEdit,...)
WatermarkOnDraft=Воден знак върху проект на документ
@ -1518,8 +1524,10 @@ ExpenseReportsSetup=Setup of module Expense Reports
TemplatePDFExpenseReports=Document templates to generate expense report document
NoModueToManageStockIncrease=No module able to manage automatic stock increase has been activated. Stock increase will be done on manual input only.
YouMayFindNotificationsFeaturesIntoModuleNotification=You may find options for EMail notifications by enabling and configuring the module "Notification".
ListOfNotificationsPerContact=List of notifications per contact*
ListOfNotificationsPerUser=List of notifications per user*
ListOfNotificationsPerUserOrContact=List of notifications per user* or per contact**
ListOfFixedNotifications=List of fixed notifications
GoOntoUserCardToAddMore=Go on the tab "Notifications" of a user to add or remove notifications for users
GoOntoContactCardToAddMore=Go on the tab "Notifications" of a thirdparty contact to add or remove notifications for contacts/addresses
Threshold=Threshold
BackupDumpWizard=Wizard to build database backup dump file

View File

@ -312,6 +312,7 @@ LatestRelatedBill=Последна свързана фактура
WarningBillExist=Внимание, една или повече актури вече съществуват
MergingPDFTool=Инструмент за sliwane на PDF
AmountPaymentDistributedOnInvoice=Payment amount distributed on invoice
PaymentOnDifferentThirdBills=Allow payments on different thirdparties bills but same parent company
PaymentNote=Payment note
ListOfPreviousSituationInvoices=List of previous situation invoices
ListOfNextSituationInvoices=List of next situation invoices

View File

@ -74,6 +74,7 @@ DefaultLang=Език по подразбиране
VATIsUsed=ДДС се използва
VATIsNotUsed=ДДС не се използва
CopyAddressFromSoc=Попълнете адреса на контрагента
ThirdpartyNotCustomerNotSupplierSoNoRef=Thirdparty neither customer nor supplier, no available refering objects
##### Local Taxes #####
LocalTax1IsUsed=Използване на втора такса
LocalTax1IsUsedES= RE се използва
@ -368,7 +369,8 @@ AllocateCommercial=Assigned to sales representative
Organization=Организация
FiscalYearInformation=Информация за фискалната година
FiscalMonthStart=Начален месец на фискалната година
YouMustCreateContactFirst=To be able to add email notifications, you must first insert email contacts for the third party
YouMustAssignUserMailFirst=You must create email for this user first to be able to add emails notifications for him.
YouMustCreateContactFirst=To be able to add email notifications, you must first define contacts with valid emails for the third party
ListSuppliersShort=Списък на доставчиците
ListProspectsShort=Списък на потенциални
ListCustomersShort=Списък на клиенти

View File

@ -14,6 +14,7 @@ ServiceStatusNotLateShort=Не е изтекъл
ServiceStatusLate=Спринт, изтекъл
ServiceStatusLateShort=Изтекла
ServiceStatusClosed=Затворен
ShowContractOfService=Show contract of service
Contracts=Договори
ContractsSubscriptions=Contracts/Subscriptions
ContractsAndLine=Договори и договорни линии

View File

@ -192,5 +192,5 @@ WarningClickToDialUserSetupNotComplete=Настройките на информ
WarningFeatureDisabledWithDisplayOptimizedForBlindNoJs=Фунцкията е неактива, когато конфигурацията на показването е оптимизирана за незрящ човек или текстови браузери.
WarningPaymentDateLowerThanInvoiceDate=Датата на плащане (%s) е по-ранна от датата на фактуриране (%s) за фактура %s.
WarningTooManyDataPleaseUseMoreFilters=Прекалено много информация (повече от %s линии). Моля използвайте повече филтри или задайте за константата %s по-висок лимит.
WarningSomeLinesWithNullHourlyRate=Some times were recorded by users when their hourly rate was not defined. A value of 0 was used but this may result in wrong valuation of time spent.
WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent.
WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action.

View File

@ -86,6 +86,7 @@ DirectoryRecommendation=Препоръчва се да използвате ди
LoginAlreadyExists=Вече съществува
DolibarrAdminLogin=Администраторски вход в Dolibarr
AdminLoginAlreadyExists=Администраторския профил за Dolibarr '<b>%s</b>' вече съществува. Върнете се назад, ако искате да създадете друг.
FailedToCreateAdminLogin=Failed to create Dolibarr administrator account.
WarningRemoveInstallDir=Внимание, от съображения за сигурност, след като ведъж инсталирането или надграждането завърши, за да се избегне ново използване на инструментите за инсталиране, трябва да добавите файл наречен <b>install.lock</b> в директорията с документи на Dolibarr, за да се избегне злонамерена употреба.
FunctionNotAvailableInThisPHP=Не е наличено за това PHP
ChoosedMigrateScript=Изберете скрипт за миграция

View File

@ -111,7 +111,7 @@ NoNotificationsWillBeSent=Не са планирани за това събит
ANotificationsWillBeSent=1 уведомление ще бъде изпратено по имейл
SomeNotificationsWillBeSent=%s уведомления ще бъдат изпратени по имейл
AddNewNotification=Activate a new email notification target
ListOfActiveNotifications=List all active email notification targets
ListOfActiveNotifications=List all active targets for email notification
ListOfNotificationsDone=Списък на всички имейли, изпратени уведомления
MailSendSetupIs=Настройката за изпращането на имейл е била настроена на '%s'. Този режим не може да бъде използван за масове изпращане на имейли.
MailSendSetupIs2=Трябва първо да отидете, с административен акаунт, в меню %sНачало - Настройка - Имейли%s, за да промените параметър <strong>'%s'</strong> да използва режим '%s'. С този режим можете да въведете настройка на SMTP сървъра предоставен от вашия интернет доставчик и да използвате опцията за масово изпращане на имейли.

View File

@ -84,6 +84,7 @@ SeeAbove=Виж по-горе
HomeArea=Начало
LastConnexion=Последно свързване
PreviousConnexion=Предишно свързване
PreviousValue=Previous value
ConnectedOnMultiCompany=Свързан към обекта
ConnectedSince=Свързан от
AuthenticationMode=Режим на удостоверяване

View File

@ -11,8 +11,10 @@ SharedProject=Всички
PrivateProject=Project contacts
MyProjectsDesc=Тази гледна точка е ограничена до проекти, които са за контакт (какъвто и да е тип).
ProjectsPublicDesc=Този възглед представя всички проекти, по които могат да се четат.
TasksOnProjectsPublicDesc=This view presents all tasks on projects you are allowed to read.
ProjectsPublicTaskDesc=Този изглед показва всички проекти и задачи, които са ви позволени да прочетете.
ProjectsDesc=Този възглед представя всички проекти (потребителски разрешения ви даде разрешение да видите всичко).
TasksOnProjectsDesc=This view presents all tasks on all projects (your user permissions grant you permission to view everything).
MyTasksDesc=Тази гледна точка е ограничена до проекти или задачи, които са контакт (какъвто и да е тип).
OnlyOpenedProject=Само отворени проекти са видими (планирани проекти или със затворен статус не са видими).
ClosedProjectsAreHidden=Closed projects are not visible.
@ -130,6 +132,9 @@ OpportunityProbability=Opportunity probability
OpportunityProbabilityShort=Opp. probab.
OpportunityAmount=Opportunity amount
OpportunityAmountShort=Opp. amount
OpportunityAmountAverageShort=Average Opp. amount
OpportunityAmountWeigthedShort=Weighted Opp. amount
WonLostExcluded=Won/Lost excluded
##### Types de contacts #####
TypeContact_project_internal_PROJECTLEADER=Ръководител на проекта
TypeContact_project_external_PROJECTLEADER=Ръководител на проекта

View File

@ -114,12 +114,14 @@ RecordMovement=Record transfert
ReceivingForSameOrder=Receipts for this order
StockMovementRecorded=Stock movements recorded
RuleForStockAvailability=Rules on stock requirements
StockMustBeEnoughForInvoice=Stock level must be enough to add product/service to invoice
StockMustBeEnoughForOrder=Stock level must be enough to add product/service to order
StockMustBeEnoughForShipment= Stock level must be enough to add product/service to shipment
StockMustBeEnoughForInvoice=Stock level must be enough to add product/service to invoice (check is done on current real stock when adding a line into invoice whatever is rule for automatic stock change)
StockMustBeEnoughForOrder=Stock level must be enough to add product/service to order (check is done on current real stock when adding a line into order whatever is rule for automatic stock change)
StockMustBeEnoughForShipment= Stock level must be enough to add product/service to shipment (check is done on current real stock when adding a line into shipment whatever is rule for automatic stock change)
MovementLabel=Label of movement
InventoryCode=Movement or inventory code
IsInPackage=Contained into package
WarehouseAllowNegativeTransfer=Stock can be negative
qtyToTranferIsNotEnough=You don't have enough stock from your source warehouse
ShowWarehouse=Show warehouse
MovementCorrectStock=Stock correction for product %s
MovementTransferStock=Stock transfer of product %s into another warehouse

View File

@ -21,3 +21,5 @@ ViewSiteInNewTab=View site in new tab
ViewPageInNewTab=View page in new tab
SetAsHomePage=Set as Home page
RealURL=Real URL
ViewWebsiteInProduction=View web site using home URLs
SetHereVirtualHost=If you can set, on your web server, a dedicated virtual host with a root directory on <strong>%s</strong>, define here the virtual hostname so the preview will be done using this direct access instead of Dolibarr URLs wrapper.

View File

@ -385,6 +385,9 @@ NoDetails=No more details in footer
DisplayCompanyInfo=Display company address
DisplayCompanyInfoAndManagers=Display company and manager names
EnableAndSetupModuleCron=If you want to have this recurring invoice beeing generated automatically, module *%s* must be enabled and correctly setup. Otherwise, generation of invoices must be done manually from this template with button *Create*. Note that even if you enabled automatic generation, you can still safely launch manual generation. Duplicates generation for same period are not possible.
ModuleCompanyCodeAquarium=Return an accountancy code built by:<br>%s followed by third party supplier code for a supplier accountancy code,<br>%s followed by third party customer code for a customer accountancy code.
ModuleCompanyCodePanicum=Return an empty accountancy code.
ModuleCompanyCodeDigitaria=Accountancy code depends on third party code. The code is composed of the character "C" in the first position followed by the first 5 characters of the third party code.
# Modules
Module0Name=Users & groups
@ -468,7 +471,7 @@ Module510Desc=Management of employees salaries and payments
Module520Name=Loan
Module520Desc=Management of loans
Module600Name=Notifications
Module600Desc=Send EMail notifications (triggered by some business events) to third-party contacts (setup defined on each thirdparty) or fixed emails
Module600Desc=Send EMail notifications (triggered by some business events) to users (setup defined on each user), third-party contacts (setup defined on each thirdparty) or fixed emails
Module700Name=Donations
Module700Desc=Donation management
Module770Name=Expense reports
@ -1067,7 +1070,10 @@ HRMSetup=HRM module setup
CompanySetup=Companies module setup
CompanyCodeChecker=Module for third parties code generation and checking (customer or supplier)
AccountCodeManager=Module for accountancy code generation (customer or supplier)
NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:<br>* per third parties contacts (customers or suppliers), one contact at time.<br>* or by setting global target email addresses in module setup page.
NotificationsDesc=EMails notifications feature allows you to silently send automatic mail, for some Dolibarr events. Targets of notifications can be defined:
NotificationsDescUser=* per users, one user at time.
NotificationsDescContact=* per third parties contacts (customers or suppliers), one contact at time.
NotificationsDescGlobal=* or by setting global target emails in module setup page.
ModelModules=Documents templates
DocumentModelOdt=Generate documents from OpenDocuments templates (.ODT or .ODS files for OpenOffice, KOffice, TextEdit,...)
WatermarkOnDraft=Watermark on draft document
@ -1518,8 +1524,10 @@ ExpenseReportsSetup=Setup of module Expense Reports
TemplatePDFExpenseReports=Document templates to generate expense report document
NoModueToManageStockIncrease=No module able to manage automatic stock increase has been activated. Stock increase will be done on manual input only.
YouMayFindNotificationsFeaturesIntoModuleNotification=You may find options for EMail notifications by enabling and configuring the module "Notification".
ListOfNotificationsPerContact=List of notifications per contact*
ListOfNotificationsPerUser=List of notifications per user*
ListOfNotificationsPerUserOrContact=List of notifications per user* or per contact**
ListOfFixedNotifications=List of fixed notifications
GoOntoUserCardToAddMore=Go on the tab "Notifications" of a user to add or remove notifications for users
GoOntoContactCardToAddMore=Go on the tab "Notifications" of a thirdparty contact to add or remove notifications for contacts/addresses
Threshold=Threshold
BackupDumpWizard=Wizard to build database backup dump file

View File

@ -312,6 +312,7 @@ LatestRelatedBill=Latest related invoice
WarningBillExist=Warning, one or more invoice already exist
MergingPDFTool=Merging PDF tool
AmountPaymentDistributedOnInvoice=Payment amount distributed on invoice
PaymentOnDifferentThirdBills=Allow payments on different thirdparties bills but same parent company
PaymentNote=Payment note
ListOfPreviousSituationInvoices=List of previous situation invoices
ListOfNextSituationInvoices=List of next situation invoices

View File

@ -74,6 +74,7 @@ DefaultLang=Language by default
VATIsUsed=VAT is used
VATIsNotUsed=VAT is not used
CopyAddressFromSoc=Fill address with thirdparty address
ThirdpartyNotCustomerNotSupplierSoNoRef=Thirdparty neither customer nor supplier, no available refering objects
##### Local Taxes #####
LocalTax1IsUsed=Use second tax
LocalTax1IsUsedES= RE is used
@ -368,7 +369,8 @@ AllocateCommercial=Assigned to sales representative
Organization=Organization
FiscalYearInformation=Information on the fiscal year
FiscalMonthStart=Starting month of the fiscal year
YouMustCreateContactFirst=To be able to add email notifications, you must first insert email contacts for the third party
YouMustAssignUserMailFirst=You must create email for this user first to be able to add emails notifications for him.
YouMustCreateContactFirst=To be able to add email notifications, you must first define contacts with valid emails for the third party
ListSuppliersShort=List of suppliers
ListProspectsShort=List of prospects
ListCustomersShort=List of customers

View File

@ -14,6 +14,7 @@ ServiceStatusNotLateShort=Not expired
ServiceStatusLate=Running, expired
ServiceStatusLateShort=Expired
ServiceStatusClosed=Closed
ShowContractOfService=Show contract of service
Contracts=Contracts
ContractsSubscriptions=Contracts/Subscriptions
ContractsAndLine=Contracts and line of contracts

View File

@ -192,5 +192,5 @@ WarningClickToDialUserSetupNotComplete=Setup of ClickToDial information for your
WarningFeatureDisabledWithDisplayOptimizedForBlindNoJs=Feature disabled when display setup is optimized for blind person or text browsers.
WarningPaymentDateLowerThanInvoiceDate=Payment date (%s) is earlier than invoice date (%s) for invoice %s.
WarningTooManyDataPleaseUseMoreFilters=Too many data (more than %s lines). Please use more filters or set the constant %s to a higher limit.
WarningSomeLinesWithNullHourlyRate=Some times were recorded by users when their hourly rate was not defined. A value of 0 was used but this may result in wrong valuation of time spent.
WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent.
WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action.

View File

@ -86,6 +86,7 @@ DirectoryRecommendation=It is recommanded to use a directory outside of your dir
LoginAlreadyExists=Already exists
DolibarrAdminLogin=Dolibarr admin login
AdminLoginAlreadyExists=Dolibarr administrator account '<b>%s</b>' already exists. Go back, if you want to create another one.
FailedToCreateAdminLogin=Failed to create Dolibarr administrator account.
WarningRemoveInstallDir=Warning, for security reasons, once the install or upgrade is complete, to avoid using install tools again, you should add a file called <b>install.lock</b> into Dolibarr document directory, in order to avoid malicious use of it.
FunctionNotAvailableInThisPHP=Not available on this PHP
ChoosedMigrateScript=Choose migration script

View File

@ -111,7 +111,7 @@ NoNotificationsWillBeSent=No email notifications are planned for this event and
ANotificationsWillBeSent=1 notification will be sent by email
SomeNotificationsWillBeSent=%s notifications will be sent by email
AddNewNotification=Activate a new email notification target
ListOfActiveNotifications=List all active email notification targets
ListOfActiveNotifications=List all active targets for email notification
ListOfNotificationsDone=List all email notifications sent
MailSendSetupIs=Configuration of email sending has been setup to '%s'. This mode can't be used to send mass emailing.
MailSendSetupIs2=You must first go, with an admin account, into menu %sHome - Setup - EMails%s to change parameter <strong>'%s'</strong> to use mode '%s'. With this mode, you can enter setup of the SMTP server provided by your Internet Service Provider and use Mass emailing feature.

Some files were not shown because too many files have changed in this diff Show More