Upload markdown files and organize them in a tree structure
⚠️ Warning: This action cannot be undone!
controllers/productController.php (5,533 lines) - Updated Version
product
initiateStaticSessionCommingWithCurl.php (Line 11)
$ajaxDoArr = array("addOneSimpleReturn", "addsizeColorToProductAjax", "editAjax", "productsAndProUnitsToExcel");
// CURL POST detection throughout controller
">if (isset($_POST['curlpost039;]) && $_POST[039;curlpost039;] == 1) {
// JSON response for external systems
$data = array('status039; => 039;success039;, 039;status_code039; => 200, 039;message039; => $response);
">echo json_encode($data);
} else {
// Standard web response
header("location:?do=sucess");
}
productsAndProUnitsToExcel for advanced reporting
product
CREATE TABLE product (
productId INT PRIMARY KEY AUTO_INCREMENT,
productName VARCHAR(256) NOT NULL DEFAULT '039;,
productDescription TEXT,
productCatId INT NOT NULL,
productBuyPrice DECIMAL(10,2) NOT NULL,
productSellAllPrice DECIMAL(10,2) NOT NULL,
productSellUnitPrice DECIMAL(10,2) NOT NULL,
productSellHalfPrice DECIMAL(10,2) NOT NULL,
productDate DATE NOT NULL,
conditions INT NOT NULL DEFAULT 0, -- 0=active, 1=deleted
userId INT NOT NULL,
limitamount INT NOT NULL DEFAULT 0, -- minimum stock alert
parcode VARCHAR(256), -- barcode
type INT NOT NULL DEFAULT 0, -- 1=manufacturing, 0=regular
sellingtype INT DEFAULT 0, -- 1=FIFO, 2=LIFO, 3=expiry
expireDate INT,
dailyentryId INT NOT NULL,
isService INT NOT NULL DEFAULT 0, -- 0=product, 1=service
isOptic INT NOT NULL DEFAULT 0, -- 0=regular, 1=optic without variants, 2=optic with variants
lastbuyprice DECIMAL(10,2),
lastbuyprice_withDiscount DECIMAL(10,2),
meanbuyprice DECIMAL(10,2),
meanbuyprice_withDiscount DECIMAL(10,2),
productbuypricereal DECIMAL(10,2) DEFAULT 0,
buypricereal_precentage DECIMAL(10,2) DEFAULT 0,
buytotal_precentage DECIMAL(10,2) DEFAULT 0,
buyhalf_precentage DECIMAL(10,2) DEFAULT 0,
buypart_precentage DECIMAL(10,2) DEFAULT 0,
logo VARCHAR(255), -- main product image
logo1 VARCHAR(255), -- additional images
logo2 VARCHAR(255),
logo3 VARCHAR(255),
logo4 VARCHAR(255),
logo5 VARCHAR(255),
logo6 VARCHAR(255),
logo7 VARCHAR(255),
hasSizeAndColor TINYINT NOT NULL DEFAULT 0,
overAllAveragePrice DECIMAL(10,2) NOT NULL DEFAULT 0,
online TEXT, -- online store configuration
reviewType INT NOT NULL DEFAULT 0,
updatebyuser INT NOT NULL DEFAULT 0,
proExcelid INT NOT NULL DEFAULT 0,
proExcelParcode VARCHAR(12) NOT NULL,
webApiId INT NOT NULL DEFAULT 0,
runquery VARCHAR(256) NOT NULL DEFAULT '039;,
weightedDiscount FLOAT NOT NULL DEFAULT 0,
sortby INT NOT NULL DEFAULT 0,
TypeOfBarcodeInTax VARCHAR(10),
barcodeInTax VARCHAR(150),
productNameE VARCHAR(256), -- English name
partNumber INT NOT NULL DEFAULT 0,
vehicleType INT NOT NULL DEFAULT 0,
company INT NOT NULL DEFAULT 0,
weight DECIMAL(10,2) DEFAULT 0,
origin VARCHAR(150),
hscode DECIMAL(10,2) DEFAULT 0,
power TINYINT DEFAULT 0,
ProductionDate VARCHAR(150),
expiry INT NOT NULL DEFAULT 0,
procode VARCHAR(150),
lastbuyprice_withTax DECIMAL(10,2),
meanbuyprice_withTax DECIMAL(10,2),
treeId INT NOT NULL DEFAULT 0, -- accounting integration
price4 FLOAT NOT NULL DEFAULT 0, -- additional price tiers
price5 FLOAT NOT NULL DEFAULT 0,
price6 FLOAT NOT NULL DEFAULT 0,
price7 FLOAT NOT NULL DEFAULT 0,
price8 FLOAT NOT NULL DEFAULT 0,
clientid INT NOT NULL DEFAULT 0, -- client-specific products
grantduration INT NOT NULL DEFAULT 0, -- warranty period
onlinepro TINYINT DEFAULT 0,
minappearonline INT NOT NULL DEFAULT 0,
selladdpercent FLOAT NOT NULL DEFAULT 0,
selldiscountpercent FLOAT NOT NULL DEFAULT 0,
buydiscountpercent FLOAT NOT NULL DEFAULT 0,
onlinecatid INT NOT NULL DEFAULT 0,
sellpercenttype INT NOT NULL DEFAULT 0,
searchfiltersid VARCHAR(150),
lastbuyprice_withDiscountAndTax DECIMAL(10,2),
itemsymbol VARCHAR(255),
inMenu TINYINT DEFAULT 0 -- restaurant menu visibility
);
productcat - Product Categories
CREATE TABLE productcat (
productCatId INT PRIMARY KEY AUTO_INCREMENT,
productCatName VARCHAR(256) NOT NULL,
productCatDate DATE NOT NULL,
conditions INT NOT NULL DEFAULT 0,
userid INT NOT NULL,
catImage VARCHAR(256),
onlineCatId INT NOT NULL DEFAULT 0,
parentCatId INT NOT NULL DEFAULT 0,
buypricereal DECIMAL(10,2) DEFAULT 0, -- default markup %
buytotal_precentage DECIMAL(10,2) DEFAULT 0,
buyhalf_precentage DECIMAL(10,2) DEFAULT 0,
buypart_precentage DECIMAL(10,2) DEFAULT 0,
treeId INT NOT NULL DEFAULT 0,
catorder INT NOT NULL DEFAULT 0
);
productunit - Product Units
CREATE TABLE productunit (
productunitid INT PRIMARY KEY AUTO_INCREMENT,
productid INT NOT NULL,
unitid INT NOT NULL,
unitsellprice DECIMAL(10,2) NOT NULL,
unitbuyprice DECIMAL(10,2) NOT NULL,
unitquantity DECIMAL(10,2) NOT NULL, -- conversion factor
conditions INT NOT NULL DEFAULT 0,
isMainUnit TINYINT NOT NULL DEFAULT 0, -- primary unit flag
price4 FLOAT NOT NULL DEFAULT 0,
price5 FLOAT NOT NULL DEFAULT 0,
price6 FLOAT NOT NULL DEFAULT 0,
price7 FLOAT NOT NULL DEFAULT 0,
price8 FLOAT NOT NULL DEFAULT 0
);
storedetail - Store Inventory
CREATE TABLE storedetail (
storedetailid INT PRIMARY KEY AUTO_INCREMENT,
productid INT NOT NULL,
storeid INT NOT NULL,
productquantity DECIMAL(10,2) NOT NULL,
productbuyprice DECIMAL(10,2) NOT NULL,
productsellingprice DECIMAL(10,2) NOT NULL,
productDate DATE NOT NULL,
userid INT NOT NULL,
reserved DECIMAL(10,2) DEFAULT 0, -- reserved quantity
expiredate DATE,
detailComment TEXT,
dailyentryId INT NOT NULL DEFAULT 0
);
productingredients - Manufacturing Recipes
CREATE TABLE productingredients (
id INT PRIMARY KEY AUTO_INCREMENT,
productid INT NOT NULL, -- finished product
rawmaterialid INT NOT NULL, -- raw material
quantity DECIMAL(10,2) NOT NULL, -- required quantity
unitid INT NOT NULL,
conditions INT NOT NULL DEFAULT 0
);
sizecolor - Product Variants
CREATE TABLE sizecolor (
sizecolorid INT PRIMARY KEY AUTO_INCREMENT,
productid INT NOT NULL,
sizename VARCHAR(256),
colorname VARCHAR(256),
parcode VARCHAR(256),
sellunitprice DECIMAL(10,2),
buyprice DECIMAL(10,2),
conditions INT NOT NULL DEFAULT 0
);
productserial - Serial Number Tracking
CREATE TABLE productserial (
productserailid INT PRIMARY KEY AUTO_INCREMENT,
productid INT NOT NULL,
serialnumber VARCHAR(256),
storeid INT NOT NULL,
conditions INT NOT NULL DEFAULT 0, -- 0=available, 1=sold
userid INT NOT NULL,
productDate DATE NOT NULL
);
add() function)
-- Insert new product (via DAO)
INSERT INTO product (
productName, productDescription, productCatId, productBuyPrice,
productSellAllPrice, productSellUnitPrice, productSellHalfPrice,
productDate, conditions, userId, limitamount, parcode, type,
sellingtype, expireDate, dailyentryId, isService, isOptic,
productbuypricereal, buypricereal_precentage, buytotal_precentage,
buyhalf_precentage, buypart_precentage, logo, hasSizeAndColor,
TypeOfBarcodeInTax, barcodeInTax, productNameE, partNumber,
vehicleType, company, weight, origin, hscode, power, ProductionDate,
expiry, procode, treeId, price4, price5, price6, price7, price8,
clientid, grantduration, onlinepro, minappearonline, selladdpercent,
selldiscountpercent, buydiscountpercent, onlinecatid, sellpercenttype,
searchfiltersid, itemsymbol, inMenu, webApiId
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
-- Insert product units (multiple units per product)
INSERT INTO productunit (
productid, unitid, unitsellprice, unitbuyprice, unitquantity,
conditions, isMainUnit, price4, price5, price6, price7, price8
) VALUES (?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?)
-- Insert store inventory for each store
INSERT INTO storedetail (
productid, storeid, productquantity, productbuyprice,
productsellingprice, productDate, userid, reserved,
expiredate, detailComment, dailyentryId
) VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?, 0)
-- Insert size/color variants (if applicable)
INSERT INTO sizecolor (
productid, sizename, colorname, parcode, sellunitprice, buyprice, conditions
) VALUES (?, ?, ?, ?, ?, ?, 0)
-- Insert manufacturing ingredients (if manufacturing product)
INSERT INTO productingredients (
productid, rawmaterialid, quantity, unitid, conditions
) VALUES (?, ?, ?, ?, 0)
-- Generate available parcode entry
INSERT INTO availableparcode (value) VALUES (?)
-- Update product with daily entry ID
UPDATE product SET dailyentryId = ? WHERE productId = ?
show() functions)
-- Get all active products with categories
SELECT product.*, productcat.productCatName
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
WHERE product.conditions = 0 AND productcat.conditions = 0
ORDER BY product.productId DESC
-- Search products by name and category
SELECT product.*, productcat.productCatName
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
WHERE CONCAT(product.productName, "/", productcat.productCatName) LIKE "%?%"
AND product.conditions = 0
AND productcat.conditions = 0
ORDER BY product.productId DESC
-- Get products by category
SELECT * FROM product
WHERE productCatId = ? AND conditions = 0
ORDER BY productId DESC
-- Get products with store quantities
SELECT p.*, pc.productCatName,
SUM(sd.productquantity) as totalQuantity,
GROUP_CONCAT(CONCAT(s.storeName, ':039;, sd.productquantity)) as storeQuantities
FROM product p
JOIN productcat pc ON p.productCatId = pc.productCatId
LEFT JOIN storedetail sd ON p.productId = sd.productid
LEFT JOIN store s ON sd.storeid = s.storeId
WHERE p.conditions = 0
GROUP BY p.productId
ORDER BY p.productId DESC
-- Search by barcode
SELECT productId FROM product WHERE parcode = ? AND conditions = 0
-- Get products by multiple barcodes
SELECT productId, parcode FROM product WHERE parcode IN (?, ?, ?, ...)
update() function)
-- Update main product record
UPDATE product SET
productName = ?, productDescription = ?, productCatId = ?,
productBuyPrice = ?, productSellAllPrice = ?, productSellUnitPrice = ?,
productSellHalfPrice = ?, limitamount = ?, parcode = ?, type = ?,
sellingtype = ?, expireDate = ?, isService = ?, isOptic = ?,
productbuypricereal = ?, buypricereal_precentage = ?, buytotal_precentage = ?,
buyhalf_precentage = ?, buypart_precentage = ?, logo = ?, hasSizeAndColor = ?,
TypeOfBarcodeInTax = ?, barcodeInTax = ?, productNameE = ?,
partNumber = ?, vehicleType = ?, company = ?, weight = ?, origin = ?,
hscode = ?, power = ?, ProductionDate = ?, expiry = ?, procode = ?,
price4 = ?, price5 = ?, price6 = ?, price7 = ?, price8 = ?,
clientid = ?, grantduration = ?, onlinepro = ?, minappearonline = ?,
selladdpercent = ?, selldiscountpercent = ?, buydiscountpercent = ?,
onlinecatid = ?, sellpercenttype = ?, searchfiltersid = ?, itemsymbol = ?,
inMenu = ?, updatebyuser = ?
WHERE productId = ?
-- Update product units (delete and re-insert pattern)
DELETE FROM productunit WHERE productid = ? AND conditions = 0
INSERT INTO productunit (productid, unitid, unitsellprice, unitbuyprice, unitquantity, conditions, isMainUnit, price4, price5, price6, price7, price8)
VALUES (?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?)
-- Update store details
UPDATE storedetail SET
productquantity = ?, productbuyprice = ?, productsellingprice = ?,
expiredate = ?, detailComment = ?
WHERE productid = ? AND storeid = ?
-- Update size/color variants
UPDATE sizecolor SET
sizename = ?, colorname = ?, parcode = ?, sellunitprice = ?, buyprice = ?
WHERE sizecolorid = ?
-- Update manufacturing ingredients
DELETE FROM productingredients WHERE productid = ? AND conditions = 0
INSERT INTO productingredients (productid, rawmaterialid, quantity, unitid, conditions)
VALUES (?, ?, ?, ?, 0)
-- Soft delete product
UPDATE product SET conditions = 1 WHERE productId = ?
-- Soft delete related units
UPDATE productunit SET conditions = 1 WHERE productid = ?
-- Soft delete variants
UPDATE sizecolor SET conditions = 1 WHERE productid = ?
-- Soft delete ingredients
UPDATE productingredients SET conditions = 1 WHERE productid = ?
-- Restore product
UPDATE product SET conditions = 0 WHERE productId = ?
-- Permanent delete (with cleanup)
DELETE FROM productingredients WHERE productid = ?
DELETE FROM sizecolor WHERE productid = ?
DELETE FROM productunit WHERE productid = ?
DELETE FROM storedetail WHERE productid = ?
DELETE FROM productserial WHERE productid = ?
DELETE FROM product WHERE productId = ?
-- Get manufacturing products (final products)
SELECT product.*, productcat.productCatName
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
WHERE product.conditions = 0
AND productcat.conditions = 0
AND product.type = 0
-- Get raw materials
SELECT product.*, productcat.productCatName
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
WHERE product.conditions = 0
AND productcat.conditions = 0
AND product.type = 1
-- Get products with production rates
SELECT product.*, productcat.productCatName
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
JOIN productionrate ON productionrate.finalName = product.productId
WHERE product.conditions = 0
AND productcat.conditions = 0
AND productionrate.conditions = 0
AND product.type = 0
GROUP BY product.productId
-- Get products by price range
SELECT * FROM product
WHERE productSellUnitPrice BETWEEN ? AND ?
AND conditions = 0
-- Get products by store availability
SELECT DISTINCT p.* FROM product p
JOIN storedetail sd ON p.productId = sd.productid
WHERE sd.storeid = ? AND sd.productquantity > 0 AND p.conditions = 0
-- Get low stock products
SELECT p.*, SUM(sd.productquantity) as totalQty
FROM product p
LEFT JOIN storedetail sd ON p.productId = sd.productid
WHERE p.conditions = 0
GROUP BY p.productId
HAVING totalQty < p.limitamount OR totalQty IS NULL
-- Get products with serial numbers
SELECT DISTINCT p.* FROM product p
JOIN productserial ps ON p.productId = ps.productid
WHERE ps.conditions = 0 AND p.conditions = 0
-- Get optic products with variants
SELECT p.*, sc.sizename, sc.colorname, sc.parcode as variant_barcode
FROM product p
LEFT JOIN sizecolor sc ON p.productId = sc.productid
WHERE p.isOptic IN (1, 2) AND p.conditions = 0
ORDER BY p.productId, sc.sizecolorid
-- Get product quantities by store
SELECT sd.*, s.storeName, p.productName
FROM storedetail sd
JOIN store s ON sd.storeid = s.storeId
JOIN product p ON sd.productid = p.productId
WHERE sd.productid = ?
ORDER BY s.storeName
-- Update inventory quantity
UPDATE storedetail
SET productquantity = productquantity + ?
WHERE productid = ? AND storeid = ?
-- Get total product quantity across all stores
SELECT SUM(productquantity) as totalQuantity
FROM storedetail
WHERE productid = ?
-- Move inventory between stores
UPDATE storedetail SET productquantity = productquantity - ?
WHERE productid = ? AND storeid = ?;
UPDATE storedetail SET productquantity = productquantity + ?
WHERE productid = ? AND storeid = ?
-- Reserve inventory
UPDATE storedetail
SET reserved = reserved + ?
WHERE productid = ? AND storeid = ?
-- Generate next available barcode
SELECT MAX(CAST(value AS UNSIGNED)) + 1 as nextBarcode
FROM availableparcode
-- Check barcode uniqueness
SELECT COUNT(*) FROM product WHERE parcode = ?
UNION ALL
SELECT COUNT(*) FROM sizecolor WHERE parcode = ?
-- Add serial number
INSERT INTO productserial (productid, serialnumber, storeid, conditions, userid, productDate)
VALUES (?, ?, ?, 0, ?, ?)
-- Get available serial numbers
SELECT * FROM productserial
WHERE productid = ? AND conditions = 0
ORDER BY serialnumber
-- Mark serial as sold
UPDATE productserial SET conditions = 1 WHERE productserailid = ?
addoptic)
productController.php?do=addoptic
Purpose: Specialized form for adding optical products (glasses/lenses) with size and color variants
">elseif ($do == "addoptic") {
// Display optical product form
unset($_SESSION["productserialArray"]);
$generatedParcode = generateParcode();
$smarty->assign("generatedParcode", $generatedParcode);
$allParents = getProductCatParentOptic(); // Special optic categories
$smarty->assign("allParents", $allParents);
$unitsData = getUnits();
$smarty->assign("unitsData", $unitsData);
$smarty->display("productview/addopticproduct.html");
}
">elseif ($do == "addopticdata") {
include_once("../public/authentication.php");
try {
addoptic(); // Process optical product
header("location:?do=sucess");
} ">catch (Exception $e) {
header("location:?do=error");
}
}
function addoptic() {
$currentType = filter_input(INPUT_POST, "currentType");
">if ($currentType == 0) {
addOpticProductWithSizeColor(); // With variants
} ">elseif ($currentType == 1) {
addOpticProductWithOutSizeColor(); // Without variants
}
}
-- Create Product Category (if new optic category)
INSERT INTO productcat (productCatName, productCatParent, productCatDescription,
conditions, clientid, onlinecatid, searchfiltersid, tagids)
VALUES (?, ?, ?, 0, ?, ?, ?, ?);
-- Create Optic Product
INSERT INTO product (
productName, productBuyPrice, productSellAllPrice, productSellUnitPrice,
productSellHalfPrice, productCatId, limitamount, parcode, type, sellingtype,
isOptic, -- CRITICAL: Mark as optical product
hasSizeAndColor, -- CRITICAL: Enable variants for glasses
productDescription, clientid, expireDate, logo, TypeOfBarcodeInTax,
conditions, addtoday, adduserid
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
2, -- isOptic = 2 (optic with variants)
1, -- hasSizeAndColor = 1 (enable variants)
?, ?, ?, ?, ?, 0, NOW(), ?);
-- Add Size/Color Variants for Optical Products
INSERT INTO sizecolor (
productid, sizename, colorname, parcode, sellunitprice, buyprice,
productquantity, conditions, addtoday, adduserid
) VALUES (@product_id, ?, ?, ?, ?, ?, ?, 0, NOW(), ?);
-- Store Inventory for Each Variant
INSERT INTO storedetail (
productid, storeid, productquantity, productbuyprice, productsellingprice,
parcode, sizeid, colorid, conditions, addtoday, adduserid
) VALUES (@product_id, ?, ?, ?, ?, ?, ?, ?, 0, NOW(), ?);
-- Store Movement Report
INSERT INTO storereport (
productid, storeid, productquantity, productpricebefore, productpriceafter,
storemovementtype, storemovementmodelid, conditions, addtoday, adduserid,
tablename, storemovementcomment
) VALUES (@product_id, ?, ?, 0, ?, 0, @product_id, 0, NOW(), ?,
'productController.php/addoptic039;, 039;إضافة منتج بصريات039;);
getProductCatParentOptic())
POST /api/v1/products/optic
{
"product_name": "string",
"category_id": "integer",
"buy_price": "decimal",
"sell_prices": {
"retail": "decimal",
"wholesale": "decimal",
"unit": "decimal"
},
"variants": [
{
"size": "string",
"color": "string",
"quantity": "integer",
"store_id": "integer"
}
],
"is_optic": 2,
"has_variants": true,
"barcode_auto": true
}
productController.php?do=uploadexcel
Purpose: Upload Excel file to bulk import products
">elseif ($do == "uploadexcel") {
">$youtubes = $youtubeLinkDAO->queryAll();
$smarty->assign("youtubes", $youtubes);
$smarty->display("productview/uploadexcel.html");
}
">elseif ($do == "addproductexcel") {
include_once("../public/authentication.php");
try {
addProductExcelWithColorOrSize(); // Process Excel upload
header("location:?do=sucess");
} ">catch (Exception $e) {
header("location:?do=error");
}
}
productController.php?do=productsAndProUnitsToExcel
Purpose: Export products and units data to Excel format
">elseif ($do == "productsAndProUnitsToExcel") {
// Create PHPExcel object
">$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->setTitle("Products");
// Set headers in Arabic
$objPHPExcel->getActiveSheet()
->SetCellValue('A1039;, 039;اسم التصنيف039;) // Category Name
->SetCellValue('B1039;, 039;اسم المنتج039;) // Product Name
->SetCellValue('C1039;, 039;سعر الشراء039;) // Buy Price
->SetCellValue('D1039;, 039;سعر البيع039;) // Sell Price
->SetCellValue('E1039;, 039;الكمية039;) // Quantity
->SetCellValue('F1039;, 039;الوحدة039;); // Unit
// Export data and download
// ... (continues with data export logic)
}
-- Bulk Product Import from Excel
INSERT INTO product (
productName, productBuyPrice, productSellAllPrice, productCatId,
limitamount, parcode, type, sellingtype, hasSizeAndColor,
conditions, addtoday, adduserid
) VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, 0, NOW(), ?), -- Row 1 from Excel
(?, ?, ?, ?, ?, ?, ?, ?, ?, 0, NOW(), ?), -- Row 2 from Excel
-- ... (multiple rows from Excel file)
-- Handle Size/Color Variants from Excel
INSERT INTO sizecolor (
productid, sizename, colorname, parcode, sellunitprice, buyprice,
productquantity, conditions, addtoday, adduserid
) VALUES (@product_id, ?, ?, ?, ?, ?, ?, 0, NOW(), ?);
-- Create Store Inventory for Imported Products
INSERT INTO storedetail (
productid, storeid, productquantity, productbuyprice, productsellingprice,
conditions, addtoday, adduserid
) VALUES (@product_id, ?, ?, ?, ?, 0, NOW(), ?);
-- Export Query for Excel Generation
SELECT
pc.productCatName as 'اسم التصنيف039;,
p.productName as 'اسم المنتج039;,
p.productBuyPrice as 'سعر الشراء039;,
p.productSellAllPrice as 'سعر البيع039;,
COALESCE(SUM(sd.productquantity), 0) as 'الكمية039;,
u.unitName as 'الوحدة039;,
p.parcode as 'الباركود039;
FROM product p
JOIN productcat pc ON p.productCatId = pc.productCatId
LEFT JOIN storedetail sd ON p.productId = sd.productid
LEFT JOIN productunit pu ON p.productId = pu.productid AND pu.isMainUnit = 1
LEFT JOIN unit u ON pu.unitid = u.unitId
WHERE p.conditions = 0
GROUP BY p.productId
ORDER BY pc.productCatName, p.productName
// Excel Upload
POST /api/v1/products/upload-excel
Content-Type: multipart/form-data
{
"excel_file": "file",
"store_id": "integer",
"category_id": "integer", // Optional default category
"overwrite_existing": "boolean"
}
// Excel Export
GET /api/v1/products/export-excel
Query Parameters:
- → format: excel|csv
- → category_id: integer (optional)
- → store_id: integer (optional)
- → include_variants: boolean
- → include_inventory: boolean
-- Base query with category information
SELECT product.*, productcat.productCatName,
SUM(sd.productquantity) as totalQuantity,
COUNT(DISTINCT sd.storeid) as storeCount
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
LEFT JOIN storedetail sd ON product.productId = sd.productid
WHERE product.conditions = 0 AND productcat.conditions = 0
GROUP BY product.productId
ORDER BY product.productId DESC
LIMIT ? OFFSET ?
-- With filters:
-- Category filter: AND product.productCatId = ?
-- Search: AND (product.productName LIKE "%?%" OR product.parcode LIKE "%?%")
-- Price range: AND product.productSellUnitPrice BETWEEN ? AND ?
-- Store: AND EXISTS(SELECT 1 FROM storedetail WHERE productid = product.productId AND storeid = ?)
-- Low stock: HAVING totalQuantity < product.limitamount
BEGIN TRANSACTION;
-- Insert main product
INSERT INTO product (productName, productCatId, productBuyPrice, productSellUnitPrice, ...)
VALUES (?, ?, ?, ?, ...);
SET @product_id = LAST_INSERT_ID();
-- Insert units
INSERT INTO productunit (productid, unitid, unitsellprice, unitbuyprice, unitquantity, isMainUnit, ...)
VALUES (@product_id, ?, ?, ?, ?, 1, ...);
-- Insert store inventory
INSERT INTO storedetail (productid, storeid, productquantity, productbuyprice, productsellingprice, ...)
VALUES (@product_id, ?, ?, ?, ?, ...);
-- Insert size/color variants (if applicable)
IF (@has_variants) THEN
INSERT INTO sizecolor (productid, sizename, colorname, parcode, sellunitprice, buyprice)
VALUES (@product_id, ?, ?, ?, ?, ?);
END IF;
-- Insert manufacturing recipe (if manufacturing product)
IF (@is_manufacturing) THEN
INSERT INTO productingredients (productid, rawmaterialid, quantity, unitid)
VALUES (@product_id, ?, ?, ?);
END IF;
-- Generate barcode
INSERT INTO availableparcode (value) VALUES (?);
COMMIT;
BEGIN TRANSACTION;
-- Update main product
UPDATE product SET productName = ?, productBuyPrice = ?, ... WHERE productId = ?;
-- Handle units (replace all)
DELETE FROM productunit WHERE productid = ?;
INSERT INTO productunit (productid, unitid, ...) VALUES (?, ?, ...);
-- Update store quantities
UPDATE storedetail SET productquantity = ?, ... WHERE productid = ? AND storeid = ?;
-- Handle variants
DELETE FROM sizecolor WHERE productid = ?;
INSERT INTO sizecolor (productid, sizename, ...) VALUES (?, ?, ...);
COMMIT;
-- Main product with category
SELECT p.*, pc.productCatName FROM product p
JOIN productcat pc ON p.productCatId = pc.productCatId
WHERE p.productId = ? AND p.conditions = 0;
-- Product units
SELECT pu.*, u.unitName FROM productunit pu
JOIN unit u ON pu.unitid = u.unitid
WHERE pu.productid = ? AND pu.conditions = 0;
-- Store inventory
SELECT sd.*, s.storeName FROM storedetail sd
JOIN store s ON sd.storeid = s.storeId
WHERE sd.productid = ?;
-- Variants (if applicable)
SELECT * FROM sizecolor WHERE productid = ? AND conditions = 0;
-- Manufacturing recipe (if applicable)
SELECT pi.*, p.productName as rawMaterialName FROM productingredients pi
JOIN product p ON pi.rawmaterialid = p.productId
WHERE pi.productid = ? AND pi.conditions = 0;
/api/v1/products
GET /api/v1/products
Query Parameters:
page: Page number (default: 1)
limit: Items per page (default: 20, max: 100)
search: Search in name/barcode
category_id: Filter by category
store_id: Filter by store availability
price_min: Minimum selling price
price_max: Maximum selling price
low_stock: Boolean, products below minimum stock
type: Product type (0=regular, 1=manufacturing)
is_service: Boolean, service products only
is_optic: Boolean, optic products only
has_variants: Boolean, products with size/color variants
sort: Sort field (name, price, date, stock)
order: Sort order (asc, desc)
{
"success": true,
"data": [
{
"productId": 1,
"productName": "iPhone 14 Pro",
"productNameE": "iPhone 14 Pro",
"productDescription": "Latest iPhone model with advanced features",
"productCatId": 5,
"category": {
"productCatId": 5,
"productCatName": "Mobile Phones"
},
"productBuyPrice": 800.00,
"productSellUnitPrice": 1200.00,
"productSellAllPrice": 1180.00,
"productSellHalfPrice": 1190.00,
"price4": 1100.00,
"price5": 1050.00,
"price6": 1000.00,
"price7": 950.00,
"price8": 900.00,
"limitamount": 5,
"parcode": "1234567890123",
"type": 0,
"sellingtype": 1,
"isService": 0,
"isOptic": 0,
"hasSizeAndColor": 1,
"logo": "iphone14pro.jpg",
"totalQuantity": 45,
"storeCount": 3,
"stores": [
{
"storeid": 1,
"storeName": "Main Store",
"quantity": 25,
"reserved": 2
},
{
"storeid": 2,
"storeName": "Branch Store",
"quantity": 20,
"reserved": 0
}
],
"units": [
{
"unitid": 1,
"unitName": "Piece",
"isMainUnit": 1,
"unitsellprice": 1200.00,
"unitbuyprice": 800.00,
"unitquantity": 1.0
}
],
"variants": [
{
"sizecolorid": 1,
"sizename": "128GB",
"colorname": "Space Black",
"parcode": "1234567890124",
"sellunitprice": 1200.00,
"buyprice": 800.00
}
],
"productDate": "2024-01-15",
"conditions": 0,
"created_by": 1,
"updated_by": 2,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T14:22:00Z"
}
],
"pagination": {
"current_page": 1,
"total_pages": 25,
"total_items": 487,
"per_page": 20
},
"summary": {
"total_products": 487,
"total_value": 125000.50,
"low_stock_count": 15,
"out_of_stock_count": 3
}
}
GET /api/v1/products/{id}
Response:
{
"success": true,
"data": {
"productId": 1,
"productName": "iPhone 14 Pro",
"productNameE": "iPhone 14 Pro",
"productDescription": "Latest iPhone model with advanced features",
"category": {
"productCatId": 5,
"productCatName": "Mobile Phones"
},
"pricing": {
"productBuyPrice": 800.00,
"productSellUnitPrice": 1200.00,
"productSellAllPrice": 1180.00,
"productSellHalfPrice": 1190.00,
"price4": 1100.00,
"price5": 1050.00,
"price6": 1000.00,
"price7": 950.00,
"price8": 900.00,
"lastbuyprice": 790.00,
"meanbuyprice": 805.00
},
"inventory": {
"limitamount": 5,
"totalQuantity": 45,
"reserved": 2,
"available": 43,
"stores": [
{
"storeid": 1,
"storeName": "Main Store",
"quantity": 25,
"reserved": 2,
"available": 23
}
]
},
"specifications": {
"parcode": "1234567890123",
"weight": 206.0,
"origin": "China",
"partNumber": "A2890",
"vehicleType": 0,
"company": 1,
"power": 0,
"grantduration": 12
},
"variants": [
{
"sizecolorid": 1,
"sizename": "128GB",
"colorname": "Space Black",
"parcode": "1234567890124",
"sellunitprice": 1200.00,
"buyprice": 800.00,
"inventory": {
"totalQuantity": 15,
"stores": [
{
"storeid": 1,
"quantity": 10
}
]
}
}
],
"units": [
{
"unitid": 1,
"unitName": "Piece",
"isMainUnit": 1,
"unitsellprice": 1200.00,
"unitbuyprice": 800.00,
"unitquantity": 1.0
}
],
"manufacturing": {
"type": 0,
"isManufacturing": false,
"ingredients": []
},
"images": {
"logo": "iphone14pro.jpg",
"logo1": "iphone14pro_2.jpg",
"logo2": "iphone14pro_3.jpg"
},
"settings": {
"isService": 0,
"isOptic": 0,
"hasSizeAndColor": 1,
"inMenu": 1,
"onlinepro": 1,
"sellingtype": 1
},
"created_by": 1,
"updated_by": 2,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T14:22:00Z"
}
}
POST /api/v1/products
Content-Type: multipart/form-data
Request Body:
{
"productName": "New Product Name",
"productNameE": "New Product Name EN",
"productDescription": "Product description",
"productCatId": 5,
"productBuyPrice": 100.00,
"productSellUnitPrice": 150.00,
"productSellAllPrice": 145.00,
"productSellHalfPrice": 148.00,
"price4": 140.00,
"price5": 135.00,
"price6": 130.00,
"price7": 125.00,
"price8": 120.00,
"limitamount": 10,
"parcode": "1234567890125",
"type": 0,
"sellingtype": 1,
"isService": 0,
"isOptic": 0,
"hasSizeAndColor": 0,
"inMenu": 1,
"weight": 0.5,
"origin": "Egypt",
"grantduration": 6,
"units": [
{
"unitid": 1,
"isMainUnit": 1,
"unitsellprice": 150.00,
"unitbuyprice": 100.00,
"unitquantity": 1.0
}
],
"stores": [
{
"storeid": 1,
"quantity": 50,
"buyprice": 100.00,
"sellprice": 150.00
}
],
"variants": [
{
"sizename": "Large",
"colorname": "Red",
"parcode": "1234567890126",
"sellunitprice": 155.00,
"buyprice": 105.00
}
],
"ingredients": [
{
"rawmaterialid": 25,
"quantity": 2.0,
"unitid": 1
}
],
"images": {
"logo": "base64_encoded_or_upload",
"logo1": "base64_encoded_or_upload"
}
}
Response:
{
"success": true,
"message": "Product created successfully",
"data": {
"productId": 125,
"productName": "New Product Name",
"parcode": "1234567890125",
"webApiId": 125,
"created_at": "2024-01-20T09:15:00Z"
}
}
PUT /api/v1/products/{id}
Content-Type: multipart/form-data
Request Body: (Same as create)
Response:
{
"success": true,
"message": "Product updated successfully",
"data": {
"productId": 125,
"productName": "Updated Product Name",
"updated_at": "2024-01-20T11:30:00Z",
"updated_by": 2
}
}
DELETE /api/v1/products/{id}
Response:
{
"success": true,
"message": "Product deleted successfully"
}
GET /api/v1/products/{id}/inventory
Response:
{
"success": true,
"data": {
"productId": 1,
"productName": "iPhone 14 Pro",
"totalQuantity": 45,
"reserved": 2,
"available": 43,
"stores": [
{
"storeid": 1,
"storeName": "Main Store",
"quantity": 25,
"reserved": 2,
"available": 23,
"buyprice": 800.00,
"sellprice": 1200.00,
"lastUpdated": "2024-01-15T10:30:00Z"
}
],
"movements": [
{
"date": "2024-01-15T10:30:00Z",
"type": "purchase",
"quantity": 50,
"storeid": 1,
"reference": "PO-001"
}
]
}
}
PUT /api/v1/products/{id}/inventory
Request Body:
{
"stores": [
{
"storeid": 1,
"quantity": 30,
"operation": "set", // set, add, subtract
"reason": "Stock adjustment",
"reference": "ADJ-001"
}
]
}
Response:
{
"success": true,
"message": "Inventory updated successfully",
"data": {
"productId": 1,
"updates": [
{
"storeid": 1,
"old_quantity": 25,
"new_quantity": 30,
"change": 5
}
]
}
}
GET /api/v1/products/search
Query Parameters:
q: Search query
fields: Fields to search (name,barcode,description)
category_id: Limit to category
limit: Maximum results
{
"success": true,
"data": [
{
"productId": 1,
"productName": "iPhone 14 Pro",
"parcode": "1234567890123",
"productCatName": "Mobile Phones",
"productSellUnitPrice": 1200.00,
"totalQuantity": 45
}
]
}
GET /api/v1/products/{id}/variants
Response:
{
"success": true,
"data": [
{
"sizecolorid": 1,
"sizename": "128GB",
"colorname": "Space Black",
"parcode": "1234567890124",
"sellunitprice": 1200.00,
"buyprice": 800.00,
"inventory": {
"totalQuantity": 15,
"stores": [
{
"storeid": 1,
"storeName": "Main Store",
"quantity": 10
}
]
}
}
]
}
POST /api/v1/products/bulk-import
Content-Type: multipart/form-data
Request:
file: Excel file (.xlsx, .xls)
update_existing: Boolean, update if product exists
{
"success": true,
"message": "Bulk import completed",
"data": {
"imported": 150,
"updated": 25,
"skipped": 5,
"errors": 2,
"details": [
{"row": 3, "error": "Invalid category"},
{"row": 7, "error": "Duplicate barcode"}
]
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The given data was invalid",
"details": {
"productName": ["Product name is required"],
"productBuyPrice": ["Buy price must be greater than 0"],
"parcode": ["Barcode already exists"]
}
}
}
$rules = [
'productName039; => 039;required|string|max:256039;,
'productCatId039; => 039;required|exists:productcat,productCatId039;,
'productBuyPrice039; => 039;required|numeric|min:0039;,
'productSellUnitPrice039; => 039;required|numeric|gte:productBuyPrice039;,
'parcode039; => 039;nullable|string|max:256|unique:product,parcode|unique:sizecolor,parcode039;,
'limitamount039; => 039;integer|min:0039;,
'type039; => 039;in:0,1039;,
'isService039; => 039;boolean039;,
'isOptic039; => 039;in:0,1,2039;,
'hasSizeAndColor039; => 039;boolean039;
];
// Business validations
">if ($productBuyPrice > $productSellUnitPrice) {
throw new ValidationException('Selling price must be greater than buying price039;);
}
">if ($parcode && $this->barcodeExists($parcode)) {
throw new ValidationException('Barcode already exists039;);
}
-- Essential indexes for products
CREATE INDEX idx_product_name ON product(productName);
CREATE INDEX idx_product_category ON product(productCatId);
CREATE INDEX idx_product_barcode ON product(parcode);
CREATE INDEX idx_product_conditions ON product(conditions);
CREATE INDEX idx_product_type ON product(type);
CREATE INDEX idx_product_service ON product(isService);
CREATE INDEX idx_product_optic ON product(isOptic);
-- Store inventory indexes
CREATE INDEX idx_storedetail_product ON storedetail(productid);
CREATE INDEX idx_storedetail_store ON storedetail(storeid);
CREATE INDEX idx_storedetail_quantity ON storedetail(productquantity);
-- Variant indexes
CREATE INDEX idx_sizecolor_product ON sizecolor(productid);
CREATE INDEX idx_sizecolor_barcode ON sizecolor(parcode);
-- Manufacturing indexes
CREATE INDEX idx_ingredients_product ON productingredients(productid);
CREATE INDEX idx_ingredients_raw ON productingredients(rawmaterialid);
curl -X POST http://localhost/api/v1/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-jwt-token" \
-d '{
"productName": "New Product",
"productCatId": 1,
"productBuyPrice": 50.00,
"productSellUnitPrice": 75.00,
"parcode": "1234567890",
"units": [{"unitid": 1, "isMainUnit": 1, "unitsellprice": 75.00, "unitbuyprice": 50.00, "unitquantity": 1.0}],
"stores": [{"storeid": 1, "quantity": 100}]
}'
curl -X GET "http://localhost/api/v1/products/search?q=iPhone&category_id=5&limit=20" \
-H "Authorization: Bearer your-jwt-token"
curl -X PUT http://localhost/api/v1/products/123/inventory \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-jwt-token" \
-d '{
"stores": [
{
"storeid": 1,
"quantity": 50,
"operation": "add",
"reason": "New stock arrival"
}
]
}'
class ProductAPI {
constructor(baseURL, token) {
this.baseURL = baseURL;
this.token = token;
}
async getProducts(filters = {}) {
const params = new URLSearchParams(filters);
const response = ">await fetch(${this.baseURL}/api/v1/products?${params}, {
headers: { 'Authorization039;: Bearer ${this.token} }
});
return await response.json();
}
async createProduct(productData) {
const response = ">await fetch(${this.baseURL}/api/v1/products, {
method: 'POST039;,
headers: {
'Content-Type039;: 039;application/json039;,
'Authorization039;: Bearer ${this.token}
},
body: JSON.stringify(productData)
});
return await response.json();
}
async updateInventory(productId, inventoryData) {
const response = ">await fetch(${this.baseURL}/api/v1/products/${productId}/inventory, {
method: 'PUT039;,
headers: {
'Content-Type039;: 039;application/json039;,
'Authorization039;: Bearer ${this.token}
},
body: JSON.stringify(inventoryData)
});
return await response.json();
}
async searchProducts(query, options = {}) {
const params = new URLSearchParams({ q: query, ...options });
const response = ">await fetch(${this.baseURL}/api/v1/products/search?${params}, {
headers: { 'Authorization039;: Bearer ${this.token} }
});
return await response.json();
}
}
// Product caching
Cache::remember("product_{$productId}", 1800, ">function() ">use ($productId) {
return Product::with(['category039;, 039;units039;, 039;variants039;, 039;stores039;])->find($productId);
});
// Inventory optimization
$products = Product::select('productId039;, 039;productName039;, 039;parcode039;)
->with(['stores039; => ">function($query) {
$query->select('productid039;, 039;storeid039;, 039;productquantity039;);
}])
->whereHas('stores039;, ">function($query) {
$query->where('productquantity039;, 039;>039;, 0);
})
->paginate(50);
">public function test_can_create_product_with_variants()
{
$productData = [
'productName039; => 039;Test Product039;,
'productCatId039; => 1,
'productBuyPrice039; => 50.00,
'productSellUnitPrice039; => 75.00,
'hasSizeAndColor039; => 1,
'variants039; => [
[
'sizename039; => 039;Large039;,
'colorname039; => 039;Red039;,
'sellunitprice039; => 80.00,
'buyprice039; => 55.00
]
]
];
$response = $this->postJson('/api/v1/products039;, $productData);
$response->assertStatus(201)
->assertJson([
'success039; => true,
'data039; => [
'productName039; => 039;Test Product039;
]
]);
$this->assertDatabaseHas('product039;, [039;productName039; => 039;Test Product039;]);
$this->assertDatabaseHas('sizecolor039;, [039;sizename039; => 039;Large039;]);
}
---
properties.sql and controller examination but were missing from the original documentation.
productCatController.php
productController.php ✅ FULLY DOCUMENTED
unitController.php
sparePartController.php
storeparcodeController.php
sizecolorController.php
// Line 439-467 in productController.php
">elseif ($do == "deleted") {
$allproductdata = $productDAO->queryByConditions(1); // conditions=1 means deleted
$smarty->assign("productsData", $allproductdata);
$alldata = getProductCatsForShow();
$smarty->assign("alldata", $alldata);
$smarty->display("productview/deleted.html");
}
SQL Operations:
-- Get all deleted products
SELECT * FROM product WHERE conditions = 1 ORDER BY productId DESC
-- Get product categories for filtering
SELECT productcat.*, parent.productCatName as parentName
FROM productcat
LEFT JOIN productcat as parent ON productcat.productCatParentId = parent.productCatId
WHERE productcat.conditions = 0
API Endpoint: GET /controllers/productController.php?do=deleted
Business Logic:
// Line 1264-1292 in productController.php
">elseif ($do == "showbarcode") {
$Programsettingdata = $ProgramsettingDAO->load(1);
$smarty->assign("Programsettingdata", $Programsettingdata);
">$companyname = $ProgramsettingsDAO->load(1);
$smarty->assign("companyname", $companyname->companyname);
// Get user's store for quantity display
$userdata = $userDAO->load($_SESSION['userid039;]);
$storeid = $userdata->userstoreid;
$smarty->assign("storeid", $storeid);
$smarty->assign("productScripts", 1);
$smarty->display("productview/addproduct.html");
}
SQL Operations:
-- Get program settings for barcode configuration
SELECT * FROM programsettings WHERE programsettingsid = 1
-- Get user's store assignment
SELECT * FROM user WHERE userid = ?
-- Get products with barcodes
SELECT product.*, productcat.productCatName
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
WHERE product.conditions = 0 AND product.productparcode IS NOT NULL
API Endpoint: GET /controllers/productController.php?do=showbarcode
Business Logic:
// Line 1341+ in productController.php
">elseif ($do == "showbarcodebuybill") {
">$buybillid = $_GET['buybillid039;];
$parcodeTypeToPrint = (int) $_GET['parcodeTypeToPrint039;];
">$type = $_GET['type039;];
// Get all products from purchase bill
$allproductbuy = $buyBillDetailDAO->queryByBuybillid($buybillid);
foreach ($allproductbuy as $allpro) {
$productfullinfo = $productDAO->load($allpro->buybilldetailproductid);
// Process barcode generation for each product
}
}
SQL Operations:
-- Get purchase bill products
SELECT * FROM buybilldetail WHERE buybilldetailbuybillid = ?
-- Get full product information
SELECT product.*, productcat.productCatName, productunit.productunitname
FROM product
JOIN productcat ON product.productCatId = productcat.productCatId
JOIN productunit ON product.productunitid = productunit.productunitid
WHERE product.productId = ?
-- Update barcode printing status
UPDATE buybilldetail SET printed = 1 WHERE buybilldetailid = ?
API Endpoint: GET /controllers/productController.php?do=showbarcodebuybill&buybillid={id}&parcodeTypeToPrint={type}
Business Logic: Generate printable barcodes for newly purchased inventory
---
// Line 1897+ in productController.php
">elseif ($do == "addCollectiveProduct") {
// Collective product creation logic
// Allows creating product bundles/kits
// Manages component relationships
}
SQL Operations:
-- Create main collective product
INSERT INTO product (productName, productCatId, isCollective, conditions, userid)
VALUES (?, ?, 1, 0, ?)
-- Add component products to collective
INSERT INTO collectiveproduct (collectiveProductId, componentProductId, componentQuantity)
VALUES (?, ?, ?)
-- Update component stock when collective is sold
UPDATE productstoreunit SET productQuantity = productQuantity - ?
WHERE productid = ? AND storeid = ?
API Endpoint: POST /controllers/productController.php?do=addCollectiveProduct
Business Logic:
// Line 1924+ in productController.php
">elseif ($do == "addsizecolorproduct") {
// Add size/color variants to products
// Used for clothing, shoes, etc.
// Manages variant pricing and inventory
}
SQL Operations:
-- Add size variant
INSERT INTO sizecolor (productId, sizeId, colorId, quantity, price)
VALUES (?, ?, ?, ?, ?)
-- Update product to indicate it has variants
UPDATE product SET hasSizeColor = 1 WHERE productId = ?
-- Get available sizes and colors
SELECT * FROM size WHERE conditions = 0
SELECT * FROM color WHERE conditions = 0
Business Logic: Manage product variants with separate inventory tracking
---
// Line 870+ in productController.php
">elseif ($do == "executeOperation") {
try {
executeOperation(); // Function processes bulk operations
show();
$smarty->display("productview/show.html");
} ">catch (Exception $e) {
$smarty->display("error.html");
}
}
SQL Operations:
-- Bulk soft delete
UPDATE product SET conditions = 1 WHERE productId IN (?, ?, ?)
-- Bulk restore
UPDATE product SET conditions = 0 WHERE productId IN (?, ?, ?)
-- Bulk price update
UPDATE product SET productSellPrice = ? WHERE productId IN (?, ?, ?)
-- Bulk category change
UPDATE product SET productCatId = ? WHERE productId IN (?, ?, ?)
API Endpoint: POST /controllers/productController.php?do=executeOperation
---
// Line 1015+ in productController.php
">elseif ($do == "returndelete") {
try {
$note = returndelete(); // Restore deleted product
">if ($note != "success") {
$smarty->assign('msgnote039;, $note);
$smarty->display("notes.html");
} else {
header("location:?do=sucess");
}
} ">catch (Exception $e) {
header("location:?do=error");
}
}
SQL Operations:
-- Restore deleted product
UPDATE product SET conditions = 0 WHERE productId = ?
-- Check for dependencies before restore
SELECT COUNT(*) FROM sellbillunit WHERE sellbillunitproductid = ?
SELECT COUNT(*) FROM buybilldetail WHERE buybilldetailproductid = ?
---
// Line 1036+ in productController.php
">elseif ($do == "tempdelete") {
try {
$note = tempdelete();
">if ($note != "success") {
$smarty->assign('msgnote039;, $note);
$smarty->display("notes.html");
} else {
header("location:?do=sucess");
}
} ">catch (Exception $e) {
header("location:?do=error");
}
}
SQL Operations:
-- Soft delete product
UPDATE product SET conditions = 1 WHERE productId = ?
-- Log deletion activity
INSERT INTO productactivity (productId, action, userid, activity_date)
VALUES (?, 'soft_delete039;, ?, NOW())
---
// Line 1229+ in productController.php
">elseif ($do == "deleteFinaly") {
try {
$data = deleteFinaly();
">if ($data != -1) {
header("location:?do=sucess");
} else {
header("location:?do=error");
}
} ">catch (Exception $e) {
header("location:?do=error");
}
}
SQL Operations:
-- Check for dependencies
SELECT COUNT(*) FROM sellbillunit WHERE sellbillunitproductid = ?
SELECT COUNT(*) FROM buybilldetail WHERE buybilldetailproductid = ?
-- Delete product images
DELETE FROM productimage WHERE productId = ?
-- Delete size/color variants
DELETE FROM sizecolor WHERE productId = ?
-- Finally delete product
DELETE FROM product WHERE productId = ?
---