Files
doormile_backend/models/audit.go
Suriya 90fa4fbb74 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>
2026-08-06 13:08:57 +05:30

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"
}