Files
opensourcepos/app/Controllers/Config.php
objecttothis e90b5b87da Replace tabs with spaces (#4196)
Signed-off-by: objecttothis <objecttothis@gmail.com>
2025-03-28 21:24:21 +04:00

971 lines
40 KiB
PHP

<?php
namespace App\Controllers;
use App\Libraries\Barcode_lib;
use App\Libraries\Mailchimp_lib;
use App\Libraries\Receiving_lib;
use App\Libraries\Sale_lib;
use App\Libraries\Tax_lib;
use App\Models\Appconfig;
use App\Models\Attribute;
use App\Models\Customer_rewards;
use App\Models\Dinner_table;
use App\Models\Module;
use App\Models\Enums\Rounding_mode;
use App\Models\Stock_location;
use App\Models\Tax;
use CodeIgniter\Database\BaseConnection;
use CodeIgniter\Encryption\EncrypterInterface;
use Config\Database;
use Config\OSPOS;
use Config\Services;
use DirectoryIterator;
use NumberFormatter;
use ReflectionException;
class Config extends Secure_Controller
{
protected $helpers = ['security'];
private BaseConnection $db;
private EncrypterInterface $encrypter;
private Barcode_lib $barcode_lib;
private Sale_lib $sale_lib;
private Receiving_lib $receiving_lib;
private Tax_lib $tax_lib;
private Appconfig $appconfig;
private Attribute $attribute;
private Customer_rewards $customer_rewards;
private Dinner_table $dinner_table;
protected Module $module;
private Stock_location $stock_location;
private Tax $tax;
private array $config;
public function __construct()
{
parent::__construct('config');
$this->barcode_lib = new Barcode_lib();
$this->sale_lib = new Sale_lib();
$this->receiving_lib = new receiving_lib();
$this->tax_lib = new Tax_lib();
$this->appconfig = model(Appconfig::class);
$this->attribute = model(Attribute::class);
$this->customer_rewards = model(Customer_rewards::class);
$this->dinner_table = model(Dinner_table::class);
$this->module = model(Module::class);
$this->stock_location = model(Stock_location::class);
$this->tax = model(Tax::class);
$this->config = config(OSPOS::class)->settings;
$this->db = Database::connect();
helper('security');
if (check_encryption()) {
$this->encrypter = Services::encrypter();
} else {
log_message('alert', 'Error preparing encryption key');
}
}
/**
* This function loads all the licenses starting with the first one being OSPOS one
*/
private function _licenses(): array //TODO: remove hungarian notation. Super long function. Perhaps we need to refactor out functions?
{
$i = 0;
$bower = false;
$composer = false;
$license = [];
$license[$i]['title'] = 'Open Source Point Of Sale ' . config('App')->application_version;
if (file_exists('license/LICENSE')) {
$license[$i]['text'] = file_get_contents('license/LICENSE', false, null, 0, 3000);
} else {
$license[$i]['text'] = 'LICENSE file must be in OSPOS license directory. You are not allowed to use OSPOS application until the distribution copy of LICENSE file is present.';
}
$dir = new DirectoryIterator('license'); // read all the files in the dir license
foreach ($dir as $fileinfo) { //TODO: $fileinfo doesn't match our variable naming convention
// license files must be in couples: .version (name & version) & .license (license text)
if ($fileinfo->isFile()) {
if ($fileinfo->getExtension() == 'version') {
++$i;
$basename = 'license/' . $fileinfo->getBasename('.version');
$license[$i]['title'] = file_get_contents($basename . '.version', false, null, 0, 100);
$license_text_file = $basename . '.license';
if (file_exists($license_text_file)) {
$license[$i]['text'] = file_get_contents($license_text_file, false, null, 0, 2000);
} else {
$license[$i]['text'] = $license_text_file . ' file is missing';
}
} elseif ($fileinfo->getBasename() == 'bower.LICENSES') {
// set a flag to indicate that the JS Plugin bower.LICENSES file is available and needs to be attached at the end
$bower = true;
} elseif ($fileinfo->getBasename() == 'composer.LICENSES') {
// set a flag to indicate that the composer.LICENSES file is available and needs to be attached at the end
$composer = true;
}
}
}
// attach the licenses from the LICENSES file generated by bower
if ($composer) {
++$i;
$license[$i]['title'] = 'Composer Libraries';
$license[$i]['text'] = '';
$file = file_get_contents('license/composer.LICENSES');
$array = json_decode($file, true);
foreach ($array as $key => $val) {
if (is_array($val) && $key == 'dependencies') {
foreach ($val as $key1 => $val1) {
if (is_array($val1)) {
$license[$i]['text'] .= "component: $key1\n"; //TODO: Duplicated Code
foreach ($val1 as $key2 => $val2) {
if (is_array($val2)) {
$license[$i]['text'] .= "$key2: ";
foreach ($val2 as $key3 => $val3) {
$license[$i]['text'] .= "$val3 ";
}
$license[$i]['text'] .= "\n";
} else {
$license[$i]['text'] .= "$key2: $val2\n";
}
}
$license[$i]['text'] .= "\n";
} else {
$license[$i]['text'] .= "$key1: $val1\n";
}
}
}
}
}
// attach the licenses from the LICENSES file generated by bower
if ($bower) {
++$i;
$license[$i]['title'] = 'JS Plugins';
$license[$i]['text'] = '';
$file = file_get_contents('license/bower.LICENSES');
$array = json_decode($file, true);
foreach ($array as $key => $val) {
if (is_array($val)) {
$license[$i]['text'] .= "component: $key\n"; //TODO: Duplicated Code.
foreach ($val as $key1 => $val1) {
if (is_array($val1)) {
$license[$i]['text'] .= "$key1: ";
foreach ($val1 as $key2 => $val2) {
$license[$i]['text'] .= "$val2 ";
}
$license[$i]['text'] .= '\n';
} else {
$license[$i]['text'] .= "$key1: $val1\n";
}
}
$license[$i]['text'] .= '\n';
}
}
}
return $license;
}
/**
* This function loads all the available themes in the dist/bootswatch directory
* @return array
*/
private function _themes(): array //TODO: Hungarian notation
{
$themes = [];
// read all themes in the dist folder
$dir = new DirectoryIterator('resources/bootswatch');
foreach ($dir as $dirinfo) { //TODO: $dirinfo doesn't follow naming convention
if ($dirinfo->isDir() && !$dirinfo->isDot() && $dirinfo->getFileName() != 'fonts') {
$file = $dirinfo->getFileName();
$themes[$file] = ucfirst($file);
}
}
asort($themes);
return $themes;
}
/**
*/
public function getIndex(): void
{
$data['stock_locations'] = $this->stock_location->get_all()->getResultArray();
$data['dinner_tables'] = $this->dinner_table->get_all()->getResultArray();
$data['customer_rewards'] = $this->customer_rewards->get_all()->getResultArray();
$data['support_barcode'] = $this->barcode_lib->get_list_barcodes();
$data['barcode_fonts'] = $this->barcode_lib->listfonts('fonts');
$data['logo_exists'] = $this->config['company_logo'] != '';
$data['line_sequence_options'] = $this->sale_lib->get_line_sequence_options();
$data['register_mode_options'] = $this->sale_lib->get_register_mode_options();
$data['invoice_type_options'] = $this->sale_lib->get_invoice_type_options();
$data['rounding_options'] = rounding_mode::get_rounding_options();
$data['tax_code_options'] = $this->tax_lib->get_tax_code_options();
$data['tax_category_options'] = $this->tax_lib->get_tax_category_options();
$data['tax_jurisdiction_options'] = $this->tax_lib->get_tax_jurisdiction_options();
$data['show_office_group'] = $this->module->get_show_office_group();
$data['currency_code'] = $this->config['currency_code'] ?? '';
$data['dbVersion'] = mysqli_get_server_info($this->db->getConnection());
//Load all the license statements, they are already XSS cleaned in the private function
$data['licenses'] = $this->_licenses();
//Load all the themes, already XSS cleaned in the private function
$data['themes'] = $this->_themes();
//General related fields
$image_allowed_types = ['jpg','jpeg','gif','svg','webp','bmp','png','tif','tiff'];
$data['image_allowed_types'] = array_combine($image_allowed_types, $image_allowed_types);
$data['selected_image_allowed_types'] = explode(',', $this->config['image_allowed_types']);
//Integrations Related fields
$data['mailchimp'] = [];
if (check_encryption()) { //TODO: Hungarian notation
if (!isset($this->encrypter)) {
helper('security');
$this->encrypter = Services::encrypter();
}
$data['mailchimp']['api_key'] = (isset($this->config['mailchimp_api_key']) && !empty($this->config['mailchimp_api_key']))
? $this->encrypter->decrypt($this->config['mailchimp_api_key'])
: '';
$data['mailchimp']['list_id'] = (isset($this->config['mailchimp_list_id']) && !empty($this->config['mailchimp_list_id']))
? $this->encrypter->decrypt($this->config['mailchimp_list_id'])
: '';
//Remove any backup of .env created by check_encryption()
remove_backup();
} else {
$data['mailchimp']['api_key'] = '';
$data['mailchimp']['list_id'] = '';
}
$data['mailchimp']['lists'] = $this->_mailchimp();
echo view('configs/manage', $data);
}
/**
* Saves company information. Used in app/Views/configs/info_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveInfo(): void
{
$upload_data = $this->upload_logo();
$upload_success = empty($upload_data['error']);
$batch_save_data = [
'company' => $this->request->getPost('company'),
'address' => $this->request->getPost('address'),
'phone' => $this->request->getPost('phone'),
'email' => strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL)),
'fax' => $this->request->getPost('fax'),
'website' => $this->request->getPost('website', FILTER_SANITIZE_URL),
'return_policy' => $this->request->getPost('return_policy')
];
if (!empty($upload_data['orig_name']) && $upload_data['raw_name']) {
$batch_save_data['company_logo'] = $upload_data['raw_name'] . '.' . $upload_data['file_ext'];
}
$result = $this->appconfig->batch_save($batch_save_data);
$success = $upload_success && $result;
$message = lang('Config.saved_' . ($success ? '' : 'un') . 'successfully');
$message = $upload_success ? $message : strip_tags($upload_data['error']);
echo json_encode(['success' => $success, 'message' => $message]);
}
/**
* @return array
*/
private function upload_logo(): array
{
$file = $this->request->getFile('company_logo');
if (!$file) {
return [];
}
helper(['form']);
$validation_rule = [
'company_logo' => [
'label' => 'Company logo',
'rules' => [
'uploaded[company_logo]',
'is_image[company_logo]',
'max_size[company_logo,1024]',
'mime_in[company_logo,image/png,image/jpg,image/jpeg,image/gif]',
'ext_in[company_logo,png,jpg,gif]',
'max_dims[company_logo,800,680]',
]
]
];
if (!$this->validate($validation_rule)) {
return (['error' => $this->validator->getError('company_logo')]);
}
$filename = $file->getClientName();
$info = pathinfo($filename);
$file_info = [
'orig_name' => $filename,
'raw_name' => $info['filename'],
'file_ext' => $file->guessExtension()
];
$file->move(FCPATH . 'uploads/', $file_info['raw_name'] . '.' . $file_info['file_ext'], true);
return ($file_info);
}
/**
* Saves general configuration. Used in app/Views/configs/general_config.php
*
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postSaveGeneral(): void
{
$batch_save_data = [
'theme' => $this->request->getPost('theme'),
'login_form' => $this->request->getPost('login_form'),
'default_sales_discount_type' => $this->request->getPost('default_sales_discount_type') != null,
'default_sales_discount' => parse_decimals($this->request->getPost('default_sales_discount')),
'default_receivings_discount_type' => $this->request->getPost('default_receivings_discount_type') != null,
'default_receivings_discount' => parse_decimals($this->request->getPost('default_receivings_discount')),
'enforce_privacy' => $this->request->getPost('enforce_privacy') != null,
'receiving_calculate_average_price' => $this->request->getPost('receiving_calculate_average_price') != null,
'lines_per_page' => $this->request->getPost('lines_per_page', FILTER_SANITIZE_NUMBER_INT),
'notify_horizontal_position' => $this->request->getPost('notify_horizontal_position'),
'notify_vertical_position' => $this->request->getPost('notify_vertical_position'),
'image_max_width' => $this->request->getPost('image_max_width', FILTER_SANITIZE_NUMBER_INT),
'image_max_height' => $this->request->getPost('image_max_height', FILTER_SANITIZE_NUMBER_INT),
'image_max_size' => $this->request->getPost('image_max_size', FILTER_SANITIZE_NUMBER_INT),
'image_allowed_types' => implode(',', $this->request->getPost('image_allowed_types')),
'gcaptcha_enable' => $this->request->getPost('gcaptcha_enable') != null,
'gcaptcha_secret_key' => $this->request->getPost('gcaptcha_secret_key'),
'gcaptcha_site_key' => $this->request->getPost('gcaptcha_site_key'),
'suggestions_first_column' => $this->request->getPost('suggestions_first_column'),
'suggestions_second_column' => $this->request->getPost('suggestions_second_column'),
'suggestions_third_column' => $this->request->getPost('suggestions_third_column'),
'giftcard_number' => $this->request->getPost('giftcard_number'),
'derive_sale_quantity' => $this->request->getPost('derive_sale_quantity') != null,
'multi_pack_enabled' => $this->request->getPost('multi_pack_enabled') != null,
'include_hsn' => $this->request->getPost('include_hsn') != null,
'category_dropdown' => $this->request->getPost('category_dropdown') != null
];
$this->module->set_show_office_group($this->request->getPost('show_office_group') != null);
if ($batch_save_data['category_dropdown'] == 1) {
$definition_data['definition_name'] = 'ospos_category';
$definition_data['definition_flags'] = 0;
$definition_data['definition_type'] = 'DROPDOWN';
$definition_data['definition_id'] = CATEGORY_DEFINITION_ID;
$definition_data['deleted'] = 0;
$this->attribute->save_definition($definition_data, CATEGORY_DEFINITION_ID);
} elseif ($batch_save_data['category_dropdown'] == NO_DEFINITION_ID) {
$this->attribute->delete_definition(CATEGORY_DEFINITION_ID);
}
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Checks a number against the currently selected locale. Used in app/Views/configs/locale_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckNumberLocale(): void
{
$number_locale = $this->request->getPost('number_locale');
$save_number_locale = $this->request->getPost('save_number_locale');
$fmt = new NumberFormatter($number_locale, NumberFormatter::CURRENCY);
if ($number_locale != $save_number_locale) {
$currency_symbol = $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
$currency_code = $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE);
$save_number_locale = $number_locale;
} else {
$currency_symbol = empty($this->request->getPost('currency_symbol')) ? $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL) : $this->request->getPost('currency_symbol');
$currency_code = empty($this->request->getPost('currency_code')) ? $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE) : $this->request->getPost('currency_code');
}
if ($this->request->getPost('thousands_separator') == 'false') {
$fmt->setTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '');
}
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $currency_symbol);
$number_local_example = $fmt->format(1234567890.12300);
echo json_encode([
'success' => $number_local_example != false,
'save_number_locale' => $save_number_locale,
'number_locale_example' => $number_local_example,
'currency_symbol' => $currency_symbol,
'currency_code' => $currency_code,
]);
}
/**
* Saves locale configuration. Used in app/Views/configs/locale_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveLocale(): void
{
$exploded = explode(":", $this->request->getPost('language'));
$batch_save_data = [
'currency_symbol' => $this->request->getPost('currency_symbol'),
'currency_code' => $this->request->getPost('currency_code'),
'language_code' => $exploded[0],
'language' => $exploded[1],
'timezone' => $this->request->getPost('timezone'),
'dateformat' => $this->request->getPost('dateformat'),
'timeformat' => $this->request->getPost('timeformat'),
'thousands_separator' => $this->request->getPost('thousands_separator') != null,
'number_locale' => $this->request->getPost('number_locale'),
'currency_decimals' => $this->request->getPost('currency_decimals', FILTER_SANITIZE_NUMBER_INT),
'tax_decimals' => $this->request->getPost('tax_decimals', FILTER_SANITIZE_NUMBER_INT),
'quantity_decimals' => $this->request->getPost('quantity_decimals', FILTER_SANITIZE_NUMBER_INT),
'country_codes' => htmlspecialchars($this->request->getPost('country_codes')),
'payment_options_order' => $this->request->getPost('payment_options_order'),
'date_or_time_format' => $this->request->getPost('date_or_time_format') != null,
'cash_decimals' => $this->request->getPost('cash_decimals', FILTER_SANITIZE_NUMBER_INT),
'cash_rounding_code' => $this->request->getPost('cash_rounding_code'),
'financial_year' => $this->request->getPost('financial_year', FILTER_SANITIZE_NUMBER_INT)
];
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves email configuration. Used in app/Views/configs/email_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveEmail(): void
{
$password = '';
if (check_encryption() && !empty($this->request->getPost('smtp_pass'))) {
$password = $this->encrypter->encrypt($this->request->getPost('smtp_pass'));
}
$batch_save_data = [
'protocol' => $this->request->getPost('protocol'),
'mailpath' => $this->request->getPost('mailpath'),
'smtp_host' => $this->request->getPost('smtp_host'),
'smtp_user' => $this->request->getPost('smtp_user'),
'smtp_pass' => $password,
'smtp_port' => $this->request->getPost('smtp_port', FILTER_SANITIZE_NUMBER_INT),
'smtp_timeout' => $this->request->getPost('smtp_timeout', FILTER_SANITIZE_NUMBER_INT),
'smtp_crypto' => $this->request->getPost('smtp_crypto')
];
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves SMS message configuration. Used in app/Views/configs/message_config.php.
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveMessage(): void
{
$password = '';
if (check_encryption() && !empty($this->request->getPost('msg_pwd'))) {
$password = $this->encrypter->encrypt($this->request->getPost('msg_pwd'));
}
$batch_save_data = [
'msg_msg' => $this->request->getPost('msg_msg'),
'msg_uid' => $this->request->getPost('msg_uid'),
'msg_pwd' => $password,
'msg_src' => $this->request->getPost('msg_src')
];
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* This function fetches all the available lists from Mailchimp for the given API key
*/
private function _mailchimp(string $api_key = ''): array //TODO: Hungarian notation
{
$mailchimp_lib = new Mailchimp_lib(['api_key' => $api_key]);
$result = [];
$lists = $mailchimp_lib->getLists();
if ($lists !== false) {
if (is_array($lists) && !empty($lists['lists']) && is_array($lists['lists'])) {
foreach ($lists['lists'] as $list) {
$result[$list['id']] = $list['name'] . ' [' . $list['stats']['member_count'] . ']';
}
}
}
return $result;
}
/**
* Gets Mailchimp lists when a valid API key is inserted. Used in app/Views/configs/integrations_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckMailchimpApiKey(): void
{
$lists = $this->_mailchimp($this->request->getPost('mailchimp_api_key'));
$success = count($lists) > 0;
echo json_encode([
'success' => $success,
'message' => lang('Config.mailchimp_key_' . ($success ? '' : 'un') . 'successfully'),
'mailchimp_lists' => $lists
]);
}
/**
* Saves Mailchimp configuration. Used in app/Views/configs/integrations_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveMailchimp(): void
{
$api_key = '';
$list_id = '';
if (check_encryption()) {
$api_key_unencrypted = $this->request->getPost('mailchimp_api_key');
if (!empty($api_key_unencrypted)) {
$api_key = $this->encrypter->encrypt($api_key_unencrypted);
}
$list_id_unencrypted = $this->request->getPost('mailchimp_list_id');
if (!empty($list_id_unencrypted)) {
$list_id = $this->encrypter->encrypt($list_id_unencrypted);
}
}
$batch_save_data = ['mailchimp_api_key' => $api_key, 'mailchimp_list_id' => $list_id];
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Gets all stock locations. Used in app/Views/configs/stock_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function getStockLocations(): void
{
$stock_locations = $this->stock_location->get_all()->getResultArray();
echo view('partial/stock_locations', ['stock_locations' => $stock_locations]);
}
/**
* @return void
*/
public function getDinnerTables(): void
{
$dinner_tables = $this->dinner_table->get_all()->getResultArray();
echo view('partial/dinner_tables', ['dinner_tables' => $dinner_tables]);
}
/**
* Gets all tax categories.
*
* @return void
*/
public function ajax_tax_categories(): void //TODO: Is this function called anywhere in the code?
{
$tax_categories = $this->tax->get_all_tax_categories()->getResultArray();
echo view('partial/tax_categories', ['tax_categories' => $tax_categories]);
}
/**
* Gets all customer rewards. Used in app/Views/configs/reward_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function getCustomerRewards(): void
{
$customer_rewards = $this->customer_rewards->get_all()->getResultArray();
echo view('partial/customer_rewards', ['customer_rewards' => $customer_rewards]);
}
/**
* @return void
*/
private function _clear_session_state(): void //TODO: Hungarian notation
{
$this->sale_lib->clear_sale_location();
$this->sale_lib->clear_table();
$this->sale_lib->clear_all();
$this->receiving_lib = new Receiving_lib();
$this->receiving_lib->clear_stock_source();
$this->receiving_lib->clear_stock_destination();
$this->receiving_lib->clear_all();
}
/**
* Saves stock locations. Used in app/Views/configs/stock_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSaveLocations(): void
{
$this->db->transStart();
$not_to_delete = [];
foreach ($this->request->getPost() as $key => $value) {
if (str_contains($key, 'stock_location')) {
// save or update
foreach ($value as $location_id => $location_name) {
$location_data = ['location_name' => $location_name];
if ($this->stock_location->save_value($location_data, $location_id)) {
$location_id = $this->stock_location->get_location_id($location_name);
$not_to_delete[] = $location_id;
$this->_clear_session_state();
}
}
}
}
// all locations not available in post will be deleted now
$deleted_locations = $this->stock_location->get_all()->getResultArray();
foreach ($deleted_locations as $location => $location_data) {
if (!in_array($location_data['location_id'], $not_to_delete)) {
$this->stock_location->delete($location_data['location_id']);
}
}
$this->db->transComplete();
$success = $this->db->transStatus();
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves all dinner tables. Used in app/Views/configs/table_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveTables(): void
{
$this->db->transStart();
$dinner_table_enable = $this->request->getPost('dinner_table_enable') != null;
$this->appconfig->save(['dinner_table_enable' => $dinner_table_enable]);
if ($dinner_table_enable) {
$not_to_delete = [];
foreach ($this->request->getPost() as $key => $value) { //TODO: Not sure if this is the best way to filter the array
if (strstr($key, 'dinner_table') && $key != 'dinner_table_enable') {
$dinner_table_id = preg_replace("/.*?_(\d+)$/", "$1", $key);
$not_to_delete[] = $dinner_table_id;
// save or update
$table_data = ['name' => $value];
if ($this->dinner_table->save_value($table_data, $dinner_table_id)) {
$this->_clear_session_state(); //TODO: Remove hungarian notation.
}
}
}
// all tables not available in post will be deleted now
$deleted_tables = $this->dinner_table->get_all()->getResultArray();
foreach ($deleted_tables as $dinner_tables => $table) {
if (!in_array($table['dinner_table_id'], $not_to_delete)) {
$this->dinner_table->delete($table['dinner_table_id']);
}
}
}
$this->db->transComplete();
$success = $this->db->transStatus();
echo json_encode(['success' => $success,'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves tax configuration. Used in app/Views/configs/tax_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveTax(): void
{
$default_tax_1_rate = $this->request->getPost('default_tax_1_rate');
$default_tax_2_rate = $this->request->getPost('default_tax_2_rate');
$batch_save_data = [
'default_tax_1_rate' => parse_tax(filter_var($default_tax_1_rate, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)),
'default_tax_1_name' => $this->request->getPost('default_tax_1_name'),
'default_tax_2_rate' => parse_tax(filter_var($default_tax_2_rate, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)),
'default_tax_2_name' => $this->request->getPost('default_tax_2_name'),
'tax_included' => $this->request->getPost('tax_included') != null,
'use_destination_based_tax' => $this->request->getPost('use_destination_based_tax') != null,
'default_tax_code' => $this->request->getPost('default_tax_code'),
'default_tax_category' => $this->request->getPost('default_tax_category'),
'default_tax_jurisdiction' => $this->request->getPost('default_tax_jurisdiction'),
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT)
];
$success = $this->appconfig->batch_save($batch_save_data);
$message = lang('Config.saved_' . ($success ? '' : 'un') . 'successfully');
echo json_encode(['success' => $success, 'message' => $message]);
}
/**
* Saves customer rewards configuration. Used in app/Views/configs/reward_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveRewards(): void
{
$this->db->transStart();
$customer_reward_enable = $this->request->getPost('customer_reward_enable') != null;
$this->appconfig->save(['customer_reward_enable' => $customer_reward_enable]);
if ($customer_reward_enable) {
$not_to_delete = [];
$array_save = [];
foreach ($this->request->getPost() as $key => $value) {
if (strstr($key, 'customer_reward') && $key != 'customer_reward_enable') {
$customer_reward_id = preg_replace("/.*?_(\d+)$/", "$1", $key);
$not_to_delete[] = $customer_reward_id;
$array_save[$customer_reward_id]['package_name'] = $value;
} elseif (str_contains($key, 'reward_points')) {
$customer_reward_id = preg_replace("/.*?_(\d+)$/", "$1", $key);
$array_save[$customer_reward_id]['points_percent'] = $value;
}
}
if (!empty($array_save)) {
foreach ($array_save as $key => $value) {
// save or update
$package_data = ['package_name' => $value['package_name'], 'points_percent' => $value['points_percent']];
$this->customer_rewards->save_value($package_data, $key); //TODO: reflection exception
}
}
// all packages not available in post will be deleted now
$deleted_packages = $this->customer_rewards->get_all()->getResultArray();
foreach ($deleted_packages as $customer_rewards => $reward_category) {
if (!in_array($reward_category['package_id'], $not_to_delete)) {
$this->customer_rewards->delete($reward_category['package_id']);
}
}
}
$this->db->transComplete();
$success = $this->db->transStatus();
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves barcode configuration. Used in app/Views/configs/barcode_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveBarcode(): void
{
$batch_save_data = [
'barcode_type' => $this->request->getPost('barcode_type'),
'barcode_width' => $this->request->getPost('barcode_width', FILTER_SANITIZE_NUMBER_INT),
'barcode_height' => $this->request->getPost('barcode_height', FILTER_SANITIZE_NUMBER_INT),
'barcode_font' => $this->request->getPost('barcode_font'),
'barcode_font_size' => $this->request->getPost('barcode_font_size', FILTER_SANITIZE_NUMBER_INT),
'barcode_first_row' => $this->request->getPost('barcode_first_row'),
'barcode_second_row' => $this->request->getPost('barcode_second_row'),
'barcode_third_row' => $this->request->getPost('barcode_third_row'),
'barcode_num_in_row' => $this->request->getPost('barcode_num_in_row', FILTER_SANITIZE_NUMBER_INT),
'barcode_page_width' => $this->request->getPost('barcode_page_width', FILTER_SANITIZE_NUMBER_INT),
'barcode_page_cellspacing' => $this->request->getPost('barcode_page_cellspacing', FILTER_SANITIZE_NUMBER_INT),
'barcode_generate_if_empty' => $this->request->getPost('barcode_generate_if_empty') != null,
'allow_duplicate_barcodes' => $this->request->getPost('allow_duplicate_barcodes') != null,
'barcode_content' => $this->request->getPost('barcode_content'),
'barcode_formats' => json_encode($this->request->getPost('barcode_formats'))
];
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves receipt configuration. Used in app/Views/configs/receipt_config.php.
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveReceipt(): void
{
$batch_save_data = [
'receipt_template' => $this->request->getPost('receipt_template'),
'receipt_font_size' => $this->request->getPost('receipt_font_size', FILTER_SANITIZE_NUMBER_INT),
'print_delay_autoreturn' => $this->request->getPost('print_delay_autoreturn', FILTER_SANITIZE_NUMBER_INT),
'email_receipt_check_behaviour' => $this->request->getPost('email_receipt_check_behaviour'),
'print_receipt_check_behaviour' => $this->request->getPost('print_receipt_check_behaviour'),
'receipt_show_company_name' => $this->request->getPost('receipt_show_company_name') != null,
'receipt_show_taxes' => $this->request->getPost('receipt_show_taxes') != null,
'receipt_show_tax_ind' => $this->request->getPost('receipt_show_tax_ind') != null,
'receipt_show_total_discount' => $this->request->getPost('receipt_show_total_discount') != null,
'receipt_show_description' => $this->request->getPost('receipt_show_description') != null,
'receipt_show_serialnumber' => $this->request->getPost('receipt_show_serialnumber') != null,
'print_silently' => $this->request->getPost('print_silently') != null,
'print_header' => $this->request->getPost('print_header') != null,
'print_footer' => $this->request->getPost('print_footer') != null,
'print_top_margin' => $this->request->getPost('print_top_margin', FILTER_SANITIZE_NUMBER_INT),
'print_left_margin' => $this->request->getPost('print_left_margin', FILTER_SANITIZE_NUMBER_INT),
'print_bottom_margin' => $this->request->getPost('print_bottom_margin', FILTER_SANITIZE_NUMBER_INT),
'print_right_margin' => $this->request->getPost('print_right_margin', FILTER_SANITIZE_NUMBER_INT)
];
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves invoice configuration. Used in app/Views/configs/invoice_config.php.
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveInvoice(): void
{
$batch_save_data = [
'invoice_enable' => $this->request->getPost('invoice_enable') != null,
'sales_invoice_format' => $this->request->getPost('sales_invoice_format'),
'sales_quote_format' => $this->request->getPost('sales_quote_format'),
'recv_invoice_format' => $this->request->getPost('recv_invoice_format'),
'invoice_default_comments' => $this->request->getPost('invoice_default_comments'),
'invoice_email_message' => $this->request->getPost('invoice_email_message'),
'line_sequence' => $this->request->getPost('line_sequence'),
'last_used_invoice_number' => $this->request->getPost('last_used_invoice_number', FILTER_SANITIZE_NUMBER_INT),
'last_used_quote_number' => $this->request->getPost('last_used_quote_number', FILTER_SANITIZE_NUMBER_INT),
'quote_default_comments' => $this->request->getPost('quote_default_comments'),
'work_order_enable' => $this->request->getPost('work_order_enable') != null,
'work_order_format' => $this->request->getPost('work_order_format'),
'last_used_work_order_number' => $this->request->getPost('last_used_work_order_number', FILTER_SANITIZE_NUMBER_INT),
'invoice_type' => $this->request->getPost('invoice_type')
];
$success = $this->appconfig->batch_save($batch_save_data);
// Update the register mode with the latest change so that if the user
// switches immediately back to the register the mode reflects the change
if ($success) {
if ($this->config['invoice_enable']) {
$this->sale_lib->set_mode($this->config['default_register_mode']);
} else {
$this->sale_lib->set_mode('sale');
}
}
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Removes the company logo from the database. Used in app/Views/configs/info_config.php.
*
* @return void
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postRemoveLogo(): void
{
$success = $this->appconfig->save(['company_logo' => '']);
echo json_encode(['success' => $success]);
}
}