deliveries
This commit is contained in:
@@ -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 {
|
||||
// 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)=CURDATE()
|
||||
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,
|
||||
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 ?
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user