store filter
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user