feat 生日券功能,自动上传消费数据,提醒访客到期
This commit is contained in:
102
Src/Dlhis.Canteen/Voucher/Controllers/EMealVoucherController.cs
Normal file
102
Src/Dlhis.Canteen/Voucher/Controllers/EMealVoucherController.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Response;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Dlhis.Canteen.Voucher.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EMealVoucherController : ControllerBase
|
||||
{
|
||||
private readonly IEMealVoucherService _eMealVoucherService;
|
||||
|
||||
public EMealVoucherController(IEMealVoucherService eMealVoucherService)
|
||||
{
|
||||
_eMealVoucherService = eMealVoucherService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页数据
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("page")]
|
||||
public async Task<Pagination<EMealVoucherPageResponse>> GetPageAsync([FromQuery] EMealVoucherPageRequest request)
|
||||
{
|
||||
return await _eMealVoucherService.GetPageAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取我的电子餐券申请
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("my")]
|
||||
public async Task<Pagination<EMealVoucherMyPageResponse>> GetMyEMealVoucherPageAsync([FromQuery] EMealVoucherPageRequest request)
|
||||
{
|
||||
return await _eMealVoucherService.GetMyEMealVoucherPageAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查看电子餐券
|
||||
/// </summary>
|
||||
/// <param name="no"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("details")]
|
||||
public async Task<List<EMealVoucherDetailResponse>> GetDetailsByNoAsync(string no)
|
||||
{
|
||||
return await _eMealVoucherService.GetDetailsByNoAsync(no);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取url签名
|
||||
/// </summary>
|
||||
/// <param name="detailId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("signature")]
|
||||
public async Task<string> GetQrCodeSignatureAsync(long detailId)
|
||||
{
|
||||
return await _eMealVoucherService.GetQrCodeSignatureAsync(detailId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新url签名
|
||||
/// </summary>
|
||||
/// <param name="detailId"></param>
|
||||
[HttpPost("signature/refresh")]
|
||||
public async Task RefreshSignatureAsync(long detailId)
|
||||
{
|
||||
await _eMealVoucherService.RefreshSignatureAsync(detailId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取二维码
|
||||
/// </summary>
|
||||
/// <param name="signature"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpGet("qrcode")]
|
||||
public async Task<string> GetQrCodeAsync(string signature)
|
||||
{
|
||||
return await _eMealVoucherService.GetQrCodeAsync(signature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 餐券消费分页
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("balance/page")]
|
||||
[IgnoreTenant]
|
||||
public async Task<Pagination<BalanceRecordEMealVoucherResponse>> GetEMealVoucherPageAsync([FromQuery] BalanceRecordEMealVoucherPageRequest request)
|
||||
{
|
||||
return await _eMealVoucherService.GetEMealVoucherPageAsync(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Dlhis.Canteen.Voucher.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 券二维码服务
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class VoucherQrCodesController : ControllerBase
|
||||
{
|
||||
private readonly IVoucherQrCodeService _voucherQrCodeService;
|
||||
|
||||
public VoucherQrCodesController(IVoucherQrCodeService voucherQrCodeService)
|
||||
{
|
||||
_voucherQrCodeService = voucherQrCodeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取二维码
|
||||
/// </summary>
|
||||
/// <param name="voucherNo">券码</param>
|
||||
/// <param name="isNeedRefresh">true:请求刷新</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<string> GetQrCodeAsync(string voucherNo, bool isNeedRefresh = false)
|
||||
{
|
||||
return await _voucherQrCodeService.GetQrCodeAsync(voucherNo, isNeedRefresh);
|
||||
}
|
||||
}
|
||||
107
Src/Dlhis.Canteen/Voucher/Controllers/VouchersController.cs
Normal file
107
Src/Dlhis.Canteen/Voucher/Controllers/VouchersController.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using Dlhis.Basic.Vouchers.Request;
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Response;
|
||||
using Dlhis.Canteen.Tickets.Request;
|
||||
using Dlhis.Canteen.Tickets.Services;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Dlhis.Constants;
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.Authentication.Abstractions;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 券
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class VouchersController : ControllerBase
|
||||
{
|
||||
private readonly INamedResolver _namedResolver;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
|
||||
public VouchersController(INamedResolver namedResolver, ICurrentUser currentUser)
|
||||
{
|
||||
_namedResolver = namedResolver;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取分页数据(按券类型)
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("page")]
|
||||
public async Task<Pagination<VoucherPageResponse>> GetPageAsync([FromQuery] VoucherPageRequest request)
|
||||
{
|
||||
return await _namedResolver.GetService<IVoucherService>(request.Type.ToString() + "VoucherService").GetPageAsync(request);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取我的分页数据(按券类型)(H5)
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("my")]
|
||||
public async Task<Pagination<VoucherPageResponse>> GetMyPageAsync([FromQuery] VoucherPageRequest request)
|
||||
{
|
||||
var userCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode);
|
||||
request.UserCode = userCode;
|
||||
return await _namedResolver.GetService<IVoucherService>(request.Type.ToString()).GetPageAsync(request);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建生日券
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("birthday/create")]
|
||||
public async Task CreateBirthdayVoucherAsync(VoucherByBirthdayRequest request)
|
||||
{
|
||||
var srv = _namedResolver.GetService<IVoucherService>(VoucherEnumType.Birthday.ToString() + "VoucherService");
|
||||
srv.ThrowIfNull("不支持的券类型");
|
||||
await srv.CreateAsync(new Dictionary<string, object>
|
||||
{
|
||||
["userCodes"] = request.UserCodes,
|
||||
["begin"] = request.Begin,
|
||||
["end"] = request.End,
|
||||
["remark"] = request.Remark
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 餐券消费分页
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("balance/page")]
|
||||
[IgnoreTenant]
|
||||
public async Task<Pagination<VoucherBalancePageResponse>> GetVoucherBalancePageAsync([FromQuery] VoucherBalancePageRequest request)
|
||||
{
|
||||
var srv = _namedResolver.GetService<IVoucherService>(request.Type.ToString() + "VoucherService");
|
||||
|
||||
return await srv.GetVoucherBalancePageAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 我的餐券消费分页(H5)
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("balance/my/page")]
|
||||
[IgnoreTenant]
|
||||
public async Task<Pagination<VoucherBalancePageResponse>> GetMyVoucherBalancePageAsync([FromQuery] VoucherBalancePageRequest request)
|
||||
{
|
||||
var srv = _namedResolver.GetService<IVoucherService>(request.Type.ToString());
|
||||
return await srv.GetVoucherBalancePageAsync(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Requests;
|
||||
|
||||
public class EMealVoucherPageRequest : PageDto, IValidatableObject
|
||||
{
|
||||
public DateTimePeriod SearchDateTimePeriod { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (SearchDateTimePeriod.HasValue())
|
||||
{
|
||||
SearchDateTimePeriod.End = SearchDateTimePeriod.Start!.Value.AddDays(1).AddSeconds(-1);
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Requests;
|
||||
|
||||
public class VoucherBalancePageRequest : PageDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 券类型 VoucherEnumType
|
||||
/// </summary>
|
||||
[EnumDataType(typeof(VoucherEnumType))]
|
||||
public VoucherEnumType Type { get; set; }
|
||||
|
||||
public string UserCode { get; set; }
|
||||
|
||||
public DateTimePeriod SearchDateTimePeriod { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Dlhis.Basic.Vouchers.Request;
|
||||
|
||||
public class VoucherByBirthdayRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 支持指定工号
|
||||
/// </summary>
|
||||
public List<string> UserCodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始范围
|
||||
/// </summary>
|
||||
public DateTime Begin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束范围
|
||||
/// </summary>
|
||||
public DateTime End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "请填写备注")]
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
35
Src/Dlhis.Canteen/Voucher/Requests/VoucherPageRequest.cs
Normal file
35
Src/Dlhis.Canteen/Voucher/Requests/VoucherPageRequest.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
|
||||
namespace Dlhis.Canteen.Tickets.Request;
|
||||
|
||||
public class VoucherPageRequest : PageDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 类型 VoucherEnumType
|
||||
/// </summary>
|
||||
[EnumDataType(typeof(VoucherEnumType))]
|
||||
public VoucherEnumType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工号
|
||||
/// </summary>
|
||||
public string UserCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询日期区间
|
||||
/// </summary>
|
||||
public DateTimePeriod SearchDateTimePeriod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 一级部门
|
||||
/// </summary>
|
||||
public string DepartmentNoFirst { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 二级部门
|
||||
/// </summary>
|
||||
public string DepartmentNoSecond { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Dlhis.Canteen.Voucher.Response;
|
||||
|
||||
public class EMealVoucherDetailResponse
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用餐人
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 手机号
|
||||
/// </summary>
|
||||
public string Phone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 就餐开始
|
||||
/// </summary>
|
||||
public DateTime Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 就餐结束
|
||||
/// </summary>
|
||||
public DateTime End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余金额
|
||||
/// </summary>
|
||||
public decimal Balance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原始金额
|
||||
/// </summary>
|
||||
public decimal OriginBalance { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Dlhis.Canteen.Voucher.Response;
|
||||
|
||||
public class EMealVoucherMyPageResponse
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public string No { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public DateTime Date { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Mapster.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Response;
|
||||
|
||||
public class EMealVoucherPageResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// OA流程号
|
||||
/// </summary>
|
||||
public string No { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 申请人工号
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 申请人手机号
|
||||
/// </summary>
|
||||
public string Phone { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string CurrentFactories { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可使用的厂区编码
|
||||
/// </summary>
|
||||
public List<string> Factories => CurrentFactories.ToObject<List<string>>();
|
||||
|
||||
/// <summary>
|
||||
/// 申请时间
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成本日期
|
||||
/// </summary>
|
||||
public string CostId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 来源
|
||||
/// </summary>
|
||||
public string Source { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 申请事由
|
||||
/// </summary>
|
||||
public string Reason { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string CurrentShifts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用餐次
|
||||
/// </summary>
|
||||
public List<string> Shifts
|
||||
{
|
||||
get
|
||||
{
|
||||
var a = CurrentShifts.ToObject<List<int>>().Select(x => (ShiftEnumType)(x * 10)).ToList();
|
||||
return a.Select(x=>x.GetDescription()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消费券明细
|
||||
/// </summary>
|
||||
public List<EMealVoucherDetailResponse> Details { get; set; }
|
||||
}
|
||||
129
Src/Dlhis.Canteen/Voucher/Response/VoucherBalancePageResponse.cs
Normal file
129
Src/Dlhis.Canteen/Voucher/Response/VoucherBalancePageResponse.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.Utils.Converters;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Response;
|
||||
|
||||
public class VoucherBalancePageResponse
|
||||
{
|
||||
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 string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 来源
|
||||
/// </summary>
|
||||
public BalanceRecordSourceEnumType Source { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消费识别来源
|
||||
/// </summary>
|
||||
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 string ShiftTypeDesc => ShiftType?.GetDescription();
|
||||
|
||||
/// <summary>
|
||||
/// 消费机器唯一信息
|
||||
/// </summary>
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成本中心
|
||||
/// </summary>
|
||||
public string CostId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消费者所在基地
|
||||
/// </summary>
|
||||
public string OriginTenantId { 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 string Factory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人事范围
|
||||
/// </summary>
|
||||
public string Werks { get; set; }
|
||||
}
|
||||
56
Src/Dlhis.Canteen/Voucher/Response/VoucherPageResponse.cs
Normal file
56
Src/Dlhis.Canteen/Voucher/Response/VoucherPageResponse.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Response;
|
||||
|
||||
public class VoucherPageResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 券类型
|
||||
/// </summary>
|
||||
public VoucherEnumType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工号
|
||||
/// </summary>
|
||||
public string UserCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名称
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始余额
|
||||
/// </summary>
|
||||
public decimal OriginalAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前余额
|
||||
/// </summary>
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
public string CostId { get; set; }
|
||||
|
||||
|
||||
public string DepartmentNo { get; set; }
|
||||
public string DepartmentName { get; set; }
|
||||
|
||||
public string DepartmentNoFirst { get; set; }
|
||||
public string DepartmentNameFirst { get; set; }
|
||||
public string DepartmentNoSecond { get; set; }
|
||||
public string DepartmentNameSecond { get; set; }
|
||||
|
||||
|
||||
public string Werks { get; set; }
|
||||
public string Factory { get; set; }
|
||||
}
|
||||
25
Src/Dlhis.Canteen/Voucher/Services/IEMealVoucherService.cs
Normal file
25
Src/Dlhis.Canteen/Voucher/Services/IEMealVoucherService.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Response;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Services;
|
||||
|
||||
public interface IEMealVoucherService : IScopeDependency
|
||||
{
|
||||
Task<Pagination<EMealVoucherPageResponse>> GetPageAsync([FromQuery] EMealVoucherPageRequest request);
|
||||
|
||||
Task<Pagination<EMealVoucherMyPageResponse>> GetMyEMealVoucherPageAsync(EMealVoucherPageRequest request);
|
||||
|
||||
Task<List<EMealVoucherDetailResponse>> GetDetailsByNoAsync(string no);
|
||||
|
||||
Task<string> GetQrCodeSignatureAsync(long detailId);
|
||||
|
||||
Task RefreshSignatureAsync(long detailId);
|
||||
|
||||
Task<string> GetQrCodeAsync(string signature);
|
||||
|
||||
Task<Pagination<BalanceRecordEMealVoucherResponse>> GetEMealVoucherPageAsync([FromQuery] BalanceRecordEMealVoucherPageRequest request);
|
||||
}
|
||||
13
Src/Dlhis.Canteen/Voucher/Services/IVoucherQrCodeService.cs
Normal file
13
Src/Dlhis.Canteen/Voucher/Services/IVoucherQrCodeService.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Dlhis.Canteen.Voucher.Services;
|
||||
|
||||
public interface IVoucherQrCodeService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 获取二维码
|
||||
/// </summary>
|
||||
/// <param name="voucherNo"></param>
|
||||
/// <param name="isNeedRefresh"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> GetQrCodeAsync(string voucherNo, bool isNeedRefresh = false);
|
||||
}
|
||||
28
Src/Dlhis.Canteen/Voucher/Services/IVoucherService.cs
Normal file
28
Src/Dlhis.Canteen/Voucher/Services/IVoucherService.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Dlhis.Canteen.Tickets.Request;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
|
||||
namespace Dlhis.Canteen.Tickets.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 券
|
||||
/// </summary>
|
||||
public interface IVoucherService : IScopeDependency
|
||||
{
|
||||
/// <summary>
|
||||
/// 分页数据
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
Task<Pagination<VoucherPageResponse>> GetPageAsync(VoucherPageRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// 创建
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task CreateAsync(Dictionary<string, object> pairs);
|
||||
|
||||
|
||||
Task<Pagination<VoucherBalancePageResponse>> GetVoucherBalancePageAsync(VoucherBalancePageRequest request);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Dlhis.Canteen.Tickets.Request;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Dlhis.Entity.Basic.Entity;
|
||||
using Dlhis.Entity.Canteen.Entities.Voucher;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
|
||||
namespace Dlhis.Canteen.Tickets.Services.Implements;
|
||||
|
||||
public abstract class BaseVoucherService : IVoucherService
|
||||
{
|
||||
protected IDbContext DbContext { get; set; }
|
||||
|
||||
protected BaseVoucherService(IDbContext dbContext)
|
||||
{
|
||||
DbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<Pagination<VoucherPageResponse>> GetPageAsync(VoucherPageRequest request)
|
||||
{
|
||||
var pagination = await DbContext.Queryable<VoucherEntity>()
|
||||
.LeftJoin<VoucherUserInfoEntity>((x, u) => x.No == u.VoucherNo)
|
||||
.LeftJoin<GainfoEntity>((x, u, ga) => u.UserCode == ga.Code)
|
||||
.Where(x => x.Type == request.Type)
|
||||
.WhereIF(request.UserCode.IsPresent(), (x, u, ga) => u.UserCode == request.UserCode)
|
||||
.WhereIF(request.SearchDateTimePeriod.HasValue(),
|
||||
(x, u, ga) => x.CreateTime >= request.SearchDateTimePeriod.Start &&
|
||||
x.CreateTime <= request.SearchDateTimePeriod.End)
|
||||
.WhereIF(request.DepartmentNoFirst.IsPresent(),
|
||||
(x, u, ga) => u.DepartmentNoFirst == request.DepartmentNoFirst)
|
||||
.WhereIF(request.DepartmentNoSecond.IsPresent(),
|
||||
(x, u, ga) => u.DepartmentNoSecond == request.DepartmentNoSecond)
|
||||
.OrderByDescending(x => x.ClaimDateTime)
|
||||
.Select((x, u, ga) => new VoucherPageResponse
|
||||
{
|
||||
Type = x.Type,
|
||||
UserCode = u.UserCode,
|
||||
UserName = ga.Name,
|
||||
OriginalAmount = x.OriginalBalance,
|
||||
Amount = x.Balance,
|
||||
Remark = x.Remark,
|
||||
Description = x.Description,
|
||||
|
||||
CostId = u.CostId,
|
||||
|
||||
DepartmentNo = u.DepartmentNo,
|
||||
DepartmentNoFirst = u.DepartmentNoFirst,
|
||||
DepartmentNoSecond = u.DepartmentNoSecond,
|
||||
|
||||
Werks = u.Werks,
|
||||
Factory = u.Factory
|
||||
})
|
||||
.ToPageListAsync(request);
|
||||
|
||||
var searchNos = pagination.Data.SelectMany(x =>
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
x.DepartmentNo,
|
||||
x.DepartmentNoFirst,
|
||||
x.DepartmentNoSecond
|
||||
};
|
||||
}).Distinct().ToList();
|
||||
|
||||
var departments = await DbContext.Queryable<DepartmentEntity>().Where(x => searchNos.Contains(x.No)).ToListAsync();
|
||||
|
||||
pagination.Data.ForEach(x =>
|
||||
{
|
||||
x.DepartmentName = departments.FirstOrDefault(d => d.No == x.DepartmentNo)?.Name;
|
||||
x.DepartmentNameFirst = departments.FirstOrDefault(d => d.No == x.DepartmentNoFirst)?.Name;
|
||||
x.DepartmentNameSecond = departments.FirstOrDefault(d => d.No == x.DepartmentNoSecond)?.Name;
|
||||
});
|
||||
|
||||
return pagination;
|
||||
}
|
||||
|
||||
public abstract Task CreateAsync(Dictionary<string, object> pairs);
|
||||
public abstract Task<Pagination<VoucherBalancePageResponse>> GetVoucherBalancePageAsync(VoucherBalancePageRequest request);
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Dlhis.Basic.Api;
|
||||
using Dlhis.Canteen.Tickets.Services;
|
||||
using Dlhis.Canteen.Tickets.Services.Implements;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Dlhis.Constants;
|
||||
using Dlhis.Entity.Basic.Entity;
|
||||
using Dlhis.Entity.Basic.Enums;
|
||||
using Dlhis.Entity.Canteen.Entities;
|
||||
using Dlhis.Entity.Canteen.Entities.Voucher;
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.DataAccess.Entity;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Services.Implements;
|
||||
|
||||
[Service("BirthdayVoucherService")]
|
||||
public class BirthdayVoucherService : BaseVoucherService, IVoucherService
|
||||
{
|
||||
private readonly IFactorySettingApi _factorySettingApi;
|
||||
|
||||
/// <inheritdoc />
|
||||
public BirthdayVoucherService(IDbContext dbContext, IFactorySettingApi factorySettingApi) : base(dbContext)
|
||||
{
|
||||
_factorySettingApi = factorySettingApi;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task CreateAsync(Dictionary<string, object> pairs)
|
||||
{
|
||||
var p = GetDateRange(pairs);
|
||||
var remark = pairs != null && pairs.TryGetValue("remark", out var r) ? r?.ToString() : string.Empty;
|
||||
var userCodes = pairs != null && pairs.TryGetValue("userCodes", out var c) ? c as List<string> : new List<string>();
|
||||
|
||||
//忽略tenant操作
|
||||
await DbContext.IgnoreAsync<ITenantId>(async () =>
|
||||
{
|
||||
var gainfos = await GetGainfosAsync(userCodes, p.begin, p.end);
|
||||
var departmentNos = gainfos.Select(g => g.DepartmentNo).Distinct().ToList();
|
||||
var departmentInfos = await DbContext.Queryable<DepartmentEntity>()
|
||||
.Where(x => departmentNos.Contains(x.No))
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var gainfo in gainfos.Where(x => x.Birthday.HasValue))
|
||||
{
|
||||
await DbContext.Client.Ado.BeginTranAsync();
|
||||
try
|
||||
{
|
||||
var years = GetBirthdayYears(gainfo.Birthday.Value, p.begin, p.end);
|
||||
foreach (var year in years)
|
||||
{
|
||||
await GenerateVoucherAsync(gainfo, departmentInfos, year, remark);
|
||||
}
|
||||
|
||||
await DbContext.Client.Ado.CommitTranAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
await DbContext.Client.Ado.RollbackTranAsync();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task GenerateVoucherAsync(GainfoEntity gainfo, List<DepartmentEntity> departments, int year, string remark)
|
||||
{
|
||||
//生日券金额固定100元
|
||||
const decimal amount = 100;
|
||||
|
||||
var dayStr = year + "-" + gainfo.Birthday.Value.ToString("MM-dd");
|
||||
//由数据类型+工号+生日组成唯一标识
|
||||
var no = GenerateUniqueCode(VoucherEnumType.Birthday.ToString() + gainfo.Code + dayStr);
|
||||
|
||||
if (!await DbContext.Queryable<VoucherEntity>()
|
||||
.Where(x => x.No == no)
|
||||
.Where(x => x.Type == VoucherEnumType.Birthday)
|
||||
.AnyAsync())
|
||||
{
|
||||
await DbContext.InsertAsync(new VoucherEntity
|
||||
{
|
||||
No = no,
|
||||
Type = VoucherEnumType.Birthday,
|
||||
ClaimDateTime = new DateTime(year, gainfo.Birthday.Value.Month, gainfo.Birthday.Value.Day),
|
||||
|
||||
OriginalBalance = amount,
|
||||
Balance = amount,
|
||||
Description = dayStr + "生日券",
|
||||
Remark = remark,
|
||||
|
||||
CreatedBy = 1,
|
||||
CreateTime = DateTime.Now,
|
||||
ModifiedBy = 1,
|
||||
ModifiedTime = DateTime.Now,
|
||||
Version = 0
|
||||
});
|
||||
|
||||
var department = departments.FirstOrDefault(x => x.No == gainfo.DepartmentNo);
|
||||
await DbContext.InsertAsync(new VoucherUserInfoEntity
|
||||
{
|
||||
VoucherNo = no,
|
||||
UserCode = gainfo.Code,
|
||||
CostId = gainfo.CostId,
|
||||
Werks = gainfo.Werks,
|
||||
Factory = gainfo.Factory,
|
||||
DepartmentNo = gainfo.DepartmentNo,
|
||||
DepartmentNoFirst = department?.DepartmentNoFirst,
|
||||
DepartmentNoSecond = department?.DepartmentNoSecond,
|
||||
|
||||
CreatedBy = 1,
|
||||
CreateTime = DateTime.Now,
|
||||
ModifiedBy = 1,
|
||||
ModifiedTime = DateTime.Now
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private (DateTime begin, DateTime end) GetDateRange(Dictionary<string, object> pairs)
|
||||
{
|
||||
var begin = DateTime.Today;
|
||||
var end = begin;
|
||||
|
||||
if (pairs != null)
|
||||
{
|
||||
if (pairs.TryGetValue("begin", out var b))
|
||||
{
|
||||
if (b is DateTime bb)
|
||||
{
|
||||
begin = bb;
|
||||
}
|
||||
}
|
||||
|
||||
if (pairs.TryGetValue("end", out var e))
|
||||
{
|
||||
if (e is DateTime ee)
|
||||
{
|
||||
end = ee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (begin, end);
|
||||
}
|
||||
|
||||
private async Task<List<GainfoEntity>> GetGainfosAsync(List<string> userCodes, DateTime begin, DateTime end)
|
||||
{
|
||||
var factries = await _factorySettingApi.GetEnableBirthdayVoucherFactoriesAsync();
|
||||
|
||||
var isToday = begin.Date == end.Date;
|
||||
|
||||
var beginMonth = begin.Month;
|
||||
var endMonth = end.Month;
|
||||
|
||||
var overYear = endMonth < beginMonth;
|
||||
//var limit = end.Date.AddHours(9);//9点入职
|
||||
return await DbContext.Queryable<GainfoEntity>()
|
||||
.WhereIF(userCodes.IsPresent(), x => userCodes.Contains(x.Code))
|
||||
.Where(x => x.Type == GainfoUserTypeEnumType.Normal || x.Type == GainfoUserTypeEnumType.SecurityWhite)
|
||||
.Where(x => x.Birthday.HasValue && !string.IsNullOrEmpty(x.CostId))
|
||||
.WhereIF(isToday, x => SqlFunc.DateValue(x.Birthday.Value, DateType.Month) == begin.Month && SqlFunc.DateValue(x.Birthday.Value, DateType.Day) == begin.Day)
|
||||
.WhereIF(!isToday && !overYear, x => SqlFunc.DateValue(x.Birthday.Value, DateType.Month) >= beginMonth && SqlFunc.DateValue(x.Birthday.Value, DateType.Month) <= endMonth)
|
||||
.WhereIF(!isToday && overYear, x => SqlFunc.DateValue(x.Birthday.Value, DateType.Month) >= beginMonth || SqlFunc.DateValue(x.Birthday.Value, DateType.Month) <= endMonth)
|
||||
.Where(x => factries.Contains(x.Factory))
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
private static string GenerateUniqueCode(string data)
|
||||
{
|
||||
return QrCodeConstants.Birthday + data.ToArray().Select(x =>
|
||||
{
|
||||
var b = Encoding.ASCII.GetBytes(x.ToString());
|
||||
int i = b[0];
|
||||
return Convert.ToString(i);
|
||||
}).Join(string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算给定生日在区间 [begin, end] 内出现的所有年份(可能为0、1或多个)。
|
||||
/// - 对于每个候选年份构造安全的日期(处理 2/29 在非闰年的情况,退到当年最大天数)。
|
||||
/// - 若区间内找不到匹配年份,则返回包含 begin.Year 的单元素列表作为兜底行为,保持向后兼容。
|
||||
/// </summary>
|
||||
private static List<int> GetBirthdayYears(DateTime birthday, DateTime begin, DateTime end)
|
||||
{
|
||||
var years = new List<int>();
|
||||
|
||||
// 扩展范围到 begin.Year-1 .. end.Year+1 以覆盖跨年边界的极端情况
|
||||
var startYear = begin.Year - 1;
|
||||
var endYear = end.Year + 1;
|
||||
|
||||
for (var y = startYear; y <= endYear; y++)
|
||||
{
|
||||
var candidate = SafeDate(y, birthday);
|
||||
if (candidate >= begin && candidate <= end)
|
||||
{
|
||||
years.Add(candidate.Year);
|
||||
}
|
||||
}
|
||||
|
||||
// 去重并排序
|
||||
years = years.Distinct().OrderBy(x => x).ToList();
|
||||
|
||||
return years;
|
||||
|
||||
static DateTime SafeDate(int year, DateTime bday)
|
||||
{
|
||||
var day = Math.Min(bday.Day, DateTime.DaysInMonth(year, bday.Month));
|
||||
return new DateTime(year, bday.Month, day);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Pagination<VoucherBalancePageResponse>> GetVoucherBalancePageAsync(VoucherBalancePageRequest request)
|
||||
{
|
||||
return await DbContext.Queryable<BalanceRecordEntity>()
|
||||
.LeftJoin<BusinessPlaceEntity>((x, bPlace) => x.BusinessPlaceCode == bPlace.Code)
|
||||
.LeftJoin<DepartmentEntity>((x, bPlace, department) => x.DepartmentNo == department.No)
|
||||
.Where(x => x.UserCode == request.UserCode)
|
||||
.WhereIF(request.SearchDateTimePeriod.HasValue(), x => x.CostDate >= request.SearchDateTimePeriod.Start && x.CostDate <= request.SearchDateTimePeriod.End) //成本日期
|
||||
.Where(x => x.Status == BalanceRecordStatusEnumType.Valid && x.Type == BalanceRecordTypeEnumType.Out) //有效,消费数据
|
||||
.Where(x => x.Source == BalanceRecordSourceEnumType.Birthday)
|
||||
.Select((x, bPlace, department) => new VoucherBalancePageResponse
|
||||
{
|
||||
No = x.No,
|
||||
UserNo = x.UserNo,
|
||||
Name = x.Name,
|
||||
UserCode = x.UserCode,
|
||||
DepartmentNo = x.DepartmentNo,
|
||||
DepartmentName = department.Name,
|
||||
CostDate = x.CostDate,
|
||||
Remark = x.Remark,
|
||||
Source = x.Source,
|
||||
Type = x.Type,
|
||||
Amount = SqlFunc.Abs(x.Amount),
|
||||
BusinessPlaceName = bPlace.Name,
|
||||
ShiftType = x.ShiftType,
|
||||
DeviceInfo = x.DeviceUniqueNo,
|
||||
CostId = x.CostId,
|
||||
OriginTenantId = x.OriginTenantId,
|
||||
Status = x.Status,
|
||||
CostDateTime = x.CostDateTime,
|
||||
Factory = x.TenantId,
|
||||
Werks = x.Werks
|
||||
})
|
||||
.ToPageListAsync(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using System.Text;
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Response;
|
||||
using Dlhis.Canteen.Voucher.Requests;
|
||||
using Dlhis.Canteen.Voucher.Response;
|
||||
using Dlhis.Constants;
|
||||
using Dlhis.Entity.Basic.Entity;
|
||||
using Dlhis.Entity.Canteen.Entities;
|
||||
using Dlhis.Entity.Canteen.Entities.EMealVoucher;
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Kurisu.AspNetCore.Authentication.Abstractions;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
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.Canteen.Voucher.Services.Implements;
|
||||
|
||||
public class EMealVoucherService : IEMealVoucherService
|
||||
{
|
||||
private readonly IDbContext _dbContext;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
|
||||
public EMealVoucherService(IDbContext dbContext, ICurrentUser currentUser)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Pagination<EMealVoucherPageResponse>> GetPageAsync(EMealVoucherPageRequest request)
|
||||
{
|
||||
return await _dbContext.Queryable<EMealVoucherEntity>()
|
||||
.WhereIF(request.Search.IsPresent(), x => x.No == request.Search ||
|
||||
x.Code == request.Search ||
|
||||
x.Title.Contains(request.Search))
|
||||
.WhereIF(request.SearchDateTimePeriod.HasValue(), x => x.Date >= request.SearchDateTimePeriod.Start && x.Date <= request.SearchDateTimePeriod.End)
|
||||
.OrderBy(x => x.Date, OrderByType.Desc)
|
||||
.Select(x => new EMealVoucherPageResponse
|
||||
{
|
||||
No = x.No,
|
||||
Title = x.Title,
|
||||
Code = x.Code,
|
||||
Phone = x.Phone,
|
||||
CurrentFactories = x.Factories.ToString(),
|
||||
Date = x.Date,
|
||||
CostId = x.CostId,
|
||||
Source = x.Source,
|
||||
Reason = x.Reason,
|
||||
CurrentShifts = x.Shifts.ToString(),
|
||||
Details = SqlFunc.Subqueryable<EMealVoucherDetailEntity>().Where(p => p.No == x.No).ToList(p => new EMealVoucherDetailResponse
|
||||
{
|
||||
Id = p.Id,
|
||||
Name = p.Name,
|
||||
Phone = p.Phone,
|
||||
Start = p.Start,
|
||||
End = p.End,
|
||||
Balance = p.Balance,
|
||||
OriginBalance = p.OriginBalance,
|
||||
})
|
||||
})
|
||||
.ToPageListAsync(request);
|
||||
}
|
||||
|
||||
public async Task<Pagination<EMealVoucherMyPageResponse>> GetMyEMealVoucherPageAsync(EMealVoucherPageRequest request)
|
||||
{
|
||||
var code = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode);
|
||||
|
||||
return await _dbContext.Queryable<EMealVoucherEntity>()
|
||||
.Where(x => x.Code == code)
|
||||
.OrderBy(x => x.Id, OrderByType.Desc)
|
||||
.Select<EMealVoucherMyPageResponse>()
|
||||
.ToPageListAsync(request);
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<EMealVoucherDetailResponse>> GetDetailsByNoAsync(string no)
|
||||
{
|
||||
return await _dbContext.Queryable<EMealVoucherDetailEntity>()
|
||||
.Where(x => x.No == no)
|
||||
.Select<EMealVoucherDetailResponse>()
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> GetQrCodeSignatureAsync(long detailId)
|
||||
{
|
||||
return await GenerateSignatureAsync(detailId, false);
|
||||
}
|
||||
|
||||
public async Task RefreshSignatureAsync(long detailId)
|
||||
{
|
||||
await GenerateSignatureAsync(detailId, true);
|
||||
}
|
||||
|
||||
private async Task<string> GenerateSignatureAsync(long detailId, bool isRefresh)
|
||||
{
|
||||
var eMealVoucherDetail = await _dbContext.Queryable<EMealVoucherDetailEntity>().Where(x => x.Id == detailId).SingleAsync();
|
||||
eMealVoucherDetail.ThrowIfNull("数据不存在");
|
||||
if (eMealVoucherDetail.Signature.IsPresent())
|
||||
{
|
||||
if (isRefresh)
|
||||
{
|
||||
await _dbContext.Deleteable<EMealVoucherDetailQrCodeEntity>().Where(x => x.Signature == eMealVoucherDetail.Signature).ExecuteCommandAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
return eMealVoucherDetail.Signature;
|
||||
}
|
||||
}
|
||||
|
||||
eMealVoucherDetail.Signature = Guid.NewGuid().ToString().Replace("-", "") + DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
await _dbContext.UpdateAsync(eMealVoucherDetail);
|
||||
|
||||
return eMealVoucherDetail.Signature;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<string> GetQrCodeAsync(string signature)
|
||||
{
|
||||
var eMealVoucherDetail = await _dbContext.Queryable<EMealVoucherDetailEntity>().Where(x => x.Signature == signature).SingleAsync();
|
||||
eMealVoucherDetail.ThrowIfNull("无效地址");
|
||||
var eMealVoucher = await _dbContext.Queryable<EMealVoucherEntity>().Where(x => x.No == eMealVoucherDetail.No).SingleAsync();
|
||||
|
||||
var ts = DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString().Reverse().Join(string.Empty);
|
||||
var originData = string.Concat(eMealVoucher.No, ":", ts, ":", eMealVoucher.Code, ":", eMealVoucherDetail.IdNo);
|
||||
|
||||
var qrCode = QrCodeConstants.EMealVoucher + originData.ToArray().Select(x =>
|
||||
{
|
||||
var b = Encoding.ASCII.GetBytes(x.ToString());
|
||||
int i = b[0];
|
||||
return Convert.ToString(i);
|
||||
}).Join(string.Empty);
|
||||
|
||||
|
||||
await _dbContext.InsertAsync(new EMealVoucherDetailQrCodeEntity
|
||||
{
|
||||
Signature = signature,
|
||||
OriginData = originData,
|
||||
QrCode = qrCode
|
||||
});
|
||||
|
||||
return qrCode;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Pagination<BalanceRecordEMealVoucherResponse>> GetEMealVoucherPageAsync(BalanceRecordEMealVoucherPageRequest request)
|
||||
{
|
||||
var tenantId = _currentUser.GetStringTenantId();
|
||||
|
||||
return await _dbContext.Queryable<BalanceRecordEntity>()
|
||||
.LeftJoin<BusinessPlaceEntity>((x, bPlace) => x.BusinessPlaceCode == bPlace.Code)
|
||||
.LeftJoin<DepartmentEntity>((x, bPlace, department) => x.DepartmentNo == department.No)
|
||||
.Where(x => x.Status == BalanceRecordStatusEnumType.Valid && x.Type == BalanceRecordTypeEnumType.Out) //有效,消费数据
|
||||
.WhereIF(request.SearchDateTimePeriod.HasValue(), x => x.CostDate >= request.SearchDateTimePeriod.Start && x.CostDate <= request.SearchDateTimePeriod.End) //成本日期
|
||||
.Where(x => x.Source == BalanceRecordSourceEnumType.EMealVoucher)
|
||||
.Where(x => SqlFunc.Subqueryable<EMealVoucherEntity>().Where(p => p.Factory == tenantId).Where(p => p.Code == x.UserCode).Any() || x.TenantId == tenantId)
|
||||
.Select((x, bPlace, department) => new BalanceRecordEMealVoucherResponse
|
||||
{
|
||||
No = x.No,
|
||||
UserNo = x.UserNo,
|
||||
Name = x.Name,
|
||||
UserCode = x.UserCode,
|
||||
DepartmentNo = x.DepartmentNo,
|
||||
DepartmentName = department.Name,
|
||||
CostDate = x.CostDate,
|
||||
Remark = x.Remark,
|
||||
Source = x.Source,
|
||||
Type = x.Type,
|
||||
Amount = SqlFunc.Abs(x.Amount),
|
||||
BusinessPlaceName = bPlace.Name,
|
||||
ShiftType = x.ShiftType,
|
||||
DeviceInfo = x.DeviceUniqueNo,
|
||||
CostId = x.CostId,
|
||||
OriginTenantId = x.OriginTenantId,
|
||||
Status = x.Status,
|
||||
CostDateTime = x.CostDateTime,
|
||||
Factory = x.TenantId,
|
||||
Werks = x.Werks
|
||||
})
|
||||
.ToPageListAsync(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
|
||||
using System.Text;
|
||||
using Dlhis.Constants;
|
||||
using Dlhis.Entity.Canteen.Entities.Voucher;
|
||||
using Kurisu.AspNetCore.Authentication.Abstractions;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
|
||||
namespace Dlhis.Canteen.Voucher.Services.Implements;
|
||||
|
||||
public class VoucherQrCodeService : IVoucherQrCodeService
|
||||
{
|
||||
private readonly IDbContext _dbContext;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
|
||||
public VoucherQrCodeService(IDbContext dbContext, ICurrentUser currentUser)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> GetQrCodeAsync(string voucherNo, bool isNeedRefresh = false)
|
||||
{
|
||||
var userCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode);
|
||||
if (!await _dbContext.Queryable<VoucherUserInfoEntity>().Where(x => x.VoucherNo == voucherNo && x.UserCode == userCode).AnyAsync())
|
||||
{
|
||||
true.ThrowIfTrue("非法的消费券");
|
||||
}
|
||||
|
||||
var qrcodeInfo = await _dbContext.Queryable<VoucherQrCodeEntity>().SingleAsync(x => x.VoucherNo == voucherNo);
|
||||
|
||||
if (qrcodeInfo == null)
|
||||
{
|
||||
qrcodeInfo = new VoucherQrCodeEntity
|
||||
{
|
||||
VoucherNo = voucherNo,
|
||||
QrCode = GenerateQrCode(voucherNo)
|
||||
};
|
||||
|
||||
await _dbContext.InsertAsync(qrcodeInfo);
|
||||
return qrcodeInfo.QrCode;
|
||||
}
|
||||
|
||||
var now = DateTime.Now;
|
||||
if (qrcodeInfo.ModifiedTime.AddMinutes(1) >= now && !isNeedRefresh)
|
||||
{
|
||||
return qrcodeInfo.QrCode;
|
||||
}
|
||||
|
||||
qrcodeInfo.QrCode = GenerateQrCode(voucherNo);
|
||||
await _dbContext.UpdateAsync(qrcodeInfo);
|
||||
|
||||
return qrcodeInfo.QrCode;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// qrCode生成
|
||||
/// </summary>
|
||||
/// <param name="voucherNo"></param>
|
||||
/// <returns></returns>
|
||||
private static string GenerateQrCode(string voucherNo)
|
||||
{
|
||||
var ts = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
return QrCodeConstants.Birthday + voucherNo.ToArray().Select(x =>
|
||||
{
|
||||
var b = Encoding.ASCII.GetBytes(x.ToString());
|
||||
int i = b[0];
|
||||
return Convert.ToString(i);
|
||||
|
||||
}).Join(string.Empty) + ts;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user