diff --git a/Src/Dlhis.Canteen.Api/ITicketApi.cs b/Src/Dlhis.Canteen.Api/IVoucherApi.cs
similarity index 64%
rename from Src/Dlhis.Canteen.Api/ITicketApi.cs
rename to Src/Dlhis.Canteen.Api/IVoucherApi.cs
index 149b9826..3aabef3b 100644
--- a/Src/Dlhis.Canteen.Api/ITicketApi.cs
+++ b/Src/Dlhis.Canteen.Api/IVoucherApi.cs
@@ -4,13 +4,13 @@ namespace Dlhis.Canteen.Api;
[RequestResultHandler]
[EnableRemoteClient(Name = "canteen-service", BaseUrl = "${InternalRequest:CanteenRequestUrl}")]
-public interface ITicketApi
+public interface IVoucherApi
{
///
/// 创建券
///
///
- ///
- [Post("/api/tickets/{type}/create")]
- Task CreateAsync(string type);
+ /// s
+ [Post("/api/vouchers/birthday/create")]
+ Task CreateAsync(VoucherByBirthdayRequest request);
}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen.Api/VoucherByBirthdayRequest.cs b/Src/Dlhis.Canteen.Api/VoucherByBirthdayRequest.cs
new file mode 100644
index 00000000..e05df6d5
--- /dev/null
+++ b/Src/Dlhis.Canteen.Api/VoucherByBirthdayRequest.cs
@@ -0,0 +1,8 @@
+namespace Dlhis.Canteen.Api;
+
+public class VoucherByBirthdayRequest
+{
+ public DateTime Begin { get; set; }
+ public DateTime End { get; set; }
+ public string Remark { get; set; }
+}
diff --git a/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/BirthdayConsumeHandler.cs b/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/BirthdayConsumeHandler.cs
index dafafc7d..c00fd862 100644
--- a/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/BirthdayConsumeHandler.cs
+++ b/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/BirthdayConsumeHandler.cs
@@ -1,8 +1,10 @@
+using Dlhis.Basic.Api;
using Dlhis.Canteen.Order.Repository;
using Dlhis.Canteen.Order.Request;
using Dlhis.Canteen.Order.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Entities.Voucher;
using Dlhis.Entity.Canteen.Enums;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
@@ -22,64 +24,78 @@ public class BirthdayConsumeHandler : IConsumeHandler
private readonly IDbContext _dbContext;
private readonly IOrderCommonHandler _orderCommonHandler;
private readonly IOrderRepository _orderRepository;
+ private readonly IFactorySettingApi _factorySettingApi;
public BirthdayConsumeHandler(IDbContext dbContext,
IOrderCommonHandler orderCommonHandler,
- IOrderRepository orderRepository)
+ IOrderRepository orderRepository,
+ IFactorySettingApi factorySettingApi)
{
_dbContext = dbContext;
_orderCommonHandler = orderCommonHandler;
_orderRepository = orderRepository;
+ _factorySettingApi = factorySettingApi;
}
public async Task> ConsumeAsync(OrderAddRequest request, GainfoEntity gainfo)
{
var msg = string.Empty;
- var ticketNo = request.UserUniqueNo;
+ var qrCode = request.UserUniqueNo;
- var exists = await _dbContext.Queryable()
- .Where(x => x.Type == TicketEnumType.Birthday)
- .Where(x => x.QrCode == ticketNo)
- .AnyAsync();
-
- exists.ThrowIfFalse("生日券无效");
+ var voucherQrCode = await _dbContext.Queryable()
+ .LeftJoin((x, u) => x.VoucherNo == u.VoucherNo)
+ .Where(x => x.QrCode == qrCode)
+ .Select((x, u) => new
+ {
+ x.VoucherNo,
+ u.UserCode,
+ u.Factory
+ })
+ .SingleAsync();
+ voucherQrCode.ThrowIfNull("生日券无效");
try
{
var checkData = await _orderCommonHandler.PreCheckAsync(request.DeviceUniqueNo, request.CostDateTime!.Value);
- var isSupermarket = await _dbContext.Queryable()
+ var businessPlace = await _dbContext.Queryable()
.Where(x => x.Code == checkData.BusinessPlaceCode)
- .Select(x => x.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket)
+ //.Select(x => x.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket)
.SingleAsync();
+ businessPlace.ThrowIfNull("营业点不存在");
+ var isSupermarket = businessPlace.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket;
isSupermarket.ThrowIfFalse("请在超市消费");
+ var allowFactories = await _factorySettingApi.GetEnableUseBirthdayVoucherFactoriesAsync(voucherQrCode.Factory);
+ allowFactories.Contains(businessPlace.TenantId).ThrowIfFalse($"该厂区({businessPlace.TenantId})不可使用此生日券");
+
var order = await _orderRepository.CreateDeviceConsumeOrderAsync(checkData, request.Adapt(), gainfo);
await _orderCommonHandler.TryConsumeAsync(order.Id, async () =>
{
await CommonHelper.RetryAsync(async () =>
{
- var ticket = await _dbContext.Queryable()
- .Where(x => x.Type == TicketEnumType.Birthday)
- .Where(x => x.QrCode == ticketNo)
+ var voucher = await _dbContext.Queryable()
+ .Where(x => x.Type == VoucherEnumType.Birthday)
+ .Where(x => x.No == voucherQrCode.VoucherNo)
.SingleAsync();
//金额+-
- ticket.Balance += order.Amount;
- (ticket.Balance < 0).ThrowIfTrue("余额不足,无法消费");
+ voucher.Balance += order.Amount;
+ (voucher.Balance < 0).ThrowIfTrue("余额不足,无法消费");
- await _dbContext.Updateable()
- .SetColumns(x => x.Balance == ticket.Balance)
+ await _dbContext.Updateable()
+ .SetColumns(x => x.Balance == voucher.Balance)
.SetColumns(x => x.Version == x.Version + 1)
.SetColumns(x => x.ModifiedTime == DateTime.Now)
- .Where(x => x.QrCode == ticketNo && x.Version == ticket.Version) //必须与查询时的version一致
+ .Where(x => x.No == voucher.No && x.Version == voucher.Version) //必须与查询时的version一致
.ExecuteCommandThrowVersionAsync();
//写入记录
var balanceRecord = order.Adapt();
- balanceRecord.Remark = $"{ticket.QrCode}(生日券消费)";
+ balanceRecord.Remark = $"{voucher.No}(生日券消费)";
await _dbContext.InsertAsync(balanceRecord);
+
}, 5);
});
}
@@ -87,14 +103,15 @@ public class BirthdayConsumeHandler : IConsumeHandler
{
msg = ex.Message;
}
-
+
//获取餐券余额
- var data = await _dbContext.Queryable()
- .LeftJoin((x, ga) => x.UserCode == ga.Code)
- .Where(x => x.Type == TicketEnumType.Birthday && x.QrCode == ticketNo)
- .Select((x, ga) => new OrderResultResponse
+ var data = await _dbContext.Queryable()
+ .LeftJoin((x, u) => x.No == u.VoucherNo)
+ .LeftJoin((x, u, ga) => u.UserCode == ga.Code)
+ .Where(x => x.Type == VoucherEnumType.Birthday && x.No == voucherQrCode.VoucherNo)
+ .Select((x, u, ga) => new OrderResultResponse
{
- UserCode = x.UserCode,
+ UserCode = u.UserCode,
UserName = ga.Name,
CurrentBalance = x.Balance
})
diff --git a/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/EMealVoucherHandler.cs b/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/EMealVoucherHandler.cs
index 86140edf..fecf22f4 100644
--- a/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/EMealVoucherHandler.cs
+++ b/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/EMealVoucherHandler.cs
@@ -3,6 +3,7 @@ using Dlhis.Canteen.Order.Request;
using Dlhis.Canteen.Order.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Entities.EMealVoucher;
using Dlhis.Entity.Canteen.Enums;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
diff --git a/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/OrderCommonHandler.cs b/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/OrderCommonHandler.cs
index 08d5164e..9d300e37 100644
--- a/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/OrderCommonHandler.cs
+++ b/Src/Dlhis.Canteen/Order/Services/ConsumeHandlers/OrderCommonHandler.cs
@@ -8,6 +8,7 @@ using Dlhis.Entity.Device.Enums;
using Kurisu.AspNetCore.CustomClass;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
+using Microsoft.Extensions.Primitives;
namespace Dlhis.Canteen.Order.Services.ConsumeHandlers;
@@ -40,7 +41,8 @@ public class OrderCommonHandler : IOrderCommonHandler
{
try
{
- if (_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue("X-Requested-DeviceIp", out var ip))
+ StringValues ip = "";
+ if (_httpContextAccessor.HttpContext?.Request.Headers.TryGetValue("X-Requested-DeviceIp", out ip) == true)
{
var device = await _dbContext.Queryable().Where(x => x.UniqueNo == deviceNo).SingleAsync();
device.ConnectionInfo = new
diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
index d63c8e65..87bceaac 100644
--- a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
@@ -6,6 +6,7 @@ using Dlhis.Canteen.Setting.Services;
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 Dlhis.Entity.Device;
using Dlhis.Entity.Device.Entities;
diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
index 8d92bffa..2faf441f 100644
--- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
@@ -6,6 +6,8 @@ using Dlhis.Canteen.Setting.Services;
using Dlhis.Constants;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Entities.EMealVoucher;
+using Dlhis.Entity.Canteen.Entities.Voucher;
using Dlhis.Entity.Canteen.Enums;
using Dlhis.Entity.Device;
using Dlhis.Entity.Device.Entities;
@@ -160,27 +162,35 @@ public class OrderService : IOrderService
switch (flag)
{
case QrCodeConstants.User:
- {
- gainfo = await GetUserByQrCodeAsync(request.UserUniqueNo);
- await CheckPermissionAsync(gainfo.Code, request.DeviceUniqueNo);
- }
+ {
+ gainfo = await GetUserByQrCodeAsync(request.UserUniqueNo);
+ await CheckPermissionAsync(gainfo.Code, request.DeviceUniqueNo);
+ }
break;
case QrCodeConstants.EMealVoucher:
- {
- request.Source = BalanceRecordSourceEnumType.EMealVoucher;
- var eMealVoucherQrCode = await _dbContext.Queryable().Where(x => x.QrCode == request.UserUniqueNo).SingleAsync();
- eMealVoucherQrCode.ThrowIfNull("无法识别");
- var code = eMealVoucherQrCode.OriginData.Split(':')[2];
- gainfo = await _dbContext.Queryable().Where(x => x.Code == code).SingleAsync();
- }
+ {
+ request.Source = BalanceRecordSourceEnumType.EMealVoucher;
+ var eMealVoucherQrCode = await _dbContext.Queryable().Where(x => x.QrCode == request.UserUniqueNo).SingleAsync();
+ eMealVoucherQrCode.ThrowIfNull("无法识别");
+ var code = eMealVoucherQrCode.OriginData.Split(':')[2];
+ gainfo = await _dbContext.Queryable().Where(x => x.Code == code).SingleAsync();
+ }
break;
case QrCodeConstants.Birthday:
- {
- request.Source = BalanceRecordSourceEnumType.Birthday;
- var ticket = await _dbContext.Queryable().Where(x => x.Type == TicketEnumType.Birthday).Where(x => x.QrCode == request.UserUniqueNo).SingleAsync();
- ticket.ThrowIfNull("无法识别");
- gainfo = await _dbContext.Queryable().Where(x => x.Code == ticket.UserCode).SingleAsync();
- }
+ {
+ request.Source = BalanceRecordSourceEnumType.Birthday;
+ var qrcode = await _dbContext.Queryable()
+ .Where(x => x.QrCode == request.UserUniqueNo)
+ .SingleAsync();
+
+ qrcode.ThrowIfNull("券码无法识别");
+
+ var vourcher = await _dbContext.Queryable()
+ .Where(x => x.VoucherNo == qrcode.VoucherNo)
+ .SingleAsync();
+
+ gainfo = await _dbContext.Queryable().Where(x => x.Code == vourcher.UserCode).SingleAsync();
+ }
break;
default: throw new UserFriendlyException($"无法识别{request.UserUniqueNo}");
@@ -201,7 +211,7 @@ public class OrderService : IOrderService
//在线
if (!request.IsOffline)
{
- gainfo.ThrowIfNull("无法识别");
+ gainfo.ThrowIfNull("无法识别人员信息");
}
else
{
@@ -213,6 +223,7 @@ public class OrderService : IOrderService
.FirstAsync();
}
+ gainfo.ThrowIfNull("无法识别人员信息");
return gainfo;
}
@@ -292,7 +303,9 @@ public class OrderService : IOrderService
.Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo && x.BusinessPlaceCode.HasValue)
.Select((x, b, bs) => new
{
- b.Code, bs.ShiftCode, Factory = b.TenantId
+ b.Code,
+ bs.ShiftCode,
+ Factory = b.TenantId
})
.SingleAsync();
@@ -485,7 +498,7 @@ public class OrderService : IOrderService
return await _dbContext.Queryable().Where(x => x.Code == gainfoQrCode.UserCode).SingleAsync();
}
-
+
///
/// 检查是否能够进行离线消费,处理hpt重复提交
///
diff --git a/Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs b/Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs
deleted file mode 100644
index 9dfb8ae1..00000000
--- a/Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Dlhis.Canteen.Tickets.Request;
-using Dlhis.Canteen.Tickets.Response;
-using Dlhis.Canteen.Tickets.Services;
-using Kurisu.AspNetCore.DataAccess.Dto;
-using Kurisu.AspNetCore.Utils.Extensions;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-
-namespace Dlhis.Canteen.Tickets.Controllers;
-
-///
-/// 券
-///
-[Authorize]
-[Route("api/[controller]")]
-[ApiController]
-public class TicketsController : ControllerBase
-{
- private readonly INamedResolver _namedResolver;
-
- public TicketsController(INamedResolver namedResolver)
- {
- _namedResolver = namedResolver;
- }
-
- ///
- /// 获取分页数据(按券类型)
- ///
- ///
- ///
- [HttpGet("page")]
- public async Task> GetPageAsync(TicketPageRequest request)
- {
- return await _namedResolver.GetService(request.Type.ToString()).GetPageAsync(request);
- }
-
- ///
- /// 创建券
- ///
- /// 券类型,需要后端支持
- [AllowAnonymous]
- [HttpPost("{type:required}/create")]
- public async Task CreateAsync(string type)
- {
- var srv = _namedResolver.GetService(type);
- srv.ThrowIfNull("不支持的券类型");
-
- await srv.CreateAsync();
- }
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Tickets/Request/TicketPageRequest.cs b/Src/Dlhis.Canteen/Tickets/Request/TicketPageRequest.cs
deleted file mode 100644
index 02620a43..00000000
--- a/Src/Dlhis.Canteen/Tickets/Request/TicketPageRequest.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using Dlhis.Entity.Canteen.Enums;
-using Kurisu.AspNetCore.DataAccess.Dto;
-
-namespace Dlhis.Canteen.Tickets.Request;
-
-public class TicketPageRequest : PageDto
-{
- ///
- /// 类型
- ///
- [EnumDataType(typeof(TicketEnumType))]
- public TicketEnumType Type { get; set; }
-
- ///
- /// 工号
- ///
- public string UserCode { get; set; }
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Tickets/Services/IBirthdayTicketService.cs b/Src/Dlhis.Canteen/Tickets/Services/IBirthdayTicketService.cs
deleted file mode 100644
index 1b67cc3a..00000000
--- a/Src/Dlhis.Canteen/Tickets/Services/IBirthdayTicketService.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Dlhis.Canteen.Tickets.Services;
-
-public interface IBirthdayTicketService : ITicketService
-{
-
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Tickets/Services/ITicketService.cs b/Src/Dlhis.Canteen/Tickets/Services/ITicketService.cs
deleted file mode 100644
index bc8731f2..00000000
--- a/Src/Dlhis.Canteen/Tickets/Services/ITicketService.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Dlhis.Canteen.Tickets.Request;
-using Dlhis.Canteen.Tickets.Response;
-using Kurisu.AspNetCore.DataAccess.Dto;
-
-namespace Dlhis.Canteen.Tickets.Services;
-
-///
-/// 券
-///
-public interface ITicketService : IScopeDependency
-{
- ///
- /// 分页数据
- ///
- ///
- ///
- Task> GetPageAsync(TicketPageRequest request);
-
- ///
- /// 创建
- ///
- ///
- Task CreateAsync();
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Tickets/Services/Implements/BirthdayTicketService.cs b/Src/Dlhis.Canteen/Tickets/Services/Implements/BirthdayTicketService.cs
deleted file mode 100644
index 78bc5e07..00000000
--- a/Src/Dlhis.Canteen/Tickets/Services/Implements/BirthdayTicketService.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Text;
-using Dlhis.Constants;
-using Dlhis.Entity.Basic.Entity;
-using Dlhis.Entity.Canteen.Entities;
-using Dlhis.Entity.Canteen.Enums;
-using Kurisu.AspNetCore.DataAccess.Entity;
-using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
-using Kurisu.AspNetCore.Utils.Extensions;
-using SqlSugar;
-
-namespace Dlhis.Canteen.Tickets.Services.Implements;
-
-[Service(nameof(TicketEnumType.Birthday))]
-public class BirthdayTicketService : BaseTicketService, IBirthdayTicketService
-{
- ///
- public BirthdayTicketService(IDbContext dbContext) : base(dbContext)
- {
- }
-
- ///
- public override async Task CreateAsync()
- {
- await DbContext.IgnoreAsync(async () =>
- {
- var today = DateTime.Today;
- var userCodes = await DbContext.Queryable()
- .Where(x => SqlFunc.DateIsSame(SqlFunc.ToDate(x.Birthday), today, DateType.Day))
- .Select(x => new { x.Code, x.Factory })
- .ToListAsync();
-
- const decimal amount = 30;
- var todayStr = today.ToString("yyyy-MM-dd");
- foreach (var item in userCodes)
- {
- var qrCode = GetQrCode(item.Code + todayStr);
- if (!await DbContext.Queryable().Where(x => x.Type == TicketEnumType.Birthday && x.UserCode == item.Code && x.QrCode == qrCode).AnyAsync())
- {
- await DbContext.InsertAsync(new TicketEntity
- {
- Type = TicketEnumType.Birthday,
- UserCode = item.Code,
- OriginalBalance = amount,
- Balance = amount,
- QrCode = qrCode,
- Remark = todayStr + "生日券",
- TenantId = item.Factory
- });
- }
- }
- });
- }
-
- private static string GetQrCode(string data)
- {
- var qrCode = QrCodeConstants.Birthday + data.ToArray().Select(x =>
- {
- var b = Encoding.ASCII.GetBytes(x.ToString());
- int i = b[0];
- return Convert.ToString(i);
- }).Join(string.Empty);
-
- return qrCode;
- }
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Tickets/Services/Implements/TicketService.cs b/Src/Dlhis.Canteen/Tickets/Services/Implements/TicketService.cs
deleted file mode 100644
index 8af5da71..00000000
--- a/Src/Dlhis.Canteen/Tickets/Services/Implements/TicketService.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using Dlhis.Canteen.Tickets.Request;
-using Dlhis.Canteen.Tickets.Response;
-using Dlhis.Entity.Basic.Entity;
-using Dlhis.Entity.Canteen.Entities;
-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 BaseTicketService : ITicketService
-{
- protected IDbContext DbContext { get; set; }
-
- protected BaseTicketService(IDbContext dbContext)
- {
- DbContext = dbContext;
- }
-
- public async Task> GetPageAsync(TicketPageRequest request)
- {
- return await DbContext.Queryable()
- .LeftJoin((x, ga) => x.UserCode == ga.Code)
- .Where(x => x.Type == request.Type)
- .WhereIF(request.UserCode.IsPresent(), x => x.UserCode == request.UserCode)
- .Select((x, ga) => new TicketPageResponse { UserName = ga.Name }, true)
- .ToPageListAsync(request);
- }
-
- public abstract Task CreateAsync();
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Controllers/EMealVoucherController.cs b/Src/Dlhis.Canteen/Voucher/Controllers/EMealVoucherController.cs
similarity index 94%
rename from Src/Dlhis.Canteen/EMealVoucher/Controllers/EMealVoucherController.cs
rename to Src/Dlhis.Canteen/Voucher/Controllers/EMealVoucherController.cs
index 6a961cbb..1e8a8d04 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Controllers/EMealVoucherController.cs
+++ b/Src/Dlhis.Canteen/Voucher/Controllers/EMealVoucherController.cs
@@ -1,14 +1,14 @@
-using Dlhis.Canteen.EMealVoucher.Request;
-using Dlhis.Canteen.EMealVoucher.Response;
-using Dlhis.Canteen.EMealVoucher.Services;
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.EMealVoucher.Controllers;
+namespace Dlhis.Canteen.Voucher.Controllers;
[Authorize]
[Route("api/[controller]")]
diff --git a/Src/Dlhis.Canteen/Voucher/Controllers/VoucherQrCodesController.cs b/Src/Dlhis.Canteen/Voucher/Controllers/VoucherQrCodesController.cs
new file mode 100644
index 00000000..a608870a
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Controllers/VoucherQrCodesController.cs
@@ -0,0 +1,33 @@
+using Dlhis.Canteen.Voucher.Services;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Dlhis.Canteen.Voucher.Controllers;
+
+///
+/// 券二维码服务
+///
+[Authorize]
+[ApiController]
+[Route("api/[controller]")]
+public class VoucherQrCodesController : ControllerBase
+{
+ private readonly IVoucherQrCodeService _voucherQrCodeService;
+
+ public VoucherQrCodesController(IVoucherQrCodeService voucherQrCodeService)
+ {
+ _voucherQrCodeService = voucherQrCodeService;
+ }
+
+ ///
+ /// 获取二维码
+ ///
+ /// 券码
+ /// true:请求刷新
+ ///
+ [HttpGet]
+ public async Task GetQrCodeAsync(string voucherNo, bool isNeedRefresh = false)
+ {
+ return await _voucherQrCodeService.GetQrCodeAsync(voucherNo, isNeedRefresh);
+ }
+}
diff --git a/Src/Dlhis.Canteen/Voucher/Controllers/VouchersController.cs b/Src/Dlhis.Canteen/Voucher/Controllers/VouchersController.cs
new file mode 100644
index 00000000..6b905a26
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Controllers/VouchersController.cs
@@ -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;
+
+///
+/// 券
+///
+[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;
+ }
+
+ ///
+ /// 获取分页数据(按券类型)
+ ///
+ ///
+ ///
+ [HttpGet("page")]
+ public async Task> GetPageAsync([FromQuery] VoucherPageRequest request)
+ {
+ return await _namedResolver.GetService(request.Type.ToString() + "VoucherService").GetPageAsync(request);
+ }
+
+
+ ///
+ /// 获取我的分页数据(按券类型)(H5)
+ ///
+ ///
+ ///
+ [HttpGet("my")]
+ public async Task> GetMyPageAsync([FromQuery] VoucherPageRequest request)
+ {
+ var userCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode);
+ request.UserCode = userCode;
+ return await _namedResolver.GetService(request.Type.ToString()).GetPageAsync(request);
+ }
+
+
+ ///
+ /// 创建生日券
+ ///
+ ///
+ [AllowAnonymous]
+ [HttpPost("birthday/create")]
+ public async Task CreateBirthdayVoucherAsync(VoucherByBirthdayRequest request)
+ {
+ var srv = _namedResolver.GetService(VoucherEnumType.Birthday.ToString() + "VoucherService");
+ srv.ThrowIfNull("不支持的券类型");
+ await srv.CreateAsync(new Dictionary
+ {
+ ["userCodes"] = request.UserCodes,
+ ["begin"] = request.Begin,
+ ["end"] = request.End,
+ ["remark"] = request.Remark
+ });
+ }
+
+ ///
+ /// 餐券消费分页
+ ///
+ ///
+ ///
+ [HttpGet("balance/page")]
+ [IgnoreTenant]
+ public async Task> GetVoucherBalancePageAsync([FromQuery] VoucherBalancePageRequest request)
+ {
+ var srv = _namedResolver.GetService(request.Type.ToString() + "VoucherService");
+
+ return await srv.GetVoucherBalancePageAsync(request);
+ }
+
+ ///
+ /// 我的餐券消费分页(H5)
+ ///
+ ///
+ ///
+ [HttpGet("balance/my/page")]
+ [IgnoreTenant]
+ public async Task> GetMyVoucherBalancePageAsync([FromQuery] VoucherBalancePageRequest request)
+ {
+ var srv = _namedResolver.GetService(request.Type.ToString());
+ return await srv.GetVoucherBalancePageAsync(request);
+ }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Request/EMealVoucherPageRequest.cs b/Src/Dlhis.Canteen/Voucher/Requests/EMealVoucherPageRequest.cs
similarity index 92%
rename from Src/Dlhis.Canteen/EMealVoucher/Request/EMealVoucherPageRequest.cs
rename to Src/Dlhis.Canteen/Voucher/Requests/EMealVoucherPageRequest.cs
index 6dbcde84..4fe64f7a 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Request/EMealVoucherPageRequest.cs
+++ b/Src/Dlhis.Canteen/Voucher/Requests/EMealVoucherPageRequest.cs
@@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
using Kurisu.AspNetCore.CustomClass;
using Kurisu.AspNetCore.DataAccess.Dto;
-namespace Dlhis.Canteen.EMealVoucher.Request;
+namespace Dlhis.Canteen.Voucher.Requests;
public class EMealVoucherPageRequest : PageDto, IValidatableObject
{
diff --git a/Src/Dlhis.Canteen/Voucher/Requests/VoucherBalancePageRequest.cs b/Src/Dlhis.Canteen/Voucher/Requests/VoucherBalancePageRequest.cs
new file mode 100644
index 00000000..ec84c447
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Requests/VoucherBalancePageRequest.cs
@@ -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
+{
+ ///
+ /// 券类型 VoucherEnumType
+ ///
+ [EnumDataType(typeof(VoucherEnumType))]
+ public VoucherEnumType Type { get; set; }
+
+ public string UserCode { get; set; }
+
+ public DateTimePeriod SearchDateTimePeriod { get; set; }
+}
diff --git a/Src/Dlhis.Canteen/Voucher/Requests/VoucherByBirthdayRequest.cs b/Src/Dlhis.Canteen/Voucher/Requests/VoucherByBirthdayRequest.cs
new file mode 100644
index 00000000..3543653b
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Requests/VoucherByBirthdayRequest.cs
@@ -0,0 +1,28 @@
+
+using System.ComponentModel.DataAnnotations;
+
+namespace Dlhis.Basic.Vouchers.Request;
+
+public class VoucherByBirthdayRequest
+{
+ ///
+ /// 支持指定工号
+ ///
+ public List UserCodes { get; set; }
+
+ ///
+ /// 开始范围
+ ///
+ public DateTime Begin { get; set; }
+
+ ///
+ /// 结束范围
+ ///
+ public DateTime End { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [Required(ErrorMessage = "请填写备注")]
+ public string Remark { get; set; }
+}
diff --git a/Src/Dlhis.Canteen/Voucher/Requests/VoucherPageRequest.cs b/Src/Dlhis.Canteen/Voucher/Requests/VoucherPageRequest.cs
new file mode 100644
index 00000000..ff0dab33
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Requests/VoucherPageRequest.cs
@@ -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
+{
+ ///
+ /// 类型 VoucherEnumType
+ ///
+ [EnumDataType(typeof(VoucherEnumType))]
+ public VoucherEnumType Type { get; set; }
+
+ ///
+ /// 工号
+ ///
+ public string UserCode { get; set; }
+
+ ///
+ /// 查询日期区间
+ ///
+ public DateTimePeriod SearchDateTimePeriod { get; set; }
+
+ ///
+ /// 一级部门
+ ///
+ public string DepartmentNoFirst { get; set; }
+
+ ///
+ /// 二级部门
+ ///
+ public string DepartmentNoSecond { get; set; }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherDetailResponse.cs b/Src/Dlhis.Canteen/Voucher/Response/EMealVoucherDetailResponse.cs
similarity index 93%
rename from Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherDetailResponse.cs
rename to Src/Dlhis.Canteen/Voucher/Response/EMealVoucherDetailResponse.cs
index c185c7b2..b35b5cb8 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherDetailResponse.cs
+++ b/Src/Dlhis.Canteen/Voucher/Response/EMealVoucherDetailResponse.cs
@@ -1,4 +1,4 @@
-namespace Dlhis.Canteen.EMealVoucher.Response;
+namespace Dlhis.Canteen.Voucher.Response;
public class EMealVoucherDetailResponse
{
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherMyPageResponse.cs b/Src/Dlhis.Canteen/Voucher/Response/EMealVoucherMyPageResponse.cs
similarity index 81%
rename from Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherMyPageResponse.cs
rename to Src/Dlhis.Canteen/Voucher/Response/EMealVoucherMyPageResponse.cs
index 5769bbc0..0d222479 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherMyPageResponse.cs
+++ b/Src/Dlhis.Canteen/Voucher/Response/EMealVoucherMyPageResponse.cs
@@ -1,4 +1,4 @@
-namespace Dlhis.Canteen.EMealVoucher.Response;
+namespace Dlhis.Canteen.Voucher.Response;
public class EMealVoucherMyPageResponse
{
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherPageResponse.cs b/Src/Dlhis.Canteen/Voucher/Response/EMealVoucherPageResponse.cs
similarity index 94%
rename from Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherPageResponse.cs
rename to Src/Dlhis.Canteen/Voucher/Response/EMealVoucherPageResponse.cs
index 0cd8428d..b7085c88 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Response/EMealVoucherPageResponse.cs
+++ b/Src/Dlhis.Canteen/Voucher/Response/EMealVoucherPageResponse.cs
@@ -3,7 +3,7 @@ using Kurisu.AspNetCore.Utils.Extensions;
using Mapster.Utils;
using Newtonsoft.Json;
-namespace Dlhis.Canteen.EMealVoucher.Response;
+namespace Dlhis.Canteen.Voucher.Response;
public class EMealVoucherPageResponse
{
@@ -65,7 +65,7 @@ public class EMealVoucherPageResponse
{
get
{
- var a = CurrentShifts.ToObject>().Select(x => ((ShiftEnumType)(x * 10))).ToList();
+ var a = CurrentShifts.ToObject>().Select(x => (ShiftEnumType)(x * 10)).ToList();
return a.Select(x=>x.GetDescription()).ToList();
}
}
diff --git a/Src/Dlhis.Canteen/Voucher/Response/VoucherBalancePageResponse.cs b/Src/Dlhis.Canteen/Voucher/Response/VoucherBalancePageResponse.cs
new file mode 100644
index 00000000..bf975702
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Response/VoucherBalancePageResponse.cs
@@ -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; }
+
+ ///
+ /// 流水号
+ ///
+ public string No { get; set; }
+
+ ///
+ /// 档案号/QRCode
+ ///
+ public string UserNo { get; set; }
+
+ ///
+ /// 姓名
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 学工号
+ ///
+ public string UserCode { get; set; }
+
+ ///
+ /// 部门号
+ ///
+ public string DepartmentNo { get; set; }
+
+ ///
+ /// 部门
+ ///
+ public string DepartmentName { get; set; }
+
+ ///
+ /// 所属成本日期
+ ///
+ [JsonConverter(typeof(ToDateJsonConverter))]
+ public DateTime CostDate { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string Remark { get; set; }
+
+ ///
+ /// 来源
+ ///
+ public BalanceRecordSourceEnumType Source { get; set; }
+
+ ///
+ /// 消费识别来源
+ ///
+ public string SourceDesc => Source.GetDescription();
+
+ ///
+ /// 收入/支出
+ ///
+ public BalanceRecordTypeEnumType Type { get; set; }
+
+ public string TypeDesc => Type.GetDescription();
+
+ ///
+ /// 金额
+ ///
+ public decimal Amount { get; set; }
+
+ ///
+ /// 营业点
+ ///
+ public string BusinessPlaceName { get; set; }
+
+ ///
+ /// 餐次
+ ///
+ public ShiftEnumType? ShiftType { get; set; }
+
+ ///
+ /// 餐次
+ ///
+ public string ShiftTypeDesc => ShiftType?.GetDescription();
+
+ ///
+ /// 消费机器唯一信息
+ ///
+ public string DeviceInfo { get; set; }
+
+ ///
+ /// 成本中心
+ ///
+ public string CostId { get; set; }
+
+ ///
+ /// 消费者所在基地
+ ///
+ public string OriginTenantId { get; set; }
+
+ ///
+ /// 数据状态
+ ///
+ public BalanceRecordStatusEnumType Status { get; set; }
+
+ ///
+ /// 数据状态描述
+ ///
+ public string StatusDesc => Status.GetDescription();
+
+ ///
+ /// 记录产生时间
+ ///
+ public DateTime CostDateTime { get; set; }
+
+ ///
+ /// 厂区
+ ///
+ public string Factory { get; set; }
+
+ ///
+ /// 人事范围
+ ///
+ public string Werks { get; set; }
+}
diff --git a/Src/Dlhis.Canteen/Tickets/Response/TicketPageResponse.cs b/Src/Dlhis.Canteen/Voucher/Response/VoucherPageResponse.cs
similarity index 50%
rename from Src/Dlhis.Canteen/Tickets/Response/TicketPageResponse.cs
rename to Src/Dlhis.Canteen/Voucher/Response/VoucherPageResponse.cs
index b7be7bc6..a623c07e 100644
--- a/Src/Dlhis.Canteen/Tickets/Response/TicketPageResponse.cs
+++ b/Src/Dlhis.Canteen/Voucher/Response/VoucherPageResponse.cs
@@ -1,13 +1,13 @@
using Dlhis.Entity.Canteen.Enums;
-namespace Dlhis.Canteen.Tickets.Response;
+namespace Dlhis.Canteen.Voucher.Response;
-public class TicketPageResponse
+public class VoucherPageResponse
{
///
/// 券类型
///
- public TicketEnumType Type { get; set; }
+ public VoucherEnumType Type { get; set; }
///
/// 工号
@@ -30,12 +30,27 @@ public class TicketPageResponse
public decimal Amount { get; set; }
///
- /// 消费码
+ /// 描述
///
- public string QrCode { get; set; }
+ public string Description { get; set; }
///
/// 备注
///
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; }
}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Services/IEMealVoucherService.cs b/Src/Dlhis.Canteen/Voucher/Services/IEMealVoucherService.cs
similarity index 85%
rename from Src/Dlhis.Canteen/EMealVoucher/Services/IEMealVoucherService.cs
rename to Src/Dlhis.Canteen/Voucher/Services/IEMealVoucherService.cs
index 3c4fc174..7982fec0 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Services/IEMealVoucherService.cs
+++ b/Src/Dlhis.Canteen/Voucher/Services/IEMealVoucherService.cs
@@ -1,11 +1,11 @@
-using Dlhis.Canteen.EMealVoucher.Request;
-using Dlhis.Canteen.EMealVoucher.Response;
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.EMealVoucher.Services;
+namespace Dlhis.Canteen.Voucher.Services;
public interface IEMealVoucherService : IScopeDependency
{
diff --git a/Src/Dlhis.Canteen/Voucher/Services/IVoucherQrCodeService.cs b/Src/Dlhis.Canteen/Voucher/Services/IVoucherQrCodeService.cs
new file mode 100644
index 00000000..edbe47d4
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Services/IVoucherQrCodeService.cs
@@ -0,0 +1,13 @@
+namespace Dlhis.Canteen.Voucher.Services;
+
+public interface IVoucherQrCodeService
+{
+
+ ///
+ /// 获取二维码
+ ///
+ ///
+ ///
+ ///
+ Task GetQrCodeAsync(string voucherNo, bool isNeedRefresh = false);
+}
diff --git a/Src/Dlhis.Canteen/Voucher/Services/IVoucherService.cs b/Src/Dlhis.Canteen/Voucher/Services/IVoucherService.cs
new file mode 100644
index 00000000..1ad09b15
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Services/IVoucherService.cs
@@ -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;
+
+///
+/// 券
+///
+public interface IVoucherService : IScopeDependency
+{
+ ///
+ /// 分页数据
+ ///
+ ///
+ ///
+ Task> GetPageAsync(VoucherPageRequest request);
+
+ ///
+ /// 创建
+ ///
+ ///
+ Task CreateAsync(Dictionary pairs);
+
+
+ Task> GetVoucherBalancePageAsync(VoucherBalancePageRequest request);
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Voucher/Services/Implements/BaseVoucherService.cs b/Src/Dlhis.Canteen/Voucher/Services/Implements/BaseVoucherService.cs
new file mode 100644
index 00000000..e0222840
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Services/Implements/BaseVoucherService.cs
@@ -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> GetPageAsync(VoucherPageRequest request)
+ {
+ var pagination = await DbContext.Queryable()
+ .LeftJoin((x, u) => x.No == u.VoucherNo)
+ .LeftJoin((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
+ {
+ x.DepartmentNo,
+ x.DepartmentNoFirst,
+ x.DepartmentNoSecond
+ };
+ }).Distinct().ToList();
+
+ var departments = await DbContext.Queryable().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 pairs);
+ public abstract Task> GetVoucherBalancePageAsync(VoucherBalancePageRequest request);
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Voucher/Services/Implements/BirthdayVoucherService.cs b/Src/Dlhis.Canteen/Voucher/Services/Implements/BirthdayVoucherService.cs
new file mode 100644
index 00000000..e878e34e
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Services/Implements/BirthdayVoucherService.cs
@@ -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;
+
+ ///
+ public BirthdayVoucherService(IDbContext dbContext, IFactorySettingApi factorySettingApi) : base(dbContext)
+ {
+ _factorySettingApi = factorySettingApi;
+ }
+
+ ///
+ public override async Task CreateAsync(Dictionary 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 : new List();
+
+ //忽略tenant操作
+ await DbContext.IgnoreAsync(async () =>
+ {
+ var gainfos = await GetGainfosAsync(userCodes, p.begin, p.end);
+ var departmentNos = gainfos.Select(g => g.DepartmentNo).Distinct().ToList();
+ var departmentInfos = await DbContext.Queryable()
+ .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 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()
+ .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 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> GetGainfosAsync(List 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()
+ .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);
+ }
+
+ ///
+ /// 计算给定生日在区间 [begin, end] 内出现的所有年份(可能为0、1或多个)。
+ /// - 对于每个候选年份构造安全的日期(处理 2/29 在非闰年的情况,退到当年最大天数)。
+ /// - 若区间内找不到匹配年份,则返回包含 begin.Year 的单元素列表作为兜底行为,保持向后兼容。
+ ///
+ private static List GetBirthdayYears(DateTime birthday, DateTime begin, DateTime end)
+ {
+ var years = new List();
+
+ // 扩展范围到 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> GetVoucherBalancePageAsync(VoucherBalancePageRequest request)
+ {
+ return await DbContext.Queryable()
+ .LeftJoin((x, bPlace) => x.BusinessPlaceCode == bPlace.Code)
+ .LeftJoin((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);
+ }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs b/Src/Dlhis.Canteen/Voucher/Services/Implements/EMealVoucherService.cs
similarity index 97%
rename from Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs
rename to Src/Dlhis.Canteen/Voucher/Services/Implements/EMealVoucherService.cs
index 9bb4b838..7c3cf576 100644
--- a/Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs
+++ b/Src/Dlhis.Canteen/Voucher/Services/Implements/EMealVoucherService.cs
@@ -1,11 +1,12 @@
using System.Text;
-using Dlhis.Canteen.EMealVoucher.Request;
-using Dlhis.Canteen.EMealVoucher.Response;
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;
@@ -15,7 +16,7 @@ using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
using SqlSugar;
-namespace Dlhis.Canteen.EMealVoucher.Services.Implements;
+namespace Dlhis.Canteen.Voucher.Services.Implements;
public class EMealVoucherService : IEMealVoucherService
{
diff --git a/Src/Dlhis.Canteen/Voucher/Services/Implements/VoucherQrCodeService.cs b/Src/Dlhis.Canteen/Voucher/Services/Implements/VoucherQrCodeService.cs
new file mode 100644
index 00000000..7b2fb713
--- /dev/null
+++ b/Src/Dlhis.Canteen/Voucher/Services/Implements/VoucherQrCodeService.cs
@@ -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 GetQrCodeAsync(string voucherNo, bool isNeedRefresh = false)
+ {
+ var userCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode);
+ if (!await _dbContext.Queryable().Where(x => x.VoucherNo == voucherNo && x.UserCode == userCode).AnyAsync())
+ {
+ true.ThrowIfTrue("非法的消费券");
+ }
+
+ var qrcodeInfo = await _dbContext.Queryable().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;
+ }
+
+
+ ///
+ /// qrCode生成
+ ///
+ ///
+ ///
+ 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;
+ }
+}
diff --git a/Src/Dlhis.Entity/Basic/Entity/DepartmentEntity.cs b/Src/Dlhis.Entity/Basic/Entity/DepartmentEntity.cs
index 270793d5..a177074c 100644
--- a/Src/Dlhis.Entity/Basic/Entity/DepartmentEntity.cs
+++ b/Src/Dlhis.Entity/Basic/Entity/DepartmentEntity.cs
@@ -26,5 +26,17 @@ namespace Dlhis.Entity.Basic.Entity
///
[SugarColumn(IsNullable = false, ColumnDescription = "部门名称")]
public string Name { get; set; }
+
+ ///
+ /// 部门编码
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "一级部门编码")]
+ public string DepartmentNoFirst { get; set; }
+
+ ///
+ /// 部门编码
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "二级部门编码")]
+ public string DepartmentNoSecond { get; set; }
}
}
\ No newline at end of file
diff --git a/Src/Dlhis.Entity/Basic/Entity/OutsourceWhiteListEntity.cs b/Src/Dlhis.Entity/Basic/Entity/OutsourceWhiteListEntity.cs
new file mode 100644
index 00000000..4c6cd27a
--- /dev/null
+++ b/Src/Dlhis.Entity/Basic/Entity/OutsourceWhiteListEntity.cs
@@ -0,0 +1,13 @@
+using Kurisu.AspNetCore.DataAccess.Entity;
+using Kurisu.AspNetCore.DataAccess.SqlSugar;
+using SqlSugar;
+
+namespace Dlhis.Entity.Basic.Entity;
+
+
+[SugarTable(TableName = "OutsourceWhiteList", TableDescription = "外包人员白名单")]
+public class OutsourceWhiteListEntity : SugarBaseEntity, ISoftDeleted
+{
+ public string UserCode { get; set; }
+ public bool IsDeleted { get; set; }
+}
diff --git a/Src/Dlhis.Entity/Canteen/Entities/EMealVoucherDetailEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherDetailEntity.cs
similarity index 97%
rename from Src/Dlhis.Entity/Canteen/Entities/EMealVoucherDetailEntity.cs
rename to Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherDetailEntity.cs
index 52816945..2a9b8d2d 100644
--- a/Src/Dlhis.Entity/Canteen/Entities/EMealVoucherDetailEntity.cs
+++ b/Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherDetailEntity.cs
@@ -2,7 +2,7 @@
using Kurisu.AspNetCore.DataAccess.SqlSugar;
using SqlSugar;
-namespace Dlhis.Entity.Canteen.Entities;
+namespace Dlhis.Entity.Canteen.Entities.EMealVoucher;
///
/// 电子餐券明细
diff --git a/Src/Dlhis.Entity/Canteen/Entities/EMealVoucherDetailQrCodeEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherDetailQrCodeEntity.cs
similarity index 94%
rename from Src/Dlhis.Entity/Canteen/Entities/EMealVoucherDetailQrCodeEntity.cs
rename to Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherDetailQrCodeEntity.cs
index b1a6b505..1f0216a8 100644
--- a/Src/Dlhis.Entity/Canteen/Entities/EMealVoucherDetailQrCodeEntity.cs
+++ b/Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherDetailQrCodeEntity.cs
@@ -1,7 +1,7 @@
using Kurisu.AspNetCore.DataAccess.SqlSugar;
using SqlSugar;
-namespace Dlhis.Entity.Canteen.Entities;
+namespace Dlhis.Entity.Canteen.Entities.EMealVoucher;
///
/// 电子餐券明细QrCode
diff --git a/Src/Dlhis.Entity/Canteen/Entities/EMealVoucherEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherEntity.cs
similarity index 97%
rename from Src/Dlhis.Entity/Canteen/Entities/EMealVoucherEntity.cs
rename to Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherEntity.cs
index e015507c..c7d3b875 100644
--- a/Src/Dlhis.Entity/Canteen/Entities/EMealVoucherEntity.cs
+++ b/Src/Dlhis.Entity/Canteen/Entities/EMealVoucher/EMealVoucherEntity.cs
@@ -2,7 +2,7 @@
using Kurisu.AspNetCore.DataAccess.SqlSugar;
using SqlSugar;
-namespace Dlhis.Entity.Canteen.Entities;
+namespace Dlhis.Entity.Canteen.Entities.EMealVoucher;
///
/// 餐券
diff --git a/Src/Dlhis.Entity/Canteen/Entities/UserBalanceTmpEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/UserBalanceTmpEntity.cs
deleted file mode 100644
index 1fb925ec..00000000
--- a/Src/Dlhis.Entity/Canteen/Entities/UserBalanceTmpEntity.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using Kurisu.AspNetCore.DataAccess.Entity;
-using Kurisu.AspNetCore.DataAccess.SqlSugar;
-using SqlSugar;
-
-namespace Dlhis.Entity.Canteen.Entities;
-
-///
-/// 用户余额表
-///
-[SugarTable(TableName = "UserBalanceTmp", TableDescription = "用户余额表")]
-public class UserBalanceTmpEntity : SugarBaseEntity, IVersion
-{
- ///
- /// 学工号
- ///
- [SugarColumn(IsNullable = false, ColumnDescription = "学工号", UniqueGroupNameList = new[] { "idx_UserBalances_useCode" })]
- public string UserCode { get; set; }
-
- ///
- /// 余额
- ///
- [SugarColumn(IsNullable = false, ColumnDescription = "余额")]
- public decimal Balance { get; set; }
-
-
- [SugarColumn(IsNullable = false)]
- public int Version { get; set; }
-}
\ No newline at end of file
diff --git a/Src/Dlhis.Entity/Canteen/Entities/UserBalanceUploadRecordEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/UserBalanceUploadRecordEntity.cs
new file mode 100644
index 00000000..7d81c52e
--- /dev/null
+++ b/Src/Dlhis.Entity/Canteen/Entities/UserBalanceUploadRecordEntity.cs
@@ -0,0 +1,35 @@
+using Kurisu.AspNetCore.DataAccess.SqlSugar;
+using SqlSugar;
+
+namespace Dlhis.Entity.Canteen.Entities;
+
+///
+/// 用户消费上传记录表
+///
+[SugarTable(TableName = "UserBalanceUploadRecords", TableDescription = "用户消费上传记录表")]
+public class UserBalanceUploadRecordEntity : SugarBaseEntity
+{
+ ///
+ /// 年份
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "年份")]
+ public int Year { get; set; }
+
+ ///
+ /// 月份
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "月份")]
+ public int Month { get; set; }
+
+ ///
+ /// 学工号
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "学工号", UniqueGroupNameList = new[] { "idx_UserBalances_useCode" })]
+ public string UserCode { get; set; }
+
+ ///
+ /// 消费
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "余额")]
+ public decimal Cost { get; set; }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherEntity.cs
similarity index 64%
rename from Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs
rename to Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherEntity.cs
index 451b7ba4..1ae1af6b 100644
--- a/Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs
+++ b/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherEntity.cs
@@ -4,25 +4,30 @@ using Kurisu.AspNetCore.DataAccess.SqlSugar;
using SqlSugar;
using SqlSugar.DbConvert;
-namespace Dlhis.Entity.Canteen.Entities;
+namespace Dlhis.Entity.Canteen.Entities.Voucher;
///
/// 券
///
-[SugarTable("Tickets", TableDescription = "券")]
-public class TicketEntity : SugarBaseEntity, ITenantId, IVersion
+[SugarTable("Vouchers", TableDescription = "券")]
+public class VoucherEntity : SugarBaseEntity, IVersion
{
+ ///
+ /// 券唯一标识
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "券唯一标识")]
+ public string No { get; set; }
+
+ ///
+ /// 获取日期时间
+ ///
+ public DateTime ClaimDateTime { get; set; }
+
///
/// 类型
///
[SugarColumn(IsNullable = false, ColumnDataType = "varchar(50)", ColumnDescription = "券类型", SqlParameterDbType = typeof(EnumToStringConvert))]
- public TicketEnumType Type { get; set; }
-
- ///
- /// 工号
- ///
- [SugarColumn(IsNullable = false, ColumnDescription = "工号")]
- public string UserCode { get; set; }
+ public VoucherEnumType Type { get; set; }
///
/// 初始余额
@@ -37,10 +42,10 @@ public class TicketEntity : SugarBaseEntity, ITenantId, IVersion
public decimal Balance { get; set; }
///
- /// 消费码
+ /// 描述
///
- [SugarColumn(IsNullable = false, ColumnDescription = "消费码")]
- public string QrCode { get; set; }
+ [SugarColumn(IsNullable = true, ColumnDescription = "描述")]
+ public string Description { get; set; }
///
/// 备注
@@ -48,8 +53,5 @@ public class TicketEntity : SugarBaseEntity, ITenantId, IVersion
[SugarColumn(IsNullable = true, ColumnDescription = "备注")]
public string Remark { get; set; }
- public string TenantId { get; set; }
-
- ///
public int Version { get; set; }
}
\ No newline at end of file
diff --git a/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherQrCodeEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherQrCodeEntity.cs
new file mode 100644
index 00000000..12fa83c8
--- /dev/null
+++ b/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherQrCodeEntity.cs
@@ -0,0 +1,20 @@
+using Kurisu.AspNetCore.DataAccess.SqlSugar;
+using SqlSugar;
+
+namespace Dlhis.Entity.Canteen.Entities.Voucher;
+
+[SugarTable(TableName = "VoucherQrCodes")]
+public class VoucherQrCodeEntity : SugarBaseEntity
+{
+ ///
+ /// 券No
+ ///
+ [SugarColumn(ColumnDescription = "券No")]
+ public string VoucherNo { get; set; }
+
+ ///
+ /// 二维码
+ ///
+ [SugarColumn(ColumnDescription = "二维码", UniqueGroupNameList = new[] { "idx_EMealVoucherDetailQrCode_qrcode" })]
+ public string QrCode { get; set; }
+}
diff --git a/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherUserInfoEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherUserInfoEntity.cs
new file mode 100644
index 00000000..54874fc7
--- /dev/null
+++ b/Src/Dlhis.Entity/Canteen/Entities/Voucher/VoucherUserInfoEntity.cs
@@ -0,0 +1,63 @@
+using Kurisu.AspNetCore.DataAccess.SqlSugar;
+using SqlSugar;
+
+namespace Dlhis.Entity.Canteen.Entities.Voucher;
+
+///
+/// 券发放时候关联的用户信息
+///
+[SugarTable(TableName = "VoucherUserInfos")]
+public class VoucherUserInfoEntity : SugarBaseEntity
+{
+ ///
+ /// 券码
+ ///
+ [SugarColumn(IsNullable = false)]
+ public string VoucherNo { get; set; }
+
+ ///
+ /// 工号
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "工号")]
+ public string UserCode { get; set; }
+
+ ///
+ /// 成本中心
+ ///
+ [SugarColumn(IsNullable = false)]
+ public string CostId { get; set; }
+
+ ///
+ /// 人事范围
+ ///
+ [SugarColumn(IsNullable = false)]
+ public string Werks { get; set; }
+
+ ///
+ /// 厂区
+ ///
+ [SugarColumn(IsNullable = false)]
+ public string Factory { get; set; }
+
+ ///
+ /// 当前部门
+ ///
+ [SugarColumn(IsNullable = false)]
+ public string DepartmentNo { get; set; }
+
+ ///
+ /// 一级部门
+ ///
+ [SugarColumn(IsNullable = false)]
+ public string DepartmentNoFirst { get; set; }
+
+ ///
+ /// 二级部门
+ ///
+ [SugarColumn(IsNullable = true)]
+ public string DepartmentNoSecond { get; set; }
+
+
+ [SugarColumn(IsNullable = true, ColumnDataType = "varchar(255)")]
+ public string Signature { get; set; }
+}
diff --git a/Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs b/Src/Dlhis.Entity/Canteen/Enums/VoucherEnumType.cs
similarity index 89%
rename from Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs
rename to Src/Dlhis.Entity/Canteen/Enums/VoucherEnumType.cs
index 3df284e2..36e69470 100644
--- a/Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs
+++ b/Src/Dlhis.Entity/Canteen/Enums/VoucherEnumType.cs
@@ -6,7 +6,7 @@ namespace Dlhis.Entity.Canteen.Enums;
/// 券类型
///
[Description("券类型")]
-public enum TicketEnumType
+public enum VoucherEnumType
{
///
/// 生日券
diff --git a/Src/Dlhis.Entity/Device/Entities/DevicePermissionManuallyEntity.cs b/Src/Dlhis.Entity/Device/Entities/DevicePermissionManuallyEntity.cs
index 5a27d65d..df67a7b6 100644
--- a/Src/Dlhis.Entity/Device/Entities/DevicePermissionManuallyEntity.cs
+++ b/Src/Dlhis.Entity/Device/Entities/DevicePermissionManuallyEntity.cs
@@ -9,19 +9,23 @@ namespace Dlhis.Entity.Device.Entities;
/// 设备权限(手动)
///
[SugarTable(TableName = "DevicePermissionManually")]
-public class DevicePermissionManuallyEntity : SugarBaseEntity, ISoftDeleted , ITenantId
+public class DevicePermissionManuallyEntity : SugarBaseEntity, ISoftDeleted, ITenantId
{
[DeviceCode]
[SugarColumn(IsNullable = false)]
public Guid DeviceCode { get; set; }
-
+
[SugarColumn(IsNullable = false)]
public string UserNo { get; set; }
-
-
+
+ ///
+ /// 有效时间
+ ///
+ [SugarColumn(IsNullable = true)]
+ public DateTime? ValidDateTime { get; set; }
+
public bool IsDeleted { get; set; }
-
-
+
public string TenantId { get; set; }
}
\ No newline at end of file
diff --git a/Src/Dlhis.Entity/Sys/Entities/FactorySettingEntity.cs b/Src/Dlhis.Entity/Sys/Entities/FactorySettingEntity.cs
index b30049fc..0e1b02cf 100644
--- a/Src/Dlhis.Entity/Sys/Entities/FactorySettingEntity.cs
+++ b/Src/Dlhis.Entity/Sys/Entities/FactorySettingEntity.cs
@@ -49,5 +49,17 @@ public class FactorySettingEntity : SugarBaseEntity, ITenantId
[SugarColumn(IsNullable = true, ColumnDataType = "time", ColumnDescription = "工作网格编辑限制时间")]
public TimeOnly? WorkGridSetLimit { get; set; }
+ ///
+ /// 是否启用生日电子餐券
+ ///
+ [SugarColumn(ColumnDataType = "bit", ColumnDescription = "是否启用生日电子餐券", DefaultValue = "0")]
+ public bool EnableBirthdayVoucher { get; set; }
+
+ ///
+ /// 允许消费的厂区
+ ///
+ [SugarColumn(ColumnDescription = "允许消费的厂区")]
+ public string EnableUseBirthdayVoucherFactories { get; set; }
+
public string TenantId { get; set; }
}
\ No newline at end of file
diff --git a/Src/Dlhis.External/EMealVoucher/Services/Implements/EMealVoucherService.cs b/Src/Dlhis.External/EMealVoucher/Services/Implements/EMealVoucherService.cs
index 27c4a930..a5f8d488 100644
--- a/Src/Dlhis.External/EMealVoucher/Services/Implements/EMealVoucherService.cs
+++ b/Src/Dlhis.External/EMealVoucher/Services/Implements/EMealVoucherService.cs
@@ -1,5 +1,5 @@
using Dlhis.Entity.Basic.Entity;
-using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Entities.EMealVoucher;
using Dlhis.Entity.Canteen.Enums;
using Dlhis.External.EMealVoucher.Request;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
diff --git a/Src/Dlhis.External/OpenApi/Controllers/CanteenController.cs b/Src/Dlhis.External/OpenApi/Controllers/CanteenController.cs
index 4d4ff92f..1f79d274 100644
--- a/Src/Dlhis.External/OpenApi/Controllers/CanteenController.cs
+++ b/Src/Dlhis.External/OpenApi/Controllers/CanteenController.cs
@@ -1,5 +1,6 @@
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Entities.EMealVoucher;
using Dlhis.Entity.Canteen.Enums;
using Dlhis.External.OpenApi.Response;
using Kurisu.AspNetCore.CustomClass;
diff --git a/Src/Dlhis.Jip.Api/Dto/SapOrganizationItem.cs b/Src/Dlhis.Jip.Api/Dto/SapOrganizationItem.cs
index 1f8d6ce3..f3535a3b 100644
--- a/Src/Dlhis.Jip.Api/Dto/SapOrganizationItem.cs
+++ b/Src/Dlhis.Jip.Api/Dto/SapOrganizationItem.cs
@@ -41,6 +41,37 @@ public class SapOrganizationItem
/// 事业部
///
public string ORGID02 { get; set; }
+
+ ///
+ /// 一级部分
+ ///
+ public string ORGID03 { get; set; }
+
+ ///
+ /// 二级部门
+ ///
+ public string ORGID04 { get; set; }
+
+
+ ///
+ /// 三级部门
+ ///
+ public string ORGID05 { get; set; }
+
+ ///
+ /// 四级部门
+ ///
+ public string ORGID06 { get; set; }
+
+ ///
+ /// 五级部门
+ ///
+ public string ORGID07 { get; set; }
+
+ ///
+ /// 六级部门
+ ///
+ public string ORGID08 { get; set; }
}
diff --git a/Src/Dlhis.Jip.Api/IJinkoJipApi.cs b/Src/Dlhis.Jip.Api/IJinkoJipApi.cs
index 23214f21..b0311737 100644
--- a/Src/Dlhis.Jip.Api/IJinkoJipApi.cs
+++ b/Src/Dlhis.Jip.Api/IJinkoJipApi.cs
@@ -86,4 +86,14 @@ public interface IJinkoJipApi
[RequestLog]
[Post("/JIP/HCM/HCM_I_SHIFTREP")]
Task SyncWorkShiftAsync(SyncWorkShiftRequest request);
+
+
+ ///
+ /// 费用上传
+ ///
+ ///
+ ///
+ [RequestLog]
+ [Post("/JIP/HCM/HCM_0015_INSERT")]
+ Task UploadCostAsync(UploadCostRequest request);
}
\ No newline at end of file
diff --git a/Src/Dlhis.Jip.Api/Requests/UploadCostRequest.cs b/Src/Dlhis.Jip.Api/Requests/UploadCostRequest.cs
new file mode 100644
index 00000000..5ea54df2
--- /dev/null
+++ b/Src/Dlhis.Jip.Api/Requests/UploadCostRequest.cs
@@ -0,0 +1,39 @@
+
+
+using Newtonsoft.Json;
+
+namespace Dlhis.Jip.Api.Requests;
+
+public class UploadCostRequest
+{
+ [JsonProperty("T_DATA")]
+ public List Data { get; set; }
+}
+
+
+public class UploadCostItemRequest
+{
+ ///
+ /// 工号 可选,为空则删除日期下的所有记录
+ ///
+ [JsonProperty("ZWORKCODE")]
+ public string WorkCode { get; set; }
+
+ ///
+ /// 子信息类型 9020 水费扣减(上饶),9021 冷水扣减(上饶),9022 热水扣减(上饶), 2086餐卡消费金额 , 2088生日券发放金额、2089生日券消费金额
+ ///
+ [JsonProperty("SUBTY")]
+ public string Code { get; set; }
+
+ ///
+ /// 开始日期
+ ///
+ [JsonProperty("BEGDA")]
+ public string BeginDate { get; set; }
+
+ ///
+ /// 工资项金额
+ ///
+ [JsonProperty("BETRG")]
+ public decimal Charge { get; set; }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Jip.Api/Responses/UploadCostResponse.cs b/Src/Dlhis.Jip.Api/Responses/UploadCostResponse.cs
new file mode 100644
index 00000000..49c3c42b
--- /dev/null
+++ b/Src/Dlhis.Jip.Api/Responses/UploadCostResponse.cs
@@ -0,0 +1,47 @@
+
+using Newtonsoft.Json;
+
+namespace Dlhis.Jip.Api.Responses;
+
+public class UploadCostResponse
+{
+ [JsonProperty("T_DATA")]
+ public List Data { get; set; }
+}
+
+public class UploadCostItemResponse
+{
+ [JsonProperty("ZWORKCODE")]
+ public string WorkCode { get; set; }
+
+ ///
+ /// 子信息类型 9020 水费扣减(上饶),9021 冷水扣减(上饶),9022 热水扣减(上饶)
+ ///
+ [JsonProperty("SUBTY")]
+ public string Code { get; set; }
+
+ ///
+ /// 开始日期
+ ///
+ [JsonProperty("BEGDA")]
+ public string BeginDate { get; set; }
+
+ ///
+ /// 工资项金额
+ ///
+ [JsonProperty("BETRG")]
+ public decimal Price { get; set; }
+
+
+ ///
+ /// S 成功
+ ///
+ [JsonProperty("MSGTY")]
+ public string Success { get; set; }
+
+ ///
+ /// 响应消息
+ ///
+ [JsonProperty("MSGTX")]
+ public string Message { get; set; }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.ScheduledTask/Attributes/RecurringJobAttribute.cs b/Src/Dlhis.ScheduledTask/Attributes/RecurringJobAttribute.cs
index 9db34804..9d8a9c46 100644
--- a/Src/Dlhis.ScheduledTask/Attributes/RecurringJobAttribute.cs
+++ b/Src/Dlhis.ScheduledTask/Attributes/RecurringJobAttribute.cs
@@ -11,12 +11,10 @@ public class RecurringJobAttribute : Attribute
///
/// 任务的唯一标识符。
/// Cron 表达式,定义任务的执行计划。
- /// 是否在开发环境中运行。
- public RecurringJobAttribute(string uniqueJobKey, string cron, bool runOnDevelopment = false)
+ public RecurringJobAttribute(string uniqueJobKey, string cron)
{
UniqueJobKey = uniqueJobKey;
Cron = cron;
- RunOnDevelopment = runOnDevelopment;
}
///
@@ -37,7 +35,7 @@ public class RecurringJobAttribute : Attribute
///
/// 是否在开发环境中运行。
///
- public bool RunOnDevelopment { get; }
+ public bool RunOnDevelopment { get; set; } = false;
///
/// 任务所属队列,默认为 "default"。
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs
index 91df64bb..82e1b273 100644
--- a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs
@@ -36,6 +36,11 @@ public class DeviceUploadLogsController : ControllerBase
return await _deviceUploadLogService.GetPageAsync(request);
}
+ ///
+ /// 查询用户的上传记录分页
+ ///
+ ///
+ ///
[HttpGet("userpage")]
public async Task> GetUserPageAsync([FromQuery] DeviceUploadLogUserPageRequest request)
{
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
index d43f0938..936559ec 100644
--- a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
@@ -238,13 +238,13 @@ public class DeviceUploadLogService : IDeviceUploadLogService
{
try
{
- await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
+ await _dingTalkApi.SendWorkMessageByWorkGridAsync(new JinkoSendWorkMessageRequest
{
Content = $"{workGridInfo.WorkGrid.WorkGridName}的网格长,你好,检测到你网格中 {currentGainfo.Name}({currentGainfo.Code}){request.RaiseDateTime.ToString("yyyy年MM月dd日")}未排班,但是有考勤记录,请前往系统处理!",
WorkCodes = new List { workGridInfo.WorkGrid.LeaderUserCode }
});
- await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
+ await _dingTalkApi.SendWorkMessageByWorkGridAsync(new JinkoSendWorkMessageRequest
{
Content = $"{currentGainfo.Name}({currentGainfo.Code},检测到你在{workGridInfo.WorkGrid.WorkGridName}网格中,当日未排班,考勤记录不生效,请立即联系网格长",
WorkCodes = new List { currentGainfo.Code }
diff --git a/Src/Dlhis.ScheduledTask/Jobs/CostUploadJob.cs b/Src/Dlhis.ScheduledTask/Jobs/CostUploadJob.cs
new file mode 100644
index 00000000..6695974e
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/Jobs/CostUploadJob.cs
@@ -0,0 +1,84 @@
+using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Enums;
+using Dlhis.Jip.Api;
+using Dlhis.Jip.Api.Requests;
+using Dlhis.ScheduledTask.Attributes;
+using SqlSugar;
+
+namespace Dlhis.ScheduledTask.Jobs;
+
+///
+/// 每月8号上传消费数据
+///
+[RecurringJob(nameof(CostUploadJob), "0 0 0 8 * ? ", Name = "每月8号上传消费数据")]
+public class CostUploadJob : BaseJob
+{
+
+ public CostUploadJob(IServiceProvider serviceProvider) : base(serviceProvider)
+ {
+ }
+
+ protected override async Task RunAsync(IServiceProvider serviceProvider)
+ {
+ var jipApi = serviceProvider.GetService();
+
+ var now = DateTime.Now;
+ var month = now.Month == 1 ? 12 : now.Month - 1;
+ var s = new DateTime(2025, month, 1);
+ var e = new DateTime(2025, month + 1, 1);
+ var endDayOfMonth = e.AddDays(-1);
+
+ //从余额找人
+ var userCodes = await DbContext.Queryable()
+ .Where(x => SqlFunc.Subqueryable()
+ .Where(p => p.UserCode == x.UserCode)
+ .Where(p => p.Year == s.Year && p.Month == s.Month)
+ .NotAny()
+ )
+ .Select(x => x.UserCode)
+ .Distinct()
+ .ToListAsync();
+
+ foreach (var userCode in userCodes)
+ {
+ var balance = await DbContext.Queryable()
+ .Where(x => x.UserCode == userCode)
+ .Where(x => x.Status == BalanceRecordStatusEnumType.Valid)
+ .Where(x => x.Type == BalanceRecordTypeEnumType.Out)
+ .Where(x => x.CostDate >= s && x.CostDate < e)
+ .Where(x => !BalanceRecordSourceConstants.IgnoreSources.Contains(x.Source))
+ .SumAsync(x => x.Amount);
+
+ var response = await jipApi.UploadCostAsync(new UploadCostRequest
+ {
+ Data = new List
+ {
+ new UploadCostItemRequest
+ {
+ WorkCode = userCode,
+ BeginDate = endDayOfMonth.ToString("yyyy-MM-dd"),
+ Charge = balance,
+ Code= "2086"
+ }
+ }
+ });
+
+ if (response.Data.FirstOrDefault(x => x.WorkCode == userCode)?.Success == "S")
+ {
+ if (!await DbContext.Queryable()
+ .Where(x => x.UserCode == userCode)
+ .Where(x => x.Year == s.Year && x.Month == s.Month)
+ .AnyAsync())
+ {
+ await DbContext.InsertAsync(new UserBalanceUploadRecordEntity
+ {
+ Year = s.Year,
+ Month = s.Month,
+ UserCode = userCode,
+ Cost = balance,
+ });
+ }
+ }
+ }
+ }
+}
diff --git a/Src/Dlhis.ScheduledTask/Jobs/GenerateBirthdayVoucherJob.cs b/Src/Dlhis.ScheduledTask/Jobs/GenerateBirthdayVoucherJob.cs
new file mode 100644
index 00000000..afff58db
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/Jobs/GenerateBirthdayVoucherJob.cs
@@ -0,0 +1,28 @@
+using Dlhis.Canteen.Api;
+using Dlhis.ScheduledTask.Attributes;
+
+namespace Dlhis.ScheduledTask.Jobs;
+
+///
+/// 生日券生成
+///
+[RecurringJob(nameof(GenerateBirthdayVoucherJob), "0 0 1,12 * * ?", Name = "生日券生成")]
+public class GenerateBirthdayVoucherJob : BaseJob
+{
+ public GenerateBirthdayVoucherJob(IServiceProvider serviceProvider) : base(serviceProvider)
+ {
+ }
+
+ protected override async Task RunAsync(IServiceProvider serviceProvider)
+ {
+ var now = DateTime.Today.Date;
+
+ var voucherApi = serviceProvider.GetService();
+ await voucherApi.CreateAsync(new VoucherByBirthdayRequest
+ {
+ Begin = now,
+ End = now,
+ Remark = "定时执行生成"
+ });
+ }
+}
diff --git a/Src/Dlhis.ScheduledTask/Jobs/SendMsgToWorkGridLeaderJob.cs b/Src/Dlhis.ScheduledTask/Jobs/SendMsgToWorkGridLeaderJob.cs
index 448d1f5b..e44df8b2 100644
--- a/Src/Dlhis.ScheduledTask/Jobs/SendMsgToWorkGridLeaderJob.cs
+++ b/Src/Dlhis.ScheduledTask/Jobs/SendMsgToWorkGridLeaderJob.cs
@@ -31,7 +31,7 @@ public class SendMsgToWorkGridLeaderJob : BaseJob
foreach (var items in infos.Chunk(5))
{
- await dingtalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
+ await dingtalkApi.SendWorkMessageByWorkGridAsync(new JinkoSendWorkMessageRequest
{
Content = "你好,网格长,请看到消息后,前往人脸应用平台,执行明天的排班,已排班的请忽略!",
WorkCodes = items.Select(x => x.LeaderUserCode).ToList()
diff --git a/Src/Dlhis.ScheduledTask/Jobs/SyncOrganizationJob.cs b/Src/Dlhis.ScheduledTask/Jobs/SyncOrganizationJob.cs
index 3896edd1..43b00d1e 100644
--- a/Src/Dlhis.ScheduledTask/Jobs/SyncOrganizationJob.cs
+++ b/Src/Dlhis.ScheduledTask/Jobs/SyncOrganizationJob.cs
@@ -40,6 +40,8 @@ public class SyncOrganizationJob : BaseJob
No = item.OBJID,
Name = item.STEXT,
PNo = item.SOBID,
+ DepartmentNoFirst = item.ORGID03,
+ DepartmentNoSecond = item.ORGID04
};
await DbContext.InsertAsync(department);
@@ -48,6 +50,8 @@ public class SyncOrganizationJob : BaseJob
{
department.PNo = item.SOBID;
department.Name = item.STEXT;
+ department.DepartmentNoFirst = item.ORGID03;
+ department.DepartmentNoSecond = item.ORGID04;
await DbContext.UpdateAsync(department);
}
diff --git a/Src/Dlhis.ScheduledTask/Jobs/TipAppointmentExpireJob.cs b/Src/Dlhis.ScheduledTask/Jobs/TipAppointmentExpireJob.cs
new file mode 100644
index 00000000..83b20067
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/Jobs/TipAppointmentExpireJob.cs
@@ -0,0 +1,77 @@
+using Dlhis.Basic.Api;
+using Dlhis.Basic.Api.Requests;
+using Dlhis.Entity.Visitor.Entity;
+using Dlhis.Entity.Visitor.Enums;
+using Dlhis.ScheduledTask.Attributes;
+
+namespace Dlhis.ScheduledTask.Jobs;
+
+///
+/// 每天10点提醒访客预约到期
+///
+[RecurringJob(nameof(TipAppointmentExpireJob), "0 0 10 * * ?", Name = "提醒到访人访客将要到期")]
+public class TipAppointmentExpireJob : BaseJob
+{
+ private readonly IDingTalkApi _dingTalkApi;
+
+ public TipAppointmentExpireJob(IServiceProvider serviceProvider, IDingTalkApi dingTalkApi) : base(serviceProvider)
+ {
+ _dingTalkApi = dingTalkApi;
+ }
+
+ protected override async Task RunAsync(IServiceProvider serviceProvider)
+ {
+ var details = await DbContext.Queryable()
+ .Where(x => (x.IsEnterDoorArea && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived) ||
+ (x.IsEnterWorkplace && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Arrived))
+ .ToListAsync();
+
+ var warningDetails = new List();
+ foreach (var detail in details)
+ {
+ if (IsWarningData(detail))
+ {
+ warningDetails.Add(detail);
+ }
+ }
+
+ if (warningDetails.Any())
+ {
+ foreach (var item in warningDetails.GroupBy(x => x.No))
+ {
+ var appointment = await DbContext.Queryable()
+ .Where(x => x.No == item.Key)
+ .SingleAsync();
+
+ await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
+ {
+ WorkCodes = new List { appointment.Code },
+ Content = $"您的访客预约 {appointment.No}《{appointment.Title}》中有访客即将到达访问结束时间,请及时处理。"
+ });
+ }
+ }
+ }
+
+ private static bool IsWarningData(VisitorAppointmentDetailEntity detail)
+ {
+ var now = DateTime.Now.Date.AddDays(-3);
+ if (detail.IsEnterDoorArea
+ && detail.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived
+ && detail.DoorEnd.Value.Date == now)
+ {
+ return true;
+ }
+
+ if (detail.IsEnterWorkplace
+ && detail.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Arrived
+ && detail.WorkplaceEnd.Value.Date <= now)
+ {
+ return true;
+ }
+
+ return false;
+ }
+}
+
+
+
diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs
index 3a8a1f49..2cf21b14 100644
--- a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs
+++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs
@@ -76,87 +76,6 @@ public class AssignmentsController : ControllerBase
await _assignmentService.UpdateDeviceTaskStatusAsync(requests);
}
- [AllowAnonymous]
- [HttpPost("balance/calc/{month:int}")]
- [IgnoreTenant]
- public async Task Calc([FromRoute] int month)
- {
- if (month is < 1 or > 12)
- {
- throw new UserFriendlyException("月份错误");
- }
-
- var s = new DateTime(2025, month, 1);
- var e = new DateTime(2025, month + 1, 1);
-
- var userCodes = await _dbContext.Queryable()
- .Where(x => SqlFunc.Subqueryable().Where(p => p.UserCode == x.UserCode).NotAny())
- .Select(x => x.UserCode)
- .Distinct()
- .ToListAsync();
-
- foreach (var userCode in userCodes)
- {
- if (!await _dbContext.Queryable().Where(x => x.UserCode == userCode).AnyAsync())
- {
- await _dbContext.InsertAsync(new UserBalanceTmpEntity
- {
- UserCode = userCode,
- Balance = 0,
- Version = 0
- });
- }
-
- var balance = await _dbContext.Queryable()
- .Where(x => x.UserCode == userCode)
- .Where(x => x.Status == BalanceRecordStatusEnumType.Valid)
- .Where(x => x.Type == BalanceRecordTypeEnumType.Out)
- .Where(x => x.CostDate >= s && x.CostDate < e)
- .Where(x => !BalanceRecordSourceConstants.IgnoreSources.Contains(x.Source))
- .SumAsync(x => x.Amount);
-
- await _dbContext.Updateable()
- .SetColumns(x => x.Balance == balance)
- .SetColumns(x => x.ModifiedTime == DateTime.Now)
- .Where(x => x.UserCode == userCode)
- .ExecuteCommandAsync();
- }
-
- //
- // var userCodes = await _dbContext.Queryable().Where(x => x.ResignationDate.HasValue && x.ResignationDate >= s && x.ResignationDate <= e)
- // .Where(x => x.Type != GainfoUserTypeEnumType.External && x.Type != GainfoUserTypeEnumType.Outsource)
- // .Select(x => x.Code)
- // .Distinct()
- // .ToListAsync();
- //
- // foreach (var userCode in userCodes)
- // {
- // if (!await _dbContext.Queryable().Where(x => x.UserCode == userCode).AnyAsync())
- // {
- // await _dbContext.InsertAsync(new UserBalanceTmpEntity
- // {
- // UserCode = userCode,
- // Balance = 0,
- // Version = 0
- // });
- // }
- //
- // var balance = await _dbContext.Queryable()
- // .Where(x => x.UserCode == userCode)
- // .Where(x => x.Status == BalanceRecordStatusEnumType.Valid)
- // .Where(x => !BalanceRecordSourceConstants.IgnoreSources.Contains(x.Source))
- // .Where(x => x.CostDate >= s && x.CostDate <= e)
- // .Where(x => x.Type == BalanceRecordTypeEnumType.In)
- // .SumAsync(x => x.Amount);
- //
- // await _dbContext.Updateable()
- // .SetColumns(x => x.Balance == balance)
- // .SetColumns(x => x.ModifiedTime == DateTime.Now)
- // .Where(x => x.UserCode == userCode)
- // .ExecuteCommandAsync();
- // }
- }
-
[Obsolete]
[AllowAnonymous]
[IgnoreTenant]