fix 支持离线查询
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using Dlhis.Middle.Request;
|
using Dlhis.Middle.Request;
|
||||||
using Dlhis.Middle.Response;
|
using Dlhis.Middle.Response;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||||
using Kurisu.RemoteCall.Attributes;
|
using Kurisu.RemoteCall.Attributes;
|
||||||
|
|
||||||
@@ -12,4 +13,15 @@ public interface ICanteenApi
|
|||||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||||
[Post("/api/canteen/orders")]
|
[Post("/api/canteen/orders")]
|
||||||
Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||||
|
[Post("/api/canteen/balances/device/page")]
|
||||||
|
Task<DefaultApiResult<Pagination<BalanceRecordDeviceResponse>>> GetPageByDeviceUniqueNoAsync(BalanceRecordPageByDeviceUniqueNoRequest request);
|
||||||
|
|
||||||
|
|
||||||
|
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||||
|
[Post("/api/canteen/balances/refund")]
|
||||||
|
Task<DefaultApiResult<OrderResultResponse>> RefundAsync(BalanceRecordRefundRequest request);
|
||||||
}
|
}
|
||||||
89
Src/Dlhis.Middle/Controllers/BalancesController.cs
Normal file
89
Src/Dlhis.Middle/Controllers/BalancesController.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using Dlhis.Middle.Api;
|
||||||
|
using Dlhis.Middle.Request;
|
||||||
|
using Dlhis.Middle.Response;
|
||||||
|
using Dlhis.Middle.Services;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||||
|
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Dlhis.Middle.Controllers;
|
||||||
|
|
||||||
|
[Route("api/canteen/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class BalancesController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IBalanceService _balanceService;
|
||||||
|
private readonly IHealthCheckService _healthCheckService;
|
||||||
|
private readonly ICanteenApi _canteenApi;
|
||||||
|
|
||||||
|
public BalancesController(IBalanceService balanceService, IHealthCheckService healthCheckService, ICanteenApi canteenApi)
|
||||||
|
{
|
||||||
|
_balanceService = balanceService;
|
||||||
|
_healthCheckService = healthCheckService;
|
||||||
|
_canteenApi = canteenApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备消费记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("device/page")]
|
||||||
|
[IgnoreTenant]
|
||||||
|
public async Task<DefaultApiResult<Pagination<BalanceRecordDeviceResponse>>> GetPageByDeviceUniqueNoGetAsync([FromQuery] BalanceRecordPageByDeviceUniqueNoRequest request)
|
||||||
|
{
|
||||||
|
if (_healthCheckService.GetIsOffline())
|
||||||
|
{
|
||||||
|
return new DefaultApiResult<Pagination<BalanceRecordDeviceResponse>>()
|
||||||
|
{
|
||||||
|
Data = await _balanceService.GetPageByDeviceUniqueNoAsync(request),
|
||||||
|
Code = ApiStateCode.Success
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _canteenApi.GetPageByDeviceUniqueNoAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备消费记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("device/page")]
|
||||||
|
[IgnoreTenant]
|
||||||
|
public async Task<DefaultApiResult<Pagination<BalanceRecordDeviceResponse>>> GetPageByDeviceUniqueNoPostAsync(BalanceRecordPageByDeviceUniqueNoRequest request)
|
||||||
|
{
|
||||||
|
if (_healthCheckService.GetIsOffline())
|
||||||
|
{
|
||||||
|
return new DefaultApiResult<Pagination<BalanceRecordDeviceResponse>>()
|
||||||
|
{
|
||||||
|
Data = await _balanceService.GetPageByDeviceUniqueNoAsync(request),
|
||||||
|
Code = ApiStateCode.Success
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _canteenApi.GetPageByDeviceUniqueNoAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 退款
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[HttpPost("refund")]
|
||||||
|
[IgnoreTenant]
|
||||||
|
public async Task<DefaultApiResult<OrderResultResponse>> RefundAsync(BalanceRecordRefundRequest request)
|
||||||
|
{
|
||||||
|
if (_healthCheckService.GetIsOffline())
|
||||||
|
{
|
||||||
|
return new DefaultApiResult<OrderResultResponse>()
|
||||||
|
{
|
||||||
|
Data = null,
|
||||||
|
Code = ApiStateCode.Error,
|
||||||
|
Msg = "不支持离线退款"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _canteenApi.RefundAsync(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||||
|
|
||||||
|
namespace Dlhis.Middle.Request;
|
||||||
|
|
||||||
|
public class BalanceRecordPageByDeviceUniqueNoRequest : PageDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 设备唯一号
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "设备唯一号不能为空")]
|
||||||
|
public string DeviceUniqueNo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询日期(优先使用)
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? SearchDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询时间段(开始)
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? Start { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询时间段(结束)
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? End { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工号
|
||||||
|
/// </summary>
|
||||||
|
public string UserCode { get; set; }
|
||||||
|
}
|
||||||
12
Src/Dlhis.Middle/Request/BalanceRecordRefundRequest.cs
Normal file
12
Src/Dlhis.Middle/Request/BalanceRecordRefundRequest.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Dlhis.Middle.Request;
|
||||||
|
|
||||||
|
public class BalanceRecordRefundRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// no
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "消费流水号不能为空")]
|
||||||
|
public string No { get; set; }
|
||||||
|
}
|
||||||
109
Src/Dlhis.Middle/Response/BalanceRecordDeviceResponse.cs
Normal file
109
Src/Dlhis.Middle/Response/BalanceRecordDeviceResponse.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
using Dlhis.Entity.Canteen.Enums;
|
||||||
|
using Kurisu.AspNetCore.Utils.Converters;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.Middle.Response;
|
||||||
|
|
||||||
|
public class BalanceRecordDeviceResponse
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流水号
|
||||||
|
/// </summary>
|
||||||
|
public string No { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 档案号/QRCode
|
||||||
|
/// </summary>
|
||||||
|
public string UserNo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 姓名
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 学工号
|
||||||
|
/// </summary>
|
||||||
|
public string UserCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门号
|
||||||
|
/// </summary>
|
||||||
|
public string DepartmentNo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门
|
||||||
|
/// </summary>
|
||||||
|
public string DepartmentName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属成本日期
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(ToDateJsonConverter))]
|
||||||
|
public DateTime CostDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 来源
|
||||||
|
/// </summary>
|
||||||
|
public BalanceRecordSourceEnumType Source { get; set; }
|
||||||
|
public string SourceDesc => Source.GetDescription();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 收入/支出
|
||||||
|
/// </summary>
|
||||||
|
public BalanceRecordTypeEnumType Type { get; set; }
|
||||||
|
public string TypeDesc => Type.GetDescription();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 金额
|
||||||
|
/// </summary>
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 营业点
|
||||||
|
/// </summary>
|
||||||
|
public string BusinessPlaceName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 餐次
|
||||||
|
/// </summary>
|
||||||
|
public ShiftEnumType? ShiftType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据状态
|
||||||
|
/// </summary>
|
||||||
|
public BalanceRecordStatusEnumType Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据状态描述
|
||||||
|
/// </summary>
|
||||||
|
public string StatusDesc => Status.GetDescription();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录产生时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime CostDateTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 汇总金额
|
||||||
|
/// </summary>
|
||||||
|
public decimal Sum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 厂区id
|
||||||
|
/// </summary>
|
||||||
|
public string TenantId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 厂区名称
|
||||||
|
/// </summary>
|
||||||
|
public string TenantName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// image
|
||||||
|
/// </summary>
|
||||||
|
public string Image { get; set; }
|
||||||
|
}
|
||||||
10
Src/Dlhis.Middle/Services/IBalanceService.cs
Normal file
10
Src/Dlhis.Middle/Services/IBalanceService.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Dlhis.Middle.Request;
|
||||||
|
using Dlhis.Middle.Response;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||||
|
|
||||||
|
namespace Dlhis.Middle.Services;
|
||||||
|
|
||||||
|
public interface IBalanceService : IScopeDependency
|
||||||
|
{
|
||||||
|
Task<Pagination<BalanceRecordDeviceResponse>> GetPageByDeviceUniqueNoAsync(BalanceRecordPageByDeviceUniqueNoRequest request);
|
||||||
|
}
|
||||||
@@ -11,5 +11,8 @@ public interface ICanteenSettingService : IScopeDependency
|
|||||||
/// <param name="tenantId"></param>
|
/// <param name="tenantId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Dictionary<CanteenSettingItemEnumType, string>> GetUserSettingAsync(string userNo, string tenantId);
|
Task<Dictionary<CanteenSettingItemEnumType, string>> GetUserSettingAsync(string userNo, string tenantId);
|
||||||
|
|
||||||
|
|
||||||
|
Task<TimeOnly?> GetBusinessSwitchTimeAsync(string tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
102
Src/Dlhis.Middle/Services/Implements/BalanceService.cs
Normal file
102
Src/Dlhis.Middle/Services/Implements/BalanceService.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Canteen.Enums;
|
||||||
|
using Dlhis.Middle.Entities;
|
||||||
|
using Dlhis.Middle.Request;
|
||||||
|
using Dlhis.Middle.Response;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
|
||||||
|
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace Dlhis.Middle.Services.Implements;
|
||||||
|
|
||||||
|
public class BalanceService : IBalanceService
|
||||||
|
{
|
||||||
|
private readonly IDbContext _dbContext;
|
||||||
|
private readonly ICanteenSettingService _canteenSettingService;
|
||||||
|
|
||||||
|
public BalanceService(IDbContext dbContext, ICanteenSettingService canteenSettingService)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_canteenSettingService = canteenSettingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<Pagination<BalanceRecordDeviceResponse>> GetPageByDeviceUniqueNoAsync(BalanceRecordPageByDeviceUniqueNoRequest request)
|
||||||
|
{
|
||||||
|
var device = await _dbContext.Queryable<LocalDeviceEntity>()
|
||||||
|
.Where(x => x.UniqueNo == request.DeviceUniqueNo)
|
||||||
|
.SingleAsync();
|
||||||
|
|
||||||
|
if (device == null)
|
||||||
|
{
|
||||||
|
return new Pagination<BalanceRecordDeviceResponse>
|
||||||
|
{
|
||||||
|
Data = new List<BalanceRecordDeviceResponse>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.SearchDate.HasValue)
|
||||||
|
{
|
||||||
|
request.Start = request.SearchDate;
|
||||||
|
request.End = request.SearchDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var switchTime = await _canteenSettingService.GetBusinessSwitchTimeAsync(device.TenantId);
|
||||||
|
if (switchTime.HasValue)
|
||||||
|
{
|
||||||
|
var setTime = request.Start!.Value.Add(switchTime.Value.ToTimeSpan());
|
||||||
|
if (DateTime.Now < setTime)
|
||||||
|
{
|
||||||
|
request.Start = request.Start.Value.AddDays(-1);
|
||||||
|
request.End = request.End!.Value.AddDays(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var page = await _dbContext.Queryable<LocalBalanceRecordEntity>()
|
||||||
|
.LeftJoin<LocalGainfoEntity>((record, ga) => record.UserNo == ga.No)
|
||||||
|
.LeftJoin<LocalDepartmentEntity>((record, ga, department) => ga.DepartmentNo == department.No)
|
||||||
|
.LeftJoin<LocalBusinessPlaceEntity>((record, ga, department, bPlace) => record.BusinessPlaceCode == bPlace.Code)
|
||||||
|
//.LeftJoin<ImageRecordEntity>((record, ga, department, bPlace, imageRecord) => imageRecord.No == record.No)
|
||||||
|
.Where(record => record.DeviceUniqueNo == device.UniqueNo)
|
||||||
|
.Where(record => record.CostDate >= request.Start && record.CostDate <= request.End)
|
||||||
|
.Where(record => record.Type == BalanceRecordTypeEnumType.Out
|
||||||
|
&& (record.Status == BalanceRecordStatusEnumType.Valid || (record.Status == BalanceRecordStatusEnumType.Obsolute && record.Remark == "退款")))
|
||||||
|
.WhereIF(request.UserCode.IsPresent(), record => record.UserCode == request.UserCode)
|
||||||
|
.OrderBy(record => record.CostDateTime, OrderByType.Desc)
|
||||||
|
.Select((record, ga, department, bPlace) => new BalanceRecordDeviceResponse
|
||||||
|
{
|
||||||
|
Id = record.Id,
|
||||||
|
Amount = SqlFunc.Abs(record.Amount),
|
||||||
|
CostDate = record.CostDate,
|
||||||
|
DepartmentNo = record.DepartmentNo,
|
||||||
|
UserNo = record.UserNo,
|
||||||
|
UserCode = record.UserCode,
|
||||||
|
Type = record.Type,
|
||||||
|
Status = record.Status,
|
||||||
|
Source = record.Source,
|
||||||
|
No = SqlFunc.IIF(record.Status == BalanceRecordStatusEnumType.Obsolute && record.Remark == "退款", "(已退)" + record.No, record.No),
|
||||||
|
Name = record.Name,
|
||||||
|
DepartmentName = department.Name,
|
||||||
|
BusinessPlaceName = bPlace.Name,
|
||||||
|
ShiftType = record.ShiftType,
|
||||||
|
CostDateTime = record.CostDateTime,
|
||||||
|
TenantId = record.TenantId,
|
||||||
|
Image = string.Empty
|
||||||
|
})
|
||||||
|
.ToPageListAsync(request);
|
||||||
|
|
||||||
|
//消费总金额
|
||||||
|
var sum = await _dbContext.Queryable<LocalBalanceRecordEntity>()
|
||||||
|
.Where(record => record.CostDate >= request.Start && record.CostDate <= request.End)
|
||||||
|
.Where(record => record.DeviceUniqueNo == device.UniqueNo)
|
||||||
|
.Where(record => record.Type == BalanceRecordTypeEnumType.Out && record.Status == BalanceRecordStatusEnumType.Valid)
|
||||||
|
.SumAsync(record => SqlFunc.Abs(SqlFunc.IsNull(record.Amount, 0)));
|
||||||
|
|
||||||
|
page.Data.ForEach(x => x.Sum = sum);
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,4 +34,23 @@ public class CanteenSettingService : ICanteenSettingService
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<TimeOnly?> GetBusinessSwitchTimeAsync(string tenantId)
|
||||||
|
{
|
||||||
|
var setting = await _context.Queryable<LocalCanteenSettingEntity>()
|
||||||
|
.Where(x => x.Enable)
|
||||||
|
.Where(x => x.TenantId == tenantId)
|
||||||
|
.Where(x => x.Item == CanteenSettingItemEnumType.BusinessSwitchTime)
|
||||||
|
.FirstAsync();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return TimeOnly.Parse(setting.Value);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user