Merge branch 'feat-wallet' into development

This commit is contained in:
2024-11-14 15:44:01 +08:00
84 changed files with 2096 additions and 1784 deletions

View File

@@ -7,6 +7,4 @@ namespace Dlhis.Basic.Organization.Services;
public interface IGainfoMealService : IScopeDependency
{
Task<Pagination<GainfoMealResponse>> GetPageAsync(GainfoMealPageRequest request);
Task MigrationAsync(GainfoBalanceMigrationRequest request);
}

View File

@@ -9,7 +9,6 @@ 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;
using Kurisu.AspNetCore.Utils.Extensions;
using SqlSugar;
@@ -28,138 +27,47 @@ public class GainfoMealService : IGainfoMealService
public async Task<Pagination<GainfoMealResponse>> GetPageAsync(GainfoMealPageRequest request)
{
var tenantId = _currentUser.GetStringTenantId();
var factory = _currentUser.GetStringTenantId();
var factories = await GetWalletFactoriesAsync(factory);
var page = await _dbContext.Queryable<GainfoMealEntity>()
.LeftJoin<GainfoEntity>((meal, gainfo) => meal.UserCode == gainfo.Code)
.LeftJoin<GainfoLeaveEntity>((meal, gainfo, gainfoLeave) => meal.UserCode == gainfoLeave.Code)
.LeftJoin<DepartmentEntity>((meal, gainfo, gainfoLeave, dept1) => dept1.No == gainfo.DepartmentNo)
.LeftJoin<DepartmentEntity>((meal, gainfo, gainfoLeave, dept1, dept2) => dept2.No == gainfoLeave.DepartmentNo)
.WhereIF(request.Search.IsPresent(), (meal, gainfo, gainfoLeave, dept1, dept2) => meal.UserCode == request.Search
|| gainfo.Name == request.Search
|| gainfoLeave.Name == request.Search)
.Where((meal, gainfo, gainfoLeave) => gainfo.Factory == tenantId || gainfoLeave.Factory == tenantId)
.WhereIF(request.IsLeave, (meal, gainfo, gainfoLeave) => SqlFunc.Subqueryable<GainfoLeaveEntity>().Where(x => x.Code == meal.UserCode).Any())
.WhereIF(request.IsLeave && request.SearchDateTimePeriod.HasValue(), (meal, gainfo, gainfoLeave) => gainfoLeave.ResignationDate >= request.SearchDateTimePeriod.Start && gainfoLeave.ResignationDate <= request.SearchDateTimePeriod.End)
.Select((meal, gainfo, gainfoLeave, dept1, dept2) => new GainfoMealResponse
return await _dbContext.Queryable<GainfoEntity>().AS(request.IsLeave ? "GainfoLeave" : "Gainfo")
.LeftJoin<DepartmentEntity>((x, dept) => dept.No == x.DepartmentNo)
.WhereIF(request.Search.IsPresent(), x => x.Code == request.Search || x.Name == request.Search)
.Where(x => SqlFunc.Subqueryable<BalanceRecordEntity>().Where(p => p.UserCode == x.Code && factories.Contains(p.TenantId)).Any())
.WhereIF(request.IsLeave && request.SearchDateTimePeriod.HasValue(), x => x.ResignationDate >= request.SearchDateTimePeriod.Start &&
x.ResignationDate <= request.SearchDateTimePeriod.End)
.Select((x, dept) => new GainfoMealResponse
{
Balance = meal.Balance,
UserCode = meal.UserCode,
UserName = SqlFunc.IsNull(gainfo.Name, gainfoLeave.Name),
UserNo = SqlFunc.IsNull(gainfo.No, gainfoLeave.No),
DepartmentName = SqlFunc.IsNull(dept1.Name, dept2.Name),
Status = SqlFunc.IsNullOrEmpty(gainfo.No) ? GainfoStatusEnumType.Leave : GainfoStatusEnumType.Working
UserCode = x.Code,
UserName = x.Name,
UserNo = x.No,
DepartmentName = dept.Name,
Status = request.IsLeave
? GainfoStatusEnumType.Leave
: GainfoStatusEnumType.Working,
CurrentMealSupplementAmount = SqlFunc.Subqueryable<MealSupplementRecordEntity>()
.Where(p => p.Code == x.Code)
.Where(p => factories.Contains(p.Factory))
.WhereIF(request.SearchDateTimePeriod.HasValue(), p => p.Date >= request.SearchDateTimePeriod.Start && p.Date <= request.SearchDateTimePeriod.End)
.Sum(p => p.Amount),
CurrentBalance = SqlFunc.Subqueryable<BalanceRecordEntity>()
.Where(p => factories.Contains(p.TenantId))
.Where(p => p.UserCode == x.Code && p.Status == BalanceRecordStatusEnumType.Valid && p.IsDeleted == false)
.Where(p => p.Source != BalanceRecordSourceEnumType.EMealVoucher)
.Sum(p => p.Amount)
})
.ToPageListAsync(request);
var userCodes = page.Data.Select(x => x.UserCode).ToList();
var summary = await _dbContext.Queryable<MealSupplementRecordEntity>()
.Where(x => userCodes.Contains(x.Code))
.WhereIF(request.SearchDateTimePeriod.HasValue(), x => x.Date >= request.SearchDateTimePeriod.Start && x.Date <= request.SearchDateTimePeriod.End)
.GroupBy(x => x.Code)
.Select(x => new
{
x.Code,
Amount = SqlFunc.AggregateSum(x.Amount)
})
.ToListAsync();
page.Data.ForEach(x => { x.MealSupplementAmount = summary.FirstOrDefault(item => item.Code == x.UserCode)?.Amount ?? 0; });
return page;
}
public async Task MigrationAsync(GainfoBalanceMigrationRequest request)
//***********************************************************************************************************************************************************************
public async Task<List<string>> GetWalletFactoriesAsync(string factory)
{
//只能针对离职人员
var gainfoLeave = await _dbContext.Queryable<GainfoLeaveEntity>().Where(x => x.Code == request.BeforeCode).SingleAsync();
gainfoLeave.ThrowIfNull("需要对已离职人员迁移");
var wallets = await _dbContext.Queryable<WalletEntity>().ToListAsync();
var code = wallets.First(x => x.Factory == factory).Code;
var beforeBalance = await _dbContext.Queryable<GainfoMealEntity>().Where(x => x.UserCode == request.BeforeCode).Select(x => x.Balance).SingleAsync();
(beforeBalance <= 0).ThrowIfTrue("不可操作,余额不足");
var now = DateTime.Now;
await _dbContext.InsertAsync(new BalanceRecordEntity
{
No = SnowFlakeHelper.Instance.NextId().ToString(),
UserNo = gainfoLeave.No,
Name = gainfoLeave.Name,
UserCode = gainfoLeave.Code,
DepartmentNo = gainfoLeave.DepartmentNo,
Source = BalanceRecordSourceEnumType.BalanceMigration,
Type = BalanceRecordTypeEnumType.In,
Amount = -Math.Abs(beforeBalance),
BusinessPlaceCode = null,
BusinessShiftCode = null,
ShiftType = null,
CostDate = now.Date,
DeviceUniqueNo = null,
IP = null,
CostId = gainfoLeave.CostId,
OriginTenantId = gainfoLeave.Factory,
IsCostCrossTenant = false,
Status = BalanceRecordStatusEnumType.Valid,
CostDateTime = DateTime.Now,
Remark = $"{gainfoLeave.Code}:余额转出",
ApplicationType = CanteenApplicationTypeEnumType.BalanceMigration,
TenantId = gainfoLeave.Factory,
Werks = gainfoLeave.Werks,
IsDeleted = false,
});
var beforeBalanceAmount = await _dbContext.Queryable<BalanceRecordEntity>()
.Where(x => x.UserCode == gainfoLeave.Code)
.Where(x => x.Status == BalanceRecordStatusEnumType.Valid)
.SumAsync(x => x.Amount);
await _dbContext.Updateable<GainfoMealEntity>()
.SetColumns(x => x.Balance == beforeBalanceAmount)
.SetColumns(x => x.ModifiedTime == DateTime.Now)
.SetColumns(x => x.Version == x.Version + 1)
.Where(x => x.UserCode == request.BeforeCode) //不需要判断version
.ExecuteCommandAsync();
//转移到现有人员
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == request.NowCode).SingleAsync();
gainfo.ThrowIfNull("目标人员不存在");
await _dbContext.InsertAsync(new BalanceRecordEntity
{
No = SnowFlakeHelper.Instance.NextId().ToString(),
UserNo = gainfo.No,
Name = gainfo.Name,
UserCode = gainfo.Code,
DepartmentNo = gainfo.DepartmentNo,
Source = BalanceRecordSourceEnumType.BalanceMigration,
Type = BalanceRecordTypeEnumType.In,
Amount = beforeBalance,
BusinessPlaceCode = null,
BusinessShiftCode = null,
ShiftType = null,
CostDate = now.Date,
DeviceUniqueNo = null,
IP = null,
CostId = gainfo.CostId,
OriginTenantId = gainfo.Factory,
IsCostCrossTenant = false,
Status = BalanceRecordStatusEnumType.Valid,
CostDateTime = DateTime.Now,
Remark = $"{gainfoLeave.Code}:余额转入",
ApplicationType = CanteenApplicationTypeEnumType.MealSupplement,
TenantId = gainfo.Factory,
Werks = gainfo.Werks,
IsDeleted = false,
});
var nowGainfoMeal = await _dbContext.Queryable<GainfoMealEntity>().Where(x => x.UserCode == request.NowCode).SingleAsync();
var nowBalance = nowGainfoMeal.Balance + beforeBalance;
await _dbContext.Updateable<GainfoMealEntity>()
.SetColumns(x => x.Balance == nowBalance)
.SetColumns(x => x.ModifiedTime == DateTime.Now)
.SetColumns(x => x.Version == x.Version + 1)
.Where(x => x.UserCode == request.NowCode && x.Version == nowGainfoMeal.Version)
.ExecuteCommandThrowVersionAsync("转入失败");
return wallets.Where(x => x.Code == code).Select(x => x.Factory).ToList();
}
}

View File

@@ -197,10 +197,9 @@ public class GainfoService : IGainfoService
var info = await _gainfoStore.Queryable(GainfoStatusEnumType.Working)
.LeftJoin<DepartmentEntity>((ga, department) => ga.DepartmentNo == department.No)
.LeftJoin<GainfoMealEntity>((ga, department, mealUser) => ga.Code == mealUser.UserCode)
.LeftJoin<BasicTypeEntity>((ga, department, mealUser, type) => type.Code == ga.CardType.ToString() && type.Type == "timeperiod")
.LeftJoin<BasicTypeEntity>((ga, department, type) => type.Code == ga.CardType.ToString() && type.Type == "timeperiod")
.Where((ga, department) => ga.Id == gainfo.Id)
.Select((ga, department, mealUser, type) => new GainfoCurrentResponse
.Select((ga, department, type) => new GainfoCurrentResponse
{
UserNo = ga.No,
Birthday = ga.Birthday,
@@ -210,10 +209,6 @@ public class GainfoService : IGainfoService
UserCode = ga.Code,
UserName = ga.Name,
Factory = ga.Factory,
MealInfo = new GainfoCurrentMealInfoResponse
{
Balance = mealUser.Balance
},
CardType = ga.CardType,
CardTypeName = type.Display
}).SingleAsync();
@@ -225,7 +220,7 @@ public class GainfoService : IGainfoService
var tenantResult = await _tenantApi.GetTenantByCodeAsync(info.Factory);
if (tenantResult is { Data: not null })
{
info.Factory = tenantResult.Data.Name;
info.FactoryName = tenantResult.Data.Name;
}
}
catch (Exception)