store filter

This commit is contained in:
2026-08-31 16:39:20 +05:30
parent bc10b589cd
commit d8cfe2e87b

View File

@@ -508,7 +508,27 @@ func (r *productRepository) GetLocationProducts(tenantID, locationID, subcategor
}
offset := (pageno - 1) * pagesize
params := []interface{}{tenantID, locationID}
// locationID 0 means EVERY branch this tenant runs.
//
// There was no such read, and the console papered over it by listing the
// FIRST branch under "All branches" — so a merchant with five outlets saw
// RS Puram's four products and not NSN's five, with nothing on screen
// saying so. Picking one branch showed MORE than picking all of them, which
// is the one shape a filter must never have.
//
// Aggregated per product rather than one row per branch: this is the admin
// catalogue answering "what do we sell", and the same product repeated five
// times is a different question nobody asked. Stock sums across branches —
// each productstocks row belongs to exactly one branch, so the join cannot
// double-count it — while price, publication and status collapse to the
// best answer any branch has, which is what a tenant-wide view of a
// per-branch column means.
allBranches := locationID <= 0
params := []interface{}{tenantID}
if !allBranches {
params = append(params, locationID)
}
// b.price is the per-store selling price. It has to be selected explicitly:
// a.* only covers products (whose price column is retailprice, the master
@@ -531,8 +551,20 @@ func (r *productRepository) GetLocationProducts(tenantID, locationID, subcategor
// productlocations. Without it the column came back null for every row —
// including ones that had just been published — and the store catalogue,
// which filters on it, showed nothing.
query := `SELECT a.*, b.productlocationid, b.status, b.publishedat,
COALESCE(NULLIF(b.price, 0), a.retailprice, 0) AS price,
// Per-branch columns are aggregated when every branch is asked for, and
// selected plainly when one is. Postgres needs one or the other — a column
// that is neither grouped nor aggregated is a hard error, not a warning —
// so the two shapes are written out rather than patched together.
perBranch := `b.productlocationid, b.status, b.publishedat,
COALESCE(NULLIF(b.price, 0), a.retailprice, 0) AS price,`
if allBranches {
perBranch = `MIN(b.productlocationid) AS productlocationid,
MAX(b.status) AS status,
MAX(b.publishedat) AS publishedat,
COALESCE(NULLIF(MAX(b.price), 0), a.retailprice, 0) AS price,`
}
query := `SELECT a.*, ` + perBranch + `
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) -
@@ -541,8 +573,11 @@ func (r *productRepository) GetLocationProducts(tenantID, locationID, subcategor
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
WHERE a.approve=1 AND a.tenantid = ? AND b.locationid = ?`
LEFT JOIN productstocks c ON a.productid = c.productid AND b.locationid = c.locationid AND a.tenantid = c.tenantid
WHERE a.approve=1 AND a.tenantid = ?`
if !allBranches {
query += ` AND b.locationid = ?`
}
if subcategoryID != 0 {
query += " AND a.subcategoryid = ?"
@@ -554,10 +589,18 @@ func (r *productRepository) GetLocationProducts(tenantID, locationID, subcategor
params = append(params, "%"+strings.ToLower(keyword)+"%")
}
query += ` GROUP BY a.productid, a.productname, a.productimage, a.categoryid, a.subcategoryid,
// Grouped by the product alone when every branch is asked for, so one
// product is one row however many outlets stock it. Including b.locationid
// there would return the same product five times over — which is what a
// merchant with five branches would have seen instead of a catalogue.
groupBy := ` GROUP BY a.productid, a.productname, a.productimage, a.categoryid, a.subcategoryid,
a.productunit, a.productcost, a.taxpercent, a.taxamount, a.retailprice,
b.tenantid, b.locationid, b.productlocationid, b.status, b.price, b.publishedat
ORDER BY a.productid DESC LIMIT ? OFFSET ?`
b.tenantid, b.locationid, b.productlocationid, b.status, b.price, b.publishedat`
if allBranches {
groupBy = ` GROUP BY a.productid, a.productname, a.productimage, a.categoryid, a.subcategoryid,
a.productunit, a.productcost, a.taxpercent, a.taxamount, a.retailprice`
}
query += groupBy + ` ORDER BY a.productid DESC LIMIT ? OFFSET ?`
params = append(params, pagesize, offset)