fix 支持离线查询

This commit is contained in:
2024-08-28 11:50:30 +08:00
parent c850519b63
commit c9938bd258
9 changed files with 389 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
using Dlhis.Middle.Request;
using Dlhis.Middle.Response;
using Kurisu.AspNetCore.DataAccess.Dto;
using Kurisu.AspNetCore.UnifyResultAndValidation;
using Kurisu.RemoteCall.Attributes;
@@ -12,4 +13,15 @@ public interface ICanteenApi
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
[Post("/api/canteen/orders")]
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);
}

View 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);
}
}

View File

@@ -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; }
}

View 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; }
}

View 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; }
}

View 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);
}

View File

@@ -11,5 +11,8 @@ public interface ICanteenSettingService : IScopeDependency
/// <param name="tenantId"></param>
/// <returns></returns>
Task<Dictionary<CanteenSettingItemEnumType, string>> GetUserSettingAsync(string userNo, string tenantId);
Task<TimeOnly?> GetBusinessSwitchTimeAsync(string tenantId);
}

View 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;
}
}

View File

@@ -34,4 +34,23 @@ public class CanteenSettingService : ICanteenSettingService
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;
}
}
}