新增 mark-problematic/mark-claimed/handle-status 接口,异常事件审计表与占位符渲染;inApp/email 通知及下单/入库/出库自动触发运行时。 Co-authored-by: Cursor <cursoragent@cursor.com>
191 lines
6.0 KiB
C#
191 lines
6.0 KiB
C#
using System.Text.Json;
|
||
using System.Text.Json.Nodes;
|
||
using System.Text.Json.Serialization;
|
||
using Oms.Application.Dtos.Orders;
|
||
using Oms.Domain.OrdersAggregate.Consts;
|
||
using Oms.Domain.SystemAggregate.Consts;
|
||
|
||
namespace Oms.Application.Shared;
|
||
|
||
/// <summary>
|
||
/// OMS 通用文档与展示辅助方法。
|
||
/// </summary>
|
||
public static class OmsDocHelper
|
||
{
|
||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||
{
|
||
PropertyNameCaseInsensitive = true
|
||
};
|
||
|
||
private static readonly JsonSerializerOptions SnapshotJsonOptions = new()
|
||
{
|
||
PropertyNameCaseInsensitive = true,
|
||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||
};
|
||
|
||
/// <summary>
|
||
/// 将页码规范为至少 1。
|
||
/// </summary>
|
||
public static int NormalizePage(int page) => page <= 0 ? 1 : page;
|
||
|
||
/// <summary>
|
||
/// 将每页条数规范为 1~200。
|
||
/// </summary>
|
||
public static int NormalizePageSize(int pageSize) => pageSize <= 0 ? 20 : Math.Min(pageSize, 200);
|
||
|
||
/// <summary>
|
||
/// 将默认 DateTime 转为 null。
|
||
/// </summary>
|
||
public static DateTime? NullIfDefault(DateTime value) => value == default ? null : value;
|
||
|
||
/// <summary>
|
||
/// 将库内 JSON 字符串转为 API 可输出的 CLR 对象(避免 JsonElement 被 Newtonsoft 序列化成 valueKind)。
|
||
/// </summary>
|
||
public static object? DeserializeJsonObject(string? json)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(json))
|
||
{
|
||
return null;
|
||
}
|
||
|
||
using var document = JsonDocument.Parse(json);
|
||
return ConvertJsonElement(document.RootElement);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 反序列化 JSON 字符串为指定类型。
|
||
/// </summary>
|
||
public static T? DeserializeJson<T>(string? json)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(json))
|
||
{
|
||
return default;
|
||
}
|
||
|
||
return JsonSerializer.Deserialize<T>(json, JsonOptions);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将请求体中的动态 JSON(JsonElement / JToken / Dictionary 等)规范为可落库的 JSON 字符串。
|
||
/// </summary>
|
||
public static string? SerializeJson<T>(T? value)
|
||
{
|
||
if (value is null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
if (value is JsonElement element)
|
||
{
|
||
return element.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined
|
||
? null
|
||
: element.GetRawText();
|
||
}
|
||
|
||
if (value is JsonNode node)
|
||
{
|
||
return node.ToJsonString();
|
||
}
|
||
|
||
if (value is string text)
|
||
{
|
||
return string.IsNullOrWhiteSpace(text) ? null : text;
|
||
}
|
||
|
||
var typeName = value.GetType().FullName;
|
||
if (typeName is not null && typeName.StartsWith("Newtonsoft.Json.Linq.", StringComparison.Ordinal))
|
||
{
|
||
return value.ToString();
|
||
}
|
||
|
||
return JsonSerializer.Serialize(value, JsonOptions);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 序列化发布快照(忽略 null,避免写出旧兼容字段)。
|
||
/// </summary>
|
||
public static string? SerializeSnapshotJson<T>(T? value)
|
||
{
|
||
if (value is null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return JsonSerializer.Serialize(value, SnapshotJsonOptions);
|
||
}
|
||
|
||
public static SalesProductRulesPublishSnapshotDto? DeserializeRulesSnapshot(string? json)
|
||
{
|
||
var snapshot = DeserializeJson<SalesProductRulesPublishSnapshotDto>(json);
|
||
PublishSnapshotNormalizer.NormalizeRulesSnapshot(snapshot);
|
||
return snapshot;
|
||
}
|
||
|
||
public static SalesProductPricePublishSnapshotDto? DeserializePriceSnapshot(string? json)
|
||
{
|
||
var snapshot = DeserializeJson<SalesProductPricePublishSnapshotDto>(json);
|
||
PublishSnapshotNormalizer.NormalizePriceSnapshot(snapshot);
|
||
return snapshot;
|
||
}
|
||
|
||
private static object? ConvertJsonElement(JsonElement element) => element.ValueKind switch
|
||
{
|
||
JsonValueKind.Object => element.EnumerateObject()
|
||
.ToDictionary(property => property.Name, property => ConvertJsonElement(property.Value)),
|
||
JsonValueKind.Array => element.EnumerateArray()
|
||
.Select(ConvertJsonElement)
|
||
.ToList(),
|
||
JsonValueKind.String => element.GetString(),
|
||
JsonValueKind.Number => element.TryGetInt64(out var integer)
|
||
? integer
|
||
: element.GetDecimal(),
|
||
JsonValueKind.True => true,
|
||
JsonValueKind.False => false,
|
||
JsonValueKind.Null or JsonValueKind.Undefined => null,
|
||
_ => element.GetRawText()
|
||
};
|
||
|
||
/// <summary>
|
||
/// 反序列化 JSON 字符串数组。
|
||
/// </summary>
|
||
public static List<string> DeserializeStringList(string? json) => JsonStringArrayHelper.Deserialize(json);
|
||
|
||
/// <summary>
|
||
/// 将订单状态码转为中文名称。
|
||
/// </summary>
|
||
public static string? GetOrderStatusName(string statusCode)
|
||
{
|
||
return statusCode switch
|
||
{
|
||
OrderStatusCodes.Draft => "草稿",
|
||
OrderStatusCodes.Predeclared => "已预报",
|
||
OrderStatusCodes.Received => "已收货",
|
||
OrderStatusCodes.PendingPayment => "待支付",
|
||
OrderStatusCodes.PendingShip => "待发货",
|
||
OrderStatusCodes.PendingOnline => "待上网",
|
||
OrderStatusCodes.Shipping => "运输中",
|
||
OrderStatusCodes.DeliverySuccess => "派送成功",
|
||
OrderStatusCodes.DeliveryFailed => "派送失败",
|
||
OrderStatusCodes.Problematic => "问题件",
|
||
OrderStatusCodes.Deleted => "已删除",
|
||
OrderStatusCodes.Claimed => "理赔件",
|
||
_ => statusCode
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将仓库类型码转为中文名称。
|
||
/// </summary>
|
||
public static string GetWarehouseTypeName(string warehouseType)
|
||
{
|
||
return warehouseType switch
|
||
{
|
||
WarehouseTypeCodes.Main => "主仓",
|
||
WarehouseTypeCodes.Transit => "中转仓",
|
||
WarehouseTypeCodes.Return => "退货仓",
|
||
WarehouseTypeCodes.Other => "其他",
|
||
_ => warehouseType
|
||
};
|
||
}
|
||
}
|