product quantity

This commit is contained in:
2026-07-28 15:37:04 +05:30
parent c2f7d2481c
commit 139ce5cda2

View File

@@ -409,11 +409,19 @@ func (r *productRepository) GetLocationProducts(tenantID, locationID, subcategor
// a.* only covers products (whose price column is retailprice, the master
// price), so without this the catalogue could never read back a price set
// for this outlet via CreateProductLocation.
// quantity/productstock both alias the same live SUM(in)-SUM(out) balance
// from productstocks — placed after a.* so they overwrite the static,
// never-decremented products.quantity column GORM would otherwise scan
// into Locationproducts.Quantity, which is what made the console's stock
// column look frozen after an order despite CreateOrder recording the
// "out" ledger entry correctly.
query := `SELECT a.*, b.productlocationid, b.status, b.price,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END), 0) AS total_in,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS total_out,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END) -
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS productstock
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS productstock,
COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END) -
SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS quantity
FROM products a
INNER JOIN productlocations b ON a.productid = b.productid AND a.tenantid = b.tenantid
LEFT JOIN productstocks c ON a.productid = c.productid AND b.locationid = c.locationid AND a.tenantid = c.tenantid
@@ -593,12 +601,15 @@ func (r *productRepository) GetProductByVariant(tenantid, variantid, locationid
var data []models.Products
// productstock is a correlated subquery (not a JOIN+GROUP BY) so it can
// coexist with `p.*` without having to enumerate every products column.
// When locationid is 0 (caller didn't scope to a store), both the
// subquery and the productlocations join simply match nothing, so
// Productstock/Locationstatus come back zero-valued — same response
// shape as before this field existed, not an error.
// productstock/quantity are correlated subqueries (not a JOIN+GROUP BY) so
// they can coexist with `p.*` without having to enumerate every products
// column. quantity is duplicated on purpose: it's placed after `p.*` so it
// overwrites the static, never-decremented products.quantity column that
// would otherwise scan into Products.Quantity. When locationid is 0
// (caller didn't scope to a store), both subqueries and the
// productlocations join simply match nothing, so
// Productstock/Quantity/Locationstatus come back zero-valued — same
// response shape as before this field existed, not an error.
err := r.db.
Table("products p").
Select(`
@@ -613,8 +624,14 @@ func (r *productRepository) GetProductByVariant(tenantid, variantid, locationid
SUM(CASE WHEN LOWER(ps.stocktype) = 'out' THEN ps.quantity ELSE 0 END)
FROM productstocks ps
WHERE ps.productid = p.productid AND ps.tenantid = p.tenantid AND ps.locationid = ?
), 0) AS productstock
`, locationid).
), 0) AS productstock,
COALESCE((
SELECT SUM(CASE WHEN LOWER(ps.stocktype) = 'in' THEN ps.quantity ELSE 0 END) -
SUM(CASE WHEN LOWER(ps.stocktype) = 'out' THEN ps.quantity ELSE 0 END)
FROM productstocks ps
WHERE ps.productid = p.productid AND ps.tenantid = p.tenantid AND ps.locationid = ?
), 0) AS quantity
`, locationid, locationid).
Joins("LEFT JOIN productcategories c ON p.categoryid = c.categoryid").
Joins("LEFT JOIN productsubcategories d ON p.subcategoryid = d.subcatid").
Joins("LEFT JOIN productdiscounts pd ON pd.productid = p.productid").