ICS modules

This commit is contained in:
Thanakorn S
2026-03-21 14:58:15 +07:00
parent 2e558a55bb
commit a4f474b5df
45 changed files with 3110 additions and 597 deletions
+11
View File
@@ -78,3 +78,14 @@
.page-item-secondary .page-link {
color: var(--bs-secondary);
}
.card-loader-overlay {
position: absolute;
inset: 0;
background: rgba(255, 255, 255, 0.85);
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
border-radius: inherit;
}
+126
View File
@@ -115,6 +115,111 @@ $(function () {
});
$('input.contact_search').each(function (i, el) {
var $el = $(el);
$el.autocomplete({
// Fetch data from server
source: function (request, response) {
// Abort previous request (prevent multiple firing)
if ($el.data('xhr')) {
$el.data('xhr').abort();
}
// Prepare payload
let q = prepare_form_data(0, true);
q['keyword'] = request.term;
let json = JSON.stringify(q);
// Send AJAX request
var xhr = $.ajax({
url: server_url + 'ics/api/engine/contact_search.php',
type: 'POST',
dataType: 'json',
data: { json: json },
// for CSRF validation
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
success: function (res) {
var aca = [];
// Map result to autocomplete format
$.each(res.result, function (i, item) {
var temp = "";
temp += "<div class='contact-result-item' style='font-family:\"Poppins\",sans-serif;padding:4px 0;'>";
temp += "<div style='font-size:10px;text-transform:uppercase;color:#E66239;font-weight:600;line-height:1.2;'>";
temp += "Tax ID: " + (item.tax_id || 'N/A');
temp += "</div>";
temp += "<div style='font-size:13px;font-weight:500;color:#171717;margin-top:2px;'>";
temp += item.contact_name;
temp += "</div>";
temp += "</div>";
aca.push({
label: temp, // HTML dropdown
value: item.contact_name, // Default value
data: item // Full object
});
});
response(aca);
}
});
// Save request reference
$el.data('xhr', xhr);
},
minLength: 0,
delay: 300,
// When selecting item
select: function (e, ui) {
if (ui.item && ui.item.data) {
var contact = ui.item.data;
// Replace input value with SKU
$(this)
.val(contact.contact_name)
.attr("data-id", contact.id)
.attr("secondary", contact.contact_name);
console.log("Input updated with contact name:", contact.contact_name);
return false; // Prevent overwrite by default value
}
}
})
// Allow HTML rendering in dropdown
.data("ui-autocomplete")._renderItem = function (ul, item) {
return $("<li>")
.append($("<div>").html(item.label))
.appendTo(ul);
};
// Add this ↓
$el.on('blur', function () {
var secondary = $(this).attr('secondary');
console.log($(this).attr('data-id'))
if (secondary) {
$('input#contact').val($('input#contact').attr('secondary'));
}
});
});
});
@@ -400,3 +505,24 @@ document.addEventListener('DOMContentLoaded', () => {
});
});
/**
* Helper function to format date strings (assuming input is in ISO format)
*/
function format_date(iso_string) {
var split = iso_string.split(" ");
if (split.length === 2) {
var datePart = split[0].split("-");
}
return (datePart) ? `${datePart[2]}/${datePart[1]}/${datePart[0]} ${split[1]}` : iso_string;
}
function format_number(value, decimal) {
var n = Number(value);
if (isNaN(n)) return '--';
if (decimal !== undefined) n = n.toFixed(decimal);
var parts = n.toString().split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
}
+272
View File
@@ -57,8 +57,12 @@ function db_check($sth, &$answer, $options = []) {
$log_message = $options['log'] ?? "DB Error";
error_log($log_message . " in " . $trace['file'] . " line " . $trace['line'] . ": " . $sth->errorInfo()[2]);
// production version
$answer["message"] = $options['message'] ?? "A server error occurred. Please try again.";
// development version
$answer["message"] = $sth->errorInfo()[2];
http_response_code($options['code'] ?? 500);
if(isset($options['before_exit'])) {
@@ -148,6 +152,7 @@ if(!empty($_SESSION["login_company_id"])){
$company_id = (int)$_SESSION["login_company_id"];
$user_id = (int)$_SESSION["login_user_id"];
$uuid = bin2hex(random_bytes(16));
// create json for table logging
$logging = array(
@@ -158,4 +163,271 @@ if(!empty($_SESSION["login_company_id"])){
);
}
/**
* HELPER CLASSES AND FUNCTIONS
* These are designed to be reusable across different API endpoints for consistent data handling and error management.
* They are not specific to any single operation and can be used wherever similar patterns arise.
*/
/**
* Helper class to manage data consistency
*/
class WarehouseManager {
private $pdo;
private $company_id;
public function __construct($pdo, $company_id) {
$this->pdo = $pdo;
$this->company_id = $company_id;
}
public function getWarehouseName($warehouse_id) {
$sql = "SELECT warehouse_name FROM md_warehouse
WHERE company_id = :company_id AND id = :warehouse_id";
$sth = $this->pdo->prepare($sql);
$sth->execute([
":company_id" => $this->company_id,
":warehouse_id" => $warehouse_id
]);
return $sth->fetchColumn();
}
public function getStockContext($warehouse_id, $id) {
$name = $this->getWarehouseName($warehouse_id);
$table = "td_stock_" . $name;
$sql = "SELECT * FROM `$table`
WHERE company_id = :company_id AND id = :id";
$sth = $this->pdo->prepare($sql);
$sth->execute([
":company_id" => $this->company_id,
":id" => $id
]);
return [
'table' => $table,
'name' => $name,
'row' => $sth->fetch(PDO::FETCH_ASSOC) ?: []
];
}
public function adjustBalance($type, $warehouse_id, $product_sku, $old_qty, $new_qty) {
// Lock the row — other transactions wait here
$sql = "SELECT id FROM warehouse_balance
WHERE company_id = :company_id
AND warehouse_id = :warehouse_id
AND product_sku = :product_sku
FOR UPDATE";
$sth = $this->pdo->prepare($sql);
$sth->execute([
":company_id" => $this->company_id,
":warehouse_id" => $warehouse_id,
":product_sku" => $product_sku
]);
if (!$sth->fetchColumn()) {
$sql = "INSERT INTO warehouse_balance
(company_id, warehouse_id, product_sku)
VALUES (:company_id, :warehouse_id, :product_sku)";
$sth = $this->pdo->prepare($sql);
$sth->execute([
":company_id" => $this->company_id,
":warehouse_id" => $warehouse_id,
":product_sku" => $product_sku
]);
}
$column = $type === 'in' ? 'total_in' : 'total_out';
// This is already atomic since it uses relative update
$sql = "UPDATE warehouse_balance
SET `$column` = `$column` - :old_qty + :new_qty
WHERE company_id = :company_id
AND warehouse_id = :warehouse_id
AND product_sku = :product_sku";
$sth = $this->pdo->prepare($sql);
$sth->execute([
":company_id" => $this->company_id,
":warehouse_id" => $warehouse_id,
":product_sku" => $product_sku,
":old_qty" => $old_qty,
":new_qty" => $new_qty
]);
}
}
class FileUploader {
private $target_dir;
private $allowed_mimes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf'];
private $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf'];
private $max_size = 5 * 1024 * 1024; // 5MB
private $uploaded_files = []; // newly uploaded filenames
private $deleted_files = []; // files we deleted from disk
public function __construct($target_dir) {
$this->target_dir = rtrim($target_dir, '/') . '/';
$this->ensureDirectory();
}
private function ensureDirectory() {
if (!is_dir($this->target_dir)) {
mkdir($this->target_dir, 0755, true);
}
if (!is_writable($this->target_dir)) {
throw new Exception("Target directory is not writable.");
}
}
/**
* Remove files that user deleted in the UI
*/
public function cleanup($existing_csv, $keep_csv) {
if (empty($existing_csv)) return;
$existing = array_filter(array_map('trim', explode(',', $existing_csv)));
$keep = !empty($keep_csv) ? array_filter(array_map('trim', explode(',', $keep_csv))) : [];
foreach ($existing as $file) {
if (!in_array($file, $keep)) {
$path = $this->target_dir . $file;
if (file_exists($path)) {
unlink($path);
$this->deleted_files[] = $file;
}
}
}
}
/**
* Upload new files from $_FILES
* Returns array of errors (empty = success)
*/
public function upload($field_name) {
if (!isset($_FILES[$field_name])) return [];
$errors = [];
foreach ($_FILES[$field_name]['name'] as $key => $name) {
$error_code = $_FILES[$field_name]['error'][$key];
if ($error_code !== UPLOAD_ERR_OK) {
$errors[] = "{$name}: " . $this->getUploadError($error_code);
continue;
}
$tmp_name = $_FILES[$field_name]['tmp_name'][$key];
$file_size = $_FILES[$field_name]['size'][$key];
$extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if ($file_size > $this->max_size) {
$errors[] = "{$name}: exceeds " . ($this->max_size / 1024 / 1024) . "MB limit";
continue;
}
if (!in_array($extension, $this->allowed_extensions)) {
$errors[] = "{$name}: .{$extension} is not allowed";
continue;
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmp_name);
finfo_close($finfo);
if (!in_array($mime, $this->allowed_mimes)) {
$errors[] = "{$name}: content type ({$mime}) is not allowed";
continue;
}
$file_id = uniqid() . "_" . time() . "." . $extension;
$destination = $this->target_dir . $file_id;
if (move_uploaded_file($tmp_name, $destination)) {
$this->uploaded_files[] = $file_id;
chmod($destination, 0644);
} else {
$errors[] = "{$name}: failed to save";
}
}
return $errors;
}
/**
* Build final CSV string for DB
*/
public function buildFileString($keep_csv) {
$keep = !empty($keep_csv) ? array_filter(array_map('trim', explode(',', $keep_csv))) : [];
$final = array_merge($keep, $this->uploaded_files);
return implode(",", array_filter($final));
}
/**
* Rollback uploaded files if DB fails
*/
public function rollbackUploads() {
foreach ($this->uploaded_files as $file) {
$path = $this->target_dir . $file;
if (file_exists($path)) {
unlink($path);
}
}
$this->uploaded_files = [];
}
private function getUploadError($code) {
$messages = [
UPLOAD_ERR_INI_SIZE => "exceeds server max upload size (" . ini_get('upload_max_filesize') . ")",
UPLOAD_ERR_FORM_SIZE => "exceeds form max size",
UPLOAD_ERR_PARTIAL => "was only partially uploaded",
UPLOAD_ERR_NO_FILE => "no file was sent",
UPLOAD_ERR_NO_TMP_DIR => "server missing temp folder",
UPLOAD_ERR_CANT_WRITE => "server failed to write to disk",
UPLOAD_ERR_EXTENSION => "blocked by server extension",
];
return $messages[$code] ?? "unknown error (code {$code})";
}
}
/**
* Helper function
*/
// transaction wrapper with retry logic for deadlocks
function dbTransaction($pdo, $callback, $maxRetries = 3) {
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
try {
$pdo->beginTransaction();
$result = $callback($pdo);
$pdo->commit();
return $result;
} catch (PDOException $e) {
$pdo->rollBack();
if ($e->getCode() == '40001' && $attempt < $maxRetries - 1) {
usleep(600000 * ($attempt + 1));
continue;
}
error_log("[DB ERROR] " . $e->getMessage() . " | " . $e->getFile() . ":" . $e->getLine());
throw $e;
} catch (Exception $e) {
$pdo->rollBack();
error_log("[ERROR] " . $e->getMessage() . " | " . $e->getFile() . ":" . $e->getLine());
throw $e;
}
}
}
?>
+46 -153
View File
@@ -1,162 +1,46 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
/** * FILE SYNCHRONIZATION & UPLOAD LOGIC
* -----------------------------------------------------------------------------------
* Strategy: "Keep & Sync"
* 1. Identify which existing files were removed by the user and delete them from disk.
* 2. Upload any brand-new files dropped into the Dropzone.
* 3. Re-assemble a final comma-separated string containing (Kept Files + New Files).
* -----------------------------------------------------------------------------------
*/
try {
/** 1. FILE HANDLING **/
$uploader = new FileUploader($include_url . "uploads/contact/");
// Define the physical path for storage
$target_dir = $include_url . "uploads/contact/";
/** 1. DISK CLEANUP (Removal of deleted files) **/
// Cleanup deleted files
if ($id > 0) {
// Fetch currently stored filenames from DB for comparison
$sql_check = "SELECT `files` FROM md_contact WHERE company_id = :company_id AND id = :id";
$sth_check = $pdo2->prepare($sql_check);
$sth_check->execute([":company_id" => $company_id, ":id" => $id]);
$existing_db_string = $sth_check->fetchColumn();
if (!empty($existing_db_string)) {
$existing_files_array = explode(',', $existing_db_string);
// 'keep_files' comes from JS (Dropzone.files names currently in the UI)
$keep_files = isset($data['keep_files']) ? explode(',', $data['keep_files']) : [];
foreach ($existing_files_array as $file_on_disk) {
$file_on_disk = trim($file_on_disk);
if (empty($file_on_disk)) continue;
/**
* If a file exists in the database but is NOT in the 'keep_files' list,
* it means the user clicked 'Remove' in the UI. We delete it from the server.
*/
if (!in_array($file_on_disk, $keep_files)) {
$full_path = $target_dir . $file_on_disk;
if (file_exists($full_path)) {
unlink($full_path); // Physically remove (rm) the file
}
}
}
}
}
/** 2. PERMISSION & DIRECTORY CHECK **/
$parent_dir = dirname($target_dir);
if (!is_writable($parent_dir)) {
exit(json_encode([
"success" => 0,
"message" => "Server error: Target directory is not writable. Check permissions."
]));
}
// Ensure the directory exists
if (!is_dir($target_dir)) {
mkdir($target_dir, 0755, true);
}
/** 3. PROCESSING NEW UPLOADS **/
$uploaded_names = [];
// Allowed MIME types whitelist
$allowed_mimes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf'];
// Allowed extensions whitelist
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf'];
// Max file size: 5MB
$max_size = 5 * 1024 * 1024;
if (isset($_FILES['contact_files'])) {
foreach ($_FILES['contact_files']['name'] as $key => $name) {
if ($_FILES['contact_files']['error'][$key] === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['contact_files']['tmp_name'][$key];
$file_size = $_FILES['contact_files']['size'][$key];
$extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
// Check 1: File size
if ($file_size > $max_size) {
error_log("Rejected oversized file: " . $name);
continue;
}
// Check 2: Extension whitelist
if (!in_array($extension, $allowed_extensions)) {
error_log("Rejected extension: " . $name);
continue;
}
// Check 3: Real MIME type (reads actual file bytes, not filename)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmp_name);
finfo_close($finfo);
if (!in_array($mime, $allowed_mimes)) {
error_log("Rejected MIME type: " . $mime . " for file: " . $name);
continue;
}
// Safe unique filename — no original extension trusted
$file_id = uniqid() . "_" . time() . "." . $extension;
$destination = $target_dir . $file_id;
if (move_uploaded_file($tmp_name, $destination)) {
$uploaded_names[] = $file_id;
chmod($destination, 0644);
} else {
error_log("Failed to move uploaded file: " . $name);
}
}
}
}
/** 4. CONSTRUCTING THE FINAL DATABASE STRING **/
// Parse files the user kept from the existing session
$keep_files = isset($data['keep_files']) ? explode(',', $data['keep_files']) : [];
// Merge old kept filenames with the brand-new unique filenames
$final_file_array = array_merge($keep_files, $uploaded_names);
// Clean up: Remove empty values and trim whitespace
$final_file_array = array_filter(array_map('trim', $final_file_array));
// The final comma-separated string for the DB 'files' column
$db_image_string = implode(",", $final_file_array);
/********************************************************************************** */
// 2. Initialize log array
$table_log = [];
// Get existing log and existing files if updating
if ($id > 0) {
$sql = "SELECT `log`, `files` FROM md_contact WHERE company_id = :company_id AND id = :id";
$sql = "SELECT `files` FROM md_contact WHERE company_id = :company_id AND id = :id";
$sth = $pdo2->prepare($sql);
$sth->execute([":company_id" => $company_id, ":id" => $id]);
$uploader->cleanup($sth->fetchColumn(), $data['keep_files'] ?? '');
}
// Upload new files
$errors = $uploader->upload('contact_files');
if (!empty($errors)) {
$answer["success"] = 0;
$answer["message"] = $errors[0];
exit(json_encode($answer));
}
$db_image_string = $uploader->buildFileString($data['keep_files'] ?? '');
/** 2. DATABASE **/
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, $id, $db_image_string) {
$sql = "SELECT `log` FROM md_contact
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
$row = $sth->fetch(PDO::FETCH_ASSOC);
if ($row) {
$table_log = json_decode($row['log'] ?? '[]', true);
}
}
// Append the new log entry
$table_log = json_decode($sth->fetchColumn() ?: '[]', true);
if (!is_array($table_log)) $table_log = [];
$table_log[] = $logging;
// 3. Database Operation
$params = [
":company_id" => $company_id,
":contact_name" => $data["contact_name"],
@@ -170,11 +54,10 @@
":remark" => $data["remark"],
":files" => $db_image_string,
":status" => (int)$data["status"],
":log" => json_encode($table_log)
":log" => json_encode($table_log),
];
if ($id > 0) {
// UPDATE
$sql = "UPDATE md_contact SET
`contact_name` = :contact_name,
`tax_id` = :tax_id,
@@ -189,24 +72,34 @@
`status` = :status,
`log` = :log
WHERE id = :id AND company_id = :company_id";
$params[":id"] = $id;
$sth = $pdo2->prepare($sql);
$sth->execute($params);
} else {
// INSERT
$sql = "INSERT INTO md_contact
(company_id, contact_name, tax_id, organization, branch, contact_type,
billing_address, shipping_location, shipping_address, remark, files, status, log)
VALUES
(:company_id, :contact_name, :tax_id, :organization, :branch, :contact_type,
:billing_address, :shipping_location, :shipping_address, :remark, :files, :status, :log)";
$sth = $pdo2->prepare($sql);
$sth->execute($params);
}
$sth = $pdo->prepare($sql);
$sth->execute($params);
});
$answer["success"] = 1;
} catch (PDOException $e) {
// DB failed — rollback uploaded files
if (isset($uploader)) $uploader->rollbackUploads();
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
if (isset($uploader)) $uploader->rollbackUploads();
$answer["success"] = 0;
$answer["message"] = $e->getMessage();
}
exit(json_encode($answer));
?>
+35 -46
View File
@@ -1,43 +1,34 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging) {
$id = (int)$data['id'];
// Initialize log array
$table_log = [];
// Get existing log only if we are updating an existing record
if ($id > 0) {
$sql = "SELECT `log`
FROM md_contact_type
WHERE
company_id = :company_id AND
id = :id";
$sth = $pdo2->prepare($sql);
$sql = "SELECT `log` FROM md_contact_type
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
"id" => $id
":id" => $id
]);
if ($sth->errorCode() !== '00000') {
$error = $sth->errorInfo();
$answer["message"] = $error[2] ?? $error[0];
exit(json_encode($answer));
}
$row = $sth->fetch(PDO::FETCH_ASSOC);
if ($row) {
$table_log = json_decode($row['log'] ?? '[]', true);
}
}
// Append the new log entry (assuming $logging is defined in your preset/utils)
$table_log = json_decode($sth->fetchColumn() ?: '[]', true);
if (!is_array($table_log)) $table_log = [];
$table_log[] = $logging;
$params = [
":company_id" => $company_id,
":contact_type" => $data["contact_type"],
":description" => $data["description"],
":status" => (int)$data["status"],
":log" => json_encode($table_log),
];
if ($id > 0) {
// UPDATE existing record
$sql = "UPDATE md_contact_type SET
`contact_type` = :contact_type,
`description` = :description,
@@ -45,33 +36,31 @@
`log` = :log
WHERE id = :id AND company_id = :company_id";
$sth = $pdo2->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
":contact_type" => $data["contact_type"],
":description" => $data["description"],
":status" => (int)$data["status"],
":log" => json_encode($table_log),
]);
$params[":id"] = $id;
} else {
// INSERT new record
$sql = "INSERT INTO md_contact_type
(company_id, contact_type, `description`, `status`, `log`)
VALUES
(:company_id, :contact_type, :description, :status, :log)";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":contact_type" => $data["contact_type"],
":description" => $data["description"],
":status" => (int)$data["status"],
":log" => json_encode($table_log),
]);
}
$sth = $pdo->prepare($sql);
$sth->execute($params);
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+1 -1
View File
@@ -185,7 +185,7 @@
url: "<?php echo $server_url?>contact/api/engine/manage_contact.php",
autoPrepare: true,
checkRequired: 1,
debugMode: 1,
debugMode: 0,
formData: formData,
action: 'manage',
onSuccess: function(res) {
+2 -2
View File
@@ -84,7 +84,7 @@
}
function retreive_for_edit() {
function retrieve_for_edit() {
<?php if(empty($_GET['id'])){ ?>
return false;
@@ -114,7 +114,7 @@
$(async function() {
try {
await retreive_for_edit();
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
+2
View File
@@ -75,8 +75,10 @@ class db_statement extends PDOStatement {
//..................... PDO1 .....................//
$pdo1 = new database($db_type.':host='.$db_server.';dbname='.$db_database.';charset=utf8', $db_user, $db_pass);
$pdo1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//..................... PDO2 .....................//
$pdo2 = new database($db_type2.':host='.$db_server2.';dbname='.$db_database2.';charset=utf8', $db_user2, $db_pass2);
$pdo2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>
+25
View File
@@ -0,0 +1,25 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$sql = "SELECT *
FROM md_contact
WHERE
company_id = :company_id and
contact_name like :keyword
LIMIT 50
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":keyword" => '%'.$data["keyword"].'%'
]);
db_check($sth, $answer);
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
$answer["result"] = $result;
$answer["success"] = 1;
exit(json_encode($answer));
?>
+87
View File
@@ -0,0 +1,87 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, $uuid, &$answer) {
$id = (int)$data['id'];
$warehouse_id = (int)$data["warehouse"];
$whMgmt = new WarehouseManager($pdo, $company_id);
$warehouse = $whMgmt->getStockContext($warehouse_id, $id);
$row = $warehouse['row'] ?? [];
$table = $warehouse['table'];
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log[] = $logging;
if ($id > 0) {
$sql = "UPDATE `$table` SET
`product_sku` = :product_sku,
`in` = :quantity,
`zone` = :zone,
`aisle` = :aisle,
`rack` = :rack,
`contact_id` = :contact_id,
`description` = :description,
`log` = :log
WHERE id = :id AND company_id = :company_id";
$sth = $pdo->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
":product_sku" => $data["product_sku"],
":quantity" => $data["quantity"],
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
} else {
$sql = "INSERT INTO `$table`
(uuid, company_id, `date`, product_sku, `in`, zone, aisle, rack, contact_id, `description`, `log`, `type`)
VALUES
(:uuid, :company_id, :date, :product_sku, :quantity, :zone, :aisle, :rack, :contact_id, :description, :log, 'in')";
$sth = $pdo->prepare($sql);
$sth->execute([
":uuid" => $uuid,
":company_id" => $company_id,
":date" => date('Y-m-d H:i:s'),
":product_sku" => $data["product_sku"],
":quantity" => $data["quantity"],
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
}
$whMgmt->adjustBalance('in', $warehouse_id, $data["product_sku"], $row['in'] ?? 0, $data["quantity"]);
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+87
View File
@@ -0,0 +1,87 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, $uuid) {
$id = (int)$data['id'];
$warehouse_id = (int)$data["warehouse"];
$whMgmt = new WarehouseManager($pdo, $company_id);
$warehouse = $whMgmt->getStockContext($warehouse_id, $id);
$row = $warehouse['row'] ?? [];
$table = $warehouse['table'];
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log[] = $logging;
if ($id > 0) {
$sql = "UPDATE `$table` SET
`product_sku` = :product_sku,
`out` = :quantity,
`zone` = :zone,
`aisle` = :aisle,
`rack` = :rack,
`contact_id` = :contact_id,
`description` = :description,
`log` = :log
WHERE id = :id AND company_id = :company_id";
$sth = $pdo->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
":product_sku" => $data["product_sku"],
":quantity" => $data["quantity"],
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
} else {
$sql = "INSERT INTO `$table`
(uuid, company_id, `date`, product_sku, `out`, zone, aisle, rack, contact_id, `description`, `log`, `type`)
VALUES
(:uuid, :company_id, :date, :product_sku, :quantity, :zone, :aisle, :rack, :contact_id, :description, :log, 'out')";
$sth = $pdo->prepare($sql);
$sth->execute([
":uuid" => $uuid,
":company_id" => $company_id,
":date" => date('Y-m-d H:i:s'),
":product_sku" => $data["product_sku"],
":quantity" => $data["quantity"],
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
}
$whMgmt->adjustBalance('out', $warehouse_id, $data["product_sku"], $row['out'] ?? 0, $data["quantity"]);
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
@@ -0,0 +1,113 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, $uuid) {
$id = (int)$data['id'];
$whMgmt = new WarehouseManager($pdo, $company_id);
for ($i = 0; $i < 2; $i++) {
$data['type'] = ($i == 0) ? "from" : "to";
$data['ref_type'] = ($i == 0) ? "to" : "from";
$data['col'] = ($i == 0) ? "out" : "in";
$warehouse_id = (int)$data['warehouse_' . $data["type"]];
$ref_warehouse_id = (int)$data['warehouse_' . $data["ref_type"]];
$data["warehouse"] = $data['warehouse_' . $data["type"]];
$data["zone"] = $data['zone_' . $data["type"]];
$data["aisle"] = $data['aisle_' . $data["type"]];
$data["rack"] = $data['rack_' . $data["type"]];
$warehouse = $whMgmt->getStockContext($warehouse_id, $id);
$row = $warehouse['row'] ?? [];
$table = $warehouse['table'];
// get uuid for update
if ($id > 0 && $data['type'] == "from") {
$sql = "SELECT uuid FROM `$table`
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
$uuid = $sth->fetchColumn();
}
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log[] = $logging;
if ($id > 0) {
$sql = "UPDATE `$table` SET
`product_sku` = :product_sku,
`{$data['col']}` = :quantity,
`zone` = :zone,
`aisle` = :aisle,
`rack` = :rack,
`contact_id` = :contact_id,
`description` = :description,
`log` = :log
WHERE uuid = :uuid AND company_id = :company_id";
$sth = $pdo->prepare($sql);
$sth->execute([
":uuid" => $uuid,
":company_id" => $company_id,
":product_sku" => $data["product_sku"],
":quantity" => $data["quantity"],
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
} else {
$sql = "INSERT INTO `$table`
(uuid, company_id, `date`, product_sku, `{$data['col']}`, ref_warehouse, zone, aisle, rack, contact_id, `description`, `log`, `type`)
VALUES
(:uuid, :company_id, :date, :product_sku, :quantity, :ref_warehouse, :zone, :aisle, :rack, :contact_id, :description, :log, 'transfer')";
$sth = $pdo->prepare($sql);
$sth->execute([
":uuid" => $uuid,
":company_id" => $company_id,
":date" => date('Y-m-d H:i:s'),
":product_sku" => $data["product_sku"],
":quantity" => $data["quantity"],
":ref_warehouse" => $ref_warehouse_id,
":zone" => $data["zone"],
":aisle" => $data["aisle"],
":rack" => $data["rack"],
":contact_id" => (int)$data["contact_id"],
":description" => $data["description"],
":log" => json_encode($table_log),
]);
}
$whMgmt->adjustBalance($data['col'], $warehouse_id, $data["product_sku"], $row[$data['col']] ?? 0, $data["quantity"]);
}
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+9 -2
View File
@@ -4,7 +4,14 @@
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
// identity source of zone and aisle
if(empty($data["type"])){
$warehouse = (int)$data['warehouse'];
$zone = $data['zone'];
}else{
$warehouse = (int)$data['warehouse_'.$data["type"]];
$zone = $data['zone_'.$data["type"]];
}
$sql = "SELECT *
FROM md_storage
@@ -18,7 +25,7 @@
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse,
":zone" => $data["zone"]
":zone" => $zone
]);
db_check($sth, $answer);
@@ -26,7 +33,7 @@
$output = [];
foreach ($pre as $key => $value) {
$output = array_merge($output, range($value["aisle_form"], $value["aisle_to"]));
$output = array_merge($output, range($value["aisle_from"], $value["aisle_to"]));
}
$answer["output"] = $output;
+24 -5
View File
@@ -3,8 +3,26 @@
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
// identity source of zone and aisle
if(empty($data["type"])){
$warehouse = (int)$data['warehouse'];
$zone = $data['zone'];
$aisle = $data["aisle"];
}else{
$warehouse = (int)$data['warehouse_'.$data["type"]];
$zone = $data['zone_'.$data["type"]];
$aisle = $data["aisle_".$data["type"]];
}
// Detect if numeric and zero-pad both input and query columns
if (is_numeric($aisle)) {
$aisle = str_pad($aisle, 5, '0', STR_PAD_LEFT);
$condition = "LPAD(aisle_from, 5, '0') <= :aisle_from AND LPAD(aisle_to, 5, '0') >= :aisle_to";
} else {
$condition = ":aisle_from >= aisle_from AND :aisle_to <= aisle_to";
}
$id = (int)$data['id'];
$sql = "SELECT *
FROM md_storage
@@ -12,15 +30,16 @@
company_id = :company_id and
warehouse = :warehouse and
`zone` = :zone and
:aisle between aisle_from and aisle_to
$condition
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse,
":zone" => $data["zone"],
":aisle" => $data["aisle"]
":zone" => $zone,
":aisle_from" => $aisle,
":aisle_to" => $aisle
]);
db_check($sth, $answer);
@@ -28,7 +47,7 @@
$output = [];
foreach ($pre as $key => $value) {
$output = array_merge($output, range($value["rack_form"], $value["rack_to"]));
$output = array_merge($output, range($value["rack_from"], $value["rack_to"]));
}
$answer["output"] = $output;
+51
View File
@@ -0,0 +1,51 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
$warehouse = (int)$data["wh"];
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , a.in as quantity, b.contact_name, c.product_name
FROM `{$table}` a
LEFT JOIN md_contact b ON
a.company_id = b.company_id and
a.contact_id = b.id
LEFT JOIN md_product c ON
a.company_id = b.company_id and
a.product_sku = c.sku
WHERE
a.company_id = :company_id and
a.id = :id ";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$answer["output"] = $sth->fetch(PDO::FETCH_ASSOC);
$answer["success"] = 1;
exit(json_encode($answer));
?>
+51
View File
@@ -0,0 +1,51 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
$warehouse = (int)$data["wh"];
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , a.out as quantity, b.contact_name, c.product_name
FROM `{$table}` a
LEFT JOIN md_contact b ON
a.company_id = b.company_id and
a.contact_id = b.id
LEFT JOIN md_product c ON
a.company_id = b.company_id and
a.product_sku = c.sku
WHERE
a.company_id = :company_id and
a.id = :id ";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$answer["output"] = $sth->fetch(PDO::FETCH_ASSOC);
$answer["success"] = 1;
exit(json_encode($answer));
?>
@@ -0,0 +1,101 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
$warehouse = (int)$data["wh"];
/**
* FROM warehouse, zone, aisle, rack, product name, quantity, contact name
*/
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , a.out as quantity, b.contact_name, c.product_name
FROM `{$table}` a
LEFT JOIN md_contact b ON
a.company_id = b.company_id and
a.contact_id = b.id
LEFT JOIN md_product c ON
a.company_id = b.company_id and
a.product_sku = c.sku
WHERE
a.company_id = :company_id and
a.id = :id ";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$output = $sth->fetch(PDO::FETCH_ASSOC);
/**
* TO warehouse, zone, aisle, rack, product name, quantity, contact name
*/
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $output["ref_warehouse"]
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , a.in as quantity, b.contact_name, c.product_name
FROM `{$table}` a
LEFT JOIN md_contact b ON
a.company_id = b.company_id and
a.contact_id = b.id
LEFT JOIN md_product c ON
a.company_id = b.company_id and
a.product_sku = c.sku
WHERE
a.company_id = :company_id and
a.uuid = :id ";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $output["uuid"]
]);
db_check($sth, $answer);
$output["ref"] = $sth->fetch(PDO::FETCH_ASSOC);
$answer["output"] = $output;
$answer["success"] = 1;
exit(json_encode($answer));
?>
+6
View File
@@ -4,7 +4,13 @@
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
// identity source of zone and aisle
if(empty($data["type"])){
$warehouse = (int)$data['warehouse'];
}else{
$warehouse = (int)$data['warehouse_'.$data["type"]];
}
$sql = "SELECT *
FROM md_storage
+53
View File
@@ -0,0 +1,53 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
$warehouse = (int)$data["warehouse"];
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
if(!$warehouse) {
$answer["message"] = "Warehouse not found";
exit(json_encode($answer));
}
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , ROUND(a.in,2) as quantity ,
b.product_name
FROM `{$table}` a
LEFT JOIN md_product b ON
a.company_id = b.company_id and
a.product_sku = b.sku
WHERE
a.company_id = {$company_id} and
a.type = 'in'
ORDER BY a.date DESC";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id
]);
db_check($sth, $answer);
$answer["output"] = $sth->fetchAll(PDO::FETCH_ASSOC);
$answer["success"] = 1;
exit(json_encode($answer));
?>
+53
View File
@@ -0,0 +1,53 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
$warehouse = (int)$data["warehouse"];
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
if(!$warehouse) {
$answer["message"] = "Warehouse not found";
exit(json_encode($answer));
}
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , ROUND(a.out,2) as quantity ,
b.product_name
FROM `{$table}` a
LEFT JOIN md_product b ON
a.company_id = b.company_id and
a.product_sku = b.sku
WHERE
a.company_id = {$company_id} and
a.type = 'out'
ORDER BY a.date DESC";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id
]);
db_check($sth, $answer);
$answer["output"] = $sth->fetchAll(PDO::FETCH_ASSOC);
$answer["success"] = 1;
exit(json_encode($answer));
?>
+54
View File
@@ -0,0 +1,54 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
$warehouse = (int)$data["warehouse"];
// get warehouse name
$sql = "SELECT warehouse_name
FROM md_warehouse
WHERE
company_id = :company_id and
id = :warehouse
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $warehouse
]);
db_check($sth, $answer);
$warehouse = $sth->fetchColumn();
if(!$warehouse) {
$answer["message"] = "Warehouse not found";
exit(json_encode($answer));
}
$table = "td_stock_" . $warehouse;
$sql = "SELECT a.* , ROUND(a.in,2) as quantity,
b.product_name
FROM `{$table}` a
LEFT JOIN md_product b ON
a.company_id = b.company_id and
a.product_sku = b.sku
WHERE
a.company_id = {$company_id} and
a.type = 'transfer' and
a.out > 0
ORDER BY a.date DESC";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id
]);
db_check($sth, $answer);
$answer["output"] = $sth->fetchAll(PDO::FETCH_ASSOC);
$answer["success"] = 1;
exit(json_encode($answer));
?>
+24
View File
@@ -0,0 +1,24 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$sql = "SELECT SUM(capacity) as total_capacity, count(*) as total_warehouse
FROM md_warehouse a
WHERE
a.company_id = :company_id
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id
]);
db_check($sth, $answer);
$output = $sth->fetch(PDO::FETCH_ASSOC);
$answer["output"] = $output;
$answer["success"] = 1;
exit(json_encode($answer));
?>
@@ -76,14 +76,14 @@
<!-- Contact -->
<div class="mb-3 col-lg-6">
<label for="contact" class="form-label">Contact</label>
<input type="text" class="form-control" id="contact" placeholder="Enter contact name">
<input type="text" class="form-control contact_search" id="contact" placeholder="Enter contact name">
</div>
<!-- Notes / Description -->
<div class="mb-3 col-lg-12">
<label for="notes" class="form-label">Notes / Description</label>
<textarea class="form-control" id="notes" rows="3" placeholder="Enter any notes"></textarea>
<label for="description" class="form-label">Notes / Description</label>
<textarea class="form-control" id="description" rows="3" placeholder="Enter any notes"></textarea>
</div>
<!-- Submit Button -->
@@ -108,8 +108,11 @@
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/manage_stock_in.php",
autoPrepare: true,
checkRequired: 0,
checkRequired: 1,
debugMode: 0,
data: {
"contact_id": $("#contact").attr('data-id')
},
action: 'manage',
onSuccess: function(res) {
@@ -142,13 +145,14 @@
function retrieve_zone() {
function retrieve_zone(callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_zone.php",
autoPrepare: true,
checkRequired: 0,
noLoading: true,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select zone</option>`;
@@ -156,6 +160,8 @@
option += `<option value='${item.zone}'>${item.zone}</option>`;
})
$(`select#zone`).html(option);
if (callback) callback(); // ← add this
}
});
@@ -163,7 +169,7 @@
function retrieve_aisle() {
function retrieve_aisle(callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_aisle.php",
@@ -177,6 +183,8 @@
option += `<option value='${item}'>${item}</option>`;
})
$(`select#aisle`).html(option);
if (callback) callback(); // ← add this
}
});
@@ -184,7 +192,7 @@
function retrieve_rack() {
function retrieve_rack(callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_rack.php",
@@ -198,6 +206,71 @@
option += `<option value='${item}'>${item}</option>`;
})
$(`select#rack`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_for_edit() {
<?php if(empty($_GET["id"])){ ?>
return false;
<?php } ?>
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_stock_in.php",
autoPrepare: true,
checkRequired: 0,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
var data = res.output;
// 1. Set warehouse (already populated from page load)
$(`#warehouse`).val('<?php echo $_GET["wh"];?>').attr('disabled', true); // set warehouse BEFORE retrieve_zone
// 2. Retrieve zone (autoPrepare reads warehouse value)
retrieve_zone(function() {
$(`select#zone`).val(data.zone).attr('disabled', true); // set zone BEFORE retrieve_aisle
// 3. Retrieve aisle (autoPrepare reads zone value)
retrieve_aisle(function() {
$(`#aisle`).val(data.aisle).attr('disabled', true); // set aisle BEFORE retrieve_rack
// 4. Retrieve rack (autoPrepare reads aisle value)
retrieve_rack(function() {
$(`#rack`).val(data.rack).attr('disabled', true);
// retrieve for edit
$.each(data, function(key, item) {
if (!['warehouse', 'zone', 'aisle', 'rack'].includes(key)) {
$(`#${key}`).val(item);
}
});
$('#contact').val(data.contact_name)
.attr('secondary', data.contact_name)
.attr('data-id', data.contact_id);
$('#product_name').val(data.product_name);
$('#product_sku').attr('secondary', data.product_sku);
$(`button[type=submit]`).text('Update');
$(`button[type=reset]`).hide();
});
});
});
// Set re
}
});
@@ -208,12 +281,13 @@
$(async function() {
try {
await retrieve_warehouse();
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
});
<?php if(empty($_GET["id"])){ ?>
$("select#warehouse").change(function() {
retrieve_zone();
});
@@ -226,7 +300,7 @@
retrieve_rack();
});
<?php } ?>
</script>
</body>
+307
View File
@@ -0,0 +1,307 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row ">
<div class="col-12">
<div class="mb-6">
<h1 class="fs-3 mb-0">Stock Out</h1>
</div>
</div>
</div>
<div class="row g">
<div class="col-lg-8 col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="fs-5 mb-4">Add Stock</h2>
<form class="row gx-5">
<!-- Product Name -->
<div class="mb-3 col-lg-3">
<label for="product_sku" class="form-label">SKU</label>
<input type="text" id="product_sku" class="form-control product_search"
placeholder="Type product sku..." autocomplete="off" required>
</div>
<div class="mb-3 col-lg-3">
<label for="product_name" class="form-label">Name</label>
<input type="text" id="product_name" class="form-control" autocomplete="off" disabled>
</div>
<!-- SKU or Product Code -->
<div class="mb-3 col-lg-6">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" class="form-control" id="quantity" placeholder="Enter quantity" required>
</div>
<!-- Warehouse -->
<div class="mb-3 col-lg-6">
<label for="warehouse" class="form-label">Warehouse</label>
<select name="warehouse" id="warehouse" class="form-select" required></select>
</div>
<div class="mb-3 col-lg-6">
<label for="zone" class="form-label">Zone</label>
<select name="zone" id="zone" class="form-select" required>
<option value="">Please select zone</option>
</select>
</div>
<div class="mb-3 col-lg-6">
<label for="aisle" class="form-label">Aisle</label>
<select name="aisle" id="aisle" class="form-select" required>
<option value="">Please select aisle</option>
</select>
</div>
<div class="mb-3 col-lg-6">
<label for="rack" class="form-label">Rack</label>
<select name="rack" id="rack" class="form-select" required>
<option value="">Please select rack</option>
</select>
</div>
<!-- Contact -->
<div class="mb-3 col-lg-6">
<label for="contact" class="form-label">Contact</label>
<input type="text" class="form-control contact_search" id="contact" placeholder="Enter contact name">
</div>
<!-- Notes / Description -->
<div class="mb-3 col-lg-12">
<label for="description" class="form-label">Notes / Description</label>
<textarea class="form-control" id="description" rows="3" placeholder="Enter any notes"></textarea>
</div>
<!-- Submit Button -->
<div class="mb-3 col-lg-12">
<button type="submit" class="btn btn-primary" onclick="manage_stock_out();">Add Stock</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<script>
function manage_stock_out() {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/manage_stock_out.php",
autoPrepare: true,
checkRequired: 1,
debugMode: 0,
data: {
"contact_id": $("#contact").attr('data-id')
},
action: 'manage',
onSuccess: function(res) {
window.location.href = "<?php echo $server_url?>ics/stock_out.php";
}
});
}
function retrieve_warehouse() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/warehouse.php",
autoPrepare: true,
checkRequired: 0,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select warehouse</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item.id}'>${item.warehouse_name}</option>`;
})
$(`select#warehouse`).html(option);
}
});
}
function retrieve_zone(callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_zone.php",
autoPrepare: true,
checkRequired: 0,
noLoading: true,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select zone</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item.zone}'>${item.zone}</option>`;
})
$(`select#zone`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_aisle(callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_aisle.php",
autoPrepare: true,
checkRequired: 0,
noLoading: true,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select aisle</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item}'>${item}</option>`;
})
$(`select#aisle`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_rack(callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_rack.php",
autoPrepare: true,
checkRequired: 0,
noLoading: true,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select rack</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item}'>${item}</option>`;
})
$(`select#rack`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_for_edit() {
<?php if(empty($_GET["id"])){ ?>
return false;
<?php } ?>
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_stock_out.php",
autoPrepare: true,
checkRequired: 0,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
var data = res.output;
// 1. Set warehouse (already populated from page load)
$(`#warehouse`).val(<?php echo $_GET["wh"];?>).attr('disabled', true); // set warehouse BEFORE retrieve_zone
// 2. Retrieve zone (autoPrepare reads warehouse value)
retrieve_zone(function() {
$(`select#zone`).val(data.zone).attr('disabled', true); // set zone BEFORE retrieve_aisle
// 3. Retrieve aisle (autoPrepare reads zone value)
retrieve_aisle(function() {
$(`#aisle`).val(data.aisle).attr('disabled', true); // set aisle BEFORE retrieve_rack
// 4. Retrieve rack (autoPrepare reads aisle value)
retrieve_rack(function() {
$(`#rack`).val(data.rack).attr('disabled', true);
// retrieve for edit
$.each(data, function(key, item) {
if (!['warehouse', 'zone', 'aisle', 'rack'].includes(key)) {
$(`#${key}`).val(item);
}
});
$('#contact').val(data.contact_name)
.attr('secondary', data.contact_name)
.attr('data-id', data.contact_id);
$('#product_name').val(data.product_name);
$('#product_sku').attr('secondary', data.product_sku);
$(`button[type=submit]`).text('Update');
$(`button[type=reset]`).hide();
});
});
});
// Set re
}
});
}
$(async function() {
try {
await retrieve_warehouse();
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
});
<?php if(empty($_GET["id"])){ ?>
$("select#warehouse").change(function() {
retrieve_zone();
});
$("select#zone").change(function() {
retrieve_aisle();
});
$("select#aisle").change(function() {
retrieve_rack();
});
<?php } ?>
</script>
</body>
</html>
+369
View File
@@ -0,0 +1,369 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row ">
<div class="col-12">
<div class="mb-6">
<h1 class="fs-3 mb-0">Stock Transfer</h1>
</div>
</div>
</div>
<div class="row g">
<div class="col-lg-8 col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="fs-5 mb-4">Add Stock</h2>
<form class="row gx-5">
<!-- Product Name -->
<div class="mb-3 col-lg-3">
<label for="product_sku" class="form-label">SKU</label>
<input type="text" id="product_sku" class="form-control product_search"
placeholder="Type product sku..." autocomplete="off" required>
</div>
<div class="mb-3 col-lg-3">
<label for="product_name" class="form-label">Name</label>
<input type="text" id="product_name" class="form-control" autocomplete="off" disabled>
</div>
<!-- SKU or Product Code -->
<div class="mb-3 col-lg-6">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" class="form-control" id="quantity" placeholder="Enter quantity" required>
</div>
<!-- Warehouse -->
<div class="mb-3 col-lg-3">
<label for="warehouse" class="form-label">From Warehouse</label>
<select name="warehouse" id="warehouse_from" role="from" class="form-select" required></select>
</div>
<div class="mb-3 col-lg-3">
<label for="zone" class="form-label">From Zone</label>
<select name="zone" id="zone_from" role="from" class="form-select" required>
<option value="">Please select zone</option>
</select>
</div>
<div class="mb-3 col-lg-3">
<label for="aisle" class="form-label">From Aisle</label>
<select name="aisle" id="aisle_from" role="from" class="form-select" required>
<option value="">Please select aisle</option>
</select>
</div>
<div class="mb-3 col-lg-3">
<label for="rack" class="form-label">From Rack</label>
<select name="rack" id="rack_from" role="from" class="form-select" required>
<option value="">Please select rack</option>
</select>
</div>
<!-- Warehouse -->
<div class="mb-3 col-lg-3">
<label for="warehouse" class="form-label">To Warehouse</label>
<select name="warehouse" id="warehouse_to" role="to" class="form-select" required></select>
</div>
<div class="mb-3 col-lg-3">
<label for="zone" class="form-label">To Zone</label>
<select name="zone" id="zone_to" role="to" class="form-select" required>
<option value="">Please select zone</option>
</select>
</div>
<div class="mb-3 col-lg-3">
<label for="aisle" class="form-label">To Aisle</label>
<select name="aisle" id="aisle_to" role="to" class="form-select" required>
<option value="">Please select aisle</option>
</select>
</div>
<div class="mb-3 col-lg-3">
<label for="rack" class="form-label">To Rack</label>
<select name="rack" id="rack_to" role="to" class="form-select" required>
<option value="">Please select rack</option>
</select>
</div>
<!-- Contact -->
<div class="mb-3 col-lg-6">
<label for="contact" class="form-label">Contact</label>
<input type="text" class="form-control contact_search" id="contact" placeholder="Enter contact name">
</div>
<!-- Notes / Description -->
<div class="mb-3 col-lg-12">
<label for="description" class="form-label">Notes / Description</label>
<textarea class="form-control" id="description" rows="3" placeholder="Enter any notes"></textarea>
</div>
<!-- Submit Button -->
<div class="mb-3 col-lg-12">
<button type="submit" class="btn btn-primary" onclick="manage_stock_transfer();">Add Stock</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<script>
function manage_stock_transfer() {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/manage_stock_transfer.php",
autoPrepare: true,
checkRequired: 1,
debugMode: 0,
data: {
"contact_id": $("#contact").attr('data-id')
},
action: 'manage',
onSuccess: function(res) {
window.location.href = "<?php echo $server_url?>ics/stock_transfer.php";
}
});
}
function retrieve_warehouse(type) {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/warehouse.php",
autoPrepare: true,
checkRequired: 0,
data: {
"type": type
},
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select warehouse</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item.id}'>${item.warehouse_name}</option>`;
})
$(`select[name='warehouse'][role='${type}']`).html(option);
}
});
}
function retrieve_zone(type, callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_zone.php",
autoPrepare: true,
checkRequired: 0,
data: {
"type": type
},
noLoading: true,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select zone</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item.zone}'>${item.zone}</option>`;
})
$(`select[name='zone'][role='${type}']`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_aisle(type, callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_aisle.php",
autoPrepare: true,
checkRequired: 0,
data: {
"type": type
},
noLoading: true,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select aisle</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item}'>${item}</option>`;
})
$(`select[name='aisle'][role='${type}']`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_rack(type, callback) {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_rack.php",
autoPrepare: true,
checkRequired: 0,
data: {
"type": type
},
noLoading: true,
action: 'read',
onSuccess: function(res) {
var option = `<option value="">Please select rack</option>`;
$.each(res.output, function(key, item) {
option += `<option value='${item}'>${item}</option>`;
})
$(`select[name='rack'][role='${type}']`).html(option);
if (callback) callback(); // ← add this
}
});
}
function retrieve_for_edit() {
<?php if(empty($_GET["id"])){ ?>
return false;
<?php } ?>
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/retrieve_stock_transfer.php",
autoPrepare: true,
checkRequired: 0,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
var type = 'from';
var warehouse = res.output.ref.ref_warehouse;
var data = res.output;
/**
* From warehouse
*/
$(`select[name='warehouse'][role=${type}]`).val(warehouse).attr('disabled', true);
retrieve_zone(type, function() {
$(`select[name='zone'][role=${type}]`).val(data.zone).attr('disabled', true);
retrieve_aisle(type, function() {
$(`select[name='aisle'][role=${type}]`).val(data.aisle).attr('disabled', true);
retrieve_rack(type, function() {
$(`select[name='rack'][role=${type}]`).val(data.rack).attr('disabled', true);
type = 'to';
warehouse = res.output.ref_warehouse;
data = res.output.ref;
/**
* To warehouse
*/
$(`select[name='warehouse'][role=${type}]`).val(warehouse).attr('disabled', true);
retrieve_zone(type, function() {
$(`select[name='zone'][role=${type}]`).val(data.zone).attr('disabled', true);
retrieve_aisle(type, function() {
$(`select[name='aisle'][role=${type}]`).val(data.aisle).attr('disabled',true);
retrieve_rack(type, function() {
$(`select[name='rack'][role=${type}]`).val(data.rack).attr('disabled',true);
});
});
});
});
});
});
var data = res.output;
// retrieve for edit
$.each(data, function(key, item) {
if (!['warehouse', 'zone', 'aisle', 'rack'].includes(key)) {
$(`#${key}`).val(item);
}
});
$('#contact').val(data.contact_name)
.attr('secondary', data.contact_name)
.attr('data-id', data.contact_id);
$('#product_name').val(data.product_name);
$('#product_sku').attr('secondary', data.product_sku);
$(`button[type=submit]`).text('Update');
$(`button[type=reset]`).hide();
}
});
}
$(async function() {
try {
await retrieve_warehouse("from");
await retrieve_warehouse("to");
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
});
<?php if(empty($_GET["id"])){ ?>
$("select[name='warehouse']").change(function() {
retrieve_zone($(this).attr('role'));
});
$("select[name='zone']").change(function() {
retrieve_aisle($(this).attr('role'));
});
$("select[name='aisle']").change(function() {
retrieve_rack($(this).attr('role'));
});
<?php } ?>
</script>
</body>
</html>
+110 -4
View File
@@ -18,7 +18,7 @@
<div class="mb-6 d-flex justify-content-between align-items-center">
<h1 class="fs-3 mb-0">Stock in
</h1>
<a href="<?php echo $server_url?>ics/add_stock_in.php" class="btn btn-primary">
<a href="<?php echo $server_url?>ics/manage_stock_in.php" class="btn btn-primary">
<span><i class="ti ti-plus"></i></span>
<span>ADD Stock In</span></a>
@@ -27,18 +27,31 @@
</div>
<div class="row g-5">
<div class="mb-3 col-lg-2">
<input class="form-control" value='Warehouse' disabled>
</div>
<div class="mb-3 col-lg-4">
<select name="warehouse" id="warehouse" class="form-select" required></select>
</div>
<div class="mb-3 col-lg-6">
<button class='btn btn-secondary' onclick='retrieve_stock_in()'>Search</button>
</div>
<div class="col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="mb-4 fs-5">Item List</h2>
<div class="table-responsive">
<table class="table table-hover mb-0 table-centered" id="product">
<table class="table table-hover mb-0 table-centered" id="stock_in">
<thead class="table-primary border-light">
<tr>
<th>Date</th>
<th>Product</th>
<th>Quantity</th>
<th>Warehouse</th>
<th>Storage Location</th>
<th>Zone</th>
<th>Aisle</th>
<th>Rack</th>
<th>Status</th>
<th>Action</th>
</tr>
@@ -63,7 +76,100 @@
<?php require "../include_ending.php";?>
<script>
function retrieve_stock_in() {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/stock_in.php",
autoPrepare: true,
checkRequired: 0,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
// Register the array as a table name
alasql('CREATE TABLE IF NOT EXISTS stock_in');
alasql.tables.stock_in.data = res.output || [];
var total_records = alasql.tables.stock_in.data.length;
var table_id = 'stock_in';
var page = generate_pagination(table_id, total_records);
$(`table#${table_id} tfoot`).html(page);
// dynamic function name
if (typeof window[`change_page_${table_id}`] === "function") {
window[`change_page_${table_id}`](1);
} else {
console.error(`Function change_page_${table_id} does not exist.`);
}
}
});
}
function change_page_stock_in(page_num) {
var offset = (page_num - 1) * prop_limit;
var page_data = alasql(`SELECT * FROM stock_in LIMIT ${prop_limit} OFFSET ${offset}`);
var body = ``;
var warehouse = $(`select#warehouse`).val();
$.each(page_data, function(key, item) {
body += `<tr>
<td class="py-3">${format_date(item["date"])}</td>
<td class="py-3">${item["product_sku"]}: ${item['product_name']}</td>
<td class="py-3">${item['quantity']}</td>
<td class="py-3">${item['zone']}</td>
<td class="py-3">${item['aisle']}</td>
<td class="py-3">${item['rack']}</td>
<td class="py-3">
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
</td>
<td class="py-3">
<a href="<?php echo $server_url?>ics/manage_stock_in.php?id=${item['id']}&wh=${warehouse}" class=""><i class="ti ti-eye fs-5"></i></a>
<a href="#" class="link-danger"><i class="ti ti-trash ms-2 fs-5"></i></a>
</td>
</tr>`;
})
$("table#stock_in > tbody").html(body);
}
function retrieve_warehouse() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/warehouse.php",
autoPrepare: true,
checkRequired: 0,
action: 'read',
onSuccess: function(res) {
var option = ``;
$.each(res.output, function(key, item) {
option += `<option value='${item.id}'>${item.warehouse_name}</option>`;
})
$(`select#warehouse`).html(option);
}
});
}
$(async function() {
try {
await retrieve_warehouse();
await retrieve_stock_in();
} catch (e) {
console.log(e);
}
});
</script>
</body>
+177
View File
@@ -0,0 +1,177 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row ">
<div class="col-12">
<div class="mb-6 d-flex justify-content-between align-items-center">
<h1 class="fs-3 mb-0">Stock Out
</h1>
<a href="<?php echo $server_url?>ics/manage_stock_out.php" class="btn btn-primary">
<span><i class="ti ti-plus"></i></span>
<span>ADD Stock Out</span></a>
</div>
</div>
</div>
<div class="row g-5">
<div class="mb-3 col-lg-2">
<input class="form-control" value='Warehouse' disabled>
</div>
<div class="mb-3 col-lg-4">
<select name="warehouse" id="warehouse" class="form-select" required></select>
</div>
<div class="mb-3 col-lg-6">
<button class='btn btn-secondary' onclick='retrieve_stock_out()'>Search</button>
</div>
<div class="col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="mb-4 fs-5">Item List</h2>
<div class="table-responsive">
<table class="table table-hover mb-0 table-centered" id="stock_out">
<thead class="table-primary border-light">
<tr>
<th>Date</th>
<th>Product</th>
<th>Quantity</th>
<th>Zone</th>
<th>Aisle</th>
<th>Rack</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody></tbody>
<tfoot class="">
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<script>
function retrieve_stock_out() {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/stock_out.php",
autoPrepare: true,
checkRequired: 0,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
// Register the array as a table name
alasql('CREATE TABLE IF NOT EXISTS stock_out');
alasql.tables.stock_out.data = res.output || [];
var total_records = alasql.tables.stock_out.data.length;
var table_id = 'stock_out';
var page = generate_pagination(table_id, total_records);
$(`table#${table_id} tfoot`).html(page);
// dynamic function name
if (typeof window[`change_page_${table_id}`] === "function") {
window[`change_page_${table_id}`](1);
} else {
console.error(`Function change_page_${table_id} does not exist.`);
}
}
});
}
function change_page_stock_out(page_num) {
var offset = (page_num - 1) * prop_limit;
var page_data = alasql(`SELECT * FROM stock_out LIMIT ${prop_limit} OFFSET ${offset}`);
var body = ``;
var warehouse = $(`select#warehouse`).val();
$.each(page_data, function(key, item) {
body += `<tr>
<td class="py-3">${format_date(item["date"])}</td>
<td class="py-3">${item["product_sku"]}: ${item['product_name']}</td>
<td class="py-3">${item['quantity']}</td>
<td class="py-3">${item['zone']}</td>
<td class="py-3">${item['aisle']}</td>
<td class="py-3">${item['rack']}</td>
<td class="py-3">
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
</td>
<td class="py-3">
<a href="<?php echo $server_url?>ics/manage_stock_out.php?id=${item['id']}&wh=${warehouse}" class=""><i class="ti ti-eye fs-5"></i></a>
<a href="#" class="link-danger"><i class="ti ti-trash ms-2 fs-5"></i></a>
</td>
</tr>`;
})
$("table#stock_out > tbody").html(body);
}
function retrieve_warehouse() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/warehouse.php",
autoPrepare: true,
checkRequired: 0,
action: 'read',
onSuccess: function(res) {
var option = ``;
$.each(res.output, function(key, item) {
option += `<option value='${item.id}'>${item.warehouse_name}</option>`;
})
$(`select#warehouse`).html(option);
}
});
}
$(async function() {
try {
await retrieve_warehouse();
await retrieve_stock_out();
} catch (e) {
console.log(e);
}
});
</script>
</body>
</html>
+52 -18
View File
@@ -23,23 +23,26 @@
</div>
<div class="row g-5 mb-5">
<div class="col-xl-3 col-md-6 col-12">
<div class="card ">
<div class="card" id="capacity">
<div class="card-body p-5">
<div class="d-flex justify-content-between">
<div>
<span class="mb-4 d-block">Total Sales</span>
<h3 class="fw-bold mb-0">1,234</h3>
<span class="mb-4 d-block">Total Capacity</span>
<h3 class="fw-bold mb-0 text-info">0</h3>
<p class="mb-0 small text-secondary">Across all warehouses</p>
</div>
<div class="">
<i class="ti ti-box-seam fs-3 text-muted"></i>
</div>
</div>
<!-- overlay -->
<div class="card-loader-overlay">
<div class="spinner-border spinner-border-sm text-primary"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 col-12">
<div class="card ">
<div class="card-body p-5">
@@ -53,6 +56,10 @@
<i class="ti ti-trending-up fs-3 text-success"></i>
</div>
</div>
<!-- overlay -->
<div class="card-loader-overlay">
<div class="spinner-border spinner-border-sm text-primary"></div>
</div>
</div>
</div>
@@ -71,6 +78,10 @@
<i class="ti ti-trending-down fs-3 text-danger"></i>
</div>
</div>
<!-- overlay -->
<div class="card-loader-overlay">
<div class="spinner-border spinner-border-sm text-primary"></div>
</div>
</div>
</div>
@@ -89,6 +100,10 @@
<i class="ti ti-alert-triangle fs-3 text-warning"></i>
</div>
</div>
<!-- overlay -->
<div class="card-loader-overlay">
<div class="spinner-border spinner-border-sm text-primary"></div>
</div>
</div>
</div>
@@ -116,6 +131,10 @@
<div>
<div id="stockMovementChart"></div>
</div>
<!-- overlay -->
<div class="card-loader-overlay">
<div class="spinner-border spinner-border-sm text-primary"></div>
</div>
</div>
</div>
@@ -134,6 +153,10 @@
<div>
<div id="stockLevelTrendChart"></div>
</div>
<!-- overlay -->
<div class="card-loader-overlay">
<div class="spinner-border spinner-border-sm text-primary"></div>
</div>
</div>
</div>
@@ -232,19 +255,6 @@
</div>
</div>
<div class="row">
<div class="col-12">
<footer class="text-center py-2 mt-6 text-secondary ">
<p class="mb-0">Copyright © 2026 InApp Inventory Dashboard. Developed by <a href="https://codescandy.com/"
target="_blank" class="text-primary">CodesCandy</a> </p>
</footer>
</div>
</div>
<div class="position-fixed end-0 bottom-0 m-4">
<a href="https://codescandy.com/template/inventory-admin-dashboard-template/" class="btn btn-dark"
target="_blank"> Download Now</a>
</div>
</div>
</main>
@@ -252,7 +262,31 @@
<?php require "../include_ending.php";?>
<script>
function retrieve_warehouse_stats() {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/warehouse_stats.php",
autoPrepare: true,
checkRequired: 0,
action: 'read',
onSuccess: function(res) {
console.log(res);
$("#capacity h3").text(format_number(res.output.total_capacity,2));
$("#capacity p").text("Accross "+ format_number(res.output.total_warehouse) + " warehouses");
$("#capacity .card-loader-overlay").hide();
}
});
}
$(function() {
retrieve_warehouse_stats();
});
</script>
+177
View File
@@ -0,0 +1,177 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row ">
<div class="col-12">
<div class="mb-6 d-flex justify-content-between align-items-center">
<h1 class="fs-3 mb-0">Stock Transfer
</h1>
<a href="<?php echo $server_url?>ics/manage_stock_transfer.php" class="btn btn-primary">
<span><i class="ti ti-plus"></i></span>
<span>ADD Stock Transfer</span></a>
</div>
</div>
</div>
<div class="row g-5">
<div class="mb-3 col-lg-2">
<input class="form-control" value='Warehouse From' disabled>
</div>
<div class="mb-3 col-lg-4">
<select name="warehouse" id="warehouse" class="form-select" required></select>
</div>
<div class="mb-3 col-lg-4">
<button class='btn btn-secondary' onclick='retrieve_stock_transfer()'>Search</button>
</div>
<div class="col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="mb-4 fs-5">Item List</h2>
<div class="table-responsive">
<table class="table table-hover mb-0 table-centered" id="stock_transfer">
<thead class="table-primary border-light">
<tr>
<th>Date</th>
<th>Product</th>
<th>Quantity</th>
<th>Zone</th>
<th>Aisle</th>
<th>Rack</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody></tbody>
<tfoot class="">
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<script>
function retrieve_stock_transfer() {
return ajax_request({
url: "<?php echo $server_url?>ics/api/engine/stock_transfer.php",
autoPrepare: true,
checkRequired: 0,
debugMode: 0,
action: 'read',
onSuccess: function(res) {
// Register the array as a table name
alasql('CREATE TABLE IF NOT EXISTS stock_transfer');
alasql.tables.stock_transfer.data = res.output || [];
var total_records = alasql.tables.stock_transfer.data.length;
var table_id = 'stock_transfer';
var page = generate_pagination(table_id, total_records);
$(`table#${table_id} tfoot`).html(page);
// dynamic function name
if (typeof window[`change_page_${table_id}`] === "function") {
window[`change_page_${table_id}`](1);
} else {
console.error(`Function change_page_${table_id} does not exist.`);
}
}
});
}
function change_page_stock_transfer(page_num) {
var offset = (page_num - 1) * prop_limit;
var page_data = alasql(`SELECT * FROM stock_transfer LIMIT ${prop_limit} OFFSET ${offset}`);
var body = ``;
var warehouse = $(`select#warehouse`).val();
$.each(page_data, function(key, item) {
body += `<tr>
<td class="py-3">${format_date(item["date"])}</td>
<td class="py-3">${item["product_sku"]}: ${item['product_name']}</td>
<td class="py-3">${item['quantity']}</td>
<td class="py-3">${item['zone']}</td>
<td class="py-3">${item['aisle']}</td>
<td class="py-3">${item['rack']}</td>
<td class="py-3">
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
</td>
<td class="py-3">
<a href="<?php echo $server_url?>ics/manage_stock_transfer.php?id=${item['id']}&wh=${warehouse}" class=""><i class="ti ti-eye fs-5"></i></a>
<a href="#" class="link-danger"><i class="ti ti-trash ms-2 fs-5"></i></a>
</td>
</tr>`;
})
$("table#stock_transfer > tbody").html(body);
}
function retrieve_warehouse() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/warehouse.php",
autoPrepare: true,
checkRequired: 0,
action: 'read',
onSuccess: function(res) {
var option = ``;
$.each(res.output, function(key, item) {
option += `<option value='${item.id}'>${item.warehouse_name}</option>`;
})
$(`select#warehouse`).html(option);
}
});
}
$(async function() {
try {
await retrieve_warehouse();
await retrieve_stock_transfer();
} catch (e) {
console.log(e);
}
});
</script>
</body>
</html>
+1 -1
View File
@@ -46,8 +46,8 @@
<!-- theme script -->
<link rel="stylesheet" href="<?php echo $server_url?>assets/css/main.css">
<link rel="stylesheet" href="<?php echo $server_url?>assets/css/custom.css">
<script type="module" src="<?php echo $server_url?>assets/js/main.js"></script>
<link rel="stylesheet" href="<?php echo $server_url?>assets/css/custom.css">
<script src="<?php echo $server_url?>assets/js/custom.js"></script>
</head>
+59
View File
@@ -0,0 +1,59 @@
<!-- SIDEBAR -->
<aside id="sidebar" class="sidebar overflow-y-auto">
<div class="logo-area">
<a href="<?php echo $server_url?>index.php" class="d-inline-flex">
<img
src="data:image/svg+xml,%3csvg%20width='62'%20height='67'%20viewBox='0%200%2062%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M30.604%2066.378L0.00805664%2048.1582V35.7825L30.604%2054.0023V66.378Z'%20fill='%23302C4D'/%3e%3cpath%20d='M61.1996%2048.1582L30.604%2066.378V54.0023L61.1996%2035.7825V48.1582Z'%20fill='%23E66239'/%3e%3cpath%20d='M30.5955%200L0%2018.2198V30.5955L30.5955%2012.3757V0Z'%20fill='%23657E92'/%3e%3cpath%20d='M61.191%2018.2198L30.5955%200V12.3757L61.191%2030.5955V18.2198Z'%20fill='%23A3B2BE'/%3e%3cpath%20d='M30.604%2048.8457L0.00805664%2030.6259V18.2498L30.604%2036.47V48.8457Z'%20fill='%23302C4D'/%3e%3cpath%20d='M61.1996%2030.6259L30.604%2048.8457V36.47L61.1996%2018.2498V30.6259Z'%20fill='%23E66239'/%3e%3c/svg%3e"
alt=""
width="24"
/>
<span class="logo-text ms-2">
<img src="./assets/images/logo.svg" alt="" />
</span>
</a>
</div>
<ul class="nav flex-column">
<!-- Main -->
<li class="nav-text-space">
<small class="nav-text text-muted">Setting</small>
</li>
<li>
<a class="nav-link active" href="index.html">
<i class="ti ti-home"></i>
<span class="nav-text">Dashboard</span>
</a>
</li>
<li>
<a class="nav-link" href="inventory.html">
<i class="ti ti-box-seam"></i>
<span class="nav-text">Inventory</span>
</a>
</li>
<li>
<a class="nav-link" href="low-stock-products.html">
<i class="ti ti-alert-triangle"></i>
<span class="nav-text">Low Stock Products</span>
</a>
</li>
<li>
<a class="nav-link" href="stock-expired.html">
<i class="ti ti-clock"></i>
<span class="nav-text">Expired Stock</span>
</a>
</li>
<li>
<a class="nav-link" href="reports.html">
<i class="ti ti-receipt"></i>
<span class="nav-text">Reports</span>
</a>
</li>
</ul>
</aside>
+2 -2
View File
@@ -100,14 +100,14 @@
</li>
<li>
<a class="nav-link" href="stock-out.html">
<a class="nav-link" href="<?php echo $server_url?>ics/stock_out.php">
<i class="ti ti-package-export"></i>
<span class="nav-text">Stock Out</span>
</a>
</li>
<li>
<a class="nav-link" href="stock-out.html">
<a class="nav-link" href="<?php echo $server_url?>ics/stock_transfer.php">
<i class="ti ti-package"></i>
<span class="nav-text">Stock Transfer</span>
</a>
+14
View File
@@ -5,6 +5,8 @@ if(!isset($_SESSION["otp"])){
header('Location: '.$server_url.'login/index.php');
}
require 'preset.php';
?>
<div id="overlay" class="overlay"></div>
@@ -109,6 +111,11 @@ if(!isset($_SESSION["otp"])){
<span>Switch Branch</span>
</a>
<a href="javascript:;" class="" onclick="profile_setting();">
<span> Setting</span>
</a>
<a href="javascript:;" class="" onclick="log_out();">
<span> Log Out</span>
@@ -145,4 +152,11 @@ function log_out() {
});
}
function profile_setting(){
window.location.href = "<?php echo $server_url?>setting/profile.php";
}
</script>
+22 -17
View File
@@ -1,27 +1,21 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging) {
$id = (int)$data['id'];
// get existing log
$sql = "SELECT `log`
FROM md_product_category
WHERE
company_id = :company_id and
id = :id";
$sth = $pdo2->prepare($sql);
$sql = "SELECT `log` FROM md_product_category
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$row = $sth->fetch(PDO::FETCH_ASSOC);
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log = json_decode($sth->fetchColumn() ?: '[]', true);
$table_log[] = $logging;
if ($id > 0) {
@@ -34,7 +28,7 @@
`log` = :log
WHERE id = :id AND company_id = :company_id";
$sth = $pdo2->prepare($sql);
$sth = $pdo->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
@@ -52,7 +46,7 @@
VALUES
(:company_id, :category, :slug, :description, :status, :log)";
$sth = $pdo2->prepare($sql);
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":category" => $data["category"],
@@ -63,7 +57,18 @@
]);
}
$answer["success"] = 1;
exit(json_encode($answer));
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+26 -16
View File
@@ -3,25 +3,22 @@
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging) {
$id = (int)$data['id'];
// get existing log
$sql = "SELECT `log`
FROM md_product
WHERE
company_id = :company_id and
id = :id ";
$sth = $pdo2->prepare($sql);
$sql = "SELECT `log` FROM md_product
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$row = $sth->fetch(PDO::FETCH_ASSOC);
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log = json_decode($sth->fetchColumn() ?: '[]', true);
$table_log[] = $logging;
if ($id > 0) {
@@ -30,6 +27,7 @@
product_name = :product_name,
sku = :sku,
price = :price,
min_stock = :min_stock,
category = :category,
product_image = :product_image,
`description` = :description,
@@ -37,13 +35,14 @@
`log` = :log
WHERE id = :id AND company_id = :company_id";
$sth = $pdo2->prepare($sql);
$sth = $pdo->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
":product_name" => $data["product_name"],
":sku" => $data["sku"],
":price" => $data["price"],
":min_stock" => $data["min_stock"],
":category" => $data["category"],
":product_image"=> $data["product_image"],
":description" => $data["description"],
@@ -54,16 +53,17 @@
} else {
$sql = "INSERT INTO md_product
(company_id, product_name, sku, price, category, product_image, `description`, `status`, `log`)
(company_id, product_name, sku, price, min_stock, category, product_image, `description`, `status`, `log`)
VALUES
(:company_id, :product_name, :sku, :price, :category, :product_image, :description, :status, :log)";
(:company_id, :product_name, :sku, :price, :min_stock, :category, :product_image, :description, :status, :log)";
$sth = $pdo2->prepare($sql);
$sth = $pdo->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":product_name" => $data["product_name"],
":sku" => $data["sku"],
":price" => $data["price"],
":min_stock" => $data["min_stock"],
":category" => $data["category"],
":product_image"=> $data["product_image"],
":description" => $data["description"],
@@ -72,8 +72,18 @@
]);
}
});
$answer["success"] = 1;
exit(json_encode($answer));
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+38 -55
View File
@@ -1,31 +1,37 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging) {
$id = (int)($data['id'] ?? 0);
// get existing log
$sql = "SELECT `log`
FROM md_storage
WHERE company_id = :company_id
AND id = :id";
$sth = $pdo2->prepare($sql);
$sql = "SELECT `log` FROM md_storage
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
':company_id' => $company_id,
':id' => $id,
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$row = $sth->fetch(PDO::FETCH_ASSOC);
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log = json_decode($sth->fetchColumn() ?: '[]', true);
if (!is_array($table_log)) $table_log = [];
// add new log entry (assumes $logging already prepared)
$table_log[] = $logging;
$params = [
":company_id" => $company_id,
":warehouse" => $data["warehouse"] ?? "",
":zone" => $data["zone"] ?? "",
":aisle_from" => $data["aisle_from"] ?? "",
":aisle_to" => $data["aisle_to"] ?? "",
":rack_from" => $data["rack_from"] ?? "",
":rack_to" => $data["rack_to"] ?? "",
":description" => $data["description"] ?? "",
":status" => (int)($data["status"] ?? 1),
":log" => json_encode($table_log, JSON_UNESCAPED_UNICODE),
];
if ($id > 0) {
$sql = "UPDATE md_storage SET
@@ -38,27 +44,9 @@ if ($id > 0) {
description = :description,
status = :status,
`log` = :log
WHERE id = :id
AND company_id = :company_id";
WHERE id = :id AND company_id = :company_id";
$sth = $pdo2->prepare($sql);
$sth->execute([
":id" => $id,
":company_id" => $company_id,
":warehouse" => $data["warehouse"] ?? "",
":zone" => $data["zone"] ?? "",
":aisle_from" => $data["aisle_from"] ?? "",
":aisle_to" => $data["aisle_to"] ?? "",
":rack_from" => $data["rack_from"] ?? "",
":rack_to" => $data["rack_to"] ?? "",
":description" => $data["description"] ?? "",
":status" => (int)($data["status"] ?? 1),
":log" => json_encode($table_log, JSON_UNESCAPED_UNICODE),
]);
$params[":id"] = $id;
} else {
@@ -66,28 +54,23 @@ if ($id > 0) {
(company_id, warehouse, zone, aisle_from, aisle_to, rack_from, rack_to, description, status, `log`)
VALUES
(:company_id, :warehouse, :zone, :aisle_from, :aisle_to, :rack_from, :rack_to, :description, :status, :log)";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse" => $data["warehouse"] ?? "",
":zone" => $data["zone"] ?? "",
":aisle_from" => $data["aisle_from"] ?? "",
":aisle_to" => $data["aisle_to"] ?? "",
":rack_from" => $data["rack_from"] ?? "",
":rack_to" => $data["rack_to"] ?? "",
":description" => $data["description"] ?? "",
":status" => (int)($data["status"] ?? 1),
":log" => json_encode($table_log, JSON_UNESCAPED_UNICODE),
]);
}
db_check($sth, $answer);
$sth = $pdo->prepare($sql);
$sth->execute($params);
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+42 -61
View File
@@ -1,49 +1,25 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
try {
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging) {
$id = (int)($data['id'] ?? 0);
$pdo2->beginTransaction();
// get existing log
$sql = "SELECT `log`
FROM md_warehouse
WHERE company_id = :company_id
AND id = :id";
$sth = $pdo2->prepare($sql);
$sql = "SELECT `log` FROM md_warehouse
WHERE company_id = :company_id AND id = :id";
$sth = $pdo->prepare($sql);
$sth->execute([
':company_id' => $company_id,
':id' => $id,
":company_id" => $company_id,
":id" => $id
]);
db_check($sth, $answer);
$row = $sth->fetch(PDO::FETCH_ASSOC);
$table_log = json_decode($row['log'] ?? '[]', true);
$table_log = json_decode($sth->fetchColumn() ?: '[]', true);
if (!is_array($table_log)) $table_log = [];
// add new log entry (assumes $logging already prepared)
$table_log[] = $logging;
if ($id > 0) {
$sql = "UPDATE md_warehouse SET
warehouse_name = :warehouse_name,
location = :location,
manager = :manager,
capacity = :capacity,
description = :description,
status = :status,
`log` = :log
WHERE id = :id
AND company_id = :company_id";
$sth = $pdo2->prepare($sql);
$sth->execute([
":id" => $id,
$params = [
":company_id" => $company_id,
":warehouse_name" => $data["warehouse_name"] ?? "",
":location" => $data["location"] ?? "",
@@ -52,8 +28,21 @@ if ($id > 0) {
":description" => $data["description"] ?? "",
":status" => (int)($data["status"] ?? 1),
":log" => json_encode($table_log, JSON_UNESCAPED_UNICODE),
]);
db_check($sth, $answer);
];
if ($id > 0) {
$sql = "UPDATE md_warehouse SET
`warehouse_name` = :warehouse_name,
`location` = :location,
`manager` = :manager,
`capacity` = :capacity,
`description` = :description,
`status` = :status,
`log` = :log
WHERE id = :id AND company_id = :company_id";
$params[":id"] = $id;
} else {
@@ -61,38 +50,30 @@ if ($id > 0) {
(company_id, warehouse_name, location, manager, capacity, description, status, `log`)
VALUES
(:company_id, :warehouse_name, :location, :manager, :capacity, :description, :status, :log)";
}
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id,
":warehouse_name" => $data["warehouse_name"] ?? "",
":location" => $data["location"] ?? "",
":manager" => (int)($data["manager"] ?? 0),
":capacity" => (int)($data["capacity"] ?? 0),
":description" => $data["description"] ?? "",
":status" => (int)($data["status"] ?? 1),
":log" => json_encode($table_log, JSON_UNESCAPED_UNICODE),
]);
db_check($sth, $answer);
$sth = $pdo->prepare($sql);
$sth->execute($params);
if(!empty($data["warehouse_name"])){
/**
* Create warehouse table
*/
// Create stock table for new warehouse
if ($id == 0 && !empty($data["warehouse_name"])) {
$safe_name = 'td_stock_' . preg_replace('/[^a-zA-Z0-9_]/', '', $data["warehouse_name"]);
$sql = "CREATE TABLE `$safe_name` LIKE `td_stock`";
$sth = $pdo2->prepare($sql);
$sth->execute();
db_check($sth, $answer);
$pdo->exec($sql);
}
}
$pdo2->commit();
});
$answer["success"] = 1;
} catch (PDOException $e) {
$answer["success"] = 0;
$answer["message"] = "Database error, please try again";
} catch (Exception $e) {
$answer["success"] = 0;
$answer["message"] = "Something went wrong";
}
exit(json_encode($answer));
?>
+2 -2
View File
@@ -87,7 +87,7 @@
}
function retreive_for_edit() {
function retrieve_for_edit() {
<?php if(empty($_GET["id"])){ ?>
return false;
@@ -117,7 +117,7 @@
$(async function() {
try {
await retreive_for_edit();
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
+6 -2
View File
@@ -43,6 +43,10 @@
<label for="price" class="form-label">Price</label>
<input type="number" class="form-control" id="price" placeholder="0.00" step="0.01" required>
</div>
<div class="col-md-6 mb-3">
<label for="min_stock" class="form-label">min_stock</label>
<input type="number" class="form-control" id="min_stock" placeholder="0" required>
</div>
</div>
<div class="mb-3">
@@ -115,7 +119,7 @@
}
function retreive_for_edit() {
function retrieve_for_edit() {
<?php if(empty($_GET["id"])){ ?>
return false;
@@ -146,7 +150,7 @@
$(async function() {
try {
await retrieve_category();
await retreive_for_edit();
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
+2 -2
View File
@@ -120,7 +120,7 @@
}
function retreive_for_edit() {
function retrieve_for_edit() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/retrieve_storage.php",
@@ -148,7 +148,7 @@
try {
await retrieve_warehouse();
<?php if(!empty($_GET["id"])){ ?>
await retreive_for_edit();
await retrieve_for_edit();
<?php } ?>
} catch (e) {
console.log(e);
+2 -2
View File
@@ -113,7 +113,7 @@
}
function retreive_for_edit() {
function retrieve_for_edit() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/retrieve_warehouse.php",
@@ -141,7 +141,7 @@
try {
await retrieve_manager();
<?php if(!empty($_GET["id"])){ ?>
await retreive_for_edit();
await retrieve_for_edit();
<?php } ?>
} catch (e) {
console.log(e);
+1 -1
View File
@@ -344,7 +344,7 @@
<td class="py-3">${item['product_name']}</td>
<td class="py-3">${item['sku']}</td>
<td class="py-3">${item['description']}</td>
<td class="py-3">${item['status']}</td>
<td class="py-3" style='text-align: right;'>${format_number(item['min_stock'],2)}</td>
<td class="py-3">
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
</td>
+1 -1
View File
@@ -295,7 +295,7 @@
<td class="py-3">${item['warehouse_name']}</td>
<td class="py-3">${item['location']}</td>
<td class="py-3">${item['manager']}</td>
<td class="py-3">${item['capacity']}</td>
<td class="py-3" style='text-align: right;'>${format_number(item['capacity'],2)}</td>
<td class="py-3">${item['product']}</td>
<td class="py-3">
<span class="badge bg-${item['bg_class']}">${item.status}</span>
+3 -5
View File
@@ -3,11 +3,9 @@
//<><><><><><><><> MAIN TRCLOUD <><><><><><><><>//
if(true){
$expire = "2027-01-01";
}
// configuration
// global variables
$prop['limit'] = 50;
}
?>
+191
View File
@@ -0,0 +1,191 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_setting_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-5 gap-3">
<div class="">
<h1 class="fs-3 mb-1">Manage Profile</h1>
<p class="mb-0">Update profile detail</p>
</div>
</div>
</div>
</div>
<div class="row" id="userForm">
<div class="col-12">
<div class="card">
<div class="card-body p-6">
<!-- Row 1: username / email -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" placeholder="Enter username" required>
</div>
<div class="col-md-6 mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" required>
</div>
</div>
<!-- Row 2: password / phone -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" placeholder="Enter password" required>
</div>
<div class="col-md-6 mb-3">
<label for="phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="phone" placeholder="Enter phone number">
</div>
</div>
<!-- Row 3: name / surname -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" placeholder="Enter first name" required>
</div>
<div class="col-md-6 mb-3">
<label for="surname" class="form-label">Surname</label>
<input type="text" class="form-control" id="surname" placeholder="Enter last name" required>
</div>
</div>
<!-- Row 4: country / language -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="country" class="form-label">Country</label>
<input type="text" class="form-control" id="country" placeholder="Enter country">
</div>
<div class="col-md-6 mb-3">
<label for="language" class="form-label">Language</label>
<select class="form-select" id="language">
<option value="th" selected>Thai (th)</option>
<option value="en">English (en)</option>
</select>
</div>
</div>
<!-- default_company / profile_picture -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="default_company" class="form-label">Default Company ID</label>
<input type="number" class="form-control" id="default_company" placeholder="0" value="0">
</div>
</div>
<!-- address -->
<div class="mb-3">
<label for="address" class="form-label">Address</label>
<input type="text" class="form-control" id="address" placeholder="Enter address">
</div>
<!-- facebook / line_code -->
<div class="row">
<div class="col-md-6 mb-3">
<label for="facebook" class="form-label">Facebook</label>
<input type="text" class="form-control" id="facebook" placeholder="Enter Facebook profile">
</div>
<div class="col-md-6 mb-3">
<label for="line_code" class="form-label">Line Code</label>
<input type="text" class="form-control" id="line_code" placeholder="Enter Line ID">
</div>
</div>
<!-- signature -->
<div class="mb-3">
<label for="signature" class="form-label">Signature</label>
<input type="text" class="form-control" id="signature" placeholder="Enter signature">
</div>
<!-- Buttons -->
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary" onclick="manage_user();">Create</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<script>
function manage_category() {
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/manage_category.php",
autoPrepare: true,
checkRequired: 1,
debugMode: 0,
action: 'manage',
onSuccess: function(res) {
window.location.href = "<?php echo $server_url?>inventory/product.php";
}
});
}
function retrieve_for_edit() {
<?php if(empty($_GET["id"])){ ?>
return false;
<?php } ?>
return ajax_request({
url: "<?php echo $server_url?>inventory/api/engine/retrieve_category.php",
autoPrepare: true,
checkRequired: 0,
action: 'read',
onSuccess: function(res) {
$.each(res.output, function(key, item) {
$(`#${key}`).val(item);
});
$(`button[type=submit]`).text('Update');
$(`button[type=reset]`).hide();
}
});
}
$(async function() {
try {
await retrieve_for_edit();
} catch (e) {
console.log(e);
}
});
</script>
</body>
</html>