CMXX - Pricelists

This commit is contained in:
“VeLiTi”
2025-01-23 12:54:16 +01:00
parent 53686b3c33
commit 661783270a
16 changed files with 811 additions and 182 deletions

28
api.php
View File

@@ -16,6 +16,34 @@ require_once './assets/functions.php';
include './settings/settings.php';
include './settings/config.php';
//------------------------------------------
// Header security - enabled via config
//------------------------------------------
if (header_security){
header('Content-Type: application/json');
// Set strict security headers
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
header('Content-Security-Policy: default-src \'none\'');
header('Access-Control-Allow-Origin: ' . $_ENV['ALLOWED_ORIGIN']);
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Accept, Authorization');
// Validate Content-Type
if (!str_contains($_SERVER['CONTENT_TYPE'],'application/json')) {
http_response_code(400);
exit(json_encode(['error' => 'Invalid Content-Type']));
}
// Validate request size
if ($_SERVER['CONTENT_LENGTH'] > '5M') {
http_response_code(413);
exit(json_encode(['error' => 'Request too large']));
}
}
//------------------------------------------
// Retrieve API version and Collection
// api.php/(v)ersion/{get/post}/collection/

View File

@@ -67,6 +67,10 @@ elseif (isset($criterias['list']) && $criterias['list'] =='') {
//SQL for Paging
$sql = 'SELECT * FROM products '.$whereclause.'';
}
elseif (isset($criterias['list']) && $criterias['list'] =='price'){
//GET ALL PRODUCTS AND PRODUCT ATTRIBUTES FOR PRICING
$sql = '(SELECT rowID as product_id, productname as product_name FROM products where salesflag = 1 '.$whereclause.' ) UNION (SELECT attribute_id as product_id, item_name as product_name FROM `products_attributes_items` WHERE item_status = 1 '.$whereclause.' )';
}
else {
//SQL for Paging
$sql = 'SELECT * FROM products '.$whereclause.' LIMIT :page,:num_products';
@@ -100,7 +104,7 @@ if(isset($criterias['totals']) && $criterias['totals']==''){
$messages = $stmt->fetch();
$messages = $messages[0];
}
elseif(isset($criterias['list']) && $criterias['list']==''){
elseif(isset($criterias['list'])){
//Excute Query
$stmt->execute();
//Get results

View File

@@ -0,0 +1,142 @@
<?php
defined($security_key) or exit;
//------------------------------------------
// Products_configurations
//------------------------------------------
//Connect to DB
$pdo = dbConnect($dbname);
//SoldTo is empty
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
//default whereclause
$whereclause = '';
switch ($permission) {
case '4':
$whereclause = '';
break;
case '3':
$whereclause = '';
break;
default:
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
$whereclause = 'WHERE accounthierarchy like "'.$condition.'"';
break;
}
//NEW ARRAY
$criterias = [];
$clause = '';
//Check for $_GET variables and build up clause
if(isset($get_content) && $get_content!=''){
//GET VARIABLES FROM URL
$requests = explode("&", $get_content);
//Check for keys and values
foreach ($requests as $y){
$v = explode("=", $y);
//INCLUDE VARIABLES IN ARRAY
$criterias[$v[0]] = $v[1];
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){
//do nothing
}
elseif ($v[0] == 'search') {
//build up search
$clause .= ' AND productcode like :'.$v[0];
}
else {//create clause
$clause .= ' AND '.$v[0].' = :'.$v[0];
}
}
if ($whereclause == '' && $clause !=''){
$whereclause = 'WHERE '.substr($clause, 4);
} else {
$whereclause .= $clause;
}
}
//ENSURE PRODUCTROWID IS SEND
if (isset($criterias['productrowid']) && $criterias['productrowid'] != ''){
//CHECK IF ALLOWED TO CRUD VERSIONS
$sql = "SELECT * FROM products WHERE rowID = ? '.$whereclause.'";
$stmt = $pdo->prepare($sql);
$stmt->execute([$criterias['productrowid']]);
$product_data = $stmt->fetch();
$product_owner = ($product_data['rowID'])? 1 : 0;
//IF PRODUCT IS OWNED THEN CRUD is ALLOWED
if ($product_owner === 1 ){
//Define Query
if(isset($criterias['totals']) && $criterias['totals'] ==''){
//Request for total rows
$sql = 'SELECT count(*) as count FROM products_configurations '.$whereclause.'';
}
elseif (isset($criterias['list']) && $criterias['list'] =='') {
//SQL for Paging
$sql = 'SELECT * FROM products_configurations '.$whereclause.'';
}
else {
//SQL for Paging
$sql = 'SELECT * FROM products_configurations '.$whereclause.'';
}
$stmt = $pdo->prepare($sql);
//Bind to query
if (str_contains($whereclause, ':condition')){
$stmt->bindValue('condition', $condition, PDO::PARAM_STR);
}
if (!empty($criterias)){
foreach ($criterias as $key => $value){
$key_condition = ':'.$key;
if (str_contains($whereclause, $key_condition)){
if ($key == 'search'){
$search_value = '%'.$value.'%';
$stmt->bindValue($key, $search_value, PDO::PARAM_STR);
}
else {
$stmt->bindValue($key, $value, PDO::PARAM_STR);
}
}
}
}
//Add paging details
if(isset($criterias['totals']) && $criterias['totals']==''){
$stmt->execute();
$messages = $stmt->fetch();
$messages = $messages[0];
}
elseif(isset($criterias['list']) && $criterias['list']==''){
//Excute Query
$stmt->execute();
//Get results
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
else {
//$current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1;
//$stmt->bindValue('page', ($current_page - 1) * $page_rows_products, PDO::PARAM_INT);
//$stmt->bindValue('num_products', $page_rows_products, PDO::PARAM_INT);
//Excute Query
$stmt->execute();
//Get results
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
//------------------------------------------
//JSON_ENCODE
//------------------------------------------
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
//Send results
echo $messages;
}
}
?>

View File

@@ -0,0 +1,107 @@
<?php
defined($security_key) or exit;
//------------------------------------------
// Products_configurations
//------------------------------------------
//Connect to DB
$pdo = dbConnect($dbname);
//CONTENT FROM API (POST)
$post_content = json_decode($input,true);
//SoldTo is empty
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
//default whereclause
$whereclause = '';
switch ($permission) {
case '4':
$whereclause = '';
break;
case '3':
$whereclause = '';
break;
default:
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
$whereclause = ' AND accounthierarchy like "'.$condition.'"';
break;
}
//ENSURE PRODUCTROWID IS SEND
if (isset($post_content['productrowid']) && $post_content['productrowid'] != ''){
//CHECK IF ALLOWED TO CRUD VERSIONS
$sql = "SELECT * FROM products WHERE rowID = ? '.$whereclause.'";
$stmt = $pdo->prepare($sql);
$stmt->execute([$post_content['productrowid']]);
$product_data = $stmt->fetch();
$product_owner = ($product_data['rowID'])? 1 : 0;
//IF PRODUCT IS OWNED THEN CRUD is ALLOWED
if ($product_owner === 1 ){
//SET PARAMETERS FOR QUERY
$id = $post_content['rowID'] ?? ''; //check for rowID
$command = ($id == '')? 'insert' : 'update'; //IF rowID = empty then INSERT
if (isset($post_content['delete'])){$command = 'delete';} //change command to delete
$date = date('Y-m-d H:i:s');
//CREATE EMPTY STRINGS
$clause = '';
$clause_insert ='';
$input_insert = '';
if ($command == 'insert'){
$post_content['createdby'] = $username;
}
if ($command == 'update'){
$post_content['updatedby'] = $username;
}
//CREAT NEW ARRAY AND MAP TO CLAUSE
if(isset($post_content) && $post_content!=''){
foreach ($post_content as $key => $var){
if ($key == 'submit' || $key == 'rowID'){
//do nothing
}
else {
$criterias[$key] = $var;
$clause .= ' , '.$key.' = ?';
$clause_insert .= ' , '.$key.'';
$input_insert .= ', ?'; // ? for each insert item
$execute_input[]= $var; // Build array for input
}
}
}
//CLEAN UP INPUT
$clause = substr($clause, 2); //Clean clause - remove first comma
$clause_insert = substr($clause_insert, 2); //Clean clause - remove first comma
$input_insert = substr($input_insert, 1); //Clean clause - remove first comma
//QUERY AND VERIFY ALLOWED
if ($command == 'update' && isAllowed('products_configurations',$profile,$permission,'U') === 1){
$sql = 'UPDATE products_configurations SET '.$clause.' WHERE rowID = ? '.$whereclause.'';
$execute_input[] = $id;
$stmt = $pdo->prepare($sql);
$stmt->execute($execute_input);
}
elseif ($command == 'insert' && isAllowed('products_configurations',$profile,$permission,'C') === 1){
$sql = 'INSERT INTO products_configurations ('.$clause_insert.') VALUES ('.$input_insert.')';
$stmt = $pdo->prepare($sql);
$stmt->execute($execute_input);
}
elseif ($command == 'delete' && isAllowed('products_configurations',$profile,$permission,'D') === 1){
$stmt = $pdo->prepare('DELETE FROM products_configurations WHERE rowID = ? '.$whereclause.'');
$stmt->execute([ $id ]);
//Add deletion to changelog
changelog($dbname,'products_configurations',$id,'Delete','Delete',$username);
} else
{
//do nothing
}
}
}
?>

View File

@@ -2846,6 +2846,7 @@ function getLatestVersion($productcode,$token){
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function getRelativeTime($timestamp) {
if (!empty($timestamp) || $timestamp != ""){
//GET TRANSLATION FILE
if(isset($_SESSION['country_code'])){
$api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php';
@@ -2914,6 +2915,7 @@ function getRelativeTime($timestamp) {
return $years.(($years != 1)?$time_years:$time_year) . " $suffix";
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generate language files ++++++++++++++

View File

@@ -60,8 +60,8 @@ $view = '
<div class="title">
<i class="fa-solid fa-coins"></i>
<div class="txt">
<h2>'.($pricelists_h2 ?? '').' ('.$query_total.')</h2>
<p>'.($pricelists_p ?? '').'</p>
<h2>'.($pricelists_h2 ?? 'Pricelists').' ('.$query_total.')</h2>
<p>'.($pricelists_p ?? 'Manage pricelists').'</p>
</div>
</div>
</div>';
@@ -95,7 +95,7 @@ $view .= '
<thead>
<tr>
<th>'.($pricelists_rowID ?? 'rowID').'</th>
th>'.($pricelists_status ?? 'status').'</th>
<th>'.($pricelists_status ?? 'status').'</th>
<th>'.($pricelists_name ?? 'name').'</th>
<th class="responsive-hidden">'.$general_created.'</th>
<th>'.$general_actions.'</th>

View File

@@ -15,9 +15,10 @@ $delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
// Default input product values
$text_variable = [
$pricelists = [
'rowID' => '',
'variable' => '',
'status' => '',
'name' => '',
'created' => '',
'createdby' => '',
'updated' => '',
@@ -25,6 +26,7 @@ $text_variable = [
'accounthierarchy' => ''
];
if (isset($_GET['rowID'])) {
//CALL TO API
$api_url = '/v2/pricelists/rowID='.$_GET['rowID'];
@@ -40,6 +42,14 @@ if (isset($_GET['rowID'])) {
//Decode Payload
if (!empty($pricelists_items)){$pricelists_items = json_decode($pricelists_items,true);}else{$pricelists_items = null;}
//GET PRODUCTS AND ATTRIBUTES
$api_url = '/v2/products/list=price';
$responses = ioServer($api_url,'');
//Decode Payload
if (!empty($responses)){$products = json_decode($responses,true);}else{$products = null;}
if ($update_allowed === 1){
if (isset($_POST['submit'])) {
@@ -57,7 +67,6 @@ if (isset($_GET['rowID'])) {
}
if (isset($_POST['add'])) {
//GET ALL POST DATA
$payload = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//API call
@@ -66,7 +75,6 @@ if (isset($_GET['rowID'])) {
if ($responses === 'NOK'){
} else {
generateLanguageFile($_POST['language_key'],$_SESSION['userkey']);
header('Location: index.php?page=pricelists_manage&rowID='.$_GET['rowID'].'');
exit;
}
@@ -94,11 +102,6 @@ if (isset($_GET['rowID'])) {
}
}
if ($NOK_error == 0){
//NO errors generatelanguagefile
generateLanguageFile($attr_language,$_SESSION['userkey']);
}
header('Location: index.php?page=pricelists_manage&rowID='.$_GET['rowID'].'');
exit;
}
@@ -132,8 +135,8 @@ if (isset($_GET['rowID'])) {
} else {
//GET ROWID OF CREATED ITEM
$variable_rowID = json_decode($responses,true);
header('Location: index.php?page=pricelists_manage&rowID='.$variable_rowID['rowID'].'');
$pricelists_rowID = json_decode($responses,true);
header('Location: index.php?page=pricelists_manage&rowID='.$pricelists_rowID['rowID'].'');
exit;
}
}
@@ -161,7 +164,7 @@ if (isset($success_msg)){
$view .='
<form action="" method="post">
<div class="content-title responsive-flex-wrap responsive-pad-bot-3">
<h2 class="responsive-width-100">'.($text_variables_h2 ?? '').'</h2>
<h2 class="responsive-width-100">'.($pricelists_h2 ?? '').'</h2>
<a href="index.php?page=pricelists" class="btn alt mar-right-2">'.$button_cancel.'</a>
';
@@ -183,24 +186,45 @@ $view .= '<div class="tabs">
//Define Service and User enabled
$view .= '<div class="content-block tab-content active">
<div class="form responsive-width-100">
<label for="variable">'.($text_variable_name ?? '').'</label>
<input id="variable" type="text" name="variable" placeholder="'.($text_variable_name ?? '').'" value="'.$text_variable['variable'].'" pattern="^\S+$" required">
<input type="hidden" name="rowID" value="'.$text_variable['rowID'].'" readonly>
';
$view .= '</div>
<label for="">'.($pricelists_status ?? 'Status').'</label>
<select name="status">
<option value="0" '.($pricelists['status']==0?' selected':'').'>'.$general_status_0.'</option>
<option value="1" '.($pricelists['status']==1?' selected':'').'>'.$general_status_1.'</option>
</select>
</div>
<div class="form responsive-width-100">
<label for="name">'.($pricelists_name ?? 'Pricelistname').'</label>
<input id="name" type="text" name="name" placeholder="'.($pricelists_name ?? '').'" value="'.$pricelists['name'].'" required">
<input type="hidden" name="rowID" value="'.$pricelists['rowID'].'" readonly>
</div>
<div class="form responsive-width-100">
<label for="">'.($pricelists_currency ?? 'Currency').'</label>
<select name="currency">';
foreach ($supportedCurrencies as $key => $value){
$view .='<option value="'.$key.'" '.(($pricelists['currency'] == $key)?' selected':'').'>'.(${'general_currency_'.$key} ?? $value).'</option>';
}
$view .='</select>
</div>
<div class="form responsive-width-100">
<label for="name">'.($pricelists_start_date ?? 'Start date').'</label>
<input type="date" name="start_date" placeholder="'.($pricelists_start_date ?? '').'"value="'.$pricelists['start_date'].'" required>
</div>
<div class="form responsive-width-100">
<label for="name">'.($pricelists_end_date?? 'End date').'</label>
<input type="date" name="end_date" placeholder="'.($pricelists_end_date ?? '').'"value="'.$pricelists['end_date'].'" required>
</div>
</div>';
$view .= '<div class="content-block tab-content">
<div class="form responsive-width-100">
<label for="">'.$general_created.'</label>
<input id="name" type="text" name="" placeholder="'.$general_created.'" value="'.getRelativeTime($text_variable['created']).'" readonly>
<input id="name" type="text" name="" placeholder="'.$general_created.'" value="'.getRelativeTime($pricelists['created']).'" readonly>
<label for="">'.$general_createdby.'</label>
<input id="name" type="text" name="" placeholder="'.$general_createdby.'" value="'.$text_variable['createdby'].'" readonly>
<input id="name" type="text" name="" placeholder="'.$general_createdby.'" value="'.$pricelists['createdby'].'" readonly>
<label for="productcode">'.$general_updated.'</label>
<input id="name" type="text" name="" placeholder="'.$general_updated.'" value="'.getRelativeTime($text_variable['updated']).'" readonly>
<input id="name" type="text" name="" placeholder="'.$general_updated.'" value="'.getRelativeTime($pricelists['updated']).'" readonly>
<label for="productcode">'.$general_updatedby.'</label>
<input id="name" type="text" name="" placeholder="'.$general_updatedby.'" value="'.$text_variable['updatedby'].'" readonly>
<input id="name" type="text" name="" placeholder="'.$general_updatedby.'" value="'.$pricelists['updatedby'].'" readonly>
</div>
</div>';
$view .= '</form>';
@@ -216,8 +240,11 @@ $view .= '
<table>
<thead>
<tr>
<th>'.($text_variable_translation_languagekey ?? '').'</th>
<th>'.($text_variable_translation_translation ?? '').'</th>
<th>'.($pricelists_item_status ?? 'Status').'</th>
<th>'.($pricelists_item_product_id ?? 'Product ID').'</th>
<th>'.($pricelists_item_price ?? 'Price').'</th>
<th>'.($pricelists_item_rpp ?? 'RPP').'</th>
<th>'.($pricelists_item_price_modifier ?? 'Modifier').'</th>
<th>'.$general_created.'</th>
<th>'.$general_actions.'</th>
</tr>
@@ -229,23 +256,44 @@ $view .= '
$view .= '
<tr>
<td colspan="8" style="text-align:center;">'.($message_no_text_variables ?? '').'</td>
<td colspan="8" style="text-align:center;">'.($message_no_pricelists ?? 'There are no pricelist items').'</td>
</tr>';
}
else {
foreach ($pricelists_items as $pricelists_item){
$view .= '
foreach ($pricelists_items as $pricelist_item){
<tr>
<td><input form="update" type="text" name="item['.$pricelists_item['rowID'].'][name]" placeholder="'.($text_variable_translation_translation ?? '').'" value="'.$pricelists_item['name'].'"></td>
<td>'.getRelativeTime($pricelists_item['created']).'</td>
$view .= '
<tr><td>
<select form="update" name="item['.$pricelist_item['rowID'].'][status]">
<option value="0" '.($pricelist_item['status']==0?' selected':'').'>'.$general_status_0.'</option>
<option value="1" '.($pricelist_item['status']==1?' selected':'').'>'.$general_status_1.'</option>
</select>
</td>
<td>
<select form="update" name="item['.$pricelist_item['rowID'].'][product_id]">';
foreach ($products as $product){
$view .= '<option value="'.$product['product_id'].'" '.($product['product_id']==$pricelist_item['product_id'] ?' selected':'').'>'.(${$product['product_name']} ?? $product['product_name']).'</option>
';}
$view .= ' </select>
</td>
<td><input form="update" type="number" min="0" step="0.01" name="item['.$pricelist_item['rowID'].'][price]" placeholder="'.($pricelists_item_price ?? 'Price').'" value="'.$pricelist_item['price'].'"></td>
<td><input form="update" type="number" min="0" step="0.01" name="item['.$pricelist_item['rowID'].'][rrp]" placeholder="'.($pricelists_item_rrp ?? 'Recommended Price').'" value="'.$pricelist_item['rrp'].'"></td>
<td>
<select form="update" name="item['.$pricelist_item['rowID'].'][price_modifier]">';
foreach ($supportedModifiers as $key => $value){
$view .='<option value="'.$key.'" '.(($pricelist_item['price_modifier'] == $key)?' selected':'').'>'.(${'general_modifier_'.$key} ?? $value).'</option>';
}
$view .=' </select>
</td>
<td>'.getRelativeTime($pricelist_item['created']).'</td>
<td><input form="update" type="submit" name="update" value="&" class="btn"></td>
<input form="update" type="hidden" name="item['.$pricelists_item['rowID'].'][rowID]" value="'.$pricelists_item['rowID'].'" readonly>
<input form="update" type="hidden" name="item['.$pricelists_item['rowID'].'][pricelist_ID]" value="'.$pricelists['rowID'].'" readonly>
<input form="update" type="hidden" name="item['.$pricelist_item['rowID'].'][rowID]" value="'.$pricelist_item['rowID'].'" readonly>
<input form="update" type="hidden" name="item['.$pricelist_item['rowID'].'][pricelist_ID]" value="'.$pricelist_item['pricelist_ID'].'" readonly>
</tr>
</form>';
}
}
$view .= '
</tbody>
</table>
@@ -259,15 +307,40 @@ $view .= '
const newRow = document.createElement(\'tr\');
newRow.innerHTML = `
<td><input form="new" type="text" name="name" placeholder="'.($text_variable_translation_translation ?? '').'" value=""></td>
<tr><td>
<select form="new" name="status">
<option value="0">'.$general_status_0.'</option>
<option value="1" selected>'.$general_status_1.'</option>
</select>
</td>
<td>
<select form="new" name="product_id">';
foreach ($products as $product){
$view .= '<option value="'.$product['product_id'].'">'.(${$product['product_name']} ?? $product['product_name']).'</option>
';}
$view .= ' </select>
</td>
<td><input form="new" type="number" min="0" step="0.01" name="price" placeholder="'.($pricelists_item_price ?? 'Price').'" value=""></td>
<td><input form="new" type="number" min="0" step="0.01" name="rrp" placeholder="'.($pricelists_item_rrp ?? 'Recommended Price').'" value=""></td>
<td>
<select form="new" name="price_modifier">';
foreach ($supportedModifiers as $key => $value){
$view .='<option value="'.$key.'" '.(($key == 1)?' selected':'').'>'.(${'general_modifier_'.$key} ?? $value).'</option>';
}
$view .=' </select>
</td>
<td></td>
<td><input form="new" type="submit" name="add" value="+" class="btn"></td>
<input form="new" type="hidden" name="rowID" value="" readonly>
<input form="new" type="hidden" name="pricelist_ID" value="'.$pricelists_item['rowID'].'" readonly>
<input form="new" type="hidden" name="pricelist_ID" value="'.$pricelists['rowID'].'" readonly>
</tr>
`;
tbody.appendChild(newRow);
}
</script>
</script>';
$view .= '
</div>
</div>
';

View File

@@ -54,6 +54,11 @@ $product_software = ioServer($api_url,'');
//Decode Payload
if (!empty($product_software)){$product_software = decode_payload($product_software);}else{$product_software = null;}
//CALL TO API FOR Product_configuration
$api_url = '/v2/products_configurations/productrowid='.$_GET['rowID'];
$products_configurations = ioServer($api_url,'');
//Decode Payload
if (!empty($products_configurations)){$products_configurations = json_decode($products_configurations,true);}else{$products_configurations = null;}
//------------------------------
//Variables
@@ -157,7 +162,41 @@ $view .= '<div class="content-block">
</div>
';
if ($responses->configurable == 1){
$view .= '<div class="content-block">
<div class="block-header">
<i class="fa-solid fa-bars fa-sm"></i>'.($product_configuration ?? 'Product configuration').'
<a href="index.php?page=products_configurations&productrowid='.$_GET['rowID'].'" class="btn2"> + </a>
</div>';
if (!empty($products_configurations)){
$view .= '
<div class="table">
<table class="sortable">
<thead>
<tr>
<th>'.($product_configuration_version ?? 'Config-version').'</th>
<th>'.$general_actions.'</th>
</tr>
</thead>
<tbody>';
foreach ($products_configurations as $product_config){
$view .= '<tr>
<td></td>
<td></td>
</tr>';
}
$view .= '
</tbody>
</table>
</div>
';
}
$view .= '
</div>
';
}
$view .= '<div class="content-block">
<div class="block-header">
@@ -173,6 +212,7 @@ $view .= '<div class="content-block">
<th>'.$product_version_number.'</th>
<th>'.$product_status.'</th>
<th>'.$product_version_version.'</th>
<th>'.($product_version_config ?? 'Config').'</th>
<th>'.$general_actions.'</th>
</tr>
</thead>
@@ -183,6 +223,7 @@ $view .= '<div class="content-block">
<td>'.$version->rowID.'</td>
<td>'.(($version->status == 1)? '<span class="status enabled">'.$prod_status_1:'<span class="status">'.$prod_status_0).'</td>
<td>'.$version->version.'</td>
<td>'.(!empty($version->config) ? ($general_yes ?? 'Y') : ($general_no ?? 'N')).'</td>
<td><a href="index.php?page=products_versions&productrowid='.$_GET['rowID'].'&rowID='.$version->rowID.'" class="btn_link">'.$general_view.'</a></td>
</tr>';
}
@@ -249,6 +290,11 @@ $view .= '<div class="content-block">
</div>
<div class="table order-table">
<table>
</tr>
<tr>
<td style="width:25%;">'.($product_configurable ?? 'Configurable').'</td>
<td>'.(($responses->configurable == 1)? $enabled : $disabled).'</td>
</tr>
<tr>
<td style="width:25%;">'.$product_serialized.'</td>
<td>'.(($responses->sn == 1)? $enabled : $disabled).'</td>

View File

@@ -38,7 +38,8 @@ $product = [
'build' => 1,
'partnerhierarchy' => '',
'sn' =>'',
'healthindex' =>''
'healthindex' =>'',
'configurable' =>''
];
if (isset($_GET['id'])) {
@@ -56,8 +57,10 @@ if (isset($_GET['id'])) {
uploadProduct($_POST['productcode']);
}
if (isset($_POST['submit'])) {
//GET ALL POST DATA
$data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
var_dump($data);
//Secure data
$payload = generate_payload($data);
//API call
@@ -171,6 +174,11 @@ $view .= '<div class="content-block tab-content active">
$view .= '<div class="content-block tab-content">
<div class="form responsive-width-100">
<label for="serialized">'.($product_configurable ?? 'Configurable').'</label>
<select id="status" name="configurable">
<option value="1" '.($product['configurable']==1?' selected':'').'>'.$enabled.'</option>
<option value="0" '.($product['configurable']==0?' selected':'').'>'.$disabled.'</option>
</select>
<label for="serialized">'.$product_serialized.'</label>
<select id="status" name="sn">
<option value="1" '.($product['sn']==1?' selected':'').'>'.$enabled.'</option>

197
products_configurations.php Normal file
View File

@@ -0,0 +1,197 @@
<?php
defined(page_security_key) or exit;
$page = 'products_configurations';
//Check if allowed
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
header('location: index.php');
exit;
}
//PAGE Security
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
// Default input product values
$products_configurations = [
'rowID' => '',
'productrowid' => '',
'status' => '',
'version' => '',
'config' => '',
'created' => '',
'createdby' => $_SESSION['username'],
'measurement' => '',
];
//productrowid is required by api
$productrowid = $_GET['productrowid'] ?? '';
if (isset($_GET['rowID'])) {
// ID param exists, edit an existing product
//CALL TO API
$api_url = '/v2/products_configurations/rowID='.$_GET['rowID'].'&productrowid='.$productrowid;
$responses = ioServer($api_url,'');
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;}
$products_configurations = json_decode(json_encode($responses[0]), true);
if ($update_allowed === 1){
if (isset($_POST['submit'])) {
//GET ALL POST DATA
$payload = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//API call
$responses = ioServer('/v2/products_configurations', $payload);
if ($responses === 'NOK'){
} else {
header('Location: index.php?page=product&rowID='.$productrowid.'&success_msg=2');
exit;
}
}
}
if ($delete_allowed === 1){
if (isset($_POST['delete'])) {
//GET ALL POST DATA
$payload = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//API call
$responses = ioServer('/v2/products_configurations', $payload);
if ($responses === 'NOK'){
} else {
// Redirect and delete product
header('Location: index.php?page=product&rowID='.$productrowid.'&success_msg=3');
exit;
}
}
}
} else {
// Create a new product
if (isset($_POST['submit']) && $create_allowed === 1) {
//GET ALL POST DATA
$data = json_encode($_POST , JSON_UNESCAPED_UNICODE);
//Secure data
$payload = generate_payload($data);
//API call
$responses = ioServer('/v2/products_configurations', $payload);
if ($responses === 'NOK'){
}
else {
header('Location: index.php?page=product&rowID='.$productrowid.'&success_msg=1');
exit;
}
}
}
template_header('Products configurations', 'products configurations', 'manage');
$view ='
<form action="" method="post" enctype="multipart/form-data">
<div class="content-title responsive-flex-wrap responsive-pad-bot-3">
<h2 class="responsive-width-100">'.$product_version_version.'</h2>
<a href="index.php?page=product&rowID='.$productrowid.'" class="btn alt mar-right-2">'.$button_cancel.'</a>
';
if ($delete_allowed === 1){
$view .= '<input type="submit" name="delete" value="Delete" class="btn red mar-right-2" onclick="return confirm(\'Are you sure you want to delete this product?\')">';
}
if ($update_allowed === 1){
$view .= '<input type="submit" name="submit" value="Save" class="btn">';
}
$view .= '</div>';
$view .= '<div class="tabs">
<a href="#" class="active">'.$tab1.'</a>
<a href="#">'.$tab3.'</a>
</div>
';
$view .= '<div class="content-block tab-content active">
<div class="form responsive-width-100">
<label for="status">'.$product_status.'</label>
<select id="status" name="status">
<option value="1" '.($products_configurations['status']==1?' selected':'').'>'.$prod_status_1 .'</option>
<option value="0" '.($products_configurations['status']==0?' selected':'').'>'.$prod_status_0 .'</option>
</select>
<label for=""><i class="required">*</i>'.$product_version_version.'</label>
<input id="name" type="text" name="version" placeholder="'.$product_version_version.'" value="'.$products_configurations['version'].'" required>
';
//VIEW FOR PRODUCT CONFIGURATION
if (isset($_GET['rowID']) && $_GET['rowID'] !=''){
$view .= '
<label for="">'.($product_version_config ?? 'Config').'</label>
<div class="table">
<textarea id="config" name="config" placeholder="'.($product_version_config ?? 'Config').'">'.$products_configurations['config'].'</textarea>
</table>
</div>';
}
if (isset($_GET['rowID']) && $_GET['rowID'] !='' && !empty($products_configurations['measurement'])){
$measurements = json_decode($products_configurations['measurement'],true);
$view .= '
<label for="">'.$product_version_measurement.'</label>
<div class="table">
<table>
<thead>
<tr>
<td>Test</td>
<td>N</td>
<td>Average</td>
<td>Median</td>
<td>STdev</td>
</tr>
</thead>
<tbody>
';
foreach ($measurements as $name => $measurement){
$view .='
<tr>
<td>'.$name.'</td>
<td>'.$measurement['n'].'</td>
<td>'.$measurement['average'].'</td>
<td>'.$measurement['median'].'</td>
<td>'.$measurement['stdev'].'</td>
</tr>
';
}
$view .= '</tbody>
</table>
</div>';
}
$view .= '
<input type="hidden" name="rowID" value="'.$products_configurations['rowID'].'">
<input type="hidden" name="productrowid" value="'.$productrowid.'">
</div>
</div>';
$view .= '<div class="content-block tab-content">
<div class="form responsive-width-100">
<label for="productcode">'.$general_created.'</label>
<input id="name" type="text" name="" placeholder="'.$general_created.'" value="'.$products_configurations['created'].'" readonly>
<label for="productcode">'.$general_createdby.'</label>
<input id="name" type="text" name="" placeholder="'.$general_createdby.'" value="'.$products_configurations['createdby'].'" readonly>
</div>
</div>';
$view .= '</form>';
//Output
echo $view;
template_footer()
?>

View File

@@ -18,7 +18,7 @@ $products_versions = [
'productrowid' => '',
'status' => '',
'version' => '',
'software' => '',
'config' => '',
'created' => '',
'createdby' => $_SESSION['username'],
'measurement' => '',
@@ -30,11 +30,11 @@ $productrowid = $_GET['productrowid'] ?? '';
if (isset($_GET['rowID'])) {
// ID param exists, edit an existing product
//CALL TO API
$api_url = '/v1/products_versions/rowID='.$_GET['rowID'].'&productrowid='.$productrowid;
$api_url = '/v2/products_versions/rowID='.$_GET['rowID'].'&productrowid='.$productrowid;
$responses = ioServer($api_url,'');
//Decode Payload
if (!empty($responses)){$responses = decode_payload($responses);}else{$responses = null;}
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;}
$products_versions = json_decode(json_encode($responses[0]), true);
@@ -42,40 +42,10 @@ if (isset($_GET['rowID'])) {
if ($update_allowed === 1){
if (isset($_POST['submit'])) {
//CHECK FOR FIRMWARE FILE
$firmware_file = $_FILES["fileToUpload"]["name"] ?? '';
if($firmware_file !='' || !empty($firmware_file)){
$extension = strtolower(pathinfo($firmware_file, PATHINFO_EXTENSION));
$target_dir = dirname(__FILE__)."/firmware/";
if ($extension == 'hex'){
//READ FILE
$contents = file_get_contents($_FILES["fileToUpload"]["tmp_name"]);
//firmwarename
$firmware_name = pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_FILENAME);
//Filename
$input_file = $target_dir . $firmware_name.'.HEX';
//store firmware file
file_put_contents($input_file, $contents);
} else {
$target_file = $target_dir . $firmware_file;
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
$firmware_name = $firmware_file;
}
//Use firmwarefile name as software version
$_POST['software'] = $firmware_name;
}
//GET ALL POST DATA
$data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//Secure data
$payload = generate_payload($data);
$payload = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//API call
$responses = ioServer('/v1/products_versions', $payload);
$responses = ioServer('/v2/products_versions', $payload);
if ($responses === 'NOK'){
} else {
@@ -89,11 +59,9 @@ if (isset($_GET['rowID'])) {
if ($delete_allowed === 1){
if (isset($_POST['delete'])) {
//GET ALL POST DATA
$data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//Secure data
$payload = generate_payload($data);
$payload = json_encode($_POST, JSON_UNESCAPED_UNICODE);
//API call
$responses = ioServer('/v1/products_versions', $payload);
$responses = ioServer('/v2/products_versions', $payload);
if ($responses === 'NOK'){
} else {
@@ -108,42 +76,12 @@ if (isset($_GET['rowID'])) {
// Create a new product
if (isset($_POST['submit']) && $create_allowed === 1) {
//CHECK FOR FIRMWARE FILE
$firmware_file = $_FILES["fileToUpload"]["name"] ?? '';
if($firmware_file !='' || !empty($firmware_file)){
$extension = strtolower(pathinfo($firmware_file, PATHINFO_EXTENSION));
$target_dir = dirname(__FILE__)."/firmware/";
if ($extension == 'hex'){
//READ FILE
$contents = file_get_contents($_FILES["fileToUpload"]["tmp_name"]);
//firmwarename
$firmware_name = pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_FILENAME);
//Filename
$input_file = $target_dir . $firmware_name.'.HEX';
//store firmware file
file_put_contents($input_file, $contents);
$firmware_name = $firmware_name.'.HEX';
} else {
$target_file = $target_dir . $firmware_file;
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
$firmware_name = $firmware_file;
}
//Use firmwarefile name as software version
$_POST['software'] = $firmware_name;
}
//GET ALL POST DATA
$data = json_encode($_POST , JSON_UNESCAPED_UNICODE);
//Secure data
$payload = generate_payload($data);
//API call
$responses = ioServer('/v1/products_versions', $payload);
$responses = ioServer('/v2/products_versions', $payload);
if ($responses === 'NOK'){
}
@@ -189,6 +127,17 @@ $view .= '<div class="content-block tab-content active">
<input id="name" type="text" name="version" placeholder="'.$product_version_version.'" value="'.$products_versions['version'].'" required>
';
//VIEW FOR PRODUCT CONFIGURATION
if (isset($_GET['rowID']) && $_GET['rowID'] !=''){
$view .= '
<label for="">'.($product_version_config ?? 'Config').'</label>
<div class="table">
<textarea id="config" name="config" placeholder="'.($product_version_config ?? 'Config').'">'.$products_versions['config'].'</textarea>
</table>
</div>';
}
if (isset($_GET['rowID']) && $_GET['rowID'] !='' && !empty($products_versions['measurement'])){
$measurements = json_decode($products_versions['measurement'],true);

65
security.php Normal file
View File

@@ -0,0 +1,65 @@
<?php
// test-headers.php
function testSecurityHeaders($url) {
// Initialize cURL
$ch = curl_init($url);
// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
// Execute request
$response = curl_exec($ch);
// Get headers
$headers = [];
$headerLines = explode("\n", $response);
foreach ($headerLines as $line) {
if (strpos($line, ':') !== false) {
list($key, $value) = explode(':', $line, 2);
$headers[trim($key)] = trim($value);
}
}
// Define expected security headers
$expectedHeaders = [
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'DENY',
'X-XSS-Protection' => '1; mode=block',
'Content-Security-Policy' => 'default-src \'none\'',
'Access-Control-Allow-Origin' => null, // Will check if exists
'Access-Control-Allow-Methods' => null, // Will check if exists
'Access-Control-Allow-Headers' => null, // Will check if exists
'Strict-Transport-Security' => null // Will check if exists
];
// Check each expected header
echo "Security Headers Test Results:\n";
echo "==============================\n\n";
foreach ($expectedHeaders as $header => $expectedValue) {
if (isset($headers[$header])) {
if ($expectedValue === null) {
echo "{$header} is present: {$headers[$header]}\n";
} elseif ($headers[$header] === $expectedValue) {
echo "{$header} has correct value: {$headers[$header]}\n";
} else {
echo "{$header} has incorrect value. Expected: {$expectedValue}, Got: {$headers[$header]}\n";
}
} else {
echo "{$header} is missing\n";
}
}
// Check for HTTPS
$isHttps = strpos($url, 'https://') === 0;
echo $isHttps ?
"\n✅ HTTPS is enabled\n" :
"\n❌ HTTPS is not enabled - Security headers may not be effective!\n";
curl_close($ch);
}
// Usage
testSecurityHeaders('https://dev.veliti.nl/api.php');

View File

@@ -246,6 +246,13 @@ $page_rows_pricelists = 50;//pricelists
//------------------------------------------
$supportedLanguages = ['US', 'NL', 'DE', 'ES','PT'];
//------------------------------------------
// Pricing
//------------------------------------------
$supportedCurrencies = ["0" =>"euro", "1"=>"dollar"];
$supportedModifiers = ["0" =>"subtract", "1"=>"add"];
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// All individual views and APIs - Profile ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++

View File

@@ -6,7 +6,7 @@ define('superuser_profile','dashboard,profile,assets,equipments,equipment,equipm
/*Admin*/
define('admin_profile','dashboard,profile,buildtool,sales,accounts,account,contracts,contract,contract_manage,cartests,cartest,cartest_manage,assets,equipments,equipment,equipment_healthindex,equipment_data,equipment_manage,equipment_manage_edit,equipments_mass_update,histories,history,history_manage,firmwaretool,rmas,rma,rma_manage,rma_history,rma_history_manage,buildtool,products,products_versions,products_software,product,product_manage,servicereports,servicereport,admin,partners,partner,users,user,user_manage,communications,communication,communication_send,marketing,reporting,report_build,report_contracts_billing,report_healthindex,changelog,application');
/*AdminPlus*/
define('adminplus_profile','dashboard,profile,buildtool,sales,accounts,account,contracts,contract,contract_manage,billing,cartests,cartest,cartest_manage,assets,equipments,equipment,equipment_healthindex,equipment_data,equipment_manage,equipment_manage_edit,equipments_mass_update,histories,history,history_manage,firmwaretool,rmas,rma,rma_manage,rma_history,rma_history_manage,buildtool,products,products_versions,products_software,products_attributes,products_attributes_items,products_attributes_manage,product,product_manage,servicereports,servicereport,admin,partners,partner,users,user,user_manage,communications,communication,communication_send,marketing,reporting,report_build,report_contracts_billing,report_healthindex,report_usage,config,settings,logfile,changelog,language,translations,translations_details,translation_manage,media,media_manage,application,maintenance,profiles,vin');
define('adminplus_profile','dashboard,profile,buildtool,sales,accounts,account,contracts,contract,contract_manage,billing,cartests,cartest,cartest_manage,assets,equipments,equipment,equipment_healthindex,equipment_data,equipment_manage,equipment_manage_edit,equipments_mass_update,histories,history,history_manage,firmwaretool,rmas,rma,rma_manage,rma_history,rma_history_manage,buildtool,products,products_versions,products_software,products_attributes,products_attributes_items,products_attributes_manage,products_configurations,product,product_manage,pricelists,pricelists_items,pricelists_manage,servicereports,servicereport,admin,partners,partner,users,user,user_manage,communications,communication,communication_send,marketing,reporting,report_build,report_contracts_billing,report_healthindex,report_usage,config,settings,logfile,changelog,language,translations,translations_details,translation_manage,media,media_manage,application,maintenance,profiles,vin');
/*Build*/
define('build','dashboard,profile,buildtool,firmwaretool,buildtool,products_software,application');
/*Distribution*/

View File

@@ -41,11 +41,12 @@ $all_views = [
"products_attributes",
"products_attributes_items",
"products_attributes_manage",
"products_configurations",
"product",
"product_manage",
"pricelists",
"pricelists_items",
"pricelists_manage",
"product_manage",
"servicereports",
"servicereport",
"admin",