Merge branch 'price-global-variables' of

https://github.com/IonAgorria/dolibarr into
IonAgorria-price-global-variables

Conflicts:
	htdocs/install/mysql/migration/3.7.0-3.8.0.sql
	htdocs/product/dynamic_price/editor.php
This commit is contained in:
Laurent Destailleur 2015-03-22 12:45:04 +01:00
commit 55140afde4
19 changed files with 1491 additions and 80 deletions

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

@ -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

@ -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

@ -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';
/**

View File

@ -415,3 +415,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_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

@ -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

@ -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

@ -1205,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) {
@ -1240,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) {
@ -1696,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) {