hss-pos / backend /internal /services /sync_enqueue.go
sashank1989
feat: hybrid cloud sync + fix table/KOT state after payment
46ae36f
Raw
History Blame Contribute Delete
5.52 kB
package services
import (
"encoding/json"
"time"
"restaurant-pos/internal/models"
"gorm.io/gorm"
)
// SyncEnqueuer provides simple helper methods to enqueue sync events from handlers.
// Handlers call these after successful operations.
// EnqueueOrderSync enqueues an order event with a lightweight summary payload.
func (s *SyncService) EnqueueOrderSync(order *models.Order, action string) {
if s == nil || s.Config.IsCloud() || s.Config.CloudURL == "" {
return
}
// Build lightweight payload (no full items — just summary)
items := []map[string]interface{}{}
for _, item := range order.Items {
items = append(items, map[string]interface{}{
"name": item.ProductName,
"qty": item.Quantity,
"total": item.TotalPrice,
})
}
itemsJSON, _ := json.Marshal(items)
// Get table name if linked
tableName := ""
if order.TableID != nil && *order.TableID != "" {
var table models.RestaurantTable
s.DB.Select("name").Where("id = ?", *order.TableID).First(&table)
tableName = table.Name
}
// Get staff name (captain)
staffName := ""
if order.CaptainID != nil && *order.CaptainID != "" {
var user models.User
s.DB.Select("full_name").Where("id = ?", *order.CaptainID).First(&user)
staffName = user.FullName
}
// Get payment method from first payment if available
paymentMethod := ""
if len(order.Payments) > 0 {
paymentMethod = string(order.Payments[0].Method)
}
payload := map[string]interface{}{
"order_number": order.OrderNumber,
"source": order.Source,
"status": order.Status,
"payment_status": order.PaymentStatus,
"sub_total": order.SubTotal,
"tax_amount": order.TaxAmount,
"discount_amount": order.DiscountAmount,
"grand_total": order.GrandTotal,
"payment_method": paymentMethod,
"item_count": len(order.Items),
"customer_name": order.CustomerName,
"customer_phone": order.CustomerPhone,
"table_name": tableName,
"staff_name": staffName,
"items_summary": string(itemsJSON),
"order_date": order.CreatedAt.Format(time.RFC3339),
}
s.EnqueueEvent("order", order.ID, action, payload)
}
// EnqueuePaymentSync enqueues a payment event.
func (s *SyncService) EnqueuePaymentSync(payment *models.Payment, action string) {
if s == nil || s.Config.IsCloud() || s.Config.CloudURL == "" {
return
}
payload := map[string]interface{}{
"order_id": payment.OrderID,
"method": payment.Method,
"amount": payment.Amount,
"reference": payment.Reference,
}
s.EnqueueEvent("payment", payment.ID, action, payload)
}
// EnqueueDailySummary generates and enqueues end-of-day summary.
func (s *SyncService) EnqueueDailySummary(db *gorm.DB, date string) {
if s == nil || s.Config.IsCloud() || s.Config.CloudURL == "" {
return
}
dateStart := date + " 00:00:00"
dateEnd := date + " 23:59:59"
var totalOrders int64
var totalRevenue, totalTax, totalDiscount float64
var cashRev, cardRev, upiRev float64
var cancelledOrders int64
var cancelledValue float64
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid'", dateStart, dateEnd).
Count(&totalOrders)
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid'", dateStart, dateEnd).
Select("COALESCE(SUM(grand_total), 0)").Row().Scan(&totalRevenue)
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid'", dateStart, dateEnd).
Select("COALESCE(SUM(tax_amount), 0)").Row().Scan(&totalTax)
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid'", dateStart, dateEnd).
Select("COALESCE(SUM(discount_amount), 0)").Row().Scan(&totalDiscount)
// Payment method breakdown
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid' AND payment_method = 'cash'", dateStart, dateEnd).
Select("COALESCE(SUM(grand_total), 0)").Row().Scan(&cashRev)
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid' AND payment_method = 'card'", dateStart, dateEnd).
Select("COALESCE(SUM(grand_total), 0)").Row().Scan(&cardRev)
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND payment_status = 'paid' AND payment_method = 'upi'", dateStart, dateEnd).
Select("COALESCE(SUM(grand_total), 0)").Row().Scan(&upiRev)
// Cancelled
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND status = 'cancelled'", dateStart, dateEnd).
Count(&cancelledOrders)
db.Model(&models.Order{}).
Where("created_at BETWEEN ? AND ? AND status = 'cancelled'", dateStart, dateEnd).
Select("COALESCE(SUM(grand_total), 0)").Row().Scan(&cancelledValue)
// Expenses
var expenseTotal float64
db.Model(&models.Expense{}).
Where("date = ?", date).
Select("COALESCE(SUM(amount), 0)").Row().Scan(&expenseTotal)
avgOrder := float64(0)
if totalOrders > 0 {
avgOrder = totalRevenue / float64(totalOrders)
}
summary := map[string]interface{}{
"date": date,
"total_orders": totalOrders,
"total_revenue": totalRevenue,
"total_tax": totalTax,
"total_discount": totalDiscount,
"cash_revenue": cashRev,
"card_revenue": cardRev,
"upi_revenue": upiRev,
"other_revenue": totalRevenue - cashRev - cardRev - upiRev,
"avg_order_value": avgOrder,
"cancelled_orders": cancelledOrders,
"cancelled_value": cancelledValue,
"expense_total": expenseTotal,
}
s.EnqueueEvent("daily_summary", date, "update", summary)
}