上传源代码版本

This commit is contained in:
Im-Jenisson
2026-06-01 16:30:29 +08:00
commit b2a9b7d3c2
462 changed files with 104365 additions and 0 deletions

25
Bak/DAL/DAL.csproj Normal file
View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Compile Remove="interfaces\**" />
<Compile Remove="repositories\**" />
<EmbeddedResource Remove="interfaces\**" />
<EmbeddedResource Remove="repositories\**" />
<None Remove="interfaces\**" />
<None Remove="repositories\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MDL\MDL.csproj" />
<ProjectReference Include="..\DB\DB.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MySql.Data" Version="8.0.33" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="SqlSugar" Version="5.1.4.207" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface IArrivalHandoverFormRepository
{
Task<int> InsertAsync(ArrivalHandoverFormEntity form);
Task<ArrivalHandoverFormEntity> GetByIdAsync(int id);
Task<ArrivalHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber);
Task<List<ArrivalHandoverFormEntity>> GetAllAsync();
Task<int> UpdateAsync(ArrivalHandoverFormEntity form);
Task<int> DeleteAsync(int id);
Task<bool> ExistsByHandoverNumberAsync(string handoverNumber);
/// <summary>
/// 批量获取到货交接单(分页)
/// </summary>
/// <param name="page">页码</param>
/// <param name="pageSize">每页数量</param>
/// <param name="sortBy">排序字段</param>
/// <param name="sortOrder">排序方向</param>
/// <param name="handoverNumber">交接单号</param>
/// <param name="creator">创建人</param>
/// <param name="startDate">开始日期</param>
/// <param name="endDate">结束日期</param>
/// <returns>到货交接单列表和总记录数</returns>
Task<(List<ArrivalHandoverFormEntity> Forms, int TotalCount)> GetArrivalHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string creator,
DateTime? startDate = null,
DateTime? endDate = null);
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using SqlSugar;
namespace DAL.Interfaces
{
public interface IBagTagRepository
{
Task<int> InsertAsync(BagTagEntity tag);
Task<BagTagEntity> GetByIdAsync(int id);
Task<BagTagEntity> GetByTagNumberAsync(string tagNumber);
Task<List<BagTagEntity>> GetAllAsync();
Task<int> UpdateAsync(BagTagEntity tag);
Task<int> InsertWaybillAsync(BagTagWaybillEntity waybill);
Task<List<MDL.DTOs.BagTagWaybillWithDetailsDto>> GetWaybillsByTagNumberAsync(string tagNumber);
Task<bool> ExistsByTagNumberAsync(string tagNumber);
Task<bool> IsWaybillAssociatedAsync(string tagNumber, string finalMileTrackingNumber);
Task<(List<BagTagEntity> BagTags, int TotalCount)> GetBagTagsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string tagNumber,
string channel,
string status,
string creator);
Task<int> RemoveWaybillAssociationAsync(string tagNumber, string finalMileTrackingNumber);
Task<BagTagWaybillEntity> GetWaybillAssociationAsync(string finalMileTrackingNumber);
Task<bool> IsWaybillAssociatedAnywhereAsync(string finalMileTrackingNumber);
Task<List<BagTagEntity>> GetAvailableBagTagsByChannelAsync(string channel);
/// <summary>
/// 查询符合条件的 USPS 包裹
/// </summary>
Task<List<string>> GetEligibleUspsWaybillsAsync(DateTime cutoffTime);
/// <summary>
/// 获取符合条件的包裹数量
/// </summary>
Task<int> GetEligibleUspsWaybillCountAsync(DateTime cutoffTime);
}
}

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 货物数据仓库接口
/// </summary>
public interface ICargoDataRepository
{
/// <summary>
/// 批量插入货物数据
/// </summary>
/// <param name="cargoDataList">货物数据列表</param>
/// <returns>插入成功的记录数</returns>
Task<int> BatchInsertAsync(List<CargoDataEntity> cargoDataList);
/// <summary>
/// 根据中性面单单号查询货物数据
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>货物数据实体</returns>
Task<CargoDataEntity?> GetByWaybillNumberAsync(string neutralWaybillNumber);
/// <summary>
/// 查询货物数据
/// </summary>
/// <param name="searchKey">搜索关键字(中性面单/提单号/大包号)</param>
/// <param name="customerId">客户ID可选</param>
/// <param name="pageIndex">页码默认1</param>
/// <param name="pageSize">每页记录数默认100</param>
/// <returns>货物数据列表</returns>
Task<IEnumerable<CargoDataEntity>> QueryAsync(string? searchKey = null, int? customerId = null, int pageIndex = 1, int pageSize = 100);
/// <summary>
/// 按中性面单单号批量更新货物数据
/// </summary>
/// <param name="cargoDataList">货物数据列表</param>
/// <returns>更新成功的记录数</returns>
Task<int> BatchUpdateByWaybillNumberAsync(List<CargoDataEntity> cargoDataList);
/// <summary>
/// 按中性面单单号批量删除货物数据
/// </summary>
/// <param name="neutralWaybillNumbers">中性面单单号列表</param>
/// <returns>删除成功的记录数</returns>
Task<int> BatchDeleteByWaybillNumbersAsync(List<string> neutralWaybillNumbers);
}
}

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 客户API信息的数据访问接口
/// </summary>
public interface ICustomerApiRepository
{
/// <summary>
/// 创建客户API记录
/// </summary>
/// <param name="entity">客户API实体</param>
/// <returns>创建的记录ID</returns>
Task<int> CreateAsync(CustomerApiEntity entity);
/// <summary>
/// 根据ID获取客户API记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>客户API实体</returns>
Task<CustomerApiEntity?> GetByIdAsync(int id);
/// <summary>
/// 根据客户ID获取客户API记录
/// </summary>
/// <param name="customerId">客户ID</param>
/// <returns>客户API实体列表</returns>
Task<List<CustomerApiEntity>> GetByCustomerIdAsync(int customerId);
/// <summary>
/// 根据客户代码获取客户API记录
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <returns>客户API实体列表</returns>
Task<List<CustomerApiEntity>> GetByCustomerCodeAsync(string customerCode);
/// <summary>
/// 根据API密钥获取客户API记录
/// </summary>
/// <param name="apiKey">API密钥</param>
/// <returns>客户API实体</returns>
Task<CustomerApiEntity?> GetByApiKeyAsync(string apiKey);
/// <summary>
/// 验证客户API凭证并返回客户API信息
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <param name="apiKey">API密钥</param>
/// <returns>客户API实体如果验证失败则返回null</returns>
Task<CustomerApiEntity?> ValidateAndGetApiCredentialsAsync(string customerCode, string apiKey);
/// <summary>
/// 验证客户API凭证
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <param name="apiKey">API密钥</param>
/// <returns>是否验证通过</returns>
Task<bool> ValidateApiCredentialsAsync(string customerCode, string apiKey);
/// <summary>
/// 更新客户API记录
/// </summary>
/// <param name="entity">客户API实体</param>
/// <returns>更新是否成功</returns>
Task<bool> UpdateAsync(CustomerApiEntity entity);
/// <summary>
/// 删除客户API记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>删除是否成功</returns>
Task<bool> DeleteAsync(int id);
/// <summary>
/// 获取所有客户API记录
/// </summary>
/// <returns>客户API实体列表</returns>
Task<List<CustomerApiEntity>> GetAllAsync();
}
}

View File

@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 客户资料的数据访问接口
/// </summary>
public interface ICustomerRepository
{
/// <summary>
/// 创建客户记录
/// </summary>
/// <param name="entity">客户实体</param>
/// <returns>创建的记录ID</returns>
Task<int> CreateAsync(CustomerEntity entity);
/// <summary>
/// 根据ID获取客户记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>客户实体</returns>
Task<CustomerEntity?> GetByIdAsync(int id);
/// <summary>
/// 根据客户代码获取客户记录
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <returns>客户实体</returns>
Task<CustomerEntity?> GetByCustomerCodeAsync(string customerCode);
/// <summary>
/// 更新客户记录
/// </summary>
/// <param name="entity">客户实体</param>
/// <returns>更新是否成功</returns>
Task<bool> UpdateAsync(CustomerEntity entity);
/// <summary>
/// 删除客户记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>删除是否成功</returns>
Task<bool> DeleteAsync(int id);
/// <summary>
/// 获取所有客户记录
/// </summary>
/// <returns>客户实体列表</returns>
Task<List<CustomerEntity>> GetAllAsync();
/// <summary>
/// 检查客户是否存在
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <returns>是否存在</returns>
Task<bool> ExistsAsync(string customerCode);
/// <summary>
/// 根据ID列表批量获取客户记录
/// </summary>
/// <param name="ids">ID列表</param>
/// <returns>客户实体列表</returns>
Task<List<CustomerEntity>> GetByIdsAsync(List<int> ids);
}
}

View File

@@ -0,0 +1,72 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 面单PDF缓存的数据访问接口
/// </summary>
public interface ILabelPdfCacheRepository
{
/// <summary>
/// 根据中性面单单号获取缓存记录
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <returns>缓存记录实体</returns>
Task<LabelPdfCache?> GetByWaybillNumberAsync(string waybillNumber);
/// <summary>
/// 创建缓存记录
/// </summary>
/// <param name="entity">缓存实体</param>
/// <returns>创建的记录ID</returns>
Task<long> CreateAsync(LabelPdfCache entity);
/// <summary>
/// 更新缓存记录
/// </summary>
/// <param name="entity">缓存实体</param>
/// <returns>更新是否成功</returns>
Task<bool> UpdateAsync(LabelPdfCache entity);
/// <summary>
/// 标记缓存为失效状态
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <returns>操作是否成功</returns>
Task<bool> InvalidateCacheAsync(string waybillNumber);
/// <summary>
/// 获取待处理的缓存任务列表
/// </summary>
/// <param name="maxRetryCount">最大重试次数</param>
/// <param name="limit">最大返回数量</param>
/// <returns>待处理的缓存任务列表</returns>
Task<List<LabelPdfCache>> GetPendingTasksAsync(int maxRetryCount, int limit);
/// <summary>
/// 获取订单表中新的有标签订单(缓存表中不存在的)
/// </summary>
/// <param name="limit">最大返回数量</param>
/// <returns>新订单的面单号列表</returns>
Task<List<string>> GetNewOrdersWithLabelsAsync(int limit);
/// <summary>
/// 获取需要重新处理的失效缓存列表
/// </summary>
/// <param name="limit">最大返回数量</param>
/// <returns>失效的缓存记录列表</returns>
Task<List<LabelPdfCache>> GetInvalidCachesAsync(int limit);
/// <summary>
/// 异步更新条码信息
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <param name="barcodeNumber">条码号</param>
/// <param name="barcodeType">条码类型</param>
/// <param name="confidence">识别置信度</param>
/// <returns>更新是否成功</returns>
Task<bool> UpdateBarcodeInfoAsync(string waybillNumber, string barcodeNumber, byte barcodeType, int confidence);
}
}

View File

@@ -0,0 +1,126 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using MDL.DTOs;
namespace DAL.Interfaces
{
/// <summary>
/// 标签替换请求的数据访问接口
/// </summary>
public interface ILabelReplaceRepository
{
/// <summary>
/// 创建标签替换请求记录
/// </summary>
/// <param name="entity">标签替换请求实体</param>
/// <returns>创建的记录ID</returns>
Task<int> CreateAsync(LabelReplaceEntity entity);
/// <summary>
/// 根据ID获取标签替换请求记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>标签替换请求实体</returns>
Task<LabelReplaceEntity?> GetByIdAsync(int id);
/// <summary>
/// 根据中性面单单号获取标签替换请求记录
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <returns>标签替换请求实体</returns>
Task<LabelReplaceEntity?> GetByWaybillNumberAsync(string waybillNumber);
/// <summary>
/// 根据跟踪单号获取标签替换请求记录
/// </summary>
/// <param name="trackingNumber">跟踪单号</param>
/// <returns>标签替换请求实体列表</returns>
Task<List<LabelReplaceEntity>> GetByTrackingNumberAsync(string trackingNumber);
/// <summary>
/// 更新标签替换请求记录
/// </summary>
/// <param name="entity">标签替换请求实体</param>
/// <returns>更新是否成功</returns>
Task<bool> UpdateAsync(LabelReplaceEntity entity);
/// <summary>
/// 删除标签替换请求记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>删除是否成功</returns>
Task<bool> DeleteAsync(int id);
/// <summary>
/// 获取所有标签替换请求记录
/// </summary>
/// <returns>标签替换请求实体列表</returns>
Task<List<LabelReplaceEntity>> GetAllAsync();
/// <summary>
/// 分页获取标签替换请求记录
/// </summary>
/// <param name="page">页码</param>
/// <param name="pageSize">每页大小</param>
/// <param name="sortBy">排序字段</param>
/// <param name="sortOrder">排序顺序</param>
/// <param name="billOfLadingNumber">提单号</param>
/// <param name="masterPackageNumber">大包号</param>
/// <param name="referenceNumber">参考号</param>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <param name="replaceStatus">换单状态</param>
/// <param name="customerId">客户ID</param>
/// <returns>标签替换请求实体列表和总记录数</returns>
Task<(List<LabelReplaceWithCustomerDto>, int)> GetByPageAsync(int page, int pageSize, string sortBy, string sortOrder, string billOfLadingNumber, string masterPackageNumber, string referenceNumber, string neutralWaybillNumber, string finalMileTrackingNumber, string replaceStatus, int? customerId, string startCreatedAt, string endCreatedAt, string startReplacedAt, string endReplacedAt);
/// <summary>
/// 批量查询换单状态
/// </summary>
/// <param name="customerId">客户ID</param>
/// <param name="waybillNumbers">中性面单单号列表</param>
/// <param name="trackingNumbers">尾程跟踪单号列表</param>
/// <returns>标签替换请求实体列表和最新扫描时间映射</returns>
Task<(List<LabelReplaceEntity>, Dictionary<string, DateTime>)> GetLabelReplaceStatusAsync(int customerId, List<string> waybillNumbers, List<string> trackingNumbers);
/// <summary>
/// 根据交接单号列表批量获取标签替换请求记录
/// </summary>
/// <param name="handoverNumbers">交接单号列表</param>
/// <param name="customerId">客户ID</param>
/// <returns>标签替换请求实体列表</returns>
Task<List<LabelReplaceEntity>> GetByHandoverNumbersAsync(List<string> handoverNumbers, int? customerId);
/// <summary>
/// 将base64编码转换为PDF文件并保存
/// </summary>
/// <param name="base64Content">base64编码的PDF内容</param>
/// <param name="fileName">文件名</param>
/// <returns>保存的文件路径</returns>
Task<string> ConvertBase64ToPdfAsync(string base64Content, string fileName);
/// <summary>
/// 更新Label字段但保持LabelRetrievedAt不变
/// </summary>
/// <param name="id">记录ID</param>
/// <param name="newLabel">新的Label值</param>
/// <returns>更新是否成功</returns>
Task<bool> UpdateLabelWithoutChangingRetrievedAtAsync(int id, string newLabel);
/// <summary>
/// 获取每日标签统计数据
/// </summary>
/// <param name="startDate">开始日期</param>
/// <param name="endDate">结束日期</param>
/// <param name="customerId">客户ID</param>
/// <returns>每日标签统计数据列表</returns>
Task<List<DailyLabelStatsDto>> GetDailyLabelStatsAsync(string startDate, string endDate, int? customerId);
/// <summary>
/// 获取每日标签统计数据中文版本使用自定义SQL
/// </summary>
/// <returns>每日标签统计数据列表</returns>
Task<List<DailyLabelStatsChineseDto>> GetDailyLabelStatsChineseAsync();
}
}

View File

@@ -0,0 +1,114 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 标签历史扫描记录仓储接口
/// </summary>
public interface ILabelScanRepository
{
/// <summary>
/// 创建标签扫描记录
/// </summary>
/// <param name="entity">标签扫描记录实体</param>
/// <returns>创建的记录ID</returns>
Task<int> CreateAsync(LabelScanEntity entity);
/// <summary>
/// 根据中性面单单号获取标签扫描记录列表
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>标签扫描记录列表</returns>
Task<List<LabelScanEntity>> GetByNeutralWaybillNumberAsync(string neutralWaybillNumber);
Task<List<LabelScanEntity>> GetByNeutralWaybillNumbersAsync(List<string> neutralWaybillNumbers);
/// <summary>
/// 根据参考号获取标签扫描记录列表
/// </summary>
/// <param name="referenceNumber">参考号</param>
/// <returns>标签扫描记录列表</returns>
Task<List<LabelScanEntity>> GetByReferenceNumberAsync(string referenceNumber);
/// <summary>
/// 根据尾程跟踪单号获取标签扫描记录列表
/// </summary>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <returns>标签扫描记录列表</returns>
Task<List<LabelScanEntity>> GetByFinalMileTrackingNumberAsync(string finalMileTrackingNumber);
/// <summary>
/// 根据客户ID获取标签扫描记录列表
/// </summary>
/// <param name="customerId">客户ID</param>
/// <returns>标签扫描记录列表</returns>
Task<List<LabelScanEntity>> GetByCustomerIdAsync(int customerId);
/// <summary>
/// 根据客户ID和中性面单单号获取标签扫描记录列表
/// </summary>
/// <param name="customerId">客户ID</param>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>标签扫描记录列表</returns>
Task<List<LabelScanEntity>> GetByCustomerIdAndWaybillNumberAsync(int customerId, string neutralWaybillNumber);
/// <summary>
/// 统计客户的订单扫描次数
/// </summary>
/// <param name="customerId">客户ID</param>
/// <param name="neutralWaybillNumber">中性面单单号(可选,不提供则统计所有订单)</param>
/// <returns>扫描次数</returns>
Task<int> CountScansByCustomerAndWaybillAsync(int customerId, string neutralWaybillNumber = null);
/// <summary>
/// 获取客户的扫描记录分组统计
/// </summary>
/// <param name="customerId">客户ID</param>
/// <returns>按订单分组的扫描统计信息</returns>
Task<Dictionary<string, int>> GetScanStatsByCustomerAsync(int customerId);
/// <summary>
/// 更新标签扫描记录
/// </summary>
/// <param name="entity">标签扫描记录实体</param>
/// <returns>是否更新成功</returns>
Task<bool> UpdateAsync(LabelScanEntity entity);
/// <summary>
/// 获取所有标签扫描记录
/// </summary>
/// <returns>标签扫描记录实体列表</returns>
Task<List<LabelScanEntity>> GetAllAsync();
/// <summary>
/// 分页获取标签扫描记录
/// </summary>
/// <param name="page">页码</param>
/// <param name="pageSize">每页大小</param>
/// <param name="sortBy">排序字段</param>
/// <param name="sortOrder">排序顺序</param>
/// <param name="customerId">客户ID</param>
/// <param name="referenceNumber">参考号</param>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <param name="result">扫描结果</param>
/// <returns>标签扫描记录DTO列表和总记录数</returns>
Task<(List<MDL.DTOs.LabelScanWithCustomerDto>, int)> GetByPageAsync(int page, int pageSize, string sortBy, string sortOrder, int? customerId, string referenceNumber, string neutralWaybillNumber, string finalMileTrackingNumber, int? result, string startCreatedAt, string endCreatedAt);
/// <summary>
/// 根据中性面单单号获取最新的扫描记录
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>最新的标签扫描记录</returns>
Task<LabelScanEntity> GetLatestScanByWaybillAsync(string neutralWaybillNumber);
/// <summary>
/// 根据日期范围获取扫描记录
/// </summary>
/// <param name="startDate">开始日期</param>
/// <param name="endDate">结束日期</param>
/// <returns>标签扫描记录列表</returns>
Task<List<LabelScanEntity>> GetByDateRangeAsync(System.DateTime startDate, System.DateTime endDate);
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 订单日志仓储接口
/// </summary>
public interface IOrderLogRepository
{
/// <summary>
/// 插入订单日志
/// </summary>
/// <param name="log">订单日志实体</param>
/// <returns>插入是否成功</returns>
Task<bool> InsertOrderLogAsync(OrderLogEntity log);
/// <summary>
/// 根据中性面单单号获取订单日志列表
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>订单日志实体列表</returns>
Task<List<OrderLogEntity>> GetOrderLogsByWaybillNumberAsync(string neutralWaybillNumber);
/// <summary>
/// 根据尾程跟踪单号获取订单日志列表
/// </summary>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <returns>订单日志实体列表</returns>
Task<List<OrderLogEntity>> GetOrderLogsByTrackingNumberAsync(string finalMileTrackingNumber);
/// <summary>
/// 获取所有订单日志列表(分页)
/// </summary>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">每页大小</param>
/// <returns>订单日志实体列表</returns>
Task<List<OrderLogEntity>> GetAllOrderLogsAsync(int pageIndex, int pageSize);
/// <summary>
/// 根据操作类型和操作结果获取订单日志列表
/// </summary>
/// <param name="operationType">操作类型</param>
/// <param name="operationResult">操作结果</param>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">每页大小</param>
/// <returns>订单日志实体列表</returns>
Task<List<OrderLogEntity>> GetOrderLogsByOperationAsync(string operationType, string operationResult, int pageIndex, int pageSize);
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
/// <summary>
/// 出货交接单与袋牌关联仓库接口
/// </summary>
public interface IShippingHandoverFormBagTagRepository
{
/// <summary>
/// 插入关联记录
/// </summary>
/// <param name="relation">关联实体</param>
/// <returns>影响行数</returns>
Task<int> InsertAsync(ShippingHandoverFormBagTagEntity relation);
/// <summary>
/// 批量插入关联记录
/// </summary>
/// <param name="relations">关联实体列表</param>
/// <returns>影响行数</returns>
Task<int> InsertBatchAsync(List<ShippingHandoverFormBagTagEntity> relations);
/// <summary>
/// 根据出货交接单ID获取关联的袋牌列表
/// </summary>
/// <param name="shippingHandoverFormId">出货交接单ID</param>
/// <returns>袋牌列表</returns>
Task<List<ShippingHandoverFormBagTagEntity>> GetByShippingHandoverFormIdAsync(int shippingHandoverFormId);
/// <summary>
/// 根据袋牌ID获取关联的出货交接单
/// </summary>
/// <param name="bagTagId">袋牌ID</param>
/// <returns>关联实体</returns>
Task<ShippingHandoverFormBagTagEntity> GetByBagTagIdAsync(int bagTagId);
/// <summary>
/// 删除关联记录
/// </summary>
/// <param name="id">关联ID</param>
/// <returns>影响行数</returns>
Task<int> DeleteAsync(int id);
/// <summary>
/// 根据出货交接单ID删除所有关联记录
/// </summary>
/// <param name="shippingHandoverFormId">出货交接单ID</param>
/// <returns>影响行数</returns>
Task<int> DeleteByShippingHandoverFormIdAsync(int shippingHandoverFormId);
/// <summary>
/// 检查袋牌是否已关联到出货交接单
/// </summary>
/// <param name="bagTagId">袋牌ID</param>
/// <returns>是否已关联</returns>
Task<bool> ExistsByBagTagIdAsync(int bagTagId);
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface IShippingHandoverFormRepository
{
Task<int> InsertAsync(ShippingHandoverFormEntity form);
Task<ShippingHandoverFormEntity> GetByIdAsync(int id);
Task<ShippingHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber);
Task<List<ShippingHandoverFormEntity>> GetAllAsync();
Task<int> UpdateAsync(ShippingHandoverFormEntity form);
Task<int> DeleteAsync(int id);
Task<bool> ExistsByHandoverNumberAsync(string handoverNumber);
Task<(List<ShippingHandoverFormEntity> Forms, int TotalCount)> GetShippingHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string channel,
string creator,
System.DateTime? startDeliveryTime = null,
System.DateTime? endDeliveryTime = null);
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface ITagInstanceRepository
{
Task<TagInstanceEntity> CreateAsync(TagInstanceEntity entity);
Task<TagInstanceEntity> UpdateAsync(TagInstanceEntity entity);
Task<TagInstanceEntity> GetByIdAsync(long id);
Task<List<TagInstanceEntity>> GetByWaybillAsync(string neutralWaybillNumber);
Task<List<TagInstanceEntity>> GetByTagTypeAsync(string tagType);
}
}

View File

@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace DAL.Interfaces
{
public interface ITagRepository
{
Task SaveResultAsync(string id, string result);
}
}

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface ITagTemplateRepository
{
Task<TagTemplateEntity> CreateAsync(TagTemplateEntity entity);
Task<TagTemplateEntity> UpdateAsync(TagTemplateEntity entity);
Task<bool> DeleteAsync(int id);
Task<TagTemplateEntity> GetByIdAsync(int id);
Task<TagTemplateEntity> GetByTagTypeAsync(string tagType);
Task<List<TagTemplateEntity>> GetAllAsync();
}
}

View File

@@ -0,0 +1,112 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
public class ArrivalHandoverFormRepository : IArrivalHandoverFormRepository
{
private readonly ISqlSugarProvider _provider;
public ArrivalHandoverFormRepository(ISqlSugarProvider provider)
{
_provider = provider;
// 初始化表结构
var db = _provider.GetClient();
db.CodeFirst.InitTables(typeof(ArrivalHandoverFormEntity));
}
public async Task<int> InsertAsync(ArrivalHandoverFormEntity form)
{
var db = _provider.GetClient();
return await db.Insertable(form).ExecuteCommandAsync();
}
public async Task<ArrivalHandoverFormEntity> GetByIdAsync(int id)
{
var db = _provider.GetClient();
return await db.Queryable<ArrivalHandoverFormEntity>().Where(f => f.Id == id).FirstAsync();
}
public async Task<ArrivalHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber)
{
var db = _provider.GetClient();
return await db.Queryable<ArrivalHandoverFormEntity>().Where(f => f.HandoverNumber == handoverNumber).FirstAsync();
}
public async Task<List<ArrivalHandoverFormEntity>> GetAllAsync()
{
var db = _provider.GetClient();
return await db.Queryable<ArrivalHandoverFormEntity>().ToListAsync();
}
public async Task<int> UpdateAsync(ArrivalHandoverFormEntity form)
{
var db = _provider.GetClient();
return await db.Updateable(form).ExecuteCommandAsync();
}
public async Task<int> DeleteAsync(int id)
{
var db = _provider.GetClient();
return await db.Deleteable<ArrivalHandoverFormEntity>().Where(f => f.Id == id).ExecuteCommandAsync();
}
public async Task<bool> ExistsByHandoverNumberAsync(string handoverNumber)
{
var db = _provider.GetClient();
return await db.Queryable<ArrivalHandoverFormEntity>().Where(f => f.HandoverNumber == handoverNumber).AnyAsync();
}
public async Task<(List<ArrivalHandoverFormEntity> Forms, int TotalCount)> GetArrivalHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string creator,
DateTime? startDate = null,
DateTime? endDate = null)
{
var db = _provider.GetClient();
var query = db.Queryable<ArrivalHandoverFormEntity>();
if (!string.IsNullOrEmpty(handoverNumber))
{
query = query.Where(f => f.HandoverNumber.Contains(handoverNumber));
}
if (!string.IsNullOrEmpty(creator))
{
query = query.Where(f => f.Creator.Contains(creator));
}
if (startDate.HasValue)
{
query = query.Where(f => f.ReceiptTime >= startDate.Value);
}
if (endDate.HasValue)
{
query = query.Where(f => f.ReceiptTime <= endDate.Value);
}
var totalCount = await query.CountAsync();
if (!string.IsNullOrEmpty(sortBy))
{
query = sortOrder.ToLower() == "asc"
? query.OrderBy(sortBy)
: query.OrderBy($"{sortBy} desc");
}
else
{
query = query.OrderBy("CreatedAt desc");
}
var forms = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
return (forms, totalCount);
}
}
}

View File

@@ -0,0 +1,274 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
public class BagTagRepository : IBagTagRepository
{
private readonly ISqlSugarProvider _provider;
public BagTagRepository(ISqlSugarProvider provider)
{
_provider = provider;
// 初始化表结构,只执行一次
var db = _provider.GetClient();
if (db != null)
{
db.CodeFirst.InitTables(typeof(BagTagEntity));
db.CodeFirst.InitTables(typeof(BagTagWaybillEntity));
}
}
/// <summary>
/// 获取数据库连接,每次都获取新的连接
/// </summary>
/// <returns>数据库连接</returns>
private ISqlSugarClient GetDb()
{
return _provider.GetClient();
}
public async Task<int> InsertAsync(BagTagEntity tag)
{
return await GetDb().Insertable(tag).ExecuteCommandAsync();
}
public async Task<BagTagEntity> GetByIdAsync(int id)
{
return await GetDb().Queryable<BagTagEntity>().Where(t => t.Id == id).FirstAsync();
}
public async Task<BagTagEntity> GetByTagNumberAsync(string tagNumber)
{
return await GetDb().Queryable<BagTagEntity>().Where(t => t.TagNumber == tagNumber).FirstAsync();
}
public async Task<List<BagTagEntity>> GetAllAsync()
{
return await GetDb().Queryable<BagTagEntity>().ToListAsync();
}
public async Task<int> UpdateAsync(BagTagEntity tag)
{
return await GetDb().Updateable(tag).ExecuteCommandAsync();
}
public async Task<int> InsertWaybillAsync(BagTagWaybillEntity waybill)
{
return await GetDb().Insertable(waybill).ExecuteCommandAsync();
}
public async Task<List<MDL.DTOs.BagTagWaybillWithDetailsDto>> GetWaybillsByTagNumberAsync(string tagNumber)
{
var db = GetDb();
// Optimized SQL query
var sql = $@"
SELECT
w.Id,
w.TagNumber,
w.FinalMileTrackingNumber,
w.CreatedAt,
w.Creator,
w.Remark,
l.NeutralWaybillNumber,
l.BillOfLadingNumber,
c.CustomerName as CustomerAbbreviation,
NULL as ReplaceCompletedTime
FROM bag_tag_waybills w
LEFT JOIN (
SELECT
FinalMileTrackingNumber,
NeutralWaybillNumber,
BillOfLadingNumber,
CustomerId
FROM (
SELECT
FinalMileTrackingNumber,
NeutralWaybillNumber,
BillOfLadingNumber,
CustomerId,
ROW_NUMBER() OVER (PARTITION BY FinalMileTrackingNumber ORDER BY CreatedAt DESC) as rn
FROM label_replace_requests
) sub
WHERE sub.rn = 1
) l ON w.FinalMileTrackingNumber = l.FinalMileTrackingNumber
LEFT JOIN customers c ON l.CustomerId = c.Id
WHERE w.TagNumber = @tagNumber
ORDER BY w.Id
";
return await db.Ado.SqlQueryAsync<MDL.DTOs.BagTagWaybillWithDetailsDto>(sql, new { tagNumber });
}
public async Task<bool> ExistsByTagNumberAsync(string tagNumber)
{
return await GetDb().Queryable<BagTagEntity>().Where(t => t.TagNumber == tagNumber).AnyAsync();
}
public async Task<bool> IsWaybillAssociatedAsync(string tagNumber, string finalMileTrackingNumber)
{
return await GetDb().Queryable<BagTagWaybillEntity>()
.Where(w => w.TagNumber == tagNumber && w.FinalMileTrackingNumber == finalMileTrackingNumber)
.AnyAsync();
}
public async Task<(List<BagTagEntity> BagTags, int TotalCount)> GetBagTagsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string tagNumber,
string channel,
string status,
string creator)
{
var query = GetDb().Queryable<BagTagEntity>();
// 应用过滤条件
if (!string.IsNullOrEmpty(tagNumber))
{
query = query.Where(t => t.TagNumber.Contains(tagNumber));
}
if (!string.IsNullOrEmpty(channel))
{
query = query.Where(t => t.ChannelName == channel);
}
if (!string.IsNullOrEmpty(status))
{
query = query.Where(t => t.Status == status);
}
if (!string.IsNullOrEmpty(creator))
{
query = query.Where(t => t.Creator.Contains(creator));
}
// 获取总记录数
var totalCount = await query.CountAsync();
// 应用排序
if (!string.IsNullOrEmpty(sortBy))
{
query = sortOrder.ToLower() == "asc"
? query.OrderBy(sortBy)
: query.OrderBy($"{sortBy} desc");
}
else
{
// 默认按创建时间降序排序
query = query.OrderBy("CreatedAt desc");
}
// 应用分页
var bagTags = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
return (bagTags, totalCount);
}
public async Task<int> RemoveWaybillAssociationAsync(string tagNumber, string finalMileTrackingNumber)
{
return await GetDb().Deleteable<BagTagWaybillEntity>()
.Where(w => w.TagNumber == tagNumber && w.FinalMileTrackingNumber == finalMileTrackingNumber)
.ExecuteCommandAsync();
}
public async Task<BagTagWaybillEntity> GetWaybillAssociationAsync(string finalMileTrackingNumber)
{
return await GetDb().Queryable<BagTagWaybillEntity>()
.Where(w => w.FinalMileTrackingNumber == finalMileTrackingNumber)
.FirstAsync();
}
public async Task<bool> IsWaybillAssociatedAnywhereAsync(string finalMileTrackingNumber)
{
return await GetDb().Queryable<BagTagWaybillEntity>()
.Where(w => w.FinalMileTrackingNumber == finalMileTrackingNumber)
.AnyAsync();
}
public async Task<List<BagTagEntity>> GetAvailableBagTagsByChannelAsync(string channel)
{
var db = GetDb();
// 先查询所有状态为Closed且渠道匹配的袋牌
var closedBagTags = await db.Queryable<BagTagEntity>()
.Where(t => t.Status == "Closed" && t.ChannelName == channel)
.ToListAsync();
if (closedBagTags.Count == 0)
{
return closedBagTags;
}
// 提取袋牌ID列表
var bagTagIds = closedBagTags.Select(t => t.Id).ToList();
// 查询已绑定到出库交接单的袋牌ID
var boundBagTagIds = await db.Queryable<ShippingHandoverFormBagTagEntity>()
.Where(st => bagTagIds.Contains(st.BagTagId))
.Select(st => st.BagTagId)
.ToListAsync();
// 过滤出未绑定的袋牌并排序
var availableBagTags = closedBagTags
.Where(t => !boundBagTagIds.Contains(t.Id))
.OrderBy(t => t.Id)
.ToList();
return availableBagTags;
}
public async Task<List<string>> GetEligibleUspsWaybillsAsync(DateTime cutoffTime)
{
var db = GetDb();
var sql = @"
SELECT DISTINCT
l.FinalMileTrackingNumber
FROM label_replace_requests l
LEFT JOIN bag_tag_waybills b ON l.FinalMileTrackingNumber = b.FinalMileTrackingNumber
JOIN label_scan_history s ON l.NeutralWaybillNumber = s.NeutralWaybillNumber
WHERE
l.ReplaceStatus = 'Y'
AND s.Result = 0
AND s.CreatedAt >= @CutoffTime
AND l.FinalMileTrackingNumber IS NOT NULL
AND l.FinalMileTrackingNumber != ''
AND b.Id IS NULL
AND (
l.FinalMileTrackingNumber REGEXP '^(92|93|94|95)'
OR l.FinalMileTrackingNumber REGEXP '^420[0-9]{5}(92|93|94|95)'
OR l.FinalMileTrackingNumber REGEXP '^420[0-9]{9}(92|93|94|95)'
)
ORDER BY s.CreatedAt ASC
";
return await db.Ado.SqlQueryAsync<string>(sql, new { CutoffTime = cutoffTime });
}
public async Task<int> GetEligibleUspsWaybillCountAsync(DateTime cutoffTime)
{
var db = GetDb();
var sql = @"
SELECT COUNT(DISTINCT l.FinalMileTrackingNumber)
FROM label_replace_requests l
LEFT JOIN bag_tag_waybills b ON l.FinalMileTrackingNumber = b.FinalMileTrackingNumber
JOIN label_scan_history s ON l.NeutralWaybillNumber = s.NeutralWaybillNumber
WHERE
l.ReplaceStatus = 'Y'
AND s.Result = 0
AND s.CreatedAt >= @CutoffTime
AND l.FinalMileTrackingNumber IS NOT NULL
AND l.FinalMileTrackingNumber != ''
AND b.Id IS NULL
AND (
l.FinalMileTrackingNumber REGEXP '^(92|93|94|95)'
OR l.FinalMileTrackingNumber REGEXP '^420[0-9]{5}(92|93|94|95)'
OR l.FinalMileTrackingNumber REGEXP '^420[0-9]{9}(92|93|94|95)'
)
";
return await db.Ado.GetIntAsync(sql, new { CutoffTime = cutoffTime });
}
}
}

View File

@@ -0,0 +1,127 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DAL.Interfaces;
using MDL.Models;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 货物数据仓库实现类
/// </summary>
public class CargoDataRepository : ICargoDataRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar数据库提供程序</param>
public CargoDataRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
/// <summary>
/// 批量插入货物数据
/// </summary>
public async Task<int> BatchInsertAsync(List<CargoDataEntity> cargoDataList)
{
var db = _provider.GetClient();
return await db.Insertable(cargoDataList).ExecuteCommandAsync();
}
/// <summary>
/// 根据中性面单单号查询货物数据
/// </summary>
public async Task<CargoDataEntity?> GetByWaybillNumberAsync(string neutralWaybillNumber)
{
var db = _provider.GetClient();
return await db.Queryable<CargoDataEntity>()
.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber && x.Status == "Y")
.FirstAsync();
}
/// <summary>
/// 查询货物数据
/// </summary>
public async Task<IEnumerable<CargoDataEntity>> QueryAsync(string? searchKey = null, int? customerId = null, int pageIndex = 1, int pageSize = 100)
{
var db = _provider.GetClient();
var query = db.Queryable<CargoDataEntity>().Where(x => x.Status == "Y");
// 搜索关键字过滤
if (!string.IsNullOrEmpty(searchKey))
{
query = query.Where(x =>
x.NeutralWaybillNumber.Contains(searchKey) ||
(x.BillOfLadingNumber != null && x.BillOfLadingNumber.Contains(searchKey)) ||
(x.MasterPackageNumber != null && x.MasterPackageNumber.Contains(searchKey)));
}
// 客户ID过滤
if (customerId.HasValue)
{
query = query.Where(x => x.CustomerId == customerId.Value);
}
// 分页查询
return await query
.OrderByDescending(x => x.ImportedAt)
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
/// <summary>
/// 按中性面单单号批量更新货物数据
/// </summary>
public async Task<int> BatchUpdateByWaybillNumberAsync(List<CargoDataEntity> cargoDataList)
{
var db = _provider.GetClient();
int totalUpdated = 0;
// 分组更新每批处理100条
foreach (var batch in cargoDataList.GroupBy(x => x.NeutralWaybillNumber))
{
var data = batch.FirstOrDefault();
if (data == null)
{
continue;
}
// 更新除中性面单单号外的其他字段
int updated = await db.Updateable<CargoDataEntity>()
.SetColumns(x => new CargoDataEntity
{
BillOfLadingNumber = data.BillOfLadingNumber,
MasterPackageNumber = data.MasterPackageNumber,
CustomerId = data.CustomerId,
ImportedAt = data.ImportedAt,
ImportedBy = data.ImportedBy,
Status = data.Status
})
.Where(x => x.NeutralWaybillNumber == data.NeutralWaybillNumber)
.ExecuteCommandAsync();
totalUpdated += updated;
}
return totalUpdated;
}
/// <summary>
/// 按中性面单单号批量删除货物数据
/// </summary>
public async Task<int> BatchDeleteByWaybillNumbersAsync(List<string> neutralWaybillNumbers)
{
var db = _provider.GetClient();
return await db.Updateable<CargoDataEntity>()
.SetColumns(x => new CargoDataEntity { Status = "N" })
.Where(x => neutralWaybillNumbers.Contains(x.NeutralWaybillNumber))
.ExecuteCommandAsync();
}
}
}

View File

@@ -0,0 +1,176 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 客户API信息的数据访问实现类
/// </summary>
public class CustomerApiRepository : ICustomerApiRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar数据库提供程序</param>
public CustomerApiRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
/// <summary>
/// 创建客户API记录
/// </summary>
/// <param name="entity">客户API实体</param>
/// <returns>创建的记录ID</returns>
public async Task<int> CreateAsync(CustomerApiEntity entity)
{
var db = _provider.GetClient();
// 确保表存在
if (!db.DbMaintenance.IsAnyTable("customer_apis"))
{
db.CodeFirst.InitTables(typeof(CustomerApiEntity));
}
// 设置时间戳
entity.CreatedAt = DateTime.UtcNow;
entity.UpdatedAt = DateTime.UtcNow;
// 插入数据并返回自增ID
return await db.Insertable(entity).ExecuteReturnIdentityAsync();
}
/// <summary>
/// 根据ID获取客户API记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>客户API实体</returns>
public async Task<CustomerApiEntity?> GetByIdAsync(int id)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerApiEntity>()
.Where(x => x.Id == id)
.FirstAsync();
}
/// <summary>
/// 根据客户ID获取客户API记录
/// </summary>
/// <param name="customerId">客户ID</param>
/// <returns>客户API实体列表</returns>
public async Task<List<CustomerApiEntity>> GetByCustomerIdAsync(int customerId)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerApiEntity>()
.Where(x => x.CustomerId == customerId)
.ToListAsync();
}
/// <summary>
/// 根据客户代码获取客户API记录
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <returns>客户API实体列表</returns>
public async Task<List<CustomerApiEntity>> GetByCustomerCodeAsync(string customerCode)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerApiEntity>()
.Where(x => x.CustomerCode == customerCode)
.ToListAsync();
}
/// <summary>
/// 根据API密钥获取客户API记录
/// </summary>
/// <param name="apiKey">API密钥</param>
/// <returns>客户API实体</returns>
public async Task<CustomerApiEntity?> GetByApiKeyAsync(string apiKey)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerApiEntity>()
.Where(x => x.ApiKey == apiKey)
.FirstAsync();
}
/// <summary>
/// 验证客户API凭证并返回客户API信息
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <param name="apiKey">API密钥</param>
/// <returns>客户API实体如果验证失败则返回null</returns>
public async Task<CustomerApiEntity?> ValidateAndGetApiCredentialsAsync(string customerCode, string apiKey)
{
var db = _provider.GetClient();
// 查询有效启用且未过期的API密钥
var now = DateTime.UtcNow;
return await db.Queryable<CustomerApiEntity>()
.Where(x => x.CustomerCode == customerCode && x.ApiKey == apiKey)
.Where(x => x.Status == "Y")
.Where(x => x.ExpireDate == null || x.ExpireDate > now)
.FirstAsync();
}
/// <summary>
/// 验证客户API凭证
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <param name="apiKey">API密钥</param>
/// <returns>是否验证通过</returns>
public async Task<bool> ValidateApiCredentialsAsync(string customerCode, string apiKey)
{
var result = await ValidateAndGetApiCredentialsAsync(customerCode, apiKey);
return result != null;
}
/// <summary>
/// 更新客户API记录
/// </summary>
/// <param name="entity">客户API实体</param>
/// <returns>更新是否成功</returns>
public async Task<bool> UpdateAsync(CustomerApiEntity entity)
{
var db = _provider.GetClient();
// 更新时间戳
entity.UpdatedAt = DateTime.UtcNow;
// 更新数据并返回影响行数
var rows = await db.Updateable(entity).ExecuteCommandAsync();
return rows > 0;
}
/// <summary>
/// 删除客户API记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>删除是否成功</returns>
public async Task<bool> DeleteAsync(int id)
{
var db = _provider.GetClient();
var rows = await db.Deleteable<CustomerApiEntity>()
.Where(x => x.Id == id)
.ExecuteCommandAsync();
return rows > 0;
}
/// <summary>
/// 获取所有客户API记录
/// </summary>
/// <returns>客户API实体列表</returns>
public async Task<List<CustomerApiEntity>> GetAllAsync()
{
var db = _provider.GetClient();
return await db.Queryable<CustomerApiEntity>()
.OrderByDescending(x => x.CreatedAt)
.ToListAsync();
}
}
}

View File

@@ -0,0 +1,142 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 客户资料的数据访问实现类
/// </summary>
public class CustomerRepository : ICustomerRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar数据库提供程序</param>
public CustomerRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
/// <summary>
/// 创建客户记录
/// </summary>
/// <param name="entity">客户实体</param>
/// <returns>创建的记录ID</returns>
public async Task<int> CreateAsync(CustomerEntity entity)
{
var db = _provider.GetClient();
// 确保表存在
if (!db.DbMaintenance.IsAnyTable("customers"))
{
db.CodeFirst.InitTables(typeof(CustomerEntity));
}
// 设置时间戳
entity.CreatedAt = DateTime.UtcNow;
entity.UpdatedAt = DateTime.UtcNow;
// 插入数据并返回自增ID
return await db.Insertable(entity).ExecuteReturnIdentityAsync();
}
/// <summary>
/// 根据ID获取客户记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>客户实体</returns>
public async Task<CustomerEntity?> GetByIdAsync(int id)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerEntity>()
.Where(x => x.Id == id)
.FirstAsync();
}
/// <summary>
/// 根据客户代码获取客户记录
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <returns>客户实体</returns>
public async Task<CustomerEntity?> GetByCustomerCodeAsync(string customerCode)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerEntity>()
.Where(x => x.CustomerCode == customerCode)
.FirstAsync();
}
/// <summary>
/// 更新客户记录
/// </summary>
/// <param name="entity">客户实体</param>
/// <returns>更新是否成功</returns>
public async Task<bool> UpdateAsync(CustomerEntity entity)
{
var db = _provider.GetClient();
// 更新时间戳
entity.UpdatedAt = DateTime.UtcNow;
// 更新数据并返回影响行数
var rows = await db.Updateable(entity).ExecuteCommandAsync();
return rows > 0;
}
/// <summary>
/// 删除客户记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>删除是否成功</returns>
public async Task<bool> DeleteAsync(int id)
{
var db = _provider.GetClient();
var rows = await db.Deleteable<CustomerEntity>()
.Where(x => x.Id == id)
.ExecuteCommandAsync();
return rows > 0;
}
/// <summary>
/// 获取所有客户记录
/// </summary>
/// <returns>客户实体列表</returns>
public async Task<List<CustomerEntity>> GetAllAsync()
{
var db = _provider.GetClient();
return await db.Queryable<CustomerEntity>()
.OrderByDescending(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 检查客户是否存在
/// </summary>
/// <param name="customerCode">客户代码</param>
/// <returns>是否存在</returns>
public async Task<bool> ExistsAsync(string customerCode)
{
var db = _provider.GetClient();
return await db.Queryable<CustomerEntity>()
.Where(x => x.CustomerCode == customerCode)
.AnyAsync();
}
public async Task<List<CustomerEntity>> GetByIdsAsync(List<int> ids)
{
if (ids == null || ids.Count == 0)
return new List<CustomerEntity>();
var db = _provider.GetClient();
return await db.Queryable<CustomerEntity>()
.Where(x => ids.Contains(x.Id))
.ToListAsync();
}
}
}

View File

@@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 面单PDF缓存的数据访问实现类
/// </summary>
public class LabelPdfCacheRepository : ILabelPdfCacheRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar数据库提供程序</param>
public LabelPdfCacheRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
/// <summary>
/// 根据中性面单单号获取缓存记录
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <returns>缓存记录实体</returns>
public async Task<LabelPdfCache?> GetByWaybillNumberAsync(string waybillNumber)
{
var db = _provider.GetClient();
return await db.Queryable<LabelPdfCache>()
.Where(c => c.NeutralWaybillNumber == waybillNumber)
.FirstAsync();
}
/// <summary>
/// 创建缓存记录
/// </summary>
/// <param name="entity">缓存实体</param>
/// <returns>创建的记录ID</returns>
public async Task<long> CreateAsync(LabelPdfCache entity)
{
var db = _provider.GetClient();
// 确保表存在
if (!db.DbMaintenance.IsAnyTable("label_pdf_cache"))
{
db.CodeFirst.InitTables(typeof(LabelPdfCache));
}
// 设置时间戳
entity.CreatedTime = DateTime.UtcNow;
entity.UpdatedTime = DateTime.UtcNow;
// 插入数据并返回自增ID
return await db.Insertable(entity).ExecuteReturnIdentityAsync();
}
/// <summary>
/// 更新缓存记录
/// </summary>
/// <param name="entity">缓存实体</param>
/// <returns>更新是否成功</returns>
public async Task<bool> UpdateAsync(LabelPdfCache entity)
{
var db = _provider.GetClient();
entity.UpdatedTime = DateTime.UtcNow;
return await db.Updateable(entity).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 标记缓存为失效状态
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <returns>操作是否成功</returns>
public async Task<bool> InvalidateCacheAsync(string waybillNumber)
{
var db = _provider.GetClient();
var existing = await db.Queryable<LabelPdfCache>()
.Where(c => c.NeutralWaybillNumber == waybillNumber)
.FirstAsync();
if (existing == null)
{
return false;
}
existing.Status = 3; // 3=已失效
existing.UpdatedTime = DateTime.UtcNow;
return await db.Updateable(existing).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 获取待处理的缓存任务列表
/// </summary>
/// <param name="maxRetryCount">最大重试次数</param>
/// <param name="limit">最大返回数量</param>
/// <returns>待处理的缓存记录列表</returns>
public async Task<List<LabelPdfCache>> GetPendingTasksAsync(int maxRetryCount, int limit)
{
var db = _provider.GetClient();
return await db.Queryable<LabelPdfCache>()
.Where(c => c.Status == 0 || (c.Status == 2 && c.RetryCount < maxRetryCount))
.Where(c => SqlFunc.Subqueryable<LabelReplaceEntity>()
.Where(l => l.NeutralWaybillNumber == c.NeutralWaybillNumber && !string.IsNullOrEmpty(l.Label))
.Any())
.OrderBy(c => c.CreatedTime, OrderByType.Asc)
.Take(limit)
.ToListAsync();
}
/// <summary>
/// 获取订单表中新的有标签订单(缓存表中不存在的)
/// </summary>
/// <param name="limit">最大返回数量</param>
/// <returns>新订单的面单号列表</returns>
public async Task<List<string>> GetNewOrdersWithLabelsAsync(int limit)
{
var db = _provider.GetClient();
return await db.Queryable<LabelReplaceEntity>()
.Where(o => !string.IsNullOrEmpty(o.Label))
.Where(o => !SqlFunc.Subqueryable<LabelPdfCache>()
.Where(c => c.NeutralWaybillNumber == o.NeutralWaybillNumber)
.Any())
.Select(o => o.NeutralWaybillNumber)
.Take(limit)
.ToListAsync();
}
/// <summary>
/// 获取需要重新处理的失效缓存列表
/// </summary>
/// <param name="limit">最大返回数量</param>
/// <returns>失效的缓存记录列表</returns>
public async Task<List<LabelPdfCache>> GetInvalidCachesAsync(int limit)
{
var db = _provider.GetClient();
return await db.Queryable<LabelPdfCache>()
.Where(c => c.Status == 3)
.Where(c => SqlFunc.Subqueryable<LabelReplaceEntity>()
.Where(l => l.NeutralWaybillNumber == c.NeutralWaybillNumber && !string.IsNullOrEmpty(l.Label))
.Any())
.OrderBy(c => c.UpdatedTime, OrderByType.Asc)
.Take(limit)
.ToListAsync();
}
/// <summary>
/// 异步更新条码信息
/// </summary>
/// <param name="waybillNumber">中性面单单号</param>
/// <param name="barcodeNumber">条码号</param>
/// <param name="barcodeType">条码类型</param>
/// <param name="confidence">识别置信度</param>
/// <returns>更新是否成功</returns>
public async Task<bool> UpdateBarcodeInfoAsync(string waybillNumber, string barcodeNumber, byte barcodeType, int confidence)
{
var db = _provider.GetClient();
var existing = await db.Queryable<LabelPdfCache>()
.Where(c => c.NeutralWaybillNumber == waybillNumber)
.FirstAsync();
if (existing == null)
{
return false;
}
existing.BarcodeNumber = barcodeNumber;
existing.BarcodeType = barcodeType;
existing.BarcodeConfidence = confidence;
existing.BarcodeExtractTime = DateTime.UtcNow;
existing.UpdatedTime = DateTime.UtcNow;
return await db.Updateable(existing).ExecuteCommandAsync() > 0;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,361 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using System;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 标签历史扫描记录仓储实现类
/// </summary>
public class LabelScanRepository : ILabelScanRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar提供程序</param>
public LabelScanRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
/// <summary>
/// 创建标签扫描记录
/// </summary>
/// <param name="entity">标签扫描记录实体</param>
/// <returns>创建的记录ID</returns>
public async Task<int> CreateAsync(LabelScanEntity entity)
{
var db = _provider.GetClient();
// 确保表存在
if (!db.DbMaintenance.IsAnyTable("label_scan_history"))
{
db.CodeFirst.InitTables(typeof(LabelScanEntity));
}
// 设置时间戳
entity.CreatedAt = DateTime.UtcNow;
entity.UpdatedAt = DateTime.UtcNow;
// 插入数据并返回自增ID
return await db.Insertable(entity).ExecuteReturnIdentityAsync();
}
/// <summary>
/// 根据中性面单单号获取标签扫描记录列表
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByNeutralWaybillNumberAsync(string neutralWaybillNumber)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 根据多个中性面单单号获取标签扫描记录列表
/// </summary>
/// <param name="neutralWaybillNumbers">中性面单单号列表</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByNeutralWaybillNumbersAsync(List<string> neutralWaybillNumbers)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => neutralWaybillNumbers.Contains(x.NeutralWaybillNumber))
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 根据参考号获取标签扫描记录列表
/// </summary>
/// <param name="referenceNumber">参考号</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByReferenceNumberAsync(string referenceNumber)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.ReferenceNumber == referenceNumber)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 根据尾程跟踪单号获取标签扫描记录列表
/// </summary>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByFinalMileTrackingNumberAsync(string finalMileTrackingNumber)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.FinalMileTrackingNumber == finalMileTrackingNumber)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 根据客户ID获取标签扫描记录列表
/// </summary>
/// <param name="customerId">客户ID</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByCustomerIdAsync(int customerId)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.CustomerId == customerId)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 根据客户ID和中性面单单号获取标签扫描记录列表
/// </summary>
/// <param name="customerId">客户ID</param>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByCustomerIdAndWaybillNumberAsync(int customerId, string neutralWaybillNumber)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.CustomerId == customerId && x.NeutralWaybillNumber == neutralWaybillNumber)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 统计客户的订单扫描次数
/// </summary>
/// <param name="customerId">客户ID</param>
/// <param name="neutralWaybillNumber">中性面单单号(可选,不提供则统计所有订单)</param>
/// <returns>扫描次数</returns>
public async Task<int> CountScansByCustomerAndWaybillAsync(int customerId, string neutralWaybillNumber = null)
{
var db = _provider.GetClient();
var query = db.Queryable<LabelScanEntity>().Where(x => x.CustomerId == customerId);
if (!string.IsNullOrEmpty(neutralWaybillNumber))
{
query = query.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber);
}
return await query.CountAsync();
}
/// <summary>
/// 获取客户的扫描记录分组统计
/// </summary>
/// <param name="customerId">客户ID</param>
/// <returns>按订单分组的扫描统计信息</returns>
public async Task<Dictionary<string, int>> GetScanStatsByCustomerAsync(int customerId)
{
var db = _provider.GetClient();
var result = await db.Queryable<LabelScanEntity>()
.Where(x => x.CustomerId == customerId)
.GroupBy(x => x.NeutralWaybillNumber)
.Select(x => new {
WaybillNumber = x.NeutralWaybillNumber,
Count = SqlFunc.AggregateCount(x.Id)
})
.ToListAsync();
return result.ToDictionary(item => item.WaybillNumber, item => item.Count);
}
/// <summary>
/// 更新标签扫描记录
/// </summary>
/// <param name="entity">标签扫描记录实体</param>
/// <returns>是否更新成功</returns>
public async Task<bool> UpdateAsync(LabelScanEntity entity)
{
var db = _provider.GetClient();
entity.UpdatedAt = DateTime.UtcNow;
return await db.Updateable(entity).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 获取所有标签扫描记录
/// </summary>
/// <returns>标签扫描记录实体列表</returns>
public async Task<List<LabelScanEntity>> GetAllAsync()
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.OrderByDescending(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 分页获取标签扫描记录
/// </summary>
/// <param name="page">页码</param>
/// <param name="pageSize">每页大小</param>
/// <param name="sortBy">排序字段</param>
/// <param name="sortOrder">排序顺序</param>
/// <param name="customerId">客户ID</param>
/// <param name="referenceNumber">参考号</param>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <param name="result">扫描结果</param>
/// <returns>标签扫描记录DTO列表和总记录数</returns>
public async Task<(List<MDL.DTOs.LabelScanWithCustomerDto>, int)> GetByPageAsync(int page, int pageSize, string sortBy, string sortOrder, int? customerId, string referenceNumber, string neutralWaybillNumber, string finalMileTrackingNumber, int? result, string startCreatedAt, string endCreatedAt)
{
var db = _provider.GetClient();
var query = db.Queryable<LabelScanEntity>();
// 应用筛选条件
if (customerId.HasValue)
{
query = query.Where(x => x.CustomerId == customerId);
}
if (!string.IsNullOrEmpty(referenceNumber))
{
query = query.Where(x => x.ReferenceNumber.Contains(referenceNumber));
}
if (!string.IsNullOrEmpty(neutralWaybillNumber))
{
// 处理多个单号的情况,支持逗号分隔
var waybillNumbers = neutralWaybillNumber.Split(new[] { ',', '\n', '\r', ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (waybillNumbers.Length > 1)
{
query = query.Where(x => waybillNumbers.Contains(x.NeutralWaybillNumber));
}
else if (waybillNumbers.Length == 1)
{
query = query.Where(x => x.NeutralWaybillNumber.Contains(waybillNumbers[0]));
}
}
if (!string.IsNullOrEmpty(finalMileTrackingNumber))
{
query = query.Where(x => x.FinalMileTrackingNumber.Contains(finalMileTrackingNumber));
}
if (result.HasValue)
{
query = query.Where(x => (int)x.Result == result);
}
// 应用时间筛选条件
if (!string.IsNullOrEmpty(startCreatedAt) && DateTime.TryParse(startCreatedAt, out DateTime startCreatedAtDate))
{
query = query.Where(x => x.CreatedAt >= startCreatedAtDate);
}
if (!string.IsNullOrEmpty(endCreatedAt) && DateTime.TryParse(endCreatedAt, out DateTime endCreatedAtDate))
{
query = query.Where(x => x.CreatedAt <= endCreatedAtDate);
}
// 获取总记录数
int totalCount = await query.CountAsync();
// 应用排序
if (!string.IsNullOrEmpty(sortBy))
{
if (sortOrder.ToLower() == "asc")
{
query = query.OrderBy(sortBy);
}
else
{
query = query.OrderBy($"{sortBy} DESC");
}
}
else
{
query = query.OrderByDescending(x => x.CreatedAt);
}
// 应用分页
var entities = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
// 如果没有数据,直接返回
if (entities.Count == 0)
{
return (new List<MDL.DTOs.LabelScanWithCustomerDto>(), totalCount);
}
// 提取所有非null的客户ID用于批量查询
var customerIds = entities.Select(l => l.CustomerId).Distinct().ToList();
// 批量查询客户信息
var customerList = await db.Queryable<MDL.Models.CustomerEntity>()
.Where(c => customerIds.Contains(c.Id))
.ToListAsync();
// 手动构建字典,确保类型正确
Dictionary<int, string> customers = new Dictionary<int, string>();
foreach (var customer in customerList)
{
customers[customer.Id] = customer.CustomerCode;
}
// 构建DTO列表
var dtos = new List<MDL.DTOs.LabelScanWithCustomerDto>();
foreach (var l in entities)
{
var dto = new MDL.DTOs.LabelScanWithCustomerDto
{
Id = l.Id,
CustomerId = l.CustomerId,
ReferenceNumber = l.ReferenceNumber,
NeutralWaybillNumber = l.NeutralWaybillNumber,
FinalMileTrackingNumber = l.FinalMileTrackingNumber,
Result = (int)l.Result,
Description = l.Description,
CreatedBy = l.CreatedBy,
CreatedAt = l.CreatedAt,
UpdatedAt = l.UpdatedAt
};
// 处理客户代码
if (customers.TryGetValue(l.CustomerId, out var customerCode))
{
dto.CustomerCode = customerCode;
}
dtos.Add(dto);
}
return (dtos, totalCount);
}
/// <summary>
/// 根据中性面单单号获取最新的扫描记录
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>最新的标签扫描记录</returns>
public async Task<LabelScanEntity> GetLatestScanByWaybillAsync(string neutralWaybillNumber)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber)
.OrderByDescending(x => x.CreatedAt)
.FirstAsync();
}
/// <summary>
/// 根据日期范围获取扫描记录
/// </summary>
/// <param name="startDate">开始日期</param>
/// <param name="endDate">结束日期</param>
/// <returns>标签扫描记录列表</returns>
public async Task<List<LabelScanEntity>> GetByDateRangeAsync(System.DateTime startDate, System.DateTime endDate)
{
var db = _provider.GetClient();
return await db.Queryable<LabelScanEntity>()
.Where(x => x.CreatedAt >= startDate && x.CreatedAt <= endDate)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
}
}

View File

@@ -0,0 +1,114 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 订单日志仓储实现类
/// </summary>
public class OrderLogRepository : IOrderLogRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar数据库提供程序</param>
public OrderLogRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
/// <summary>
/// 获取数据库客户端
/// </summary>
private ISqlSugarClient Db => _provider.GetClient();
/// <summary>
/// 插入订单日志
/// </summary>
/// <param name="log">订单日志实体</param>
/// <returns>插入是否成功</returns>
public async Task<bool> InsertOrderLogAsync(OrderLogEntity log)
{
// 确保表存在
if (!Db.DbMaintenance.IsAnyTable("order_logs"))
{
Db.CodeFirst.InitTables(typeof(OrderLogEntity));
}
var result = await Db.Insertable(log).ExecuteCommandAsync();
return result > 0;
}
/// <summary>
/// 根据中性面单单号获取订单日志列表
/// </summary>
/// <param name="neutralWaybillNumber">中性面单单号</param>
/// <returns>订单日志实体列表</returns>
public async Task<List<OrderLogEntity>> GetOrderLogsByWaybillNumberAsync(string neutralWaybillNumber)
{
return await Db.Queryable<OrderLogEntity>()
.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 根据尾程跟踪单号获取订单日志列表
/// </summary>
/// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
/// <returns>订单日志实体列表</returns>
public async Task<List<OrderLogEntity>> GetOrderLogsByTrackingNumberAsync(string finalMileTrackingNumber)
{
return await Db.Queryable<OrderLogEntity>()
.Where(x => x.FinalMileTrackingNumber == finalMileTrackingNumber)
.OrderBy(x => x.CreatedAt)
.ToListAsync();
}
/// <summary>
/// 获取所有订单日志列表(分页)
/// </summary>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">每页大小</param>
/// <returns>订单日志实体列表</returns>
public async Task<List<OrderLogEntity>> GetAllOrderLogsAsync(int pageIndex, int pageSize)
{
return await Db.Queryable<OrderLogEntity>()
.OrderBy(x => x.CreatedAt, OrderByType.Desc)
.ToPageListAsync(pageIndex, pageSize);
}
/// <summary>
/// 根据操作类型和操作结果获取订单日志列表
/// </summary>
/// <param name="operationType">操作类型</param>
/// <param name="operationResult">操作结果</param>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">每页大小</param>
/// <returns>订单日志实体列表</returns>
public async Task<List<OrderLogEntity>> GetOrderLogsByOperationAsync(string operationType, string operationResult, int pageIndex, int pageSize)
{
var query = Db.Queryable<OrderLogEntity>();
if (!string.IsNullOrEmpty(operationType))
{
query = query.Where(x => x.OperationType == operationType);
}
if (!string.IsNullOrEmpty(operationResult))
{
query = query.Where(x => x.OperationResult == operationResult);
}
return await query
.OrderBy(x => x.CreatedAt, OrderByType.Desc)
.ToPageListAsync(pageIndex, pageSize);
}
}
}

View File

@@ -0,0 +1,116 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
/// <summary>
/// 出货交接单与袋牌关联仓库实现
/// </summary>
public class ShippingHandoverFormBagTagRepository : IShippingHandoverFormBagTagRepository
{
private readonly ISqlSugarProvider _provider;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="provider">SqlSugar提供器</param>
public ShippingHandoverFormBagTagRepository(ISqlSugarProvider provider)
{
_provider = provider;
// 初始化表结构
var db = _provider.GetClient();
db.CodeFirst.InitTables(typeof(ShippingHandoverFormBagTagEntity));
}
/// <summary>
/// 插入关联记录
/// </summary>
/// <param name="relation">关联实体</param>
/// <returns>影响行数</returns>
public async Task<int> InsertAsync(ShippingHandoverFormBagTagEntity relation)
{
var db = _provider.GetClient();
return await db.Insertable(relation).ExecuteCommandAsync();
}
/// <summary>
/// 批量插入关联记录
/// </summary>
/// <param name="relations">关联实体列表</param>
/// <returns>影响行数</returns>
public async Task<int> InsertBatchAsync(List<ShippingHandoverFormBagTagEntity> relations)
{
var db = _provider.GetClient();
return await db.Insertable(relations).ExecuteCommandAsync();
}
/// <summary>
/// 根据出货交接单ID获取关联的袋牌列表
/// </summary>
/// <param name="shippingHandoverFormId">出货交接单ID</param>
/// <returns>袋牌列表</returns>
public async Task<List<ShippingHandoverFormBagTagEntity>> GetByShippingHandoverFormIdAsync(int shippingHandoverFormId)
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormBagTagEntity>()
.Where(r => r.ShippingHandoverFormId == shippingHandoverFormId)
.ToListAsync();
}
/// <summary>
/// 根据袋牌ID获取关联的出货交接单
/// </summary>
/// <param name="bagTagId">袋牌ID</param>
/// <returns>关联实体</returns>
public async Task<ShippingHandoverFormBagTagEntity> GetByBagTagIdAsync(int bagTagId)
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormBagTagEntity>()
.Where(r => r.BagTagId == bagTagId)
.FirstAsync();
}
/// <summary>
/// 删除关联记录
/// </summary>
/// <param name="id">关联ID</param>
/// <returns>影响行数</returns>
public async Task<int> DeleteAsync(int id)
{
var db = _provider.GetClient();
return await db.Deleteable<ShippingHandoverFormBagTagEntity>()
.Where(r => r.Id == id)
.ExecuteCommandAsync();
}
/// <summary>
/// 根据出货交接单ID删除所有关联记录
/// </summary>
/// <param name="shippingHandoverFormId">出货交接单ID</param>
/// <returns>影响行数</returns>
public async Task<int> DeleteByShippingHandoverFormIdAsync(int shippingHandoverFormId)
{
var db = _provider.GetClient();
return await db.Deleteable<ShippingHandoverFormBagTagEntity>()
.Where(r => r.ShippingHandoverFormId == shippingHandoverFormId)
.ExecuteCommandAsync();
}
/// <summary>
/// 检查袋牌是否已关联到出货交接单
/// </summary>
/// <param name="bagTagId">袋牌ID</param>
/// <returns>是否已关联</returns>
public async Task<bool> ExistsByBagTagIdAsync(int bagTagId)
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormBagTagEntity>()
.Where(r => r.BagTagId == bagTagId)
.AnyAsync();
}
}
}

View File

@@ -0,0 +1,122 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
public class ShippingHandoverFormRepository : IShippingHandoverFormRepository
{
private readonly ISqlSugarProvider _provider;
public ShippingHandoverFormRepository(ISqlSugarProvider provider)
{
_provider = provider;
// 初始化表结构
var db = _provider.GetClient();
db.CodeFirst.InitTables(typeof(ShippingHandoverFormEntity));
}
public async Task<int> InsertAsync(ShippingHandoverFormEntity form)
{
var db = _provider.GetClient();
return await db.Insertable(form).ExecuteReturnIdentityAsync();
}
public async Task<ShippingHandoverFormEntity> GetByIdAsync(int id)
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormEntity>().Where(f => f.Id == id).FirstAsync();
}
public async Task<ShippingHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber)
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormEntity>().Where(f => f.HandoverNumber == handoverNumber).FirstAsync();
}
public async Task<List<ShippingHandoverFormEntity>> GetAllAsync()
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormEntity>().ToListAsync();
}
public async Task<int> UpdateAsync(ShippingHandoverFormEntity form)
{
var db = _provider.GetClient();
return await db.Updateable(form).ExecuteCommandAsync();
}
public async Task<int> DeleteAsync(int id)
{
var db = _provider.GetClient();
return await db.Deleteable<ShippingHandoverFormEntity>().Where(f => f.Id == id).ExecuteCommandAsync();
}
public async Task<bool> ExistsByHandoverNumberAsync(string handoverNumber)
{
var db = _provider.GetClient();
return await db.Queryable<ShippingHandoverFormEntity>().Where(f => f.HandoverNumber == handoverNumber).AnyAsync();
}
public async Task<(List<ShippingHandoverFormEntity> Forms, int TotalCount)> GetShippingHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string channel,
string creator,
System.DateTime? startDeliveryTime = null,
System.DateTime? endDeliveryTime = null)
{
var db = _provider.GetClient();
var query = db.Queryable<ShippingHandoverFormEntity>();
// 应用过滤条件
if (!string.IsNullOrEmpty(handoverNumber))
{
query = query.Where(f => f.HandoverNumber.Contains(handoverNumber));
}
if (!string.IsNullOrEmpty(channel))
{
query = query.Where(f => f.Channel.Contains(channel));
}
if (!string.IsNullOrEmpty(creator))
{
query = query.Where(f => f.Creator.Contains(creator));
}
if (startDeliveryTime.HasValue)
{
query = query.Where(f => f.DeliveryTime >= startDeliveryTime);
}
if (endDeliveryTime.HasValue)
{
query = query.Where(f => f.DeliveryTime <= endDeliveryTime);
}
// 获取总记录数
var totalCount = await query.CountAsync();
// 应用排序
if (!string.IsNullOrEmpty(sortBy))
{
query = sortOrder.ToLower() == "asc"
? query.OrderBy(sortBy)
: query.OrderBy($"{sortBy} desc");
}
else
{
// 默认按创建时间降序排序
query = query.OrderBy("CreatedAt desc");
}
// 应用分页
var forms = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
return (forms, totalCount);
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using DAL.Interfaces;
using MDL.Models;
using SqlSugar;
using DB.Database;
namespace DAL.Repositories
{
public class TagInstanceRepository : ITagInstanceRepository
{
private readonly SqlSugarScope _db;
public TagInstanceRepository(ISqlSugarProvider sqlSugarProvider)
{
_db = sqlSugarProvider.GetClient();
}
public async Task<TagInstanceEntity> CreateAsync(TagInstanceEntity entity)
{
await _db.Insertable(entity).ExecuteCommandAsync();
return entity;
}
public async Task<TagInstanceEntity> UpdateAsync(TagInstanceEntity entity)
{
await _db.Updateable(entity).ExecuteCommandAsync();
return entity;
}
public async Task<TagInstanceEntity> GetByIdAsync(long id)
{
return await _db.Queryable<TagInstanceEntity>().Where(x => x.Id == id).FirstAsync();
}
public async Task<List<TagInstanceEntity>> GetByWaybillAsync(string neutralWaybillNumber)
{
return await _db.Queryable<TagInstanceEntity>()
.Where(x => x.NeutralWaybillNumber == neutralWaybillNumber)
.ToListAsync();
}
public async Task<List<TagInstanceEntity>> GetByTagTypeAsync(string tagType)
{
return await _db.Queryable<TagInstanceEntity>()
.Where(x => x.TagType == tagType)
.ToListAsync();
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Threading.Tasks;
using MDL.Models;
using DAL.Interfaces;
using DB.Database;
using SqlSugar;
namespace DAL.Repositories
{
public class TagRepository : ITagRepository
{
private readonly ISqlSugarProvider _provider;
public TagRepository(ISqlSugarProvider provider)
{
_provider = provider;
}
public async Task SaveResultAsync(string id, string result)
{
var db = _provider.GetClient();
var entity = new TagResultEntity
{
RequestId = id,
Result = result,
CreatedAt = DateTime.UtcNow
};
// ensure table exists (simple auto-creation)
db.CodeFirst.InitTables(typeof(TagResultEntity));
await db.Insertable(entity).ExecuteCommandAsync();
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using DAL.Interfaces;
using MDL.Models;
using SqlSugar;
using DB.Database;
namespace DAL.Repositories
{
public class TagTemplateRepository : ITagTemplateRepository
{
private readonly SqlSugarScope _db;
public TagTemplateRepository(ISqlSugarProvider sqlSugarProvider)
{
_db = sqlSugarProvider.GetClient();
}
public async Task<TagTemplateEntity> CreateAsync(TagTemplateEntity entity)
{
await _db.Insertable(entity).ExecuteCommandAsync();
return entity;
}
public async Task<TagTemplateEntity> UpdateAsync(TagTemplateEntity entity)
{
await _db.Updateable(entity).ExecuteCommandAsync();
return entity;
}
public async Task<bool> DeleteAsync(int id)
{
var result = await _db.Deleteable<TagTemplateEntity>().Where(x => x.Id == id).ExecuteCommandAsync();
return result > 0;
}
public async Task<TagTemplateEntity> GetByIdAsync(int id)
{
return await _db.Queryable<TagTemplateEntity>().Where(x => x.Id == id).FirstAsync();
}
public async Task<TagTemplateEntity> GetByTagTypeAsync(string tagType)
{
return await _db.Queryable<TagTemplateEntity>().Where(x => x.TagType == tagType && x.IsActive).FirstAsync();
}
public async Task<List<TagTemplateEntity>> GetAllAsync()
{
return await _db.Queryable<TagTemplateEntity>().ToListAsync();
}
}
}