feat(awards): add cleanupDuplicateAwards utility and CLI tool skeleton
This commit is contained in:
parent
2e1fbf8006
commit
a1bdf4ffb1
2 changed files with 96 additions and 0 deletions
|
|
@ -160,3 +160,85 @@ export async function notifyAwardGrants(
|
|||
console.error("[Awards] Failed to send award-grant notifications:", err);
|
||||
}
|
||||
}
|
||||
|
||||
export interface CleanupResult {
|
||||
profilesChecked: number;
|
||||
profilesModified: number;
|
||||
duplicatesRemoved: number;
|
||||
details: { profileId: number; removed: number }[];
|
||||
}
|
||||
|
||||
export async function cleanupDuplicateAwards(
|
||||
payload: PayloadType,
|
||||
): Promise<CleanupResult> {
|
||||
const result: CleanupResult = {
|
||||
profilesChecked: 0,
|
||||
profilesModified: 0,
|
||||
duplicatesRemoved: 0,
|
||||
details: [],
|
||||
};
|
||||
|
||||
let page = 1;
|
||||
let hasMore = true;
|
||||
|
||||
while (hasMore) {
|
||||
const profiles = await payload.find({
|
||||
collection: "profiles",
|
||||
limit: 500,
|
||||
page,
|
||||
depth: 0,
|
||||
overrideAccess: true,
|
||||
});
|
||||
|
||||
result.profilesChecked += profiles.totalDocs;
|
||||
|
||||
for (const profile of profiles.docs) {
|
||||
const awards = (profile as unknown as ProgressionDoc).progression?.awards;
|
||||
if (!awards || awards.length <= 1) continue;
|
||||
|
||||
const seen = new Map<number, { entry: AwardGrantEntry; index: number }>();
|
||||
const indicesToRemove: number[] = [];
|
||||
|
||||
for (let i = 0; i < awards.length; i++) {
|
||||
const entry = awards[i];
|
||||
const id = awardIdOf(entry);
|
||||
if (id === null) continue;
|
||||
|
||||
const existing = seen.get(id);
|
||||
if (existing) {
|
||||
if (entry.awardedAt < existing.entry.awardedAt) {
|
||||
indicesToRemove.push(existing.index);
|
||||
seen.set(id, { entry, index: i });
|
||||
} else {
|
||||
indicesToRemove.push(i);
|
||||
}
|
||||
} else {
|
||||
seen.set(id, { entry, index: i });
|
||||
}
|
||||
}
|
||||
|
||||
if (indicesToRemove.length > 0) {
|
||||
const cleaned = awards.filter((_, i) => !indicesToRemove.includes(i));
|
||||
await payload.update({
|
||||
collection: "profiles",
|
||||
id: profile.id,
|
||||
data: {
|
||||
progression: {
|
||||
...(profile as unknown as ProgressionDoc).progression,
|
||||
awards: cleaned,
|
||||
},
|
||||
},
|
||||
overrideAccess: true,
|
||||
});
|
||||
result.profilesModified += 1;
|
||||
result.duplicatesRemoved += indicesToRemove.length;
|
||||
result.details.push({ profileId: profile.id, removed: indicesToRemove.length });
|
||||
}
|
||||
}
|
||||
|
||||
hasMore = page < profiles.totalPages;
|
||||
page += 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
14
src/tools/cli/grant_award.ts
Normal file
14
src/tools/cli/grant_award.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { getPayload } from "payload";
|
||||
import config from "@payload-config";
|
||||
|
||||
(async () => {
|
||||
const payload = await getPayload({ config });
|
||||
|
||||
// payload.logger.log("Retrieving user profiles...");
|
||||
|
||||
// await payload.find({
|
||||
// collection: "profiles",
|
||||
// overrideAccess: true,
|
||||
// select
|
||||
// })
|
||||
})();
|
||||
Loading…
Reference in a new issue