").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'));
+ }
+ });
+
+ });
+
});
@@ -198,7 +303,7 @@ function ajax_request(options) {
isAjaxProcessing = false;
return Promise.reject("validation_failed");
}
-
+
if(options.data){
Object.entries(options.data).forEach(([key, value]) => {
payloadJson[key] = value;
@@ -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('.');
+}
\ No newline at end of file
diff --git a/app/assets/utils/db_auth.php b/app/assets/utils/db_auth.php
index 7b2e433..931f080 100644
--- a/app/assets/utils/db_auth.php
+++ b/app/assets/utils/db_auth.php
@@ -57,7 +57,11 @@ 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);
@@ -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;
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/app/contact/api/engine/manage_contact.php b/app/contact/api/engine/manage_contact.php
index d57a7eb..a813a61 100644
--- a/app/contact/api/engine/manage_contact.php
+++ b/app/contact/api/engine/manage_contact.php
@@ -1,212 +1,105 @@
0) {
+ $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'] ?? '');
+ }
- /** 1. DISK CLEANUP (Removal of 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();
+ // Upload new files
+ $errors = $uploader->upload('contact_files');
+ if (!empty($errors)) {
+ $answer["success"] = 0;
+ $answer["message"] = $errors[0];
+ exit(json_encode($answer));
+ }
- 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']) : [];
+ $db_image_string = $uploader->buildFileString($data['keep_files'] ?? '');
- foreach ($existing_files_array as $file_on_disk) {
- $file_on_disk = trim($file_on_disk);
- if (empty($file_on_disk)) continue;
+ /** 2. DATABASE **/
+ dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, $id, $db_image_string) {
- /**
- * 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
- }
- }
+ $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
+ ]);
+
+ $table_log = json_decode($sth->fetchColumn() ?: '[]', true);
+ if (!is_array($table_log)) $table_log = [];
+ $table_log[] = $logging;
+
+ $params = [
+ ":company_id" => $company_id,
+ ":contact_name" => $data["contact_name"],
+ ":tax_id" => $data["tax_id"],
+ ":organization" => $data["organization"],
+ ":branch" => $data["branch"],
+ ":contact_type" => (int)$data["contact_type"],
+ ":billing_address" => $data["billing_address"],
+ ":shipping_location"=> $data["shipping_location"],
+ ":shipping_address" => $data["shipping_address"],
+ ":remark" => $data["remark"],
+ ":files" => $db_image_string,
+ ":status" => (int)$data["status"],
+ ":log" => json_encode($table_log),
+ ];
+
+ if ($id > 0) {
+ $sql = "UPDATE md_contact SET
+ `contact_name` = :contact_name,
+ `tax_id` = :tax_id,
+ `organization` = :organization,
+ `branch` = :branch,
+ `contact_type` = :contact_type,
+ `billing_address` = :billing_address,
+ `shipping_location` = :shipping_location,
+ `shipping_address` = :shipping_address,
+ `remark` = :remark,
+ `files` = :files,
+ `status` = :status,
+ `log` = :log
+ WHERE id = :id AND company_id = :company_id";
+ $params[":id"] = $id;
+ } else {
+ $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 = $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();
}
- /** 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";
- $sth = $pdo2->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[] = $logging;
-
- // 3. Database Operation
- $params = [
- ":company_id" => $company_id,
- ":contact_name" => $data["contact_name"],
- ":tax_id" => $data["tax_id"],
- ":organization" => $data["organization"],
- ":branch" => $data["branch"],
- ":contact_type" => (int)$data["contact_type"],
- ":billing_address" => $data["billing_address"],
- ":shipping_location"=> $data["shipping_location"],
- ":shipping_address" => $data["shipping_address"],
- ":remark" => $data["remark"],
- ":files" => $db_image_string,
- ":status" => (int)$data["status"],
- ":log" => json_encode($table_log)
- ];
-
- if ($id > 0) {
- // UPDATE
- $sql = "UPDATE md_contact SET
- `contact_name` = :contact_name,
- `tax_id` = :tax_id,
- `organization` = :organization,
- `branch` = :branch,
- `contact_type` = :contact_type,
- `billing_address` = :billing_address,
- `shipping_location` = :shipping_location,
- `shipping_address` = :shipping_address,
- `remark` = :remark,
- `files` = :files,
- `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);
- }
-
- $answer["success"] = 1;
exit(json_encode($answer));
?>
\ No newline at end of file
diff --git a/app/contact/api/engine/manage_contact_type.php b/app/contact/api/engine/manage_contact_type.php
index 7478244..ed3d1d0 100644
--- a/app/contact/api/engine/manage_contact_type.php
+++ b/app/contact/api/engine/manage_contact_type.php
@@ -1,77 +1,66 @@
0) {
- $sql = "SELECT `log`
- FROM md_contact_type
- WHERE
- company_id = :company_id AND
- id = :id";
- $sth = $pdo2->prepare($sql);
- $sth->execute([
- ":company_id" => $company_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);
- }
+ $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
+ ]);
+
+ $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) {
+
+ $sql = "UPDATE md_contact_type SET
+ `contact_type` = :contact_type,
+ `description` = :description,
+ `status` = :status,
+ `log` = :log
+ WHERE id = :id AND company_id = :company_id";
+
+ $params[":id"] = $id;
+
+ } else {
+
+ $sql = "INSERT INTO md_contact_type
+ (company_id, contact_type, `description`, `status`, `log`)
+ VALUES
+ (:company_id, :contact_type, :description, :status, :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";
}
- // Append the new log entry (assuming $logging is defined in your preset/utils)
- $table_log[] = $logging;
-
- if ($id > 0) {
- // UPDATE existing record
- $sql = "UPDATE md_contact_type SET
- `contact_type` = :contact_type,
- `description` = :description,
- `status` = :status,
- `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),
- ]);
-
- } 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),
- ]);
- }
-
- $answer["success"] = 1;
exit(json_encode($answer));
?>
\ No newline at end of file
diff --git a/app/contact/manage_contact.php b/app/contact/manage_contact.php
index c12f9ad..ccfa8a9 100644
--- a/app/contact/manage_contact.php
+++ b/app/contact/manage_contact.php
@@ -185,7 +185,7 @@
url: "contact/api/engine/manage_contact.php",
autoPrepare: true,
checkRequired: 1,
- debugMode: 1,
+ debugMode: 0,
formData: formData,
action: 'manage',
onSuccess: function(res) {
diff --git a/app/contact/manage_contact_type.php b/app/contact/manage_contact_type.php
index e51c057..dffdac4 100644
--- a/app/contact/manage_contact_type.php
+++ b/app/contact/manage_contact_type.php
@@ -84,7 +84,7 @@
}
- function retreive_for_edit() {
+ function retrieve_for_edit() {
return false;
@@ -114,7 +114,7 @@
$(async function() {
try {
- await retreive_for_edit();
+ await retrieve_for_edit();
} catch (e) {
console.log(e);
}
diff --git a/app/dbconn.php b/app/dbconn.php
index 87f514d..470f01d 100644
--- a/app/dbconn.php
+++ b/app/dbconn.php
@@ -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);
?>
\ No newline at end of file
diff --git a/app/ics/api/engine/contact_search.php b/app/ics/api/engine/contact_search.php
new file mode 100644
index 0000000..3ef9a1f
--- /dev/null
+++ b/app/ics/api/engine/contact_search.php
@@ -0,0 +1,25 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/manage_stock_in.php b/app/ics/api/engine/manage_stock_in.php
new file mode 100644
index 0000000..23a8cf5
--- /dev/null
+++ b/app/ics/api/engine/manage_stock_in.php
@@ -0,0 +1,87 @@
+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));
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/manage_stock_out.php b/app/ics/api/engine/manage_stock_out.php
new file mode 100644
index 0000000..d7824ba
--- /dev/null
+++ b/app/ics/api/engine/manage_stock_out.php
@@ -0,0 +1,87 @@
+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));
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/manage_stock_transfer.php b/app/ics/api/engine/manage_stock_transfer.php
new file mode 100644
index 0000000..b37288b
--- /dev/null
+++ b/app/ics/api/engine/manage_stock_transfer.php
@@ -0,0 +1,113 @@
+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));
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/retrieve_aisle.php b/app/ics/api/engine/retrieve_aisle.php
index 8fbee7c..af7fc85 100644
--- a/app/ics/api/engine/retrieve_aisle.php
+++ b/app/ics/api/engine/retrieve_aisle.php
@@ -4,7 +4,14 @@
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
- $warehouse = (int)$data['warehouse'];
+ // 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;
diff --git a/app/ics/api/engine/retrieve_rack.php b/app/ics/api/engine/retrieve_rack.php
index 6d6d9b9..691406c 100644
--- a/app/ics/api/engine/retrieve_rack.php
+++ b/app/ics/api/engine/retrieve_rack.php
@@ -3,8 +3,26 @@
require '../../../assets/utils/db_auth.php';
+ // 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'];
- $warehouse = (int)$data['warehouse'];
$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;
diff --git a/app/ics/api/engine/retrieve_stock_in.php b/app/ics/api/engine/retrieve_stock_in.php
new file mode 100644
index 0000000..b2add0f
--- /dev/null
+++ b/app/ics/api/engine/retrieve_stock_in.php
@@ -0,0 +1,51 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/retrieve_stock_out.php b/app/ics/api/engine/retrieve_stock_out.php
new file mode 100644
index 0000000..40e359d
--- /dev/null
+++ b/app/ics/api/engine/retrieve_stock_out.php
@@ -0,0 +1,51 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/retrieve_stock_transfer.php b/app/ics/api/engine/retrieve_stock_transfer.php
new file mode 100644
index 0000000..d17ab4c
--- /dev/null
+++ b/app/ics/api/engine/retrieve_stock_transfer.php
@@ -0,0 +1,101 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/retrieve_zone.php b/app/ics/api/engine/retrieve_zone.php
index 23fdfd3..304bdf4 100644
--- a/app/ics/api/engine/retrieve_zone.php
+++ b/app/ics/api/engine/retrieve_zone.php
@@ -4,7 +4,13 @@
require '../../../assets/utils/db_auth.php';
$id = (int)$data['id'];
- $warehouse = (int)$data['warehouse'];
+
+ // 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
diff --git a/app/ics/api/engine/stock_in.php b/app/ics/api/engine/stock_in.php
new file mode 100644
index 0000000..f91dffe
--- /dev/null
+++ b/app/ics/api/engine/stock_in.php
@@ -0,0 +1,53 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/stock_out.php b/app/ics/api/engine/stock_out.php
new file mode 100644
index 0000000..e877c15
--- /dev/null
+++ b/app/ics/api/engine/stock_out.php
@@ -0,0 +1,53 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/stock_transfer.php b/app/ics/api/engine/stock_transfer.php
new file mode 100644
index 0000000..9dc36f7
--- /dev/null
+++ b/app/ics/api/engine/stock_transfer.php
@@ -0,0 +1,54 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/api/engine/warehouse_stats.php b/app/ics/api/engine/warehouse_stats.php
new file mode 100644
index 0000000..6ff71b1
--- /dev/null
+++ b/app/ics/api/engine/warehouse_stats.php
@@ -0,0 +1,24 @@
+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));
+
+?>
\ No newline at end of file
diff --git a/app/ics/add_stock_in.php b/app/ics/manage_stock_in.php
similarity index 70%
rename from app/ics/add_stock_in.php
rename to app/ics/manage_stock_in.php
index 99b084e..6dd4427 100644
--- a/app/ics/add_stock_in.php
+++ b/app/ics/manage_stock_in.php
@@ -76,14 +76,14 @@
-
+
-
-
+
+
@@ -108,8 +108,11 @@
return ajax_request({
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: "ics/api/engine/retrieve_zone.php",
autoPrepare: true,
checkRequired: 0,
noLoading: true,
+ debugMode: 0,
action: 'read',
onSuccess: function(res) {
var option = `
`;
@@ -156,6 +160,8 @@
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: "ics/api/engine/retrieve_aisle.php",
@@ -177,6 +183,8 @@
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: "ics/api/engine/retrieve_rack.php",
@@ -198,6 +206,71 @@
option += `
`;
})
$(`select#rack`).html(option);
+
+ if (callback) callback(); // ← add this
+ }
+ });
+
+ }
+
+
+
+ function retrieve_for_edit() {
+
+
+ return false;
+
+
+ return ajax_request({
+ 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('').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);
}
});
-
+
$("select#warehouse").change(function() {
retrieve_zone();
});
@@ -225,8 +299,8 @@
$("select#aisle").change(function() {
retrieve_rack();
});
-
+