feat: hub console backend — complete API surface

This commit is contained in:
2026-07-04 16:14:12 +05:30
parent c8adaf7815
commit 707323b68c
10 changed files with 1302 additions and 42 deletions

View File

@@ -0,0 +1,84 @@
package controllers
import (
"encoding/json"
"fmt"
"time"
"doormile/constants"
"doormile/db"
"doormile/internal/notify"
"doormile/models"
"doormile/utils"
)
// AssignMilerToBooking is the single source of truth for manually assigning a
// miler to a pickup booking — shared by the admin console (AdminAssignMiler)
// and the hub console (HubAssignMiler) so both go through identical DB
// updates, NATS publish, and FCM notify instead of duplicating the logic.
func AssignMilerToBooking(bookingID, milerUserID int, assignedByUserID *int) (*models.PickupBooking, error) {
tx := db.DB.Begin()
var booking models.PickupBooking
if err := tx.First(&booking, bookingID).Error; err != nil {
tx.Rollback()
return nil, fmt.Errorf("booking not found")
}
booking.Status = constants.BookingMilerAssigned
booking.Assignedmileruserid = &milerUserID
booking.Updatedat = time.Now()
if err := tx.Save(&booking).Error; err != nil {
tx.Rollback()
return nil, fmt.Errorf("failed to update booking: %w", err)
}
assignment := models.BookingAssignment{
Bookingid: booking.Bookingid,
Mileruserid: milerUserID,
Assignedbyuserid: assignedByUserID,
Assignmentstatus: constants.AssignmentAssigned,
}
if err := tx.Create(&assignment).Error; err != nil {
tx.Rollback()
return nil, fmt.Errorf("failed to create assignment: %w", err)
}
if err := tx.Model(&models.MilerProfile{}).Where("userid = ?", milerUserID).
Update("availabilitystatus", constants.MilerAssigned).Error; err != nil {
tx.Rollback()
return nil, fmt.Errorf("failed to update miler availability: %w", err)
}
tx.Commit()
if db.Js != nil {
payload := map[string]interface{}{
"booking_id": booking.Bookingid,
"booking_no": booking.Bookingno,
"status": booking.Status,
"miler_id": milerUserID,
"updated_at": time.Now().UnixMilli(),
}
if data, err := json.Marshal(payload); err == nil {
if _, err := db.Js.Publish("api.v1.bookings.update", data); err != nil {
utils.Warn("Failed to publish booking.update to NATS", "booking_id", booking.Bookingid, "error", err)
}
}
}
var miler models.MilerProfile
if db.DB.Where("userid = ?", milerUserID).First(&miler).Error == nil && miler.Devicetoken != "" {
if err := notify.SendToDevice(
miler.Devicetoken,
"New Pickup Assigned",
"New booking assigned — tap to view details",
map[string]string{"booking_id": fmt.Sprintf("%d", booking.Bookingid)},
); err != nil {
utils.Warn("FCM: failed to notify miler on manual assignment",
"miler_id", milerUserID, "booking_id", booking.Bookingid, "error", err)
}
}
return &booking, nil
}