From 964e0335837c58ed50f513e6cbe550ecba9ee7f3 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Tue, 11 Feb 2025 16:33:21 +0800 Subject: [PATCH] feat tickets --- Dlhis.Jinko.Face.sln | 13 ++++ .../Services/Implements/DishesService.cs | 5 +- Src/Dlhis.Basic/Dlhis.Basic.csproj | 1 + .../Implements/GainfoQrCodeService.cs | 6 +- .../Services/Implements/GainfoService.cs | 3 +- .../Implements/IdentityUserSyncService.cs | 3 +- .../Dlhis.Canteen.Api.csproj | 13 ++++ Src/Dlhis.Canteen.Api/ITicketApi.cs | 16 +++++ Src/Dlhis.Canteen/Dlhis.Canteen.csproj | 1 + .../Implements/EMealVoucherService.cs | 5 +- .../Implements/MealSupplementRecordService.cs | 3 +- .../Services/Implements/BalanceService.cs | 3 +- .../Order/Services/Implements/OrderService.cs | 13 +++- .../Services/Implements/WalletService.cs | 3 +- .../Tickets/Controllers/TicketsController.cs | 50 ++++++++++++++ .../Tickets/Request/TicketPageRequest.cs | 19 ++++++ .../Tickets/Response/TicketPageResponse.cs | 41 ++++++++++++ .../Services/IBirthdayTicketService.cs | 6 ++ .../Tickets/Services/ITicketService.cs | 24 +++++++ .../Implements/BirthdayTicketService.cs | 65 +++++++++++++++++++ .../Services/Implements/TicketService.cs | 32 +++++++++ Src/Dlhis.Constants/Dlhis.Constants.csproj | 9 +++ Src/Dlhis.Constants/QrCodeConstants.cs | 19 ++++++ Src/Dlhis.Constants/TickConstants.cs | 6 ++ Src/Dlhis.Constants/UserClaimConstants.cs | 9 +++ .../Canteen/Entities/TicketEntity.cs | 52 +++++++++++++++ .../Canteen/Enums/TicketEnumType.cs | 16 +++++ .../Implements/DeviceUploadLogService.cs | 5 +- .../Dlhis.ScheduledTask.csproj | 3 + Src/Dlhis.ScheduledTask/Dockerfile | 13 +++- .../Jobs/CreateBirthdayTicketJob.cs | 22 +++++++ .../appsettings.Development.json | 19 +++--- Src/Dlhis.ScheduledTask/appsettings.json | 3 +- 33 files changed, 473 insertions(+), 28 deletions(-) create mode 100644 Src/Dlhis.Canteen.Api/Dlhis.Canteen.Api.csproj create mode 100644 Src/Dlhis.Canteen.Api/ITicketApi.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Request/TicketPageRequest.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Response/TicketPageResponse.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Services/IBirthdayTicketService.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Services/ITicketService.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Services/Implements/BirthdayTicketService.cs create mode 100644 Src/Dlhis.Canteen/Tickets/Services/Implements/TicketService.cs create mode 100644 Src/Dlhis.Constants/Dlhis.Constants.csproj create mode 100644 Src/Dlhis.Constants/QrCodeConstants.cs create mode 100644 Src/Dlhis.Constants/TickConstants.cs create mode 100644 Src/Dlhis.Constants/UserClaimConstants.cs create mode 100644 Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs create mode 100644 Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs create mode 100644 Src/Dlhis.ScheduledTask/Jobs/CreateBirthdayTicketJob.cs diff --git a/Dlhis.Jinko.Face.sln b/Dlhis.Jinko.Face.sln index 8ab23f97..0cf2b39a 100644 --- a/Dlhis.Jinko.Face.sln +++ b/Dlhis.Jinko.Face.sln @@ -47,6 +47,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Jip.Api", "Src\Dlhis. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Dh.Api", "Src\Dlhis.Dh.Api\Dlhis.Dh.Api.csproj", "{E673CA04-3567-4E03-9A86-994F50291ACC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Constants", "Src\Dlhis.Constants\Dlhis.Constants.csproj", "{F98329D8-F8CA-4794-B1BF-8659112119F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Canteen.Api", "Src\Dlhis.Canteen.Api\Dlhis.Canteen.Api.csproj", "{7934BE46-9409-4D28-8B35-82A0F900DD01}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -117,6 +121,14 @@ Global {E673CA04-3567-4E03-9A86-994F50291ACC}.Debug|Any CPU.Build.0 = Debug|Any CPU {E673CA04-3567-4E03-9A86-994F50291ACC}.Release|Any CPU.ActiveCfg = Release|Any CPU {E673CA04-3567-4E03-9A86-994F50291ACC}.Release|Any CPU.Build.0 = Release|Any CPU + {F98329D8-F8CA-4794-B1BF-8659112119F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F98329D8-F8CA-4794-B1BF-8659112119F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F98329D8-F8CA-4794-B1BF-8659112119F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F98329D8-F8CA-4794-B1BF-8659112119F7}.Release|Any CPU.Build.0 = Release|Any CPU + {7934BE46-9409-4D28-8B35-82A0F900DD01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7934BE46-9409-4D28-8B35-82A0F900DD01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7934BE46-9409-4D28-8B35-82A0F900DD01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7934BE46-9409-4D28-8B35-82A0F900DD01}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -134,6 +146,7 @@ Global {A501D16E-638F-4156-989C-2BACCC2FAC2B} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A} {841B7B43-5394-413F-9D68-A07EBDD6D4CD} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A} {E673CA04-3567-4E03-9A86-994F50291ACC} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A} + {7934BE46-9409-4D28-8B35-82A0F900DD01} = {3D8A98C1-83C9-4375-AEAB-4F72AFAF365B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7439494A-E2FD-4FEA-8ABF-74AE57A4A5A0} diff --git a/Src/Dlhis.Basic/Dishes/Services/Implements/DishesService.cs b/Src/Dlhis.Basic/Dishes/Services/Implements/DishesService.cs index 17d54967..4e738197 100644 --- a/Src/Dlhis.Basic/Dishes/Services/Implements/DishesService.cs +++ b/Src/Dlhis.Basic/Dishes/Services/Implements/DishesService.cs @@ -1,6 +1,7 @@ using Dlhis.Basic.Dishes.Request; using Dlhis.Basic.Dishes.Response; using Dlhis.Basic.Places.Services; +using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Canteen.Entities; using Dlhis.Entity.Canteen.Enums; @@ -45,7 +46,7 @@ public class DishesService : IDishesService .ToPageListAsync(request); } - + public async Task SaveDishesAsync(DishesSaveRequest request) { if (!request.Id.HasValue) @@ -68,7 +69,7 @@ public class DishesService : IDishesService { var subjectId = _currentUser.GetIntSubjectId(); var gainfo = await _dbContext.Queryable().Where(x => x.IdentityUserId == subjectId).FirstAsync(); - var jinkoCode = _currentUser.GetUserClaim("jinko-code") ?? string.Empty; + var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty; if (jinkoCode.IsPresent()) { gainfo = await _dbContext.Queryable().Where(x => x.Code == jinkoCode).FirstAsync(); diff --git a/Src/Dlhis.Basic/Dlhis.Basic.csproj b/Src/Dlhis.Basic/Dlhis.Basic.csproj index eb9f5b54..7b161cb8 100644 --- a/Src/Dlhis.Basic/Dlhis.Basic.csproj +++ b/Src/Dlhis.Basic/Dlhis.Basic.csproj @@ -26,6 +26,7 @@ + diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoQrCodeService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoQrCodeService.cs index ab6564d7..fac551b2 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoQrCodeService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoQrCodeService.cs @@ -1,4 +1,5 @@ using System.Text; +using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; @@ -21,7 +22,7 @@ public class GainfoQrCodeService : IGainfoQrCodeService public async Task GetMyQrCodeAsync(bool isNeedRefresh = false) { - var jinkoCode = _currentUser.GetUserClaim("jinko-code"); + var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); if (jinkoCode.IsEmpty()) { return null; @@ -63,11 +64,12 @@ public class GainfoQrCodeService : IGainfoQrCodeService var ts = DateTimeOffset.Now.ToUnixTimeMilliseconds(); var qrCode = string.Concat("consumer", ":", code, ":"); - return "01" + qrCode.ToArray().Select(x => + return QrCodeConstants.User + qrCode.ToArray().Select(x => { var b = Encoding.ASCII.GetBytes(x.ToString()); int i = b[0]; return Convert.ToString(i); + }).Join(string.Empty) + ts; } } \ No newline at end of file diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs index 32083932..3f1b7bf1 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs @@ -2,6 +2,7 @@ using Dlhis.Basic.Device.Services; using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; +using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Device.Entities; @@ -195,7 +196,7 @@ public class GainfoService : IGainfoService public async Task CurrentUserInfoAsync() { - var code = _currentUser.GetUserClaim("jinko-code"); + var code = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); if (code.IsEmpty()) { _logger.LogWarning("工号为空尝试获取人员信息"); diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/IdentityUserSyncService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/IdentityUserSyncService.cs index 5bde9773..a68e296d 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/IdentityUserSyncService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/IdentityUserSyncService.cs @@ -1,3 +1,4 @@ +using Dlhis.Constants; using Dlhis.Entity.Sys.Entities; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; @@ -41,7 +42,7 @@ public class IdentityUserSyncService : IIdentityUserSyncService var id = (int)await _identityDbContext.InsertReturnIdentityAsync(user); user.Id = id; - await AddUserClaim(_identityDbContext, id, "jinko-code", userName); + await AddUserClaim(_identityDbContext, id, UserClaimConstants.JinkoCode, userName); await AddUserClaim(_identityDbContext, id, "name", name); } diff --git a/Src/Dlhis.Canteen.Api/Dlhis.Canteen.Api.csproj b/Src/Dlhis.Canteen.Api/Dlhis.Canteen.Api.csproj new file mode 100644 index 00000000..dba64aca --- /dev/null +++ b/Src/Dlhis.Canteen.Api/Dlhis.Canteen.Api.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + disable + + + + + + + diff --git a/Src/Dlhis.Canteen.Api/ITicketApi.cs b/Src/Dlhis.Canteen.Api/ITicketApi.cs new file mode 100644 index 00000000..149b9826 --- /dev/null +++ b/Src/Dlhis.Canteen.Api/ITicketApi.cs @@ -0,0 +1,16 @@ +using Kurisu.RemoteCall.Attributes; + +namespace Dlhis.Canteen.Api; + +[RequestResultHandler] +[EnableRemoteClient(Name = "canteen-service", BaseUrl = "${InternalRequest:CanteenRequestUrl}")] +public interface ITicketApi +{ + /// + /// 创建券 + /// + /// + /// + [Post("/api/tickets/{type}/create")] + Task CreateAsync(string type); +} \ No newline at end of file diff --git a/Src/Dlhis.Canteen/Dlhis.Canteen.csproj b/Src/Dlhis.Canteen/Dlhis.Canteen.csproj index f893a588..b3030c28 100644 --- a/Src/Dlhis.Canteen/Dlhis.Canteen.csproj +++ b/Src/Dlhis.Canteen/Dlhis.Canteen.csproj @@ -22,6 +22,7 @@ + diff --git a/Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs b/Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs index 466e2e5d..9bb4b838 100644 --- a/Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs +++ b/Src/Dlhis.Canteen/EMealVoucher/Services/Implements/EMealVoucherService.cs @@ -3,6 +3,7 @@ using Dlhis.Canteen.EMealVoucher.Request; using Dlhis.Canteen.EMealVoucher.Response; using Dlhis.Canteen.Order.Request; using Dlhis.Canteen.Order.Response; +using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Canteen.Entities; using Dlhis.Entity.Canteen.Enums; @@ -65,7 +66,7 @@ public class EMealVoucherService : IEMealVoucherService public async Task> GetMyEMealVoucherPageAsync(EMealVoucherPageRequest request) { - var code = _currentUser.GetUserClaim("jinko-code"); + var code = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); return await _dbContext.Queryable() .Where(x => x.Code == code) @@ -126,7 +127,7 @@ public class EMealVoucherService : IEMealVoucherService var ts = DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString().Reverse().Join(string.Empty); var originData = string.Concat(eMealVoucher.No, ":", ts, ":", eMealVoucher.Code, ":", eMealVoucherDetail.IdNo); - var qrCode = "02" + originData.ToArray().Select(x => + var qrCode = QrCodeConstants.EMealVoucher + originData.ToArray().Select(x => { var b = Encoding.ASCII.GetBytes(x.ToString()); int i = b[0]; diff --git a/Src/Dlhis.Canteen/MealSupplementRecord/Services/Implements/MealSupplementRecordService.cs b/Src/Dlhis.Canteen/MealSupplementRecord/Services/Implements/MealSupplementRecordService.cs index 0e2094cf..79f03e25 100644 --- a/Src/Dlhis.Canteen/MealSupplementRecord/Services/Implements/MealSupplementRecordService.cs +++ b/Src/Dlhis.Canteen/MealSupplementRecord/Services/Implements/MealSupplementRecordService.cs @@ -1,5 +1,6 @@ using Dlhis.Canteen.MealSupplementRecord.Request; using Dlhis.Canteen.MealSupplementRecord.Response; +using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Canteen.Entities; using Dlhis.Entity.Canteen.Enums; @@ -93,7 +94,7 @@ public class MealSupplementRecordService : IMealSupplementRecordService public async Task GetMyMealSupplementRecords(MealSupplementRecordMyRequest request) { - var code = _currentUser.GetUserClaim("jinko-code") ?? string.Empty; + var code = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty; var data = await _dbContext.Queryable() .Where(x => x.CostDateTime >= request.SearchDateTimePeriod.Start && x.CostDateTime <= request.SearchDateTimePeriod.End) diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs index 15df612e..0c99ae1a 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs @@ -3,6 +3,7 @@ using Dlhis.Canteen.Order.Repository; using Dlhis.Canteen.Order.Request; using Dlhis.Canteen.Order.Response; using Dlhis.Canteen.Setting.Services; +using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Canteen.Entities; using Dlhis.Entity.Canteen.Enums; @@ -334,7 +335,7 @@ public class BalanceService : IBalanceService public async Task GetPageByUserAsync(BalanceRecordUserPageRequest request) { - var userCode = _currentUser.GetUserClaim("jinko-code") ?? string.Empty; + var userCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty; var factory = await _dbContext.Queryable().Where(x => x.Code == request.WalletCode).Select(x => x.Factory).FirstAsync(); var factories = await _balanceRepository.GetWalletFactoriesAsync(factory); diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs index 5d49bb46..16ec206b 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs @@ -21,6 +21,7 @@ using Kurisu.AspNetCore.DataAccess.Dto; using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.UnifyResultAndValidation; +using Dlhis.Constants; namespace Dlhis.Canteen.Order.Services.Implements; @@ -88,7 +89,7 @@ public class OrderService : IOrderService { var subjectId = _currentUser.GetIntSubjectId(); var gainfo = await _dbContext.Queryable().Where(x => x.IdentityUserId == subjectId).FirstAsync(); - var jinkoCode = _currentUser.GetUserClaim("jinko-code") ?? string.Empty; + var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty; if (jinkoCode.IsPresent()) { gainfo = await _dbContext.Queryable().Where(x => x.Code == jinkoCode).SingleAsync(); @@ -153,12 +154,12 @@ public class OrderService : IOrderService if (request.Source == BalanceRecordSourceEnumType.QrCode) { - if (request.UserUniqueNo.StartsWith("01")) + if (request.UserUniqueNo.StartsWith(QrCodeConstants.User)) { gainfo = await GetUserByQrCodeAsync(request.UserUniqueNo); await CheckPermissionAsync(gainfo.Code, request.DeviceUniqueNo); } - else if (request.UserUniqueNo.StartsWith("02")) + else if (request.UserUniqueNo.StartsWith(QrCodeConstants.EMealVoucher)) { request.Source = BalanceRecordSourceEnumType.EMealVoucher; var eMealVoucherQrCode = await _dbContext.Queryable().Where(x => x.QrCode == request.UserUniqueNo).SingleAsync(); @@ -166,6 +167,12 @@ public class OrderService : IOrderService var code = eMealVoucherQrCode.OriginData.Split(':')[2]; gainfo = await _dbContext.Queryable().Where(x => x.Code == code).SingleAsync(); } + else if (request.UserUniqueNo.StartsWith(QrCodeConstants.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(); + } else { throw new UserFriendlyException($"无法识别{request.UserUniqueNo}"); diff --git a/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs b/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs index 42f3a8fc..ffe3dd45 100644 --- a/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs +++ b/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs @@ -1,5 +1,6 @@ using Dlhis.Canteen.Order.Repository; using Dlhis.Canteen.Setting.Response; +using Dlhis.Constants; using Dlhis.Entity.Canteen.Entities; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; @@ -37,7 +38,7 @@ public class WalletService : IWalletService /// public async Task GetBalanceAsync(string walletCode) { - var userCode = _currentUser.GetUserClaim("jinko-code"); + var userCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); if (!await _dbContext.Queryable().Where(x => x.UserCode == userCode).AnyAsync()) { diff --git a/Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs b/Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs new file mode 100644 index 00000000..9dfb8ae1 --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Controllers/TicketsController.cs @@ -0,0 +1,50 @@ +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 new file mode 100644 index 00000000..02620a43 --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Request/TicketPageRequest.cs @@ -0,0 +1,19 @@ +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/Response/TicketPageResponse.cs b/Src/Dlhis.Canteen/Tickets/Response/TicketPageResponse.cs new file mode 100644 index 00000000..b7be7bc6 --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Response/TicketPageResponse.cs @@ -0,0 +1,41 @@ +using Dlhis.Entity.Canteen.Enums; + +namespace Dlhis.Canteen.Tickets.Response; + +public class TicketPageResponse +{ + /// + /// 券类型 + /// + public TicketEnumType Type { get; set; } + + /// + /// 工号 + /// + public string UserCode { get; set; } + + /// + /// 用户名称 + /// + public string UserName { get; set; } + + /// + /// 初始余额 + /// + public decimal OriginalAmount { get; set; } + + /// + /// 当前余额 + /// + public decimal Amount { get; set; } + + /// + /// 消费码 + /// + public string QrCode { get; set; } + + /// + /// 备注 + /// + public string Remark { 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 new file mode 100644 index 00000000..1b67cc3a --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Services/IBirthdayTicketService.cs @@ -0,0 +1,6 @@ +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 new file mode 100644 index 00000000..bc8731f2 --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Services/ITicketService.cs @@ -0,0 +1,24 @@ +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 new file mode 100644 index 00000000..ba75b0e9 --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Services/Implements/BirthdayTicketService.cs @@ -0,0 +1,65 @@ +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, + OriginalAmount = amount, + Amount = 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 new file mode 100644 index 00000000..8af5da71 --- /dev/null +++ b/Src/Dlhis.Canteen/Tickets/Services/Implements/TicketService.cs @@ -0,0 +1,32 @@ +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.Constants/Dlhis.Constants.csproj b/Src/Dlhis.Constants/Dlhis.Constants.csproj new file mode 100644 index 00000000..132c02c5 --- /dev/null +++ b/Src/Dlhis.Constants/Dlhis.Constants.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/Src/Dlhis.Constants/QrCodeConstants.cs b/Src/Dlhis.Constants/QrCodeConstants.cs new file mode 100644 index 00000000..ed15fccc --- /dev/null +++ b/Src/Dlhis.Constants/QrCodeConstants.cs @@ -0,0 +1,19 @@ +namespace Dlhis.Constants; + +public class QrCodeConstants +{ + /// + /// 个人码 + /// + public const string User = "01"; + + /// + /// 电子餐券 + /// + public const string EMealVoucher = "02"; + + /// + /// 生日券 + /// + public const string Birthday = "03"; +} diff --git a/Src/Dlhis.Constants/TickConstants.cs b/Src/Dlhis.Constants/TickConstants.cs new file mode 100644 index 00000000..b24c0775 --- /dev/null +++ b/Src/Dlhis.Constants/TickConstants.cs @@ -0,0 +1,6 @@ +// namespace Dlhis.Constants; +// +// public class TickConstants +// { +// public const string { get; set; } +// } diff --git a/Src/Dlhis.Constants/UserClaimConstants.cs b/Src/Dlhis.Constants/UserClaimConstants.cs new file mode 100644 index 00000000..635fdf0f --- /dev/null +++ b/Src/Dlhis.Constants/UserClaimConstants.cs @@ -0,0 +1,9 @@ +namespace Dlhis.Constants; + +public class UserClaimConstants +{ + /// + /// 晶科工号 + /// + public const string JinkoCode = "jinko-code"; +} diff --git a/Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs new file mode 100644 index 00000000..d3ca3c05 --- /dev/null +++ b/Src/Dlhis.Entity/Canteen/Entities/TicketEntity.cs @@ -0,0 +1,52 @@ +using Dlhis.Entity.Canteen.Enums; +using Kurisu.AspNetCore.DataAccess.Entity; +using Kurisu.AspNetCore.DataAccess.SqlSugar; +using SqlSugar; +using SqlSugar.DbConvert; + +namespace Dlhis.Entity.Canteen.Entities; + +/// +/// 券 +/// +[SugarTable("Tickets", TableDescription = "券")] +public class TicketEntity : SugarBaseEntity, ITenantId +{ + /// + /// 类型 + /// + [SugarColumn(IsNullable = false, ColumnDataType = "varchar(50)", ColumnDescription = "券类型", SqlParameterDbType = typeof(EnumToStringConvert))] + public TicketEnumType Type { get; set; } + + /// + /// 工号 + /// + [SugarColumn(IsNullable = false, ColumnDescription = "工号")] + public string UserCode { get; set; } + + /// + /// 初始余额 + /// + [SugarColumn(IsNullable = false, ColumnDescription = "初始余额")] + public decimal OriginalAmount { get; set; } + + /// + /// 当前余额 + /// + [SugarColumn(IsNullable = false, ColumnDescription = "当前余额")] + public decimal Amount { get; set; } + + /// + /// 消费码 + /// + [SugarColumn(IsNullable = false, ColumnDescription = "消费码")] + public string QrCode { get; set; } + + /// + /// 备注 + /// + [SugarColumn(IsNullable = true, ColumnDescription = "备注")] + public string Remark { get; set; } + + public string TenantId { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs b/Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs new file mode 100644 index 00000000..3df284e2 --- /dev/null +++ b/Src/Dlhis.Entity/Canteen/Enums/TicketEnumType.cs @@ -0,0 +1,16 @@ +using System.ComponentModel; + +namespace Dlhis.Entity.Canteen.Enums; + +/// +/// 券类型 +/// +[Description("券类型")] +public enum TicketEnumType +{ + /// + /// 生日券 + /// + [Description("生日券")] + Birthday = 1 +} \ No newline at end of file diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs index da1be9e3..6336d998 100644 --- a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs +++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs @@ -1,4 +1,5 @@ -using Dlhis.Entity.Basic.Entity; +using Dlhis.Constants; +using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; @@ -95,7 +96,7 @@ public class DeviceUploadLogService : IDeviceUploadLogService public async Task> GetMyRecordsAsync(DeviceUploadLogMyRecordRequest request) { - var jinkoCode = _currentUser.GetUserClaim("jinko-code") ?? string.Empty; + var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty; return await _dbContext.Queryable() .LeftJoin((log, d) => log.DeviceUniqueNo == d.UniqueNo) diff --git a/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj b/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj index 0376df7c..0429e8ce 100644 --- a/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj +++ b/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj @@ -20,10 +20,13 @@ + + + diff --git a/Src/Dlhis.ScheduledTask/Dockerfile b/Src/Dlhis.ScheduledTask/Dockerfile index babe2308..dadbd4fe 100644 --- a/Src/Dlhis.ScheduledTask/Dockerfile +++ b/Src/Dlhis.ScheduledTask/Dockerfile @@ -1,25 +1,34 @@ -#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. +# 请参阅 https://aka.ms/customizecontainer 以了解如何自定义调试容器,以及 Visual Studio 如何使用此 Dockerfile 生成映像以更快地进行调试。 +# 此阶段用于在快速模式(默认为调试配置)下从 VS 运行时 FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 + +# 此阶段用于生成服务项目 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src COPY ["Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj", "Src/Dlhis.ScheduledTask/"] COPY ["Src/Dlhis.Basic.Api/Dlhis.Basic.Api.csproj", "Src/Dlhis.Basic.Api/"] +COPY ["Src/Dlhis.Canteen.Api/Dlhis.Canteen.Api.csproj", "Src/Dlhis.Canteen.Api/"] +COPY ["Src/Dlhis.Constants/Dlhis.Constants.csproj", "Src/Dlhis.Constants/"] COPY ["Src/Dlhis.Entity/Dlhis.Entity.csproj", "Src/Dlhis.Entity/"] +COPY ["Src/Dlhis.DataPermission.Model/Dlhis.DataPermission.Model.csproj", "Src/Dlhis.DataPermission.Model/"] +COPY ["Src/Dlhis.Jip.Api/Dlhis.Jip.Api.csproj", "Src/Dlhis.Jip.Api/"] COPY ["Src/Dlhis.Sys.Api/Dlhis.Sys.Api.csproj", "Src/Dlhis.Sys.Api/"] -RUN dotnet restore "./Src/Dlhis.ScheduledTask/./Dlhis.ScheduledTask.csproj" +RUN dotnet restore "./Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj" COPY . . WORKDIR "/src/Src/Dlhis.ScheduledTask" RUN dotnet build "./Dlhis.ScheduledTask.csproj" -c $BUILD_CONFIGURATION -o /app/build +# 此阶段用于发布要复制到最终阶段的服务项目 FROM build AS publish ARG BUILD_CONFIGURATION=Release RUN dotnet publish "./Dlhis.ScheduledTask.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false +# 此阶段在生产中使用,或在常规模式下从 VS 运行时使用(在不使用调试配置时为默认值) FROM base AS final WORKDIR /app COPY --from=publish /app/publish . diff --git a/Src/Dlhis.ScheduledTask/Jobs/CreateBirthdayTicketJob.cs b/Src/Dlhis.ScheduledTask/Jobs/CreateBirthdayTicketJob.cs new file mode 100644 index 00000000..75058d75 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/Jobs/CreateBirthdayTicketJob.cs @@ -0,0 +1,22 @@ +using Dlhis.Canteen.Api; +using Dlhis.Entity.Canteen.Enums; +using Dlhis.ScheduledTask.Attributes; + +namespace Dlhis.ScheduledTask.Jobs; + +/// +/// +/// +[RecurringJob(nameof(CreateBirthdayTicketJob), "0 0 1 * * ?", Name = "生日券发放")] +public class CreateBirthdayTicketJob : BaseJob +{ + public CreateBirthdayTicketJob(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + /// + protected override async Task RunAsync(IServiceProvider serviceProvider) + { + await serviceProvider.GetService().CreateAsync(TicketEnumType.Birthday.ToString()); + } +} \ No newline at end of file diff --git a/Src/Dlhis.ScheduledTask/appsettings.Development.json b/Src/Dlhis.ScheduledTask/appsettings.Development.json index da038ced..143db3b6 100644 --- a/Src/Dlhis.ScheduledTask/appsettings.Development.json +++ b/Src/Dlhis.ScheduledTask/appsettings.Development.json @@ -7,7 +7,8 @@ }, "InternalRequest": { "SysRequestUrl": "http://localhost:5003", - "BasicRequestUrl": "http://localhost:5002" + "BasicRequestUrl": "http://localhost:5002", + "CanteenRequestUrl": "http://localhost:5008" }, "FaceUrlOptions": { "Url": "http://192.168.199.115:5002/api/gainfos/face?token=", @@ -36,18 +37,18 @@ "ClientSecret": "123456" } }, -// "JinkoOptions": { -// "Jip": { -// "BaseUrl": "http://172.16.202.34:8000", -// "Key": "FACE-7409WIBX", -// "Secret": "be0a4b88-cd80-4509-b9b9-865205d0d3d8" -// } -// }, + // "JinkoOptions": { + // "Jip": { + // "BaseUrl": "http://172.16.202.34:8000", + // "Key": "FACE-7409WIBX", + // "Secret": "be0a4b88-cd80-4509-b9b9-865205d0d3d8" + // } + // }, "JinkoOptions": { "Jip": { "BaseUrl": "http://jip.jinkosolar.com", "Key": "FACE-CUOJG9N7", "Secret": "130c2f2d-03a0-4720-8e25-538ffac7a7cb" } - }, + } } diff --git a/Src/Dlhis.ScheduledTask/appsettings.json b/Src/Dlhis.ScheduledTask/appsettings.json index b2bd19b9..d3bba67c 100644 --- a/Src/Dlhis.ScheduledTask/appsettings.json +++ b/Src/Dlhis.ScheduledTask/appsettings.json @@ -7,7 +7,8 @@ }, "InternalRequest": { "SysRequestUrl": "http://sys", - "BasicRequestUrl": "http://basic" + "BasicRequestUrl": "http://basic", + "CanteenRequestUrl": "http://canteen" }, "DataProtectionOptions": { "Enable": true,