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

This commit is contained in:
Laurent Destailleur 2019-04-08 14:09:29 +02:00
commit 2174e70414
30 changed files with 4106 additions and 691 deletions

View File

@ -31,7 +31,6 @@ addons:
- pgloader - pgloader
php: php:
- '5.4'
- '5.5' - '5.5'
- '5.6' - '5.6'
- '7.0' - '7.0'
@ -62,8 +61,6 @@ matrix:
- php: nightly - php: nightly
# We exclude some combinations not usefull to save Travis CPU # We exclude some combinations not usefull to save Travis CPU
exclude: exclude:
- php: '5.5'
env: DB=mariadb
- php: '5.6' - php: '5.6'
env: DB=mariadb env: DB=mariadb
- php: '7.0' - php: '7.0'
@ -72,8 +69,6 @@ matrix:
env: DB=mariadb env: DB=mariadb
- php: '7.2' - php: '7.2'
env: DB=mariadb env: DB=mariadb
- php: '5.5'
env: DB=postgresql
- php: '5.6' - php: '5.6'
env: DB=postgresql env: DB=postgresql
- php: '7.0' - php: '7.0'

328
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -142,7 +142,11 @@ class Facturation
$this->montantRemise($montant_remise_ht); $this->montantRemise($montant_remise_ht);
$newcartarray=$_SESSION['poscart']; $newcartarray=$_SESSION['poscart'];
$i=count($newcartarray);
$i = 0;
if (!is_null($newcartarray) && !empty($newcartarray)) {
$i=count($newcartarray);
}
$newcartarray[$i]['id']=$i; $newcartarray[$i]['id']=$i;
$newcartarray[$i]['ref']=$product->ref; $newcartarray[$i]['ref']=$product->ref;

View File

@ -983,19 +983,42 @@ class Categorie extends CommonObject
* fulllabel = nom avec chemin complet de la categorie * fulllabel = nom avec chemin complet de la categorie
* fullpath = chemin complet compose des id * fullpath = chemin complet compose des id
* *
* @param string $type Type of categories ('customer', 'supplier', 'contact', 'product', 'member') or (0, 1, 2, ...). * @param string $type Type of categories ('customer', 'supplier', 'contact', 'product', 'member') or (0, 1, 2, ...).
* @param int $markafterid Removed all categories including the leaf $markafterid in category tree. * @param int|string|array $markafterid Keep only or removed all categories including the leaf $markafterid in category tree (exclude) or Keep only of category is inside the leaf starting with this id.
* @param int $keeponlyifinleafid Keep only of category is inside the leaf starting with this id. * $markafterid can be an : int (id of category)
* @return array|int Array of categories. this->cats and this->motherof are set, -1 on error * string (categories ids seprated by comma)
* array (list of categories ids)
* @param int $include [=0] Removed or 1=Keep only
* @return array|int Array of categories. this->cats and this->motherof are set, -1 on error
*/ */
public function get_full_arbo($type, $markafterid = 0, $keeponlyifinleafid = 0) public function get_full_arbo($type, $markafterid = 0, $include = 0)
{ {
// phpcs:enable // phpcs:enable
global $conf, $langs; global $conf, $langs;
if (! is_numeric($type)) $type = $this->MAP_ID[$type]; if (! is_numeric($type)) $type = $this->MAP_ID[$type];
$this->cats = array(); if (is_string($markafterid))
{
$markafterid = explode(',', $markafterid);
}
elseif (is_numeric($markafterid))
{
if ($markafterid > 0)
{
$markafterid = array($markafterid);
}
else
{
$markafterid = array();
}
}
elseif (!is_array($markafterid))
{
$markafterid = array();
}
$this->cats = array();
// Init this->motherof that is array(id_son=>id_parent, ...) // Init this->motherof that is array(id_son=>id_parent, ...)
$this->load_motherof(); $this->load_motherof();
@ -1040,39 +1063,22 @@ class Categorie extends CommonObject
$this->build_path_from_id_categ($key, 0); // Process a branch from the root category key (this category has no parent) $this->build_path_from_id_categ($key, 0); // Process a branch from the root category key (this category has no parent)
} }
// Exclude leaf including $markafterid from tree // Include or exclude leaf including $markafterid from tree
if ($markafterid) if (count($markafterid) > 0)
{ {
$keyfiltercatid = implode('|', $markafterid);
//print "Look to discard category ".$markafterid."\n"; //print "Look to discard category ".$markafterid."\n";
$keyfilter1='^'.$markafterid.'$'; $keyfilter1 = '^' . $keyfiltercatid . '$';
$keyfilter2='_'.$markafterid.'$'; $keyfilter2 = '_' . $keyfiltercatid . '$';
$keyfilter3='^'.$markafterid.'_'; $keyfilter3 = '^' . $keyfiltercatid . '_';
$keyfilter4='_'.$markafterid.'_'; $keyfilter4 = '_' . $keyfiltercatid . '_';
foreach($this->cats as $key => $val) foreach($this->cats as $key => $val)
{ {
if (preg_match('/'.$keyfilter1.'/', $val['fullpath']) || preg_match('/'.$keyfilter2.'/', $val['fullpath']) $test = (preg_match('/' . $keyfilter1 . '/', $val['fullpath']) || preg_match('/' . $keyfilter2 . '/', $val['fullpath'])
|| preg_match('/'.$keyfilter3.'/', $val['fullpath']) || preg_match('/'.$keyfilter4.'/', $val['fullpath'])) || preg_match('/' . $keyfilter3 . '/', $val['fullpath']) || preg_match('/' . $keyfilter4 . '/', $val['fullpath']));
{
unset($this->cats[$key]); if (($test && !$include) || (!$test && $include))
}
}
}
// Exclude leaf including $markafterid from tree
if ($keeponlyifinleafid)
{
//print "Look to discard category ".$keeponlyifinleafid."\n";
$keyfilter1='^'.$keeponlyifinleafid.'$';
$keyfilter2='_'.$keeponlyifinleafid.'$';
$keyfilter3='^'.$keeponlyifinleafid.'_';
$keyfilter4='_'.$keeponlyifinleafid.'_';
foreach($this->cats as $key => $val)
{
if (preg_match('/'.$keyfilter1.'/', $val['fullpath']) || preg_match('/'.$keyfilter2.'/', $val['fullpath'])
|| preg_match('/'.$keyfilter3.'/', $val['fullpath']) || preg_match('/'.$keyfilter4.'/', $val['fullpath']))
{
// We keep
}
else
{ {
unset($this->cats[$key]); unset($this->cats[$key]);
} }

View File

@ -623,7 +623,7 @@ if (empty($reshook))
{ {
$db->begin(); $db->begin();
$result=$object->cloture($user, 4, ''); $result=$object->cloture($user, Propal::STATUS_BILLED, '');
if ($result < 0) if ($result < 0)
{ {
setEventMessages($object->error, $object->errors, 'errors'); setEventMessages($object->error, $object->errors, 'errors');

View File

@ -936,7 +936,7 @@ class Invoices extends DolibarrApi
*/ */
public function markAsCreditAvailable($id) public function markAsCreditAvailable($id)
{ {
if(! DolibarrApiAccess::$user->rights->facture->creer) { if( ! DolibarrApiAccess::$user->rights->facture->creer) {
throw new RestException(401); throw new RestException(401);
} }
@ -949,91 +949,147 @@ class Invoices extends DolibarrApi
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
} }
$result = $this->invoice->fetch_thirdparty(); if ($this->invoice->paye) {
if( ! $result ) { throw new RestException(500, 'Alreay payed');
throw new RestException(404, 'Thirdparty not found');
} }
if (! $this->invoice->paye) // protection against multiple submit $this->invoice->fetch($id);
{ $this->invoice->fetch_thirdparty();
$this->db->begin();
// Check if there is already a discount (protection to avoid duplicate creation when resubmit post)
$this->invoice->fetch_lines(); $discountcheck=new DiscountAbsolute($this->db);
$result=$discountcheck->fetch(0, $this->invoice->id);
$amount_ht = $amount_tva = $amount_ttc = array();
$canconvert=0;
// Loop on each vat rate if ($this->invoice->type == Facture::TYPE_DEPOSIT && empty($discountcheck->id)) $canconvert=1; // we can convert deposit into discount if deposit is payed (completely, partially or not at all) and not already converted (see real condition into condition used to show button converttoreduc)
$i=0; if (($this->invoice->type == Facture::TYPE_CREDIT_NOTE || $this->invoice->type == Facture::TYPE_STANDARD) && $this->invoice->paye == 0 && empty($discountcheck->id)) $canconvert=1; // we can convert credit note into discount if credit note is not payed back and not already converted and amount of payment is 0 (see real condition into condition used to show button converttoreduc)
$amount_ht = array(); if ($canconvert)
$amount_tva = array(); {
$amount_ttc = array(); $this->db->begin();
foreach($this->invoice->lines as $line)
{ $amount_ht = $amount_tva = $amount_ttc = array();
$amount_ht[$line->tva_tx]+=$line->total_ht; $multicurrency_amount_ht = $multicurrency_amount_tva = $multicurrency_amount_ttc = array();
$amount_tva[$line->tva_tx]+=$line->total_tva;
$amount_ttc[$line->tva_tx]+=$line->total_ttc; // Loop on each vat rate
$i++; $i = 0;
} foreach ($this->invoice->lines as $line)
{
// Insert one discount by VAT rate category if ($line->product_type < 9 && $line->total_ht != 0) // Remove lines with product_type greater than or equal to 9
$discount = new DiscountAbsolute($this->db); { // no need to create discount if amount is null
if ($this->invoice->type == 2) $discount->description='(CREDIT_NOTE)'; $amount_ht[$line->tva_tx] += $line->total_ht;
elseif ($this->invoice->type == 3) $discount->description='(DEPOSIT)'; $amount_tva[$line->tva_tx] += $line->total_tva;
else { $amount_ttc[$line->tva_tx] += $line->total_ttc;
$this->error="CantConvertToReducAnInvoiceOfThisType"; $multicurrency_amount_ht[$line->tva_tx] += $line->multicurrency_total_ht;
return -1; $multicurrency_amount_tva[$line->tva_tx] += $line->multicurrency_total_tva;
} $multicurrency_amount_ttc[$line->tva_tx] += $line->multicurrency_total_ttc;
$discount->tva_tx=abs($this->invoice->total_ttc); $i++;
$discount->fk_soc=$this->invoice->socid; }
$discount->fk_facture_source=$this->invoice->id; }
$error=0; // Insert one discount by VAT rate category
foreach($amount_ht as $tva_tx => $xxx) $discount = new DiscountAbsolute($this->db);
{ if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE){
$discount->amount_ht=abs($amount_ht[$tva_tx]); $discount->description = '(CREDIT_NOTE)';
$discount->amount_tva=abs($amount_tva[$tva_tx]); }
$discount->amount_ttc=abs($amount_ttc[$tva_tx]); elseif ($this->invoice->type == Facture::TYPE_DEPOSIT){
$discount->tva_tx=abs($tva_tx); $discount->description = '(DEPOSIT)';
}
$result=$discount->create(DolibarrApiAccess::$user); elseif ($this->invoice->type == Facture::TYPE_STANDARD || $this->invoice->type == Facture::TYPE_REPLACEMENT || $this->invoice->type == Facture::TYPE_SITUATION) {
if ($result < 0) $discount->description = '(EXCESS RECEIVED)';
{ }
$error++; else {
break; throw new RestException(500, 'Cant convert to reduc an Invoice of this type');
} }
}
$discount->fk_soc = $this->invoice->socid;
if (! $error) $discount->fk_facture_source = $this->invoice->id;
{
// Classe facture $error = 0;
$result=$this->invoice->set_paid(DolibarrApiAccess::$user);
if ($result > 0) if ($this->invoice->type == Facture::TYPE_STANDARD || $this->invoice->type == Facture::TYPE_REPLACEMENT || $this->invoice->type == Facture::TYPE_SITUATION)
{ {
//$mesg='OK'.$discount->id; // If we're on a standard invoice, we have to get excess received to create a discount in TTC without VAT
$this->db->commit();
} // Total payments
else $sql = 'SELECT SUM(pf.amount) as total_paiements';
{ $sql.= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf, '.MAIN_DB_PREFIX.'paiement as p';
$this->db->rollback(); $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
throw new RestException(500, 'Could not set paid'); $sql.= ' WHERE pf.fk_facture = '.$this->invoice->id;
} $sql.= ' AND pf.fk_paiement = p.rowid';
} $sql.= ' AND p.entity IN ('.getEntity('invoice').')';
else $resql = $this->db->query($sql);
{ if (! $resql) dol_print_error($this->db);
$this->db->rollback();
throw new RestException(500, 'Discount creation error'); $res = $this->db->fetch_object($resql);
} $total_paiements = $res->total_paiements;
}
// Total credit note and deposit
$result = $this->invoice->fetch($id); $total_creditnote_and_deposit = 0;
if( ! $result ) { $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
throw new RestException(404, 'Invoice not found'); $sql .= " re.description, re.fk_facture_source";
$sql .= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re";
$sql .= " WHERE fk_facture = " . $this->invoice->id;
$resql = $this->db->query($sql);
if (!empty($resql)) {
while ($obj = $this->db->fetch_object($resql)) $total_creditnote_and_deposit += $obj->amount_ttc;
} else dol_print_error($this->db);
$discount->amount_ht = $discount->amount_ttc = $total_paiements + $total_creditnote_and_deposit - $this->invoice->total_ttc;
$discount->amount_tva = 0;
$discount->tva_tx = 0;
$result = $discount->create(DolibarrApiAccess::$user);
if ($result < 0)
{
$error++;
}
}
if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE || $this->invoice->type == Facture::TYPE_DEPOSIT)
{
foreach ($amount_ht as $tva_tx => $xxx)
{
$discount->amount_ht = abs($amount_ht[$tva_tx]);
$discount->amount_tva = abs($amount_tva[$tva_tx]);
$discount->amount_ttc = abs($amount_ttc[$tva_tx]);
$discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$tva_tx]);
$discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$tva_tx]);
$discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
$discount->tva_tx = abs($tva_tx);
$result = $discount->create(DolibarrApiAccess::$user);
if ($result < 0)
{
$error++;
break;
}
}
}
if (empty($error))
{
if($this->invoice->type != Facture::TYPE_DEPOSIT) {
// Classe facture
$result = $this->invoice->set_paid(DolibarrApiAccess::$user);
if ($result >= 0)
{
$this->db->commit();
}
else
{
$this->db->rollback();
throw new RestException(500, 'Could not set paid');
}
} else {
$this->db->commit();
}
}
else
{
$this->db->rollback();
throw new RestException(500, 'Discount creation error');
}
} }
if( ! DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
return $this->_cleanObjectDatas($this->invoice); return $this->_cleanObjectDatas($this->invoice);
} }

View File

@ -121,7 +121,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes')
$result=$object->delete($user); $result=$object->delete($user);
if ($result > 0) if ($result > 0)
{ {
header("Location: index.php"); header("Location: list.php");
exit; exit;
} }
else else

View File

@ -1069,4 +1069,54 @@ abstract class CommonDocGenerator
} }
else return false; else return false;
} }
/**
* print standard column content
*
* @param PDF $pdf pdf object
* @param float $tab_top tab top position
* @param float $tab_height default tab height
* @param $outputlangs
* @param int $hidetop
* @return float height of col tab titles
*/
function pdfTabTitles(&$pdf, $tab_top, $tab_height, $outputlangs, $hidetop = 0)
{
global $hookmanager;
foreach ($this->cols as $colKey => $colDef) {
$parameters = array(
'colKey' => $colKey,
'pdf' => $pdf,
'outputlangs' => $outputlangs,
'tab_top' => $tab_top,
'tab_height' => $tab_height,
'hidetop' => $hidetop
);
$reshook = $hookmanager->executeHooks('pdfTabTitles', $parameters, $this); // Note that $object may have been modified by hook
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
} elseif (empty($reshook)) {
if (!$this->getColumnStatus($colKey)) continue;
// get title label
$colDef['title']['label'] = !empty($colDef['title']['label']) ? $colDef['title']['label'] : $outputlangs->transnoentities($colDef['title']['textkey']);
// Add column separator
if (!empty($colDef['border-left'])) {
$pdf->line($colDef['xStartPos'], $tab_top, $colDef['xStartPos'], $tab_top + $tab_height);
}
if (empty($hidetop)) {
$pdf->SetXY($colDef['xStartPos'] + $colDef['title']['padding'][3], $tab_top + $colDef['title']['padding'][0]);
$textWidth = $colDef['width'] - $colDef['title']['padding'][3] - $colDef['title']['padding'][1];
$pdf->MultiCell($textWidth, 2, $colDef['title']['label'], '', $colDef['title']['align']);
$this->tabTitleHeight = max($pdf->GetY() - $tab_top + $colDef['title']['padding'][2], $this->tabTitleHeight);
}
}
}
return $this->tabTitleHeight;
}
} }

View File

@ -1180,6 +1180,8 @@ class ExtraFields
// 2 : key fields name (if differ of rowid) // 2 : key fields name (if differ of rowid)
// 3 : key field parent (for dependent lists) // 3 : key field parent (for dependent lists)
// 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
// 5 : id category type
// 6 : ids categories list separated by comma for category root
$keyList=(empty($InfoFieldList[2])?'rowid':$InfoFieldList[2].' as rowid'); $keyList=(empty($InfoFieldList[2])?'rowid':$InfoFieldList[2].' as rowid');
@ -1198,136 +1200,130 @@ class ExtraFields
$keyList.= ', '.$parentField; $keyList.= ', '.$parentField;
} }
$fields_label = explode('|', $InfoFieldList[1]); $filter_categorie = false;
if (is_array($fields_label)) if (count($InfoFieldList) > 5) {
{ if ($InfoFieldList[0] == 'categorie') {
$keyList .=', '; $filter_categorie = true;
$keyList .= implode(', ', $fields_label); }
} }
$sqlwhere=''; if ($filter_categorie === false) {
$sql = 'SELECT '.$keyList; $fields_label = explode('|', $InfoFieldList[1]);
$sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0]; if (is_array($fields_label)) {
if (!empty($InfoFieldList[4])) $keyList .= ', ';
{ $keyList .= implode(', ', $fields_label);
// can use curent entity filter }
if (strpos($InfoFieldList[4], '$ENTITY$')!==false) {
$InfoFieldList[4]=str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
}
// can use SELECT request
if (strpos($InfoFieldList[4], '$SEL$')!==false) {
$InfoFieldList[4]=str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
}
// current object id can be use into filter $sqlwhere = '';
if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) { $sql = 'SELECT ' . $keyList;
$InfoFieldList[4]=str_replace('$ID$', $objectid, $InfoFieldList[4]); $sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0];
} else { if (!empty($InfoFieldList[4])) {
$InfoFieldList[4]=str_replace('$ID$', '0', $InfoFieldList[4]); // can use curent entity filter
} if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
//We have to join on extrafield table $InfoFieldList[4] = str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
if (strpos($InfoFieldList[4], 'extra')!==false) }
{ // can use SELECT request
$sql.= ' as main, '.MAIN_DB_PREFIX .$InfoFieldList[0].'_extrafields as extra'; if (strpos($InfoFieldList[4], '$SEL$') !== false) {
$sqlwhere.= ' WHERE extra.fk_object=main.'.$InfoFieldList[2]. ' AND '.$InfoFieldList[4]; $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
} }
else
{
$sqlwhere.= ' WHERE '.$InfoFieldList[4];
}
}
else
{
$sqlwhere.= ' WHERE 1=1';
}
// Some tables may have field, some other not. For the moment we disable it.
if (in_array($InfoFieldList[0], array('tablewithentity')))
{
$sqlwhere.= ' AND entity = '.$conf->entity;
}
$sql.=$sqlwhere;
//print $sql;
$sql .= ' ORDER BY ' . implode(', ', $fields_label); // current object id can be use into filter
if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
$InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
} else {
$InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
}
//We have to join on extrafield table
if (strpos($InfoFieldList[4], 'extra') !== false) {
$sql .= ' as main, ' . MAIN_DB_PREFIX . $InfoFieldList[0] . '_extrafields as extra';
$sqlwhere .= ' WHERE extra.fk_object=main.' . $InfoFieldList[2] . ' AND ' . $InfoFieldList[4];
} else {
$sqlwhere .= ' WHERE ' . $InfoFieldList[4];
}
} else {
$sqlwhere .= ' WHERE 1=1';
}
// Some tables may have field, some other not. For the moment we disable it.
if (in_array($InfoFieldList[0], array('tablewithentity'))) {
$sqlwhere .= ' AND entity = ' . $conf->entity;
}
$sql .= $sqlwhere;
//print $sql;
dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG); $sql .= ' ORDER BY ' . implode(', ', $fields_label);
$resql = $this->db->query($sql);
if ($resql)
{
$out.='<option value="0">&nbsp;</option>';
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num)
{
$labeltoshow='';
$obj = $this->db->fetch_object($resql);
// Several field into label (eq table:code|libelle:rowid) dol_syslog(get_class($this) . '::showInputField type=sellist', LOG_DEBUG);
$notrans = false; $resql = $this->db->query($sql);
$fields_label = explode('|', $InfoFieldList[1]); if ($resql) {
if (is_array($fields_label)) $out .= '<option value="0">&nbsp;</option>';
{ $num = $this->db->num_rows($resql);
$notrans = true; $i = 0;
foreach ($fields_label as $field_toshow) while ($i < $num) {
{ $labeltoshow = '';
$labeltoshow.= $obj->$field_toshow.' '; $obj = $this->db->fetch_object($resql);
}
}
else
{
$labeltoshow=$obj->{$InfoFieldList[1]};
}
$labeltoshow=dol_trunc($labeltoshow, 45);
if ($value == $obj->rowid) // Several field into label (eq table:code|libelle:rowid)
{ $notrans = false;
foreach ($fields_label as $field_toshow) $fields_label = explode('|', $InfoFieldList[1]);
{ if (is_array($fields_label)) {
$translabel=$langs->trans($obj->$field_toshow); $notrans = true;
if ($translabel!=$obj->$field_toshow) { foreach ($fields_label as $field_toshow) {
$labeltoshow=dol_trunc($translabel, 18).' '; $labeltoshow .= $obj->$field_toshow . ' ';
}else { }
$labeltoshow=dol_trunc($obj->$field_toshow, 18).' '; } else {
} $labeltoshow = $obj->{$InfoFieldList[1]};
} }
$out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>'; $labeltoshow = dol_trunc($labeltoshow, 45);
}
else
{
if (! $notrans)
{
$translabel=$langs->trans($obj->{$InfoFieldList[1]});
if ($translabel!=$obj->{$InfoFieldList[1]}) {
$labeltoshow=dol_trunc($translabel, 18);
}
else {
$labeltoshow=dol_trunc($obj->{$InfoFieldList[1]}, 18);
}
}
if (empty($labeltoshow)) $labeltoshow='(not defined)';
if ($value==$obj->rowid)
{
$out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
}
if (!empty($InfoFieldList[3]) && $parentField) if ($value == $obj->rowid) {
{ foreach ($fields_label as $field_toshow) {
$parent = $parentName.':'.$obj->{$parentField}; $translabel = $langs->trans($obj->$field_toshow);
} if ($translabel != $obj->$field_toshow) {
$labeltoshow = dol_trunc($translabel, 18) . ' ';
} else {
$labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' ';
}
}
$out .= '<option value="' . $obj->rowid . '" selected>' . $labeltoshow . '</option>';
} else {
if (!$notrans) {
$translabel = $langs->trans($obj->{$InfoFieldList[1]});
if ($translabel != $obj->{$InfoFieldList[1]}) {
$labeltoshow = dol_trunc($translabel, 18);
} else {
$labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
}
}
if (empty($labeltoshow)) $labeltoshow = '(not defined)';
if ($value == $obj->rowid) {
$out .= '<option value="' . $obj->rowid . '" selected>' . $labeltoshow . '</option>';
}
$out.='<option value="'.$obj->rowid.'"'; if (!empty($InfoFieldList[3]) && $parentField) {
$out.= ($value==$obj->rowid?' selected':''); $parent = $parentName . ':' . $obj->{$parentField};
$out.= (!empty($parent)?' parent="'.$parent.'"':''); }
$out.='>'.$labeltoshow.'</option>';
}
$i++; $out .= '<option value="' . $obj->rowid . '"';
} $out .= ($value == $obj->rowid ? ' selected' : '');
$this->db->free($resql); $out .= (!empty($parent) ? ' parent="' . $parent . '"' : '');
} $out .= '>' . $labeltoshow . '</option>';
else { }
print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
} $i++;
}
$this->db->free($resql);
} else {
print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>';
}
} else {
$data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
$out .= '<option value="0">&nbsp;</option>';
foreach ($data as $data_key => $data_value) {
$out .= '<option value="' . $data_key . '"';
$out .= ($value == $data_key ? ' selected' : '');
$out .= '>' . $data_value . '</option>';
}
}
} }
$out.='</select>'; $out.='</select>';
} }
@ -1367,6 +1363,8 @@ class ExtraFields
// 2 : key fields name (if differ of rowid) // 2 : key fields name (if differ of rowid)
// 3 : key field parent (for dependent lists) // 3 : key field parent (for dependent lists)
// 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
// 5 : id category type
// 6 : ids categories list separated by comma for category root
$keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid'); $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid');
if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3])) { if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3])) {
@ -1381,166 +1379,173 @@ class ExtraFields
} }
} }
$fields_label = explode('|', $InfoFieldList[1]); $filter_categorie = false;
if (is_array($fields_label)) { if (count($InfoFieldList) > 5) {
$keyList .= ', '; if ($InfoFieldList[0] == 'categorie') {
$keyList .= implode(', ', $fields_label); $filter_categorie = true;
} }
}
$sqlwhere = ''; if ($filter_categorie === false) {
$sql = 'SELECT ' . $keyList; $fields_label = explode('|', $InfoFieldList[1]);
$sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0]; if (is_array($fields_label)) {
if (! empty($InfoFieldList[4])) { $keyList .= ', ';
$keyList .= implode(', ', $fields_label);
}
// can use SELECT request $sqlwhere = '';
if (strpos($InfoFieldList[4], '$SEL$')!==false) { $sql = 'SELECT ' . $keyList;
$InfoFieldList[4]=str_replace('$SEL$', 'SELECT', $InfoFieldList[4]); $sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0];
} if (!empty($InfoFieldList[4])) {
// current object id can be use into filter // can use SELECT request
if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) { if (strpos($InfoFieldList[4], '$SEL$') !== false) {
$InfoFieldList[4]=str_replace('$ID$', $objectid, $InfoFieldList[4]); $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
} elseif (preg_match("#^.*list.php$#", $_SERVER["DOCUMENT_URI"])) { }
// Pattern for word=$ID$
$word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
// Removing space arount =, ( and ) // current object id can be use into filter
$InfoFieldList[4]=preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]); if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
$InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
} elseif (preg_match("#^.*list.php$#", $_SERVER["DOCUMENT_URI"])) {
// Pattern for word=$ID$
$word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
$nbPreg = 1; // Removing space arount =, ( and )
// While we have parenthesis $InfoFieldList[4] = preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
while ($nbPreg!=0) {
// Init des compteurs
$nbPregRepl = $nbPregSel = 0;
// On retire toutes les parenthèses sans = avant
$InfoFieldList[4]=preg_replace('#([^=])(\([^)^(]*(' . $word . ')[^)^(]*\))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
// On retire les espaces autour des = et parenthèses
$InfoFieldList[4]=preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
// On retire toutes les parenthèses avec = avant
$InfoFieldList[4]=preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\([^)^(]*(' . $word . ')[^)^(]*\)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
// On retire les espaces autour des = et parenthèses
$InfoFieldList[4]=preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
// Calcul du compteur général pour la boucle $nbPreg = 1;
$nbPreg = $nbPregRepl + $nbPregSel; // While we have parenthesis
} while ($nbPreg != 0) {
// Init des compteurs
$nbPregRepl = $nbPregSel = 0;
// On retire toutes les parenthèses sans = avant
$InfoFieldList[4] = preg_replace('#([^=])(\([^)^(]*(' . $word . ')[^)^(]*\))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
// On retire les espaces autour des = et parenthèses
$InfoFieldList[4] = preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
// On retire toutes les parenthèses avec = avant
$InfoFieldList[4] = preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\([^)^(]*(' . $word . ')[^)^(]*\)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
// On retire les espaces autour des = et parenthèses
$InfoFieldList[4] = preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
// Si l'on a un AND ou un OR, avant ou après // Calcul du compteur général pour la boucle
preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition); $nbPreg = $nbPregRepl + $nbPregSel;
while(!empty($matchCondition[0])) { }
// If the two sides differ but are not empty
if (! empty($matchCondition[1]) && ! empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3] ) {
// Nobody sain would do that without parentheses
$InfoFieldList[4]=str_replace('$ID$', '0', $InfoFieldList[4]);
}
else {
if (! empty($matchCondition[1])) {
$boolCond =(( $matchCondition[1] == "AND" )?' AND 1 ':' OR 0 ');
$InfoFieldList[4]=str_replace($matchCondition[0], $boolCond.$matchCondition[3], $InfoFieldList[4]);
}
elseif (! empty($matchCondition[3])) {
$boolCond =(( $matchCondition[3] == "AND" )?' 1 AND ':' 0 OR');
$InfoFieldList[4]=str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
}
else {
$InfoFieldList[4] = 1;
}
}
// Si l'on a un AND ou un OR, avant ou après // Si l'on a un AND ou un OR, avant ou après
preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition); preg_match('#(AND|OR|) *(' . $word . ') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
} while (!empty($matchCondition[0])) {
} // If the two sides differ but are not empty
else { if (!empty($matchCondition[1]) && !empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3]) {
$InfoFieldList[4]=str_replace('$ID$', '0', $InfoFieldList[4]); // Nobody sain would do that without parentheses
} $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
} else {
if (!empty($matchCondition[1])) {
$boolCond = (($matchCondition[1] == "AND") ? ' AND 1 ' : ' OR 0 ');
$InfoFieldList[4] = str_replace($matchCondition[0], $boolCond . $matchCondition[3], $InfoFieldList[4]);
} elseif (!empty($matchCondition[3])) {
$boolCond = (($matchCondition[3] == "AND") ? ' 1 AND ' : ' 0 OR');
$InfoFieldList[4] = str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
} else {
$InfoFieldList[4] = 1;
}
}
// We have to join on extrafield table // Si l'on a un AND ou un OR, avant ou après
if (strpos($InfoFieldList[4], 'extra') !== false) { preg_match('#(AND|OR|) *(' . $word . ') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
$sql .= ' as main, ' . MAIN_DB_PREFIX . $InfoFieldList[0] . '_extrafields as extra'; }
$sqlwhere .= ' WHERE extra.fk_object=main.' . $InfoFieldList[2] . ' AND ' . $InfoFieldList[4]; } else {
} else { $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
$sqlwhere .= ' WHERE ' . $InfoFieldList[4]; }
}
} else {
$sqlwhere .= ' WHERE 1=1';
}
// Some tables may have field, some other not. For the moment we disable it.
if (in_array($InfoFieldList[0], array ('tablewithentity')))
{
$sqlwhere .= ' AND entity = ' . $conf->entity;
}
// $sql.=preg_replace('/^ AND /','',$sqlwhere);
// print $sql;
$sql .= $sqlwhere; // We have to join on extrafield table
dol_syslog(get_class($this) . '::showInputField type=chkbxlst', LOG_DEBUG); if (strpos($InfoFieldList[4], 'extra') !== false) {
$resql = $this->db->query($sql); $sql .= ' as main, ' . MAIN_DB_PREFIX . $InfoFieldList[0] . '_extrafields as extra';
if ($resql) { $sqlwhere .= ' WHERE extra.fk_object=main.' . $InfoFieldList[2] . ' AND ' . $InfoFieldList[4];
$num = $this->db->num_rows($resql); } else {
$i = 0; $sqlwhere .= ' WHERE ' . $InfoFieldList[4];
}
} else {
$sqlwhere .= ' WHERE 1=1';
}
// Some tables may have field, some other not. For the moment we disable it.
if (in_array($InfoFieldList[0], array('tablewithentity'))) {
$sqlwhere .= ' AND entity = ' . $conf->entity;
}
// $sql.=preg_replace('/^ AND /','',$sqlwhere);
// print $sql;
$data=array(); $sql .= $sqlwhere;
dol_syslog(get_class($this) . '::showInputField type=chkbxlst', LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ( $i < $num ) { $data = array();
$labeltoshow = '';
$obj = $this->db->fetch_object($resql);
$notrans = false; while ($i < $num) {
// Several field into label (eq table:code|libelle:rowid) $labeltoshow = '';
$fields_label = explode('|', $InfoFieldList[1]); $obj = $this->db->fetch_object($resql);
if (is_array($fields_label)) {
$notrans = true;
foreach ($fields_label as $field_toshow) {
$labeltoshow .= $obj->$field_toshow . ' ';
}
} else {
$labeltoshow = $obj->{$InfoFieldList[1]};
}
$labeltoshow = dol_trunc($labeltoshow, 45);
if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { $notrans = false;
foreach ($fields_label as $field_toshow) { // Several field into label (eq table:code|libelle:rowid)
$translabel = $langs->trans($obj->$field_toshow); $fields_label = explode('|', $InfoFieldList[1]);
if ($translabel != $obj->$field_toshow) { if (is_array($fields_label)) {
$labeltoshow = dol_trunc($translabel, 18) . ' '; $notrans = true;
} else { foreach ($fields_label as $field_toshow) {
$labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' '; $labeltoshow .= $obj->$field_toshow . ' ';
} }
} } else {
$labeltoshow = $obj->{$InfoFieldList[1]};
}
$labeltoshow = dol_trunc($labeltoshow, 45);
$data[$obj->rowid]=$labeltoshow; if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
} else { foreach ($fields_label as $field_toshow) {
if (! $notrans) { $translabel = $langs->trans($obj->$field_toshow);
$translabel = $langs->trans($obj->{$InfoFieldList[1]}); if ($translabel != $obj->$field_toshow) {
if ($translabel != $obj->{$InfoFieldList[1]}) { $labeltoshow = dol_trunc($translabel, 18) . ' ';
$labeltoshow = dol_trunc($translabel, 18); } else {
} else { $labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' ';
$labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18); }
} }
}
if (empty($labeltoshow))
$labeltoshow = '(not defined)';
if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { $data[$obj->rowid] = $labeltoshow;
$data[$obj->rowid]=$labeltoshow; } else {
} if (!$notrans) {
$translabel = $langs->trans($obj->{$InfoFieldList[1]});
if ($translabel != $obj->{$InfoFieldList[1]}) {
$labeltoshow = dol_trunc($translabel, 18);
} else {
$labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
}
}
if (empty($labeltoshow))
$labeltoshow = '(not defined)';
if (! empty($InfoFieldList[3]) && $parentField) { if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
$parent = $parentName . ':' . $obj->{$parentField}; $data[$obj->rowid] = $labeltoshow;
} }
$data[$obj->rowid]=$labeltoshow; if (!empty($InfoFieldList[3]) && $parentField) {
} $parent = $parentName . ':' . $obj->{$parentField};
}
$i ++; $data[$obj->rowid] = $labeltoshow;
} }
$this->db->free($resql);
$out=$form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%'); $i++;
} else { }
print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>'; $this->db->free($resql);
}
$out = $form->multiselectarray($keyprefix . $key . $keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
} else {
print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>';
}
} else {
$data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
$out = $form->multiselectarray($keyprefix . $key . $keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
}
} }
} }
elseif ($type == 'link') elseif ($type == 'link')

View File

@ -3801,16 +3801,20 @@ class Form
/** /**
* Return list of categories having choosed type * Return list of categories having choosed type
* *
* @param string|int $type Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated. * @param string|int $type Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated.
* @param string $selected Id of category preselected or 'auto' (autoselect category if there is only one element) * @param string $selected Id of category preselected or 'auto' (autoselect category if there is only one element)
* @param string $htmlname HTML field name * @param string $htmlname HTML field name
* @param int $maxlength Maximum length for labels * @param int $maxlength Maximum length for labels
* @param int $excludeafterid Exclude all categories after this leaf in category tree. * @param int|string|array $markafterid Keep only or removed all categories including the leaf $markafterid in category tree (exclude) or Keep only of category is inside the leaf starting with this id.
* @param int $outputmode 0=HTML select string, 1=Array * $markafterid can be an : int (id of category)
* string (categories ids seprated by comma)
* array (list of categories ids)
* @param int $outputmode 0=HTML select string, 1=Array
* @param int $include [=0] Removed or 1=Keep only
* @return string * @return string
* @see select_categories() * @see select_categories()
*/ */
public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $excludeafterid = 0, $outputmode = 0) public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0)
{ {
// phpcs:enable // phpcs:enable
global $conf, $langs; global $conf, $langs;
@ -3850,7 +3854,7 @@ class Form
else else
{ {
$cat = new Categorie($this->db); $cat = new Categorie($this->db);
$cate_arbo = $cat->get_full_arbo($type, $excludeafterid); $cate_arbo = $cat->get_full_arbo($type, $markafterid, $include);
} }
$output = '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">'; $output = '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';

View File

@ -2115,6 +2115,10 @@ function getElementProperties($element_type)
$subelement='facturefournisseur'; $subelement='facturefournisseur';
$classfile='fournisseur.facture'; $classfile='fournisseur.facture';
} }
if ($element_type == "service") {
$classpath = 'product/class';
$subelement='product';
}
if (!isset($classfile)) $classfile = strtolower($subelement); if (!isset($classfile)) $classfile = strtolower($subelement);
if (!isset($classname)) $classname = ucfirst($subelement); if (!isset($classname)) $classname = ucfirst($subelement);

View File

@ -68,7 +68,7 @@ function commande_prepare_head(Commande $object)
if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled) $text.='/'; if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled) $text.='/';
if ($conf->livraison_bon->enabled) $text.=$langs->trans("Receivings"); if ($conf->livraison_bon->enabled) $text.=$langs->trans("Receivings");
if ($nbShipments > 0 || $nbReceiption > 0) $text.= ' <span class="badge">'.($nbShipments?$nbShipments:0); if ($nbShipments > 0 || $nbReceiption > 0) $text.= ' <span class="badge">'.($nbShipments?$nbShipments:0);
if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled) $text.='/'; if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled && ($nbShipments > 0 || $nbReceiption > 0)) $text.='/';
if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled && ($nbShipments > 0 || $nbReceiption > 0)) $text.= ($nbReceiption?$nbReceiption:0); if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled && ($nbShipments > 0 || $nbReceiption > 0)) $text.= ($nbReceiption?$nbReceiption:0);
if ($nbShipments > 0 || $nbReceiption > 0) $text.= '</span>'; if ($nbShipments > 0 || $nbReceiption > 0) $text.= '</span>';
$head[$h][1] = $text; $head[$h][1] = $text;

View File

@ -127,6 +127,25 @@ function product_prepare_head($object)
$h++; $h++;
} }
} }
// Tab to link resources
if (!empty($conf->resource->enabled))
{
if ($object->isProduct() && ! empty($conf->global->RESOURCE_ON_PRODUCTS))
{
$head[$h][0] = DOL_URL_ROOT . '/resource/element_resource.php?element=product&ref=' . $object->ref;
$head[$h][1] = $langs->trans("Resources");
$head[$h][2] = 'resources';
$h++;
}
if ($object->isService() && ! empty($conf->global->RESOURCE_ON_SERVICES))
{
$head[$h][0] = DOL_URL_ROOT . '/resource/element_resource.php?element=service&ref=' . $object->ref;
$head[$h][1] = $langs->trans("Resources");
$head[$h][2] = 'resources';
$h++;
}
}
// Show more tabs from modules // Show more tabs from modules
// Entries must be declared in modules descriptor with line // Entries must be declared in modules descriptor with line

View File

@ -170,6 +170,8 @@ class pdf_eratosthene extends ModelePDFCommandes
$this->posxdesc=$this->marge_gauche+1; $this->posxdesc=$this->marge_gauche+1;
$this->tabTitleHeight = 5; // default height
$this->tva=array(); $this->tva=array();
$this->localtax1=array(); $this->localtax1=array();
$this->localtax2=array(); $this->localtax2=array();
@ -203,6 +205,73 @@ class pdf_eratosthene extends ModelePDFCommandes
$nblignes = count($object->lines); $nblignes = count($object->lines);
$hidetop=0;
if(!empty($conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE)){
$hidetop=$conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE;
}
// Loop on each lines to detect if there is at least one image to show
$realpatharray=array();
$this->atleastonephoto = false;
if (! empty($conf->global->MAIN_GENERATE_ORDERS_WITH_PICTURE))
{
$objphoto = new Product($this->db);
for ($i = 0 ; $i < $nblignes ; $i++)
{
if (empty($object->lines[$i]->fk_product)) continue;
$objphoto->fetch($object->lines[$i]->fk_product);
//var_dump($objphoto->ref);exit;
if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO))
{
$pdir[0] = get_exdir($objphoto->id,2,0,0,$objphoto,'product') . $objphoto->id ."/photos/";
$pdir[1] = get_exdir(0,0,0,0,$objphoto,'product') . dol_sanitizeFileName($objphoto->ref).'/';
}
else
{
$pdir[0] = get_exdir(0,0,0,0,$objphoto,'product') . dol_sanitizeFileName($objphoto->ref).'/'; // default
$pdir[1] = get_exdir($objphoto->id,2,0,0,$objphoto,'product') . $objphoto->id ."/photos/"; // alternative
}
$arephoto = false;
foreach ($pdir as $midir)
{
if (! $arephoto)
{
$dir = $conf->product->dir_output.'/'.$midir;
foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
{
if (empty($conf->global->CAT_HIGH_QUALITY_IMAGES)) // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
{
if ($obj['photo_vignette'])
{
$filename= $obj['photo_vignette'];
}
else
{
$filename=$obj['photo'];
}
}
else
{
$filename=$obj['photo'];
}
$realpath = $dir.$filename;
$arephoto = true;
$this->atleastonephoto = true;
}
}
}
if ($realpath && $arephoto) $realpatharray[$i]=$realpath;
}
}
if ($conf->commande->dir_output) if ($conf->commande->dir_output)
{ {
$object->fetch_thirdparty(); $object->fetch_thirdparty();
@ -464,13 +533,19 @@ class pdf_eratosthene extends ModelePDFCommandes
$height_note=0; $height_note=0;
} }
$iniY = $tab_top + 7;
$curY = $tab_top + 7;
$nexY = $tab_top + 7;
// Use new auto collum system // Use new auto collum system
$this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
// tab simulation to know line height
$pdf->startTransaction();
$this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
$pdf->rollbackTransaction(true);
$iniY = $tab_top + $this->tabTitleHeight + 2;
$curY = $tab_top + $this->tabTitleHeight + 2;
$nexY = $tab_top + $this->tabTitleHeight + 2;
// Loop on each lines // Loop on each lines
$pageposbeforeprintlines=$pdf->getPage(); $pageposbeforeprintlines=$pdf->getPage();
$pagenb = $pageposbeforeprintlines; $pagenb = $pageposbeforeprintlines;
@ -479,6 +554,10 @@ class pdf_eratosthene extends ModelePDFCommandes
$curY = $nexY; $curY = $nexY;
$pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
$pdf->SetTextColor(0, 0, 0); $pdf->SetTextColor(0, 0, 0);
// Define size of image if we need it
$imglinesize=array();
if (! empty($realpatharray[$i])) $imglinesize=pdf_getSizeForImage($realpatharray[$i]);
$pdf->setTopMargin($tab_top_newpage); $pdf->setTopMargin($tab_top_newpage);
$pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext+$heightforinfotot); // The only function to edit the bottom margin of current page to set it. $pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext+$heightforinfotot); // The only function to edit the bottom margin of current page to set it.
@ -488,6 +567,29 @@ class pdf_eratosthene extends ModelePDFCommandes
$curX = $this->posxdesc-1; $curX = $this->posxdesc-1;
$showpricebeforepagebreak=1; $showpricebeforepagebreak=1;
$posYAfterImage=0;
$posYAfterDescription=0;
if($this->getColumnStatus('photo'))
{
// We start with Photo of product line
if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur-($heightforfooter+$heightforfreetext+$heightforinfotot))) // If photo too high, we moved completely on new page
{
$pdf->AddPage('','',true);
if (! empty($tplidx)) $pdf->useTemplate($tplidx);
$pdf->setPage($pageposbefore+1);
$curY = $tab_top_newpage;
$showpricebeforepagebreak=0;
}
if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height']))
{
$pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
// $pdf->Image does not increase value return by getY, so we save it manually
$posYAfterImage=$curY+$imglinesize['height'];
}
}
if($this->getColumnStatus('desc')) if($this->getColumnStatus('desc'))
{ {
@ -526,7 +628,11 @@ class pdf_eratosthene extends ModelePDFCommandes
$posYAfterDescription=$pdf->GetY(); $posYAfterDescription=$pdf->GetY();
} }
$nexY = $pdf->GetY();
$nexY = max($pdf->GetY(),$posYAfterImage);
$pageposafter=$pdf->getPage(); $pageposafter=$pdf->getPage();
$pdf->setPage($pageposbefore); $pdf->setPage($pageposbefore);
@ -657,7 +763,7 @@ class pdf_eratosthene extends ModelePDFCommandes
$pdf->setPage($pagenb); $pdf->setPage($pagenb);
if ($pagenb == $pageposbeforeprintlines) if ($pagenb == $pageposbeforeprintlines)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
} }
else else
{ {
@ -673,7 +779,7 @@ class pdf_eratosthene extends ModelePDFCommandes
{ {
if ($pagenb == $pageposafter) if ($pagenb == $pageposafter)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
} }
else else
{ {
@ -690,7 +796,7 @@ class pdf_eratosthene extends ModelePDFCommandes
// Show square // Show square
if ($pagenb == $pageposbeforeprintlines) if ($pagenb == $pageposbeforeprintlines)
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
else else
$this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
$bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
@ -973,19 +1079,16 @@ class pdf_eratosthene extends ModelePDFCommandes
$col2x-=20; $col2x-=20;
} }
$largcol2 = ($this->page_largeur - $this->marge_droite - $col2x); $largcol2 = ($this->page_largeur - $this->marge_droite - $col2x);
$useborder=0; $useborder=0;
$index = 0; $index = 0;
// Total HT // Total HT
$pdf->SetFillColor(255, 255, 255); $pdf->SetFillColor(255, 255, 255);
$pdf->SetXY($col1x, $tab2_top + 0); $pdf->SetXY($col1x, $tab2_top + 0);
$pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1); $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1);
$total_ht = ($conf->multicurrency->enabled && $object->mylticurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht); $total_ht = ($conf->multicurrency->enabled && $object->mylticurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht);
$pdf->SetXY($col2x, $tab2_top + 0); $pdf->SetXY($col2x, $tab2_top + 0);
$pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (! empty($object->remise)?$object->remise:0), 0, $outputlangs), 0, 'R', 1); $pdf->MultiCell($largcol2, $tab2_hl, price($total_ht + (! empty($object->remise)?$object->remise:0), 0, $outputlangs), 0, 'R', 1);
// Show VAT by rates and total // Show VAT by rates and total
$pdf->SetFillColor(248, 248, 248); $pdf->SetFillColor(248, 248, 248);
@ -1250,30 +1353,13 @@ class pdf_eratosthene extends ModelePDFCommandes
$this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param
foreach ($this->cols as $colKey => $colDef) $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
{
if(!$this->getColumnStatus($colKey)) continue;
// get title label
$colDef['title']['label'] = !empty($colDef['title']['label'])?$colDef['title']['label']:$outputlangs->transnoentities($colDef['title']['textkey']);
// Add column separator
if(!empty($colDef['border-left'])){
$pdf->line($colDef['xStartPos'], $tab_top, $colDef['xStartPos'], $tab_top + $tab_height);
}
if (empty($hidetop))
{
$pdf->SetXY($colDef['xStartPos'] + $colDef['title']['padding'][3], $tab_top + $colDef['title']['padding'][0]);
$textWidth = $colDef['width'] - $colDef['title']['padding'][3] -$colDef['title']['padding'][1];
$pdf->MultiCell($textWidth, 2, $colDef['title']['label'], '', $colDef['title']['align']);
}
}
if (empty($hidetop)){ if (empty($hidetop)){
$pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); // line prend une position y en 2eme param et 4eme param $pdf->line($this->marge_gauche, $tab_top+$this->tabTitleHeight, $this->page_largeur-$this->marge_droite, $tab_top+$this->tabTitleHeight); // line prend une position y en 2eme param et 4eme param
} }
} }
/** /**

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
* Copyright (C) 2016-2018 Philippe Grand <philippe.grand@atoo-net.com> * Copyright (C) 2016-2018 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr> * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2018 Francis Appels <francis.appels@z-application.com> * Copyright (C) 2018 Francis Appels <francis.appels@z-application.com>
* Copyright (C) 2019 Markus Welters <markus@welters.de>
* Copyright (C) 2019 Rafael Ingenleuf <ingenleuf@welters.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -32,8 +34,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
require_once DOL_DOCUMENT_ROOT.'/user/class/userbankaccount.class.php';
/** /**
* Class to generate expense report based on standard model * Class to generate expense report based on standard model
@ -121,7 +124,7 @@ class pdf_standard extends ModeleExpenseReport
*/ */
public function __construct($db) public function __construct($db)
{ {
global $conf, $langs, $mysoc; global $conf, $langs, $mysoc, $user;
// Translations // Translations
$langs->loadLangs(array("main", "trips", "projects")); $langs->loadLangs(array("main", "trips", "projects"));
@ -156,6 +159,7 @@ class pdf_standard extends ModeleExpenseReport
// Get source company // Get source company
$this->emetteur=$mysoc; $this->emetteur=$mysoc;
if (empty($this->emetteur->country_code)) $this->emetteur->country_code=substr($langs->defaultlang, -2); // By default, if was not defined if (empty($this->emetteur->country_code)) $this->emetteur->country_code=substr($langs->defaultlang, -2); // By default, if was not defined
// Define position of columns // Define position of columns
@ -626,7 +630,8 @@ class pdf_standard extends ModeleExpenseReport
*/ */
private function _pagehead(&$pdf, $object, $showaddress, $outputlangs) private function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
{ {
global $conf, $langs, $hookmanager; // global $conf, $langs, $hookmanager;
global $user, $langs, $conf, $mysoc, $db, $hookmanager;
// Load traductions files requiredby by page // Load traductions files requiredby by page
$outputlangs->loadLangs(array("main", "trips", "companies")); $outputlangs->loadLangs(array("main", "trips", "companies"));
@ -711,15 +716,23 @@ class pdf_standard extends ModeleExpenseReport
$carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->convToOutputCharset($this->emetteur->address); $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->convToOutputCharset($this->emetteur->address);
$carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->convToOutputCharset($this->emetteur->zip).' '.$outputlangs->convToOutputCharset($this->emetteur->town); $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->convToOutputCharset($this->emetteur->zip).' '.$outputlangs->convToOutputCharset($this->emetteur->town);
$carac_emetteur .= "\n"; $carac_emetteur .= "\n";
// Phone
if ($this->emetteur->phone) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Phone")." : ".$outputlangs->convToOutputCharset($this->emetteur->phone); if ($this->emetteur->phone) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Phone")." : ".$outputlangs->convToOutputCharset($this->emetteur->phone);
// Fax
if ($this->emetteur->fax) $carac_emetteur .= ($carac_emetteur ? ($this->emetteur->tel ? " - " : "\n") : '' ).$outputlangs->transnoentities("Fax")." : ".$outputlangs->convToOutputCharset($this->emetteur->fax); if ($this->emetteur->fax) $carac_emetteur .= ($carac_emetteur ? ($this->emetteur->tel ? " - " : "\n") : '' ).$outputlangs->transnoentities("Fax")." : ".$outputlangs->convToOutputCharset($this->emetteur->fax);
// EMail
if ($this->emetteur->email) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Email")." : ".$outputlangs->convToOutputCharset($this->emetteur->email); if ($this->emetteur->email) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Email")." : ".$outputlangs->convToOutputCharset($this->emetteur->email);
// Web
if ($this->emetteur->url) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Web")." : ".$outputlangs->convToOutputCharset($this->emetteur->url); if ($this->emetteur->url) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Web")." : ".$outputlangs->convToOutputCharset($this->emetteur->url);
// Receiver Properties
$receiver=new User($this->db);
$receiver->fetch($object->fk_user_author);
$receiver_account=new UserBankAccount($this->db);
$receiver_account->fetch(0, '', $object->fk_user_author);
$expense_receiver = '';
$expense_receiver .= ($expense_receiver ? "\n" : '' ).$outputlangs->convToOutputCharset($receiver->address);
$expense_receiver .= ($expense_receiver ? "\n" : '' ).$outputlangs->convToOutputCharset($receiver->zip).' '.$outputlangs->convToOutputCharset($receiver->town);
$expense_receiver .= "\n";
if ($receiver->email) $expense_receiver .= ($expense_receiver ? "\n" : '' ).$outputlangs->transnoentities("Email")." : ".$outputlangs->convToOutputCharset($receiver->email);
if ($receiver_account->iban) $expense_receiver .= ($expense_receiver ? "\n" : '' ).$outputlangs->transnoentities("IBAN")." : ".$outputlangs->convToOutputCharset($receiver_account->iban);
// Show sender // Show sender
$posy=50; $posy=50;
$posx=$this->marge_gauche; $posx=$this->marge_gauche;
@ -736,19 +749,28 @@ class pdf_standard extends ModeleExpenseReport
$pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
$pdf->SetTextColor(0, 0, 60); $pdf->SetTextColor(0, 0, 60);
// Show sender name
$pdf->SetXY($posx+2, $posy+3);
$pdf->SetFont('', 'B', $default_font_size);
$pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
// Show sender information // Show sender information
$pdf->SetXY($posx+2, $posy+8); if (empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
$pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx+2, $posy+3);
$pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); $pdf->SetFont('', 'B', $default_font_size);
$pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
$pdf->SetXY($posx+2, $posy+8);
$pdf->SetFont('', '', $default_font_size - 1);
$pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
} else {
$pdf->SetXY($posx+2, $posy+3);
$pdf->SetFont('', 'B', $default_font_size);
$pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset(dolGetFirstLastname($receiver->firstname, $receiver->lastname)), 0, 'L');
$pdf->SetXY($posx+2, $posy+8);
$pdf->SetFont('', '', $default_font_size - 1);
$pdf->MultiCell(80, 4, $expense_receiver, 0, 'L');
}
if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=$this->marge_gauche;
// Show recipient // Show recipient
$posy=50; $posy=50;
$posx=100; $posx=10;
// Show recipient frame // Show recipient frame
$pdf->SetTextColor(0, 0, 0); $pdf->SetTextColor(0, 0, 0);
@ -760,7 +782,8 @@ class pdf_standard extends ModeleExpenseReport
// Informations for trip (dates and users workflow) // Informations for trip (dates and users workflow)
if ($object->fk_user_author > 0) { if ($object->fk_user_author > 0) {
$userfee=new User($this->db); $userfee=new User($this->db);
$userfee->fetch($object->fk_user_author); $posy+=3; $userfee->fetch($object->fk_user_author);
$posy+=3;
$pdf->SetXY($posx+2, $posy); $pdf->SetXY($posx+2, $posy);
$pdf->SetFont('', '', 10); $pdf->SetFont('', '', 10);
$pdf->MultiCell(96, 4, $outputlangs->transnoentities("AUTHOR")." : ".dolGetFirstLastname($userfee->firstname, $userfee->lastname), 0, 'L'); $pdf->MultiCell(96, 4, $outputlangs->transnoentities("AUTHOR")." : ".dolGetFirstLastname($userfee->firstname, $userfee->lastname), 0, 'L');

View File

@ -180,6 +180,9 @@ class pdf_sponge extends ModelePDFFactures
// Define position of columns // Define position of columns
$this->posxdesc=$this->marge_gauche+1; // used for notes ans other stuff $this->posxdesc=$this->marge_gauche+1; // used for notes ans other stuff
$this->tabTitleHeight = 5; // default height
// Use new system for position of columns, view $this->defineColumnField() // Use new system for position of columns, view $this->defineColumnField()
$this->tva=array(); $this->tva=array();
@ -217,6 +220,11 @@ class pdf_sponge extends ModelePDFFactures
$nblignes = count($object->lines); $nblignes = count($object->lines);
$hidetop=0;
if(!empty($conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE)){
$hidetop=$conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE;
}
// Loop on each lines to detect if there is at least one image to show // Loop on each lines to detect if there is at least one image to show
$realpatharray=array(); $realpatharray=array();
$this->atleastonephoto = false; $this->atleastonephoto = false;
@ -549,13 +557,18 @@ class pdf_sponge extends ModelePDFFactures
$height_note=0; $height_note=0;
} }
$iniY = $tab_top + 7;
$curY = $tab_top + 7;
$nexY = $tab_top + 7;
// Use new auto collum system // Use new auto collum system
$this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
// Simulation de tableau pour connaitre la hauteur de la ligne de titre
$pdf->startTransaction();
$this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
$pdf->rollbackTransaction(true);
$iniY = $tab_top + $this->tabTitleHeight + 2;
$curY = $tab_top + $this->tabTitleHeight + 2;
$nexY = $tab_top + $this->tabTitleHeight + 2;
// Loop on each lines // Loop on each lines
$pageposbeforeprintlines=$pdf->getPage(); $pageposbeforeprintlines=$pdf->getPage();
$pagenb = $pageposbeforeprintlines; $pagenb = $pageposbeforeprintlines;
@ -786,7 +799,7 @@ class pdf_sponge extends ModelePDFFactures
$pdf->setPage($pagenb); $pdf->setPage($pagenb);
if ($pagenb == $pageposbeforeprintlines) if ($pagenb == $pageposbeforeprintlines)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
} }
else else
{ {
@ -803,7 +816,7 @@ class pdf_sponge extends ModelePDFFactures
{ {
if ($pagenb == $pageposafter) if ($pagenb == $pageposafter)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
} }
else else
{ {
@ -821,7 +834,7 @@ class pdf_sponge extends ModelePDFFactures
// Show square // Show square
if ($pagenb == $pageposbeforeprintlines) if ($pagenb == $pageposbeforeprintlines)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
$bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
} }
else else
@ -1541,30 +1554,13 @@ class pdf_sponge extends ModelePDFFactures
$this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param
foreach ($this->cols as $colKey => $colDef) $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
{
if(!$this->getColumnStatus($colKey)) continue;
// get title label
$colDef['title']['label'] = !empty($colDef['title']['label'])?$colDef['title']['label']:$outputlangs->transnoentities($colDef['title']['textkey']);
// Add column separator
if(!empty($colDef['border-left'])){
$pdf->line($colDef['xStartPos'], $tab_top, $colDef['xStartPos'], $tab_top + $tab_height);
}
if (empty($hidetop))
{
$pdf->SetXY($colDef['xStartPos'] + $colDef['title']['padding'][3], $tab_top + $colDef['title']['padding'][0]);
$textWidth = $colDef['width'] - $colDef['title']['padding'][3] -$colDef['title']['padding'][1];
$pdf->MultiCell($textWidth, 2, $colDef['title']['label'], '', $colDef['title']['align']);
}
}
if (empty($hidetop)){ if (empty($hidetop)){
$pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); // line prend une position y en 2eme param et 4eme param $pdf->line($this->marge_gauche, $tab_top+$this->tabTitleHeight, $this->page_largeur-$this->marge_droite, $tab_top+$this->tabTitleHeight); // line prend une position y en 2eme param et 4eme param
} }
} }
/** /**

View File

@ -1,9 +1,9 @@
<?php <?php
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com> /* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2018 Alexandre Spangaro <aspangaro@open-dsi.fr> * Copyright (C) 2013-2019 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2014 Ari Elbaz (elarifr) <github@accedinfo.com> * Copyright (C) 2014 Ari Elbaz (elarifr) <github@accedinfo.com>
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro> * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2016-2017 Laurent Destailleur <eldy@users.sourceforge.net> * Copyright (C) 2016-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2017 Open-DSI <support@open-dsi.fr> * Copyright (C) 2017 Open-DSI <support@open-dsi.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -22,8 +22,8 @@
/** /**
* \file htdocs/core/modules/modAccounting.class.php * \file htdocs/core/modules/modAccounting.class.php
* \ingroup Advanced accountancy * \ingroup Double entry accounting
* \brief Module to activate Accounting Expert module * \brief Module to activate the double entry accounting module
*/ */
include_once DOL_DOCUMENT_ROOT .'/core/modules/DolibarrModules.class.php'; include_once DOL_DOCUMENT_ROOT .'/core/modules/DolibarrModules.class.php';
@ -48,7 +48,7 @@ class modAccounting extends DolibarrModules
$this->module_position = '61'; $this->module_position = '61';
// Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module)
$this->name = preg_replace('/^mod/i', '', get_class($this)); $this->name = preg_replace('/^mod/i', '', get_class($this));
$this->description = "Advanced accounting management"; $this->description = "Double entry accounting management";
// Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version // Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version
$this->version = 'dolibarr'; $this->version = 'dolibarr';

View File

@ -169,6 +169,7 @@ class pdf_cyan extends ModelePDFPropales
$this->posxdesc=$this->marge_gauche+1; $this->posxdesc=$this->marge_gauche+1;
$this->tabTitleHeight = 5; // default height
$this->tva=array(); $this->tva=array();
$this->localtax1=array(); $this->localtax1=array();
@ -207,6 +208,11 @@ class pdf_cyan extends ModelePDFPropales
$nblignes = count($object->lines); $nblignes = count($object->lines);
$hidetop=0;
if(!empty($conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE)){
$hidetop=$conf->global->MAIN_PDF_DISABLE_COL_HEAD_TITLE;
}
// Loop on each lines to detect if there is at least one image to show // Loop on each lines to detect if there is at least one image to show
$realpatharray=array(); $realpatharray=array();
$this->atleastonephoto = false; $this->atleastonephoto = false;
@ -536,13 +542,18 @@ class pdf_cyan extends ModelePDFPropales
$height_note=0; $height_note=0;
} }
$iniY = $tab_top + 7;
$curY = $tab_top + 7;
$nexY = $tab_top + 7;
// Use new auto collum system // Use new auto collum system
$this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
// Simulation de tableau pour connaitre la hauteur de la ligne de titre
$pdf->startTransaction();
$this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
$pdf->rollbackTransaction(true);
$iniY = $tab_top + $this->tabTitleHeight + 2;
$curY = $tab_top + $this->tabTitleHeight + 2;
$nexY = $tab_top + $this->tabTitleHeight + 2;
// Loop on each lines // Loop on each lines
$pageposbeforeprintlines=$pdf->getPage(); $pageposbeforeprintlines=$pdf->getPage();
$pagenb = $pageposbeforeprintlines; $pagenb = $pageposbeforeprintlines;
@ -761,7 +772,7 @@ class pdf_cyan extends ModelePDFPropales
$pdf->setPage($pagenb); $pdf->setPage($pagenb);
if ($pagenb == $pageposbeforeprintlines) if ($pagenb == $pageposbeforeprintlines)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
} }
else else
{ {
@ -777,7 +788,7 @@ class pdf_cyan extends ModelePDFPropales
{ {
if ($pagenb == $pageposafter) if ($pagenb == $pageposafter)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code);
} }
else else
{ {
@ -795,7 +806,7 @@ class pdf_cyan extends ModelePDFPropales
// Show square // Show square
if ($pagenb == $pageposbeforeprintlines) if ($pagenb == $pageposbeforeprintlines)
{ {
$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code); $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code);
$bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1; $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1;
} }
else else
@ -1448,29 +1459,10 @@ class pdf_cyan extends ModelePDFPropales
$this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect prend une longueur en 3eme param et 4eme param
foreach ($this->cols as $colKey => $colDef) $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
{
if(!$this->getColumnStatus($colKey)) continue;
// get title label
$colDef['title']['label'] = !empty($colDef['title']['label'])?$colDef['title']['label']:$outputlangs->transnoentities($colDef['title']['textkey']);
// Add column separator
if(!empty($colDef['border-left'])){
$pdf->line($colDef['xStartPos'], $tab_top, $colDef['xStartPos'], $tab_top + $tab_height);
}
if (empty($hidetop))
{
$pdf->SetXY($colDef['xStartPos'] + $colDef['title']['padding'][3], $tab_top + $colDef['title']['padding'][0]);
$textWidth = $colDef['width'] - $colDef['title']['padding'][3] -$colDef['title']['padding'][1];
$pdf->MultiCell($textWidth, 2, $colDef['title']['label'], '', $colDef['title']['align']);
}
}
if (empty($hidetop)){ if (empty($hidetop)){
$pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); // line prend une position y en 2eme param et 4eme param $pdf->line($this->marge_gauche, $tab_top+$this->tabTitleHeight, $this->page_largeur-$this->marge_droite, $tab_top+$this->tabTitleHeight); // line prend une position y en 2eme param et 4eme param
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -23,10 +23,10 @@ if (! empty($extrafieldsobjectkey)) // $extrafieldsobject is the $object->table_
$align=$extrafields->getAlignFlag($key); $align=$extrafields->getAlignFlag($key);
$typeofextrafield=$extrafields->attributes[$extrafieldsobjectkey]['type'][$key]; $typeofextrafield=$extrafields->attributes[$extrafieldsobjectkey]['type'][$key];
print '<td class="liste_titre'.($align?' '.$align:'').'">'; print '<td class="liste_titre'.($align?' '.$align:'').'">';
$tmpkey=preg_replace('/'.$search_options_pattern.'/', '', $key);
if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')) && empty($extrafields->attributes[$extrafieldsobjectkey]['computed'][$key])) if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')) && empty($extrafields->attributes[$extrafieldsobjectkey]['computed'][$key]))
{ {
$crit=$val; $crit=$val;
$tmpkey=preg_replace('/'.$search_options_pattern.'/', '', $key);
$searchclass=''; $searchclass='';
if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring'; if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring';
if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum'; if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum';
@ -37,7 +37,7 @@ if (! empty($extrafieldsobjectkey)) // $extrafieldsobject is the $object->table_
// for the type as 'checkbox', 'chkbxlst', 'sellist' we should use code instead of id (example: I declare a 'chkbxlst' to have a link with dictionnairy, I have to extend it with the 'code' instead 'rowid') // for the type as 'checkbox', 'chkbxlst', 'sellist' we should use code instead of id (example: I declare a 'chkbxlst' to have a link with dictionnairy, I have to extend it with the 'code' instead 'rowid')
$morecss=''; $morecss='';
if ($typeofextrafield == 'sellist') $morecss='maxwidth200'; if ($typeofextrafield == 'sellist') $morecss='maxwidth200';
echo $extrafields->showInputField($key, $search_array_options[$search_options_pattern.$key], '', '', 'search_', $morecss); echo $extrafields->showInputField($key, $search_array_options[$search_options_pattern.$tmpkey], '', '', $search_options_pattern, $morecss);
} }
elseif (in_array($typeofextrafield, array('datetime','timestamp'))) elseif (in_array($typeofextrafield, array('datetime','timestamp')))
{ {

View File

@ -21,6 +21,7 @@ $out .= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
$out .= '<input type="hidden" name="action" value="add_element_resource">'; $out .= '<input type="hidden" name="action" value="add_element_resource">';
$out .= '<input type="hidden" name="element" value="'.$element.'">'; $out .= '<input type="hidden" name="element" value="'.$element.'">';
$out .= '<input type="hidden" name="element_id" value="'.$element_id.'">'; $out .= '<input type="hidden" name="element_id" value="'.$element_id.'">';
$out .= '<input type="hidden" name="ref" value="'.$element_ref.'">';
$out .= '<input type="hidden" name="resource_type" value="'.(empty($resource_type) ? 'dolresource' : $resource_type).'">'; $out .= '<input type="hidden" name="resource_type" value="'.(empty($resource_type) ? 'dolresource' : $resource_type).'">';

View File

@ -607,7 +607,7 @@ class Expedition extends CommonObject
$this->getUrlTrackingStatus($obj->tracking_number); $this->getUrlTrackingStatus($obj->tracking_number);
/* /*
* Thirparty * Thirdparty
*/ */
$result=$this->fetch_thirdparty(); $result=$this->fetch_thirdparty();

View File

@ -233,7 +233,7 @@ Limit=Limit
Limits=Limits Limits=Limits
Logout=Abmelden Logout=Abmelden
NoLogoutProcessWithAuthMode=Keine Anwendung Trennungsfunktion mit Authentifizierungsmodus <b>% s </ b> NoLogoutProcessWithAuthMode=Keine Anwendung Trennungsfunktion mit Authentifizierungsmodus <b>% s </ b>
Connection=Benutzername Connection=Anmelden
Setup=Einstellungen Setup=Einstellungen
Alert=Warnung Alert=Warnung
MenuWarnings=Benachrichtigungen MenuWarnings=Benachrichtigungen

View File

@ -494,7 +494,7 @@ Module1Name=Third Parties
Module1Desc=Companies and contacts management (customers, prospects...) Module1Desc=Companies and contacts management (customers, prospects...)
Module2Name=Commercial Module2Name=Commercial
Module2Desc=Commercial management Module2Desc=Commercial management
Module10Name=Accounting Module10Name=Accounting (simplified)
Module10Desc=Simple accounting reports (journals, turnover) based on database content. Does not use any ledger table. Module10Desc=Simple accounting reports (journals, turnover) based on database content. Does not use any ledger table.
Module20Name=Proposals Module20Name=Proposals
Module20Desc=Commercial proposal management Module20Desc=Commercial proposal management
@ -632,7 +632,7 @@ Module50200Name=Paypal
Module50200Desc=Offer customers a PayPal online payment page (PayPal account or credit/debit cards). This can be used to allow your customers to make ad-hoc payments or payments related to a specific Dolibarr object (invoice, order etc...) Module50200Desc=Offer customers a PayPal online payment page (PayPal account or credit/debit cards). This can be used to allow your customers to make ad-hoc payments or payments related to a specific Dolibarr object (invoice, order etc...)
Module50300Name=Stripe Module50300Name=Stripe
Module50300Desc=Offer customers a Stripe online payment page (credit/debit cards). This can be used to allow your customers to make ad-hoc payments or payments related to a specific Dolibarr object (invoice, order etc...) Module50300Desc=Offer customers a Stripe online payment page (credit/debit cards). This can be used to allow your customers to make ad-hoc payments or payments related to a specific Dolibarr object (invoice, order etc...)
Module50400Name=Accounting (advanced) Module50400Name=Accounting (double entry)
Module50400Desc=Accounting management (double entries, support general and auxiliary ledgers). Export the ledger in several other accounting software formats. Module50400Desc=Accounting management (double entries, support general and auxiliary ledgers). Export the ledger in several other accounting software formats.
Module54000Name=PrintIPP Module54000Name=PrintIPP
Module54000Desc=Direct print (without opening the documents) using Cups IPP interface (Printer must be visible from server, and CUPS must be installed on server). Module54000Desc=Direct print (without opening the documents) using Cups IPP interface (Printer must be visible from server, and CUPS must be installed on server).

View File

@ -300,7 +300,7 @@ class PriceParser
} }
//Get the product data (use ignore_expression to avoid possible recursion) //Get the product data (use ignore_expression to avoid possible recursion)
$product_supplier->fetch($product_supplier->id, '', '', 1); $product_supplier->fetch($product_supplier->id, '', '', '', 1);
//Accessible values by expressions //Accessible values by expressions
$extra_values = array_merge($extra_values, array( $extra_values = array_merge($extra_values, array(

View File

@ -444,7 +444,7 @@ class Reception extends CommonObject
$this->getUrlTrackingStatus($obj->tracking_number); $this->getUrlTrackingStatus($obj->tracking_number);
/* /*
* Thirparty * Thirdparty
*/ */
$result=$this->fetch_thirdparty(); $result=$this->fetch_thirdparty();

View File

@ -31,6 +31,9 @@ if (! empty($conf->projet->enabled)) {
require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php'; require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
} }
if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) {
require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
}
// Load translation files required by the page // Load translation files required by the page
$langs->loadLangs(array('resource', 'other', 'interventions')); $langs->loadLangs(array('resource', 'other', 'interventions'));
@ -79,7 +82,6 @@ if ($socid > 0) // Special for thirdparty
if ($action == 'add_element_resource' && ! $cancel) if ($action == 'add_element_resource' && ! $cancel)
{ {
$error++;
$res = 0; $res = 0;
if (! ($resource_id > 0)) if (! ($resource_id > 0))
{ {
@ -89,16 +91,20 @@ if ($action == 'add_element_resource' && ! $cancel)
} }
else else
{ {
$objstat = fetchObjectByElement($element_id, $element); $objstat = fetchObjectByElement($element_id, $element, $element_ref);
$objstat->element = $element; // For externals module, we need to keep @xx $objstat->element = $element; // For externals module, we need to keep @xx
$res = $objstat->add_element_resource($resource_id, $resource_type, $busy, $mandatory); $res = $objstat->add_element_resource($resource_id, $resource_type, $busy, $mandatory);
} }
if (! $error && $res > 0) if (! $error && $res > 0)
{ {
setEventMessages($langs->trans('ResourceLinkedWithSuccess'), null, 'mesgs'); setEventMessages($langs->trans('ResourceLinkedWithSuccess'), null, 'mesgs');
header("Location: ".$_SERVER['PHP_SELF'].'?element='.$element.'&element_id='.$element_id); header("Location: ".$_SERVER['PHP_SELF'].'?element='.$element.'&element_id='.$objstat->id);
exit; exit;
} }
else if ($objstat)
{
setEventMessages($objstat->error, $objstat->errors, 'errors');
}
} }
// Update ressource // Update ressource
@ -415,6 +421,31 @@ else
dol_fiche_end(); dol_fiche_end();
} }
} }
// Specific to product/service module
if (($element_id || $element_ref) && ($element == 'product' || $element == 'service'))
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
$product = new Product($db);
$product->fetch($element_id, $element_ref);
if (is_object($product))
{
$head = product_prepare_head($product);
$titre=$langs->trans("CardProduct".$product->type);
$picto=($product->type==Product::TYPE_SERVICE?'service':'product');
dol_fiche_head($head, 'resources', $titre, -1, $picto);
$shownav = 1;
if ($user->societe_id && ! in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) $shownav=0;
dol_banner_tab($product, 'ref', '', $shownav, 'ref', 'ref', '', '&element='.$element);
dol_fiche_end();
}
}
// hook for other elements linked // hook for other elements linked

View File

@ -1457,7 +1457,7 @@ class Societe extends CommonObject
* Delete a third party from database and all its dependencies (contacts, rib...) * Delete a third party from database and all its dependencies (contacts, rib...)
* *
* @param int $id Id of third party to delete * @param int $id Id of third party to delete
* @param User $fuser User who ask to delete thirparty * @param User $fuser User who ask to delete thirdparty
* @param int $call_trigger 0=No, 1=yes * @param int $call_trigger 0=No, 1=yes
* @return int <0 if KO, 0 if nothing done, >0 if OK * @return int <0 if KO, 0 if nothing done, >0 if OK
*/ */

View File

@ -77,7 +77,7 @@ top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
<script type="text/javascript" src="js/jquery.colorbox-min.js"></script> <!-- TODO It seems we don't need this --> <script type="text/javascript" src="js/jquery.colorbox-min.js"></script> <!-- TODO It seems we don't need this -->
<script language="javascript"> <script language="javascript">
<?php <?php
$categories = $categorie->get_full_arbo('product', 0, (($conf->global->TAKEPOS_ROOT_CATEGORY_ID > 0)?$conf->global->TAKEPOS_ROOT_CATEGORY_ID:0)); $categories = $categorie->get_full_arbo('product', (($conf->global->TAKEPOS_ROOT_CATEGORY_ID > 0)?$conf->global->TAKEPOS_ROOT_CATEGORY_ID:0), 1);
// Search root category to know its level // Search root category to know its level