feat(T4.13): add PackageFeature CRUD support
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m41s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m41s
- Proto: add feature_ids to Create/Update/Get package messages - Commands: add FeatureIds to Create/Update commands - Handlers: sync PackageFeature join entities on create/update - Queries: include PackageFeatures, map FeatureIds in responses - Bump NuGet to v0.0.188
This commit is contained in:
+1
@@ -22,4 +22,5 @@ public record CreateNewPackageCommand : IRequest<CreateNewPackageResponseDto>
|
||||
public int MaxNetworkLevel { get; init; } = 15;
|
||||
public long MagicWalletMaxDeposit { get; init; } = 1_000_000_000;
|
||||
public long MagicWalletMaxCredit { get; init; } = 2_500_000_000;
|
||||
public List<long> FeatureIds { get; init; } = new();
|
||||
}
|
||||
+16
@@ -16,6 +16,22 @@ public class CreateNewPackageCommandHandler : IRequestHandler<CreateNewPackageCo
|
||||
await _context.Packages.AddAsync(entity, cancellationToken);
|
||||
entity.AddDomainEvent(new CreateNewPackageEvent(entity));
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// Sync PackageFeatures
|
||||
if (request.FeatureIds.Any())
|
||||
{
|
||||
foreach (var featureId in request.FeatureIds)
|
||||
{
|
||||
_context.PackageFeatures.Add(new PackageFeature
|
||||
{
|
||||
PackageId = entity.Id,
|
||||
ClubFeatureId = featureId,
|
||||
IsIncluded = true
|
||||
});
|
||||
}
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
return entity.Adapt<CreateNewPackageResponseDto>();
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -24,4 +24,5 @@ public record UpdatePackageCommand : IRequest<Unit>
|
||||
public int MaxNetworkLevel { get; init; }
|
||||
public long MagicWalletMaxDeposit { get; init; }
|
||||
public long MagicWalletMaxCredit { get; init; }
|
||||
public List<long> FeatureIds { get; init; } = new();
|
||||
}
|
||||
+17
@@ -16,6 +16,23 @@ public class UpdatePackageCommandHandler : IRequestHandler<UpdatePackageCommand,
|
||||
request.Adapt(entity);
|
||||
_context.Packages.Update(entity);
|
||||
entity.AddDomainEvent(new UpdatePackageEvent(entity));
|
||||
|
||||
// Sync PackageFeatures — remove old, add new
|
||||
var existingFeatures = await _context.PackageFeatures
|
||||
.Where(pf => pf.PackageId == request.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
_context.PackageFeatures.RemoveRange(existingFeatures);
|
||||
|
||||
foreach (var featureId in request.FeatureIds)
|
||||
{
|
||||
_context.PackageFeatures.Add(new PackageFeature
|
||||
{
|
||||
PackageId = request.Id,
|
||||
ClubFeatureId = featureId,
|
||||
IsIncluded = true
|
||||
});
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
return Unit.Value;
|
||||
}
|
||||
|
||||
+16
-2
@@ -14,6 +14,7 @@ public class GetAllPackageByFilterQueryHandler : IRequestHandler<GetAllPackageBy
|
||||
.Where(x => !x.IsDeleted)
|
||||
.ApplyOrder(sortBy: request.SortBy)
|
||||
.AsNoTracking()
|
||||
.Include(x => x.PackageFeatures)
|
||||
.AsQueryable();
|
||||
if (request.Filter is not null)
|
||||
{
|
||||
@@ -25,11 +26,24 @@ public class GetAllPackageByFilterQueryHandler : IRequestHandler<GetAllPackageBy
|
||||
.Where(x => request.Filter.Price == null || x.Price == request.Filter.Price)
|
||||
;
|
||||
}
|
||||
var packages = await query
|
||||
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var models = packages.Select(p =>
|
||||
{
|
||||
var model = p.Adapt<GetAllPackageByFilterResponseModel>();
|
||||
model.FeatureIds = p.PackageFeatures?
|
||||
.Where(pf => pf.IsIncluded)
|
||||
.Select(pf => pf.ClubFeatureId)
|
||||
.ToList() ?? new();
|
||||
return model;
|
||||
}).ToList();
|
||||
|
||||
return new GetAllPackageByFilterResponseDto
|
||||
{
|
||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.ProjectToType<GetAllPackageByFilterResponseModel>().ToListAsync(cancellationToken)
|
||||
Models = models
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -31,4 +31,5 @@ public class GetAllPackageByFilterResponseDto
|
||||
public int MaxNetworkLevel { get; set; }
|
||||
public long MagicWalletMaxDeposit { get; set; }
|
||||
public long MagicWalletMaxCredit { get; set; }
|
||||
public List<long> FeatureIds { get; set; } = new();
|
||||
}
|
||||
|
||||
+11
-4
@@ -11,12 +11,19 @@ public class GetPackageQueryHandler : IRequestHandler<GetPackageQuery, GetPackag
|
||||
public async Task<GetPackageResponseDto> Handle(GetPackageQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _context.Packages
|
||||
var package = await _context.Packages
|
||||
.AsNoTracking()
|
||||
.Include(x => x.PackageFeatures)
|
||||
.Where(x => x.Id == request.Id)
|
||||
.ProjectToType<GetPackageResponseDto>()
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
.FirstOrDefaultAsync(cancellationToken)
|
||||
?? throw new NotFoundException(nameof(Package), request.Id);
|
||||
|
||||
return response ?? throw new NotFoundException(nameof(Package), request.Id);
|
||||
var response = package.Adapt<GetPackageResponseDto>();
|
||||
response.FeatureIds = package.PackageFeatures?
|
||||
.Where(pf => pf.IsIncluded)
|
||||
.Select(pf => pf.ClubFeatureId)
|
||||
.ToList() ?? new();
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,5 @@ public class GetPackageResponseDto
|
||||
public int MaxNetworkLevel { get; set; }
|
||||
public long MagicWalletMaxDeposit { get; set; }
|
||||
public long MagicWalletMaxCredit { get; set; }
|
||||
public List<long> FeatureIds { get; set; } = new();
|
||||
}
|
||||
Reference in New Issue
Block a user