using Fake.DependencyInjection; using Oms.Domain.ChannelsAggregate.Consts; using Oms.Domain.ChannelsAggregate.Entities; using Oms.Domain.ChannelsAggregate.Repositories; using Oms.Domain.OrdersAggregate.Consts; using Oms.Domain.OrdersAggregate.Entities; using Oms.Domain.OrdersAggregate.Repositories; using Oms.Domain.Shared.Enums; namespace Oms.Application.Services.Orders.Issues; public sealed class ProblematicMarkRequest { public string IssueType { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; public string Content { get; set; } = string.Empty; public int? IssueTemplateId { get; set; } public string? NotifyMethod { get; set; } public string? Remark { get; set; } public IEnumerable? ExtraReceiverUserIds { get; set; } } public class OrderExceptionWorkflowService( IOrderRepository orderRepository, IOrderExceptionEventRepository orderExceptionEventRepository, IIssueTemplateRepository issueTemplateRepository, OrderIssueNotificationService issueNotificationService) : IScopedDependency { public async Task TryMarkProblematicAsync( Order order, ProblematicMarkRequest request, int operatorUserId, bool sendNotification) { if (!OrderExceptionStatusRules.CanMarkException(order.OrderStatus)) { return OrderExceptionStatusRules.GetForbiddenReason(order.OrderStatus); } var context = IssuePlaceholderContext.FromOrder(order, request.IssueType, request.Title); var renderedTitle = IssuePlaceholderRenderer.Render(request.Title, context); var renderedContent = IssuePlaceholderRenderer.Render(request.Content, context); var fromStatus = order.OrderStatus; order.PreviousOrderStatus = fromStatus; order.OrderStatus = OrderStatusCodes.Problematic; order.HandleStatus = OrderHandleStatusCodes.Pending; order.IssueType = request.IssueType; order.IssueTitle = renderedTitle; order.IssueContent = renderedContent; order.IssueTemplateId = request.IssueTemplateId; order.IssueRemark = request.Remark; order.IssueTime = DateTime.Now; order.ClaimType = null; order.ClaimAmount = null; order.ClaimCurrency = null; order.ClaimReason = null; order.ClaimTime = null; await orderRepository.UpdateAsync(order); await orderExceptionEventRepository.InsertAsync(new OrderExceptionEvent { OrderId = order.Id, EventType = OrderExceptionEventTypeCodes.MarkProblematic, FromStatus = fromStatus, ToStatus = OrderStatusCodes.Problematic, FromHandleStatus = null, ToHandleStatus = OrderHandleStatusCodes.Pending, IssueType = request.IssueType, Title = renderedTitle, Content = renderedContent, IssueTemplateId = request.IssueTemplateId, NotifyMethod = request.NotifyMethod, Remark = request.Remark }); if (sendNotification) { await issueNotificationService.DispatchAsync( order, renderedTitle, renderedContent, request.NotifyMethod, operatorUserId, request.ExtraReceiverUserIds); } return null; } public async Task BuildRequestFromTemplateAsync( string? organizationId, string issueType, string? titleOverride, string? contentOverride, string? remark) { var normalizedType = issueType.Trim().ToLowerInvariant(); if (!IssueTypeCodes.All.Contains(normalizedType)) { normalizedType = IssueTypeCodes.Other; } var normalizedOrg = NormalizeOrganizationId(organizationId); var hasOrgFilter = normalizedOrg != null; var orgValue = normalizedOrg ?? string.Empty; var templates = await issueTemplateRepository.GetListAsync(x => x.Status == EnableStatus.Enabled && x.IssueType == normalizedType && (!hasOrgFilter || x.OrganizationId == orgValue || x.OrganizationId == null || x.OrganizationId == string.Empty)); var template = templates.FirstOrDefault(x => x.OrganizationId == normalizedOrg) ?? templates.FirstOrDefault(x => string.IsNullOrWhiteSpace(x.OrganizationId)) ?? templates.FirstOrDefault(); var title = !string.IsNullOrWhiteSpace(titleOverride) ? titleOverride.Trim() : template?.Title?.Trim(); var content = !string.IsNullOrWhiteSpace(contentOverride) ? contentOverride.Trim() : template?.Content?.Trim(); if (string.IsNullOrWhiteSpace(title) || string.IsNullOrWhiteSpace(content)) { return null; } return new ProblematicMarkRequest { IssueType = normalizedType, Title = title, Content = content, IssueTemplateId = template?.Id, NotifyMethod = template == null ? null : IssueNotifyMethodCodes.Normalize(template.NotifyMethod), Remark = remark }; } private static string? NormalizeOrganizationId(string? organizationId) { var text = organizationId?.Trim(); return string.IsNullOrWhiteSpace(text) ? null : text; } }