diff --git a/Src/Dlhis.Basic/Device/Response/DeviceGroupPageResponse.cs b/Src/Dlhis.Basic/Device/Response/DeviceGroupPageResponse.cs
index cde4884f..5b3873db 100644
--- a/Src/Dlhis.Basic/Device/Response/DeviceGroupPageResponse.cs
+++ b/Src/Dlhis.Basic/Device/Response/DeviceGroupPageResponse.cs
@@ -1,5 +1,13 @@
-namespace Dlhis.Basic.Device.Response;
+using SqlSugar;
+
+namespace Dlhis.Basic.Device.Response;
public class DeviceGroupPageResponse
{
+ public Guid Code { get; set; }
+
+ ///
+ /// 设备组名称
+ ///
+ public string Name { get; set; }
}
diff --git a/Src/Dlhis.Basic/Program.cs b/Src/Dlhis.Basic/Program.cs
index d077cec2..d7c99860 100644
--- a/Src/Dlhis.Basic/Program.cs
+++ b/Src/Dlhis.Basic/Program.cs
@@ -15,7 +15,5 @@ public class Startup : DefaultStartup
public Startup(IConfiguration configuration) : base(configuration)
{
IdentityModelEventSource.ShowPII = true;
-
}
-
}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/BalanceRecord/Request/BalanceRecordRequest.cs b/Src/Dlhis.Canteen/BalanceRecord/Request/BalanceRecordRequest.cs
deleted file mode 100644
index 1e5c37ba..00000000
--- a/Src/Dlhis.Canteen/BalanceRecord/Request/BalanceRecordRequest.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using Kurisu.Core.DataAccess.Dto;
-
-namespace Dlhis.Canteen.BalanceRecord.Request;
-
-public class BalanceRecordRequest : PageDto
-{
-}
diff --git a/Src/Dlhis.Canteen/BalanceRecord/Response/BalanceRecordResponse.cs b/Src/Dlhis.Canteen/BalanceRecord/Response/BalanceRecordResponse.cs
deleted file mode 100644
index 044dd75f..00000000
--- a/Src/Dlhis.Canteen/BalanceRecord/Response/BalanceRecordResponse.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace Dlhis.Canteen.BalanceRecord.Response;
-
-public class BalanceRecordResponse
-{
-}
diff --git a/Src/Dlhis.Canteen/BalanceRecord/Services/IBalanceRecordService.cs b/Src/Dlhis.Canteen/BalanceRecord/Services/IBalanceRecordService.cs
deleted file mode 100644
index e7fa831e..00000000
--- a/Src/Dlhis.Canteen/BalanceRecord/Services/IBalanceRecordService.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Dlhis.Canteen.BalanceRecord.Request;
-using Dlhis.Canteen.BalanceRecord.Response;
-using Kurisu.Core.DataAccess.Dto;
-
-namespace Dlhis.Canteen.BalanceRecord.Services;
-
-public interface IBalanceRecordService : IScopeDependency
-{
- Task> GetPageAsync(BalanceRecordRequest request);
-}
diff --git a/Src/Dlhis.Canteen/BalanceRecord/Services/Implements/BalanceRecordService.cs b/Src/Dlhis.Canteen/BalanceRecord/Services/Implements/BalanceRecordService.cs
deleted file mode 100644
index 50f67844..00000000
--- a/Src/Dlhis.Canteen/BalanceRecord/Services/Implements/BalanceRecordService.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Dlhis.Canteen.BalanceRecord.Request;
-using Dlhis.Canteen.BalanceRecord.Response;
-using Dlhis.Entity.Canteen.Entities;
-using Kurisu.Core.DataAccess.Dto;
-using Kurisu.SqlSugar.Extensions;
-using Kurisu.SqlSugar.Services;
-
-namespace Dlhis.Canteen.BalanceRecord.Services.Implements;
-
-public class BalanceRecordService : IBalanceRecordService
-{
- private readonly IDbContext _dbContext;
-
- public BalanceRecordService(IDbContext dbContext)
- {
- _dbContext = dbContext;
- }
-
- public async Task> GetPageAsync(BalanceRecordRequest request)
- {
- return await _dbContext.Queryable()
- .Select()
- .ToPageListAsync(request);
- }
-}
diff --git a/Src/Dlhis.Canteen/Dlhis.Canteen.csproj b/Src/Dlhis.Canteen/Dlhis.Canteen.csproj
index fe29c4df..0d652e95 100644
--- a/Src/Dlhis.Canteen/Dlhis.Canteen.csproj
+++ b/Src/Dlhis.Canteen/Dlhis.Canteen.csproj
@@ -28,7 +28,6 @@
-
diff --git a/Src/Dlhis.Canteen/Order/Controllers/BalancesController.cs b/Src/Dlhis.Canteen/Order/Controllers/BalancesController.cs
new file mode 100644
index 00000000..ee4c5d16
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/Controllers/BalancesController.cs
@@ -0,0 +1,32 @@
+using Dlhis.Canteen.Order.Request;
+using Dlhis.Canteen.Order.Response;
+using Dlhis.Canteen.Order.Services;
+using Kurisu.Core.DataAccess.Dto;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Dlhis.Canteen.Order.Controllers;
+
+[Authorize]
+[Route("api/[controller]")]
+[ApiController]
+public class BalancesController : ControllerBase
+{
+ private readonly IBalanceService _balanceService;
+
+ public BalancesController(IBalanceService balanceService)
+ {
+ _balanceService = balanceService;
+ }
+
+ ///
+ /// 获取消费记录
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task> GetPageAsync([FromQuery] BalanceRecordPageRequest request)
+ {
+ return await _balanceService.GetPageAsync(request);
+ }
+}
diff --git a/Src/Dlhis.Canteen/Order/Request/BalanceRecordPageRequest.cs b/Src/Dlhis.Canteen/Order/Request/BalanceRecordPageRequest.cs
new file mode 100644
index 00000000..0606d174
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/Request/BalanceRecordPageRequest.cs
@@ -0,0 +1,63 @@
+using Dlhis.Entity.Canteen.Enums;
+using System.ComponentModel.DataAnnotations;
+using Kurisu.Core.DataAccess.Dto;
+using Kurisu.Core.CustomClass;
+
+namespace Dlhis.Canteen.Order.Request;
+
+public class BalanceRecordPageRequest : PageDto, IValidatableObject
+{
+ [EnumDataType(typeof(DateTimeSearchEnumType))]
+ public DateTimeSearchEnumType? SearchDateTimeDimension { get; set; }
+
+ ///
+ /// 日期范围查询
+ ///
+ public DateTimePeriod SearchDateTimePeriod { get; set; }
+
+ public IEnumerable Validate(ValidationContext validationContext)
+ {
+ var now = DateTime.Now;
+ if (SearchDateTimeDimension.HasValue)
+ {
+ //重新赋值
+ SearchDateTimePeriod = new DateTimePeriod();
+
+ if (SearchDateTimeDimension == DateTimeSearchEnumType.Day)
+ {
+ SearchDateTimePeriod.Start = new DateTime(now.Year, now.Month, now.Day, 0, 0, 1);
+ SearchDateTimePeriod.End = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Week)
+ {
+ SearchDateTimePeriod.Start = now.AddDays(1 - (int)now.DayOfWeek);
+ SearchDateTimePeriod.End = SearchDateTimePeriod.Start.Value.AddDays(6);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Month)
+ {
+ SearchDateTimePeriod.Start = new DateTime(now.Year, now.Month, 1);
+ SearchDateTimePeriod.End = SearchDateTimePeriod.Start.Value.AddMonths(1).AddDays(-1);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Season)
+ {
+ SearchDateTimePeriod.Start = now.AddMonths(0 - ((now.Month - 1) % 3));
+ SearchDateTimePeriod.End = now.AddMonths(3 - ((now.Month - 1) % 3)).AddMonths(1).AddDays(-1);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.HalfOfYear)
+ {
+ SearchDateTimePeriod.Start = now.AddDays(-180);
+ SearchDateTimePeriod.End = now;
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Year)
+ {
+ SearchDateTimePeriod.Start = new DateTime(now.Year, 1, 1);
+ SearchDateTimePeriod.End = SearchDateTimePeriod.Start.Value.AddYears(1).AddDays(-1);
+ }
+
+ SearchDateTimePeriod.Start = SearchDateTimePeriod.Start.Value.Date;
+ SearchDateTimePeriod.End = SearchDateTimePeriod.End.Value.Date;
+ }
+
+ yield break;
+ }
+}
diff --git a/Src/Dlhis.Canteen/Order/Request/OrderAddRequest.cs b/Src/Dlhis.Canteen/Order/Request/OrderAddRequest.cs
index 3d518fb7..95255b0e 100644
--- a/Src/Dlhis.Canteen/Order/Request/OrderAddRequest.cs
+++ b/Src/Dlhis.Canteen/Order/Request/OrderAddRequest.cs
@@ -5,20 +5,25 @@ namespace Dlhis.Canteen.Order.Request;
public class OrderAddRequest
{
+ ///
+ /// 是否离线数据
+ ///
+ public bool IsOffline { get; set; } = false;
+
///
/// 消费机器唯一信息
///
- public string UniqueNo { get; set; }
+ public string DeviceUniqueNo { get; set; }
///
- /// 档案号/QrCode
+ /// 第三方订单号
///
- public string UserId { get; set; }
+ public string ThirdNo { get; set; }
///
- /// 学工号
+ /// 档案号/QrCode/学工号
///
- public string UserCode { get; set; }
+ public string UserUniqueNo { get; set; }
///
/// 来源
@@ -30,15 +35,16 @@ public class OrderAddRequest
/// 收入/支出
///
[EnumDataType(typeof(BalanceRecordTypeEnumType))]
- public BalanceRecordTypeEnumType Type { get; set; }
+ public BalanceRecordTypeEnumType? Type { get; set; } = BalanceRecordTypeEnumType.Out;
///
- /// 金额 + - 表示
+ /// 金额
///
+ [Range(0.01, double.MaxValue)]
public decimal Amount { get; set; }
///
- /// 餐补月份
+ /// 消费时间,由机器提供
///
- public string SubsidiesFromMonth { get; set; }
+ public DateTime CostDateTime { get; set; }
}
diff --git a/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs b/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs
new file mode 100644
index 00000000..bae8e194
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs
@@ -0,0 +1,109 @@
+using Dlhis.Entity.Canteen.Enums;
+using Kurisu.AspNetCore.Utils.Extensions;
+
+namespace Dlhis.Canteen.Order.Response;
+
+public class BalanceRecordResponse
+{
+ ///
+ /// 流水号
+ ///
+ public string No { get; set; }
+
+ ///
+ /// 档案号/QRCode
+ ///
+ public string UserId { get; set; }
+
+ ///
+ /// 姓名
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 学工号
+ ///
+ public string UserCode { get; set; }
+
+ ///
+ /// 部门号
+ ///
+ public string DepartmentNo { get; set; }
+
+ public string DepartmentName { 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 Guid BusinessPlaceCode { get; set; }
+ public string BusinessPlaceName { get; set; }
+
+ ///
+ /// 餐次
+ ///
+ public Guid? BusinessShiftCode { get; set; }
+ public string BusinessShiftName { get; set; }
+
+ ///
+ /// 所属成本日期
+ ///
+ public DateTime CostDate { get; set; }
+
+ ///
+ /// 消费机器唯一信息
+ ///
+ public string DeviceInfo { get; set; }
+
+ ///
+ /// 餐补月份
+ ///
+ public string SubsidiesFromMonth { get; set; }
+
+ ///
+ /// Ip
+ ///
+ public string IP { get; set; }
+
+ ///
+ /// 成本中心
+ ///
+ public string CostId { get; set; }
+
+ ///
+ /// 消费者所在基地
+ ///
+ public string OriginTenantId { get; set; }
+
+ ///
+ /// 成本计算是否允许跨基地范围
+ ///
+ public bool IsCostCrossTenant { get; set; }
+
+ ///
+ /// 数据状态
+ ///
+ public BalanceRecordStatusEnumType Status { get; set; }
+
+ ///
+ /// 数据状态描述
+ ///
+ public string StatusDesc => Status.GetDescription();
+}
diff --git a/Src/Dlhis.Canteen/Order/Services/IBalanceService.cs b/Src/Dlhis.Canteen/Order/Services/IBalanceService.cs
new file mode 100644
index 00000000..5a10e93c
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/Services/IBalanceService.cs
@@ -0,0 +1,10 @@
+using Dlhis.Canteen.Order.Request;
+using Dlhis.Canteen.Order.Response;
+using Kurisu.Core.DataAccess.Dto;
+
+namespace Dlhis.Canteen.Order.Services;
+
+public interface IBalanceService : IScopeDependency
+{
+ Task> GetPageAsync(BalanceRecordPageRequest request);
+}
diff --git a/Src/Dlhis.Canteen/Order/Services/IOrderService.cs b/Src/Dlhis.Canteen/Order/Services/IOrderService.cs
index 4beda47f..e7e36fca 100644
--- a/Src/Dlhis.Canteen/Order/Services/IOrderService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/IOrderService.cs
@@ -4,7 +4,7 @@ using Kurisu.Core.DataAccess.Dto;
namespace Dlhis.Canteen.Order.Services;
-public interface IOrderService
+public interface IOrderService : IScopeDependency
{
Task> GetPageAsync(OrderPageRequest request);
diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
new file mode 100644
index 00000000..8bb905f9
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
@@ -0,0 +1,30 @@
+using Dlhis.Canteen.Order.Request;
+using Dlhis.Canteen.Order.Response;
+using Dlhis.Entity.Canteen.Entities;
+using Kurisu.Core.DataAccess.Dto;
+using Kurisu.SqlSugar.Extensions;
+using Kurisu.SqlSugar.Services;
+
+namespace Dlhis.Canteen.Order.Services.Implements;
+
+public class BalanceService : IBalanceService
+{
+ private readonly IDbContext _dbContext;
+
+ public BalanceService(IDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task> GetPageAsync(BalanceRecordPageRequest request)
+ {
+ var page = await _dbContext.Queryable()
+ .WhereIF(request.SearchDateTimePeriod?.Start.HasValue == true, record => record.CreateTime >= request.SearchDateTimePeriod.Start)
+ .WhereIF(request.SearchDateTimePeriod?.End.HasValue == true, record => record.CreateTime <= request.SearchDateTimePeriod.End)
+ .OrderBy(record => record.CreateTime)
+ .Select()
+ .ToPageListAsync(request);
+
+ return page;
+ }
+}
diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
index 3f619363..4cf8f473 100644
--- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
@@ -1,19 +1,33 @@
using Dlhis.Canteen.Order.Request;
using Dlhis.Canteen.Order.Response;
+using Dlhis.Canteen.Setting.Services;
+using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Canteen.Entities;
+using Dlhis.Entity.Canteen.Enums;
+using Dlhis.Entity.Device.Entities;
+using Kurisu.AspNetCore.UnifyResultAndValidation;
+using Kurisu.AspNetCore.Utils;
+using Kurisu.AspNetCore.Utils.Extensions;
+using Kurisu.Core.CustomClass;
using Kurisu.Core.DataAccess.Dto;
using Kurisu.SqlSugar.Extensions;
using Kurisu.SqlSugar.Services;
+using Mapster;
+using SqlSugar;
namespace Dlhis.Canteen.Order.Services.Implements;
public class OrderService : IOrderService
{
private readonly IDbContext _dbContext;
+ private readonly ICanteenSettingService _canteenSettingService;
+ private readonly ILogger _logger;
- public OrderService(IDbContext dbContext)
+ public OrderService(IDbContext dbContext, ICanteenSettingService canteenSettingService, ILogger logger)
{
_dbContext = dbContext;
+ _canteenSettingService = canteenSettingService;
+ _logger = logger;
}
public async Task> GetPageAsync(OrderPageRequest request)
@@ -27,6 +41,208 @@ public class OrderService : IOrderService
public async Task AddAsync(OrderAddRequest request)
{
+ var device = await _dbContext.Queryable().Where(x => x.UniqueNo == request.DeviceUniqueNo).Where(x => x.Enable).FirstAsync();
+ device.ThrowIfNull("设备不存在或者尚未启用");
+ var registry = await _dbContext.Queryable().Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo).FirstAsync();
+ registry.ThrowIfNull("设备尚未注册");
+ var businessPlace = await _dbContext.Queryable().Where(x => x.Code == registry.BusinessPlaceCode).FirstAsync();
+ businessPlace.ThrowIfNull("营业点尚未设置");
+ var shifts = await _dbContext.Queryable().Where(x => x.BusinessPlaceCode == registry.BusinessPlaceCode).ToListAsync();
+
+ var shift = shifts.FirstOrDefault(x => new TimePeriod()
+ {
+ Start = x.Start,
+ End = x.End,
+
+ }.IsPresent(request.CostDateTime));
+
+ //根据档案号
+ var canteenUser = await _dbContext.Queryable()
+ .Where(x => x.UserId == request.UserUniqueNo || x.UserCode == request.UserUniqueNo)
+ .FirstAsync();
+
+ var gafinfo = await _dbContext.Queryable()
+ .Where(x => x.Guestno == canteenUser.UserId)
+ .FirstAsync();
+
+ var settings = await _canteenSettingService.GetUserSettingAsync(gafinfo.Guestno);
+ var switchTime = GetSetting(settings, CanteenSettingItemEnumType.BusinessSwitchTime);
+ //金额处理
+ request.Amount = request.Type == BalanceRecordTypeEnumType.In ? Math.Abs(request.Amount) : -Math.Abs(request.Amount);
+
+ var shiftTimePeriod = new TimePeriod()
+ {
+ Start = shift.Start,
+ End = shift.End
+ };
+
+ //成本日期 todo 优化
+ var costDate = DateTime.Now;
+ if (shift == null)
+ {
+ costDate = DateTime.Now;
+ }
+ else
+ {
+ if (shiftTimePeriod.IsCrossDay())
+ costDate = DateTime.Now.AddDays(-1);
+
+ var beginOfDay = DateTime.Today;
+ var setTime = beginOfDay.Add(switchTime.ToTimeSpan());
+ if (DateTime.Now < setTime)
+ costDate = DateTime.Now.AddDays(-1);
+ }
+
+ var order = new CanteenOrderEntity
+ {
+ RequestJson = request.ToJson(),
+ ThirdNo = request.ThirdNo,
+ Type = request.Type.Value,
+ OrderStatus = CanteenOrderStatusEnumType.Wait,
+ Name = gafinfo.Gname,
+ Source = request.Source,
+ UserId = canteenUser.UserId,
+ UserCode = canteenUser.UserCode,
+ Amount = request.Amount,
+ BusinessPlaceCode = businessPlace.Code,
+ BusinessShiftCode = shift?.Code,
+ CostDate = costDate.Date,
+ CostId = canteenUser.CostId,
+ DepartmentNo = gafinfo.Appellation,
+ DeviceInfo = device.Code.ToString(),
+
+ No = "O" + SnowFlakeHelper.Instance.NextId(),
+ SubsidiesFromMonth = DateTime.Now.ToString("yyyyMM"),
+ IsOffline = request.IsOffline,
+ IsCostCrossTenant = GetSetting(settings, CanteenSettingItemEnumType.AllowCrossTenant),
+
+ OriginTenantId = canteenUser.TenantId,
+
+ Status = BalanceRecordStatusEnumType.Doubtful,
+ };
+
+ var id = await _dbContext.InsertReturnIdentityAsync(order);
+ await GenerateChargeRecordAsync(id, settings, shifts, request.CostDateTime);
+ }
+
+ private static T GetSetting(Dictionary settings, CanteenSettingItemEnumType item, T defaultValue = default)
+ {
+ if (settings.TryGetValue(item, out var v))
+ {
+ return v.Adapt();
+ }
+
+ return defaultValue;
+ }
+
+ public async Task GenerateChargeRecordAsync(long orderId,
+ Dictionary settings,
+ List shifts,
+ DateTime costDateTime)
+ {
+ var order = await _dbContext.Queryable().Where(x => x.Id == orderId).FirstAsync();
+ //在线
+ if (!order.IsOffline)
+ {
+ shifts.FirstOrDefault(x => new TimePeriod()
+ {
+ Start = x.Start,
+ End = x.End,
+
+ }.IsPresent(costDateTime)).ThrowIfNull("当前非就餐时间,无法消费");
+ }
+
+ var beginOfDay = DateTime.Today;
+ var endOfDay = beginOfDay.AddHours(23).AddMinutes(59).AddSeconds(59);
+
+ var balanceRecords = await _dbContext.Queryable()
+ .Where(x => x.UserId == order.UserId)
+ .Where(x => x.CreateTime <= beginOfDay && x.CreateTime <= endOfDay) //今天消费记录
+ .ToListAsync();
+
+ var dayMarketCostMax = GetSetting(settings, CanteenSettingItemEnumType.DayMarketCostMax);
+ if (dayMarketCostMax != default)
+ {
+ var businessPlaceCodes = await _dbContext.Queryable().Where(x => x.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket).Select(x => x.Code).ToListAsync();
+ var cost = balanceRecords.Where(x => businessPlaceCodes.Contains(x.BusinessPlaceCode)).Sum(x => x.Amount);
+ if (cost + Math.Abs(order.Amount) > dayMarketCostMax)
+ {
+ throw new UserFriendlyException($"超出当天超市消费限制({dayMarketCostMax}),无法消费");
+ }
+ }
+
+ var allowRepeatInOneShift = GetSetting(settings, CanteenSettingItemEnumType.AllowRepeatInOneShift, true);
+ if (!allowRepeatInOneShift)
+ {
+ //todo 餐次问题
+ var costCount = balanceRecords.Where(x => x.BusinessShiftCode == order.BusinessShiftCode).Count();
+ if (costCount > 1)
+ {
+ throw new UserFriendlyException($"当前餐次不允许多次消费");
+ }
+ }
+
+ var onceCostMax = GetSetting(settings, CanteenSettingItemEnumType.OnceCostMax);
+ if (onceCostMax != default)
+ {
+ if (Math.Abs(order.Amount) > onceCostMax)
+ {
+ throw new UserFriendlyException($"一次消费金额不能超出{onceCostMax}");
+ }
+ }
+
+ var dayCostMax = GetSetting(settings, CanteenSettingItemEnumType.DayCostMax);
+ if (dayCostMax != default)
+ {
+ var cost = balanceRecords.Where(x => x.Type == BalanceRecordTypeEnumType.Out).Sum(x => Math.Abs(x.Amount));
+ if (cost + Math.Abs(order.Amount) > dayCostMax)
+ {
+ throw new UserFriendlyException($"超出当天消费限制({dayCostMax}),无法消费");
+ }
+ }
+
+
+ for (int i = 0; i < 5; i++)
+ {
+ try
+ {
+ var canteenUser = await _dbContext.Queryable().Where(x => x.UserId == order.UserId).FirstAsync();
+ //金额+-
+ canteenUser.Balance += order.Amount;
+
+ if (order.Type == BalanceRecordTypeEnumType.Out)
+ {
+ if (canteenUser.Balance < 0)
+ {
+ throw new UserFriendlyException("余额不足,无法消费");
+ }
+ }
+
+ var effect = await _dbContext.Updateable()
+ .SetColumns(x => x.Balance == canteenUser.Balance + order.Amount)
+ .SetColumns(x => x.Version == x.Version + 1)
+ .Where(x => x.UserId == order.UserId && x.Version == canteenUser.Version)//必须与查询时的version一致
+ .ExecuteCommandAsync();
+
+ if (effect <= 0)
+ {
+ throw new VersionExceptions("更新版本冲突");
+ }
+
+ var balanceRecord = order.Adapt();
+ await _dbContext.InsertAsync(balanceRecord);
+
+ break;
+ }
+ catch (Exception ex) when (ex is VersionExceptions)
+ {
+ _logger.LogError(ex, ex.Message);
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
}
}
diff --git a/Src/Dlhis.Canteen/Order/TimePeriodExtensions.cs b/Src/Dlhis.Canteen/Order/TimePeriodExtensions.cs
new file mode 100644
index 00000000..a1d2b197
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/TimePeriodExtensions.cs
@@ -0,0 +1,58 @@
+using Kurisu.Core.CustomClass;
+
+namespace Dlhis.Canteen.Order;
+
+
+///
+/// 临时的扩展类 todo: 嵌入框架
+///
+public static class TimePeriodExtensions
+{
+ public static bool IsPresent(this TimePeriod period, DateTime dateTime)
+ {
+ int hour = dateTime.Hour;
+ int minute = dateTime.Minute;
+ IReadOnlyList hourPeriod = GetHourPeriod();
+ if (hourPeriod.Contains(hour))
+ {
+ if (hour == period.Start.Value.Hour)
+ {
+ return minute > period.Start.Value.Minute;
+ }
+
+ if (hour == period.End.Value.Hour)
+ {
+ return minute < period.End.Value.Minute;
+ }
+ }
+
+ return false;
+
+
+ IReadOnlyList GetHourPeriod()
+ {
+ List list = new List();
+ if (period.IsCrossDay())
+ {
+ for (int i = 0; i < 25 - period.Start.Value.Hour; i++)
+ {
+ list.Add(period.Start.Value.Hour + i);
+ }
+
+ for (int j = 0; j < period.End.Value.Hour; j++)
+ {
+ list.Add(j + 1);
+ }
+ }
+ else
+ {
+ for (int k = period.Start.Value.Hour; k < period.End.Value.Hour + 1; k++)
+ {
+ list.Add(k);
+ }
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/Src/Dlhis.Canteen/Program.cs b/Src/Dlhis.Canteen/Program.cs
index 3aea2b2b..a8487e57 100644
--- a/Src/Dlhis.Canteen/Program.cs
+++ b/Src/Dlhis.Canteen/Program.cs
@@ -1,20 +1,19 @@
using Kurisu.AspNetCore.Startup;
using Kurisu.Startup;
-namespace Dlhis.Canteen
-{
- class Program
- {
- static void Main(string[] args)
- {
- KurisuHost.Run(true, args);
- }
- }
+namespace Dlhis.Canteen;
- public class Startup : DefaultStartup
+class Program
+{
+ static void Main(string[] args)
+ {
+ KurisuHost.Run(true, args);
+ }
+}
+
+public class Startup : DefaultStartup
+{
+ public Startup(IConfiguration configuration) : base(configuration)
{
- public Startup(IConfiguration configuration) : base(configuration)
- {
- }
}
}
\ No newline at end of file
diff --git a/Src/Dlhis.Canteen/Properties/launchSettings.json b/Src/Dlhis.Canteen/Properties/launchSettings.json
index 66e536a5..706bb9bb 100644
--- a/Src/Dlhis.Canteen/Properties/launchSettings.json
+++ b/Src/Dlhis.Canteen/Properties/launchSettings.json
@@ -6,15 +6,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
- "applicationUrl": "http://localhost:5002"
- },
- "Docker": {
- "commandName": "Docker",
- "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
- "environmentVariables": {
- "ASPNETCORE_URLS": "http://+:80"
- },
- "publishAllPorts": true
+ "applicationUrl": "http://localhost:5008"
}
},
"$schema": "https://json.schemastore.org/launchsettings.json"
diff --git a/Src/Dlhis.Canteen/SqlSugarPack.cs b/Src/Dlhis.Canteen/SqlSugarPack.cs
index 36ee6c60..03c33fa6 100644
--- a/Src/Dlhis.Canteen/SqlSugarPack.cs
+++ b/Src/Dlhis.Canteen/SqlSugarPack.cs
@@ -1,16 +1,19 @@
-using Kurisu.AspNetCore;
-using Kurisu.AspNetCore.Startup;
+using Kurisu.AspNetCore.Startup;
using Kurisu.SqlSugar.Extensions;
-using SqlSugar;
namespace Dlhis.Canteen;
public class SqlSugarPack : BaseAppPack
{
- public override bool IsBeforeUseRouting { get; }
+ public override bool IsBeforeUseRouting { get; }
public override void ConfigureServices(IServiceCollection services)
{
services.AddSqlSugar();
}
+
+ public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+
+ }
}