Add validators and services for Product Galleries and Product Tags
- Implemented Create, Delete, Get, and Update validators for Product Galleries. - Added Create, Delete, Get, and Update validators for Product Tags. - Created service classes for handling Discount Categories, Discount Orders, Discount Products, Discount Shopping Cart, Product Categories, Product Galleries, and Product Tags. - Each service class integrates with CQRS for command and query handling. - Established mapping profiles for Product Galleries.
This commit is contained in:
+7
-109
@@ -21,119 +21,17 @@ public class MigrateNetworkParentIdCommandHandler : IRequestHandler<MigrateNetwo
|
||||
|
||||
public async Task<MigrateNetworkParentIdResult> Handle(MigrateNetworkParentIdCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("=== Starting Manual ParentId → NetworkParentId Migration ===");
|
||||
_logger.LogInformation("=== ParentId Migration No Longer Needed (ParentId Removed) ===");
|
||||
|
||||
var errors = new List<string>();
|
||||
|
||||
// Step 1: Check if already migrated
|
||||
var alreadyMigrated = await _context.Users
|
||||
.Where(u => u.ParentId != null && u.NetworkParentId != null)
|
||||
.AnyAsync(cancellationToken);
|
||||
|
||||
if (alreadyMigrated)
|
||||
{
|
||||
_logger.LogWarning("⚠️ Migration already completed!");
|
||||
return new MigrateNetworkParentIdResult
|
||||
{
|
||||
Success = false,
|
||||
Message = "Migration already completed. All users with ParentId have NetworkParentId."
|
||||
};
|
||||
}
|
||||
|
||||
// Step 2: Find users to migrate
|
||||
var usersToMigrate = await _context.Users
|
||||
.Where(u => u.ParentId != null && u.NetworkParentId == null)
|
||||
.OrderBy(u => u.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (usersToMigrate.Count == 0)
|
||||
{
|
||||
return new MigrateNetworkParentIdResult
|
||||
{
|
||||
Success = true,
|
||||
Message = "No users to migrate. All done!"
|
||||
};
|
||||
}
|
||||
|
||||
// Step 3: Group by ParentId
|
||||
var parentGroups = usersToMigrate.GroupBy(u => u.ParentId);
|
||||
|
||||
int migratedCount = 0;
|
||||
int skippedCount = 0;
|
||||
|
||||
foreach (var group in parentGroups)
|
||||
{
|
||||
var parentId = group.Key;
|
||||
var children = group.OrderBy(u => u.Id).ToList();
|
||||
|
||||
if (children.Count > 2)
|
||||
{
|
||||
var warning = $"Parent {parentId} has {children.Count} children! Taking first 2 only.";
|
||||
_logger.LogWarning(warning);
|
||||
errors.Add(warning);
|
||||
|
||||
skippedCount += (children.Count - 2);
|
||||
children = children.Take(2).ToList();
|
||||
}
|
||||
|
||||
// Assign NetworkParentId and LegPosition
|
||||
for (int i = 0; i < children.Count && i < 2; i++)
|
||||
{
|
||||
var child = children[i];
|
||||
child.NetworkParentId = parentId;
|
||||
child.LegPosition = i == 0 ? NetworkLeg.Left : NetworkLeg.Right;
|
||||
migratedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Save changes
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_logger.LogInformation("✅ Migration Completed! Migrated={Migrated}, Skipped={Skipped}",
|
||||
migratedCount, skippedCount);
|
||||
|
||||
// Step 5: Validate
|
||||
await ValidateAsync(errors, cancellationToken);
|
||||
|
||||
// ParentId has been removed from User entity
|
||||
// This migration is no longer necessary
|
||||
return new MigrateNetworkParentIdResult
|
||||
{
|
||||
Success = true,
|
||||
MigratedCount = migratedCount,
|
||||
SkippedCount = skippedCount,
|
||||
ValidationErrors = errors,
|
||||
Message = $"Migration completed successfully. Migrated: {migratedCount}, Skipped: {skippedCount}"
|
||||
Message = "ParentId field has been removed. This migration is obsolete.",
|
||||
MigratedCount = 0,
|
||||
SkippedCount = 0,
|
||||
ValidationErrors = new List<string>()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task ValidateAsync(List<string> errors, CancellationToken cancellationToken)
|
||||
{
|
||||
// Check orphaned nodes
|
||||
var orphanedUsers = await _context.Users
|
||||
.Where(u => u.NetworkParentId != null &&
|
||||
!_context.Users.Any(p => p.Id == u.NetworkParentId))
|
||||
.Select(u => u.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (orphanedUsers.Any())
|
||||
{
|
||||
var error = $"Found {orphanedUsers.Count} orphaned users: {string.Join(", ", orphanedUsers)}";
|
||||
_logger.LogError(error);
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
// Check binary tree violation
|
||||
var parentsWithTooManyChildren = await _context.Users
|
||||
.Where(u => u.NetworkParentId != null)
|
||||
.GroupBy(u => u.NetworkParentId)
|
||||
.Select(g => new { ParentId = g.Key, Count = g.Count() })
|
||||
.Where(x => x.Count > 2)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (parentsWithTooManyChildren.Any())
|
||||
{
|
||||
var error = $"Binary tree violation! {parentsWithTooManyChildren.Count} parents have >2 children";
|
||||
_logger.LogError(error);
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user