fix: per-site attribution needs its own column, not pickuplocationid
Caught by testing the previous commit against production: creating a booking with a resolved site failed with pickupbookings_pickuplocationid_fkey FOREIGN KEY (pickuplocationid) REFERENCES appcustomerlocations(...) pickuplocationid is the *customer's* saved address, a B2C concept. It never referred to the client company's own kitchens or branches. The pre-existing code that validated an incoming pickuplocationid against TenantLocation was wrong on the same point and would have 500'd for any caller that used it — it had simply never been called with a value. Adds tenantlocationid to pickupbookings and consignments (nullable, indexed, additive via AutoMigrate), carried across at pickup, and points the reporting filter, the by_location breakdown and the Unattributed bucket at it. The booking request accepts tenantlocationid, and still accepts pickuplocationid as an alias so anything written against the earlier docs starts working instead of failing. Also gofmt on the two model files touched; booking.go was already failing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -356,7 +356,7 @@ func GetAdminReports(c *fiber.Ctx) error {
|
||||
|
||||
bookingScope := func() *gorm.DB {
|
||||
q := scopeToTenant(db.DB.Model(&models.PickupBooking{}), "tenantid", ownTenant)
|
||||
return scopeToLocation(q, "pickuplocationid", locationID)
|
||||
return scopeToLocation(q, "tenantlocationid", locationID)
|
||||
}
|
||||
|
||||
var totalBookings int64
|
||||
@@ -374,7 +374,7 @@ func GetAdminReports(c *fiber.Ctx) error {
|
||||
|
||||
consignmentQuery := scopeToLocation(
|
||||
scopeToTenant(db.DB.Model(&models.Consignment{}), "tenantid", ownTenant),
|
||||
"pickuplocationid", locationID).
|
||||
"tenantlocationid", locationID).
|
||||
Where("createdat BETWEEN ? AND ?", from, to)
|
||||
if hubID != "" {
|
||||
consignmentQuery = consignmentQuery.Where("currenthubid = ?", hubID)
|
||||
@@ -639,11 +639,11 @@ func GetLocationSummary(c *fiber.Ctx) error {
|
||||
// each of the client's own locations raised in the range, how many reached a
|
||||
// consignment, and what COD came back.
|
||||
//
|
||||
// Bookings with no pickuplocationid are reported as a single "Unattributed"
|
||||
// Bookings with no tenantlocationid are reported as a single "Unattributed"
|
||||
// row rather than dropped, so the per-site figures still add up to the summary
|
||||
// total. That row is not noise — it is every booking created without naming
|
||||
// its site, and it should shrink to zero as the console starts sending
|
||||
// pickuplocationid.
|
||||
// tenantlocationid.
|
||||
func locationBreakdown(tenantID, locationID int, from, to time.Time) []fiber.Map {
|
||||
// Only meaningful within one client. Across the whole network the rows
|
||||
// would be a mix of every tenant's sites, which is a screen nobody asked
|
||||
@@ -680,7 +680,7 @@ func locationBreakdown(tenantID, locationID int, from, to time.Time) []fiber.Map
|
||||
COALESCE(SUM(p.paid), 0) AS cod_collected
|
||||
FROM tenantlocations tl
|
||||
LEFT JOIN pickupbookings b
|
||||
ON b.pickuplocationid = tl.tenantlocationid
|
||||
ON b.tenantlocationid = tl.tenantlocationid
|
||||
AND b.createdat BETWEEN ? AND ?
|
||||
LEFT JOIN (
|
||||
SELECT bookingid, SUM(amount) AS paid
|
||||
@@ -723,7 +723,7 @@ func locationBreakdown(tenantID, locationID int, from, to time.Time) []fiber.Map
|
||||
if locationID == 0 {
|
||||
var unattributed int64
|
||||
db.DB.Model(&models.PickupBooking{}).
|
||||
Where("tenantid = ? AND pickuplocationid IS NULL AND createdat BETWEEN ? AND ?",
|
||||
Where("tenantid = ? AND tenantlocationid IS NULL AND createdat BETWEEN ? AND ?",
|
||||
tenantID, from, to).Count(&unattributed)
|
||||
if unattributed > 0 {
|
||||
out = append(out, fiber.Map{
|
||||
@@ -1977,10 +1977,16 @@ type AdminBookingRequest struct {
|
||||
Appcustomerid int `json:"appcustomerid"`
|
||||
CustomerPhone string `json:"customer_phone"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
// Pickuplocationid names the client site the parcel is collected from — a
|
||||
// Tenantlocationid names the client site the parcel is collected from — a
|
||||
// DailyGrubs kitchen, for instance. Optional, but supplying it lets the
|
||||
// address/pincode/coordinates be filled from the stored location instead of
|
||||
// retyped, and is the only thing that makes per-site reporting possible.
|
||||
// address/pincode/coordinates be filled from the stored site instead of
|
||||
// retyped, and is what per-site reporting groups by. When it is omitted the
|
||||
// site is inferred from the pickup coordinates or address.
|
||||
Tenantlocationid *int `json:"tenantlocationid"`
|
||||
// Pickuplocationid is accepted only as an alias for the field above, for
|
||||
// callers written against the earlier docs. It is never stored as-is: the
|
||||
// column of that name foreign-keys to appcustomerlocations, not to a
|
||||
// client's sites.
|
||||
Pickuplocationid *int `json:"pickuplocationid"`
|
||||
Pickupaddress string `json:"pickupaddress"`
|
||||
Pickuppincode string `json:"pickuppincode"`
|
||||
@@ -2027,18 +2033,30 @@ func createExpressBooking(req AdminBookingRequest) (*models.PickupBooking, error
|
||||
return nil, &expressBookingValidationError{"tenantid does not match a known tenant"}
|
||||
}
|
||||
|
||||
// A named pickup location fills in whatever the caller left blank, so the
|
||||
// console can send a kitchen id instead of restating its address every time.
|
||||
// It must belong to the booking's tenant — otherwise one client could book
|
||||
// against another client's site.
|
||||
if req.Pickuplocationid != nil {
|
||||
// A named pickup site fills in whatever the caller left blank, so the console
|
||||
// can send a kitchen id instead of restating its address every time. It must
|
||||
// belong to the booking's tenant — otherwise one client could book against
|
||||
// another client's site.
|
||||
//
|
||||
// `pickuplocationid` is accepted as an alias here purely for callers written
|
||||
// against the earlier documentation. It is the wrong column: it foreign-keys
|
||||
// to appcustomerlocations, so a tenantlocations id in it fails the insert.
|
||||
// Both names resolve to Tenantlocationid.
|
||||
siteID := req.Tenantlocationid
|
||||
if siteID == nil {
|
||||
siteID = req.Pickuplocationid
|
||||
}
|
||||
req.Pickuplocationid = nil
|
||||
|
||||
if siteID != nil {
|
||||
var loc models.TenantLocation
|
||||
if err := db.DB.Where("tenantlocationid = ?", *req.Pickuplocationid).First(&loc).Error; err != nil {
|
||||
return nil, &expressBookingValidationError{"pickuplocationid does not match a known location"}
|
||||
if err := db.DB.Where("tenantlocationid = ?", *siteID).First(&loc).Error; err != nil {
|
||||
return nil, &expressBookingValidationError{"tenantlocationid does not match a known location"}
|
||||
}
|
||||
if loc.Tenantid != req.Tenantid {
|
||||
return nil, &expressBookingValidationError{"pickuplocationid does not belong to this tenant"}
|
||||
return nil, &expressBookingValidationError{"tenantlocationid does not belong to this tenant"}
|
||||
}
|
||||
req.Tenantlocationid = siteID
|
||||
if req.Pickupaddress == "" {
|
||||
req.Pickupaddress = loc.Address
|
||||
}
|
||||
@@ -2060,10 +2078,8 @@ func createExpressBooking(req AdminBookingRequest) (*models.PickupBooking, error
|
||||
// pickup actually is. Without this the field stays null — as it did on every
|
||||
// booking in the system — and per-site reporting has nothing to group by,
|
||||
// because the console sends a kitchen's address rather than its id.
|
||||
if req.Pickuplocationid == nil {
|
||||
if matched := matchTenantLocation(req.Tenantid, req.Pickupaddress, req.Pickuplatitude, req.Pickuplongitude); matched != nil {
|
||||
req.Pickuplocationid = matched
|
||||
}
|
||||
if req.Tenantlocationid == nil {
|
||||
req.Tenantlocationid = matchTenantLocation(req.Tenantid, req.Pickupaddress, req.Pickuplatitude, req.Pickuplongitude)
|
||||
}
|
||||
|
||||
tx := db.DB.Begin()
|
||||
@@ -2099,6 +2115,7 @@ func createExpressBooking(req AdminBookingRequest) (*models.PickupBooking, error
|
||||
Tenantid: &tenantID,
|
||||
Appcustomerid: customerID,
|
||||
Pickuplocationid: req.Pickuplocationid,
|
||||
Tenantlocationid: req.Tenantlocationid,
|
||||
Pickupaddress: req.Pickupaddress,
|
||||
Pickuppincode: req.Pickuppincode,
|
||||
Pickuplatitude: req.Pickuplatitude,
|
||||
|
||||
@@ -804,6 +804,7 @@ func BookingPickupComplete(c *fiber.Ctx) error {
|
||||
Trackingno: trackingNo,
|
||||
Tenantid: consignmentTenantID,
|
||||
Pickuplocationid: booking.Pickuplocationid,
|
||||
Tenantlocationid: booking.Tenantlocationid,
|
||||
Pickuplatitude: booking.Pickuplatitude,
|
||||
Pickuplongitude: booking.Pickuplongitude,
|
||||
Deliverylatitude: booking.Deliverylatitude,
|
||||
|
||||
@@ -128,7 +128,7 @@ tenants at once aren't a meaningful report, so it 400s without one.
|
||||
|
||||
The same rows appear as `by_location` inside `GET /admin/reports`.
|
||||
|
||||
**Send `pickuplocationid` on bookings.** Attribution depends on it. The server
|
||||
**Send `tenantlocationid` on bookings.** Attribution depends on it. The server
|
||||
will try to recognise the site from the pickup coordinates (within 150m) or a
|
||||
matching address, but an explicit id is exact and always wins.
|
||||
|
||||
@@ -266,8 +266,8 @@ delivered, riderkms, ridercharges, dutyminutes }`.
|
||||
POST /admin/expressbooking
|
||||
{
|
||||
"tenantid": 13, // required; forced to your own tenant on client logins
|
||||
"pickuplocationid": 15, // a stored kitchen/branch — fills address, pincode and
|
||||
// coords for you, and is what makes per-site reporting work
|
||||
"tenantlocationid": 13, // a stored kitchen/branch — fills address, pincode and
|
||||
// coords for you, and is what per-site reporting groups by
|
||||
"customer_phone": "9876543210", // creates a Guest customer if unknown
|
||||
"customer_name": "Ramesh",
|
||||
"deliveryaddress": "12 Cross Cut Road, Gandhipuram",
|
||||
@@ -286,8 +286,12 @@ POST /admin/expressbooking
|
||||
|
||||
Rules worth knowing:
|
||||
- `parcels` must be non-empty and `tenantid` must exist.
|
||||
- Pickup address + pincode are required **unless** `pickuplocationid` supplies them.
|
||||
- A `pickuplocationid` belonging to another tenant is rejected.
|
||||
- Pickup address + pincode are required **unless** `tenantlocationid` supplies them.
|
||||
- A `tenantlocationid` belonging to another tenant is rejected.
|
||||
- `pickuplocationid` is accepted as an alias for `tenantlocationid`, for anything
|
||||
written against the earlier version of this doc. Prefer the new name: the
|
||||
database column called `pickuplocationid` means something else entirely (the
|
||||
B2C customer's saved address) and is not what per-site reporting uses.
|
||||
- **CityGate**: the pickup pincode prefix must be an open city — `641`
|
||||
Coimbatore, `600` Chennai, `560` Bengaluru, `500` Hyderabad, `629` Nagercoil.
|
||||
Any other prefix is refused at the middleware, before the handler runs.
|
||||
|
||||
@@ -98,13 +98,17 @@ Two jupiter bugs that do not carry over, by construction:
|
||||
`/admin/reports` now carries a `by_location` block alongside `by_hub`,
|
||||
`by_tenant` and `by_rider`.
|
||||
|
||||
**Attribution caveat.** Per-site figures depend on `pickuplocationid` being set
|
||||
on the booking. Every booking created before 2026-08-06 has it null, and the
|
||||
console sends a kitchen's *address*, not its id. So `createExpressBooking` now
|
||||
resolves the site itself — nearest stored location within 150m, falling back to
|
||||
an address match — and unattributed bookings are reported as their own
|
||||
`"Unattributed"` row rather than dropped, so the per-site rows still add up to
|
||||
the summary total. Sending `pickuplocationid` explicitly is still better and
|
||||
**Attribution caveat.** Per-site figures group by `tenantlocationid` on the
|
||||
booking — a column added 2026-08-06. The pre-existing `pickuplocationid` column
|
||||
is *not* it: that one foreign-keys to `appcustomerlocations`, the B2C customer's
|
||||
saved address, so writing a client-site id into it fails the insert. Every
|
||||
booking created before 2026-08-06 has no site at all.
|
||||
|
||||
Since the console sends a kitchen's *address* rather than its id,
|
||||
`createExpressBooking` resolves the site itself — nearest stored location within
|
||||
150m, falling back to an address match. Bookings with no site are reported as
|
||||
their own `"Unattributed"` row rather than dropped, so per-site rows still add
|
||||
up to the summary total. Sending `tenantlocationid` explicitly is exact and
|
||||
always wins.
|
||||
|
||||
**`applocationid` (city) is still not a report parameter.** jupiter had it;
|
||||
@@ -121,7 +125,7 @@ than one city.
|
||||
| ~ tenant create/edit | `POST /admin/tenants`, `PUT /admin/tenants/:id` | **Done** |
|
||||
| ~ location create/edit | `POST /admin/tenants/:id/locations`, `PUT /admin/tenantlocations/:id` | **Done** |
|
||||
| ~ `getbranches` | `GET /admin/hubs` — *jupiter "branches" ≈ Doormile hubs; verify this is the same concept before relying on it* | **Built** |
|
||||
| ~ `getlocationsummary` | **Gap** — no per-site rollup, same missing piece as `locationid` above | **Gap** |
|
||||
| ~ `getlocationsummary` | `GET /admin/locations/summary` — see §2.3 | **Done** |
|
||||
|
||||
Doormile adds `locationname` on a tenant location. jupiter identified a site by
|
||||
its address alone, which does not distinguish two branches on one street.
|
||||
|
||||
@@ -32,13 +32,17 @@ func (Pricing) TableName() string {
|
||||
}
|
||||
|
||||
type Consignment struct {
|
||||
Consignmentid int `json:"consignmentid" gorm:"primaryKey;column:consignmentid"`
|
||||
Trackingno string `json:"trackingno" gorm:"column:trackingno;unique;not null"`
|
||||
Orderheaderid *int `json:"orderheaderid" gorm:"column:orderheaderid"`
|
||||
Tenantid int `json:"tenantid" gorm:"column:tenantid"`
|
||||
Senderid *int `json:"senderid" gorm:"column:senderid"`
|
||||
Receiverid *int `json:"receiverid" gorm:"column:receiverid"`
|
||||
Consignmentid int `json:"consignmentid" gorm:"primaryKey;column:consignmentid"`
|
||||
Trackingno string `json:"trackingno" gorm:"column:trackingno;unique;not null"`
|
||||
Orderheaderid *int `json:"orderheaderid" gorm:"column:orderheaderid"`
|
||||
Tenantid int `json:"tenantid" gorm:"column:tenantid"`
|
||||
Senderid *int `json:"senderid" gorm:"column:senderid"`
|
||||
Receiverid *int `json:"receiverid" gorm:"column:receiverid"`
|
||||
// See PickupBooking: pickuplocationid is the customer's saved address,
|
||||
// tenantlocationid is the client's own site. Carried over at pickup so a
|
||||
// parcel stays traceable to the kitchen or branch it left.
|
||||
Pickuplocationid *int `json:"pickuplocationid" gorm:"column:pickuplocationid"`
|
||||
Tenantlocationid *int `json:"tenantlocationid" gorm:"column:tenantlocationid;index"`
|
||||
Deliverylocationid *int `json:"deliverylocationid" gorm:"column:deliverylocationid"`
|
||||
Originhubid *int `json:"originhubid" gorm:"column:originhubid"`
|
||||
Currenthubid *int `json:"currenthubid" gorm:"column:currenthubid"`
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
)
|
||||
|
||||
type PickupBooking struct {
|
||||
Bookingid int `json:"bookingid" gorm:"primaryKey;column:bookingid"`
|
||||
Bookingno string `json:"bookingno" gorm:"column:bookingno;unique;not null"`
|
||||
Bookingid int `json:"bookingid" gorm:"primaryKey;column:bookingid"`
|
||||
Bookingno string `json:"bookingno" gorm:"column:bookingno;unique;not null"`
|
||||
// Tenantid identifies which client company this booking is for. Nil for
|
||||
// direct B2C bookings (Bookingsource "Customer_App") that aren't attributed
|
||||
// to a tenant yet — see CreateCustomerBooking. Required for CRM bookings
|
||||
@@ -14,31 +14,39 @@ type PickupBooking struct {
|
||||
// a specific tenant. Propagated onto the resulting Consignment at pickup
|
||||
// time in BookingPickupComplete, instead of inferring it from whichever
|
||||
// miler happens to complete the pickup.
|
||||
Tenantid *int `json:"tenantid" gorm:"column:tenantid;index"`
|
||||
Appcustomerid int `json:"appcustomerid" gorm:"column:appcustomerid"`
|
||||
Pickuplocationid *int `json:"pickuplocationid" gorm:"column:pickuplocationid"`
|
||||
Pickupaddress string `json:"pickupaddress" gorm:"column:pickupaddress;not null"`
|
||||
Pickuppincode string `json:"pickuppincode" gorm:"column:pickuppincode;not null"`
|
||||
Pickuplatitude float64 `json:"pickuplatitude" gorm:"column:pickuplatitude;not null"`
|
||||
Pickuplongitude float64 `json:"pickuplongitude" gorm:"column:pickuplongitude;not null"`
|
||||
Deliveryaddress string `json:"deliveryaddress" gorm:"column:deliveryaddress;not null"`
|
||||
Deliverypincode string `json:"deliverypincode" gorm:"column:deliverypincode;not null"`
|
||||
Deliverylatitude float64 `json:"deliverylatitude" gorm:"column:deliverylatitude;not null"`
|
||||
Deliverylongitude float64 `json:"deliverylongitude" gorm:"column:deliverylongitude;not null"`
|
||||
Deliverycity string `json:"deliverycity" gorm:"column:deliverycity"`
|
||||
Nearesthubid *int `json:"nearesthubid" gorm:"column:nearesthubid"`
|
||||
Bookingsource string `json:"bookingsource" gorm:"column:bookingsource;default:Customer_App"`
|
||||
Providercompany string `json:"providercompany" gorm:"column:providercompany"`
|
||||
Providerlocation string `json:"providerlocation" gorm:"column:providerlocation"`
|
||||
Notes string `json:"notes" gorm:"column:notes"`
|
||||
Status string `json:"status" gorm:"column:status;default:Created"` // Created, Miler_Assigned, Pickup_Scheduled, Picked_Up, Converted_To_Consignment, Cancelled
|
||||
Preferredpickupfrom *time.Time `json:"preferredpickupfrom" gorm:"column:preferredpickupfrom"`
|
||||
Preferredpickupto *time.Time `json:"preferredpickupto" gorm:"column:preferredpickupto"`
|
||||
Assignedmileruserid *int `json:"assignedmileruserid" gorm:"column:assignedmileruserid"`
|
||||
Consignmentid *int `json:"consignmentid" gorm:"column:consignmentid"`
|
||||
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
||||
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
||||
|
||||
Tenantid *int `json:"tenantid" gorm:"column:tenantid;index"`
|
||||
Appcustomerid int `json:"appcustomerid" gorm:"column:appcustomerid"`
|
||||
// Pickuplocationid is the *customer's* saved address the parcel was collected
|
||||
// from — it carries a foreign key to appcustomerlocations. It is a B2C
|
||||
// concept and has nothing to do with the client company's own sites.
|
||||
Pickuplocationid *int `json:"pickuplocationid" gorm:"column:pickuplocationid"`
|
||||
// Tenantlocationid is the *client's* site: the kitchen, branch or depot the
|
||||
// parcel came out of. Separate column because pickuplocationid points at a
|
||||
// different table entirely; writing a tenantlocations id into it violates
|
||||
// that foreign key. This is what per-site reporting groups by.
|
||||
Tenantlocationid *int `json:"tenantlocationid" gorm:"column:tenantlocationid;index"`
|
||||
Pickupaddress string `json:"pickupaddress" gorm:"column:pickupaddress;not null"`
|
||||
Pickuppincode string `json:"pickuppincode" gorm:"column:pickuppincode;not null"`
|
||||
Pickuplatitude float64 `json:"pickuplatitude" gorm:"column:pickuplatitude;not null"`
|
||||
Pickuplongitude float64 `json:"pickuplongitude" gorm:"column:pickuplongitude;not null"`
|
||||
Deliveryaddress string `json:"deliveryaddress" gorm:"column:deliveryaddress;not null"`
|
||||
Deliverypincode string `json:"deliverypincode" gorm:"column:deliverypincode;not null"`
|
||||
Deliverylatitude float64 `json:"deliverylatitude" gorm:"column:deliverylatitude;not null"`
|
||||
Deliverylongitude float64 `json:"deliverylongitude" gorm:"column:deliverylongitude;not null"`
|
||||
Deliverycity string `json:"deliverycity" gorm:"column:deliverycity"`
|
||||
Nearesthubid *int `json:"nearesthubid" gorm:"column:nearesthubid"`
|
||||
Bookingsource string `json:"bookingsource" gorm:"column:bookingsource;default:Customer_App"`
|
||||
Providercompany string `json:"providercompany" gorm:"column:providercompany"`
|
||||
Providerlocation string `json:"providerlocation" gorm:"column:providerlocation"`
|
||||
Notes string `json:"notes" gorm:"column:notes"`
|
||||
Status string `json:"status" gorm:"column:status;default:Created"` // Created, Miler_Assigned, Pickup_Scheduled, Picked_Up, Converted_To_Consignment, Cancelled
|
||||
Preferredpickupfrom *time.Time `json:"preferredpickupfrom" gorm:"column:preferredpickupfrom"`
|
||||
Preferredpickupto *time.Time `json:"preferredpickupto" gorm:"column:preferredpickupto"`
|
||||
Assignedmileruserid *int `json:"assignedmileruserid" gorm:"column:assignedmileruserid"`
|
||||
Consignmentid *int `json:"consignmentid" gorm:"column:consignmentid"`
|
||||
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
||||
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
||||
|
||||
// Relations
|
||||
Parcels []BookingParcel `json:"parcels" gorm:"foreignKey:Bookingid"`
|
||||
ServiceOptions []BookingServiceOption `json:"serviceoptions" gorm:"foreignKey:Bookingid"`
|
||||
@@ -91,7 +99,7 @@ type BookingPayment struct {
|
||||
Bookingpaymentid int `json:"bookingpaymentid" gorm:"primaryKey;column:bookingpaymentid"`
|
||||
Bookingid int `json:"bookingid" gorm:"column:bookingid"`
|
||||
Amount float64 `json:"amount" gorm:"column:amount;not null"`
|
||||
Paymentmode string `json:"paymentmode" gorm:"column:paymentmode"` // Cash, UPI, Card, Wallet
|
||||
Paymentmode string `json:"paymentmode" gorm:"column:paymentmode"` // Cash, UPI, Card, Wallet
|
||||
Paymentstatus string `json:"paymentstatus" gorm:"column:paymentstatus;default:Pending"` // Pending, Paid, Failed, Refunded
|
||||
Collectedbyuserid *int `json:"collectedbyuserid" gorm:"column:collectedbyuserid"`
|
||||
Transactionref string `json:"transactionref" gorm:"column:transactionref"`
|
||||
@@ -129,8 +137,8 @@ type BookingVehicleRequirement struct {
|
||||
Requiredvehicletype string `json:"requiredvehicletype" gorm:"column:requiredvehicletype;not null"`
|
||||
Reason string `json:"reason" gorm:"column:reason"`
|
||||
Nearesthubid *int `json:"nearesthubid" gorm:"column:nearesthubid"`
|
||||
Scheduledpickupfrom *time.Time `json:"scheduledpickupfrom" gorm:"column:scheduledpickupfrom"`
|
||||
Scheduledpickupto *time.Time `json:"scheduledpickupto" gorm:"column:scheduledpickupto"`
|
||||
Scheduledpickupfrom *time.Time `json:"scheduledpickupfrom" gorm:"column:scheduledpickupfrom"`
|
||||
Scheduledpickupto *time.Time `json:"scheduledpickupto" gorm:"column:scheduledpickupto"`
|
||||
Assignedvehicleid *int `json:"assignedvehicleid" gorm:"column:assignedvehicleid"`
|
||||
Assigneddriveruserid *int `json:"assigneddriveruserid" gorm:"column:assigneddriveruserid"`
|
||||
Status string `json:"status" gorm:"column:status;default:Required"` // Required, Scheduled, Assigned, Arrived, Picked_Up, Cancelled
|
||||
|
||||
Reference in New Issue
Block a user