deliveries
This commit is contained in:
@@ -130,9 +130,36 @@ func (r *deliveriesRepository) CreateDeliveries(data []models.Deliveries) error
|
|||||||
ord.Orderstatus = data[i].Orderstatus
|
ord.Orderstatus = data[i].Orderstatus
|
||||||
ord.Pending = data[i].Deliverydate
|
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").
|
if err := tx.Table("orders").
|
||||||
Where("orderheaderid=?", data[i].Orderheaderid).
|
Where("orderheaderid=?", data[i].Orderheaderid).
|
||||||
Updates(&ord).Error; err != nil {
|
Update("deliveryid", data[i].Deliveryid).Error; err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -533,11 +560,14 @@ func (r *deliveriesRepository) GetTenantDeliveries(input models.DeliveryQuery) [
|
|||||||
|
|
||||||
offset := (input.Pageno - 1) * input.Pagesize
|
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 := `
|
baseQuery := `
|
||||||
SELECT a.*, b.tenantname, c.firstname AS ridername, c.contactno AS ridercontact
|
SELECT a.*, b.tenantname, c.firstname AS ridername, c.contactno AS ridercontact
|
||||||
FROM deliveries a
|
FROM deliveries a
|
||||||
JOIN tenants b ON a.tenantid = b.tenantid
|
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 = ?
|
WHERE a.tenantid = ?
|
||||||
`
|
`
|
||||||
queryBuilder.WriteString(baseQuery)
|
queryBuilder.WriteString(baseQuery)
|
||||||
@@ -903,10 +933,15 @@ func (r *deliveriesRepository) GetDeliveryQueues(uid int, fdate, tdate string) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
q1 = deliveries + `
|
// CURRENT_DATE, not CURDATE(). The latter is MySQL and this is
|
||||||
WHERE a.orderstatus='pending'
|
// Postgres, so this branch answered
|
||||||
AND a.userid=?
|
// `500 function curdate() does not exist` every time it was taken —
|
||||||
AND DATE(a.deliverydate)=CURDATE()
|
// 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`
|
ORDER BY a.deliveryid ASC`
|
||||||
if err := r.db.Raw(q1, uid).Find(&data).Error; err != nil {
|
if err := r.db.Raw(q1, uid).Find(&data).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -924,13 +959,32 @@ func (r *deliveriesRepository) GetTenantLocationDeliveries(input models.Delivery
|
|||||||
|
|
||||||
offset := (input.Pageno - 1) * input.Pagesize
|
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(`
|
qb.WriteString(`
|
||||||
SELECT a.*, b.tenantname, c.firstname AS ridername,
|
SELECT a.*, b.tenantname, c.firstname AS ridername,
|
||||||
c.contactno AS ridercontact, d.customertoken
|
c.contactno AS ridercontact, d.customertoken
|
||||||
FROM deliveries a
|
FROM deliveries a
|
||||||
JOIN tenants b ON a.tenantid = b.tenantid
|
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
|
||||||
JOIN customers d ON a.deliverycustomerid = d.customerid
|
LEFT JOIN customers d ON a.deliverycustomerid = d.customerid
|
||||||
WHERE a.tenantid = ? AND a.locationid = ?
|
WHERE a.tenantid = ? AND a.locationid = ?
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@@ -948,11 +1002,15 @@ func (r *deliveriesRepository) GetTenantLocationDeliveries(input models.Delivery
|
|||||||
|
|
||||||
if input.Keyword != "" {
|
if input.Keyword != "" {
|
||||||
like := "%" + 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(`
|
qb.WriteString(`
|
||||||
AND (
|
AND (
|
||||||
a.pickupcustomer LIKE ? OR
|
a.pickupcustomer LIKE ? OR
|
||||||
b.tenantname LIKE ? OR
|
b.tenantname LIKE ? OR
|
||||||
a.deliverycustomer LIKE ? OR m
|
a.deliverycustomer LIKE ? OR
|
||||||
a.pickupcontactno LIKE ? OR
|
a.pickupcontactno LIKE ? OR
|
||||||
a.deliverycontactno LIKE ? OR
|
a.deliverycontactno LIKE ? OR
|
||||||
a.orderid LIKE ?
|
a.orderid LIKE ?
|
||||||
|
|||||||
@@ -90,7 +90,16 @@ const (
|
|||||||
a.orderamount, a.ordervalue, a.taxamount, a.ordercharges,
|
a.orderamount, a.ordervalue, a.taxamount, a.ordercharges,
|
||||||
a.customerid, a.pickuplocationid, a.pickupaddress, a.pickuplat, a.pickuplong,
|
a.customerid, a.pickuplocationid, a.pickupaddress, a.pickuplat, a.pickuplong,
|
||||||
a.pickupcustomer, a.pickupcontactno, a.pickuplocation as pickupsuburb, a.pickupcity,
|
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,
|
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,
|
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
|
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