Merge remote-tracking branch 'Upstream/develop' into develop-ReviewAssoc

Conflicts:
	htdocs/install/mysql/migration/3.7.0-3.8.0.sql
This commit is contained in:
aspangaro 2015-03-23 06:58:25 +01:00
commit be0ab4c9b4
325 changed files with 6167 additions and 338 deletions

View File

@ -104,16 +104,15 @@ before_script:
script:
- cd htdocs/install
- date
# - php upgrade.php 3.4.0 3.5.0 > upgrade.log
# - php upgrade2.php 3.4.0 3.5.0 > upgrade2.log
- php upgrade.php 3.5.0 3.6.0 >> upgrade.log
- php upgrade2.php 3.5.0 3.6.0 >> upgrade2.log
- php upgrade.php 3.6.0 3.7.0 >> upgrade.log
# - cat upgrade360370.log
- php upgrade2.php 3.6.0 3.7.0 >> upgrade2.log
- php upgrade.php 3.7.0 3.8.0 >> upgrade.log
- php upgrade2.php 3.7.0 3.8.0 >> upgrade2.log
# - cat upgrade2.log
# - php upgrade.php 3.4.0 3.5.0 ignoredbversion > upgrade340350.log
# - php upgrade2.php 3.4.0 3.5.0 ignoredbversion > upgrade340350-2.log
- php upgrade.php 3.5.0 3.6.0 ignoredbversion > upgrade350360.log
- php upgrade2.php 3.5.0 3.6.0 ignoredbversion > upgrade350360-2.log
- php upgrade.php 3.6.0 3.7.0 ignoredbversion > upgrade360370.log
- php upgrade2.php 3.6.0 3.7.0 ignoredbversion > upgrade360370-2.log
- php upgrade.php 3.7.0 3.8.0 ignoredbversion > upgrade370380.log
- php upgrade2.php 3.7.0 3.8.0 ignoredbversion > upgrade370380-2.log
# - cat upgrade370380-2.log
- cd ../..
- date
- phpunit -d memory_limit=-1 --configuration test/phpunit/phpunittest.xml test/phpunit/AllTests.php

View File

@ -174,7 +174,7 @@ $targetcontent=$sourcecontent;
// Substitute class name
$targetcontent=preg_replace('/skeleton_class\.class\.php/', $classmin.'.class.php', $targetcontent);
$targetcontent=preg_replace('/\$element=\'skeleton\'/', '\$element=\''.$classmin.'\'', $targetcontent);
$targetcontent=preg_replace('/\$table_element=\'skeleton\'/', '\$table_element=\''.$classmin.'\'', $targetcontent);
$targetcontent=preg_replace('/\$table_element=\'skeleton\'/', '\$table_element=\''.$tablenoprefix.'\'', $targetcontent);
$targetcontent=preg_replace('/Skeleton_Class/', $classname, $targetcontent);
// Substitute comments
@ -252,7 +252,13 @@ foreach($property as $key => $prop)
if ($addfield)
{
$varprop.="\t\t\$sql.= \" ";
if ($prop['istime'])
if ($prop['field']=='datec')
{
$varprop.='"."\'".$this->db->idate(dol_now())."\'"."';
if ($i < count($property)) $varprop.=",";
$varprop.='";';
}
elseif ($prop['istime'])
{
$varprop.='".(! isset($this->'.$prop['field'].') || dol_strlen($this->'.$prop['field'].')==0?\'NULL\':"\'".$this->db->idate(';
$varprop.="\$this->".$prop['field']."";
@ -268,6 +274,12 @@ foreach($property as $key => $prop)
if ($i < count($property)) $varprop.=",";
$varprop.='";';
}
elseif ($prop['field']=='fk_user_mod' || $prop['field']=='fk_user_author')
{
$varprop.='".$user->id."';
if ($i < count($property)) $varprop.=",";
$varprop.='";';
}
else
{
$varprop.='".(! isset($this->'.$prop['field'].')?\'NULL\':"\'".';
@ -289,11 +301,17 @@ $i=0;
foreach($property as $key => $prop)
{
$i++;
if ($prop['field'] != 'rowid' && $prop['field'] != 'id')
if ($prop['field'] != 'rowid' && $prop['field'] != 'id' && $prop['field'] != 'datec' && $prop['field'] != 'fk_user_author')
{
$varprop.="\t\t\$sql.= \" ";
$varprop.=$prop['field'].'=';
if ($prop['istime'])
if ($prop['field']=='tms') {
$varprop.='".(dol_strlen($this->'.$prop['field'].')!=0 ? "\'".$this->db->idate(';
$varprop.='$this->'.$prop['field'];
$varprop.=')."\'" : "\'".$this->db->idate(dol_now())."\'").';
$varprop.='"';
}
elseif ($prop['istime'])
{
// (dol_strlen($this->datep)!=0 ? "'".$this->db->idate($this->datep)."'" : 'null')
$varprop.='".(dol_strlen($this->'.$prop['field'].')!=0 ? "\'".$this->db->idate(';
@ -301,6 +319,9 @@ foreach($property as $key => $prop)
$varprop.=')."\'" : \'null\').';
$varprop.='"';
}
elseif ($prop['field']=='fk_user_mod') {
$varprop.='".$user->id."';
}
else
{
$varprop.="\".";
@ -325,6 +346,7 @@ $targetcontent=preg_replace('/\$sql\.= " t\.field2";/', '', $targetcontent);
// Substitute select set parameters
$varprop="\n";
$varpropline="\n";
$cleanparam='';
$i=0;
foreach($property as $key => $prop)
@ -338,11 +360,22 @@ foreach($property as $key => $prop)
if ($prop['istime']) $varprop.=')';
$varprop.=";";
$varprop.="\n";
$varpropline.="\t\t\t\t\$line->".$prop['field']." = ";
if ($prop['istime']) $varpropline.='$this->db->jdate(';
$varpropline.='$obj->'.$prop['field'];
if ($prop['istime']) $varpropline.=')';
$varpropline.=";";
$varpropline.="\n";
}
}
$targetcontent=preg_replace('/\$this->prop1 = \$obj->field1;/', $varprop, $targetcontent);
$targetcontent=preg_replace('/\$this->prop2 = \$obj->field2;/', '', $targetcontent);
//Substirute fetchAll
$targetcontent=preg_replace('/\$line->prop1 = \$obj->field1;/', $varpropline, $targetcontent);
$targetcontent=preg_replace('/\$line->prop2 = \$obj->field2;/', '', $targetcontent);
// Substitute initasspecimen parameters
$varprop="\n";

View File

@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) ---Put here your own copyright and developer email---
*
* This program is free software; you can redistribute it and/or modify
@ -41,6 +42,8 @@ class Skeleton_Class extends CommonObject
var $element='skeleton'; //!< Id that identify managed objects
var $table_element='skeleton'; //!< Name of table without prefix where object is stored
var $lines=array();
var $id;
var $prop1;
var $prop2;
@ -103,11 +106,11 @@ class Skeleton_Class extends CommonObject
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// want this action to call a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_CREATE',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//if ($result < 0) $error++;
//// End call triggers
}
}
@ -115,11 +118,6 @@ class Skeleton_Class extends CommonObject
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(__METHOD__." ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
@ -175,6 +173,69 @@ class Skeleton_Class extends CommonObject
}
}
/**
* Load object in memory from the database
*
* @param string $sortorder Sort Order
* @param string $sortfield Sort field
* @param int $limit offset limit
* @param int $offset offset limit
* @param array $filter filter array
* @return int <0 if KO, >0 if OK
*/
function fetchAll($sortorder, $sortfield, $limit, $offset, $filter = array())
{
global $langs;
$sql = "SELECT";
$sql.= " t.rowid,";
$sql.= " t.field1,";
$sql.= " t.field2";
//...
$sql.= " FROM ".MAIN_DB_PREFIX."mytable as t";
// Manage filter
$sqlwhere=array();
if (count($filter)>0) {
foreach ( $filter as $key => $value ) {
//$sqlwhere []= ' AND '. $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
}
}
if (count($sqlwhere)>0) {
$sql.= ' WHERE '.implode(' AND ', $sqlwhere);
}
$sql .= " ORDER BY " . $sortfield . " " . $sortorder . " " . $this->db->plimit($limit + 1, $offset);
$this->lines = array ();
dol_syslog(get_class($this)."::fetchAll", LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
{
$num = $this->db->num_rows($resql);
while ($obj = $this->db->fetch_object($resql))
{
$line=new Skeleton_ClassLine();
$line->id = $obj->rowid;
$line->prop1 = $obj->field1;
$line->prop2 = $obj->field2;
$this->line[]=$line;
//...
}
$this->db->free($resql);
return $num;
}
else
{
$this->error="Error ".$this->db->lasterror();
dol_syslog(get_class($this)."::fetchAll ".$this->error, LOG_ERR);
return -1;
}
}
/**
* Update object into database
@ -368,3 +429,10 @@ class Skeleton_Class extends CommonObject
}
}
class Skeleton_ClassLine
{
var $id;
var $prop1;
var $prop2;
}

View File

@ -249,7 +249,11 @@ if ($action == 'export_csv')
$purchase_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=journal_achats.csv');
if ($conf->global->EXPORT_PREFIX_SPEC)
$filename=$conf->global->EXPORT_PREFIX_SPEC."_"."journal_achats.csv";
else
$filename="journal_achats.csv";
header('Content-Disposition: attachment;filename='.$filename);
if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 2) // Model Cegid Expert Export
{

View File

@ -271,7 +271,11 @@ if ($action == 'export_csv')
$sell_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=journal_ventes.csv');
if ($conf->global->EXPORT_PREFIX_SPEC)
$filename=$conf->global->EXPORT_PREFIX_SPEC."_"."journal_ventes.csv";
else
$filename="journal_ventes.csv";
header('Content-Disposition: attachment;filename='.$filename);
$companystatic = new Client($db);

View File

@ -62,7 +62,7 @@ class box_contacts extends ModeleBoxes
if ($user->rights->societe->lire)
{
$sql = "SELECT sp.rowid, sp.lastname, sp.firstname, sp.civility as civility_id, sp.datec, sp.tms, sp.fk_soc";
$sql = "SELECT sp.rowid as id, sp.lastname, sp.firstname, sp.civility as civility_id, sp.datec, sp.tms, sp.fk_soc";
$sql.= ", s.nom as socname";
$sql.= ", s.code_client";
$sql.= " FROM ".MAIN_DB_PREFIX."socpeople as sp";
@ -87,7 +87,8 @@ class box_contacts extends ModeleBoxes
$datec=$db->jdate($objp->datec);
$datem=$db->jdate($objp->tms);
$contactstatic->lastname=$objp->lastname;
$contactstatic->id=$objp->id;
$contactstatic->lastname=$objp->lastname;
$contactstatic->firstname=$objp->firstname;
$contactstatic->civility_id=$objp->civility_id;

View File

@ -567,10 +567,12 @@ class ExtraFields
{
global $conf;
if ( empty($elementtype) ) return array();
if ($elementtype == 'thirdparty') $elementtype='societe';
$array_name_label=array();
// For avoid conflicts with external modules
if (!$forceload && !empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) return $array_name_label;
@ -1054,6 +1056,7 @@ class ExtraFields
elseif ($type == 'link')
{
$out='';
$param_list=array_keys($param['options']);
// 0 : ObjectName
// 1 : classPath
@ -1292,14 +1295,15 @@ class ExtraFields
elseif ($type == 'link')
{
$out='';
$param_list=array_keys($params['options']);
// 0 : ObjectName
// 1 : classPath
$InfoFieldList = explode(":", $param_list[0]);
dol_include_once($InfoFieldList[1]);
$object = new $InfoFieldList[0]($this->db);
// only if something to display (perf)
if ($value)
{
$param_list=array_keys($params['options']);
// 0 : ObjectName
// 1 : classPath
$InfoFieldList = explode(":", $param_list[0]);
dol_include_once($InfoFieldList[1]);
$object = new $InfoFieldList[0]($this->db);
$object->fetch($value);
$value=$object->getNomUrl(3);
}

View File

@ -1643,7 +1643,7 @@ class Form
if ($result)
{
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$num = $this->db->num_rows($result);
$out.='<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';
@ -2024,7 +2024,7 @@ class Form
$result=$this->db->query($sql);
if ($result)
{
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$num = $this->db->num_rows($result);
@ -2193,7 +2193,7 @@ class Form
}
else
{
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$form.= '<option value="0">&nbsp;</option>';
$i = 0;

View File

@ -782,7 +782,7 @@ class FormOther
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$montharray = monthArray($langs); // Get array
$montharray = monthArray($langs, 1); // Get array
$select_month = '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';
if ($useempty)

View File

@ -813,11 +813,12 @@ function num_open_day($timestampStart, $timestampEnd, $inhour=0, $lastday=0, $ha
* This replace old function monthArrayOrSelected.
*
* @param Translate $outputlangs Object langs
* @param int $short 1=Return short label
* @return array Month string or array if selected < 0
*/
function monthArray($outputlangs)
function monthArray($outputlangs,$short=0)
{
$montharray = array (
$montharray = array (
1 => $outputlangs->trans("January"),
2 => $outputlangs->trans("February"),
3 => $outputlangs->trans("March"),
@ -832,6 +833,24 @@ function monthArray($outputlangs)
12 => $outputlangs->trans("December")
);
return $montharray;
if (! empty($short))
{
$montharray = array (
1 => $outputlangs->trans("Jan"),
2 => $outputlangs->trans("Feb"),
3 => $outputlangs->trans("Mar"),
4 => $outputlangs->trans("Apr"),
5 => $outputlangs->trans("May"),
6 => $outputlangs->trans("Jun"),
7 => $outputlangs->trans("Jul"),
8 => $outputlangs->trans("Aug"),
9 => $outputlangs->trans("Sep"),
10 => $outputlangs->trans("Oct"),
11 => $outputlangs->trans("Nov"),
12 => $outputlangs->trans("Dec")
);
}
return $montharray;
}

View File

@ -592,16 +592,17 @@ function dol_strtoupper($utf8_string)
* This function works only if syslog module is enabled.
* This must not use any call to other function calling dol_syslog (avoid infinite loop).
*
* @param string $message Line to log. Ne doit pas etre traduit si level = LOG_ERR
* @param int $level Log level
* 0=Show nothing
* On Windows LOG_ERR=4, LOG_WARNING=5, LOG_NOTICE=LOG_INFO=6, LOG_DEBUG=6 si define_syslog_variables ou PHP 5.3+, 7 si dolibarr
* On Linux LOG_ERR=3, LOG_WARNING=4, LOG_INFO=6, LOG_DEBUG=7
* @param int $ident 1=Increase ident of 1, -1=Decrease ident of 1
* @param string $suffixinfilename When output is a file, append this suffix into default log filename.
* @param string $message Line to log.
* @param int $level Log level
* 0=Show nothing
* On Windows LOG_ERR=4, LOG_WARNING=5, LOG_NOTICE=LOG_INFO=6, LOG_DEBUG=6 si define_syslog_variables ou PHP 5.3+, 7 si dolibarr
* On Linux LOG_ERR=3, LOG_WARNING=4, LOG_INFO=6, LOG_DEBUG=7
* @param int $ident 1=Increase ident of 1, -1=Decrease ident of 1
* @param string $suffixinfilename When output is a file, append this suffix into default log filename.
* @param string $restricttologhandler Output log only for this log handler
* @return void
*/
function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename='')
function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename='', $restricttologhandler='')
{
global $conf, $user;
@ -624,7 +625,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename='
$conf->logbuffer[] = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".$message;
}
//TODO: Remove this. MAIN_ENABLE_LOG_HTML should be deprecated and use a HTML handler
//TODO: Remove this. MAIN_ENABLE_LOG_HTML should be deprecated and use a log handler dedicated to HTML output
// If enable html log tag enabled and url parameter log defined, we show output log on HTML comments
if (! empty($conf->global->MAIN_ENABLE_LOG_HTML) && ! empty($_GET["log"]))
{
@ -648,10 +649,10 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename='
else if (! empty($_SERVER['COMPUTERNAME'])) $data['ip'] = $_SERVER['COMPUTERNAME'].(empty($_SERVER['USERNAME'])?'':'@'.$_SERVER['USERNAME']);
// This is when PHP session is ran outside a web server, like from Linux command line (Not always defined, but usefull if OS defined it).
else if (! empty($_SERVER['LOGNAME'])) $data['ip'] = '???@'.$_SERVER['LOGNAME'];
// Loop on each log handler and send output
foreach ($conf->loghandlers as $loghandlerinstance)
{
if ($restricttologhandler && $loghandlerinstance->code != $restricttologhandler) continue;
$loghandlerinstance->export($data,$suffixinfilename);
}
unset($data);
@ -2279,15 +2280,16 @@ function img_previous($titlealt = 'default')
*
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
* @param int $selected Selected
* @param string $moreclass Add more CSS classes
* @return string Return img tag
*/
function img_down($titlealt = 'default', $selected = 0)
function img_down($titlealt = 'default', $selected = 0, $moreclass='')
{
global $conf, $langs;
if ($titlealt == 'default') $titlealt = $langs->trans('Down');
return img_picto($titlealt, ($selected ? '1downarrow_selected.png' : '1downarrow.png'), 'class="imgdown"');
return img_picto($titlealt, ($selected ? '1downarrow_selected.png' : '1downarrow.png'), 'class="imgdown'.($moreclass?" ".$moreclass:"").'"');
}
/**
@ -2295,15 +2297,16 @@ function img_down($titlealt = 'default', $selected = 0)
*
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
* @param int $selected Selected
* @param string $moreclass Add more CSS classes
* @return string Return img tag
*/
function img_up($titlealt = 'default', $selected = 0)
function img_up($titlealt = 'default', $selected = 0, $moreclass='')
{
global $conf, $langs;
if ($titlealt == 'default') $titlealt = $langs->trans('Up');
return img_picto($titlealt, ($selected ? '1uparrow_selected.png' : '1uparrow.png'), 'class="imgup"');
return img_picto($titlealt, ($selected ? '1uparrow_selected.png' : '1uparrow.png'), 'class="imgup'.($moreclass?" ".$moreclass:"").'"');
}
/**
@ -2621,7 +2624,7 @@ function print_liste_field_titre($name, $file="", $field="", $begin="", $morepar
* Get title line of an array
*
* @param string $name Label of field
* @param int $thead 0=To use with standard table forat, 1=To use inside <thead><tr>, 2=To use with <div>
* @param int $thead 0=To use with standard table format, 1=To use inside <thead><tr>, 2=To use with <div>
* @param string $file Url used when we click on sort picto
* @param string $field Field to use for new sorting. Empty if this field is not sortable.
* @param string $begin ("" by defaut)

View File

@ -1885,7 +1885,7 @@ function colorArrayToHex($arraycolor,$colorifnotfound='888888')
function colorStringToArray($stringcolor,$colorifnotfound=array(88,88,88))
{
if (is_array($stringcolor)) return $stringcolor; // If already into correct output format, we return as is
$tmp=preg_match('/^([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])$/',$stringcolor,$reg);
$tmp=preg_match('/^#?([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])$/',$stringcolor,$reg);
if (! $tmp)
{
$tmp=explode(',',$stringcolor);

View File

@ -339,8 +339,9 @@ function show_theme($fuser,$edit=0,$foruserprofile=false)
if (is_dir($dirtheme."/".$subdir) && substr($subdir, 0, 1) <> '.'
&& substr($subdir, 0, 3) <> 'CVS' && ! preg_match('/common|phones/i',$subdir))
{
// Disable not stable themes
//if ($conf->global->MAIN_FEATURES_LEVEL < 1 && preg_match('/bureau2crea/i',$subdir)) continue;
// Disable not stable themes (dir ends with _exp or _dev)
if ($conf->global->MAIN_FEATURES_LEVEL < 2 && preg_match('/_dev$/i',$subdir)) continue;
if ($conf->global->MAIN_FEATURES_LEVEL < 1 && preg_match('/_exp$/i',$subdir)) continue;
print '<div class="inline-block" style="margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;">';
$file=$dirtheme."/".$subdir."/thumb.png";

View File

@ -58,7 +58,7 @@ class modDynamicPrices extends DolibarrModules
// Config pages
//-------------
//$this->config_page_url = array();
$this->config_page_url = array("dynamic_prices.php@product");
// Dependancies
//-------------

View File

@ -7,6 +7,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/syslog/logHandler.php';
*/
class mod_syslog_chromephp extends LogHandler implements LogHandlerInterface
{
var $code = 'chromephp';
/**
* Return name of logger
*
@ -111,7 +113,7 @@ class mod_syslog_chromephp extends LogHandler implements LogHandlerInterface
}
/**
* Output log content
* Output log content. We also start output buffering at first log write.
*
* @param array $content Content to log
* @return null|false

View File

@ -7,6 +7,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/syslog/logHandler.php';
*/
class mod_syslog_file extends LogHandler implements LogHandlerInterface
{
var $code = 'file';
/**
* Return name of logger

View File

@ -7,6 +7,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/syslog/logHandler.php';
*/
class mod_syslog_firephp extends LogHandler implements LogHandlerInterface
{
var $code = 'firephp';
/**
* Return name of logger
*

View File

@ -7,6 +7,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/syslog/logHandler.php';
*/
class mod_syslog_syslog extends LogHandler implements LogHandlerInterface
{
var $code = 'syslog';
/**
* Return name of logger
*

View File

@ -33,8 +33,8 @@ $tagidfortablednd=(empty($tagidfortablednd)?'tablelines':$tagidfortablednd);
if (GETPOST('action') != 'editline' && $nboflines > 1) { ?>
<script type="text/javascript">
$(document).ready(function(){
$(".imgup").hide();
$(".imgdown").hide();
$(".imgupforline").hide();
$(".imgdownforline").hide();
$(".lineupdown").removeAttr('href');
$(".tdlineupdown").css("background-image",'url(<?php echo DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/grip.png'; ?>)');
$(".tdlineupdown").css("background-repeat","no-repeat");
@ -78,8 +78,8 @@ $(document).ready(function(){
<?php } else { ?>
<script>
$(document).ready(function(){
$(".imgup").hide();
$(".imgdown").hide();
$(".imgupforline").hide();
$(".imgdownforline").hide();
$(".lineupdown").removeAttr('href');
});
</script>

View File

@ -29,7 +29,7 @@ if (GETPOST('dol_use_jmobile')) $conf->dol_use_jmobile=1;
if (! empty($conf->dol_use_jmobile)) $conf->use_javascript_ajax=1;
$arrayofjs=array('/core/js/dst.js'.(empty($conf->dol_use_jmobile)?'':'?version='.urlencode(DOL_VERSION))); // Javascript code on logon page only to detect user tz, dst_observed, dst_first, dst_second
$titleofloginpage=$langs->trans('Login').' '.$title; // title is defined by dol_loginfunction in security2.lib.php
$titleofloginpage=$langs->trans('Login').' @ '.$title; // title is defined by dol_loginfunction in security2.lib.php. We must keep the @, some tools use it to know it is login page.
print top_htmlhead('',$titleofloginpage,0,0,$arrayofjs);
?>
@ -49,7 +49,6 @@ $(document).ready(function () {
<div align="center">
<div class="login_vertical_align">
<form id="login" name="login" method="post" action="<?php echo $php_self; ?>">
<input type="hidden" name="token" value="<?php echo $_SESSION['newtoken']; ?>" />
<input type="hidden" name="loginfunction" value="loginfunction" />

View File

@ -203,12 +203,12 @@ if (empty($usemargins)) $usemargins=0;
<td align="center" class="tdlineupdown"><?php $coldisplay++; ?>
<?php if ($i > 0) { ?>
<a class="lineupdown" href="<?php echo $_SERVER["PHP_SELF"].'?id='.$this->id.'&amp;action=up&amp;rowid='.$line->id; ?>">
<?php echo img_up(); ?>
<?php echo img_up('default',0,'imgupforline'); ?>
</a>
<?php } ?>
<?php if ($i < $num-1) { ?>
<a class="lineupdown" href="<?php echo $_SERVER["PHP_SELF"].'?id='.$this->id.'&amp;action=down&amp;rowid='.$line->id; ?>">
<?php echo img_down(); ?>
<?php echo img_down('default',0,'imgdownforline'); ?>
</a>
<?php } ?>
</td>

View File

@ -540,7 +540,10 @@ class Export
if ($resql)
{
//$this->array_export_label[$indice]
$filename="export_".$datatoexport;
if ($conf->global->EXPORT_PREFIX_SPEC)
$filename=$conf->global->EXPORT_PREFIX_SPEC."_".$datatoexport;
else
$filename="export_".$datatoexport;
$filename.='.'.$objmodel->getDriverExtension();
$dirname=$conf->export->dir_temp.'/'.$user->id;

View File

@ -70,7 +70,7 @@ if ($idprod > 0)
if ($num)
{
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$i = 0;
while ($i < $num)
{

View File

@ -5,6 +5,7 @@
* Copyright (C) 2005-2010 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2014 Jean Heimburger <jean@tiaris.info>
* Copyright (C) 2015 Marcos García <marcosgdf@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
@ -304,6 +305,8 @@ if ($object->id > 0)
print '<td align="right"><a href="'.DOL_URL_ROOT.'/fourn/recap-fourn.php?socid='.$object->id.'">'.$langs->trans("ShowSupplierPreview").'</a></td></tr></table></td>';
print '</tr>';
print '</table>';
print '<br>';
/*
* List of products
@ -313,14 +316,53 @@ if ($object->id > 0)
$langs->load("products");
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("ProductsAndServices").'</td><td align="right">';
print '<td colspan="2">'.$langs->trans("ProductsAndServices").'</td><td align="right">';
print '<a href="'.DOL_URL_ROOT.'/fourn/product/list.php?fourn_id='.$object->id.'">'.$langs->trans("All").' <span class="badge">'.$object->nbOfProductRefs().'</span>';
print '</a></td></tr></table>';
print '</a></td></tr>';
//Query from product/liste.php
$sql = 'SELECT p.rowid, p.ref, p.label, pfp.tms,';
$sql.= ' p.fk_product_type';
$sql.= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp';
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = pfp.fk_product";
$sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')';
$sql.= ' AND pfp.fk_soc = '.$object->id;
$sql .= $db->order('pfp.tms', 'desc');
$sql.= $db->plimit($MAXLIST);
$query = $db->query($sql);
$return = array();
if ($db->num_rows($query)) {
$productstatic = new Product($db);
while ($objp = $db->fetch_object($query)) {
$var=!$var;
$productstatic->id = $objp->rowid;
$productstatic->ref = $objp->ref;
$productstatic->label = $objp->label;
$productstatic->type = $objp->fk_product_type;
print "<tr ".$bc[$var].">";
print '<td class="nowrap">';
print $productstatic->getNomUrl(1);
print '</td>';
print '<td align="center" width="80">';
print dol_trunc(dol_htmlentities($objp->label), 30);
print '</td>';
print '<td align="right" class="nowrap">'.dol_print_date($objp->tms).'</td>';
print '</tr>';
}
}
print '</table>';
}
print '<br>';
/*
* Last orders
*/
@ -328,8 +370,6 @@ if ($object->id > 0)
if ($user->rights->fournisseur->commande->lire)
{
// TODO move to DAO class
// Check if there are supplier orders billable
$sql2 = 'SELECT s.nom, s.rowid as socid, s.client, c.rowid, c.ref, c.total_ht, c.ref_supplier,';

View File

@ -27,7 +27,7 @@
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
/**
@ -159,7 +159,7 @@ class ProductFournisseur extends Product
*/
function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delivery_time_days=0)
{
global $conf;
global $conf, $langs;
// Clean parameter
if (empty($qty)) $qty=0;

View File

@ -2279,8 +2279,13 @@ elseif (! empty($object->id))
$formmail->withbody=1;
$formmail->withdeliveryreceipt=1;
$formmail->withcancel=1;
$object->fetch_projet();
// Tableau des substitutions
$formmail->substit['__ORDERREF__']=$object->ref;
$formmail->substit['__ORDERSUPPLIERREF__']=$object->ref_supplier;
$formmail->substit['__THIRPARTY_NAME__'] = $object->thirdparty->name;
$formmail->substit['__PROJECT_REF__'] = (is_object($object->projet)?$object->projet->ref:'');
$formmail->substit['__SIGNATURE__']=$user->signature;
$formmail->substit['__PERSONALIZED__']='';
$formmail->substit['__CONTACTCIVNAME__']='';

View File

@ -445,3 +445,23 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value
insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_CREATE','Task created','Executed when a project task is created','project',35);
insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_MODIFY','Task modified','Executed when a project task is modified','project',36);
insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_DELETE','Task deleted','Executed when a project task is deleted','project',37);
create table llx_c_price_global_variable
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
code varchar(20) NOT NULL,
description text DEFAULT NULL,
value double(24,8) DEFAULT 0
)ENGINE=innodb;
create table llx_c_price_global_variable_updater
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
type integer NOT NULL,
description text DEFAULT NULL,
parameters text DEFAULT NULL,
fk_variable integer NOT NULL,
update_interval integer DEFAULT 0,
next_update integer DEFAULT 0,
last_status text DEFAULT NULL
)ENGINE=innodb;

View File

@ -0,0 +1,25 @@
-- ============================================================================
-- Copyright (C) 2015 Ion agorria <ion@agorria.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/>.
--
-- ============================================================================
create table llx_c_price_global_variable
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
code varchar(20) NOT NULL,
description text DEFAULT NULL,
value double(24,8) DEFAULT 0
)ENGINE=innodb;

View File

@ -0,0 +1,29 @@
-- ============================================================================
-- Copyright (C) 2015 Ion agorria <ion@agorria.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/>.
--
-- ============================================================================
create table llx_c_price_global_variable_updater
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
type integer NOT NULL,
description text DEFAULT NULL,
parameters text DEFAULT NULL,
fk_variable integer NOT NULL,
update_interval integer DEFAULT 0,
next_update integer DEFAULT 0,
last_status text DEFAULT NULL
)ENGINE=innodb;

View File

@ -19,9 +19,11 @@
* Upgrade scripts can be ran from command line with syntax:
*
* cd htdocs/install
* php upgrade.php 3.4.0 3.5.0
* php upgrade.php 3.4.0 3.5.0 [dirmodule|ignoredbversion]
* php upgrade2.php 3.4.0 3.5.0
*
* Option 'dirmodule' allows to provide a path for an external module, so we migrate from command line a script from a module.
* Option 'ignoredbversion' allows to run migration even if database is a bugged database version.
* Return code is 0 if OK, >0 if error
*/
@ -55,7 +57,8 @@ $setuplang=GETPOST("selectlang",'',3)?GETPOST("selectlang",'',3):'auto';
$langs->setDefaultLang($setuplang);
$versionfrom=GETPOST("versionfrom",'',3)?GETPOST("versionfrom",'',3):(empty($argv[1])?'':$argv[1]);
$versionto=GETPOST("versionto",'',3)?GETPOST("versionto",'',3):(empty($argv[2])?'':$argv[2]);
$versionmodule=GETPOST("versionmodule",'',3)?GETPOST("versionmodule",'',3):(empty($argv[3])?'':$argv[3]);
$dirmodule=((GETPOST("dirmodule",'',3) && GETPOST("dirmodule",'',3) != 'ignoredbversion'))?GETPOST("dirmodule",'',3):((empty($argv[3]) || $argv[3] == 'ignoredbversion')?'':$argv[3]);
$ignoredbversion=(GETPOST('ignoredbversion','',3)=='ignoredbversion')?GETPOST('ignoredbversion','',3):((empty($argv[3]) || $argv[3] != 'ignoredbversion')?'':$argv[3]);
$langs->load("admin");
$langs->load("install");
@ -191,31 +194,34 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action')))
}
// Test database version is not forbidden for migration
$dbversion_disallowed=array(
array('type'=>'mysql','version'=>array(5,5,40)),
array('type'=>'mysqli','version'=>array(5,5,40))
//,array('type'=>'mysql','version'=>array(5,5,41)),
//array('type'=>'mysqli','version'=>array(5,5,41))
);
$listofforbiddenversion='';
foreach ($dbversion_disallowed as $dbversion_totest)
{
if ($dbversion_totest['type'] == $db->type) $listofforbiddenversion.=($listofforbiddenversion?', ':'').join('.',$dbversion_totest['version']);
}
foreach ($dbversion_disallowed as $dbversion_totest)
{
//print $db->type.' - '.join('.',$versionarray).' - '.versioncompare($dbversion_totest['version'],$versionarray)."<br>\n";
if ($dbversion_totest['type'] == $db->type
&& (versioncompare($dbversion_totest['version'],$versionarray) == 0 || versioncompare($dbversion_totest['version'],$versionarray)<=-4 || versioncompare($dbversion_totest['version'],$versionarray)>=4)
)
{
// Warning: database version too low.
print '<tr><td><div class="warning">'.$langs->trans("ErrorDatabaseVersionForbiddenForMigration",join('.',$versionarray),$listofforbiddenversion)."</div></td><td align=\"right\">".$langs->trans("Error")."</td></tr>\n";
dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ErrorDatabaseVersionForbiddenForMigration",join('.',$versionarray),$listofforbiddenversion));
$ok=0;
break;
}
}
if (empty($ignoredbversion))
{
$dbversion_disallowed=array(
array('type'=>'mysql','version'=>array(5,5,40)),
array('type'=>'mysqli','version'=>array(5,5,40)),
array('type'=>'mysql','version'=>array(5,5,41)),
array('type'=>'mysqli','version'=>array(5,5,41))
);
$listofforbiddenversion='';
foreach ($dbversion_disallowed as $dbversion_totest)
{
if ($dbversion_totest['type'] == $db->type) $listofforbiddenversion.=($listofforbiddenversion?', ':'').join('.',$dbversion_totest['version']);
}
foreach ($dbversion_disallowed as $dbversion_totest)
{
//print $db->type.' - '.join('.',$versionarray).' - '.versioncompare($dbversion_totest['version'],$versionarray)."<br>\n";
if ($dbversion_totest['type'] == $db->type
&& (versioncompare($dbversion_totest['version'],$versionarray) == 0 || versioncompare($dbversion_totest['version'],$versionarray)<=-4 || versioncompare($dbversion_totest['version'],$versionarray)>=4)
)
{
// Warning: database version too low.
print '<tr><td><div class="warning">'.$langs->trans("ErrorDatabaseVersionForbiddenForMigration",join('.',$versionarray),$listofforbiddenversion)."</div></td><td align=\"right\">".$langs->trans("Error")."</td></tr>\n";
dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ErrorDatabaseVersionForbiddenForMigration",join('.',$versionarray),$listofforbiddenversion));
$ok=0;
break;
}
}
}
}
// Force l'affichage de la progression
@ -370,7 +376,7 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action')))
if ($ok)
{
$dir = "mysql/migration/"; // We use mysql migration scripts whatever is database driver
if (! empty($versionmodule)) $dir=dol_buildpath('/'.$versionmodule.'/sql/',0);
if (! empty($dirmodule)) $dir=dol_buildpath('/'.$dirmodule.'/sql/',0);
// Clean last part to exclude minor version x.y.z -> x.y
$newversionfrom=preg_replace('/(\.[0-9]+)$/i','.0',$versionfrom);
@ -475,7 +481,7 @@ $ret=0;
if (! $ok && isset($argv[1])) $ret=1;
dol_syslog("Exit ".$ret);
pFooter(((! $ok && empty($_GET["ignoreerrors"])) || $versionmodule),$setuplang);
pFooter(((! $ok && empty($_GET["ignoreerrors"])) || $dirmodule),$setuplang);
if ($db->connected) $db->close();

View File

@ -161,6 +161,12 @@ ErrorPriceExpressionUnknown=Unknown error '%s'
ErrorSrcAndTargetWarehouseMustDiffers=Source and target warehouses must differs
ErrorTryToMakeMoveOnProductRequiringBatchData=Error, trying to make a stock movement without batch/serial information, on a product requiring batch/serial information
ErrorCantSetReceptionToTotalDoneWithReceptionToApprove=All recorded receptions must first be verified before being allowed to do this action
ErrorGlobalVariableUpdater0=HTTP request failed with error '%s'
ErrorGlobalVariableUpdater1=Invalid JSON format '%s'
ErrorGlobalVariableUpdater2=Missing parameter '%s'
ErrorGlobalVariableUpdater3=The requested data was not found in result
ErrorGlobalVariableUpdater4=SOAP client failed with error '%s'
ErrorGlobalVariableUpdater5=No global variable selected
# Warnings
WarningMandatorySetupNotComplete=Mandatory setup parameters are not yet defined

View File

@ -245,12 +245,25 @@ MinimumRecommendedPrice=Minimum recommended price is : %s
PriceExpressionEditor=Price expression editor
PriceExpressionSelected=Selected price expression
PriceExpressionEditorHelp1="price = 2 + 2" or "2 + 2" for setting the price. Use ; to separate expressions
PriceExpressionEditorHelp2=You can access ExtraFields with variables like <b>#options_myextrafieldkey#</b>
PriceExpressionEditorHelp2=You can access ExtraFields with variables like <b>#extrafield_myextrafieldkey#</b> and global variables with <b>#global_mycode#</b>
PriceExpressionEditorHelp3=In both product/service and supplier prices there are these variables available:<br><b>#tva_tx# #localtax1_tx# #localtax2_tx# #weight# #length# #surface# #price_min#</b>
PriceExpressionEditorHelp4=In product/service price only: <b>#supplier_min_price#</b><br>In supplier prices only: <b>#supplier_quantity# and #supplier_tva_tx#</b>
PriceExpressionEditorHelp5=Available global values:
PriceMode=Price mode
PriceNumeric=Number
DefaultPrice=Default price
ComposedProductIncDecStock=Increase/Decrease stock on parent change
ComposedProduct=Sub-product
MinSupplierPrice=Minimun supplier price
MinSupplierPrice=Minimum supplier price
DynamicPriceConfiguration=Dynamic price configuration
GlobalVariables=Global variables
GlobalVariableUpdaters=Global variable updaters
GlobalVariableUpdaterType0=JSON data
GlobalVariableUpdaterHelp0=Parses JSON data from specified URL, VALUE specifies the location of relevant value,
GlobalVariableUpdaterHelpFormat0=format is {"URL": "http://example.com/urlofjson", "VALUE": "array1,array2,targetvalue"}
GlobalVariableUpdaterType1=WebService data
GlobalVariableUpdaterHelp1=Parses WebService data from specified URL, NS specifies the namespace, VALUE specifies the location of relevant value, DATA should contain the data to send and METHOD is the calling WS method
GlobalVariableUpdaterHelpFormat1=format is {"URL": "http://example.com/urlofws", "VALUE": "array,targetvalue", "NS": "http://example.com/urlofns", "METHOD": "myWSMethod", "DATA": {"your": "data, "to": "send"}}
UpdateInterval=Update interval (minutes)
LastUpdated=Last updated
CorrectlyUpdated=Correctly updated

View File

@ -490,7 +490,8 @@ if (! defined('NOLOGIN'))
if (! $login || (in_array('ldap',$authmode) && empty($passwordtotest))) // With LDAP we refused empty password because some LDAP are "opened" for anonymous access so connexion is a success.
{
// We show login page
dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:''));
dol_syslog("--- Access to ".$_SERVER["PHP_SELF"]." showing the login form and exit");
dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:''));
exit;
}
@ -1504,7 +1505,7 @@ function left_menu($menu_array_before, $helppagename='', $moresearchform='', $me
$hookmanager->initHooks(array('searchform','leftblock'));
if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print "\n".'<!-- Begin left layout -->'."\n".'<div class="ui-layout-west">'."\n";
else print "\n".'<!-- Begin id-left -->'."\n".'<div id="id-left">'."\n";
else print "\n".'<!-- Begin id-left -->'."\n".'<div class="side-nav"><div id="id-left">'."\n";
print "\n";
@ -1690,7 +1691,7 @@ function left_menu($menu_array_before, $helppagename='', $moresearchform='', $me
print $hookmanager->resPrint;
if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '</div> <!-- End left layout -->'."\n";
else print '</div> <!-- end id-left -->'; // End div id="id-left"
else print '</div></div> <!-- end id-left -->'; // End div id="id-left"
}
print "\n";

View File

@ -0,0 +1,329 @@
<?php
/* Copyright (C) 2015 Ion Agorria <ion@agorria.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/>.
*/
/**
* \file htdocs/product/admin/expression_globals.php
* \ingroup product
* \brief Page for configuring dynamic prices
*/
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_global_variable.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_global_variable_updater.class.php';
$langs->load("products");
$id = GETPOST('id', 'int');
$action = GETPOST('action', 'alpha');
$save = GETPOST('save', 'alpha');
$cancel = GETPOST('cancel', 'alpha');
$selection = GETPOST('selection', 'int');
// Security check
if (!$user->admin) accessforbidden();
//Objects
$price_globals = new PriceGlobalVariable($db);
if ($action == 'edit_variable') {
$res = $price_globals->fetch($selection);
if ($res < 1) {
setEventMessage($price_globals->error, 'errors');
}
}
$price_updaters = new PriceGlobalVariableUpdater($db);
if ($action == 'edit_updater') {
$res = $price_updaters->fetch($selection);
if ($res < 1) {
setEventMessage($price_updaters->error, 'errors');
}
}
/*
* Actions
*/
if (!empty($action) && empty($cancel)) {
//Global variable actions
if ($action == 'create_variable' || $action == 'edit_variable') {
$price_globals->code = isset($_POST['code'])?GETPOST('code', 'alpha'):$price_globals->code;
$price_globals->description = isset($_POST['description'])?GETPOST('description', 'alpha'):$price_globals->description;
$price_globals->value = isset($_POST['value'])?GETPOST('value', 'int'):$price_globals->value;
//Check if record already exists only when saving
if (!empty($save)) {
foreach ($price_globals->listGlobalVariables() as $entry) {
if ($price_globals->id != $entry->id && dol_strtolower($price_globals->code) == dol_strtolower($entry->code)) {
setEventMessage($langs->trans("ErrorRecordAlreadyExists"), 'errors');
$save = null;
}
}
}
}
if ($action == 'create_variable' && !empty($save)) {
$res = $price_globals->create($user);
if ($res > 0) {
$action = '';
} else {
setEventMessage($price_globals->error, 'errors');
}
} elseif ($action == 'edit_variable' && !empty($save)) {
$res = $price_globals->update($user);
if ($res > 0) {
$action = '';
} else {
setEventMessage($price_globals->error, 'errors');
}
} elseif ($action == 'delete_variable') {
$res = $price_globals->delete($selection, $user);
if ($res > 0) {
$action = '';
} else {
setEventMessage($price_globals->error, 'errors');
}
}
//Updaters actions
if ($action == 'create_updater' || $action == 'edit_updater') {
$price_updaters->type = isset($_POST['type'])?GETPOST('type', 'int'):$price_updaters->type;
$price_updaters->description = isset($_POST['description'])?GETPOST('description', 'alpha'):$price_updaters->description;
$price_updaters->parameters = isset($_POST['parameters'])?GETPOST('parameters'):$price_updaters->parameters;
$price_updaters->fk_variable = isset($_POST['fk_variable'])?GETPOST('fk_variable', 'int'):$price_updaters->fk_variable;
$price_updaters->update_interval = isset($_POST['update_interval'])?GETPOST('update_interval', 'int'):$price_updaters->update_interval;
}
if ($action == 'create_updater' && !empty($save)) {
//Verify if process() works
$res = $price_updaters->process();
if ($res > 0) {
$res = $price_updaters->create($user);
}
if ($res > 0) {
$action = '';
} else {
setEventMessage($price_updaters->error, 'errors');
}
} elseif ($action == 'edit_updater' && !empty($save)) {
//Verify if process() works
$res = $price_updaters->process();
if ($res > 0) {
$res = $price_updaters->update($user);
}
if ($res > 0) {
$action = '';
} else {
setEventMessage($price_updaters->error, 'errors');
}
} elseif ($action == 'delete_updater') {
$res = $price_updaters->delete($selection, $user);
if ($res > 0) {
$action = '';
} else {
setEventMessage($price_updaters->error, 'errors');
}
}
} elseif (!empty($cancel)) {
$action = '';
}
/*
* View
*/
//Header
llxHeader("","",$langs->trans("CardProduct".$product->type));
print_fiche_titre($langs->trans("DynamicPriceConfiguration"));
$form = new Form($db);
//Global variables table
if ($action != 'create_updater' && $action != 'edit_updater') {
print $langs->trans("GlobalVariables");
print '<table summary="listofattributes" class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Code").'</td>';
print '<td>'.$langs->trans("Description").'</td>';
print '<td>'.$langs->trans("Value").'</td>';
print '<td width="80">&nbsp;</td>'; //Space for buttons
print '</tr>';
$var=True;
foreach ($price_globals->listGlobalVariables() as $i=>$entry) {
$var = !$var;
print '<tr '.$bc[$var].'>';
print '<td>'.$entry->code.'</td>';
print '<td>'.$entry->description.'</td>';
print '<td>'.price($entry->value).'</td>';
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=edit_variable&selection='.$entry->id.'">'.img_edit().'</a> &nbsp;';
print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete_variable&selection='.$entry->id.'">'.img_delete().'</a></td>';
print '</tr>';
}
print '</table>';
}
//Global variable editor
if ($action == 'create_variable' || $action == 'edit_variable') {
//Form
print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="'.$action.'">';
print '<input type="hidden" name="selection" value="'.$selection.'">';
//Table
print '<br><table summary="listofattributes" class="border centpercent">';
//Code
print '<tr>';
print '<td class="fieldrequired">'.$langs->trans("Code").'</td>';
print '<td class="valeur"><input type="text" name="code" size="20" value="'.(empty($price_globals->code)?'':$price_globals->code).'"></td>';
print '</tr>';
//Description
print '<tr>';
print '<td>'.$langs->trans("Description").'</td>';
print '<td class="valeur"><input type="text" name="description" size="50" value="'.(empty($price_globals->description)?'':$price_globals->description).'"></td>';
print '</tr>';
//Value
print '<tr>';
print '<td class="fieldrequired">'.$langs->trans("Value").'</td>';
print '<td class="valeur"><input type="text" name="value" size="10" value="'.(empty($price_globals->value)?'':$price_globals->value).'"></td>';
print '</tr>';
print '</table>';
//Form Buttons
print '<br><div align="center">';
print '<input type="submit" class="button" name="save" value="'.$langs->trans("Save").'"> &nbsp;';
print '<input type="submit" class="button" name="cancel" id="cancel" value="'.$langs->trans("Cancel").'">';
print '</div>';
print '</form>';
} else {
//Action Buttons
print '<div class="tabsAction">';
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=create_variable">'.$langs->trans("Add").'</a>';
print '</div>';
//Separator is only need for updaters table is showed after buttons
print '<br><br>';
}
//Updaters table
if ($action != 'create_variable' && $action != 'edit_variable') {
print $langs->trans("GlobalVariableUpdaters");
print '<table summary="listofattributes" class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Code").'</td>';
print '<td>'.$langs->trans("Description").'</td>';
print '<td>'.$langs->trans("Type").'</td>';
print '<td>'.$langs->trans("Parameters").'</td>';
print '<td>'.$langs->trans("UpdateInterval").'</td>';
print '<td>'.$langs->trans("LastUpdated").'</td>';
print '<td width="80">&nbsp;</td>'; //Space for buttons
print '</tr>';
$var=True;
foreach ($price_updaters->listUpdaters() as $i=>$entry) {
$code = "";
if ($entry->fk_variable > 0) {
$res = $price_globals->fetch($entry->fk_variable);
if ($res > 0) {
$code = $price_globals->code;
}
}
$var = !$var;
print '<tr '.$bc[$var].'>';
print '<td>'.$code.'</td>';
print '<td>'.$entry->description.'</td>';
print '<td>'.$langs->trans("GlobalVariableUpdaterType".$entry->type).'</td>';
print '<td style="max-width: 250px; word-wrap: break-word; white-space: pre-wrap;">'.$entry->parameters.'</td>';
print '<td>'.$entry->update_interval.'</td>';
print '<td>'.$entry->getLastUpdated().'</td>';
print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=edit_updater&selection='.$entry->id.'">'.img_edit().'</a> &nbsp;';
print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete_updater&selection='.$entry->id.'">'.img_delete().'</a></td>';
print '</tr>';
}
print '</table>';
}
//Updater editor
if ($action == 'create_updater' || $action == 'edit_updater') {
//Form
print '<form id="updaterform" action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="'.$action.'">';
print '<input type="hidden" name="selection" value="'.$selection.'">';
//Table
print '<br><table summary="listofattributes" class="border centpercent">';
//Code
print '<tr>';
print '<td class="fieldrequired">'.$langs->trans("Code").'</td><td>';
$globals_list = array();
foreach ($price_globals->listGlobalVariables() as $entry) {
$globals_list[$entry->id]=$entry->code;
}
print $form->selectarray('fk_variable', $globals_list, (empty($price_updaters->fk_variable)?0:$price_updaters->fk_variable));
print '</td></tr>';
//Description
print '<tr>';
print '<td>'.$langs->trans("Description").'</td>';
print '<td class="valeur"><input type="text" name="description" size="50" value="'.(empty($price_updaters->description)?'':$price_updaters->description).'"></td>';
print '</tr>';
//Type
print '<tr>';
print '<td class="fieldrequired">'.$langs->trans("Type").'</td><td>';
$type = empty($price_updaters->type)?0:$price_updaters->type;
$type_list = array();
foreach ($price_updaters->types as $val) {
$type_list[$val] = $langs->trans("GlobalVariableUpdaterType".$val);
}
print $form->selectarray('type', $type_list, $type);
// This code submits form when type is changed
print '<script type="text/javascript">
jQuery(document).ready(run);
function run() {
jQuery("#type").change(on_change);
}
function on_change() {
jQuery("#updaterform").submit();
}
</script>';
print '</td></tr>';
//Parameters
print '<tr>';
$help = $langs->trans("GlobalVariableUpdaterHelp".$type).'<br><b>'.$langs->trans("GlobalVariableUpdaterHelpFormat".$type).'</b>';
print '<td class="fieldrequired">'.$form->textwithpicto($langs->trans("Parameters"),$help,1).'</td><td>';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
$doleditor=new DolEditor('parameters',empty($price_updaters->parameters)?'':$price_updaters->parameters,'',300,'','',false,false,false,10,80);
$doleditor->Create();
print '</td></tr>';
print '</tr>';
//Interval
print '<tr>';
print '<td class="fieldrequired">'.$langs->trans("UpdateInterval").'</td>';
print '<td class="valeur"><input type="text" name="update_interval" size="10" value="'.(empty($price_updaters->update_interval)?'':$price_updaters->update_interval).'"></td>';
print '</tr>';
print '</table>';
//Form Buttons
print '<br><div align="center">';
print '<input type="submit" class="button" name="save" value="'.$langs->trans("Save").'"> &nbsp;';
print '<input type="submit" class="button" name="cancel" id="cancel" value="'.$langs->trans("Cancel").'">';
print '</div>';
print '</form>';
} else {
//Action Buttons
print '<div class="tabsAction">';
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=create_updater">'.$langs->trans("Add").'</a>';
print '</div>';
}
llxFooter();
$db->close();

View File

@ -673,7 +673,7 @@ class Product extends CommonObject
$sql.= ", desiredstock = " . ((isset($this->desiredstock) && $this->desiredstock != '') ? $this->desiredstock : "null");
$sql.= " WHERE rowid = " . $id;
dol_syslog(get_class($this)."update", LOG_DEBUG);
dol_syslog(get_class($this)."::update", LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
@ -916,16 +916,16 @@ class Product extends CommonObject
foreach ($langs_available as $key => $value)
{
$sql = "SELECT rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."product_lang";
$sql.= " WHERE fk_product=".$this->id;
$sql.= " AND lang='".$key."'";
$result = $this->db->query($sql);
if ($key == $current_lang)
{
if ($this->db->num_rows($result)) // si aucune ligne dans la base
$sql = "SELECT rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."product_lang";
$sql.= " WHERE fk_product=".$this->id;
$sql.= " AND lang='".$key."'";
$result = $this->db->query($sql);
if ($this->db->num_rows($result)) // if there is already a description line for this language
{
$sql2 = "UPDATE ".MAIN_DB_PREFIX."product_lang";
$sql2.= " SET label='".$this->db->escape($this->libelle)."',";
@ -947,9 +947,16 @@ class Product extends CommonObject
return -1;
}
}
else if (isset($this->multilangs["$key"]))
else if (isset($this->multilangs[$key]))
{
if ($this->db->num_rows($result)) // si aucune ligne dans la base
$sql = "SELECT rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."product_lang";
$sql.= " WHERE fk_product=".$this->id;
$sql.= " AND lang='".$key."'";
$result = $this->db->query($sql);
if ($this->db->num_rows($result)) // if there is already a description line for this language
{
$sql2 = "UPDATE ".MAIN_DB_PREFIX."product_lang";
$sql2.= " SET label='".$this->db->escape($this->multilangs["$key"]["label"])."',";
@ -974,6 +981,10 @@ class Product extends CommonObject
return -1;
}
}
else
{
// language is not current language and we didn't provide a multilang description for this language
}
}
return 1;
}
@ -1194,7 +1205,7 @@ class Product extends CommonObject
{
if (!empty($obj->fk_supplier_price_expression))
{
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$priceparser = new PriceParser($this->db);
$price_result = $priceparser->parseProductSupplier($obj->fk_product, $obj->fk_supplier_price_expression, $obj->quantity, $obj->tva_tx);
if ($price_result >= 0) {
@ -1229,7 +1240,7 @@ class Product extends CommonObject
{
if (!empty($obj->fk_supplier_price_expression))
{
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$priceparser = new PriceParser($this->db);
$price_result = $priceparser->parseProductSupplier($obj->fk_product, $obj->fk_supplier_price_expression, $obj->quantity, $obj->tva_tx);
if ($result >= 0) {
@ -1685,7 +1696,7 @@ class Product extends CommonObject
if (!empty($this->fk_price_expression) && empty($ignore_expression))
{
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$priceparser = new PriceParser($this->db);
$price_result = $priceparser->parseProduct($this);
if ($price_result >= 0)

View File

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
/* Copyright (C) 2014 Ion Agorria <ion@agorria.com>
/* Copyright (C) 2015 Ion Agorria <ion@agorria.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
@ -18,7 +18,7 @@
*/
/**
* \file htdocs/product/class/priceexpression.class.php
* \file htdocs/product/dynamic_price/class/price_expression.class.php
* \ingroup product
* \brief Class for accessing price expression table
*/
@ -35,6 +35,7 @@ class PriceExpression
var $id;
var $title;
var $expression;
public $table_element = "c_price_expression";
/**
* Constructor
@ -57,14 +58,14 @@ class PriceExpression
*/
function create($user, $notrigger=0)
{
$error=0;
$error=0;
// Clean parameters
if (isset($this->title)) $this->title=trim($this->title);
if (isset($this->expression)) $this->expression=trim($this->expression);
// Insert request
$sql = "INSERT INTO ".MAIN_DB_PREFIX."c_price_expression (";
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
$sql.= "title, expression";
$sql.= ") VALUES (";
$sql.= " ".(isset($this->title)?"'".$this->db->escape($this->title)."'":"''").",";
@ -121,7 +122,7 @@ class PriceExpression
function fetch($id)
{
$sql = "SELECT title, expression";
$sql.= " FROM ".MAIN_DB_PREFIX."c_price_expression";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE rowid = ".$id;
dol_syslog(get_class($this)."::fetch");
@ -133,8 +134,8 @@ class PriceExpression
{
$this->id = $id;
$this->title = $obj->title;
$this->expression = $obj->expression;
return 1;
$this->expression = $obj->expression;
return 1;
}
else
{
@ -156,10 +157,10 @@ class PriceExpression
function list_price_expression()
{
$sql = "SELECT rowid, title, expression";
$sql.= " FROM ".MAIN_DB_PREFIX."c_price_expression";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " ORDER BY title";
dol_syslog(get_class($this)."::list_price_expression");
dol_syslog(get_class($this)."::list_price_expression");
$resql=$this->db->query($sql);
if ($resql)
{
@ -194,7 +195,7 @@ class PriceExpression
function find_title($title)
{
$sql = "SELECT rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."c_price_expression";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE title = '".$this->db->escape($title)."'";
dol_syslog(get_class($this)."::find_title");
@ -235,7 +236,7 @@ class PriceExpression
if (isset($this->expression)) $this->expression=trim($this->expression);
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX."c_price_expression SET";
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
$sql.= " title = ".(isset($this->title)?"'".$this->db->escape($this->title)."'":"''").",";
$sql.= " expression = ".(isset($this->expression)?"'".$this->db->escape($this->expression)."'":"''")."";
$sql.= " WHERE rowid = ".$this->id;
@ -309,7 +310,7 @@ class PriceExpression
if (! $error)
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX."c_price_expression";
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE rowid = ".$rowid;
dol_syslog(get_class($this)."::delete");

View File

@ -0,0 +1,335 @@
<?php
/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
/* Copyright (C) 2015 Ion Agorria <ion@agorria.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/>.
*/
/**
* \file htdocs/product/dynamic_price/class/price_global_variable.class.php
* \ingroup product
* \brief Class for accessing price global variables table
*/
/**
* Class for accesing price global variables table
*/
class PriceGlobalVariable
{
var $db; //!< To store db handler
var $error; //!< To return error code (or message)
var $errors=array(); //!< To return several error codes (or messages)
var $id;
var $code;
var $description;
var $value;
public $table_element = "c_price_global_variable";
/**
* Constructor
*
* @param DoliDb $db Database handler
*/
function __construct($db)
{
$this->db = $db;
return 1;
}
/**
* Create object into database
*
* @param User $user User that creates
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, Id of created object if OK
*/
function create($user, $notrigger=0)
{
$error=0;
$this->checkParameters();
// Insert request
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
$sql.= "code, description, value";
$sql.= ") VALUES (";
$sql.= " ".(isset($this->code)?"'".$this->db->escape($this->code)."'":"''").",";
$sql.= " ".(isset($this->description)?"'".$this->db->escape($this->description)."'":"''").",";
$sql.= " ".$this->value;
$sql.= ")";
$this->db->begin();
dol_syslog(get_class($this)."::create", LOG_DEBUG);
$resql=$this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
if (! $error)
{
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_CREATE',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(__METHOD__." ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return $this->id;
}
}
/**
* Load object in memory from the database
*
* @param int $id Id object
* @return int < 0 if KO, 0 if OK but not found, > 0 if OK
*/
function fetch($id)
{
$sql = "SELECT code, description, value";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE rowid = ".$id;
dol_syslog(get_class($this)."::fetch");
$resql=$this->db->query($sql);
if ($resql)
{
$obj = $this->db->fetch_object($resql);
if ($obj)
{
$this->id = $id;
$this->code = $obj->code;
$this->description = $obj->description;
$this->value = $obj->value;
$this->checkParameters();
return 1;
}
else
{
return 0;
}
}
else
{
$this->error="Error ".$this->db->lasterror();
return -1;
}
}
/**
* Update object into database
*
* @param User $user User that modifies
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function update($user=0, $notrigger=0)
{
$error=0;
$this->checkParameters();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
$sql.= " code = ".(isset($this->code)?"'".$this->db->escape($this->code)."'":"''").",";
$sql.= " description = ".(isset($this->description)?"'".$this->db->escape($this->description)."'":"''").",";
$sql.= " value = ".$this->value;
$sql.= " WHERE rowid = ".$this->id;
$this->db->begin();
dol_syslog(get_class($this)."::update");
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
if (! $error)
{
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return 1;
}
}
/**
* Delete object in database
*
* @param int $rowid Row id of global variable
* @param User $user User that deletes
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function delete($rowid, $user, $notrigger=0)
{
$error=0;
$this->db->begin();
if (! $error)
{
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_DELETE',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
}
if (! $error)
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE rowid = ".$rowid;
dol_syslog(get_class($this)."::delete");
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return 1;
}
}
/**
* Initialise object with example values
* Id must be 0 if object instance is a specimen
*
* @return void
*/
function initAsSpecimen()
{
$this->id=0;
$this->code='';
$this->description='';
$this->value='';
}
/**
* Checks if all parameters are in order
*
* @return void
*/
function checkParameters()
{
// Clean parameters
if (isset($this->code)) $this->code=trim($this->code);
if (isset($this->description)) $this->description=trim($this->description);
// Check parameters
if (empty($this->value) || !is_numeric($this->value)) $this->value=0;
}
/**
* List all price global variables
*
* @return array Array of price global variables
*/
function listGlobalVariables()
{
$sql = "SELECT rowid, code, description, value";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " ORDER BY code";
dol_syslog(get_class($this)."::listGlobalVariables");
$resql=$this->db->query($sql);
if ($resql)
{
$retarray = array();
while ($record = $this->db->fetch_array($resql))
{
$variable_obj = new PriceGlobalVariable($this->db);
$variable_obj->id = $record["rowid"];
$variable_obj->code = $record["code"];
$variable_obj->description = $record["description"];
$variable_obj->value = $record["value"];
$variable_obj->checkParameters();
$retarray[]=$variable_obj;
}
$this->db->free($resql);
return $retarray;
}
else
{
$this->error=$this->db->error();
return -1;
}
}
}

View File

@ -0,0 +1,625 @@
<?php
/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
/* Copyright (C) 2015 Ion Agorria <ion@agorria.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/>.
*/
/**
* \file htdocs/product/dynamic_price/class/price_global_variable_updater.class.php
* \ingroup product
* \brief Class for price global variable updaters table
*/
/**
* Class for price global variable updaters table
*/
class PriceGlobalVariableUpdater
{
var $db; //!< To store db handler
var $error; //!< To return error code (or message)
var $errors=array(); //!< To return several error codes (or messages)
var $types=array(0, 1); //!< Updater types
var $update_min = 5; //!< Minimal update rate
var $id;
var $type;
var $description;
var $parameters;
var $fk_variable;
var $update_interval; //!< Interval in mins
var $next_update; //!< Next update timestamp
var $last_status;
public $table_element = "c_price_global_variable_updater";
/**
* Constructor
*
* @param DoliDb $db Database handler
*/
function __construct($db)
{
$this->db = $db;
return 1;
}
/**
* Create object into database
*
* @param User $user User that creates
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, Id of created object if OK
*/
function create($user, $notrigger=0)
{
$error=0;
$this->checkParameters();
// Insert request
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
$sql.= "type, description, parameters, fk_variable, update_interval, next_update, last_status";
$sql.= ") VALUES (";
$sql.= " ".$this->type.",";
$sql.= " ".(isset($this->description)?"'".$this->db->escape($this->description)."'":"''").",";
$sql.= " ".(isset($this->parameters)?"'".$this->db->escape($this->parameters)."'":"''").",";
$sql.= " ".$this->fk_variable.",";
$sql.= " ".$this->update_interval.",";
$sql.= " ".$this->next_update.",";
$sql.= " ".(isset($this->last_status)?"'".$this->db->escape($this->last_status)."'":"''");
$sql.= ")";
$this->db->begin();
dol_syslog(get_class($this)."::create", LOG_DEBUG);
$resql=$this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
if (! $error)
{
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_CREATE',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(__METHOD__." ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return $this->id;
}
}
/**
* Load object in memory from the database
*
* @param int $id Id object
* @return int < 0 if KO, 0 if OK but not found, > 0 if OK
*/
function fetch($id)
{
$sql = "SELECT type, description, parameters, fk_variable, update_interval, next_update, last_status";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE rowid = ".$id;
dol_syslog(get_class($this)."::fetch");
$resql=$this->db->query($sql);
if ($resql)
{
$obj = $this->db->fetch_object($resql);
if ($obj)
{
$this->id = $id;
$this->type = $obj->type;
$this->description = $obj->description;
$this->parameters = $obj->parameters;
$this->fk_variable = $obj->fk_variable;
$this->update_interval = $obj->update_interval;
$this->next_update = $obj->next_update;
$this->last_status = $obj->last_status;
$this->checkParameters();
return 1;
}
else
{
return 0;
}
}
else
{
$this->error="Error ".$this->db->lasterror();
return -1;
}
}
/**
* Update object into database
*
* @param User $user User that modifies
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function update($user=0, $notrigger=0)
{
$error=0;
$this->checkParameters();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
$sql.= " type = ".$this->type.",";
$sql.= " description = ".(isset($this->description)?"'".$this->db->escape($this->description)."'":"''").",";
$sql.= " parameters = ".(isset($this->parameters)?"'".$this->db->escape($this->parameters)."'":"''").",";
$sql.= " fk_variable = ".$this->fk_variable.",";
$sql.= " update_interval = ".$this->update_interval.",";
$sql.= " next_update = ".$this->next_update.",";
$sql.= " last_status = ".(isset($this->last_status)?"'".$this->db->escape($this->last_status)."'":"''");
$sql.= " WHERE rowid = ".$this->id;
$this->db->begin();
dol_syslog(get_class($this)."::update");
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
if (! $error)
{
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return 1;
}
}
/**
* Delete object in database
*
* @param int $rowid Row id of global variable
* @param User $user User that deletes
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function delete($rowid, $user, $notrigger=0)
{
$error=0;
$this->db->begin();
if (! $error)
{
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_DELETE',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
}
if (! $error)
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE rowid = ".$rowid;
dol_syslog(get_class($this)."::delete");
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return 1;
}
}
/**
* Initialise object with example values
* Id must be 0 if object instance is a specimen
*
* @return void
*/
function initAsSpecimen()
{
$this->id=0;
$this->type=0;
$this->description='';
$this->parameters='';
$this->fk_variable=0;
$this->update_interval=0;
$this->next_update=0;
$this->last_status='';
}
/**
* Returns the last updated time in string html format, returns "never" if its less than 1
*
* @return string
*/
function getLastUpdated()
{
global $langs;
$last = $this->next_update - ($this->update_interval * 60);
if ($last < 1) {
return $langs->trans("Never");
}
$status = empty($this->last_status) ? $langs->trans("CorrectlyUpdated") : $this->last_status;
return $status.'<br>'.dol_print_date($last, '%d/%m/%Y %H:%M:%S');
}
/**
* Checks if all parameters are in order
*
* @return void
*/
function checkParameters()
{
// Clean parameters
if (isset($this->description)) $this->description=trim($this->description);
if (isset($this->parameters)) $this->parameters=trim($this->parameters);
else $this->parameters="";
if (isset($this->last_status)) $this->last_status=trim($this->last_status);
// Check parameters
if (empty($this->type) || !is_numeric($this->type) || !in_array($this->type, $this->types)) $this->type=0;
if (empty($this->update_interval) || !is_numeric($this->update_interval) || $this->update_interval < 1) $this->update_interval=$this->update_min;
if (empty($this->next_update) || !is_numeric($this->next_update) || $this->next_update < 0) $this->next_update=0;
}
/**
* List all price global variables
*
* @return array Array of price global variable updaters
*/
function listUpdaters()
{
$sql = "SELECT rowid, type, description, parameters, fk_variable, update_interval, next_update, last_status";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
dol_syslog(get_class($this)."::listUpdaters");
$resql=$this->db->query($sql);
if ($resql)
{
$retarray = array();
while ($record = $this->db->fetch_array($resql))
{
$updater_obj = new PriceGlobalVariableUpdater($this->db);
$updater_obj->id = $record["rowid"];
$updater_obj->type = $record["type"];
$updater_obj->description = $record["description"];
$updater_obj->parameters = $record["parameters"];
$updater_obj->fk_variable = $record["fk_variable"];
$updater_obj->update_interval = $record["update_interval"];
$updater_obj->next_update = $record["next_update"];
$updater_obj->last_status = $record["last_status"];
$updater_obj->checkParameters();
$retarray[]=$updater_obj;
}
$this->db->free($resql);
return $retarray;
}
else
{
$this->error=$this->db->error();
return -1;
}
}
/**
* List all updaters which need to be processed
*
* @return array Array of price global variable updaters
*/
function listPendingUpdaters()
{
$sql = "SELECT rowid, type, description, parameters, fk_variable, update_interval, next_update, last_status";
$sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " WHERE next_update < ".dol_now();
dol_syslog(get_class($this)."::processUpdaters");
$resql=$this->db->query($sql);
if ($resql)
{
$retarray = array();
while ($record = $this->db->fetch_array($resql))
{
$updater_obj = new PriceGlobalVariableUpdater($this->db);
$updater_obj->id = $record["rowid"];
$updater_obj->type = $record["type"];
$updater_obj->description = $record["description"];
$updater_obj->parameters = $record["parameters"];
$updater_obj->fk_variable = $record["fk_variable"];
$updater_obj->update_interval = $record["update_interval"];
$updater_obj->next_update = $record["next_update"];
$updater_obj->last_status = $record["last_status"];
$updater_obj->checkParameters();
$retarray[]=$updater_obj;
}
$this->db->free($resql);
return $retarray;
}
else
{
$this->error=$this->db->error();
return -1;
}
}
/**
* Handles the processing of this updater
*
* @return int <0 if KO, 0 if OK but no global variable found, >0 if OK
*/
function process()
{
global $langs, $user;
$langs->load("errors");
$this->error = null;
$this->checkParameters();
//Try to load the target global variable and abort if fails
if ($this->fk_variable < 1) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater5");
return 0;
}
$price_globals = new PriceGlobalVariable($this->db);
$res = $price_globals->fetch($this->fk_variable);
if ($res < 1) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater5");
return 0;
}
//Process depending of type
if ($this->type == 0 || $this->type == 1) {
//Get and check if required parameters are present
$parameters = json_decode($this->parameters, true);
if (!isset($parameters)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater1", $this->parameters);
return -1;
}
$url = $parameters['URL'];
if (!isset($url)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater2", 'URL');
return -1;
}
$value = $parameters['VALUE'];
if (!isset($value)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater2", 'VALUE');
return -1;
}
$result = "";
if ($this->type == 0) {
//CURL client
$handle = curl_init();
curl_setopt_array($handle, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_POST => false,
CURLOPT_HEADER => false,
));
$result = curl_exec($handle);
$code = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if (!isset($result)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater0", "empty response");
return -1;
}
if ($code !== 200) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater0", $code);
return -1;
}
//Decode returned response
$result = json_decode($result, true);
} elseif ($this->type == 1) {
$ns = $parameters['NS'];
if (!isset($ns)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater2", 'NS');
return -1;
}
$method = $parameters['METHOD'];
if (!isset($method)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater2", 'METHOD');
return -1;
}
$data = $parameters['DATA'];
if (!isset($data)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater2", 'DATA');
return -1;
}
//SOAP client
require_once NUSOAP_PATH.'/nusoap.php';
$soap_client = new nusoap_client($url);
$soap_client->soap_defencoding='UTF-8';
$soap_client->decodeUTF8(false);
$result = $soap_client->call($method, $data, $ns,'');
//Check if result is a error
if ($result === false) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater4", $soap_client->error_str);
return -1;
}
}
//Explode value and walk for each key in value array to get the relevant key
$value = explode(',', $value);
foreach ($value as $key) {
$result = $result[$key];
}
if (!isset($result)) {
$this->error = $langs->trans("ErrorGlobalVariableUpdater3");
return -1;
}
//Save data to global and update it
$price_globals->value = $result;
$price_globals->update($user);
}
return 1;
}
/**
* Update next_update into database
*
* @param string $next_update Next update to write
* @param User $user User that modifies
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function update_next_update($next_update, $user=0, $notrigger=0)
{
$error=0;
$this->next_update = $next_update;
$this->checkParameters();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
$sql.= " next_update = ".$this->next_update;
$sql.= " WHERE rowid = ".$this->id;
$this->db->begin();
dol_syslog(get_class($this)."::update_next_update");
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::update_next_update ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return 1;
}
}
/**
* Update last_status into database
*
* @param string $last_status Status to write
* @param User $user User that modifies
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function update_status($last_status, $user=0, $notrigger=0)
{
$error=0;
$this->last_status = $last_status;
$this->checkParameters();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
$sql.= " last_status = ".(isset($this->last_status)?"'".$this->db->escape($this->last_status)."'":"''");
$sql.= " WHERE rowid = ".$this->id;
$this->db->begin();
dol_syslog(get_class($this)."::update_status");
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(get_class($this)."::update_status ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
else
{
$this->db->commit();
return 1;
}
}
}

View File

@ -1,5 +1,5 @@
<?php
/* Copyright (C) 2014 Ion Agorria <ion@agorria.com>
/* Copyright (C) 2015 Ion Agorria <ion@agorria.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
@ -16,13 +16,15 @@
*/
/**
* \file htdocs/product/class/priceparser.class.php
* \file htdocs/product/dynamic_price/class/price_parser.class.php
* \ingroup product
* \brief File of class to calculate prices using expression
*/
require_once DOL_DOCUMENT_ROOT.'/includes/evalmath/evalmath.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceexpression.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_global_variable.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_global_variable_updater.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
/**
@ -30,17 +32,17 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
*/
class PriceParser
{
protected $db;
// Limit of expressions per price
public $limit = 100;
// The error that ocurred when parsing price
public $error;
// The expression that caused the error
public $error_expr;
//The special char
public $special_chr = "#";
//The separator char
public $separator_chr = ";";
protected $db;
// Limit of expressions per price
public $limit = 100;
// The error that occurred when parsing price
public $error;
// The expression that caused the error
public $error_expr;
//The special char
public $special_chr = "#";
//The separator char
public $separator_chr = ";";
/**
* Constructor
@ -104,7 +106,7 @@ class PriceParser
{
return $langs->trans("ErrorPriceExpression".$code, $info);
}
else if (in_array($code, array(6))) //Errors which have 2 args
else if (in_array($code, array(6, 23))) //Errors which have 2 args
{
return $langs->trans("ErrorPriceExpression".$code, $info[0], $info[1]);
}
@ -128,6 +130,7 @@ class PriceParser
*/
public function parseExpression($product, $expression, $values)
{
global $user;
//Accessible product values by expressions
$values = array_merge($values, array(
"tva_tx" => $product->tva_tx,
@ -139,13 +142,31 @@ class PriceParser
"price_min" => $product->price_min,
));
//Retreive all extrafield for product and add it to values
//Retrieve all extrafield for product and add it to values
$extrafields = new ExtraFields($this->db);
$extralabels = $extrafields->fetch_name_optionals_label('product', true);
$product->fetch_optionals($product->id, $extralabels);
foreach ($extrafields->attribute_label as $key=>$label)
{
$values['options_'.$key] = $product->array_options['options_'.$key];
$values["extrafield_".$key] = $product->array_options['options_'.$key];
}
//Process any pending updaters
$price_updaters = new PriceGlobalVariableUpdater($this->db);
foreach ($price_updaters->listPendingUpdaters() as $entry) {
//Schedule the next update by adding current timestamp (secs) + interval (mins)
$entry->update_next_update(dol_now() + ($entry->update_interval * 60), $user);
//Do processing
$res = $entry->process();
//Store any error or clear status if OK
$entry->update_status($res < 1?$entry->error:'', $user);
}
//Get all global values
$price_globals = new PriceGlobalVariable($this->db);
foreach ($price_globals->listGlobalVariables() as $entry)
{
$values["global_".$entry->code] = $entry->value;
}
//Check if empty
@ -153,36 +174,32 @@ class PriceParser
if (empty($expression))
{
$this->error = array(20, null);
return -1;
return -2;
}
//Prepare the lib, parameters and values
$em = new EvalMath();
$em->suppress_errors = true; //Don't print errors on page
$this->error_expr = null;
$search = array();
$replace = array();
foreach ($values as $key => $value) {
if ($value !== null) {
$search[] = $this->special_chr.$key.$this->special_chr;
$replace[] = $value;
}
}
$last_result = null;
//Iterate over each expression splitted by $separator_chr
$expression = str_replace("\n", $this->separator_chr, $expression);
foreach ($values as $key => $value)
{
$expression = str_replace($this->special_chr.$key.$this->special_chr, "$value", $expression);
}
$expressions = explode($this->separator_chr, $expression);
$expressions = array_slice($expressions, 0, $limit);
$expressions = array_slice($expressions, 0, $this->limit);
foreach ($expressions as $expr) {
$expr = trim($expr);
if (!empty($expr))
{
$expr = str_ireplace($search, $replace, $expr);
$last_result = $em->evaluate($expr);
$this->error = $em->last_error_code;
if ($this->error !== null) { //$em->last_error is null if no error happened, so just check if error is not null
$this->error_expr = $expr;
return -2;
return -3;
}
}
}
@ -190,15 +207,15 @@ class PriceParser
if (empty($vars["price"])) {
$vars["price"] = $last_result;
}
if ($vars["price"] === null)
if (!isset($vars["price"]))
{
$this->error = array(21, $expression);
return -3;
return -4;
}
if ($vars["price"] < 0)
{
$this->error = array(22, $expression);
return -4;
return -5;
}
return $vars["price"];
}
@ -209,13 +226,13 @@ class PriceParser
* @param Product $product The Product object to get information
* @param string $expression The expression to parse
* @param array $extra_values Any aditional values for expression
* @return int > 0 if OK, < 1 if KO
* @return int > 0 if OK, < 1 if KO
*/
public function parseProductExpression($product, $expression, $extra_values = array())
{
//Get the supplier min
$productFournisseur = new ProductFournisseur($this->db);
$supplier_min_price = $productFournisseur->find_min_price_product_fournisseur($product->id);
$productFournisseur = new ProductFournisseur($this->db);
$supplier_min_price = $productFournisseur->find_min_price_product_fournisseur($product->id);
//Accessible values by expressions
$extra_values = array_merge($extra_values, array(
@ -237,7 +254,7 @@ class PriceParser
*
* @param Product $product The Product object to get information
* @param array $extra_values Any aditional values for expression
* @return int > 0 if OK, < 1 if KO
* @return int > 0 if OK, < 1 if KO
*/
public function parseProduct($product, $extra_values = array())
{
@ -261,7 +278,7 @@ class PriceParser
* @param int $quantity Supplier Min quantity
* @param int $tva_tx Supplier VAT rate
* @param array $extra_values Any aditional values for expression
* @return int > 0 if OK, < 1 if KO
* @return int > 0 if OK, < 1 if KO
*/
public function parseProductSupplierExpression($product_id, $expression, $quantity = null, $tva_tx = null, $extra_values = array())
{
@ -285,7 +302,7 @@ class PriceParser
* @param int $quantity Min quantity
* @param int $tva_tx VAT rate
* @param array $extra_values Any aditional values for expression
* @return int > 0 if OK, < 1 if KO
* @return int > 0 if OK, < 1 if KO
*/
public function parseProductSupplier($product_id, $expression_id, $quantity = null, $tva_tx = null, $extra_values = array())
{

View File

@ -16,23 +16,24 @@
*/
/**
* \file htdocs/product/expression.php
* \file htdocs/product/expression/editor.php
* \ingroup product
* \brief Page for editing expression
*/
require '../main.inc.php';
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceexpression.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_global_variable.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$langs->load("products");
$langs->load("accountancy"); //"Back" translation is on this file
$id = GETPOST('id', 'int');
$eid = GETPOST('eid', 'int');
$action = GETPOST('action', 'alpha');
$action = GETPOST('action', 'alpha');
$title = GETPOST('expression_title', 'alpha');
$expression = GETPOST('expression');
$tab = GETPOST('tab', 'alpha');
@ -47,6 +48,7 @@ $product = new Product($db);
$product->fetch($id, '');
$price_expression = new PriceExpression($db);
$price_globals = new PriceGlobalVariable($db);
//Fetch expression data
if (empty($eid)) //This also disables fetch when eid == 0
@ -79,7 +81,7 @@ if ($action == 'add')
{
$price_expression->title = $title;
$price_expression->expression = $expression;
$result = $price_expression->create($user);
$result = $price_expression->create($user);
if ($result > 0) //created successfully, set the eid to newly created entry
{
$eid = $price_expression->id;
@ -120,7 +122,7 @@ if ($action == 'update')
$price_expression->id = $eid;
$price_expression->title = $title;
$price_expression->expression = $expression;
$result = $price_expression->update($user);
$result = $price_expression->update($user);
if ($result < 0)
{
setEventMessage("update: ".$price_expression->error, 'errors');
@ -146,7 +148,7 @@ if ($action == 'delete')
{
if ($eid != 0)
{
$result = $price_expression->delete($eid, $user);
$result = $price_expression->delete($eid, $user);
if ($result < 0)
{
setEventMessage("delete: ".$price_expression->error, 'errors');
@ -184,8 +186,17 @@ print '<tr><td class="fieldrequired">'.$langs->trans("Name").'</td><td>';
print '<input class="flat" name="expression_title" size="15" value="'.($price_expression->title?$price_expression->title:'').'">';
print '</td></tr>';
//Help text
$help_text = $langs->trans("PriceExpressionEditorHelp1");
$help_text.= '<br><br>'.$langs->trans("PriceExpressionEditorHelp2");
$help_text.= '<br><br>'.$langs->trans("PriceExpressionEditorHelp3");
$help_text.= '<br><br>'.$langs->trans("PriceExpressionEditorHelp4");
$help_text.= '<br><br>'.$langs->trans("PriceExpressionEditorHelp5");
foreach ($price_globals->listGlobalVariables() as $entry) {
$help_text.= '<br><b>#globals_'.$entry->code.'#</b> '.$entry->description.' = '.$entry->value;
}
//Price expression editor
$help_text = $langs->trans("PriceExpressionEditorHelp1").'<br><br>'.$langs->trans("PriceExpressionEditorHelp2").'<br><br>'.$langs->trans("PriceExpressionEditorHelp3").'<br><br>'.$langs->trans("PriceExpressionEditorHelp4");
print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceExpressionEditor"),$help_text,1).'</td><td>';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
$doleditor=new DolEditor('expression',isset($price_expression->expression)?$price_expression->expression:'','',300,'','',false,false,false,4,80);
@ -194,7 +205,7 @@ print '</td></tr>';
print '</table>';
//Buttons
print '<div align="center">';
print '<div class="center">';
print '<input type="submit" class="butAction" value="'.$langs->trans("Save").'">';
print '<span id="back" class="butAction">'.$langs->trans("Back").'</span>';
if ($eid == 0)
@ -207,7 +218,7 @@ else
}
print '</div>';
print '</form>';
print '</form>';
// This code reloads the page depending of selected option, goes to page selected by tab when back is pressed
print '<script type="text/javascript">
@ -217,7 +228,7 @@ print '<script type="text/javascript">
jQuery("#expression_selection").change(on_change);
}
function on_click() {
window.location = "'.str_replace('expression.php', $tab.'.php', $_SERVER["PHP_SELF"]).'?id='.$id.($tab == 'price' ? '&action=edit_price' : '').'";
window.location = "'.str_replace('dynamic_price/editor.php', $tab.'.php', $_SERVER["PHP_SELF"]).'?id='.$id.($tab == 'price' ? '&action=edit_price' : '').'";
}
function on_change() {
window.location = "'.$_SERVER["PHP_SELF"].'?id='.$id.'&tab='.$tab.'&eid=" + $("#expression_selection").attr("value");

View File

@ -31,8 +31,8 @@ require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceexpression.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$langs->load("products");
$langs->load("suppliers");
@ -425,7 +425,7 @@ if ($id || $ref)
on_change();
}
function on_click() {
window.location = "'.DOL_URL_ROOT.'/product/expression.php?id='.$id.'&tab=fournisseurs&eid=" + $("#eid").attr("value");
window.location = "'.DOL_URL_ROOT.'/product/dynamic_price/editor.php?id='.$id.'&tab=fournisseurs&eid=" + $("#eid").attr("value");
}
function on_change() {
if ($("#eid").attr("value") == 0) {

View File

@ -27,7 +27,7 @@
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
$type=GETPOST("type",'int');
if ($type =='' && !$user->rights->produit->lire) $type='1'; // Force global page on service page only

View File

@ -31,8 +31,8 @@
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT . '/product/class/priceexpression.class.php';
require_once DOL_DOCUMENT_ROOT . '/product/class/priceparser.class.php';
require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_expression.class.php';
require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
@ -705,7 +705,7 @@ if ($action == 'edit_price' && ($user->rights->produit->creer || $user->rights->
on_change();
}
function on_click() {
window.location = "'.DOL_URL_ROOT.'/product/expression.php?id='.$id.'&tab=price&eid=" + $("#eid").attr("value");
window.location = "'.DOL_URL_ROOT.'/product/dynamic_price/editor.php?id='.$id.'&tab=price&eid=" + $("#eid").attr("value");
}
function on_change() {
if ($("#eid").attr("value") == 0) {

View File

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2003-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2005-2013 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011 Jean Heimburger <jean@tiaris.info>
* Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
*
@ -21,7 +21,7 @@
/**
* \file htdocs/product/stock/class/mouvementstock.class.php
* \ingroup stock
* \brief Fichier de la classe de gestion des mouvements de stocks
* \brief File of class to manage stock movement (input or output)
*/
@ -33,6 +33,12 @@ class MouvementStock extends CommonObject
var $error;
var $db;
var $product_id;
var $entrepot_id;
var $qty;
var $type;
/**
* Constructor
*
@ -49,10 +55,11 @@ class MouvementStock extends CommonObject
* @param User $user User object
* @param int $fk_product Id of product
* @param int $entrepot_id Id of warehouse
* @param int $qty Qty of movement (can be <0 or >0)
* @param int $qty Qty of movement (can be <0 or >0 depending on parameter type)
* @param int $type Direction of movement:
* 0=input (stock increase after stock transfert), 1=output (stock decrease after stock transfer),
* 2=output (stock decrease), 3=input (stock increase)
* Note that qty should be > 0 with 0 or 3, < 0 with 1 or 2.
* @param int $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed.
* @param string $label Label of stock movement
* @param string $inventorycode Inventory code
@ -156,9 +163,9 @@ class MouvementStock extends CommonObject
// Define current values for qty and pmp
$oldqty=$product->stock_reel;
$oldqtywarehouse=0;
$oldpmp=$product->pmp;
$oldpmpwarehouse=0;
$oldqtywarehouse=0;
//$oldpmpwarehouse=0;
// Test if there is already a record for couple (warehouse / product)
$num = 0;
@ -176,7 +183,7 @@ class MouvementStock extends CommonObject
{
$num = 1;
$oldqtywarehouse = $obj->reel;
$oldpmpwarehouse = $obj->pmp;
//$oldpmpwarehouse = $obj->pmp;
$fk_product_stock = $obj->rowid;
}
$this->db->free($resql);
@ -190,8 +197,7 @@ class MouvementStock extends CommonObject
// Calculate new PMP.
$newpmp=0;
$newpmpwarehouse=0;
/*
//$newpmpwarehouse=0;
if (! $error)
{
// Note: PMP is calculated on stock input only (type of movement = 0 or 3). If type == 0 or 3, qty should be > 0.
@ -200,7 +206,7 @@ class MouvementStock extends CommonObject
{
// If we will change PMP for the warehouse we edit and the product, we must first check/clean that PMP is defined
// on every stock entry with old value (so global updated value will match recalculated value from product_stock)
$sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp = ".($oldpmp?$oldpmp:'0');
/* $sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp = ".($oldpmp?$oldpmp:'0');
$sql.= " WHERE pmp = 0 AND fk_product = ".$fk_product;
dol_syslog(get_class($this)."::_create", LOG_DEBUG);
$resql=$this->db->query($sql);
@ -209,18 +215,19 @@ class MouvementStock extends CommonObject
$this->error=$this->db->lasterror();
$error = -4;
}
*/
$oldqtytouse=($oldqty >= 0?$oldqty:0);
// We make a test on oldpmp>0 to avoid to use normal rule on old data with no pmp field defined
if ($oldpmp > 0) $newpmp=price2num((($oldqtytouse * $oldpmp) + ($qty * $price)) / ($oldqtytouse + $qty), 'MU');
else
{
$newpmp=$price; // For this product, PMP was not yet set. We will set it later.
$newpmp=$price; // For this product, PMP was not yet set. We set it to input price.
}
/*
$oldqtywarehousetouse=$oldqtywarehouse;
if ($oldpmpwarehouse > 0) $newpmpwarehouse=price2num((($oldqtywarehousetouse * $oldpmpwarehouse) + ($qty * $price)) / ($oldqtywarehousetouse + $qty), 'MU');
else $newpmpwarehouse=$price;
*/
//print "oldqtytouse=".$oldqtytouse." oldpmp=".$oldpmp." oldqtywarehousetouse=".$oldqtywarehousetouse." oldpmpwarehouse=".$oldpmpwarehouse." ";
//print "qty=".$qty." newpmp=".$newpmp." newpmpwarehouse=".$newpmpwarehouse;
//exit;
@ -228,28 +235,31 @@ class MouvementStock extends CommonObject
else if ($type == 1 || $type == 2)
{
// After a stock decrease, we don't change value of PMP for product.
$newpmp = $oldpmp;
}
else
{
$newpmp = $oldpmp;
$newpmpwarehouse = $oldpmpwarehouse;
//$newpmpwarehouse = $oldpmpwarehouse;
}
}
*/
// Update denormalized value of stock in product_stock and product
// Update stock quantity
if (! $error)
{
if ($num > 0)
{
$sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp = ".$newpmpwarehouse.", reel = reel + ".$qty;
//$sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp = ".$newpmpwarehouse.", reel = reel + ".$qty;
$sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET reel = reel + ".$qty;
$sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product;
}
else
{
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product_stock";
$sql.= " (pmp, reel, fk_entrepot, fk_product) VALUES ";
$sql.= " (".$newpmpwarehouse.", ".$qty.", ".$entrepot_id.", ".$fk_product.")";
//$sql.= " (pmp, reel, fk_entrepot, fk_product) VALUES ";
//$sql.= " (".$newpmpwarehouse.", ".$qty.", ".$entrepot_id.", ".$fk_product.")";
$sql.= " (reel, fk_entrepot, fk_product) VALUES ";
$sql.= " (".$qty.", ".$entrepot_id.", ".$fk_product.")";
}
dol_syslog(get_class($this)."::_create", LOG_DEBUG);
@ -274,6 +284,7 @@ class MouvementStock extends CommonObject
if ($result<0) $error++;
}
// Update PMP and denormalized value of stock qty at product level
if (! $error)
{
$sql = "UPDATE ".MAIN_DB_PREFIX."product SET pmp = ".$newpmp.", stock = ".$this->db->ifsql("stock IS NULL", 0, "stock") . " + ".$qty;
@ -480,7 +491,7 @@ class MouvementStock extends CommonObject
* @param int $qty Quantity of product with batch number
* @return int <0 if KO, else return productbatch id
*/
function _create_batch($dluo, $qty )
function _create_batch($dluo, $qty)
{
$pdluo=new Productbatch($this->db);
@ -505,7 +516,7 @@ class MouvementStock extends CommonObject
$result = -1;
}
//batch record found so we update it
// Batch record found so we update it
if ($result>0)
{
if ($pdluo->id >0)
@ -545,8 +556,10 @@ class MouvementStock extends CommonObject
* @param int $origintype origin type
* @return string name url
*/
function get_origin($fk_origin, $origintype) {
switch ($origintype) {
function get_origin($fk_origin, $origintype)
{
switch ($origintype)
{
case 'commande':
require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
$origin = new Commande($this->db);
@ -576,4 +589,22 @@ class MouvementStock extends CommonObject
$origin->fetch($fk_origin);
return $origin->getNomUrl(1);
}
/**
* Initialise an instance with random values.
* Used to build previews or test instances.
* id must be 0 if object instance is a specimen.
*
* @return void
*/
function initAsSpecimen()
{
global $user,$langs,$conf,$mysoc;
// Initialize parameters
$this->id=0;
// There is no specific properties. All data into insert are provided as method parameter.
}
}

View File

@ -1,5 +1,5 @@
<?php
define("NOLOGIN",1); // This means this output page does not require to be logged.
//define("NOLOGIN",1); // This means this output page does not require to be logged.
define("NOCSRFCHECK",1); // We accept to go on this page from external web site.
@ -12,7 +12,7 @@ if ($_SERVER['REMOTE_ADDR'] != '127.0.0.1')
}
$usedolheader=0; // 1 = Test inside a dolibarr page, 0 = Use hard coded header
$usedolheader=1; // 1 = Test inside a dolibarr page, 0 = Use hard coded header
// HEADER
@ -21,39 +21,41 @@ $usedolheader=0; // 1 = Test inside a dolibarr page, 0 = Use hard coded header
if (empty($usedolheader))
{
header("Content-type: text/html; charset=UTF8");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="robots" content="noindex,nofollow" />
<meta name="author" content="Dolibarr Development Team">
<link rel="shortcut icon" type="image/x-icon" href="<?php echo DOL_URL_ROOT ?>/theme/eldy/img/favicon.ico"/>
<title>Test page</title>
<!-- Includes for JQuery (Ajax library) -->
<link rel="stylesheet" type="text/css" href="<?php echo DOL_URL_ROOT ?>/includes/jquery/css/smoothness/jquery-ui-latest.custom.css" />
<link rel="stylesheet" type="text/css" href="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/datatables/css/jquery.dataTables.css" />
<?php if ($_GET["dol_use_jmobile"] == 1) { ?>
<link rel="stylesheet" type="text/css" href="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/mobile/jquery.mobile-latest.min.css" />
<?php } ?>
<link rel="stylesheet" type="text/css" title="default" href="<?php echo DOL_URL_ROOT ?>/theme/eldy/style.css.php<?php echo ($_GET["dol_use_jmobile"] == 1)?'?dol_use_jmobile=1&dol_optimize_smallscreen=1':''; ?>" />
<!-- Includes JS for JQuery -->
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/js/jquery-latest.min.js"></script>
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/tablednd/jquery.tablednd.0.6.min.js"></script>
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/datatables/js/jquery.dataTables.js"></script>
<?php if ($_GET["dol_use_jmobile"] == 1) { ?>
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/mobile/jquery.mobile-latest.min.js"></script>--
<?php } ?>
</head>
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="robots" content="noindex,nofollow" />
<meta name="author" content="Dolibarr Development Team">
<link rel="shortcut icon" type="image/x-icon" href="<?php echo DOL_URL_ROOT ?>/theme/eldy/img/favicon.ico"/>
<title>Test page</title>
<!-- Includes for JQuery (Ajax library) -->
<link rel="stylesheet" type="text/css" href="<?php echo DOL_URL_ROOT ?>/includes/jquery/css/smoothness/jquery-ui-latest.custom.css" />
<link rel="stylesheet" type="text/css" href="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/datatables/css/jquery.dataTables.css" />
<?php if ($_GET["dol_use_jmobile"] == 1) { ?>
<link rel="stylesheet" type="text/css" href="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/mobile/jquery.mobile-latest.min.css" />
<?php } ?>
<link rel="stylesheet" type="text/css" title="default" href="<?php echo DOL_URL_ROOT ?>/theme/eldy/style.css.php<?php echo ($_GET["dol_use_jmobile"] == 1)?'?dol_use_jmobile=1&dol_optimize_smallscreen=1':''; ?>" />
<!-- Includes JS for JQuery -->
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/js/jquery-latest.min.js"></script>
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/tablednd/jquery.tablednd.0.6.min.js"></script>
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/datatables/js/jquery.dataTables.js"></script>
<?php if ($_GET["dol_use_jmobile"] == 1) { ?>
<script type="text/javascript" src="<?php echo DOL_URL_ROOT ?>/includes/jquery/plugins/mobile/jquery.mobile-latest.min.js"></script>
<?php } ?>
</head>
<body style="padding: 10px;">
<body style="padding: 10px;">
<div data-role="page">
<div data-role="page">
<?php
<?php
}
else
{
llxHeader();
$arraycss=array('/includes/jquery/plugins/datatables/css/jquery.dataTables.css');
$arrayjs=array('/includes/jquery/plugins/datatables/js/jquery.dataTables.js');
llxHeader('','','','',0,0,$arrayjs,$arraycss);
}
@ -64,7 +66,7 @@ else
<h1>
This page is a sample of page using tables. It is designed to make test with<br>
- css (edit page to change to test another css)<br>
- jmobile (add parameter dol_use_jmobile=1 to enable view with jmobile)<br>
- jmobile (add parameter dol_use_jmobile=1&dol_optimize_smallscreen=1 to enable view with jmobile)<br>
- dataTables<br>
- tablednd<br>
</h1>
@ -111,47 +113,27 @@ This page is a sample of page using tables. It is designed to make test with<br>
<br><hr><br>Example 1 : Table using tags: div.tagtable+div.tagtr+div or div.tagtable+div.tagtr+div.tagtd => Use this for tables that are edited forms<br><br>
<br><hr><br>Example 1 : Standard table => Use this if you need the drag and drop for lines<br>
<?php
$tasksarray=array(1,2,3); // To force having several lines
$tagidfortablednd='tablelines';
if (! empty($conf->use_javascript_ajax)) include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
$sortfield='aaa';
$sortorder='ASC';
$tasksarray=array(1,2,3); // To force having several lines
$tagidfortablednd='tablelines3';
if (! empty($conf->use_javascript_ajax)) include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
?>
<div class="tagtable centpercent" id="tablelines">
<div class="tagtr liste_titre">
<div class="tagtd">line3<input type="hidden" name="cartitem" value="3"></div>
<div class="tagtd">dfsdf</div>
<div class="tagtd">ffdsfsd</div>
<div class="tagtd tdlineupdown">aaaa</div>
</div>
<div class="impair tagtr">
<div class="tagtd">line4<input type="hidden" name="cartitem" value="3"></div>
<div class="tagtd">dfsdf</div>
<div class="tagtd"><input name="count" value="4"></div>
<div class="tagtd tdlineupdown">bbbb</div>
</div>
<div class="pair tagtr">
<div class="tagtd">line5<input type="hidden" name="cartitemb" value="3"></div>
<div class="tagtd">dfsdf</div>
<div class="tagtd"><input name="countb" value="4"></div>
<div class="tagtd tdlineupdown">bbbb</div>
</div>
<!-- Using form into div make Firefox crazy (page loading does not end) -->
<!-- <form class="liste_titre" method="POST" action="1.php">
<div>line1<input type="hidden" name="cartitem" value="1"></div>
<div><label><input type="checkbox" name="hidedetails" value="2"> A checkbox inside a cell</label></div>
<div><input name="count" value="4"></div>
<div><input type="submit" name="count2" class="button noshadow" value="aaa"></div>
</form>
<form class="impair" method="POST" action="2.php">
<div>line2<input type="hidden" name="cartitem" value="2"></div>
<div><select name="hidedetails"><option>aaaaaaaaaaaaaaafd sf sf gfd gfd gs fgdf gaaaa</option><option>gdfs gdf g sdfg dfg fdsg dsfg dfs gdfs gds fgs gdfdf gd</option></select></div>
<div><input name="countb" value="4"></div>
<div class="tdlineupdown"><input type="submit" value="xxx" class="button"></div>
</form>-->
</div>
<table class="liste noborder tagtable centpercent" id="tablelines3">
<tr class="liste_titre">
<?php print getTitleFieldOfList($langs->trans('title1'),0,$_SERVER["PHP_SELF"],'aaa','','','align="left"',$sortfield,$sortorder); ?>
<?php print getTitleFieldOfList($langs->trans('title2'),0,$_SERVER["PHP_SELF"],'bbb','','','align="right"',$sortfield,$sortorder); ?>
<?php print getTitleFieldOfList($langs->trans('title3'),0,$_SERVER["PHP_SELF"],'ccc','','','align="center"',$sortfield,$sortorder); ?>
</tr>
<tr class="pair"><td class="pair">a1</td><td class="pair" align="right">b1</td><td class="tdlineupdown pair" align="left">c1</td></tr>
<tr class="impair"><td class="impair">a2</td><td class="impair" align="right">b2</td><td class="tdlineupdown impair" align="left">c2</td></tr>
</table>
<br>
@ -238,7 +220,7 @@ $('xxxth').replaceWith(
<table id="idtableexample2" class="centpercent">
<thead>
<tr>
<tr class="liste_titre">
<th>snake</th>
<th><label><input type="checkbox" name="hidedetails" value="2"> A checkbox inside a cell</label></th>
<?php print getTitleFieldOfList($langs->trans('zzz'),1,$_SERVER["PHP_SELF"],'','','','align="center" class="tagtd"',$sortfield,$sortorder); ?>
@ -248,81 +230,111 @@ $('xxxth').replaceWith(
<tr>
<td>line1</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line2</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line3</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line4</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line5</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line6</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line7</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line8</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line9</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line10</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line11</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
<tr>
<td>line12</td>
<td>dfsdf</td>
<td> xxx </td>
<td align="center"> xxx </td>
</tr>
</tbody>
</table>
<br>
<br><hr><br>Example 3 : Standard table => Use this if you need the drag and drop for lines<br>
<br><hr><br>Example 3 : Table using tags: div.tagtable+div.tagtr+div or div.tagtable+div.tagtr+div.tagtd => Use this, but AVOID IT if possible, for tables that need to have a different form for each line (drag and drop of lines does not work for this case, also height of title can't be forced to a minimum)<br><br>
<?php
$tasksarray=array(1,2,3); // To force having several lines
$tagidfortablednd='tablelines3';
$tagidfortablednd='tablelines';
if (! empty($conf->use_javascript_ajax)) include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
?>
<table class="tagtable centpercent centpercent" id="tablelines3">
<tr class="liste_titre"><td>title1</td><td>title2</td></tr>
<tr class="pair"><td class="pair">a1</td><td class="tdlineupdown pair">b1</td></tr>
<tr class="impair"><td class="impair">a2</td><td class="tdlineupdown impair">b2</td></tr>
</table>
<br>
<div class="tagtable centpercent" id="tablelines">
<div class="tagtr liste_titre">
<div class="tagtd">line3<input type="hidden" name="cartitem" value="3"></div>
<div class="tagtd">dfsdf</div>
<div class="tagtd">ffdsfsd</div>
<div class="tagtd tdlineupdown">aaaa</div>
</div>
<div class="impair tagtr">
<div class="tagtd">line4<input type="hidden" name="cartitem" value="3"></div>
<div class="tagtd">dfsdf</div>
<div class="tagtd"><input name="count" value="4"></div>
<div class="tagtd tdlineupdown">bbbb</div>
</div>
<div class="pair tagtr">
<div class="tagtd">line5<input type="hidden" name="cartitemb" value="3"></div>
<div class="tagtd">dfsdf</div>
<div class="tagtd"><input name="countb" value="4"></div>
<div class="tagtd tdlineupdown">bbbb</div>
</div>
<!-- Using form into div make Firefox crazy (page loading does not end) -->
<!-- <form class="liste_titre" method="POST" action="1.php">
<div>line1<input type="hidden" name="cartitem" value="1"></div>
<div><label><input type="checkbox" name="hidedetails" value="2"> A checkbox inside a cell</label></div>
<div><input name="count" value="4"></div>
<div><input type="submit" name="count2" class="button noshadow" value="aaa"></div>
</form>
<form class="impair" method="POST" action="2.php">
<div>line2<input type="hidden" name="cartitem" value="2"></div>
<div><select name="hidedetails"><option>aaaaaaaaaaaaaaafd sf sf gfd gfd gs fgdf gaaaa</option><option>gdfs gdf g sdfg dfg fdsg dsfg dfs gdfs gds fgs gdfdf gd</option></select></div>
<div><input name="countb" value="4"></div>
<div class="tdlineupdown"><input type="submit" value="xxx" class="button"></div>
</form>-->
</div>
<?php

View File

@ -313,7 +313,7 @@ print '<tr class="liste_titre">';
print '<td class="liste_titre" align="left">';
print '<input class="flat" type="text" name="sref" size="8" value="'.$sref.'">';
print '</td>';
print '<td class="liste_titre">'; // date
print '<td class="liste_titre nowrap">'; // date
print $formother->select_month($month?$month:-1,'month',1);
$formother->select_year($year?$year:-1,'year',1, 20, 1);
print '</td>';

View File

@ -262,6 +262,7 @@ if ($result > 0)
foreach($conf->global as $key => $val)
{
if (! preg_match('/^NOTIFICATION_FIXEDEMAIL_(.*)/', $key, $reg)) continue;
$var = ! $var;
print '<tr '.$bc[$var].'><td>';
$listtmp=explode(',',$val);
$first=1;

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 969 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

View File

@ -443,11 +443,13 @@ textarea.centpercent {
.movable {
cursor: move;
}
.borderrightlight
{
border-right: 1px solid #DDD;
}
#formuserfile_link {
margin-left: 1px;
}
/* ============================================================================== */
/* Styles to hide objects */
@ -680,7 +682,7 @@ div.tmenuleft
<?php if (empty($conf->dol_optimize_smallscreen)) { ?>
width: 5px;
height: <?php print $heightmenu+4; ?>px;
background: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/menutab-r.png',1); ?>) 0 0 no-repeat;
background: url(<?php echo dol_buildpath($path.'/theme/'.$theme.'/img/menutab-r.png',1); ?>) 0 -6px no-repeat;
<?php } ?>
}
div.tmenucenter
@ -840,9 +842,6 @@ foreach($mainmenuusedarray as $val)
.bodylogin
{
background: #f0f0f0;
/* -moz-box-shadow: inset 0 0 10px #000000;
-webkit-box-shadow: inset 0 0 10px #000000;
box-shadow: inset 0 0 10px #000000; */
}
.login_vertical_align {
padding: 10px;
@ -1742,24 +1741,24 @@ table.noborder, table.formdoc, div.noborder {
border-collapse: separate !important;
border-spacing: 0px;
/*
border-right-width: 1px;
border-right-color: #BBBBBB;
border-right-style: solid;
border-left-width: 1px;
border-left-color: #B0B0B0;
border-left-style: solid;
border-bottom-width: 1px;
border-bottom-color: #BBBBBB;
border-bottom-style: solid;
*/
border-left-width: 1px;
border-left-color: #DDDDDD;
border-left-style: solid;
margin: 0px 0px 2px 0px;
-moz-box-shadow: 2px 2px 4px #DDD;
-webkit-box-shadow: 2px 2px 4px #DDD;
box-shadow: 2px 2px 4px #DDD;
-moz-box-shadow: 3px 3px 4px #ddd;
-webkit-box-shadow: 3px 3px 4px #ddd;
box-shadow: 3px 3px 4px #ddd;
-moz-border-radius: 0.2em;
-webkit-border-radius: 0.2em;
@ -1776,7 +1775,7 @@ table.noborder tr, div.noborder form {
border-left-width: 1px;
border-left-color: #BBBBBB;
border-left-style: solid;
height: 20px;
height: 26px;
}
table.noborder th, table.noborder td, div.noborder form, div.noborder form div {
@ -1800,9 +1799,10 @@ table.nobordernopadding td {
table.liste {
width: 100%;
border-collapse: collapse;
border-top-color: #FEFEFE;
/*
border-right-width: 1px;
border-right-color: #BBBBBB;
border-right-style: solid;
@ -1810,7 +1810,7 @@ table.liste {
border-left-width: 1px;
border-left-color: #CCCCCC;
border-left-style: solid;
*/
border-bottom-width: 1px;
border-bottom-color: #BBBBBB;
border-bottom-style: solid;
@ -1818,9 +1818,9 @@ table.liste {
margin-bottom: 2px;
margin-top: 0px;
-moz-box-shadow: 3px 3px 4px #DDD;
-webkit-box-shadow: 3px 3px 4px #DDD;
box-shadow: 3px 3px 4px #DDD;
-moz-box-shadow: 0px 3px 4px #DDD;
-webkit-box-shadow: 0px 3px 4px #DDD;
box-shadow: 0px 3px 4px #DDD;
}
table.liste td {
padding-right: 2px;
@ -1894,6 +1894,7 @@ table.liste td {
}
.pair, .nohover .pair:hover, tr.pair td.nohover {
/*
<?php if ($usecss3) { ?>
background: linear-gradient(bottom, rgb(<?php echo $colorbacklinepair1; ?>) 85%, rgb(<?php echo $colorbacklinepair2; ?>) 100%);
background: -o-linear-gradient(bottom, rgb(<?php echo $colorbacklinepair1; ?>) 85%, rgb(<?php echo $colorbacklinepair2; ?>) 100%);
@ -1903,13 +1904,24 @@ table.liste td {
<?php } else { ?>
background: #ffffff;
<?php } ?>
*/
font-family: <?php print $fontlist ?>;
border: 0px;
margin-bottom: 1px;
color: #202020;
background-color: #f9f9f9;
}
tr.pair td, tr.impair td {
padding: 4px;
border-bottom: 1px solid #ddd;
}
div.liste_titre .tagtd {
vertical-align: middle;
}
div.liste_titre {
min-height: 26px !important; /* We cant use height because it's a div and it should be higher if content is more. but min-height doe not work either for div */
}
tr.liste_titre, tr.liste_titre_sel, form.liste_titre, form.liste_titre_sel, table.dataTable.tr
{
height: 26px !important;
@ -2063,8 +2075,9 @@ tr.box_impair {
font-family: <?php print $fontlist ?>;
}
tr.box_pair {
<?php if ($usecss3) { ?>
/*<?php if ($usecss3) { ?>
background: -o-linear-gradient(bottom, rgb(<?php echo $colorbacklinepair1; ?>) 85%, rgb(<?php echo $colorbacklinepair2; ?>) 100%);
background: -moz-linear-gradient(bottom, rgb(<?php echo $colorbacklinepair1; ?>) 85%, rgb(<?php echo $colorbacklinepair2; ?>) 100%);
background: -webkit-linear-gradient(bottom, rgb(<?php echo $colorbacklinepair1; ?>) 85%, rgb(<?php echo $colorbacklinepair2; ?>) 100%);
@ -2073,7 +2086,15 @@ tr.box_pair {
<?php } else { ?>
background: #ffffff;
<?php } ?>
*/
font-family: <?php print $fontlist ?>;
background-color: #f9f9f9;
}
tr.box_pair td, tr.box_impair td {
padding: 4px;
border-bottom: 1px solid #ddd;
}
.formboxfilter {
@ -2924,7 +2945,10 @@ div.dolEventError h1, div.dolEventError h2 {
{
text-decoration: underline !important;
}
.paginate_button
{
font-weight: normal !important;
}
/* For jquery plugin combobox */
/* Disable this. It breaks wrapping of boxes
.ui-corner-all { white-space: nowrap; } */

1
htdocs/theme/md_exp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.new

View File

@ -0,0 +1 @@
2003-2004 Laurent Destailleur <eldy@users.sourceforge.net>

View File

@ -0,0 +1,92 @@
/*
Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
CKEDITOR.editorConfig = function( config )
{
// Define changes to default configuration here.
// http://docs.cksource.com/CKEditor_3.x/Developers_Guide
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
config.enterMode = CKEDITOR.ENTER_BR;
config.resize_enabled = false;
//config.resize_maxHeight = 3000;
//config.resize_maxWidth = 3000;
//config.height = '300px';
//config.resize_dir = 'vertical'; // horizontal, vertical, both
config.removePlugins = 'elementspath,save'; // config.removePlugins = 'elementspath,save,font';
config.removeDialogTabs = 'flash:advanced'; // config.removeDialogTabs = 'flash:advanced;image:Link';
config.protectedSource.push( /<\?[\s\S]*?\?>/g ); // Prevent PHP Code to be formatted
//config.menu_groups = 'clipboard,table,anchor,link,image'; // for context menu 'clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea'
//config.language = 'de';
//config.defaultLanguage = 'en';
//config.contentsLanguage = 'fr';
config.fullPage = false; // Not a full html page string, just part of it
config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)';
//config.contentsCss = '/css/mysitestyles.css';
config.image_previewText=' '; // Must no be empty
config.toolbar_Full =
[
['Source','-','Save','NewPage','Preview','-','Templates'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],
'/',
['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['BidiLtr', 'BidiRtl'],
['Link','Unlink','Anchor'],
['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak','Iframe'],
'/',
['Styles','Format','Font','FontSize'],
['TextColor','BGColor'],
['Maximize', 'ShowBlocks','-','About']
];
// Used for mailing fields
config.toolbar_dolibarr_mailings =
[
['Source','Maximize'],
['Cut','Copy','Paste','-','SpellChecker'],
['Undo','Redo','-','Find','Replace'],
['Format','Font','FontSize'],
['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'],
['NumberedList','BulletedList','Outdent','Indent','CreateDiv'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['Link','Unlink','Anchor','Image','Table','HorizontalRule','SpecialChar']
];
// Used for notes fields
config.toolbar_dolibarr_notes =
[
['Source','Maximize'],
['Cut','Copy','Paste','-','SpellChecker'],
['Undo','Redo','-','Find','Replace'],
['Format','Font','FontSize'],
['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'],
['NumberedList','BulletedList','Outdent','Indent'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['Link','Unlink','Image','Table','HorizontalRule','SpecialChar']
];
// Used for details lines
config.toolbar_dolibarr_details =
[
['Source','Maximize'],
['Cut','Copy','Paste','-','SpellChecker'],
['Format','Font','FontSize'],
['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'],
['NumberedList','BulletedList','Outdent','Indent'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['Link','Unlink','SpecialChar']
];
// Used for mailing fields
config.toolbar_dolibarr_readonly =
[
['Source','Maximize'],
['Find']
];
};

View File

View File

@ -0,0 +1,34 @@
<?php
/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2012 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/>.
*/
/**
* \file htdocs/theme/eldy/graph-color.php
* \brief File to declare colors to use to build graphics with theme Eldy
* \ingroup core
*
* To include file, do this:
* $color_file = DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/graph-color.php';
* if (is_readable($color_file)) include_once $color_file;
*/
global $theme_bordercolor, $theme_datacolor, $theme_bgcolor, $theme_bgcoloronglet;
$theme_bordercolor = array(235,235,224);
$theme_datacolor = array(array(190,190,220), array(200,160,180), array(125,135,150), array(170,140,190), array(190,190,170), array(190,170,190), array(170,190,190), array(150,135,125), array(85,135,150), array(150,135,80), array(150,80,150));
$theme_bgcolor = array(hexdec('F4'),hexdec('F4'),hexdec('F4'));
$theme_bgcoloronglet = array(hexdec('DE'),hexdec('E7'),hexdec('EC'));

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

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