20260627
This commit is contained in:
parent
d766343ffe
commit
fdbdfa8124
@ -12,6 +12,7 @@ CREATE TABLE IF NOT EXISTS `t_customer_account_flow` (
|
|||||||
`Currency` varchar(8) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
`Currency` varchar(8) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||||
`Remark` varchar(512) DEFAULT NULL COMMENT '备注',
|
`Remark` varchar(512) DEFAULT NULL COMMENT '备注',
|
||||||
`IsDeleted` tinyint(1) NOT NULL DEFAULT '0',
|
`IsDeleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`ConcurrencyStamp` char(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
|
||||||
`CreateUserId` int NOT NULL DEFAULT '0',
|
`CreateUserId` int NOT NULL DEFAULT '0',
|
||||||
`CreateTime` datetime NOT NULL,
|
`CreateTime` datetime NOT NULL,
|
||||||
`UpdateUserId` int DEFAULT NULL,
|
`UpdateUserId` int DEFAULT NULL,
|
||||||
|
|||||||
8
sql/migrate_t_customer_account_flow_concurrency.sql
Normal file
8
sql/migrate_t_customer_account_flow_concurrency.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- 已执行旧版 migrate_t_customer_account_flow.sql 的库补 ConcurrencyStamp(与 AggregateRoot 实体对齐)
|
||||||
|
-- 勿在 ALTER 中使用 DEFAULT(UUID()),复制环境会报 Error 1674
|
||||||
|
ALTER TABLE `t_customer_account_flow`
|
||||||
|
ADD COLUMN `ConcurrencyStamp` char(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
|
||||||
|
|
||||||
|
UPDATE `t_customer_account_flow`
|
||||||
|
SET `ConcurrencyStamp` = UUID()
|
||||||
|
WHERE `ConcurrencyStamp` = '';
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
namespace Oms.Application.Dtos.Operations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 出库扫描按单号查订单(只读展示销售产品、目的国、服务渠道)。
|
||||||
|
/// </summary>
|
||||||
|
public class OutboundOrderLookupOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 订单主键。
|
||||||
|
/// </summary>
|
||||||
|
public int OrderId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务单号。
|
||||||
|
/// </summary>
|
||||||
|
public string ServiceNo { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户单号。
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientNo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 跟踪号。
|
||||||
|
/// </summary>
|
||||||
|
public string? TrackNo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 产品编码。
|
||||||
|
/// </summary>
|
||||||
|
public string? ProductCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 销售产品主键。
|
||||||
|
/// </summary>
|
||||||
|
public int? SalesProductId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 销售产品名称。
|
||||||
|
/// </summary>
|
||||||
|
public string? SalesProductName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目的国家编码。
|
||||||
|
/// </summary>
|
||||||
|
public string? DestinationCountry { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目的国家名称。
|
||||||
|
/// </summary>
|
||||||
|
public string? DestinationCountryName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务渠道主键。
|
||||||
|
/// </summary>
|
||||||
|
public int? ServiceChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务渠道编码。
|
||||||
|
/// </summary>
|
||||||
|
public string? ChannelCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务渠道展示名。
|
||||||
|
/// </summary>
|
||||||
|
public string? ServiceChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单状态码。
|
||||||
|
/// </summary>
|
||||||
|
public string OrderStatus { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单状态名称。
|
||||||
|
/// </summary>
|
||||||
|
public string? OrderStatusName { get; set; }
|
||||||
|
}
|
||||||
@ -2,8 +2,12 @@ using Fake.Application;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Oms.Application.Dtos.Operations;
|
using Oms.Application.Dtos.Operations;
|
||||||
using Oms.Application.Dtos.Shared;
|
using Oms.Application.Dtos.Shared;
|
||||||
|
using Oms.Application.Shared;
|
||||||
|
using Oms.Domain.ChannelsAggregate.Repositories;
|
||||||
using Oms.Domain.OperationsAggregate.Entities;
|
using Oms.Domain.OperationsAggregate.Entities;
|
||||||
using Oms.Domain.OperationsAggregate.Repositories;
|
using Oms.Domain.OperationsAggregate.Repositories;
|
||||||
|
using Oms.Domain.OrdersAggregate.Consts;
|
||||||
|
using Oms.Domain.OrdersAggregate.Repositories;
|
||||||
using Oms.Domain.SystemAggregate.Repositories;
|
using Oms.Domain.SystemAggregate.Repositories;
|
||||||
|
|
||||||
namespace Oms.Application.Services.Operations;
|
namespace Oms.Application.Services.Operations;
|
||||||
@ -15,7 +19,73 @@ namespace Oms.Application.Services.Operations;
|
|||||||
public class OutboundRecordService : ApplicationService
|
public class OutboundRecordService : ApplicationService
|
||||||
{
|
{
|
||||||
private IOutboundRecordRepository OutboundRecordRepository => LazyServiceProvider.GetRequiredService<IOutboundRecordRepository>();
|
private IOutboundRecordRepository OutboundRecordRepository => LazyServiceProvider.GetRequiredService<IOutboundRecordRepository>();
|
||||||
|
private IOrderRepository OrderRepository => LazyServiceProvider.GetRequiredService<IOrderRepository>();
|
||||||
|
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService<ISalesProductRepository>();
|
||||||
|
private IServiceChannelRepository ServiceChannelRepository => LazyServiceProvider.GetRequiredService<IServiceChannelRepository>();
|
||||||
|
private IServiceChannelGroupRepository ServiceChannelGroupRepository => LazyServiceProvider.GetRequiredService<IServiceChannelGroupRepository>();
|
||||||
private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService<IWarehouseAddressRepository>();
|
private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService<IWarehouseAddressRepository>();
|
||||||
|
private ICountryRepository CountryRepository => LazyServiceProvider.GetRequiredService<ICountryRepository>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按单号查询订单(出库扫描展示销售产品、目的国、服务渠道,只读)。
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("/operation/outbound/order-lookup")]
|
||||||
|
public async Task<OutboundOrderLookupOutput> LookupOrderAsync([FromQuery] string waybillNo)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(waybillNo))
|
||||||
|
{
|
||||||
|
throw new BusinessException("请扫描或输入单号");
|
||||||
|
}
|
||||||
|
|
||||||
|
var order = await OrderRepository.GetByWaybillNoAsync(waybillNo.Trim());
|
||||||
|
if (order == null)
|
||||||
|
{
|
||||||
|
throw new BusinessException("未找到对应订单,请检查单号");
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureOutboundAllowed(order.OrderStatus);
|
||||||
|
|
||||||
|
var output = new OutboundOrderLookupOutput
|
||||||
|
{
|
||||||
|
OrderId = order.Id,
|
||||||
|
ServiceNo = order.ServiceNo,
|
||||||
|
ClientNo = order.ClientNo,
|
||||||
|
TrackNo = order.TrackNo,
|
||||||
|
ProductCode = order.ProductCode,
|
||||||
|
DestinationCountry = order.ConsigneeCountry,
|
||||||
|
OrderStatus = order.OrderStatus,
|
||||||
|
OrderStatusName = OmsDocHelper.GetOrderStatusName(order.OrderStatus)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(order.ProductCode))
|
||||||
|
{
|
||||||
|
var product = await SalesProductRepository.GetByProductCodeAsync(order.ProductCode.Trim());
|
||||||
|
if (product != null)
|
||||||
|
{
|
||||||
|
output.SalesProductId = product.Id;
|
||||||
|
output.SalesProductName = product.ProductName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(order.ConsigneeCountry))
|
||||||
|
{
|
||||||
|
var country = await CountryRepository.FirstOrDefaultAsync(x => x.CountryCode == order.ConsigneeCountry);
|
||||||
|
output.DestinationCountryName = country?.ChineseName ?? country?.EnglishName ?? order.ConsigneeCountry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(order.ChannelCode))
|
||||||
|
{
|
||||||
|
var channel = await ServiceChannelRepository.GetByChannelCodeAsync(order.ChannelCode.Trim());
|
||||||
|
if (channel != null)
|
||||||
|
{
|
||||||
|
output.ServiceChannelId = channel.Id;
|
||||||
|
output.ChannelCode = channel.ChannelCode;
|
||||||
|
output.ServiceChannelName = await BuildServiceChannelDisplayNameAsync(channel.GroupId, channel.ChannelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 新增出库记录。
|
/// 新增出库记录。
|
||||||
@ -31,12 +101,25 @@ public class OutboundRecordService : ApplicationService
|
|||||||
[HttpPost("/operation/outbound/create")]
|
[HttpPost("/operation/outbound/create")]
|
||||||
public async Task<OutboundRecordOutput> CreateAsync(CreateOutboundRecordInput input)
|
public async Task<OutboundRecordOutput> CreateAsync(CreateOutboundRecordInput input)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input.WaybillNo))
|
||||||
|
{
|
||||||
|
throw new BusinessException("运单号不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
var order = await OrderRepository.GetByWaybillNoAsync(input.WaybillNo.Trim());
|
||||||
|
if (order == null)
|
||||||
|
{
|
||||||
|
throw new BusinessException("未找到对应订单,请检查单号");
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureOutboundAllowed(order.OrderStatus);
|
||||||
|
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var operatorId = CurrentUser.GetId<int>();
|
var operatorId = CurrentUser.GetId<int>();
|
||||||
var entity = new OutboundRecord
|
var entity = new OutboundRecord
|
||||||
{
|
{
|
||||||
WaybillNo = input.WaybillNo,
|
WaybillNo = input.WaybillNo.Trim(),
|
||||||
WarehouseId = input.WarehouseId,
|
WarehouseId = input.WarehouseId ?? order.WarehouseId,
|
||||||
OperateTime = now,
|
OperateTime = now,
|
||||||
OperatorId = operatorId
|
OperatorId = operatorId
|
||||||
};
|
};
|
||||||
@ -86,4 +169,30 @@ public class OutboundRecordService : ApplicationService
|
|||||||
|
|
||||||
return new OmsItemsResult<OutboundRecordOutput> { Items = items };
|
return new OmsItemsResult<OutboundRecordOutput> { Items = items };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EnsureOutboundAllowed(string orderStatus)
|
||||||
|
{
|
||||||
|
if (orderStatus is OrderStatusCodes.PendingPayment or OrderStatusCodes.Received)
|
||||||
|
{
|
||||||
|
throw new BusinessException("订单未付款,禁止出库");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderStatus != OrderStatusCodes.PendingShip)
|
||||||
|
{
|
||||||
|
throw new BusinessException($"订单状态为「{OmsDocHelper.GetOrderStatusName(orderStatus)}」,不允许出库");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> BuildServiceChannelDisplayNameAsync(int? groupId, string channelName)
|
||||||
|
{
|
||||||
|
string? groupName = null;
|
||||||
|
if (groupId.HasValue)
|
||||||
|
{
|
||||||
|
var group = await ServiceChannelGroupRepository.FirstOrDefaultAsync(x => x.Id == groupId.Value);
|
||||||
|
groupName = group?.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
var displayName = $"{groupName}{channelName}".Trim();
|
||||||
|
return string.IsNullOrWhiteSpace(displayName) ? channelName : displayName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1142,7 +1142,7 @@ public partial class OrderService
|
|||||||
OrderFeeChargingStageCodes.Inbound,
|
OrderFeeChargingStageCodes.Inbound,
|
||||||
replaceExistingReceivable: true);
|
replaceExistingReceivable: true);
|
||||||
|
|
||||||
order.OrderStatus = OrderStatusCodes.Received;
|
order.OrderStatus = OrderStatusCodes.PendingPayment;
|
||||||
order.ReceiveTime = DateTime.Now;
|
order.ReceiveTime = DateTime.Now;
|
||||||
order.UpdateTime = DateTime.Now;
|
order.UpdateTime = DateTime.Now;
|
||||||
await OrderRepository.UpdateAsync(order);
|
await OrderRepository.UpdateAsync(order);
|
||||||
|
|||||||
@ -119,7 +119,7 @@ public partial class OrderService : ApplicationService
|
|||||||
throw new BusinessException("订单已支付");
|
throw new BusinessException("订单已支付");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order.OrderStatus != OrderStatusCodes.PendingPayment)
|
if (order.OrderStatus is not (OrderStatusCodes.PendingPayment or OrderStatusCodes.Received))
|
||||||
{
|
{
|
||||||
throw new BusinessException("当前订单状态不可支付");
|
throw new BusinessException("当前订单状态不可支付");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user