From 09878515a9a05190ba885da953b797355cdc7b21 Mon Sep 17 00:00:00 2001 From: o-psi Date: Thu, 7 Mar 2024 16:10:08 +0000 Subject: [PATCH] Inventory --- database_updates.php | 1 + db.sql | 44 ++++--- expense_add_modal.php | 38 ++++++ inventory.php | 135 ++++++++++++++++++++++ inventory_edit_item_location_modal.php | 45 ++++++++ inventory_locations.php | 137 ++++++++++++++++++++++ inventory_locations_manage.php | 153 +++++++++++++++++++++++++ inventory_manage.php | 147 ++++++++++++++++++++++++ post.php | 2 + post/expense.php | 27 ++++- post/expense_model.php | 2 + post/inventory.php | 26 +++++ post/inventory_model.php | 1 + post/ticket.php | 118 +++++++++++++++++++ products.php | 5 + ticket.php | 36 +++++- ticket_add_product_modal.php | 45 ++++++++ 17 files changed, 942 insertions(+), 20 deletions(-) create mode 100644 inventory.php create mode 100644 inventory_edit_item_location_modal.php create mode 100644 inventory_locations.php create mode 100644 inventory_locations_manage.php create mode 100644 inventory_manage.php create mode 100644 post/inventory.php create mode 100644 post/inventory_model.php create mode 100644 ticket_add_product_modal.php diff --git a/database_updates.php b/database_updates.php index 0c8b778d7..121d364cc 100644 --- a/database_updates.php +++ b/database_updates.php @@ -1645,6 +1645,7 @@ `inventory_client_id` int(11) DEFAULT NULL, `inventory_ticket_id` int(11) DEFAULT NULL, `inventory_notes` text DEFAULT NULL, + `inventory_vendor_id` int(11) DEFAULT NULL, `inventory_quantity` int(11) NOT NULL DEFAULT 0, `inventory_cost` decimal(15,2) NOT NULL DEFAULT 0.00, `inventory_created_at` datetime NOT NULL DEFAULT current_timestamp(), diff --git a/db.sql b/db.sql index 60ede72f8..cb190ba6d 100644 --- a/db.sql +++ b/db.sql @@ -674,7 +674,9 @@ CREATE TABLE `inventory` ( `inventory_product_id` int(11) NOT NULL, `inventory_location_id` int(11) NOT NULL, `inventory_client_id` int(11) DEFAULT NULL, - `inventory_ticket_id` int(11) DEFAULT NULL, + `inventory_serial` varchar(200) DEFAULT NULL, + `inventory_barcode` varchar(200) DEFAULT NULL, + `inventory_vendor_id` int(11) NOT NULL, `inventory_notes` text DEFAULT NULL, `inventory_quantity` int(11) NOT NULL DEFAULT 0, `inventory_cost` decimal(15,2) NOT NULL DEFAULT 0.00, @@ -692,19 +694,19 @@ DROP TABLE IF EXISTS `inventory_locations`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `inventory_locations` ( - `inventory_location_id` int(11) NOT NULL AUTO_INCREMENT, - `inventory_location_name` varchar(200) NOT NULL, - `inventory_location_description` text DEFAULT NULL, - `inventory_location_address` varchar(200) DEFAULT NULL, - `inventory_location_city` varchar(200) DEFAULT NULL, - `inventory_location_state` varchar(200) DEFAULT NULL, - `inventory_location_zip` varchar(200) DEFAULT NULL, - `inventory_location_country` varchar(200) DEFAULT NULL, - `inventory_location_created_at` datetime NOT NULL DEFAULT current_timestamp(), - `inventory_location_updated_at` datetime DEFAULT NULL ON UPDATE current_timestamp(), - `inventory_location_archived_at` datetime DEFAULT NULL, - `inventory_location_user_id` int(11) NOT NULL DEFAULT 0, - PRIMARY KEY (`inventory_location_id`) + `inventory_locations_id` int(11) NOT NULL AUTO_INCREMENT, + `inventory_locations_name` varchar(200) NOT NULL, + `inventory_locations_description` text DEFAULT NULL, + `inventory_locations_address` varchar(200) DEFAULT NULL, + `inventory_locations_city` varchar(200) DEFAULT NULL, + `inventory_locations_state` varchar(200) DEFAULT NULL, + `inventory_locations_zip` varchar(200) DEFAULT NULL, + `inventory_locations_country` varchar(200) DEFAULT NULL, + `inventory_locations_created_at` datetime NOT NULL DEFAULT current_timestamp(), + `inventory_locations_updated_at` datetime DEFAULT NULL ON UPDATE current_timestamp(), + `inventory_locations_archived_at` datetime DEFAULT NULL, + `inventory_locations_user_id` int(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`inventory_locations_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1551,6 +1553,20 @@ CREATE TABLE `ticket_attachments` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `ticket_products` +-- +DROP TABLE IF EXISTS `ticket_products`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ticket_products` ( + `ticket_product_id` int(11) NOT NULL AUTO_INCREMENT, + `ticket_product_product_id` int(11) NOT NULL, + `ticket_product_ticket_id` int(11) NOT NULL, + `ticket_product_quantity` int(11) NOT NULL, + PRIMARY KEY (`ticket_product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; + -- -- Table structure for table `ticket_replies` -- diff --git a/expense_add_modal.php b/expense_add_modal.php index 6238759d3..63e58c7f5 100644 --- a/expense_add_modal.php +++ b/expense_add_modal.php @@ -117,7 +117,45 @@
+
+ +
+
+ +
+ +
+ +
+
+
+
+ +
+
+ +
+ +
+
+
+ +
diff --git a/inventory.php b/inventory.php new file mode 100644 index 000000000..2cfa2d0c7 --- /dev/null +++ b/inventory.php @@ -0,0 +1,135 @@ + + +
+
+

Inventory

+
+ +
+
+
+
+
+ +
+ + +
+
+
+
+
+ Locations + +
+
+
+
+
+
+
+ + "> + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
Product NameQuantityLocationsManage product
+
+ +
+
+
+ +
+
+
+ +
+ +
+
+ + + +" tabindex="-1"> + +
+ diff --git a/inventory_locations.php b/inventory_locations.php new file mode 100644 index 000000000..ead61408d --- /dev/null +++ b/inventory_locations.php @@ -0,0 +1,137 @@ + + +
+
+

Inventory locations

+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+ + "> + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
NameDescriptionUser ResponsibleTotal QuantityManage Inventory
+
+ +
+
+
+ +
+
+
+ +
+ +
+
+ + + + + +
+
+

Inventory location:

+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+ + "> + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
Item NameQuantityUnit CostLocationManage product
+
+ + +
+
+
+ + + +
+
+
+ +
+ +
+
+ + + + + +
+
+

Inventory product:

+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+ + "> + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
LocationQuantityUnit CostManage location
+
+ + +
+
+
+ +
+
+
+ +
+ +
+
+ + + +"; + header("Location: " . $_SERVER["HTTP_REFERER"]); + + + +} \ No newline at end of file diff --git a/post/inventory_model.php b/post/inventory_model.php new file mode 100644 index 000000000..b3d9bbc7f --- /dev/null +++ b/post/inventory_model.php @@ -0,0 +1 @@ + 0) { + $sql = mysqli_query($mysqli, "SELECT * FROM taxes WHERE tax_id = $product_tax_id"); + $row = mysqli_fetch_array($sql); + $product_tax_percent = floatval($row['tax_percent']); + $product_tax_amount = $product_subtotal * $product_tax_percent / 100; + } else { + $product_tax_amount = 0; + } + + $product_total = $product_subtotal + $product_tax_amount; + + mysqli_query($mysqli, "INSERT INTO invoice_items SET item_name = '$product_name', item_description = '$product_description', item_quantity = $product_qty, item_price = $product_price, item_subtotal = $product_subtotal, item_tax = $product_tax_amount, item_total = $product_total, item_order = 1, item_tax_id = $product_tax_id, item_invoice_id = $invoice_id"); + } + + //Update Invoice Balances $sql = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_id = $invoice_id"); @@ -1764,3 +1795,90 @@ header("Location: " . $_SERVER["HTTP_REFERER"]); } + + +if (isset($_POST['add_ticket_products'])) { + + validateTechRole(); + + $ticket_id = intval($_POST['ticket_id']); + $product_id = intval($_POST['product_id']); + $qty = intval($_POST['quantity']); + + //find user inventory location + $sql = mysqli_query($mysqli, "SELECT * FROM inventory_locations WHERE inventory_locations_user_id = $session_user_id"); + $num_rows = mysqli_num_rows($sql); + + if ($num_rows == 1) { + $row = mysqli_fetch_array($sql); + $session_location_id = intval($row['inventory_locations_id']); + } elseif ($num_rows > 1) { + $_SESSION['alert_type'] = "error"; + $_SESSION['alert_message'] = "You have more than one inventory location set. Please contact your administrator"; + header("Location: " . $_SERVER["HTTP_REFERER"]); + exit; + } else { + $_SESSION['alert_type'] = "error"; + $_SESSION['alert_message'] = "You do not have an inventory location set. Please contact your administrator"; + header("Location: " . $_SERVER["HTTP_REFERER"]); + exit; + } + + //check qty against inventory + $sql = mysqli_query($mysqli, "SELECT SUM(inventory_quantity) as inventory_quantity FROM inventory WHERE inventory_product_id = $product_id AND inventory_location_id = $session_location_id GROUP BY inventory_product_id, inventory_location_id;"); + $row = mysqli_fetch_array($sql); + $inventory_qty = intval($row['inventory_quantity']); + if ($qty > $inventory_qty) { + $_SESSION['alert_type'] = "error"; + $_SESSION['alert_message'] = "You do not have enough inventory to add that quantity, QTY: $qty, Inventory: $inventory_qty in location $session_location_id, $num_rows rows found."; + header("Location: " . $_SERVER["HTTP_REFERER"]); + exit; + } + + + + // Add to DB + mysqli_query($mysqli, "INSERT INTO ticket_products SET ticket_product_ticket_id = $ticket_id, ticket_product_product_id = $product_id, ticket_product_quantity = $qty"); + + // Delete one item per qty + mysqli_query($mysqli, "UPDATE inventory SET inventory_quantity = inventory_quantity - 1 WHERE inventory_product_id = $product_id AND inventory_location_id = $session_location_id AND inventory_quantity > 0 LIMIT $qty"); + + // Logging + mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Ticket', log_action = 'Modify', log_description = '$session_name added product to ticket', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id, log_entity_id = $ticket_id"); + + $_SESSION['alert_message'] = "Product added to ticket"; + header("Location: ". $_SERVER["HTTP_REFERER"]); + +} + +if (isset($_GET['delete_ticket_product'])) { + + validateTechRole(); + + $ticket_product_id = intval($_GET['delete_ticket_product']); + $ticket_id = intval($_GET['ticket_id']); + + // Get product ID + $sql = mysqli_query($mysqli, "SELECT * FROM ticket_products WHERE ticket_product_id = $ticket_product_id"); + $row = mysqli_fetch_array($sql); + $product_id = intval($row['ticket_product_product_id']); + $qty = intval($row['ticket_product_quantity']); + + // Delete + mysqli_query($mysqli, "DELETE FROM ticket_products WHERE ticket_product_id = $ticket_product_id"); + + //find user's inventory location + $sql = mysqli_query($mysqli, "SELECT * FROM inventory_locations WHERE inventory_locations_user_id = $session_user_id"); + $row = mysqli_fetch_array($sql); + $session_location_id = intval($row['inventory_locations_id']); + + // Restore inventory quantity + mysqli_query($mysqli, "UPDATE inventory SET inventory_quantity = inventory_quantity + 1 WHERE inventory_product_id = $product_id AND inventory_location_id = $session_location_id AND inventory_quantity = 0 LIMIT $qty"); + + // Logging + mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Ticket', log_action = 'Modify', log_description = '$session_name deleted product from ticket', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id, log_entity_id = $ticket_id"); + + $_SESSION['alert_message'] = "Product removed from ticket. Please see administrator to return inventory"; + header("Location: ". $_SERVER["HTTP_REFERER"]); + +} diff --git a/products.php b/products.php index f8cd081ef..d3d2c7a69 100644 --- a/products.php +++ b/products.php @@ -43,6 +43,11 @@
+
+
+ Inventory +
+

diff --git a/ticket.php b/ticket.php index 1f8859f95..3db452e9c 100644 --- a/ticket.php +++ b/ticket.php @@ -233,6 +233,25 @@ AND ticket_attachment_ticket_id = $ticket_id" ); + // Get Products in inventory attached to this ticket + $sql_ticket_products = mysqli_query( + $mysqli, + "SELECT * FROM ticket_products + LEFT JOIN products ON ticket_products.ticket_product_product_id = products.product_id + WHERE ticket_product_ticket_id = $ticket_id" + ); + + $ticket_products_display = ''; + while ($row = mysqli_fetch_array($sql_ticket_products)) { + $ticket_product_id = intval($row['ticket_product_id']); + $product_id = intval($row['product_id']); + $product_name = nullable_htmlentities($row['product_name']); + $product_quantity = intval($row['ticket_product_quantity']); + + + $ticket_products_display .= "
$product_name x$product_quantity
"; + } + ?> @@ -380,8 +399,8 @@ - - + +
-
+
> @@ -881,6 +900,15 @@
+ +
+
Products
+ + +
+
@@ -952,6 +980,8 @@ require_once "ticket_merge_modal.php"; + require_once "ticket_add_product_modal.php"; + if ($config_module_enable_accounting) { require_once "ticket_edit_billable_modal.php"; require_once "ticket_invoice_add_modal.php"; diff --git a/ticket_add_product_modal.php b/ticket_add_product_modal.php new file mode 100644 index 000000000..73e9135da --- /dev/null +++ b/ticket_add_product_modal.php @@ -0,0 +1,45 @@ +
+ + + \ No newline at end of file