Files
meezi/src/Meezi.API/Services/Delivery/DeliveryStatusSyncService.cs
T

152 lines
4.8 KiB
C#
Raw Normal View History

2026-05-27 21:33:48 +03:30
using Meezi.API.Models.Orders;
using Meezi.Core.Entities;
using Meezi.Core.Enums;
using Meezi.Core.Interfaces;
using Meezi.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace Meezi.API.Services.Delivery;
public interface IDeliveryStatusSyncService
{
Task<bool> SyncInternalStatusAsync(
string cafeId,
string orderId,
OrderStatus newStatus,
CancellationToken ct = default);
Task<bool> ApplyPlatformStatusAsync(
DeliveryPlatform platform,
string externalOrderId,
string platformStatus,
CancellationToken ct = default);
}
public class DeliveryStatusSyncService : IDeliveryStatusSyncService
{
private readonly AppDbContext _db;
private readonly IKdsNotifier _kds;
private readonly ISnappfoodClient _snappfood;
private readonly ITap30Client _tap30;
private readonly IInventoryService _inventory;
private readonly ILogger<DeliveryStatusSyncService> _logger;
public DeliveryStatusSyncService(
AppDbContext db,
IKdsNotifier kds,
ISnappfoodClient snappfood,
ITap30Client tap30,
IInventoryService inventory,
ILogger<DeliveryStatusSyncService> logger)
{
_db = db;
_kds = kds;
_snappfood = snappfood;
_tap30 = tap30;
_inventory = inventory;
_logger = logger;
}
public async Task<bool> SyncInternalStatusAsync(
string cafeId,
string orderId,
OrderStatus newStatus,
CancellationToken ct = default)
{
var order = await _db.Orders
.FirstOrDefaultAsync(o => o.Id == orderId && o.CafeId == cafeId, ct);
if (order?.DeliveryPlatform is null || string.IsNullOrEmpty(order.ExternalOrderId))
return false;
var platformStatus = MapToPlatformStatus(newStatus);
await NotifyPlatformAsync(order.DeliveryPlatform.Value, order.ExternalOrderId, platformStatus, ct);
if (newStatus == OrderStatus.Delivered && !string.IsNullOrEmpty(order.SnappfoodOrderId))
await _snappfood.NotifyOrderDeliveredAsync(order.SnappfoodOrderId, ct);
return true;
}
public async Task<bool> ApplyPlatformStatusAsync(
DeliveryPlatform platform,
string externalOrderId,
string platformStatus,
CancellationToken ct = default)
{
var order = await _db.Orders
.Include(o => o.Items)
.ThenInclude(i => i.MenuItem)
.FirstOrDefaultAsync(
o => o.DeliveryPlatform == platform && o.ExternalOrderId == externalOrderId,
ct);
if (order is null)
return false;
var mapped = MapFromPlatformStatus(platformStatus);
if (order.Status == mapped)
return true;
if (mapped == OrderStatus.Cancelled)
await RollbackInventoryPlaceholderAsync(order, ct);
order.Status = mapped;
await _db.SaveChangesAsync(ct);
await _kds.NotifyOrderStatusChangedAsync(order.CafeId, order.Id, mapped, ct);
if (!string.IsNullOrEmpty(order.TableId))
await _kds.NotifyTableStatusChangedAsync(order.CafeId, ct);
return true;
}
private async Task NotifyPlatformAsync(
DeliveryPlatform platform,
string externalOrderId,
string status,
CancellationToken ct)
{
switch (platform)
{
case DeliveryPlatform.Snappfood:
await _snappfood.NotifyOrderStatusAsync(externalOrderId, status, ct);
break;
case DeliveryPlatform.Tap30:
await _tap30.NotifyOrderStatusAsync(externalOrderId, status, ct);
break;
}
}
private Task RollbackInventoryPlaceholderAsync(Order order, CancellationToken ct)
{
_logger.LogInformation(
"Delivery order {OrderId} cancelled — inventory rollback pending BOM linkage",
order.Id);
return Task.CompletedTask;
}
private static string MapToPlatformStatus(OrderStatus status) => status switch
{
OrderStatus.Pending => "pending",
OrderStatus.Confirmed => "confirmed",
OrderStatus.Preparing => "preparing",
OrderStatus.Ready => "ready",
OrderStatus.Delivered => "delivered",
OrderStatus.Cancelled => "cancelled",
_ => "confirmed"
};
private static OrderStatus MapFromPlatformStatus(string platformStatus) =>
platformStatus.Trim().ToLowerInvariant() switch
{
"pending" => OrderStatus.Pending,
"confirmed" => OrderStatus.Confirmed,
"preparing" or "in_progress" => OrderStatus.Preparing,
"ready" => OrderStatus.Ready,
"delivered" or "completed" => OrderStatus.Delivered,
"cancelled" or "canceled" => OrderStatus.Cancelled,
_ => OrderStatus.Confirmed
};
}