mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-05-30 11:14:59 -04:00
Compare commits
1 Commits
WebShells-
...
feature/pe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fefd34864 |
@@ -246,7 +246,7 @@ class Attributes extends Secure_Controller
|
|||||||
$data['definition_group'][''] = lang('Common.none_selected_text');
|
$data['definition_group'][''] = lang('Common.none_selected_text');
|
||||||
$data['definition_info'] = $info;
|
$data['definition_info'] = $info;
|
||||||
|
|
||||||
$show_all = Attribute::SHOW_IN_ITEMS | Attribute::SHOW_IN_RECEIVINGS | Attribute::SHOW_IN_SALES;
|
$show_all = Attribute::SHOW_IN_ITEMS | Attribute::SHOW_IN_RECEIVINGS | Attribute::SHOW_IN_SALES | Attribute::SHOW_IN_SEARCH | Attribute::SHOW_IN_CUSTOMERS | Attribute::SHOW_IN_EMPLOYEES | Attribute::SHOW_IN_SUPPLIERS;
|
||||||
$data['definition_flags'] = $this->get_attributes($show_all);
|
$data['definition_flags'] = $this->get_attributes($show_all);
|
||||||
$selected_flags = $info->definition_flags === '' ? $show_all : $info->definition_flags;
|
$selected_flags = $info->definition_flags === '' ? $show_all : $info->definition_flags;
|
||||||
$data['selected_definition_flags'] = $this->get_attributes($selected_flags);
|
$data['selected_definition_flags'] = $this->get_attributes($selected_flags);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace App\Controllers;
|
namespace App\Controllers;
|
||||||
|
|
||||||
use App\Libraries\Mailchimp_lib;
|
use App\Libraries\Mailchimp_lib;
|
||||||
|
use App\Models\Attribute;
|
||||||
use App\Models\Customer;
|
use App\Models\Customer;
|
||||||
use App\Models\Customer_rewards;
|
use App\Models\Customer_rewards;
|
||||||
use App\Models\Tax_code;
|
use App\Models\Tax_code;
|
||||||
@@ -15,34 +15,31 @@ use stdClass;
|
|||||||
|
|
||||||
class Customers extends Persons
|
class Customers extends Persons
|
||||||
{
|
{
|
||||||
private string $_list_id;
|
private string $listId;
|
||||||
private Mailchimp_lib $mailchimp_lib;
|
private Mailchimp_lib $mailchimpLib;
|
||||||
private Customer_rewards $customer_rewards;
|
private Customer_rewards $customerRewards;
|
||||||
private Customer $customer;
|
private Customer $customer;
|
||||||
private Tax_code $tax_code;
|
private Tax_code $taxCode;
|
||||||
private array $config;
|
private array $appConfig;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct('customers');
|
parent::__construct('customers');
|
||||||
$this->mailchimp_lib = new Mailchimp_lib();
|
$this->mailchimpLib = new Mailchimp_lib();
|
||||||
$this->customer_rewards = model(Customer_rewards::class);
|
$this->customerRewards = model(Customer_rewards::class);
|
||||||
$this->customer = model(Customer::class);
|
$this->customer = model(Customer::class);
|
||||||
$this->tax_code = model(Tax_code::class);
|
$this->taxCode = model(Tax_code::class);
|
||||||
$this->config = config(OSPOS::class)->settings;
|
$this->appConfig = config(OSPOS::class)->settings;
|
||||||
|
|
||||||
$encrypter = Services::encrypter();
|
$encrypter = Services::encrypter();
|
||||||
|
|
||||||
if (!empty($this->config['mailchimp_list_id'])) {
|
if (!empty($this->appConfig['mailchimp_list_id'])) {
|
||||||
$this->_list_id = $encrypter->decrypt($this->config['mailchimp_list_id']);
|
$this->listId = $encrypter->decrypt($this->appConfig['mailchimp_list_id']);
|
||||||
} else {
|
} else {
|
||||||
$this->_list_id = '';
|
$this->listId = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getIndex(): string
|
public function getIndex(): string
|
||||||
{
|
{
|
||||||
$data['table_headers'] = get_customer_manage_table_headers();
|
$data['table_headers'] = get_customer_manage_table_headers();
|
||||||
@@ -50,19 +47,13 @@ class Customers extends Persons
|
|||||||
return view('people/manage', $data);
|
return view('people/manage', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getRow(int $rowId): ResponseInterface
|
||||||
* Gets one row for a customer manage table. This is called using AJAX to update one row.
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function getRow(int $row_id): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$person = $this->customer->get_info($row_id);
|
$person = $this->customer->get_info($rowId);
|
||||||
|
|
||||||
// Retrieve the total amount the customer spent so far together with min, max and average values
|
$stats = $this->customer->get_stats($person->person_id);
|
||||||
$stats = $this->customer->get_stats($person->person_id); // TODO: This and the next 11 lines are duplicated in search(). Extract a method.
|
|
||||||
|
|
||||||
if (empty($stats)) {
|
if (empty($stats)) {
|
||||||
// Create object with empty properties.
|
|
||||||
$stats = new stdClass();
|
$stats = new stdClass();
|
||||||
$stats->total = 0;
|
$stats->total = 0;
|
||||||
$stats->min = 0;
|
$stats->min = 0;
|
||||||
@@ -72,17 +63,11 @@ class Customers extends Persons
|
|||||||
$stats->quantity = 0;
|
$stats->quantity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data_row = get_customer_data_row($person, $stats);
|
$dataRow = get_customer_data_row($person, $stats);
|
||||||
|
|
||||||
return $this->response->setJSON($data_row);
|
return $this->response->setJSON($dataRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns customer table data rows. This will be called with AJAX.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getSearch(): ResponseInterface
|
public function getSearch(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('search');
|
$search = $this->request->getGet('search');
|
||||||
@@ -92,15 +77,13 @@ class Customers extends Persons
|
|||||||
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
|
|
||||||
$customers = $this->customer->search($search, $limit, $offset, $sort, $order);
|
$customers = $this->customer->search($search, $limit, $offset, $sort, $order);
|
||||||
$total_rows = $this->customer->get_found_rows($search);
|
$totalRows = $this->customer->get_found_rows($search);
|
||||||
|
|
||||||
$data_rows = [];
|
$dataRows = [];
|
||||||
|
|
||||||
foreach ($customers->getResult() as $person) {
|
foreach ($customers->getResult() as $person) {
|
||||||
// Retrieve the total amount the customer spent so far together with min, max and average values
|
$stats = $this->customer->get_stats($person->person_id);
|
||||||
$stats = $this->customer->get_stats($person->person_id); // TODO: duplicated... see above
|
|
||||||
if (empty($stats)) {
|
if (empty($stats)) {
|
||||||
// Create object with empty properties.
|
|
||||||
$stats = new stdClass();
|
$stats = new stdClass();
|
||||||
$stats->total = 0;
|
$stats->total = 0;
|
||||||
$stats->min = 0;
|
$stats->min = 0;
|
||||||
@@ -110,16 +93,12 @@ class Customers extends Persons
|
|||||||
$stats->quantity = 0;
|
$stats->quantity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data_rows[] = get_customer_data_row($person, $stats);
|
$dataRows[] = get_customer_data_row($person, $stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
|
return $this->response->setJSON(['total' => $totalRows, 'rows' => $dataRows]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives search suggestions based on what is being searched for
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function getSuggest(): ResponseInterface
|
public function getSuggest(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('term');
|
$search = $this->request->getGet('term');
|
||||||
@@ -128,10 +107,7 @@ class Customers extends Persons
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function suggestSearch(): ResponseInterface
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function suggest_search(): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('term');
|
$search = $this->request->getGet('term');
|
||||||
$suggestions = $this->customer->get_search_suggestions($search, 25, false);
|
$suggestions = $this->customer->get_search_suggestions($search, 25, false);
|
||||||
@@ -139,16 +115,11 @@ class Customers extends Persons
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getView(int $customerId = NEW_ENTRY): string
|
||||||
* Loads the customer edit form
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getView(int $customer_id = NEW_ENTRY): string
|
|
||||||
{
|
{
|
||||||
// Set default values
|
if ($customerId == null) $customerId = NEW_ENTRY;
|
||||||
if ($customer_id == null) $customer_id = NEW_ENTRY;
|
|
||||||
|
|
||||||
$info = $this->customer->get_info($customer_id);
|
$info = $this->customer->get_info($customerId);
|
||||||
foreach (get_object_vars($info) as $property => $value) {
|
foreach (get_object_vars($info) as $property => $value) {
|
||||||
$info->$property = $value;
|
$info->$property = $value;
|
||||||
}
|
}
|
||||||
@@ -159,28 +130,27 @@ class Customers extends Persons
|
|||||||
$data['person_info']->employee_id = $this->employee->get_logged_in_employee_info()->person_id;
|
$data['person_info']->employee_id = $this->employee->get_logged_in_employee_info()->person_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$employee_info = $this->employee->get_info($info->employee_id);
|
$employeeInfo = $this->employee->get_info($info->employee_id);
|
||||||
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
|
$data['employee'] = $employeeInfo->first_name . ' ' . $employeeInfo->last_name;
|
||||||
|
|
||||||
$tax_code_info = $this->tax_code->get_info($info->sales_tax_code_id);
|
$taxCodeInfo = $this->taxCode->get_info($info->sales_tax_code_id);
|
||||||
|
|
||||||
if ($tax_code_info->tax_code != null) {
|
if ($taxCodeInfo->tax_code != null) {
|
||||||
$data['sales_tax_code_label'] = $tax_code_info->tax_code . ' ' . $tax_code_info->tax_code_name;
|
$data['sales_tax_code_label'] = $taxCodeInfo->tax_code . ' ' . $taxCodeInfo->tax_code_name;
|
||||||
} else {
|
} else {
|
||||||
$data['sales_tax_code_label'] = '';
|
$data['sales_tax_code_label'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$packages = ['' => lang('Items.none')];
|
$packages = ['' => lang('Items.none')];
|
||||||
foreach ($this->customer_rewards->get_all()->getResultArray() as $row) {
|
foreach ($this->customerRewards->get_all()->getResultArray() as $row) {
|
||||||
$packages[$row['package_id']] = $row['package_name'];
|
$packages[$row['package_id']] = $row['package_name'];
|
||||||
}
|
}
|
||||||
$data['packages'] = $packages;
|
$data['packages'] = $packages;
|
||||||
$data['selected_package'] = $info->package_id;
|
$data['selected_package'] = $info->package_id;
|
||||||
|
|
||||||
$data['use_destination_based_tax'] = $this->config['use_destination_based_tax'];
|
$data['use_destination_based_tax'] = $this->appConfig['use_destination_based_tax'];
|
||||||
|
|
||||||
// Retrieve the total amount the customer spent so far together with min, max and average values
|
$stats = $this->customer->get_stats($customerId);
|
||||||
$stats = $this->customer->get_stats($customer_id);
|
|
||||||
if (!empty($stats)) {
|
if (!empty($stats)) {
|
||||||
foreach (get_object_vars($stats) as $property => $value) {
|
foreach (get_object_vars($stats) as $property => $value) {
|
||||||
$info->$property = $value;
|
$info->$property = $value;
|
||||||
@@ -188,14 +158,11 @@ class Customers extends Persons
|
|||||||
$data['stats'] = $stats;
|
$data['stats'] = $stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the info from Mailchimp only if there is an email address assigned
|
|
||||||
if (!empty($info->email)) {
|
if (!empty($info->email)) {
|
||||||
// Collect Mailchimp customer info
|
if (($mailchimpInfo = $this->mailchimpLib->getMemberInfo($this->listId, $info->email)) !== false) {
|
||||||
if (($mailchimp_info = $this->mailchimp_lib->getMemberInfo($this->_list_id, $info->email)) !== false) {
|
$data['mailchimp_info'] = $mailchimpInfo;
|
||||||
$data['mailchimp_info'] = $mailchimp_info;
|
|
||||||
|
|
||||||
// Collect customer Mailchimp emails activities (stats)
|
if (($activities = $this->mailchimpLib->getMemberActivity($this->listId, $info->email)) !== false) {
|
||||||
if (($activities = $this->mailchimp_lib->getMemberActivity($this->_list_id, $info->email)) !== false) {
|
|
||||||
if (array_key_exists('activity', $activities)) {
|
if (array_key_exists('activity', $activities)) {
|
||||||
$open = 0;
|
$open = 0;
|
||||||
$unopen = 0;
|
$unopen = 0;
|
||||||
@@ -235,22 +202,25 @@ class Customers extends Persons
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts/updates a customer
|
* Gets person attributes for a customer (AJAX)
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
*/
|
||||||
public function postSave(int $customer_id = NEW_ENTRY): ResponseInterface
|
public function getAttributes(int $customerId = NEW_ENTRY): string
|
||||||
{
|
{
|
||||||
$first_name = $this->request->getPost('first_name');
|
return $this->getPersonAttributes($customerId, Attribute::SHOW_IN_CUSTOMERS);
|
||||||
$last_name = $this->request->getPost('last_name');
|
}
|
||||||
|
|
||||||
|
public function postSave(int $customerId = NEW_ENTRY): ResponseInterface
|
||||||
|
{
|
||||||
|
$firstName = $this->request->getPost('first_name');
|
||||||
|
$lastName = $this->request->getPost('last_name');
|
||||||
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
||||||
|
|
||||||
// Format first and last name properly
|
$firstName = $this->nameize($firstName);
|
||||||
$first_name = $this->nameize($first_name);
|
$lastName = $this->nameize($lastName);
|
||||||
$last_name = $this->nameize($last_name);
|
|
||||||
|
|
||||||
$person_data = [
|
$personData = [
|
||||||
'first_name' => $first_name,
|
'first_name' => $firstName,
|
||||||
'last_name' => $last_name,
|
'last_name' => $lastName,
|
||||||
'gender' => $this->request->getPost('gender', FILTER_SANITIZE_NUMBER_INT),
|
'gender' => $this->request->getPost('gender', FILTER_SANITIZE_NUMBER_INT),
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'phone_number' => $this->request->getPost('phone_number'),
|
'phone_number' => $this->request->getPost('phone_number'),
|
||||||
@@ -263,9 +233,9 @@ class Customers extends Persons
|
|||||||
'comments' => $this->request->getPost('comments')
|
'comments' => $this->request->getPost('comments')
|
||||||
];
|
];
|
||||||
|
|
||||||
$date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $this->request->getPost('date'));
|
$dateFormatter = date_create_from_format($this->appConfig['dateformat'] . ' ' . $this->appConfig['timeformat'], $this->request->getPost('date'));
|
||||||
|
|
||||||
$customer_data = [
|
$customerData = [
|
||||||
'consent' => $this->request->getPost('consent') != null,
|
'consent' => $this->request->getPost('consent') != null,
|
||||||
'account_number' => $this->request->getPost('account_number') == '' ? null : $this->request->getPost('account_number'),
|
'account_number' => $this->request->getPost('account_number') == '' ? null : $this->request->getPost('account_number'),
|
||||||
'tax_id' => $this->request->getPost('tax_id'),
|
'tax_id' => $this->request->getPost('tax_id'),
|
||||||
@@ -274,68 +244,57 @@ class Customers extends Persons
|
|||||||
'discount_type' => $this->request->getPost('discount_type') == null ? PERCENT : $this->request->getPost('discount_type', FILTER_SANITIZE_NUMBER_INT),
|
'discount_type' => $this->request->getPost('discount_type') == null ? PERCENT : $this->request->getPost('discount_type', FILTER_SANITIZE_NUMBER_INT),
|
||||||
'package_id' => $this->request->getPost('package_id') == '' ? null : $this->request->getPost('package_id'),
|
'package_id' => $this->request->getPost('package_id') == '' ? null : $this->request->getPost('package_id'),
|
||||||
'taxable' => $this->request->getPost('taxable') != null,
|
'taxable' => $this->request->getPost('taxable') != null,
|
||||||
'date' => $date_formatter->format('Y-m-d H:i:s'),
|
'date' => $dateFormatter->format('Y-m-d H:i:s'),
|
||||||
'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT),
|
'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT),
|
||||||
'sales_tax_code_id' => $this->request->getPost('sales_tax_code_id') == '' ? null : $this->request->getPost('sales_tax_code_id', FILTER_SANITIZE_NUMBER_INT)
|
'sales_tax_code_id' => $this->request->getPost('sales_tax_code_id') == '' ? null : $this->request->getPost('sales_tax_code_id', FILTER_SANITIZE_NUMBER_INT)
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->customer->save_customer($person_data, $customer_data, $customer_id)) {
|
if ($this->customer->save_customer($personData, $customerData, $customerId)) {
|
||||||
// Save customer to Mailchimp selected list // TODO: addOrUpdateMember should be refactored. Potentially pass an array or object instead of 6 parameters.
|
$personId = $customerId == NEW_ENTRY ? $customerData['person_id'] : $customerId;
|
||||||
$mailchimp_status = $this->request->getPost('mailchimp_status');
|
$this->savePersonAttributes($personId, Attribute::SHOW_IN_CUSTOMERS);
|
||||||
$this->mailchimp_lib->addOrUpdateMember(
|
|
||||||
$this->_list_id,
|
$mailchimpStatus = $this->request->getPost('mailchimp_status');
|
||||||
|
$this->mailchimpLib->addOrUpdateMember(
|
||||||
|
$this->listId,
|
||||||
$email,
|
$email,
|
||||||
$first_name,
|
$firstName,
|
||||||
$last_name,
|
$lastName,
|
||||||
$mailchimp_status == null ? "" : $mailchimp_status,
|
$mailchimpStatus == null ? "" : $mailchimpStatus,
|
||||||
['vip' => $this->request->getPost('mailchimp_vip') != null]
|
['vip' => $this->request->getPost('mailchimp_vip') != null]
|
||||||
);
|
);
|
||||||
|
|
||||||
// New customer
|
if ($customerId == NEW_ENTRY) {
|
||||||
if ($customer_id == NEW_ENTRY) {
|
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Customers.successful_adding') . ' ' . $first_name . ' ' . $last_name,
|
'message' => lang('Customers.successful_adding') . ' ' . $firstName . ' ' . $lastName,
|
||||||
'id' => $customer_data['person_id']
|
'id' => $customerData['person_id']
|
||||||
]);
|
]);
|
||||||
} else { // Existing customer
|
} else {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Customers.successful_updating') . ' ' . $first_name . ' ' . $last_name,
|
'message' => lang('Customers.successful_updating') . ' ' . $firstName . ' ' . $lastName,
|
||||||
'id' => $customer_id
|
'id' => $customerId
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else { // Failure
|
} else {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => lang('Customers.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
|
'message' => lang('Customers.error_adding_updating') . ' ' . $firstName . ' ' . $lastName,
|
||||||
'id' => NEW_ENTRY
|
'id' => NEW_ENTRY
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies if an email address already exists. Used in app/Views/customers/form.php
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @noinspection PhpUnused
|
|
||||||
*/
|
|
||||||
public function postCheckEmail(): ResponseInterface
|
public function postCheckEmail(): ResponseInterface
|
||||||
{
|
{
|
||||||
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
||||||
$person_id = $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT);
|
$personId = $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT);
|
||||||
|
|
||||||
$exists = $this->customer->check_email_exists($email, $person_id);
|
$exists = $this->customer->check_email_exists($email, $personId);
|
||||||
|
|
||||||
return $this->response->setJSON(!$exists ? 'true' : 'false');
|
return $this->response->setJSON(!$exists ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies if an account number already exists. Used in app/Views/customers/form.php
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @noinspection PhpUnused
|
|
||||||
*/
|
|
||||||
public function postCheckAccountNumber(): ResponseInterface
|
public function postCheckAccountNumber(): ResponseInterface
|
||||||
{
|
{
|
||||||
$exists = $this->customer->check_account_number_exists($this->request->getPost('account_number'), $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT));
|
$exists = $this->customer->check_account_number_exists($this->request->getPost('account_number'), $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT));
|
||||||
@@ -343,27 +302,22 @@ class Customers extends Persons
|
|||||||
return $this->response->setJSON(!$exists ? 'true' : 'false');
|
return $this->response->setJSON(!$exists ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This deletes customers from the customers table
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function postDelete(): ResponseInterface
|
public function postDelete(): ResponseInterface
|
||||||
{
|
{
|
||||||
$customers_to_delete = $this->request->getPost('ids');
|
$customersToDelete = $this->request->getPost('ids');
|
||||||
$customers_info = $this->customer->get_multiple_info($customers_to_delete);
|
$customersInfo = $this->customer->get_multiple_info($customersToDelete);
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
|
|
||||||
foreach ($customers_info->getResult() as $info) {
|
foreach ($customersInfo->getResult() as $info) {
|
||||||
if ($this->customer->delete($info->person_id)) {
|
if ($this->customer->delete($info->person_id)) {
|
||||||
// remove customer from Mailchimp selected list
|
$this->mailchimpLib->removeMember($this->listId, $info->email);
|
||||||
$this->mailchimp_lib->removeMember($this->_list_id, $info->email);
|
|
||||||
|
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($count == count($customers_to_delete)) {
|
if ($count == count($customersToDelete)) {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Customers.successful_deleted') . ' ' . $count . ' ' . lang('Customers.one_or_multiple')
|
'message' => lang('Customers.successful_deleted') . ' ' . $count . ' ' . lang('Customers.one_or_multiple')
|
||||||
@@ -373,12 +327,6 @@ class Customers extends Persons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Customers import from csv spreadsheet
|
|
||||||
*
|
|
||||||
* @return DownloadResponse The template for Customer CSV imports is returned and download forced.
|
|
||||||
* @noinspection PhpUnused
|
|
||||||
*/
|
|
||||||
public function getCsv(): DownloadResponse
|
public function getCsv(): DownloadResponse
|
||||||
{
|
{
|
||||||
$name = 'importCustomers.csv';
|
$name = 'importCustomers.csv';
|
||||||
@@ -386,30 +334,17 @@ class Customers extends Persons
|
|||||||
return $this->response->download($name, $data);
|
return $this->response->download($name, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the customer CSV import modal. Used in app/Views/people/manage.php
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @noinspection PhpUnused
|
|
||||||
*/
|
|
||||||
public function getCsvImport(): string
|
public function getCsvImport(): string
|
||||||
{
|
{
|
||||||
return view('customers/form_csv_import');
|
return view('customers/form_csv_import');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports a CSV file containing customers. Used in app/Views/customers/form_csv_import.php
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @noinspection PhpUnused
|
|
||||||
*/
|
|
||||||
public function postImportCsvFile(): ResponseInterface
|
public function postImportCsvFile(): ResponseInterface
|
||||||
{
|
{
|
||||||
if ($_FILES['file_path']['error'] != UPLOAD_ERR_OK) {
|
if ($_FILES['file_path']['error'] != UPLOAD_ERR_OK) {
|
||||||
return $this->response->setJSON(['success' => false, 'message' => lang('Customers.csv_import_failed')]);
|
return $this->response->setJSON(['success' => false, 'message' => lang('Customers.csv_import_failed')]);
|
||||||
} else {
|
} else {
|
||||||
if (($handle = fopen($_FILES['file_path']['tmp_name'], 'r')) !== false) {
|
if (($handle = fopen($_FILES['file_path']['tmp_name'], 'r')) !== false) {
|
||||||
// Skip the first row as it's the table description
|
|
||||||
fgetcsv($handle);
|
fgetcsv($handle);
|
||||||
$i = 1;
|
$i = 1;
|
||||||
|
|
||||||
@@ -420,7 +355,7 @@ class Customers extends Persons
|
|||||||
|
|
||||||
if (sizeof($data) >= 16 && $consent) {
|
if (sizeof($data) >= 16 && $consent) {
|
||||||
$email = strtolower($data[4]);
|
$email = strtolower($data[4]);
|
||||||
$person_data = [
|
$personData = [
|
||||||
'first_name' => $data[0],
|
'first_name' => $data[0],
|
||||||
'last_name' => $data[1],
|
'last_name' => $data[1],
|
||||||
'gender' => $data[2],
|
'gender' => $data[2],
|
||||||
@@ -435,7 +370,7 @@ class Customers extends Persons
|
|||||||
'comments' => $data[12]
|
'comments' => $data[12]
|
||||||
];
|
];
|
||||||
|
|
||||||
$customer_data = [
|
$customerData = [
|
||||||
'consent' => $consent,
|
'consent' => $consent,
|
||||||
'company_name' => $data[13],
|
'company_name' => $data[13],
|
||||||
'discount' => $data[15],
|
'discount' => $data[15],
|
||||||
@@ -444,14 +379,13 @@ class Customers extends Persons
|
|||||||
'date' => date('Y-m-d H:i:s'),
|
'date' => date('Y-m-d H:i:s'),
|
||||||
'employee_id' => $this->employee->get_logged_in_employee_info()->person_id
|
'employee_id' => $this->employee->get_logged_in_employee_info()->person_id
|
||||||
];
|
];
|
||||||
$account_number = $data[14];
|
$accountNumber = $data[14];
|
||||||
|
|
||||||
// Don't duplicate people with same email
|
|
||||||
$invalidated = $this->customer->check_email_exists($email);
|
$invalidated = $this->customer->check_email_exists($email);
|
||||||
|
|
||||||
if ($account_number != '') {
|
if ($accountNumber != '') {
|
||||||
$customer_data['account_number'] = $account_number;
|
$customerData['account_number'] = $accountNumber;
|
||||||
$invalidated &= $this->customer->check_account_number_exists($account_number);
|
$invalidated &= $this->customer->check_account_number_exists($accountNumber);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$invalidated = true;
|
$invalidated = true;
|
||||||
@@ -460,9 +394,8 @@ class Customers extends Persons
|
|||||||
if ($invalidated) {
|
if ($invalidated) {
|
||||||
$failCodes[] = $i;
|
$failCodes[] = $i;
|
||||||
log_message('error', "Row $i was not imported: Either email or account number already exist or data was invalid.");
|
log_message('error', "Row $i was not imported: Either email or account number already exist or data was invalid.");
|
||||||
} elseif ($this->customer->save_customer($person_data, $customer_data)) {
|
} elseif ($this->customer->save_customer($personData, $customerData)) {
|
||||||
// Save customer to Mailchimp selected list
|
$this->mailchimpLib->addOrUpdateMember($this->listId, $personData['email'], $personData['first_name'], '', $personData['last_name']);
|
||||||
$this->mailchimp_lib->addOrUpdateMember($this->_list_id, $person_data['email'], $person_data['first_name'], '', $person_data['last_name']);
|
|
||||||
} else {
|
} else {
|
||||||
$failCodes[] = $i;
|
$failCodes[] = $i;
|
||||||
}
|
}
|
||||||
@@ -482,4 +415,4 @@ class Customers extends Persons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,18 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Controllers;
|
namespace App\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Attribute;
|
||||||
use App\Models\Module;
|
use App\Models\Module;
|
||||||
use CodeIgniter\HTTP\ResponseInterface;
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
use Config\Services;
|
use Config\Services;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @property module module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Employees extends Persons
|
class Employees extends Persons
|
||||||
{
|
{
|
||||||
|
protected Module $module;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct('employees');
|
parent::__construct('employees');
|
||||||
@@ -21,35 +18,25 @@ class Employees extends Persons
|
|||||||
$this->module = model('Module');
|
$this->module = model('Module');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns employee table data rows. This will be called with AJAX.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getSearch(): ResponseInterface
|
public function getSearch(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('search');
|
$search = $this->request->getGet('search');
|
||||||
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
|
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
|
||||||
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
|
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
|
||||||
$sort = $this->sanitizeSortColumn(person_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
|
$sort = $this->sanitizeSortColumn(person_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
|
||||||
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
|
|
||||||
$employees = $this->employee->search($search, $limit, $offset, $sort, $order);
|
$employees = $this->employee->search($search, $limit, $offset, $sort, $order);
|
||||||
$total_rows = $this->employee->get_found_rows($search);
|
$totalRows = $this->employee->get_found_rows($search);
|
||||||
|
|
||||||
$data_rows = [];
|
$dataRows = [];
|
||||||
foreach ($employees->getResult() as $person) {
|
foreach ($employees->getResult() as $person) {
|
||||||
$data_rows[] = get_person_data_row($person);
|
$dataRows[] = get_person_data_row($person);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
|
return $this->response->setJSON(['total' => $totalRows, 'rows' => $dataRows]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* AJAX called function gives search suggestions based on what is being searched for.
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function getSuggest(): ResponseInterface
|
public function getSuggest(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('term');
|
$search = $this->request->getGet('term');
|
||||||
@@ -58,10 +45,7 @@ class Employees extends Persons
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function suggestSearch(): ResponseInterface
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function suggest_search(): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$search = $this->request->getPost('term');
|
$search = $this->request->getPost('term');
|
||||||
$suggestions = $this->employee->get_search_suggestions($search);
|
$suggestions = $this->employee->get_search_suggestions($search);
|
||||||
@@ -69,39 +53,35 @@ class Employees extends Persons
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getView(int $employeeId = NEW_ENTRY): string
|
||||||
* Loads the employee edit form
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getView(int $employee_id = NEW_ENTRY): string
|
|
||||||
{
|
{
|
||||||
$person_info = $this->employee->get_info($employee_id);
|
$personInfo = $this->employee->get_info($employeeId);
|
||||||
$current_user = $this->employee->get_logged_in_employee_info();
|
$currentUser = $this->employee->get_logged_in_employee_info();
|
||||||
|
|
||||||
if ($employee_id != NEW_ENTRY && !$this->employee->canModifyEmployee($person_info->person_id, $current_user->person_id)) {
|
if ($employeeId != NEW_ENTRY && !$this->employee->canModifyEmployee($personInfo->person_id, $currentUser->person_id)) {
|
||||||
header('Location: ' . base_url('no_access/employees/employees'));
|
header('Location: ' . base_url('no_access/employees/employees'));
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (get_object_vars($person_info) as $property => $value) {
|
foreach (get_object_vars($personInfo) as $property => $value) {
|
||||||
$person_info->$property = $value;
|
$personInfo->$property = $value;
|
||||||
}
|
}
|
||||||
$data['person_info'] = $person_info;
|
$data['person_info'] = $personInfo;
|
||||||
$data['employee_id'] = $employee_id;
|
$data['employee_id'] = $employeeId;
|
||||||
|
|
||||||
$modules = [];
|
$modules = [];
|
||||||
foreach ($this->module->get_all_modules()->getResult() as $module) {
|
foreach ($this->module->get_all_modules()->getResult() as $module) {
|
||||||
$module->grant = $this->employee->has_grant($module->module_id, $person_info->person_id);
|
$module->grant = $this->employee->has_grant($module->module_id, $personInfo->person_id);
|
||||||
$module->menu_group = $this->employee->get_menu_group($module->module_id, $person_info->person_id);
|
$module->menu_group = $this->employee->get_menu_group($module->module_id, $personInfo->person_id);
|
||||||
|
|
||||||
$modules[] = $module;
|
$modules[] = $module;
|
||||||
}
|
}
|
||||||
$data['all_modules'] = $modules;
|
$data['all_modules'] = $modules;
|
||||||
|
|
||||||
$permissions = [];
|
$permissions = [];
|
||||||
foreach ($this->module->get_all_subpermissions()->getResult() as $permission) { // TODO: subpermissions does not follow naming standards.
|
foreach ($this->module->get_all_subpermissions()->getResult() as $permission) {
|
||||||
$permission->permission_id = str_replace(' ', '_', $permission->permission_id);
|
$permission->permission_id = str_replace(' ', '_', $permission->permission_id);
|
||||||
$permission->grant = $this->employee->has_grant($permission->permission_id, $person_info->person_id);
|
$permission->grant = $this->employee->has_grant($permission->permission_id, $personInfo->person_id);
|
||||||
|
|
||||||
$permissions[] = $permission;
|
$permissions[] = $permission;
|
||||||
}
|
}
|
||||||
@@ -110,17 +90,18 @@ class Employees extends Persons
|
|||||||
return view('employees/form', $data);
|
return view('employees/form', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getAttributes(int $employeeId = NEW_ENTRY): string
|
||||||
* Inserts/updates an employee
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function postSave(int $employee_id = NEW_ENTRY): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$current_user = $this->employee->get_logged_in_employee_info();
|
return $this->getPersonAttributes($employeeId, Attribute::SHOW_IN_EMPLOYEES);
|
||||||
|
}
|
||||||
|
|
||||||
if ($employee_id != NEW_ENTRY) {
|
public function postSave(int $employeeId = NEW_ENTRY): ResponseInterface
|
||||||
$target_employee = $this->employee->get_info($employee_id);
|
{
|
||||||
if (!$this->employee->canModifyEmployee($target_employee->person_id, $current_user->person_id)) {
|
$currentUser = $this->employee->get_logged_in_employee_info();
|
||||||
|
|
||||||
|
if ($employeeId != NEW_ENTRY) {
|
||||||
|
$targetEmployee = $this->employee->get_info($employeeId);
|
||||||
|
if (!$this->employee->canModifyEmployee($targetEmployee->person_id, $currentUser->person_id)) {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => lang('Employees.error_updating_admin'),
|
'message' => lang('Employees.error_updating_admin'),
|
||||||
@@ -129,17 +110,16 @@ class Employees extends Persons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$first_name = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: duplicated code
|
$firstName = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
$last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
$lastName = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
||||||
|
|
||||||
// format first and last name properly
|
$firstName = $this->nameize($firstName);
|
||||||
$first_name = $this->nameize($first_name);
|
$lastName = $this->nameize($lastName);
|
||||||
$last_name = $this->nameize($last_name);
|
|
||||||
|
|
||||||
$person_data = [
|
$personData = [
|
||||||
'first_name' => $first_name,
|
'first_name' => $firstName,
|
||||||
'last_name' => $last_name,
|
'last_name' => $lastName,
|
||||||
'gender' => $this->request->getPost('gender', FILTER_SANITIZE_NUMBER_INT),
|
'gender' => $this->request->getPost('gender', FILTER_SANITIZE_NUMBER_INT),
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'phone_number' => $this->request->getPost('phone_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'phone_number' => $this->request->getPost('phone_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
@@ -152,108 +132,98 @@ class Employees extends Persons
|
|||||||
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
||||||
];
|
];
|
||||||
|
|
||||||
$grants_array = [];
|
$grantsArray = [];
|
||||||
$isAdmin = $this->employee->isAdmin($current_user->person_id);
|
$isAdmin = $this->employee->isAdmin($currentUser->person_id);
|
||||||
|
|
||||||
foreach ($this->module->get_all_permissions()->getResult() as $permission) {
|
foreach ($this->module->get_all_permissions()->getResult() as $permission) {
|
||||||
$grants = [];
|
$grants = [];
|
||||||
$grant = $this->request->getPost('grant_' . $permission->permission_id) != null ? $this->request->getPost('grant_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '';
|
$grant = $this->request->getPost('grant_' . $permission->permission_id) != null ? $this->request->getPost('grant_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '';
|
||||||
|
|
||||||
if ($grant == $permission->permission_id) {
|
if ($grant == $permission->permission_id) {
|
||||||
if (!$isAdmin && !$this->employee->has_grant($permission->permission_id, $current_user->person_id)) {
|
if (!$isAdmin && !$this->employee->has_grant($permission->permission_id, $currentUser->person_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$grants['permission_id'] = $permission->permission_id;
|
$grants['permission_id'] = $permission->permission_id;
|
||||||
$grants['menu_group'] = $this->request->getPost('menu_group_' . $permission->permission_id) != null ? $this->request->getPost('menu_group_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '--';
|
$grants['menu_group'] = $this->request->getPost('menu_group_' . $permission->permission_id) != null ? $this->request->getPost('menu_group_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '--';
|
||||||
$grants_array[] = $grants;
|
$grantsArray[] = $grants;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password has been changed OR first time password set
|
|
||||||
if (!empty($this->request->getPost('password')) && ENVIRONMENT != 'testing') {
|
if (!empty($this->request->getPost('password')) && ENVIRONMENT != 'testing') {
|
||||||
$exploded = explode(":", $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
|
$exploded = explode(":", $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
|
||||||
$employee_data = [
|
$employeeData = [
|
||||||
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
'password' => password_hash($this->request->getPost('password'), PASSWORD_DEFAULT),
|
'password' => password_hash($this->request->getPost('password'), PASSWORD_DEFAULT),
|
||||||
'hash_version' => 2,
|
'hash_version' => 2,
|
||||||
'language_code' => $exploded[0],
|
'language_code' => $exploded[0],
|
||||||
'language' => $exploded[1]
|
'language' => $exploded[1]
|
||||||
];
|
];
|
||||||
} else { // Password not changed
|
} else {
|
||||||
$exploded = explode(":", $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
|
$exploded = explode(":", $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
|
||||||
$employee_data = [
|
$employeeData = [
|
||||||
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
'language_code' => $exploded[0],
|
'language_code' => $exploded[0],
|
||||||
'language' => $exploded[1]
|
'language' => $exploded[1]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->employee->save_employee($person_data, $employee_data, $grants_array, $employee_id)) {
|
if ($this->employee->save_employee($personData, $employeeData, $grantsArray, $employeeId)) {
|
||||||
// New employee
|
$personId = $employeeId == NEW_ENTRY ? $employeeData['person_id'] : $employeeId;
|
||||||
if ($employee_id == NEW_ENTRY) {
|
$this->savePersonAttributes($personId, Attribute::SHOW_IN_EMPLOYEES);
|
||||||
|
|
||||||
|
if ($employeeId == NEW_ENTRY) {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Employees.successful_adding') . ' ' . $first_name . ' ' . $last_name,
|
'message' => lang('Employees.successful_adding') . ' ' . $firstName . ' ' . $lastName,
|
||||||
'id' => $employee_data['person_id']
|
'id' => $employeeData['person_id']
|
||||||
]);
|
]);
|
||||||
} else { // Existing employee
|
} else {
|
||||||
$logged_in_employee_id = session()->get('person_id');
|
$loggedInEmployeeId = session()->get('person_id');
|
||||||
if ($employee_id == $logged_in_employee_id) {
|
if ($employeeId == $loggedInEmployeeId) {
|
||||||
session()->set('language_code', $employee_data['language_code']);
|
session()->set('language_code', $employeeData['language_code']);
|
||||||
session()->set('language', $employee_data['language']);
|
session()->set('language', $employeeData['language']);
|
||||||
}
|
}
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Employees.successful_updating') . ' ' . $first_name . ' ' . $last_name,
|
'message' => lang('Employees.successful_updating') . ' ' . $firstName . ' ' . $lastName,
|
||||||
'id' => $employee_id
|
'id' => $employeeId
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else { // Failure
|
} else {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => lang('Employees.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
|
'message' => lang('Employees.error_adding_updating') . ' ' . $firstName . ' ' . $lastName,
|
||||||
'id' => NEW_ENTRY
|
'id' => NEW_ENTRY
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This deletes employees from the employees table
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function postDelete(): ResponseInterface
|
public function postDelete(): ResponseInterface
|
||||||
{
|
{
|
||||||
$employees_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
$employeesToDelete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
$current_user = $this->employee->get_logged_in_employee_info();
|
$currentUser = $this->employee->get_logged_in_employee_info();
|
||||||
|
|
||||||
if (!$this->employee->isAdmin($current_user->person_id)) {
|
if (!$this->employee->isAdmin($currentUser->person_id)) {
|
||||||
foreach ($employees_to_delete as $emp_id) {
|
foreach ($employeesToDelete as $empId) {
|
||||||
if ($this->employee->isAdmin((int)$emp_id)) {
|
if ($this->employee->isAdmin((int)$empId)) {
|
||||||
return $this->response->setJSON(['success' => false, 'message' => lang('Employees.error_deleting_admin')]);
|
return $this->response->setJSON(['success' => false, 'message' => lang('Employees.error_deleting_admin')]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->employee->delete_list($employees_to_delete)) { // TODO: this is passing a string, but delete_list expects an array
|
if ($this->employee->delete_list($employeesToDelete)) {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Employees.successful_deleted') . ' ' . count($employees_to_delete) . ' ' . lang('Employees.one_or_multiple')
|
'message' => lang('Employees.successful_deleted') . ' ' . count($employeesToDelete) . ' ' . lang('Employees.one_or_multiple')
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
return $this->response->setJSON(['success' => false, 'message' => lang('Employees.cannot_be_deleted')]);
|
return $this->response->setJSON(['success' => false, 'message' => lang('Employees.cannot_be_deleted')]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getCheckUsername($employeeId): ResponseInterface
|
||||||
* Checks an employee username against the database. Used in app\Views\employees\form.php
|
|
||||||
*
|
|
||||||
* @param $employee_id
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @noinspection PhpUnused
|
|
||||||
*/
|
|
||||||
public function getCheckUsername($employee_id): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$exists = $this->employee->username_exists($employee_id, $this->request->getGet('username'));
|
$exists = $this->employee->username_exists($employeeId, $this->request->getGet('username'));
|
||||||
return $this->response->setJSON(!$exists ? 'true' : 'false');
|
return $this->response->setJSON(!$exists ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,28 +2,28 @@
|
|||||||
|
|
||||||
namespace App\Controllers;
|
namespace App\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Attribute;
|
||||||
use App\Models\Person;
|
use App\Models\Person;
|
||||||
use CodeIgniter\HTTP\ResponseInterface;
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
|
use Config\OSPOS;
|
||||||
use Config\Services;
|
use Config\Services;
|
||||||
use function Tamtamchik\NameCase\str_name_case;
|
use function Tamtamchik\NameCase\str_name_case;
|
||||||
|
|
||||||
abstract class Persons extends Secure_Controller
|
abstract class Persons extends Secure_Controller
|
||||||
{
|
{
|
||||||
protected Person $person;
|
protected Person $person;
|
||||||
|
protected Attribute $attribute;
|
||||||
|
protected array $appConfig;
|
||||||
|
|
||||||
/**
|
public function __construct(?string $moduleId = null)
|
||||||
* @param string|null $module_id
|
|
||||||
*/
|
|
||||||
public function __construct(?string $module_id = null)
|
|
||||||
{
|
{
|
||||||
parent::__construct($module_id);
|
parent::__construct($moduleId);
|
||||||
|
|
||||||
$this->person = model(Person::class);
|
$this->person = model(Person::class);
|
||||||
|
$this->attribute = model(Attribute::class);
|
||||||
|
$this->appConfig = config(OSPOS::class)->settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getIndex(): string
|
public function getIndex(): string
|
||||||
{
|
{
|
||||||
$data['table_headers'] = get_people_manage_table_headers();
|
$data['table_headers'] = get_people_manage_table_headers();
|
||||||
@@ -31,10 +31,6 @@ abstract class Persons extends Secure_Controller
|
|||||||
return view('people/manage', $data);
|
return view('people/manage', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives search suggestions based on what is being searched for
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function getSuggest(): ResponseInterface
|
public function getSuggest(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('term');
|
$search = $this->request->getGet('term');
|
||||||
@@ -43,34 +39,88 @@ abstract class Persons extends Secure_Controller
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getRow(int $rowId): ResponseInterface
|
||||||
* Gets one row for a person manage table. This is called using AJAX to update one row.
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function getRow(int $row_id): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$data_row = get_person_data_row($this->person->get_info($row_id));
|
$dataRow = get_person_data_row($this->person->get_info($rowId));
|
||||||
|
|
||||||
return $this->response->setJSON($data_row);
|
return $this->response->setJSON($dataRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPersonAttributes(int $personId, int $definitionFlags): string
|
||||||
|
{
|
||||||
|
$data['person_id'] = $personId;
|
||||||
|
$data['config'] = $this->appConfig;
|
||||||
|
$definitionIds = json_decode($this->request->getGet('definition_ids') ?? '', true);
|
||||||
|
$data['definition_values'] = $this->attribute->getAttributesByPerson($personId) + $this->attribute->get_values_by_definitions($definitionIds);
|
||||||
|
$data['definition_names'] = $this->attribute->getDefinitionsByType(true, $definitionFlags);
|
||||||
|
|
||||||
|
foreach ($data['definition_values'] as $definitionId => $definitionValue) {
|
||||||
|
$attributeValue = $this->attribute->getPersonAttributeValue($personId, $definitionId);
|
||||||
|
$attributeId = (empty($attributeValue) || empty($attributeValue->attribute_id)) ? null : $attributeValue->attribute_id;
|
||||||
|
$values = &$data['definition_values'][$definitionId];
|
||||||
|
$values['attribute_id'] = $attributeId;
|
||||||
|
$values['attribute_value'] = $attributeValue;
|
||||||
|
$values['selected_value'] = '';
|
||||||
|
|
||||||
|
if ($definitionValue['definition_type'] === DROPDOWN) {
|
||||||
|
$values['values'] = $this->attribute->get_definition_values($definitionId);
|
||||||
|
$linkValue = $this->getPersonLinkValue($personId, $definitionId);
|
||||||
|
$values['selected_value'] = (empty($linkValue)) ? '' : $linkValue->attribute_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($definitionIds[$definitionId])) {
|
||||||
|
$values['selected_value'] = $definitionIds[$definitionId];
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($data['definition_names'][$definitionId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('attributes/person', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPersonLinkValue(int $personId, int $definitionId): ?object
|
||||||
|
{
|
||||||
|
$builder = $this->db->table('attribute_links');
|
||||||
|
$builder->where('person_id', $personId);
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
$builder->where('definition_id', $definitionId);
|
||||||
|
|
||||||
|
return $builder->get()->getRowObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function savePersonAttributes(int $personId, int $definitionFlags): void
|
||||||
|
{
|
||||||
|
$attributeLinks = $this->request->getPost('attribute_links') ?? [];
|
||||||
|
$attributeIds = $this->request->getPost('attribute_ids') ?? [];
|
||||||
|
|
||||||
|
$this->attribute->deletePersonAttributeLinks($personId);
|
||||||
|
|
||||||
|
foreach ($attributeLinks as $definitionId => $attributeId) {
|
||||||
|
$definitionInfo = $this->attribute->getAttributeInfo((int)$definitionId);
|
||||||
|
$definitionType = $definitionInfo->definition_type;
|
||||||
|
|
||||||
|
if ($definitionType !== DROPDOWN) {
|
||||||
|
$attributeId = $this->attribute->savePersonAttributeValue(
|
||||||
|
$attributeId,
|
||||||
|
(int)$definitionId,
|
||||||
|
$personId,
|
||||||
|
$attributeIds[$definitionId] ?? false,
|
||||||
|
$definitionType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->attribute->savePersonAttributeLink($personId, (int)$definitionId, (int)$attributeId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Capitalize segments of a name, and put the rest into lower case.
|
|
||||||
* You can pass the characters you want to use as delimiters as exceptions.
|
|
||||||
* The function supports UTF-8 strings
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* i.e. <?php echo nameize("john o'grady-smith"); ?>
|
|
||||||
*
|
|
||||||
* returns John O'Grady-Smith
|
|
||||||
*/
|
|
||||||
protected function nameize(string $input): string
|
protected function nameize(string $input): string
|
||||||
{
|
{
|
||||||
$adjusted_name = str_name_case($input);
|
$adjustedName = str_name_case($input);
|
||||||
|
|
||||||
// TODO: Use preg_replace to match HTML entities and convert them to lowercase. This is a workaround for https://github.com/tamtamchik/namecase/issues/20
|
|
||||||
return preg_replace_callback('/&[a-zA-Z0-9#]+;/', function ($matches) {
|
return preg_replace_callback('/&[a-zA-Z0-9#]+;/', function ($matches) {
|
||||||
return strtolower($matches[0]);
|
return strtolower($matches[0]);
|
||||||
}, $adjusted_name);
|
}, $adjustedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Controllers;
|
namespace App\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Attribute;
|
||||||
use App\Models\Supplier;
|
use App\Models\Supplier;
|
||||||
use CodeIgniter\HTTP\ResponseInterface;
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
use Config\Services;
|
use Config\Services;
|
||||||
@@ -17,9 +18,6 @@ class Suppliers extends Persons
|
|||||||
$this->supplier = model(Supplier::class);
|
$this->supplier = model(Supplier::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getIndex(): string
|
public function getIndex(): string
|
||||||
{
|
{
|
||||||
$data['table_headers'] = get_suppliers_manage_table_headers();
|
$data['table_headers'] = get_suppliers_manage_table_headers();
|
||||||
@@ -27,23 +25,14 @@ class Suppliers extends Persons
|
|||||||
return view('people/manage', $data);
|
return view('people/manage', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getRow($rowId): ResponseInterface
|
||||||
* Gets one row for a supplier manage table. This is called using AJAX to update one row.
|
|
||||||
* @param $row_id
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function getRow($row_id): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$data_row = get_supplier_data_row($this->supplier->get_info($row_id));
|
$dataRow = get_supplier_data_row($this->supplier->get_info($rowId));
|
||||||
$data_row['category'] = $this->supplier->get_category_name($data_row['category']);
|
$dataRow['category'] = $this->supplier->get_category_name($dataRow['category']);
|
||||||
|
|
||||||
return $this->response->setJSON($data_row);
|
return $this->response->setJSON($dataRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns Supplier table data rows. This will be called with AJAX.
|
|
||||||
* @return void
|
|
||||||
**/
|
|
||||||
public function getSearch(): ResponseInterface
|
public function getSearch(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('search');
|
$search = $this->request->getGet('search');
|
||||||
@@ -53,23 +42,19 @@ class Suppliers extends Persons
|
|||||||
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
|
|
||||||
$suppliers = $this->supplier->search($search, $limit, $offset, $sort, $order);
|
$suppliers = $this->supplier->search($search, $limit, $offset, $sort, $order);
|
||||||
$total_rows = $this->supplier->get_found_rows($search);
|
$totalRows = $this->supplier->get_found_rows($search);
|
||||||
|
|
||||||
$data_rows = [];
|
$dataRows = [];
|
||||||
|
|
||||||
foreach ($suppliers->getResult() as $supplier) {
|
foreach ($suppliers->getResult() as $supplier) {
|
||||||
$row = get_supplier_data_row($supplier);
|
$row = get_supplier_data_row($supplier);
|
||||||
$row['category'] = $this->supplier->get_category_name($row['category']);
|
$row['category'] = $this->supplier->get_category_name($row['category']);
|
||||||
$data_rows[] = $row;
|
$dataRows[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
|
return $this->response->setJSON(['total' => $totalRows, 'rows' => $dataRows]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives search suggestions based on what is being searched for
|
|
||||||
* @return ResponseInterface
|
|
||||||
**/
|
|
||||||
public function getSuggest(): ResponseInterface
|
public function getSuggest(): ResponseInterface
|
||||||
{
|
{
|
||||||
$search = $this->request->getGet('term');
|
$search = $this->request->getGet('term');
|
||||||
@@ -78,10 +63,7 @@ class Suppliers extends Persons
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function suggestSearch(): ResponseInterface
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function suggest_search(): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$search = $this->request->getPost('term');
|
$search = $this->request->getPost('term');
|
||||||
$suggestions = $this->supplier->get_search_suggestions($search, false);
|
$suggestions = $this->supplier->get_search_suggestions($search, false);
|
||||||
@@ -89,15 +71,9 @@ class Suppliers extends Persons
|
|||||||
return $this->response->setJSON($suggestions);
|
return $this->response->setJSON($suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getView(int $supplierId = NEW_ENTRY): string
|
||||||
* Loads the supplier edit form
|
|
||||||
*
|
|
||||||
* @param int $supplier_id
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getView(int $supplier_id = NEW_ENTRY): string
|
|
||||||
{
|
{
|
||||||
$info = $this->supplier->get_info($supplier_id);
|
$info = $this->supplier->get_info($supplierId);
|
||||||
foreach (get_object_vars($info) as $property => $value) {
|
foreach (get_object_vars($info) as $property => $value) {
|
||||||
$info->$property = $value;
|
$info->$property = $value;
|
||||||
}
|
}
|
||||||
@@ -107,25 +83,23 @@ class Suppliers extends Persons
|
|||||||
return view("suppliers/form", $data);
|
return view("suppliers/form", $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getAttributes(int $supplierId = NEW_ENTRY): string
|
||||||
* Inserts/updates a supplier
|
|
||||||
*
|
|
||||||
* @param int $supplier_id
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function postSave(int $supplier_id = NEW_ENTRY): ResponseInterface
|
|
||||||
{
|
{
|
||||||
$first_name = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: Duplicate code
|
return $this->getPersonAttributes($supplierId, Attribute::SHOW_IN_SUPPLIERS);
|
||||||
$last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
}
|
||||||
|
|
||||||
|
public function postSave(int $supplierId = NEW_ENTRY): ResponseInterface
|
||||||
|
{
|
||||||
|
$firstName = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
|
$lastName = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
|
||||||
|
|
||||||
// Format first and last name properly
|
$firstName = $this->nameize($firstName);
|
||||||
$first_name = $this->nameize($first_name);
|
$lastName = $this->nameize($lastName);
|
||||||
$last_name = $this->nameize($last_name);
|
|
||||||
|
|
||||||
$person_data = [
|
$personData = [
|
||||||
'first_name' => $first_name,
|
'first_name' => $firstName,
|
||||||
'last_name' => $last_name,
|
'last_name' => $lastName,
|
||||||
'gender' => $this->request->getPost('gender'),
|
'gender' => $this->request->getPost('gender'),
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'phone_number' => $this->request->getPost('phone_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'phone_number' => $this->request->getPost('phone_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
@@ -138,7 +112,7 @@ class Suppliers extends Persons
|
|||||||
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
||||||
];
|
];
|
||||||
|
|
||||||
$supplier_data = [
|
$supplierData = [
|
||||||
'company_name' => $this->request->getPost('company_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'company_name' => $this->request->getPost('company_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
'agency_name' => $this->request->getPost('agency_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'agency_name' => $this->request->getPost('agency_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
'category' => $this->request->getPost('category', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
'category' => $this->request->getPost('category', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
|
||||||
@@ -146,47 +120,43 @@ class Suppliers extends Persons
|
|||||||
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT)
|
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT)
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->supplier->save_supplier($person_data, $supplier_data, $supplier_id)) {
|
if ($this->supplier->save_supplier($personData, $supplierData, $supplierId)) {
|
||||||
// New supplier
|
$personId = $supplierId == NEW_ENTRY ? $supplierData['person_id'] : $supplierId;
|
||||||
if ($supplier_id == NEW_ENTRY) {
|
$this->savePersonAttributes($personId, Attribute::SHOW_IN_SUPPLIERS);
|
||||||
return $this->response->setJSON([
|
|
||||||
'success' => true,
|
|
||||||
'message' => lang('Suppliers.successful_adding') . ' ' . $supplier_data['company_name'],
|
|
||||||
'id' => $supplier_data['person_id']
|
|
||||||
]);
|
|
||||||
} else { // Existing supplier
|
|
||||||
|
|
||||||
|
if ($supplierId == NEW_ENTRY) {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Suppliers.successful_updating') . ' ' . $supplier_data['company_name'],
|
'message' => lang('Suppliers.successful_adding') . ' ' . $supplierData['company_name'],
|
||||||
'id' => $supplier_id
|
'id' => $supplierData['person_id']
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return $this->response->setJSON([
|
||||||
|
'success' => true,
|
||||||
|
'message' => lang('Suppliers.successful_updating') . ' ' . $supplierData['company_name'],
|
||||||
|
'id' => $supplierId
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else { // Failure
|
} else {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => lang('Suppliers.error_adding_updating') . ' ' . $supplier_data['company_name'],
|
'message' => lang('Suppliers.error_adding_updating') . ' ' . $supplierData['company_name'],
|
||||||
'id' => NEW_ENTRY
|
'id' => NEW_ENTRY
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This deletes suppliers from the suppliers table
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function postDelete(): ResponseInterface
|
public function postDelete(): ResponseInterface
|
||||||
{
|
{
|
||||||
$suppliers_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
|
$suppliersToDelete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
|
||||||
|
|
||||||
if ($this->supplier->delete_list($suppliers_to_delete)) {
|
if ($this->supplier->delete_list($suppliersToDelete)) {
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => lang('Suppliers.successful_deleted') . ' ' . count($suppliers_to_delete) . ' ' . lang('Suppliers.one_or_multiple')
|
'message' => lang('Suppliers.successful_deleted') . ' ' . count($suppliersToDelete) . ' ' . lang('Suppliers.one_or_multiple')
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
return $this->response->setJSON(['success' => false, 'message' => lang('Suppliers.cannot_be_deleted')]);
|
return $this->response->setJSON(['success' => false, 'message' => lang('Suppliers.cannot_be_deleted')]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Database\Migrations;
|
||||||
|
|
||||||
|
use CodeIgniter\Database\Migration;
|
||||||
|
use Config\Database;
|
||||||
|
|
||||||
|
class AddPersonToAttributeLinks extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
helper('migration');
|
||||||
|
|
||||||
|
// First, modify the generated unique column to include person_id
|
||||||
|
// Drop the existing unique constraint
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP INDEX `attribute_links_uq3`');
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP COLUMN `generated_unique_column`');
|
||||||
|
|
||||||
|
// Add person_id column
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD COLUMN `person_id` INT(10) NULL AFTER `receiving_id`');
|
||||||
|
|
||||||
|
// Add index for person_id
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD KEY `person_id` (`person_id`)');
|
||||||
|
|
||||||
|
// Add foreign key constraint for person_id
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD CONSTRAINT `ospos_attribute_links_ibfk_6` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`) ON DELETE CASCADE');
|
||||||
|
|
||||||
|
// Recreate the generated unique column with person_id support
|
||||||
|
// This ensures uniqueness for both item attributes and person attributes
|
||||||
|
$this->db->query("ALTER TABLE `ospos_attribute_links`
|
||||||
|
ADD COLUMN `generated_unique_column` VARCHAR(255) GENERATED ALWAYS AS (
|
||||||
|
CASE
|
||||||
|
WHEN `sale_id` IS NULL AND `receiving_id` IS NULL AND `item_id` IS NOT NULL THEN CONCAT('item-', `definition_id`, '-', `item_id`)
|
||||||
|
WHEN `sale_id` IS NULL AND `receiving_id` IS NULL AND `item_id` IS NULL AND `person_id` IS NOT NULL THEN CONCAT('person-', `definition_id`, '-', `person_id`)
|
||||||
|
ELSE NULL
|
||||||
|
END
|
||||||
|
) STORED");
|
||||||
|
|
||||||
|
// Re-add unique constraint
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD UNIQUE INDEX `attribute_links_uq3` (`generated_unique_column`)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
// Drop person_id related constraints and column
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP INDEX `attribute_links_uq3`');
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP COLUMN `generated_unique_column`');
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP FOREIGN KEY `ospos_attribute_links_ibfk_6`');
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP COLUMN `person_id`');
|
||||||
|
|
||||||
|
// Restore original generated column
|
||||||
|
$this->db->query("ALTER TABLE `ospos_attribute_links`
|
||||||
|
ADD COLUMN `generated_unique_column` VARCHAR(255) GENERATED ALWAYS AS (
|
||||||
|
CASE
|
||||||
|
WHEN `sale_id` IS NULL AND `receiving_id` IS NULL AND `item_id` IS NOT NULL THEN CONCAT(`definition_id`, '-', `item_id`)
|
||||||
|
ELSE NULL
|
||||||
|
END
|
||||||
|
) STORED");
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD UNIQUE INDEX `attribute_links_uq3` (`generated_unique_column`)');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Database\Migrations;
|
||||||
|
|
||||||
|
use CodeIgniter\Database\Migration;
|
||||||
|
|
||||||
|
class AddPersonAttributeFlag extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_definitions` ADD COLUMN `person_attribute` TINYINT(1) DEFAULT 0 AFTER `definition_flags`');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->db->query('ALTER TABLE `ospos_attribute_definitions` DROP COLUMN `person_attribute`');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,10 @@ return [
|
|||||||
"new" => "New Attribute",
|
"new" => "New Attribute",
|
||||||
"no_attributes_to_display" => "No Attributes to display",
|
"no_attributes_to_display" => "No Attributes to display",
|
||||||
"receipt_visibility" => "Receipt",
|
"receipt_visibility" => "Receipt",
|
||||||
|
"show_in_customers" => "Show in customers",
|
||||||
|
"show_in_customers_visibility" => "Customers",
|
||||||
|
"show_in_employees" => "Show in employees",
|
||||||
|
"show_in_employees_visibility" => "Employees",
|
||||||
"show_in_items" => "Show in items",
|
"show_in_items" => "Show in items",
|
||||||
"show_in_items_visibility" => "Items",
|
"show_in_items_visibility" => "Items",
|
||||||
"show_in_receipt" => "Show in receipt",
|
"show_in_receipt" => "Show in receipt",
|
||||||
@@ -30,5 +34,7 @@ return [
|
|||||||
"show_in_receivings_visibility" => "Receivings",
|
"show_in_receivings_visibility" => "Receivings",
|
||||||
"show_in_sales" => "Show in sales",
|
"show_in_sales" => "Show in sales",
|
||||||
"show_in_sales_visibility" => "Sales",
|
"show_in_sales_visibility" => "Sales",
|
||||||
|
"show_in_suppliers" => "Show in suppliers",
|
||||||
|
"show_in_suppliers_visibility" => "Suppliers",
|
||||||
"update" => "Update Attribute",
|
"update" => "Update Attribute",
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ class Attribute extends Model
|
|||||||
'definition_type',
|
'definition_type',
|
||||||
'definition_unit',
|
'definition_unit',
|
||||||
'definition_flags',
|
'definition_flags',
|
||||||
|
'person_attribute',
|
||||||
'deleted',
|
'deleted',
|
||||||
'attribute_id',
|
'attribute_id',
|
||||||
'definition_id',
|
'definition_id',
|
||||||
'item_id',
|
'item_id',
|
||||||
'sale_id',
|
'sale_id',
|
||||||
'receiving_id',
|
'receiving_id',
|
||||||
|
'person_id',
|
||||||
'attribute_value',
|
'attribute_value',
|
||||||
'attribute_date',
|
'attribute_date',
|
||||||
'attribute_decimal'
|
'attribute_decimal'
|
||||||
@@ -41,7 +43,12 @@ class Attribute extends Model
|
|||||||
public const SHOW_IN_ITEMS = 1; // TODO: These need to be moved to constants.php
|
public const SHOW_IN_ITEMS = 1; // TODO: These need to be moved to constants.php
|
||||||
public const SHOW_IN_SALES = 2;
|
public const SHOW_IN_SALES = 2;
|
||||||
public const SHOW_IN_RECEIVINGS = 4;
|
public const SHOW_IN_RECEIVINGS = 4;
|
||||||
public function deleteDropdownAttributeValue(string $attribute_value, int $definition_id): bool
|
public const SHOW_IN_SEARCH = 8;
|
||||||
|
public const SHOW_IN_CUSTOMERS = 16;
|
||||||
|
public const SHOW_IN_EMPLOYEES = 32;
|
||||||
|
public const SHOW_IN_SUPPLIERS = 64;
|
||||||
|
|
||||||
|
public function deleteDropdownAttributeValue(string $attributeValue, int $definitionId): bool
|
||||||
{
|
{
|
||||||
$attribute_id = $this->getAttributeIdByValue($attribute_value);
|
$attribute_id = $this->getAttributeIdByValue($attribute_value);
|
||||||
$this->deleteAttributeLinksByDefinitionIdAndAttributeId($definition_id, $attribute_id);
|
$this->deleteAttributeLinksByDefinitionIdAndAttributeId($definition_id, $attribute_id);
|
||||||
@@ -269,7 +276,7 @@ class Attribute extends Model
|
|||||||
public function get_definitions_by_flags(int $definition_flags, bool $include_types = false): array
|
public function get_definitions_by_flags(int $definition_flags, bool $include_types = false): array
|
||||||
{
|
{
|
||||||
$builder = $this->db->table('attribute_definitions');
|
$builder = $this->db->table('attribute_definitions');
|
||||||
$builder->where(new RawSql("definition_flags & $definition_flags")); // TODO: we need to heed CI warnings to escape properly
|
$builder->where(new RawSql("definition_flags & $definition_flags"));
|
||||||
$builder->where('deleted', 0);
|
$builder->where('deleted', 0);
|
||||||
$builder->where('definition_type <>', GROUP);
|
$builder->where('definition_type <>', GROUP);
|
||||||
$builder->orderBy('definition_id');
|
$builder->orderBy('definition_id');
|
||||||
@@ -291,11 +298,30 @@ class Attribute extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of attribute definition names and IDs
|
* Gets attribute definitions filtered by type (person or item)
|
||||||
*
|
*
|
||||||
* @param boolean $groups If false does not return GROUP type attributes in the array
|
* @param bool $isPersonAttribute True for person attributes, false for item attributes
|
||||||
* @return array Array containing definition IDs, attribute names and -1 index with the local language '[SELECT]' line.
|
* @param int $definitionFlags Optional visibility flags to further filter
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
public function getDefinitionsByType(bool $isPersonAttribute, int $definitionFlags = 0): array
|
||||||
|
{
|
||||||
|
$builder = $this->db->table('attribute_definitions');
|
||||||
|
$builder->where('person_attribute', $isPersonAttribute ? 1 : 0);
|
||||||
|
$builder->where('deleted', 0);
|
||||||
|
$builder->where('definition_type <>', GROUP);
|
||||||
|
|
||||||
|
if ($definitionFlags > 0) {
|
||||||
|
$builder->where(new RawSql("definition_flags & $definitionFlags"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder->orderBy('definition_name', 'ASC');
|
||||||
|
|
||||||
|
$results = $builder->get()->getResultArray();
|
||||||
|
|
||||||
|
return $this->to_array($results, 'definition_id', 'definition_name');
|
||||||
|
}
|
||||||
|
|
||||||
public function get_definition_names(bool $groups = true): array
|
public function get_definition_names(bool $groups = true): array
|
||||||
{
|
{
|
||||||
$builder = $this->db->table('attribute_definitions');
|
$builder = $this->db->table('attribute_definitions');
|
||||||
@@ -1227,4 +1253,227 @@ class Attribute extends Model
|
|||||||
$itemsBuilder->update();
|
$itemsBuilder->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all attributes connected to a person given the person_id
|
||||||
|
*
|
||||||
|
* @param int $personId Person to retrieve attributes for.
|
||||||
|
* @return array Attributes for the person.
|
||||||
|
*/
|
||||||
|
public function getAttributesByPerson(int $personId): array
|
||||||
|
{
|
||||||
|
$builder = $this->db->table('attribute_definitions');
|
||||||
|
$builder->join('attribute_links', 'attribute_links.definition_id = attribute_definitions.definition_id');
|
||||||
|
$builder->where('person_id', $personId);
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
$builder->where('deleted', 0);
|
||||||
|
$builder->orderBy('definition_name', 'ASC');
|
||||||
|
|
||||||
|
$results = $builder->get()->getResultArray();
|
||||||
|
|
||||||
|
return $this->to_array($results, 'definition_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether an attribute_link row exists given a person_id and optionally a definition_id
|
||||||
|
*
|
||||||
|
* @param int $personId ID of the person to check for an associated attribute.
|
||||||
|
* @param int|bool $definitionId Attribute definition ID to check.
|
||||||
|
* @return bool Returns true if at least one attribute_link exists or false if no attributes exist for that person and attribute.
|
||||||
|
*/
|
||||||
|
public function personAttributeLinkExists(int $personId, int|bool $definitionId = false): bool
|
||||||
|
{
|
||||||
|
$builder = $this->db->table('attribute_links');
|
||||||
|
$builder->where('person_id', $personId);
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
|
||||||
|
if ($definitionId) {
|
||||||
|
$builder->where('definition_id', $definitionId);
|
||||||
|
} else {
|
||||||
|
$builder->where('definition_id IS NOT NULL');
|
||||||
|
$builder->where('attribute_id', null);
|
||||||
|
}
|
||||||
|
$results = $builder->countAllResults();
|
||||||
|
return $results > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts or updates an attribute link for a person
|
||||||
|
*
|
||||||
|
* @param int $personId
|
||||||
|
* @param int $definitionId
|
||||||
|
* @param int $attributeId
|
||||||
|
* @return bool True if the attribute link was saved successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
public function savePersonAttributeLink(int $personId, int $definitionId, int $attributeId): bool
|
||||||
|
{
|
||||||
|
$this->db->transStart();
|
||||||
|
|
||||||
|
$builder = $this->db->table('attribute_links');
|
||||||
|
|
||||||
|
if ($this->personAttributeLinkExists($personId, $definitionId)) {
|
||||||
|
$builder->set(['attribute_id' => $attributeId]);
|
||||||
|
$builder->where('definition_id', $definitionId);
|
||||||
|
$builder->where('person_id', $personId);
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
$builder->update();
|
||||||
|
} else {
|
||||||
|
$data = [
|
||||||
|
'attribute_id' => $attributeId,
|
||||||
|
'person_id' => $personId,
|
||||||
|
'definition_id' => $definitionId
|
||||||
|
];
|
||||||
|
$builder->insert($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->transComplete();
|
||||||
|
|
||||||
|
return $this->db->transStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes attribute links for a person
|
||||||
|
*
|
||||||
|
* @param int $personId
|
||||||
|
* @param int|bool $definitionId
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function deletePersonAttributeLinks(int $personId, int|bool $definitionId = false): bool
|
||||||
|
{
|
||||||
|
$deleteData = ['person_id' => $personId];
|
||||||
|
|
||||||
|
$builder = $this->db->table('attribute_links');
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
|
||||||
|
if (!empty($definitionId)) {
|
||||||
|
$deleteData['definition_id'] = $definitionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $builder->delete($deleteData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the attribute value for a person and definition
|
||||||
|
*
|
||||||
|
* @param int $personId
|
||||||
|
* @param int $definitionId
|
||||||
|
* @return object|null
|
||||||
|
*/
|
||||||
|
public function getPersonAttributeValue(int $personId, int $definitionId): ?object
|
||||||
|
{
|
||||||
|
$builder = $this->db->table('attribute_values');
|
||||||
|
$builder->join('attribute_links', 'attribute_links.attribute_id = attribute_values.attribute_id');
|
||||||
|
$builder->where('person_id', $personId);
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
$builder->where('definition_id', $definitionId);
|
||||||
|
$query = $builder->get();
|
||||||
|
|
||||||
|
if ($query->getNumRows() == 1) {
|
||||||
|
return $query->getRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getEmptyObject('attribute_values');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves an attribute value for a person
|
||||||
|
*
|
||||||
|
* @param string $attributeValue
|
||||||
|
* @param int $definitionId
|
||||||
|
* @param int $personId
|
||||||
|
* @param int|bool $attributeId
|
||||||
|
* @param string $definitionType
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function savePersonAttributeValue(string $attributeValue, int $definitionId, int $personId, int|bool $attributeId = false, string $definitionType = DROPDOWN): int
|
||||||
|
{
|
||||||
|
$config = config(OSPOS::class)->settings;
|
||||||
|
|
||||||
|
$this->db->transStart();
|
||||||
|
|
||||||
|
switch ($definitionType) {
|
||||||
|
case DATE:
|
||||||
|
$dataType = 'date';
|
||||||
|
$attributeDateValue = DateTime::createFromFormat($config['dateformat'], $attributeValue);
|
||||||
|
$attributeValue = $attributeDateValue ? $attributeDateValue->format('Y-m-d') : $attributeValue;
|
||||||
|
break;
|
||||||
|
case DECIMAL:
|
||||||
|
$dataType = 'decimal';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$dataType = 'value';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Attribute
|
||||||
|
if (empty($attributeId) || empty($personId) || $attributeId == -1) {
|
||||||
|
$attributeId = $this->attributeValueExists($attributeValue, $definitionType);
|
||||||
|
|
||||||
|
if (!$attributeId) {
|
||||||
|
$builder = $this->db->table('attribute_values');
|
||||||
|
$builder->set(["attribute_$dataType" => $attributeValue]);
|
||||||
|
$builder->insert();
|
||||||
|
|
||||||
|
$attributeId = $this->db->insertID();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'attribute_id' => empty($attributeId) ? null : $attributeId,
|
||||||
|
'person_id' => $personId,
|
||||||
|
'definition_id' => $definitionId
|
||||||
|
];
|
||||||
|
|
||||||
|
$builder = $this->db->table('attribute_links');
|
||||||
|
$builder->set($data);
|
||||||
|
$builder->insert();
|
||||||
|
}
|
||||||
|
// Existing Attribute
|
||||||
|
else {
|
||||||
|
$builder = $this->db->table('attribute_values');
|
||||||
|
$builder->set(["attribute_$dataType" => $attributeValue]);
|
||||||
|
$builder->where('attribute_id', $attributeId);
|
||||||
|
$builder->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->transComplete();
|
||||||
|
|
||||||
|
return $attributeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets link values for a person given the person_id and visibility flags
|
||||||
|
*
|
||||||
|
* @param int $personId
|
||||||
|
* @param int $definitionFlags
|
||||||
|
* @return ResultInterface
|
||||||
|
*/
|
||||||
|
public function getPersonLinkValues(int $personId, int $definitionFlags): ResultInterface
|
||||||
|
{
|
||||||
|
$format = $this->db->escape(dateformat_mysql());
|
||||||
|
|
||||||
|
$builder = $this->db->table('attribute_links');
|
||||||
|
$builder->select("GROUP_CONCAT(attribute_value SEPARATOR ', ') AS attribute_values");
|
||||||
|
$builder->select("GROUP_CONCAT(DATE_FORMAT(attribute_date, $format) SEPARATOR ', ') AS attribute_dtvalues");
|
||||||
|
$builder->join('attribute_values', 'attribute_values.attribute_id = attribute_links.attribute_id');
|
||||||
|
$builder->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id');
|
||||||
|
$builder->where('definition_type <>', GROUP);
|
||||||
|
$builder->where('deleted', ACTIVE);
|
||||||
|
$builder->where('person_id', $personId);
|
||||||
|
$builder->where('item_id', null);
|
||||||
|
$builder->where('sale_id', null);
|
||||||
|
$builder->where('receiving_id', null);
|
||||||
|
$builder->where(new RawSql("definition_flags & $definitionFlags"));
|
||||||
|
|
||||||
|
return $builder->get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
169
app/Views/attributes/person.php
Normal file
169
app/Views/attributes/person.php
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $definition_names
|
||||||
|
* @var array $definition_values
|
||||||
|
* @var int $person_id
|
||||||
|
* @var array $config
|
||||||
|
*/
|
||||||
|
|
||||||
|
use App\Models\Attribute;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="form-group form-group-sm">
|
||||||
|
<?= form_label(lang('Attributes.definition_name'), 'definition_name_label', ['class' => 'control-label col-xs-3']) ?>
|
||||||
|
<div class="col-xs-8">
|
||||||
|
<?= form_dropdown([
|
||||||
|
'name' => 'definition_name',
|
||||||
|
'options' => $definition_names,
|
||||||
|
'selected' => -1,
|
||||||
|
'class' => 'form-control',
|
||||||
|
'id' => 'definition_name'
|
||||||
|
]) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php foreach ($definition_values as $definitionId => $definitionValue) { ?>
|
||||||
|
|
||||||
|
<div class="form-group form-group-sm">
|
||||||
|
<?= form_label(esc($definitionValue['definition_name']), esc($definitionValue['definition_name']), ['class' => 'control-label col-xs-3']) ?>
|
||||||
|
<div class="col-xs-8">
|
||||||
|
<div class="input-group">
|
||||||
|
<?php
|
||||||
|
echo form_hidden("attribute_ids[$definitionId]", strval($definitionValue['attribute_id']));
|
||||||
|
$attributeValue = $definitionValue['attribute_value'];
|
||||||
|
|
||||||
|
switch ($definitionValue['definition_type']) {
|
||||||
|
case DATE:
|
||||||
|
$value = (empty($attributeValue) || empty($attributeValue->attribute_date)) ? NOW : strtotime($attributeValue->attribute_date);
|
||||||
|
echo form_input([
|
||||||
|
'name' => "attribute_links[$definitionId]",
|
||||||
|
'value' => to_date($value),
|
||||||
|
'class' => 'form-control input-sm datetime',
|
||||||
|
'data-definition-id' => $definitionId,
|
||||||
|
'readonly' => 'true'
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case DROPDOWN:
|
||||||
|
$selectedValue = $definitionValue['selected_value'];
|
||||||
|
echo form_dropdown([
|
||||||
|
'name' => "attribute_links[$definitionId]",
|
||||||
|
'options' => $definitionValue['values'],
|
||||||
|
'selected' => $selectedValue,
|
||||||
|
'class' => 'form-control',
|
||||||
|
'data-definition-id' => $definitionId
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case TEXT:
|
||||||
|
$value = (empty($attributeValue) || empty($attributeValue->attribute_value)) ? $definitionValue['selected_value'] : $attributeValue->attribute_value;
|
||||||
|
echo form_input([
|
||||||
|
'name' => "attribute_links[$definitionId]",
|
||||||
|
'value' => esc($value),
|
||||||
|
'class' => 'form-control valid_chars',
|
||||||
|
'data-definition-id' => $definitionId
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case DECIMAL:
|
||||||
|
$value = (empty($attributeValue) || empty($attributeValue->attribute_decimal)) ? $definitionValue['selected_value'] : $attributeValue->attribute_decimal;
|
||||||
|
echo form_input([
|
||||||
|
'name' => "attribute_links[$definitionId]",
|
||||||
|
'value' => to_decimals((float)$value),
|
||||||
|
'class' => 'form-control valid_chars',
|
||||||
|
'data-definition-id' => $definitionId
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case CHECKBOX:
|
||||||
|
$value = (empty($attributeValue) || empty($attributeValue->attribute_value)) ? $definitionValue['selected_value'] : $attributeValue->attribute_value;
|
||||||
|
|
||||||
|
// Sends 0 if the box is unchecked instead of not sending anything.
|
||||||
|
echo form_input([
|
||||||
|
'type' => 'hidden',
|
||||||
|
'name' => "attribute_links[$definitionId]",
|
||||||
|
'id' => "attribute_links[$definitionId]",
|
||||||
|
'value' => 0,
|
||||||
|
'data-definition-id' => $definitionId
|
||||||
|
]);
|
||||||
|
echo form_checkbox([
|
||||||
|
'name' => "attribute_links[$definitionId]",
|
||||||
|
'id' => "attribute_links[$definitionId]",
|
||||||
|
'value' => 1,
|
||||||
|
'checked' => $value == 1,
|
||||||
|
'class' => 'checkbox-inline',
|
||||||
|
'data-definition-id' => $definitionId
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<span class="input-group-addon input-sm btn btn-default remove_attribute_btn">
|
||||||
|
<span class="glyphicon glyphicon-trash"></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function() {
|
||||||
|
<?= view('partial/datepicker_locale', ['format' => dateformat_bootstrap($config['dateformat'])]) ?>
|
||||||
|
|
||||||
|
var enableDelete = function() {
|
||||||
|
$('.remove_attribute_btn').click(function() {
|
||||||
|
$(this).parents('.form-group').remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
enableDelete();
|
||||||
|
|
||||||
|
$("input[name*='attribute_links']").change(function() {
|
||||||
|
var definitionId = $(this).data('definition-id');
|
||||||
|
$("input[name='attribute_ids[" + definitionId + "]']").val('');
|
||||||
|
}).autocomplete({
|
||||||
|
source: function(request, response) {
|
||||||
|
$.get('<?= 'attributes/suggestAttribute/' ?>' + this.element.data('definition-id') + '?term=' + request.term, function(data) {
|
||||||
|
return response(data);
|
||||||
|
}, 'json');
|
||||||
|
},
|
||||||
|
appendTo: '.modal-content',
|
||||||
|
select: function(event, ui) {
|
||||||
|
event.preventDefault();
|
||||||
|
$(this).val(ui.item.label);
|
||||||
|
},
|
||||||
|
delay: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
var getDefinitionValues = function() {
|
||||||
|
var result = {};
|
||||||
|
$("[name*='attribute_links']").each(function() {
|
||||||
|
var definitionId = $(this).data('definition-id');
|
||||||
|
var element = $(this);
|
||||||
|
|
||||||
|
// For checkboxes, use the visible checkbox, not the hidden input
|
||||||
|
if (element.attr('type') === 'hidden' && element.siblings('input[type="checkbox"]').length > 0) {
|
||||||
|
// Skip hidden inputs that have a corresponding checkbox
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For checkboxes, get the checked state
|
||||||
|
if (element.attr('type') === 'checkbox') {
|
||||||
|
result[definitionId] = element.prop('checked') ? '1' : '0';
|
||||||
|
} else {
|
||||||
|
result[definitionId] = element.val();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
var refresh = function() {
|
||||||
|
var definitionId = $("#definition_name option:selected").val();
|
||||||
|
var attributeValues = getDefinitionValues();
|
||||||
|
attributeValues[definitionId] = '';
|
||||||
|
$('#person_attributes').load(window.location.href, {
|
||||||
|
'definition_ids': JSON.stringify(attributeValues)
|
||||||
|
}, enableDelete);
|
||||||
|
};
|
||||||
|
|
||||||
|
$('#definition_name').change(function() {
|
||||||
|
refresh();
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
@@ -44,6 +44,12 @@
|
|||||||
|
|
||||||
<?= view('people/form_basic_info') ?>
|
<?= view('people/form_basic_info') ?>
|
||||||
|
|
||||||
|
<div id="person_attributes">
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#person_attributes').load('<?= "customers/attributes/$person_info->person_id" ?>');
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group form-group-sm">
|
<div class="form-group form-group-sm">
|
||||||
<?= form_label(lang('Customers.discount_type'), 'discount_type', ['class' => 'control-label col-xs-3']) ?>
|
<?= form_label(lang('Customers.discount_type'), 'discount_type', ['class' => 'control-label col-xs-3']) ?>
|
||||||
<div class="col-xs-8">
|
<div class="col-xs-8">
|
||||||
|
|||||||
@@ -29,6 +29,12 @@
|
|||||||
<div class="tab-pane fade in active" id="employee_basic_info">
|
<div class="tab-pane fade in active" id="employee_basic_info">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<?= view('people/form_basic_info') ?>
|
<?= view('people/form_basic_info') ?>
|
||||||
|
|
||||||
|
<div id="person_attributes">
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#person_attributes').load('<?= "employees/attributes/$person_info->person_id" ?>');
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,12 @@
|
|||||||
|
|
||||||
<?= view('people/form_basic_info') ?>
|
<?= view('people/form_basic_info') ?>
|
||||||
|
|
||||||
|
<div id="person_attributes">
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#person_attributes').load('<?= "suppliers/attributes/$person_info->person_id" ?>');
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group form-group-sm">
|
<div class="form-group form-group-sm">
|
||||||
<?= form_label(lang('Suppliers.account_number'), 'account_number', ['class' => 'control-label col-xs-3']) ?>
|
<?= form_label(lang('Suppliers.account_number'), 'account_number', ['class' => 'control-label col-xs-3']) ?>
|
||||||
<div class="col-xs-8">
|
<div class="col-xs-8">
|
||||||
|
|||||||
Reference in New Issue
Block a user