';
}
}
//CHECK IF OUTPUT IS MORE THAN X (config setting)
if (count($messages) == $page_rows_equipment_servicereporst && $page == 'equipment'){
$view_data .= '
';
if (str_contains($history->description, "service_mandatory_question")) {
//GET NOTES from JSON
$notes ='';
foreach ($json_array->final as $final){
if ($final->id == "service_notes"){
$notes = $final->value;
}
}
//GENERATE NOTES SECTION
$servicereport .='
'.$group_header_7.'
';
if ($notes != '') {
$servicereport .= '
'.$notes.'
';
}
else {
$servicereport .= '
'.$service_report_no_comments.'
';
}
$servicereport .='
';
}
$servicereport .= '
';
//+++++++++++++++++++++++++++++++++++++++++++++++
// Maintenance Test
//++++++++++++++++++++++++++++++++++++++++++++++
if (isset($json_array->maintenance_test)) {
if (!empty($maintenance_test)) {
$servicereport .='
';
return $view;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// overview of service events per servicekit ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function usageBilling($messages){
// Create an array to store sums by year, quarter, and month
$totals = [];
// Loop through the data and aggregate the counts by year, quarter, and month
foreach ($messages as $entry) {
$year = $entry['year'];
$quarter = $entry['quarter'];
//$dateObj = DateTime::createFromFormat('!m', $entry['month']);
//$month = $dateObj->format('F');
$month = $entry['month'];
$count = $entry['count'];
// Initialize arrays if not already set for year, quarter, and month
if (!isset($totals[$year])) {
$totals[$year] = ['total' => 0, 'quarters' => []];
}
if (!isset($totals[$year]['quarters'][$quarter])) {
$totals[$year]['quarters'][$quarter] = ['total' => 0, 'months' => []];
}
if (!isset($totals[$year]['quarters'][$quarter]['months'][$month])) {
$totals[$year]['quarters'][$quarter]['months'][$month] = 0;
}
// Add count to the corresponding year, quarter, and month
$totals[$year]['total'] += $count;
$totals[$year]['quarters'][$quarter]['total'] += $count;
$totals[$year]['quarters'][$quarter]['months'][$month] += $count;
}
return $totals;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// close contract when expired +++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function closeContract(){
include dirname(__FILE__,2).'/settings/settings_redirector.php';
$pdo = dbConnect($dbname);
//SELECT ALL ACTIVE CONTRACTS
$sql = 'SELECT * FROM contracts WHERE status = 1';
$stmt = $pdo->prepare($sql);
$stmt->execute();
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($messages as $message){
//Calculate contract end date
$end_date = date('Y-m-d', strtotime('+'.$message['duration'].' months', strtotime($message['start_date'])));
//Validate if contract end date is in the past change contact status to closed and set users to not active
if (date("Y-m-d") > $end_date){
//Contract expired -> change status to closed (2)
$sql = 'UPDATE contracts SET status = ?, updatedby = ? WHERE rowID = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([2,"system",$message['rowID']]);
//CHECK FOR ASSIGNED USER END SET SERVICE TO INACTIVE
foreach (json_decode($message['assigned_users']) as $user_assigned){
//check user exist
$sql = 'SELECT * FROM users WHERE username = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$user_assigned]);
$user_assigned = $stmt->fetch();
if (!empty($user_assigned)){
$id_exist_user = $user_assigned['id'];
$sql = 'UPDATE users SET service = ? WHERE id = ? ';
$stmt = $pdo->prepare($sql);
//Remove serviceflag from user when status is Closed
$stmt->execute(['',$id_exist_user]);
}
}
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// store measurement data into product_version ++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function storeMeasurementProduct($total_results, $token){
include dirname(__FILE__,2).'/settings/settings_redirector.php';
$pdo = dbConnect($dbname);
//Check if product version exists (else create) => store related measurement
foreach ($total_results as $products => $product){
//Product level
foreach ($product as $versions => $version){
//Version level
//Check version exist
$sql = 'SELECT p.*, pv.rowID as versionID, pv.productrowid as productID FROM products p JOIN products_versions pv ON p.rowID = pv.productrowid WHERE p.healthindex = 1 and p.productcode = ? and version = ?;';
$stmt = $pdo->prepare($sql);
$versions = ($versions != 'blank')? $versions : '';
$stmt->execute([$products,$versions]);
$output = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Prep data for api call
$api_url = '/v2/products_versions/';
$measurement = json_encode($version,JSON_UNESCAPED_UNICODE);
if (!empty($output)){
//Update version with latest measurement
$data = json_encode(array("rowID" => $output[0]['versionID'], "productrowid" => $output[0]['productID'], "status" => 1, "version" => $versions, "measurement" => $measurement), JSON_UNESCAPED_UNICODE);
ioApi($api_url,$data,$token);
}
else {
//Insert new version
//GET PRODUCT ID
$sql = 'SELECT * FROM products WHERE productcode = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$products]);
$output = $stmt->fetchAll(PDO::FETCH_ASSOC);
//CALL API
$data = json_encode(array("productrowid" => $output[0]['rowID'], "status" => 1, "version" => $versions , "measurement" => $measurement), JSON_UNESCAPED_UNICODE);
ioApi($api_url,$data,$token);
}
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// store measurement data into equipment data ++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function storeMeasurementEquipment($serialnumber){
include dirname(__FILE__,2).'/settings/settings_redirector.php';
//Connect to DB
$pdo = dbConnect($dbname);
//CHECK FOR SERIALNUMBER PROVIDED
$clause = (!empty($serialnumber) || $serialnumber !='')? 'e.serialnumber = "'.$serialnumber.'" AND': '';
//GET DATA
$sql = 'SELECT h.rowID, h.description,h.equipmentid,p.productcode,e.hw_version FROM equipment_history h JOIN equipment e ON h.equipmentid = e.rowID JOIN products p ON e.productrowid = p.rowID where '.$clause.' type="Maintenance_Test" and description like "%doubletestvalues%"';
$stmt = $pdo->prepare($sql);
$stmt->execute();
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
$tests[] ='';
foreach ($messages as $message){
$dataset = json_decode($message['description'],true);
$dataset = $dataset["doubletestvalues"];
foreach ($dataset as $measure){
//Filter out correct measurements
if ($measure['pass'] === true){
$measurementid = $message['productcode'].'||'.$message['hw_version'].'||'.$message['equipmentid'].'||'.$message['rowID'];
$tests[$measurementid] [$measure['name']]= $measure['measure'];
}
}
}
//COMPARISON -- CHECK DEVIATIONS FROM STANDARD
//LOOP over all test results
foreach ($tests as $test => $test_values){
//GET the productcode and version from Test result
if (str_contains($test,'||')){
$identification = explode('||',$test);
//GET RELATED PRODUCT DATA
$sql = 'SELECT pv.measurement FROM products_versions pv JOIN products p ON pv.productrowid = p.rowID WHERE p.productcode = ? AND pv.version = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$identification[0],$identification[1]]);
$product_measurements = $stmt->fetchAll(PDO::FETCH_ASSOC);
$product_measurements = $product_measurements[0]['measurement']?? '';
if (!empty($product_measurements)){
//Only run when there is a product version found
$product_measurements = json_decode($product_measurements,true);
$equipment_watchlist[] = '';
//Filter out non array or non objects
if (is_object($test_values) || is_array($test_values)){
//get individual test_mesurements
foreach($test_values as $test_measurement => $measured_value){
//Loop over the related product measurements
foreach($product_measurements as $product_measurement => $product_measured_values){
//Compare measured test with product measured test
if ($test_measurement == $product_measurement){
//Get the measured value from test
if (($measured_value <= $product_measured_values['stdev-3']) && ($measured_value >= $product_measured_values['stdev+3'])){
$equipment_watchlist[$test][] = array(
"measurement" => $test_measurement,
"value" => $measured_value,
"deviation" => 3
);
}
elseif ((($measured_value <= $product_measured_values['stdev-2']) && ($measured_value >= $product_measured_values['stdev-3'])) || (($measured_value >= $product_measured_values['stdev+2']) && ($measured_value <= $product_measured_values['stdev+3']))){
$equipment_watchlist[$test][] = array(
"measurement" => $test_measurement,
"value" => $measured_value,
"deviation" => 2
);
}
elseif ((($measured_value <= $product_measured_values['stdev-1']) && ($measured_value >= $product_measured_values['stdev-2'])) || (($measured_value >= $product_measured_values['stdev+1']) && ($measured_value <= $product_measured_values['stdev+2']))){
$equipment_watchlist[$test][] = array(
"measurement" => $test_measurement,
"value" => $measured_value,
"deviation" => 1
);
}
}
}
}
}
}
}
}
//STORE RESULTS IN EQUIPMENT DATA
foreach ($equipment_watchlist as $equipment => $data){
//GET the equipmentid and historyid from watchlist
if (str_contains($equipment,'||')){
$identification = explode('||',$equipment);
//Calculate healthindex
$healthindex = 100;
foreach ($data as $data_measure){
switch ($data_measure['deviation']) {
case 1:
$healthindex = $healthindex - $data_measure['deviation'];
break;
case 2:
$healthindex = $healthindex - ($data_measure['deviation']*2);
break;
case 3:
$healthindex = $healthindex - ($data_measure['deviation']*3);
break;
}
}
//json_encode array
$data = json_encode($data,JSON_UNESCAPED_UNICODE);
//Check if record exists
$sql = 'SELECT * FROM equipment_data WHERE equipmentid = ? and historyid =?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$identification[2],$identification[3]]);
$equipment_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($equipment_data)){
//EXIST UPDATE
$sql = 'UPDATE equipment_data SET measurement = ?, healthindex = ? WHERE equipmentid = ? and historyid = ?';
}
else {
//EXIST INSERT
$sql = 'INSERT INTO equipment_data (measurement, healthindex, equipmentid, historyid) VALUES (?,?,?,?)';
}
//EXECUTE QUERY
$stmt = $pdo->prepare($sql);
$stmt->execute([$data, $healthindex, $identification[2],$identification[3]]);
//$equipment_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// calculatehealthindex of asset ++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function assetHealthIndex($prof,$pem,$healthdata,$type){
$healthindex = 100;
//Allowed check
if (isAllowed('equipment_data',$prof,$pem,'R') === 1 && !empty($healthdata)){
//GET last data based on type returned
//Type
// 0 = $healthdata per equipmentid
// 1 = $healthdata per rowID of equipment_data
switch ($type) {
case 0:
$last_data_measurement = end($healthdata);
break;
default:
$last_data_measurement = $healthdata;
break;
}
//Ensure $last_data_measurement is an array
$last_data_measurement = (is_object($last_data_measurement))? (array) $last_data_measurement : $last_data_measurement;
foreach (json_decode($last_data_measurement['measurement'],true) as $data_measure){
switch ($data_measure['deviation']) {
case 1:
$healthindex = $healthindex - $data_measure['deviation'];
break;
case 2:
$healthindex = $healthindex - ($data_measure['deviation']*2);
break;
case 3:
$healthindex = $healthindex - ($data_measure['deviation']*3);
break;
}
}
}
//Not allowed or no data return 100% health
return $healthindex;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Block contracts ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function blockContracts($token){
include dirname(__FILE__,2).'/settings/settings_redirector.php';
//CALL TO API
$api_url = '/v2/contracts/status=1&type=0';
$responses = ioAPIv2($api_url,'',$token);
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;}
foreach ($responses as $response){
//GET BILLING DATA
$billing_plan = $response['billing_plan'];
$billing_max = $response['service_count'];
//DECODE ARRAYs
$servicetools = json_decode($response['servicetool'],true) ?? '';
$assigned_users = json_decode($response['assigned_users'],true) ?? '';
$ignore_lists = json_decode($response['ignore_list'],true) ?? '';
//get all assigned serialnumbers
$url_input = '';
foreach($servicetools as $service_tool){
$url_input .= $service_tool.',';
}
//get ignore list
$ignored_serialnumbers = '';
if (!empty($ignore_lists)){
foreach($ignore_lists as $list){
$ignored_serialnumbers .= $list.',';
}
$ignored_serialnumbers = '&ignore='.substr($ignored_serialnumbers,0,-1);
}
//GET END DATA
$contract_end_date = date('Y-m-d', strtotime('+'.$response['duration'].' months', strtotime($response['start_date'])));
//Return report_usage_servicereports
$api_url = '/v2/application/type=ServiceReport&serialnumber='.substr($url_input,0,-1).$ignored_serialnumbers.'&between='.$response['start_date'].'||'.$contract_end_date.'/contract_usage_servicereports';
$contract_usage_servicereports = ioAPIv2($api_url,'',$token);
//Decode Payload
if (!empty($contract_usage_servicereports)){$contract_usage_servicereports = json_decode($contract_usage_servicereports,true);}else{$contract_usage_servicereports = null;}
//GET USAGE BILLING INFORMATION
$usage_billing = usageBilling($contract_usage_servicereports);
$billing_cylce_usage = (($billing_plan == 1 && isset($usage_billing[$curYear]['quarters'][$curQuarter]['months'][$curMonth])) ? $usage_billing[$curYear]['quarters'][$curQuarter]['months'][$curMonth] : (($billing_plan == 2 && isset($usage_billing[$curYear]['quarters'][$curQuarter])) ? $usage_billing[$curYear]['quarters'][$curQuarter]: (($billing_plan == 3 && isset($usage_billing[$curYear])) ? $usage_billing[$curYear]: 0 )));
//CHECK FOR OVERRUN
if ($billing_cylce_usage >= $billing_max){
//overrun - set contract status to 3 - block and Inactivate service for all assigned users
$data = json_encode(array("rowID" => $response['rowID'], "status" => "3", "assigned_users" => $assigned_users), JSON_UNESCAPED_UNICODE);
//API call
ioAPIv2('/v2/contracts', $data,$token);
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// check date is in range ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function dateInRange($start_date, $end_date, $date_check)
{
// Convert to timestamp
$start_ts = strtotime($start_date);
$end_ts = strtotime($end_date);
$check_ts = strtotime($date_check);
// Check that user date is between start & end
return (($check_ts >= $start_ts) && ($check_ts <= $end_ts));
}
function getLatestVersion($productcode,$token){
//CALL TO API TO GET ALL ACTIVE CONTRACTS
$api_url = '/v2/products_software/productcode='.$productcode;
$responses = ioAPIv2($api_url,'',$token);
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses,true);
}
else{
$responses = $output = array(
"productcode" => "",
"version"=> "",
"mandatory"=> "",
"latest"=> "",
"software"=> "",
"source" => "",
"source_type" => ""
);
;}
//DEFAULT OUTPUT
return $responses;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Timestamp converter ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
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';
if (file_exists($api_file_language)){
include $api_file_language; //Include the code
}
else {
include dirname(__FILE__,2).'/settings/translations/translations_US.php';
}
}
else {
include dirname(__FILE__,2).'/settings/translations/translations_US.php';
}
// Ensure the timestamp is a valid integer
$timestamp = is_numeric($timestamp) ? $timestamp : strtotime($timestamp);
// Get current timestamp and calculate difference
$now = time();
$diff = $now - $timestamp;
// Define time periods
$minute = 60;
$hour = $minute * 60;
$day = $hour * 24;
$week = $day * 7;
$month = $day * 30;
$year = $day * 365;
// Handle future timestamps
if ($diff < 0) {
$diff = abs($diff);
$suffix = $time_from_now;
} else {
$suffix = $time_ago;
}
// Determine the appropriate time description
if ($diff < $minute) {
return $time_just_now;
} elseif ($diff < $hour) {
$minutes = floor($diff / $minute);
return $minutes.(($minutes != 1) ? $time_minutes : $time_minute) . " $suffix";
} elseif ($diff < $day) {
$hours = floor($diff / $hour);
return $hours.(($hours != 1) ? $time_hours : $time_hour) . " $suffix";
} elseif ($diff < $week) {
$days = floor($diff / $day);
// Special handling for today and yesterday
if ($days == 0) {
return $time_today;
} elseif ($days == 1) {
return $time_yesterday;
}
return $days.(($days != 1)?$time_days:$time_day) . " $suffix";
} elseif ($diff < $month) {
$weeks = floor($diff / $week);
return $weeks.(($weeks != 1)?$time_weeks:$time_week) . " $suffix";
} elseif ($diff < $year) {
$months = floor($diff / $month);
return $months.(($months != 1)?$time_months:$time_month) . " $suffix";
} else {
$years = floor($diff / $year);
return $years.(($years != 1)?$time_years:$time_year) . " $suffix";
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generate language files ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function generateLanguageFile($language_key,$token){
function generateFile($language_key,$token){
//GET TRANSLATION RECORDS
$api_url = '/v2/translations/generatefile='.$language_key;
$responses = ioAPIv2($api_url,'',$token);
if (!empty($responses)){
//define translation variable
$translation = '';
//Target dir
$target_dir = dirname(__FILE__,2).'/settings/translations/';
//Filename
$input_file = $target_dir.'translations_'.strtoupper($language_key).'.php';
//store translation to the file
file_put_contents($input_file, $translation);
}
}
if ($language_key != ''){
generateFile($language_key,$token);
} else {
include dirname(__FILE__,2).'/settings/settingsmenu.php';
foreach ($supportedLanguages as $language){
generateFile($language,$token);
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Removekeys from array ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function removeKeysRecursive(array &$array, array $keysToRemove): void {
foreach ($array as $key => &$value) {
// Remove the key if it exists in our removal list
if (in_array($key, $keysToRemove, true)) {
unset($array[$key]);
continue;
}
// If value is an array, recursively process it
if (is_array($value)) {
removeKeysRecursive($value, $keysToRemove);
// If array is empty after processing, remove it
if (empty($value)) {
unset($array[$key]);
}
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Catalogprocessor ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function processProductCollection($products) {
$processedProducts = [];
foreach ($products as $key => $product) {
// Check if product has versions
if (isset($product['versions']) && !empty($product['versions'])) {
// Check if there's only one version
$singleVersion = count($product['versions']) === 1;
// For each version, create a new product entry
foreach ($product['versions'] as $version) {
// Create a copy of the base product
$versionProduct = $product;
// Remove the versions array
unset($versionProduct['versions']);
// Add version specific data
$versionProduct['version_id'] = $version['version_id'];
$versionProduct['config_setting'] = $version['config_setting'];
$versionProduct['main_option_for_display'] = $version['main_option_for_display'];
$versionProduct['configurations'] = $version['configurations'];
// Only modify identifiers if there's more than one version
if (!$singleVersion) {
// Create a unique rowID for the new product
$versionProduct['rowID'] = $versionProduct['rowID'] . '_v' . $version['version_id'];
// Add version suffix to productcode and url_slug
$versionProduct['productcode'] = $versionProduct['productcode'] . '_v' . $version['version_id'];
if (!empty($versionProduct['url_slug'])) {
$versionProduct['url_slug'] = $versionProduct['url_slug'] . '_v' . $version['version_id'];
}
// Add version to product name if needed
$versionProduct['productname'] = $versionProduct['productname'] . ' (v' . $version['version_id'] . ')';
}
// Add to processed products
$processedProducts[] = $versionProduct;
}
} else {
// If no versions, add product as is
$processedProducts[] = $product;
}
}
return $processedProducts;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// CalculateTotalPrice based on options ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function calculateTotalPrice($product_data, $selected_options) {
$base_price = floatval($product_data['price']);
$total_price = $base_price;
$selected_item_names = [];
foreach ($product_data['configurations'] as $config) {
// Handle group configurations
if (isset($config['attributes']) &&
isset($selected_options[$config['assignment']])) {
$selected_group_attributes = $selected_options[$config['assignment']];
foreach ($selected_group_attributes as $selected_attribute_id) {
foreach ($config['attributes'] as $attribute) {
if ($attribute['attribute_id'] == $selected_attribute_id) {
$total_price += $attribute['price_modifier'] == 1
? floatval($attribute['price'])
: -floatval($attribute['price']);
// Collect item names
$selected_item_names[] = $attribute['item_name'];
}
}
}
}
// Handle additional products
if (isset($selected_options['products']) &&
$config['type'] == 'product' &&
in_array($config['assignment'], $selected_options['products'])) {
/*/Include Pricing of optional products
$total_price += $config['price_modifier'] == 1
? floatval($config['price'])
: -floatval($config['price']);
*/
// Collect product names
$selected_item_names[] = $config['assignment_name'];
}
}
return [
'total_price' => $total_price,
'selected_items' => implode(', ', $selected_item_names)
];
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ShoppingCartCalulator ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
class ShoppingCartCalculator {
private $products;
private $selected_country;
private $selected_shipping_method;
private $business_type;
private $discount_code;
private $db;
private $discount_message;
private $tax_rate;
public function __construct($products, $selected_country, $selected_shipping_method, $business_type, $discount_code, $db) {
$this->products = $products;
$this->selected_country = $selected_country;
$this->selected_shipping_method = $selected_shipping_method;
$this->business_type = strtolower($business_type);
$this->discount_code = $discount_code;
$this->db = $db;
$this->discount_message = '';
$this->tax_rate = $this->getTaxRate();
}
public function calculateTotals() {
// Calculate basic totals
$subtotal = $this->calculateSubtotal();
$weighttotal = $this->calculateWeightTotal();
$shippingtotal = $this->calculateShippingTotal($subtotal, $weighttotal,$this->selected_shipping_method);
$discounttotal = $this->calculateDiscountTotal();
$taxtotal = $this->calculateTaxTotal($subtotal - $discounttotal + $shippingtotal);
// Calculate final total based on business type
$total = $this->calculateFinalTotal($subtotal, $shippingtotal, $discounttotal, $taxtotal);
return [
'cart_details' => [
'products' => $this->products,
'selected_country' => $this->selected_country,
'selected_shipping_method' => $this->selected_shipping_method,
'business_type' => $this->business_type,
'discount_code' => $this->discount_code
],
'totals' => [
'subtotal' => number_format($subtotal, 2, '.', ''),
'weighttotal' => number_format($weighttotal, 2, '.', ''),
'shippingtotal' => number_format($shippingtotal, 2, '.', ''),
'discounttotal' => number_format($discounttotal, 2, '.', ''),
'discount_message' => $this->discount_message,
'tax_rate' => number_format($this->tax_rate, 2, '.', '') . '%',
'taxtotal' => number_format($taxtotal, 2, '.', ''),
'total' => number_format($total, 2, '.', '')
]
];
}
private function getTaxRate() {
$sql = "SELECT rate FROM taxes WHERE id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->selected_country]);
$tax = $stmt->fetch(PDO::FETCH_ASSOC);
return $tax ? floatval($tax['rate']) : 0;
}
private function calculateSubtotal() {
$subtotal = 0;
foreach ($this->products as $product) {
$product_price = floatval(str_replace(',', '.', $product['options_price']));
$subtotal += $product_price * $product['quantity'];
}
return $subtotal;
}
private function calculateWeightTotal() {
$weighttotal = 0;
foreach ($this->products as $product) {
$options_weight = floatval($product['options_weight']);
$weighttotal += $options_weight * $product['quantity'];
}
return $weighttotal;
}
private function calculateDiscountTotal() {
if (empty($this->discount_code)) {
$this->discount_message = '';
return 0;
}
$current_date = date('Y-m-d H:i:s');
// First check if discount code exists and is valid
$sql = "SELECT * FROM discounts WHERE discount_code = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->discount_code]);
$discount = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$discount) {
$this->discount_message = 'Invalid discount code';
return 0;
}
// Check date validity
if ($current_date < $discount['start_date']) {
$this->discount_message = 'Discount code not yet active';
return 0;
}
if ($current_date > $discount['end_date']) {
$this->discount_message = 'Discount code expired';
return 0;
}
// Convert string of IDs to arrays
$discount_product_ids = !empty($discount['product_ids']) ?
array_map('trim', explode(',', $discount['product_ids'])) : [];
$discount_category_ids = !empty($discount['category_ids']) ?
array_map('trim', explode(',', $discount['category_ids'])) : [];
$discounttotal = 0;
$eligible_products_found = false;
$total_eligible_price = 0;
// Calculate total eligible price
foreach ($this->products as $product) {
if ($this->isProductEligibleForDiscount($product, $discount_product_ids, $discount_category_ids)) {
$eligible_products_found = true;
$product_price = floatval(str_replace(',', '.', $product['options_price'])) * $product['quantity'];
$total_eligible_price += $product_price;
}
}
// Calculate discount if eligible products found
if ($eligible_products_found) {
if ($discount['discount_type'] == 1) {
// Percentage discount
$discounttotal = $total_eligible_price * ($discount['discount_value'] / 100);
} else {
// Fixed amount discount
$discounttotal = min($discount['discount_value'], $total_eligible_price);
}
$discount_type = $discount['discount_type'] == 1 ?
$discount['discount_value'] . '% discount' :
'€' . number_format($discount['discount_value'], 2) . ' discount';
$this->discount_message = "Discount applied successfully: " . $discount_type;
} else {
$this->discount_message = 'No eligible products for this discount code';
$discounttotal = 0;
}
return $discounttotal;
}
private function isProductEligibleForDiscount($product, $discount_product_ids, $discount_category_ids) {
// If no specific products or categories are set, discount applies to all products
if (empty($discount_product_ids) && empty($discount_category_ids)) {
return true;
}
$product_match = false;
$category_match = false;
// Check product ID match
if (!empty($discount_product_ids)) {
$product_match = in_array($product['id'], $discount_product_ids);
// If only product IDs are specified (no categories), return the product match result
if (empty($discount_category_ids)) {
return $product_match;
}
} else {
// If no product IDs specified, set product_match to true
$product_match = true;
}
// Check category match
if (!empty($discount_category_ids)) {
if (isset($product['meta']['category_ids'])) {
$product_categories = is_array($product['meta']['category_ids']) ?
$product['meta']['category_ids'] :
array_map('trim', explode(',', $product['meta']['category_ids']));
$category_match = !empty(array_intersect($product_categories, $discount_category_ids));
} else {
$category_match = false;
}
// If only categories are specified (no products), return the category match result
if (empty($discount_product_ids)) {
return $category_match;
}
} else {
// If no categories specified, set category_match to true
$category_match = true;
}
// If both product IDs and categories are specified, both must match
return $product_match && $category_match;
}
private function calculateShippingTotal($subtotal, $weighttotal,$selected_shipping_method) {
//USER PROVIDED SHIPMENT METHOD
$sql = "SELECT price FROM shipping WHERE ID = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->selected_shipping_method]);
$shipping = $stmt->fetch(PDO::FETCH_ASSOC);
return $shipping ? floatval($shipping['price']) : 0;
}
private function calculateTaxTotal($amount_to_tax) {
$sql = "SELECT rate FROM taxes WHERE id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->selected_country]);
$tax = $stmt->fetch(PDO::FETCH_ASSOC);
if ($this->business_type === 'b2c') {
// Tax is included in final price
return $tax ? ($amount_to_tax - ($amount_to_tax / ( 1 + ($tax['rate'] / 100)))) : 0;
} else {
// Tax is added on top for B2B
return $tax ? ($amount_to_tax * ($tax['rate'] / 100)) : 0;
}
}
private function calculateFinalTotal($subtotal, $shippingtotal, $discounttotal, $taxtotal) {
$base = $subtotal - $discounttotal + $shippingtotal;
if ($this->business_type === 'b2c') {
// Tax is included in final price
return $base;
} else {
// Tax is added on top for B2B
return $base + $taxtotal;
}
}
}
function validateCheckoutData($post_content) {
$errors = [];
// Required fields for checkout input
$required_checkout_fields = [
'cart' => 'Products',
'checkout_input.selected_country' => 'Country',
'checkout_input.selected_shipment_method' => 'Shipping method',
'checkout_input.business_type' => 'Business type',
'checkout_input.payment_method' => 'Payment method'
];
// Required fields for customer details
$required_customer_fields = [
'customer_details.email' => 'Email',
'customer_details.first_name' => 'First name',
'customer_details.last_name' => 'Last name',
'customer_details.address_street' => 'Street address',
'customer_details.address_city' => 'City',
'customer_details.address_zip' => 'ZIP code',
'customer_details.address_country' => 'Country',
'customer_details.address_phone' => 'Phone number'
];
// Validate checkout input fields
foreach ($required_checkout_fields as $field => $label) {
$keys = explode('.', $field);
if (count($keys) === 1) {
if (!isset($post_content[$keys[0]]) || empty($post_content[$keys[0]])) {
$errors[] = "$label is required";
}
} else {
if (!isset($post_content[$keys[0]][$keys[1]]) || empty($post_content[$keys[0]][$keys[1]])) {
$errors[] = "$label is required";
}
}
}
// Validate customer details fields
foreach ($required_customer_fields as $field => $label) {
$keys = explode('.', $field);
if (!isset($post_content[$keys[0]][$keys[1]]) || empty($post_content[$keys[0]][$keys[1]])) {
$errors[] = "$label is required";
}
}
// Additional validation for email format
if (isset($post_content['customer_details']['email']) && !empty($post_content['customer_details']['email'])) {
if (!filter_var($post_content['customer_details']['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format";
}
}
// Additional validation for phone number (basic format check)
if (isset($post_content['customer_details']['address_phone']) && !empty($post_content['customer_details']['address_phone'])) {
if (!preg_match("/^[0-9\-\(\)\/\+\s]*$/", $post_content['customer_details']['address_phone'])) {
$errors[] = "Invalid phone number format";
}
}
return $errors;
}
function validateTransactionData($post_content) {
$errors = [];
// Required fields for customer details
$required_fields = [
'customer_details.email' => 'Email',
'customer_details.first_name' => 'First name',
'customer_details.last_name' => 'Last name',
'customer_details.address_street' => 'Street address',
'customer_details.address_city' => 'City',
'customer_details.address_zip' => 'ZIP code',
'customer_details.address_country' => 'Country',
'total.payment_amount' => 'Payment_amount',
];
// Validate customer details fields
foreach ($required_fields as $field => $label) {
$keys = explode('.', $field);
if (!isset($post_content[$keys[0]][$keys[1]]) || empty($post_content[$keys[0]][$keys[1]])) {
$errors[] = "$label is required";
}
}
return $errors;
}
function getCountryNamesByIds($countries, $idString) {
// Create a lookup array where ID is the key and country name is the value
$countryMap = array_column($countries, 'country', 'id');
// Convert comma-separated string to array
$ids = explode(',', $idString);
// Get country names for each ID
$countryNames = [];
foreach ($ids as $id) {
$id = trim($id);
if (isset($countryMap[$id])) {
$countryNames[] = $countryMap[$id];
}
}
return $countryNames;
}
function transformOrderData(array $orderData): array {
// Initialize the result array with the first row's common data
$firstRow = $orderData[0];
$result = [
'header' => [
"id" => $firstRow['id'],
"txn_id" => $firstRow['txn_id'],
"payment_status" => $firstRow['payment_status'],
"payment_method" => $firstRow['payment_method'],
"shipping_method" => $firstRow['shipping_method'],
"discount_code" => $firstRow['discount_code'],
"created" => $firstRow['created'],
"updated " => $firstRow['updated']
],
'customer' => [
'account_id' => $firstRow['account_id'],
'email' => $firstRow['payer_email'],
'name' => $firstRow['first_name'] . ' ' . $firstRow['last_name'],
'street' => $firstRow['address_street'],
'zip' => $firstRow['address_zip'],
'state' => $firstRow['address_state'],
'city' => $firstRow['address_city'],
'country' => $firstRow['address_country'],
'phone' => $firstRow['address_phone'],
'language' => $firstRow['user_language'],
],
'products' => [],
'invoice' => [
'id' => $firstRow['invoice'],
'created' => $firstRow['invoice_created'],
'payment_status' => $firstRow['payment_status']
],
'pricing' => [
'subtotal' => 0,
'shipping_total' => $firstRow['shipping_amount'],
'tax_total' => $firstRow['tax_amount'],
'discount_total' => $firstRow['discount_amount'],
'payment_amount' => $firstRow['payment_amount']
]
];
// Process products from all rows
foreach ($orderData as $row) {
// Decode JSON string for item options
$itemOptions = json_decode($row['item_options'], true) ?? [];
// Calculate line total
$lineTotal = floatval($row['item_price']) * intval($row['item_quantity']);
// Add to subtotal
$result['pricing']['subtotal'] += $lineTotal;
// Add product information
$result['products'][] = [
'item_id' => $row['item_id'],
'productcode' => $row['productcode'],
'product_name' => $row['productname'],
'options' => $itemOptions,
'quantity' => $row['item_quantity'],
'price' => $row['item_price'],
'line_total' => number_format($lineTotal, 2, '.', '')
];
}
// Format monetary values
$result['pricing']['subtotal'] = number_format($result['pricing']['subtotal'], 2, '.', '');
$result['pricing']['shipping_total'] = number_format(floatval($result['pricing']['shipping_total']), 2, '.', '');
$result['pricing']['tax_total'] = number_format(floatval($result['pricing']['tax_total']), 2, '.', '');
$result['pricing']['discount_total'] = number_format(floatval($result['pricing']['discount_total']), 2, '.', '');
$result['pricing']['payment_amount'] = number_format(floatval($result['pricing']['payment_amount']), 2, '.', '');
return $result;
}
function transformOrders($inputData){
// Define which fields are item-specific (will go into the items array)
$itemFields = ['item_id', 'item_name', 'item_price', 'item_quantity', 'item_options', 'full_path'];
// Process the data
$combinedData = [];
foreach ($inputData as $row) {
$txnId = $row['txn_id'];
// Create header and item arrays for the current row
$headerData = [];
$itemData = [];
foreach ($row as $key => $value) {
if (in_array($key, $itemFields)) {
// This is an item field
$itemData[$key] = $value;
} else {
// This is a header field
$headerData[$key] = $value;
}
}
// Check if this transaction ID already exists in our result array
if (!isset($combinedData[$txnId])) {
// First occurrence of this transaction - create the structure
$combinedData[$txnId] = [
'header' => $headerData,
'items' => [$itemData]
];
} else {
// Transaction already exists - just add the item data
$combinedData[$txnId]['items'][] = $itemData;
}
}
// Convert associative array to indexed array if needed
$finalResult = array_values($combinedData);
return $finalResult;
}
//=============================================
// Use giftcart
//=============================================
function useGiftCart($pdo, $discount_code, $accounthierarchy){
// Get the current date
$end_date = date("Y-m-d H:i:s");
//Check if Giftcard already exists
$stmt = $pdo->prepare('SELECT * from discounts WHERE discount_code = ? AND accounthierarchy = ?');
$stmt->execute([$discount_code,$accounthierarchy]);
$discount_exist = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($discount_exist) || $discount_exist != '') {
//Update Giftcard end data
$stmt = $pdo->prepare('UPDATE discounts SET end_date = ? WHERE discount_code = ? AND accounthierarchy = ?');
$stmt->execute([$end_date,$discount_code, $accounthierarchy]);
}
}
function createGiftCart($pdo, $orderID, $giftcard_categoryID,$accounthierarchy){
//Check if Giftcard is ordered
$stmt = $pdo->prepare('SELECT t.payer_email as email, ti.id as id, t.txn_id as txn, ti.item_price as item_price, ti.item_quantity as item_quantity FROM transactions t INNER JOIN transactions_items ti ON t.txn_id = ti.txn_id INNER JOIN products_categories p ON ti.item_id = p.product_id WHERE p.category_id = ? AND ti.txn_id = ? AND accounthierarchy = ?');
$stmt->execute([$giftcard_categoryID,$orderID,$accounthierarchy]);
$giftcards = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($giftcards) {
foreach ($giftcards as $giftcard) {
//For each quantity
$x = 0;
while ($x < $giftcard['item_quantity']){
//Generate discount code = TXN/ID/X
$discount_code = $giftcard['txn'].'#'.$giftcard['id'].'#'.$x;
$value = $giftcard['item_price'];
// Get the current date
$start_date = date("Y-m-d H:i:s");
$end_date = date("Y-m-d H:i:s", strtotime("+5 years"));;
//Check if Giftcard already exists
$stmt = $pdo->prepare('SELECT * from discounts WHERE discount_code = ? AND accounthierarchy = ?');
$stmt->execute([$discount_code,$accounthierarchy]);
$discount_exist = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($discount_exist) || $discount_exist == '') {
//Insert Giftcard
$discount_type = 0; //Fixed
//SQL Insert
$stmt = $pdo->prepare('INSERT INTO discounts (discount_code,discount_type,discount_value,start_date,end_date,accounthierarchy) VALUES (?,?,?,?,?,?)');
$stmt->execute([$discount_code, $discount_type, $value, $start_date, $end_date,$accounthierarchy]);
}
$x++;
}
}
}
}
//=======================================
// findGitCommitHash
//=======================================
function findShortGitCommitHash($string) {
// Step 1: Find all hexadecimal sequences
preg_match_all('/[0-9a-f]+/i', $string, $matches);
$allHexMatches = $matches[0] ?? [];
// Step 2: Filter to only include those with exactly 6 or 7 characters
$commitHashes = array_filter($allHexMatches, function($match) {
return strlen($match) === 6 || strlen($match) === 7;
});
return array_values($commitHashes); // Re-index array
}
function compareCommitCodes($stringA, $stringB) {
// Get commit codes from both strings
$commitCodesA = findShortGitCommitHash($stringA);
$commitCodesB = findShortGitCommitHash($stringB);
// Case 1: Check if there are matching commit codes between A and B
foreach ($commitCodesA as $codeA) {
if (in_array($codeA, $commitCodesB)) {
return $codeA; // Return the first matching commit code
}
}
// Case 2: If A has commit code but B doesn't
if (count($commitCodesA) > 0 && count($commitCodesB) === 0) {
return $commitCodesA[0]; // Return the first commit code from A
}
// Case 3: If A has no commit code but B does
if (count($commitCodesA) === 0 && count($commitCodesB) > 0) {
return $commitCodesB[0]; // Return the first commit code from B
}
// Case 4: Neither has commit code
return "";
}
//=======================================
// Function to find the first existing view
//=======================================
function findExistingView($viewsArray, $defaultView, $ignoreViews) {
foreach ($viewsArray as $view) {
$file_to_check = $view.'.php';
if (in_array($view, $ignoreViews)) {
continue;
}
if (file_exists($file_to_check)) {
return $view;
}
}
// If no view exists, return the default
return $defaultView;
}
//=======================================
// Function to find the domain
//=======================================
function getDomainName($hostname) {
// Extract the domain parts
$parts = explode('.', $hostname);
$count = count($parts);
// For hostnames with enough parts to have a subdomain (at least 3 parts)
if ($count >= 3) {
// Return the second-to-last and third-to-last parts
return $parts[$count - 2];
}
// For hostnames with just domain and TLD (2 parts)
else if ($count == 2) {
// Return just the domain part (without the TLD)
return $parts[0];
}
// If it's a single part hostname
else {
return $hostname;
}
}
//=======================================
// encode ID to UUID
//=======================================
function encodeUuid($number) {
$alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$base = strlen($alphabet);
$encoded = '';
while ($number) {
$encoded = $alphabet[$number % $base] . $encoded;
$number = floor($number / $base);
}
$encoded = $encoded ?: '0';
// Pad with leading zeros from the alphabet (which is '0') if shorter than 5 characters
while (strlen($encoded) < 5) {
$encoded = '0' . $encoded;
}
return $encoded;
}
//=======================================
// decode UUID to ID
//=======================================
function decodeUuid($encoded) {
$encoded = strtoupper($encoded);
$alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$base = strlen($alphabet);
$number = 0;
$length = strlen($encoded);
for ($i = 0; $i < $length; $i++) {
$char = $encoded[$i];
$position = strpos($alphabet, $char);
if ($position === false) {
// Character not found in alphabet
return false;
}
$number = $number * $base + $position;
}
return $number;
}
/**
* Generate marketing content for a spa/hot tub company based on business criteria
*
* @param string $companyName The name of the company
* @param string $city The city location
* @param bool $gardenCenter Whether the company is a garden center
* @param string $brandType Single brand or Multi brand
* @param string $showroomSize Normal, Large, or Extra Large
* @param string $offering Economy-Premium or Premium-Highend
* @param string $dealerType Local, Professional, or Corporate
* @param bool $multipleLocations Whether the company has multiple locations
* @return array An array containing short description, long description, and unique selling points
*/
function generateSpaCompanyContent($companyName, $city, $gardenCenter, $brandType, $showroomSize, $offering, $dealerType, $multipleLocations) {
// Determine content template to use based on criteria combination
$templateIndex = determineTemplateIndex($gardenCenter, $brandType, $offering, $dealerType, $multipleLocations);
// Get content templates
$shortDescTemplates = getShortDescriptionTemplates();
$longDescTemplates = getLongDescriptionTemplates();
$uspTemplates = getUniqueSellingPointsTemplates();
// Replace placeholders in templates
$shortDescription = str_replace(
['{CompanyName}', '{City}', '{BrandType}', '{ShowroomSize}'],
[$companyName, $city, $brandType, $showroomSize],
$shortDescTemplates[$templateIndex]
);
$longDescription = str_replace(
['{CompanyName}', '{City}', '{BrandType}', '{ShowroomSize}'],
[$companyName, $city, $brandType, $showroomSize],
$longDescTemplates[$templateIndex]
);
$usps = [];
foreach ($uspTemplates[$templateIndex] as $usp) {
$usps[] = str_replace(
['{CompanyName}', '{City}', '{BrandType}', '{ShowroomSize}'],
[$companyName, $city, $brandType, $showroomSize],
$usp
);
}
return [
'short_description' => $shortDescription,
'long_description' => $longDescription,
'usp1' => $usps[0],
'usp2' => $usps[1],
'usp3' => $usps[2]
];
}
/**
* Determine which template to use based on company criteria
*/
function determineTemplateIndex($gardenCenter, $brandType, $offering, $dealerType, $multipleLocations) {
// This is a simplified method to select a template
// In a real implementation, you might want more sophisticated logic
if ($gardenCenter) {
if (strpos($offering, 'Premium') !== false) {
return 3; // Garden Center Premium
} else {
return 7; // Garden Center High-End
}
}
if ($dealerType == 'Local') {
if ($brandType == 'Single brand') {
return strpos($offering, 'Economy') !== false ? 0 : 4; // Local Economy Single Brand or Local High-End Single Brand
}
}
if ($dealerType == 'Professional') {
if ($brandType == 'Single brand') {
return 9; // Professional Single Brand Specialist
} else {
return strpos($offering, 'Economy') !== false ? 5 : 1; // Professional Economy Multi-Brand or Professional Premium Multi-Brand
}
}
if ($dealerType == 'Corporate') {
if ($multipleLocations) {
return 2; // Corporate High-End Multi-Location
} else {
return 8; // Corporate Premium Multi-Brand
}
}
if ($multipleLocations && strpos($offering, 'Economy') !== false) {
return 6; // Multi-Location Economy Single Brand
}
// Default to template 0 if no conditions match
return 0;
}
/**
* Get all short description templates
*/
function getShortDescriptionTemplates() {
return [
// 0. Local Economy Single Brand
"{CompanyName} is {City}'s trusted provider of quality hot tubs and spas at affordable prices, featuring the complete {BrandType} collection in our {ShowroomSize} showroom.",
// 1. Professional Premium Multi-Brand
"{CompanyName} brings premium spa experiences to {City} with our curated selection of luxury brands in our {ShowroomSize} professional showroom.",
// 2. Corporate High-End Multi-Location
"With locations across the region including {City}, {CompanyName} delivers exceptional high-end spa solutions backed by corporate reliability and service excellence.",
// 3. Garden Center Premium
"{CompanyName} combines garden expertise with premium spa offerings in {City}, creating the perfect outdoor relaxation destinations within our {ShowroomSize} garden center.",
// 4. Local High-End Single Brand
"{CompanyName} is {City}'s exclusive dealer for {BrandType} luxury spas, offering personalized service in an intimate {ShowroomSize} showroom experience.",
// 5. Professional Economy Multi-Brand
"As {City}'s professional spa specialists, {CompanyName} presents affordable solutions from leading brands in our {ShowroomSize} showroom designed for every budget.",
// 6. Multi-Location Economy Single Brand
"{CompanyName} makes quality relaxation accessible across multiple locations including {City}, specializing exclusively in the reliable {BrandType} collection.",
// 7. Garden Center High-End
"Elevate your garden oasis with {CompanyName}'s selection of high-end spas and hot tubs, showcased within our {ShowroomSize} {City} garden center.",
// 8. Corporate Premium Multi-Brand
"{CompanyName} combines corporate expertise with personalized service in {City}, offering premium spa solutions from the industry's most respected brands.",
// 9. Professional Single Brand Specialist
"{City}'s dedicated {BrandType} specialists at {CompanyName} provide expert guidance and professional support in our {ShowroomSize} showroom."
];
}
/**
* Get all long description templates
*/
function getLongDescriptionTemplates() {
return [
// 0. Local Economy Single Brand
"Welcome to {CompanyName}, {City}'s dedicated hot tub and spa center where affordability meets quality. Our {ShowroomSize} showroom exclusively features the complete {BrandType} line, offering reliable relaxation solutions for every home and budget. As a locally owned business, we take pride in providing personalized service to our neighbors while maintaining competitive pricing. Our knowledgeable staff guides you through the entire process from selection to installation, ensuring your perfect spa experience.",
// 1. Professional Premium Multi-Brand
"{CompanyName} has established itself as {City}'s premier destination for premium spa experiences. Our professional team showcases a carefully selected range of luxury brands in our {ShowroomSize} showroom, each chosen for superior craftsmanship and innovative features. We combine technical expertise with a consultative approach, helping clients discover the perfect spa solution for their lifestyle and wellness goals. From initial design consultation through professional installation and ongoing maintenance, our comprehensive service ensures a seamless ownership experience.",
// 2. Corporate High-End Multi-Location
"With our flagship location in {City} and showrooms across the region, {CompanyName} delivers unparalleled access to high-end spa solutions. Our corporate structure ensures consistent quality, competitive pricing, and exceptional service at every location. The {ShowroomSize} {City} showroom features our complete collection of luxury spa brands, each representing the pinnacle of design, technology, and comfort. Our team of spa professionals provides expert guidance backed by our company-wide commitment to customer satisfaction and long-term support.",
// 3. Garden Center Premium
"At {CompanyName}, we've expanded our {City} garden expertise to include premium spa and hot tub solutions that complement your outdoor living space. Our {ShowroomSize} garden center now showcases a thoughtfully curated selection of quality spas designed to transform your backyard into a year-round wellness retreat. Our unique perspective combines landscaping knowledge with spa technology expertise, allowing us to help you create integrated outdoor environments where garden beauty meets relaxation therapy. Visit our {City} location to explore how our premium spa offerings can enhance your garden sanctuary.",
// 4. Local High-End Single Brand
"{CompanyName} brings exclusive {BrandType} luxury spas to discerning clients throughout {City}. Our intimate {ShowroomSize} showroom creates a personalized shopping experience where you can explore every detail of these exceptional wellness products. As {City}'s dedicated {BrandType} specialists, we offer unmatched product knowledge and customization options not available elsewhere. Our commitment to white-glove service extends from your first consultation through years of ownership, with dedicated support from our team who knows your installation personally.",
// 5. Professional Economy Multi-Brand
"{CompanyName} was founded on the belief that quality relaxation should be accessible to everyone in {City}. Our {ShowroomSize} showroom features carefully selected spa brands that deliver reliable performance without premium price tags. Our professional team applies the same expertise and attention to detail regardless of your budget, helping you navigate options to find the perfect balance of features and affordability. We handle everything from site preparation to installation and maintenance education, ensuring a stress-free experience that matches our stress-relieving products.",
// 6. Multi-Location Economy Single Brand
"With {CompanyName}'s expanding presence across the region, including our {City} location, we've streamlined operations to bring you exceptional value through our exclusive partnership with {BrandType}. Our {ShowroomSize} showrooms showcase the complete range of these reliable spas, with consistent pricing and service standards at every location. By focusing on a single trusted manufacturer, we've developed specialized expertise that benefits our customers through knowledgeable guidance, efficient service, and optimized inventory that ensures prompt delivery and installation.",
// 7. Garden Center High-End
"{CompanyName} has evolved our {City} garden center concept to include a curated collection of high-end spas and hot tubs that represent the perfect fusion of nature and luxury. Our {ShowroomSize} showroom displays these premium wellness products in contextual settings that help you envision the transformation of your own outdoor space. Our unique approach combines horticultural expertise with spa technology knowledge, allowing us to create integrated relaxation environments that function beautifully through every season. Experience the difference at our {City} location, where garden artistry meets wellness innovation.",
// 8. Corporate Premium Multi-Brand
"As {City}'s corporate-backed premium spa provider, {CompanyName} combines the reliability of organizational strength with the personal touch of dedicated local experts. Our {ShowroomSize} showroom presents a comprehensive selection of premium brands, each meeting our rigorous standards for quality, innovation, and value. Our structured approach ensures consistency through every phase of ownership, from transparent pricing and professional needs assessment through expert installation and scheduled maintenance programs. Experience the confidence that comes from working with {City}'s most established spa provider.",
// 9. Professional Single Brand Specialist
"{CompanyName} has dedicated our {City} business to becoming the region's foremost experts in {BrandType} spas and hot tubs. Our {ShowroomSize} showroom is designed to showcase every model and feature in this exceptional line, with working displays that demonstrate the unique benefits of these wellness systems. Our professional staff undergoes specialized factory training, making them uniquely qualified to help you select, customize, and maintain your {BrandType} spa. Choose {City}'s only dedicated {BrandType} specialists for an ownership experience as refined as the products we represent."
];
}
/**
* Get all unique selling points templates
*/
function getUniqueSellingPointsTemplates() {
return [
// 0. Local Economy Single Brand
[
"Exclusive {BrandType} dealer offering the full product line at competitive prices",
"Locally owned with personalized service from neighbors who care about your experience",
"Complete solutions from selection through installation with no hidden costs"
],
// 1. Professional Premium Multi-Brand
[
"Curated selection of premium brands chosen for superior quality and innovation",
"Professional consultation process that matches your lifestyle with the perfect spa",
"Comprehensive service from design consultation through lifetime maintenance"
],
// 2. Corporate High-End Multi-Location
[
"Regional presence with consistent high-end offerings across all locations",
"Corporate buying power delivering competitive pricing on luxury products",
"Standardized excellence in customer care backed by substantial resources"
],
// 3. Garden Center Premium
[
"Integrated approach to outdoor living combining garden expertise with spa technology",
"Contextual showroom displays demonstrating how spas enhance garden environments",
"Year-round wellness solutions that complement your existing garden investments"
],
// 4. Local High-End Single Brand
[
"Exclusive {City} source for the complete {BrandType} luxury collection",
"Intimate showroom experience with personalized attention to your specific needs",
"Specialized knowledge of customization options not available at general retailers"
],
// 5. Professional Economy Multi-Brand
[
"Carefully vetted affordable brands that maximize features while minimizing cost",
"Professional guidance typically reserved for luxury customers, at every price point",
"Transparent pricing with no compromise on installation quality or service"
],
// 6. Multi-Location Economy Single Brand
[
"Specialized {BrandType} expertise developed through exclusive brand focus",
"Consistent pricing and service standards across all regional locations",
"Optimized inventory management ensuring faster delivery and installation"
],
// 7. Garden Center High-End
[
"Unique perspective integrating luxury spas into complete garden environments",
"Seasonal expertise ensuring your spa enhances your outdoor space year-round",
"One-stop resource for creating cohesive outdoor relaxation destinations"
],
// 8. Corporate Premium Multi-Brand
[
"Organizational strength providing stability and reliability throughout ownership",
"Structured approach from consultation through installation and maintenance",
"Corporate accountability backing every product sold and service performed"
],
// 9. Professional Single Brand Specialist
[
"Deep {BrandType} expertise through specialized factory training and certification",
"Complete demonstration capability showing every model in working condition",
"Unmatched product knowledge of the complete {BrandType} feature set and options"
]
];
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generate dealer information ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function generateDealerInformation($token){
//INCLUDE US LANGUAGE
include dirname(__FILE__,2).'/settings/translations/translations_US.php';
//GET ALL DEALERS
$api_url = '/v2/dealers/list=';
$responses = ioAPIv2($api_url,'',$token);
$log_results =[];
if(!empty($responses)){
//decode the API response
$responses = json_decode($responses,true);
//loop through translation records and create variables
foreach ($responses as $response){
$new_content = [];
//Generate content for missing data
$keysToCheck = ['short_description', 'long_description', 'usp1', 'usp2', 'usp3'];
foreach ($keysToCheck as $key) {
$gc = ($response['garden_center'] == 0 ? false : true);
$ml = ($response['locations'] == 0 ? false : true);
//GENERATE DATA
$generated_content = generateSpaCompanyContent(
$response['name'], // Company name
$response['city'], // City
$gc, // Garden center (yes/no)
${'brand_type_'.$response['brand_type']}, // Brand type
${'showroom_size_'.$response['showroom_size']}, // Showroom size
${'focus_offering_'.$response['focus_offering']}, // Offering
${'dealer_type_'.$response['dealer_type']}, // Dealer type
$ml // Multiple locations
);
if (isset($response[$key]) && (empty($response[$key]) || $response[$key] == '')) {
$new_content['rowID'] = encodeUuid($response['rowID']);
$new_content[$key] = $generated_content[$key];
}
}
//GET ALL POST DATA
$payload = json_encode($new_content, JSON_UNESCAPED_UNICODE);
//API call
$api_call = ioAPIv2('/v2/dealers', $payload,$token);
$api_response = json_decode($api_call ,true);
//Provide feedback
$log_results[$response['rowID']] = $api_response['rowID'].' '.$api_response['status'];
}
}
return $log_results;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function to check if origin matches allowed patterns
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function isOriginAllowed($origin, $allowedPatterns) {
if (empty($origin)) {
return false;
}
// Parse the origin to get the host part
$parsedOrigin = parse_url($origin);
$host = $parsedOrigin['host'] ?? '';
if (empty($host)) {
return false;
}
// Check if the host matches any of our patterns (exact match or subdomain)
foreach ($allowedPatterns as $pattern) {
// Check for exact match
if ($host === $pattern) {
return true;
}
// Check for subdomain match (domain.example.com)
$patternWithDot = '.' . $pattern;
if (substr($host, -strlen($patternWithDot)) === $patternWithDot) {
return true;
}
}
return false;
}
function removeTrailingElement($string,$element) {
// Trim whitespace from the end
$trimmed = rtrim($string);
// Check if the trimmed string is not empty and ends with a comma
if (!empty($trimmed) && substr($trimmed, -1) === $element) {
// Remove the last character (the comma)
return substr($trimmed, 0, -1);
}
// Return original string if it doesn't end with a comma
return $trimmed;
}
function processPostContent(array $post_content): array
{
// Use provided values if they exist and are not empty
if (isset($post_content['budget']) && !empty($post_content['budget'])) {
$budget = $post_content['budget'];
}
if (isset($post_content['showroom_quality']) && !empty($post_content['showroom_quality'])) {
$showroom_quality = $post_content['showroom_quality'];
}
if (isset($post_content['brand_category']) && !empty($post_content['brand_category'])) {
$brand_category = $post_content['brand_category'];
}
// Check if 'focus_offering' is available and not empty
if (isset($post_content['focus_offering']) && !empty($post_content['focus_offering'])) {
// 1. Add budget based on focus_offering if budget wasn't provided
if (!isset($budget)) {
$post_content['budget'] = $post_content['focus_offering'];
}
// Ensure 'dealer_type' is available for showroom_quality logic
if (isset($post_content['dealer_type'])) {
$dealer_type = $post_content['dealer_type'];
// 2, 3, 4. Determine showroom_quality if it wasn't provided
if (!isset($showroom_quality)) {
if ($post_content['focus_offering'] == 0 && $dealer_type == 0) {
$post_content['showroom_quality'] = 0;
} elseif (($post_content['focus_offering'] == 0 && $dealer_type == 1) || ($post_content['focus_offering'] == 1 && $dealer_type == 0)) {
$post_content['showroom_quality'] = 1;
} elseif ($post_content['focus_offering'] == 1 && $dealer_type == 1) {
$post_content['showroom_quality'] = 2;
}
}
}
}
// 5. Determine brand_category based on showroom_quality if it exists and brand_category wasn't provided
if (isset($post_content['showroom_quality']) && !isset($brand_category)) {
if ($post_content['showroom_quality'] == 2){
$post_content['brand_category'] = 2;
} elseif ($post_content['showroom_quality'] == 0){
$post_content['brand_category'] = 0;
} else {
$post_content['brand_category'] = 1;
}
}
if (isset($post_content['name']) && (isset($post_content['dealer_slug']) && $post_content['dealer_slug'] == '')){
$trimmedString = trim($post_content['name']);
$post_content['dealer_slug'] = str_replace(" ", "_", $trimmedString);
}
return $post_content;
}