deliveries

This commit is contained in:
2026-09-03 19:12:03 +05:30
parent 18a0f9b34d
commit fb5d7da81f
2 changed files with 78 additions and 11 deletions

View File

@@ -130,9 +130,36 @@ func (r *deliveriesRepository) CreateDeliveries(data []models.Deliveries) error
ord.Orderstatus = data[i].Orderstatus
ord.Pending = data[i].Deliverydate
res := tx.Table("orders").
Where("orderheaderid=?", data[i].Orderheaderid).
Updates(&ord)
if res.Error != nil {
tx.Rollback()
return res.Error
}
// An UPDATE matching no rows is not an SQL error, so a delivery could
// be created against an orderheaderid that does not exist and the whole
// call would still report success — leaving a job in the rider's queue
// for an order nobody can open. Same shape as the stock-request reject
// that reported "4 updated" when only 3 existed.
if res.RowsAffected == 0 {
tx.Rollback()
return fmt.Errorf("order %d not found", data[i].Orderheaderid)
}
// Link the order back to its delivery.
//
// Nothing wrote this column. `orders.deliveryid` was NULL on every row
// in production, which meant there was no way to ask an order whether
// it had been assigned — the console had to cross-reference the whole
// deliveries list to find out. Written here, in the same transaction as
// the delivery itself, so the two can never disagree.
//
// `data[i].Deliveryid` is filled in by the Create above: it is the
// primary key GORM reads back after the insert.
if err := tx.Table("orders").
Where("orderheaderid=?", data[i].Orderheaderid).
Updates(&ord).Error; err != nil {
Update("deliveryid", data[i].Deliveryid).Error; err != nil {
tx.Rollback()
return err
}
@@ -533,11 +560,14 @@ func (r *deliveriesRepository) GetTenantDeliveries(input models.DeliveryQuery) [
offset := (input.Pageno - 1) * input.Pagesize
// LEFT JOIN on the rider, for the same reason as the branch-scoped read
// below: the rider's row supplies a name and a phone number, and a delivery
// whose rider is later deactivated should lose the name, not the job.
baseQuery := `
SELECT a.*, b.tenantname, c.firstname AS ridername, c.contactno AS ridercontact
FROM deliveries a
JOIN tenants b ON a.tenantid = b.tenantid
JOIN app_users c ON a.userid = c.userid
LEFT JOIN app_users c ON a.userid = c.userid
WHERE a.tenantid = ?
`
queryBuilder.WriteString(baseQuery)
@@ -903,10 +933,15 @@ func (r *deliveriesRepository) GetDeliveryQueues(uid int, fdate, tdate string) (
return nil, err
}
} else {
q1 = deliveries + `
WHERE a.orderstatus='pending'
AND a.userid=?
AND DATE(a.deliverydate)=CURDATE()
// CURRENT_DATE, not CURDATE(). The latter is MySQL and this is
// Postgres, so this branch answered
// `500 function curdate() does not exist` every time it was taken —
// which is every call a rider's app makes without a date range, i.e.
// "show me today's jobs". Verified locally 2026-09-03.
q1 = deliveries + `
WHERE a.orderstatus='pending'
AND a.userid=?
AND DATE(a.deliverydate)=CURRENT_DATE
ORDER BY a.deliveryid ASC`
if err := r.db.Raw(q1, uid).Find(&data).Error; err != nil {
return nil, err
@@ -924,13 +959,32 @@ func (r *deliveriesRepository) GetTenantLocationDeliveries(input models.Delivery
offset := (input.Pageno - 1) * input.Pagesize
// LEFT JOIN on the rider and the customer; INNER only on the tenant.
//
// All three were inner joins and two of them were filtering the result to
// nothing. `deliverycustomerid` is 0 on every delivery this system has
// written — neither the app nor the old console sets it — so joining
// `customers` on it matched no row, and the branch-scoped read returned an
// empty list for every branch of every tenant.
//
// Measured on production 2026-09-03: tenant 1135 has 7 deliveries, 6 of
// them at location 1166, and ?tenantid=1135&locationid=1166 returned 0.
// That is the entire deliveries page for a store user, who is pinned to one
// branch and so always sends a locationid.
//
// The rider join is the same shape and would hide a delivery whose rider
// was later deactivated — the accidental-filter pattern already fixed in
// GetStaffs, GetUserById, GetTenantByID and the order listings.
//
// `customertoken` is the only thing the customer join contributes: a push
// token, worth having and not worth losing the row over.
qb.WriteString(`
SELECT a.*, b.tenantname, c.firstname AS ridername,
SELECT a.*, b.tenantname, c.firstname AS ridername,
c.contactno AS ridercontact, d.customertoken
FROM deliveries a
JOIN tenants b ON a.tenantid = b.tenantid
JOIN app_users c ON a.userid = c.userid
JOIN customers d ON a.deliverycustomerid = d.customerid
LEFT JOIN app_users c ON a.userid = c.userid
LEFT JOIN customers d ON a.deliverycustomerid = d.customerid
WHERE a.tenantid = ? AND a.locationid = ?
`)
@@ -948,11 +1002,15 @@ func (r *deliveriesRepository) GetTenantLocationDeliveries(input models.Delivery
if input.Keyword != "" {
like := "%" + input.Keyword + "%"
// A stray `m` sat after the third OR — a typed character that reached
// production. Postgres rejects the whole statement, so searching within
// a branch's deliveries failed outright rather than returning nothing,
// which is why it was invisible behind the empty-list bug above.
qb.WriteString(`
AND (
a.pickupcustomer LIKE ? OR
b.tenantname LIKE ? OR
a.deliverycustomer LIKE ? OR m
a.deliverycustomer LIKE ? OR
a.pickupcontactno LIKE ? OR
a.deliverycontactno LIKE ? OR
a.orderid LIKE ?

View File

@@ -90,7 +90,16 @@ const (
a.orderamount, a.ordervalue, a.taxamount, a.ordercharges,
a.customerid, a.pickuplocationid, a.pickupaddress, a.pickuplat, a.pickuplong,
a.pickupcustomer, a.pickupcontactno, a.pickuplocation as pickupsuburb, a.pickupcity,
a.deliveryid AS deliverycustomerid, a.deliveryaddress, a.deliverylat, a.deliverylong, a.deliverytype,
-- deliveryid is selected under its own name as well as under the
-- deliverycustomerid alias it has always carried.
--
-- The alias alone meant no caller could ask an order whether a rider
-- had been assigned to it: the deliveryid field on the response was the
-- struct's zero value on every row ever returned, because nothing was
-- ever selected into it. The alias stays rather than being corrected --
-- the customer app has read it for as long as it has existed, and both
-- names now carry the same value.
a.deliveryid AS deliverycustomerid, a.deliveryid, a.deliveryaddress, a.deliverylat, a.deliverylong, a.deliverytype,
a.deliverycustomer,a.deliverycontactno,a.deliverylocation as deliverysuburb, a.deliverycity, a.paymenttype, a.smsdelivery, b.customertoken,
c.tenantname, c.tenanttoken, c.primarycontact AS tenantcontactno, c.postcode AS tenantpostcode, c.suburb AS tenantsuburb, c.city AS tenantcity,
d.locationname, d.contactno AS locationcontactno, d.postcode AS locationpostcode, d.suburb AS locationsuburb, d.city AS locationcity