add fixes to claims and seasons

This commit is contained in:
JCEEE
2026-07-30 11:12:35 +01:00
parent 57ef30d3a7
commit b254564436
24 changed files with 2517 additions and 704 deletions
+194
View File
@@ -553,5 +553,199 @@ export async function migrate(): Promise<void> {
}
}
// ── 16. Add seasons json field to fams ──
{
const c = await getCollection("fams");
if (c) {
const hasField = c.fields.some((f: any) => f.name === "seasons");
if (!hasField) {
console.log("[migrate] Adding seasons to fams...");
c.fields.push({ name: "seasons", type: "json" });
await updateCollection(c.id, {
name: "fams", type: "base",
listRule: c.listRule, viewRule: c.viewRule,
createRule: c.createRule, updateRule: c.updateRule,
deleteRule: c.deleteRule, fields: c.fields,
});
} else {
console.log(` ↳ fams.seasons already exists`);
}
}
}
// ── 17. Add seasonIds json field to assigned_chores ──
{
const c = await getCollection("assigned_chores");
if (c) {
const hasField = c.fields.some((f: any) => f.name === "seasonIds");
if (!hasField) {
console.log("[migrate] Adding seasonIds to assigned_chores...");
c.fields.push({ name: "seasonIds", type: "json" });
await updateCollection(c.id, {
name: "assigned_chores", type: "base",
listRule: c.listRule, viewRule: c.viewRule,
createRule: c.createRule, updateRule: c.updateRule,
deleteRule: c.deleteRule, fields: c.fields,
});
} else {
console.log(` ↳ assigned_chores.seasonIds already exists`);
}
}
}
// ── 18. Create seasons collection if missing ──
{
const existing = await getCollection("seasons");
if (!existing) {
console.log("[migrate] Creating seasons collection...");
const t = await auth();
const famsCol = await getCollection("fams");
const res = await fetch(`${PB_ENDPOINT}/api/collections`, {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${t}` },
body: JSON.stringify({
name: "seasons", type: "base",
listRule: "", viewRule: "",
createRule: null, updateRule: null, deleteRule: null,
fields: [
{ name: "famId", type: "relation", required: true, maxSelect: 1, collectionId: famsCol?.id || "" },
{ name: "name", type: "text", required: true },
{ name: "color", type: "text" },
{ name: "active", type: "bool" },
{ name: "autoDisable", type: "date" },
{ name: "autoStart", type: "date" },
],
}),
});
if (res.ok) console.log(" ✓ Created seasons collection");
else console.log(` ↳ seasons collection creation skipped or already exists`);
} else {
console.log(` ↳ seasons collection already exists`);
}
}
// ── 19. Add active bool to existing seasons collection ──
{
const c = await getCollection("seasons");
if (c) {
const hasActive = c.fields.some((f: any) => f.name === "active");
if (!hasActive) {
console.log("[migrate] Adding active bool to seasons...");
c.fields.push({ name: "active", type: "bool" });
await updateCollection(c.id, {
name: "seasons", type: "base",
listRule: c.listRule, viewRule: c.viewRule,
createRule: c.createRule, updateRule: c.updateRule,
deleteRule: c.deleteRule, fields: c.fields,
});
} else {
console.log(` ↳ seasons.active already exists`);
}
}
}
// ── 20. Backfill active=true from fams.seasons array ──
{
const t = await auth();
const fams = await getCollection("fams");
if (fams) {
const hasSeasonsField = fams.fields.some((f: any) => f.name === "seasons");
if (hasSeasonsField) {
console.log("[migrate] Backfilling season active flags from fams.seasons...");
const allFams = await fetch(`${PB_ENDPOINT}/api/collections/fams/records?perPage=1000`, {
headers: { Authorization: `Bearer ${t}` },
});
const famData = await allFams.json();
for (const fam of famData.items || []) {
const activeIds = fam.seasons || [];
if (activeIds.length > 0) {
for (const sid of activeIds) {
await fetch(`${PB_ENDPOINT}/api/collections/seasons/records/${sid}`, {
method: "PATCH",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${t}` },
body: JSON.stringify({ active: true }),
});
}
}
}
console.log(` ↳ backfilled ${famData.items?.length || 0} fams`);
} else {
console.log(` ↳ fams.seasons already removed`);
}
}
}
// ── 21. Remove seasons field from fams ──
{
const c = await getCollection("fams");
if (c) {
const hasField = c.fields.some((f: any) => f.name === "seasons");
if (hasField) {
console.log("[migrate] Removing seasons field from fams...");
c.fields = c.fields.filter((f: any) => f.name !== "seasons");
await updateCollection(c.id, {
name: "fams", type: "base",
listRule: c.listRule, viewRule: c.viewRule,
createRule: c.createRule, updateRule: c.updateRule,
deleteRule: c.deleteRule, fields: c.fields,
});
} else {
console.log(` ↳ fams.seasons already removed`);
}
}
}
// ── 22. Convert rewards.claimed boolean to status select field ──
{
const c = await getCollection("rewards");
if (c) {
const hasClaimedField = c.fields.some((f: any) => f.name === "claimed");
const hasStatusField = c.fields.some((f: any) => f.name === "status");
if (hasClaimedField && !hasStatusField) {
console.log("[migrate] Converting rewards.claimed to status field...");
// Fetch all rewards to backfill status
const t = await auth();
let page = 1;
let total = 0;
while (true) {
const res = await fetch(`${PB_ENDPOINT}/api/collections/rewards/records?page=${page}&perPage=100`, {
headers: { Authorization: `Bearer ${t}` },
});
const data = await res.json();
for (const r of data.items || []) {
const status = r.claimed ? "claimed" : "unclaimed";
await fetch(`${PB_ENDPOINT}/api/collections/rewards/records/${r.id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${t}` },
body: JSON.stringify({ status }),
});
total++;
}
if (!data.items || data.items.length < 100) break;
page++;
}
console.log(` ↳ backfilled ${total} rewards with status`);
// Remove claimed field and add status + requestedAt fields
c.fields = c.fields.filter((f: any) => f.name !== "claimed");
if (!c.fields.some((f: any) => f.name === "status")) {
c.fields.push({ name: "status", type: "select", required: true, values: ["unclaimed", "requested", "claimed"], maxSelect: 1 });
}
if (!c.fields.some((f: any) => f.name === "requestedAt")) {
c.fields.push({ name: "requestedAt", type: "date", required: false });
}
await updateCollection(c.id, {
name: "rewards", type: "base",
listRule: c.listRule, viewRule: c.viewRule,
createRule: c.createRule, updateRule: c.updateRule,
deleteRule: c.deleteRule, fields: c.fields,
});
} else if (!hasClaimedField) {
console.log(` ↳ rewards.claimed already converted to status`);
}
}
}
console.log("[migrate] Done");
}