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>
161 lines
10 KiB
Go
161 lines
10 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
type Pricing struct {
|
|
Pricingid int `json:"pricingid" gorm:"primaryKey;column:pricingid"`
|
|
Tenantid int `json:"tenantid" gorm:"column:tenantid"`
|
|
Applocationid int `json:"applocationid" gorm:"column:applocationid"`
|
|
Vehicletype string `json:"vehicletype" gorm:"column:vehicletype"`
|
|
Baseprice float64 `json:"baseprice" gorm:"column:baseprice;not null"`
|
|
Baseweight float64 `json:"baseweight" gorm:"column:baseweight;not null"`
|
|
Priceperkg float64 `json:"priceperkg" gorm:"column:priceperkg;not null"`
|
|
Basedistance float64 `json:"basedistance" gorm:"column:basedistance;not null"`
|
|
Priceperkm float64 `json:"priceperkm" gorm:"column:priceperkm;not null"`
|
|
Handlingcharges float64 `json:"handlingcharges" gorm:"column:handlingcharges;default:0.00"`
|
|
Effectivefrom time.Time `json:"effectivefrom" gorm:"column:effectivefrom;not null"`
|
|
Effectiveto time.Time `json:"effectiveto" gorm:"column:effectiveto;not null"`
|
|
Currency string `json:"currency" gorm:"column:currency;default:INR"`
|
|
Priority int `json:"priority" gorm:"column:priority;default:0"`
|
|
Status string `json:"status" gorm:"column:status;default:Active"` // Active, InActive
|
|
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
|
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
|
Createdby int `json:"createdby" gorm:"column:createdby"`
|
|
Updatedby int `json:"updatedby" gorm:"column:updatedby"`
|
|
Deletedat *time.Time `json:"deletedat,omitempty" gorm:"column:deletedat"`
|
|
}
|
|
|
|
func (Pricing) TableName() string {
|
|
return "pricing"
|
|
}
|
|
|
|
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"`
|
|
// 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"`
|
|
Destinationhubid *int `json:"destinationhubid" gorm:"column:destinationhubid"`
|
|
Pickuppincode string `json:"pickuppincode" gorm:"column:pickuppincode"`
|
|
Deliverypincode string `json:"deliverypincode" gorm:"column:deliverypincode"`
|
|
Pickuplatitude float64 `json:"pickuplatitude" gorm:"column:pickuplatitude"`
|
|
Pickuplongitude float64 `json:"pickuplongitude" gorm:"column:pickuplongitude"`
|
|
Deliverylatitude float64 `json:"deliverylatitude" gorm:"column:deliverylatitude"`
|
|
Deliverylongitude float64 `json:"deliverylongitude" gorm:"column:deliverylongitude"`
|
|
Length float64 `json:"length" gorm:"column:length"`
|
|
Width float64 `json:"width" gorm:"column:width"`
|
|
Height float64 `json:"height" gorm:"column:height"`
|
|
Deadweight float64 `json:"deadweight" gorm:"column:deadweight;not null"`
|
|
Volumetricweight float64 `json:"volumetricweight" gorm:"column:volumetricweight"`
|
|
Chargeableweight float64 `json:"chargeableweight" gorm:"column:chargeableweight;not null"`
|
|
Codamount float64 `json:"codamount" gorm:"column:codamount;default:0.00"`
|
|
Codcollected float64 `json:"codcollected" gorm:"column:codcollected;default:0.00"`
|
|
Paymentmode string `json:"paymentmode" gorm:"column:paymentmode"` // Prepaid, COD, To_Pay
|
|
Billingstatus string `json:"billingstatus" gorm:"column:billingstatus;default:Unbilled"` // Unbilled, Billed, Paid, Settled
|
|
Status string `json:"status" gorm:"column:status;default:Created"` // Created, Inwarded_at_Hub, Tripsheet_Loaded, In_Transit, Out_for_Delivery, Delivered, RTO_Initiated, Returned_to_Sender, Missing, Damaged
|
|
Attemptcount int `json:"attemptcount" gorm:"column:attemptcount;default:0"`
|
|
Estimateddeliveryat *time.Time `json:"estimateddeliveryat" gorm:"column:estimateddeliveryat"`
|
|
Sladueat *time.Time `json:"sladueat" gorm:"column:sladueat"`
|
|
Returnreason string `json:"returnreason" gorm:"column:returnreason"`
|
|
Returninitiatedat *time.Time `json:"returninitiatedat" gorm:"column:returninitiatedat"`
|
|
Returndeliveredat *time.Time `json:"returndeliveredat" gorm:"column:returndeliveredat"`
|
|
Parentconsignmentid *int `json:"parentconsignmentid" gorm:"column:parentconsignmentid"`
|
|
Condition string `json:"condition" gorm:"column:condition;size:50"` // recorded at hub inbound scan: Good, Damaged, etc.
|
|
Shelf string `json:"shelf" gorm:"column:shelf;size:50"` // hub storage location assigned at inbound scan
|
|
// Deliveryotp is issued when the consignment goes out for delivery and is
|
|
// given to the receiver, not the rider — it is the only proof the parcel
|
|
// reached the right person. Never serialised outward: returning it in an API
|
|
// response would hand the rider the code they are supposed to be told.
|
|
Deliveryotp string `json:"-" gorm:"column:deliveryotp;size:6"`
|
|
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
|
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
|
Createdby int `json:"createdby" gorm:"column:createdby"`
|
|
Updatedby int `json:"updatedby" gorm:"column:updatedby"`
|
|
Deletedat *time.Time `json:"deletedat,omitempty" gorm:"column:deletedat"`
|
|
}
|
|
|
|
func (Consignment) TableName() string {
|
|
return "consignments"
|
|
}
|
|
|
|
type ConsignmentHistory struct {
|
|
Historyid int `json:"historyid" gorm:"primaryKey;column:historyid"`
|
|
Consignmentid int `json:"consignmentid" gorm:"column:consignmentid"`
|
|
Tripsheetid *int `json:"tripsheetid" gorm:"column:tripsheetid"`
|
|
Hubid *int `json:"hubid" gorm:"column:hubid"`
|
|
Userid *int `json:"userid" gorm:"column:userid"`
|
|
Eventstatus string `json:"eventstatus" gorm:"column:eventstatus;not null"`
|
|
Remarks string `json:"remarks" gorm:"column:remarks"`
|
|
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
|
}
|
|
|
|
func (ConsignmentHistory) TableName() string {
|
|
return "consignmenthistory"
|
|
}
|
|
|
|
type ConsignmentException struct {
|
|
Exceptionid int `json:"exceptionid" gorm:"primaryKey;column:exceptionid"`
|
|
Consignmentid int `json:"consignmentid" gorm:"column:consignmentid"`
|
|
Tripsheetid *int `json:"tripsheetid" gorm:"column:tripsheetid"`
|
|
Hubid *int `json:"hubid" gorm:"column:hubid"`
|
|
Reportedbyuserid *int `json:"reportedbyuserid" gorm:"column:reportedbyuserid"`
|
|
Exceptiontype string `json:"exceptiontype" gorm:"column:exceptiontype;not null"` // Lost, Damaged, Misrouted, Receiver_Refused, Missing_Contents, Undeliverable
|
|
Severity string `json:"severity" gorm:"column:severity;default:Medium"` // Low, Medium, High, Critical
|
|
Description string `json:"description" gorm:"column:description"`
|
|
Resolution string `json:"resolution" gorm:"column:resolution"`
|
|
Status string `json:"status" gorm:"column:status;default:Open"` // Open, Under_Investigation, Resolved, Closed
|
|
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
|
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
|
Createdby int `json:"createdby" gorm:"column:createdby"`
|
|
Updatedby int `json:"updatedby" gorm:"column:updatedby"`
|
|
Deletedat *time.Time `json:"deletedat,omitempty" gorm:"column:deletedat"`
|
|
}
|
|
|
|
func (ConsignmentException) TableName() string {
|
|
return "consignmentexceptions"
|
|
}
|
|
|
|
// HubConversation is a hub-scoped chat channel between hub staff and a miler
|
|
// at that hub. One conversation per (hubid, mileruserid) pair.
|
|
type HubConversation struct {
|
|
Hubconversationid int `json:"hubconversationid" gorm:"primaryKey;column:hubconversationid"`
|
|
Hubid int `json:"hubid" gorm:"column:hubid;index;not null"`
|
|
Mileruserid *int `json:"mileruserid" gorm:"column:mileruserid;index"`
|
|
Participantname string `json:"participantname" gorm:"column:participantname;not null"`
|
|
Participantrole string `json:"participantrole" gorm:"column:participantrole"`
|
|
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
|
Updatedat time.Time `json:"updatedat" gorm:"column:updatedat;default:CURRENT_TIMESTAMP"`
|
|
}
|
|
|
|
func (HubConversation) TableName() string {
|
|
return "hubconversations"
|
|
}
|
|
|
|
// HubMessage is one message within a HubConversation. Sender is "me" (the
|
|
// requesting hub staff) or "them" (the other party), matching the hub
|
|
// console frontend's bubble-side convention.
|
|
type HubMessage struct {
|
|
Hubmessageid int `json:"hubmessageid" gorm:"primaryKey;column:hubmessageid"`
|
|
Hubconversationid int `json:"hubconversationid" gorm:"column:hubconversationid;index;not null"`
|
|
Sender string `json:"sender" gorm:"column:sender;not null"` // me, them
|
|
Senderstaffid *int `json:"senderstaffid" gorm:"column:senderstaffid"`
|
|
Messagetext string `json:"messagetext" gorm:"column:messagetext;not null"`
|
|
Isread bool `json:"isread" gorm:"column:isread;default:false"`
|
|
Createdat time.Time `json:"createdat" gorm:"column:createdat;default:CURRENT_TIMESTAMP"`
|
|
}
|
|
|
|
func (HubMessage) TableName() string {
|
|
return "hubmessages"
|
|
}
|