feat : update

This commit is contained in:
2026-09-30 19:34:28 +07:00 Unverified
parent 69a4d34b97
commit da3d7d84ac
30 changed files with 10724 additions and 883 deletions
+2 -28
View File
@@ -154,12 +154,6 @@ export async function getStygianSchedule(scheduleId: number) {
};
}
export async function getActiveStygianSchedule() {
const [active] = await getDb().select({ scheduleId: stygianSchedules.scheduleId }).from(stygianSchedules)
.where(eq(stygianSchedules.isActive, true)).orderBy(desc(stygianSchedules.activatedAt)).limit(1);
return active ? getStygianSchedule(active.scheduleId) : null;
}
function itemValues(groupId: string, position: number, item: StygianRecommendationItemInput) {
return {
groupId,
@@ -168,8 +162,8 @@ function itemValues(groupId: string, position: number, item: StygianRecommendati
catalogKey: item.kind === "character" || item.kind === "weapon" || item.kind === "artifact" ? item.catalogKey : null,
weaponKey: item.kind === "character" ? item.weaponKey : null,
artifactKey: item.kind === "character" ? item.artifactKey : null,
characterKey: item.kind === "constellation" ? item.characterKey : null,
constellationLevel: item.kind === "constellation" || item.kind === "character" ? item.constellationLevel : null,
refinement: item.kind === "character" ? item.refinement : null,
constellationLevel: item.kind === "character" ? item.constellationLevel : null,
element: item.kind === "element" ? item.element : null,
};
}
@@ -207,23 +201,3 @@ export async function saveStygianRecommendations(scheduleId: number, input: unkn
return updated;
});
}
export async function activateStygianSchedule(scheduleId: number, expectedVersion: number) {
return getDb().transaction(async (tx) => {
const [target] = await tx.select({ scheduleId: stygianSchedules.scheduleId }).from(stygianSchedules).where(and(
eq(stygianSchedules.scheduleId, scheduleId),
eq(stygianSchedules.version, expectedVersion),
)).limit(1);
if (!target) throw new Error("ข้อมูลถูกแก้ไขจากหน้าอื่น กรุณารีเฟรชแล้วลองอีกครั้ง");
await tx.update(stygianSchedules).set({ isActive: false, activatedAt: null }).where(eq(stygianSchedules.isActive, true));
const [updated] = await tx.update(stygianSchedules).set({
isActive: true,
activatedAt: new Date(),
version: sql`${stygianSchedules.version} + 1`,
updatedAt: new Date(),
}).where(eq(stygianSchedules.scheduleId, scheduleId)).returning({ version: stygianSchedules.version });
const aggregateId = stygianAggregateId(scheduleId);
await tx.insert(outboxEvents).values({ topic: "stygian", aggregateId, eventType: "stygian.updated", payload: { id: aggregateId, version: updated.version, scheduleId } });
return updated;
});
}
+9 -1
View File
@@ -69,7 +69,7 @@ describe("Stygian recommendation validation", () => {
...base,
teams: [[
{ kind: "character", catalogKey: "10000001", weaponKey: null, artifactKey: null, constellationLevel: null },
{ kind: "character", catalogKey: "10000002", weaponKey: "WEAPON", artifactKey: null, constellationLevel: 2 },
{ kind: "character", catalogKey: "10000002", weaponKey: "WEAPON", artifactKey: null, constellationLevel: 2, refinement: 5 },
{ kind: "character", catalogKey: "10000003", weaponKey: null, artifactKey: "ARTIFACT", constellationLevel: 0 },
{ kind: "character", catalogKey: "10000004", weaponKey: null, artifactKey: null, constellationLevel: 6 },
]],
@@ -93,4 +93,12 @@ describe("Stygian recommendation validation", () => {
const units = Array.from({ length: 100 }, (_, index) => ({ kind: "artifact", catalogKey: `A${index}` }));
expect(stygianRecommendationsSchema.safeParse({ ...base, teams, units }).success).toBe(true);
});
it("rejects constellation units", () => {
expect(stygianRecommendationsSchema.safeParse({
...base,
teams: [],
units: [{ kind: "constellation", characterKey: "10000001", constellationLevel: 1 }],
}).success).toBe(false);
});
});
+1 -6
View File
@@ -30,6 +30,7 @@ const characterRecommendationSchema = z.strictObject({
weaponKey: z.string().min(1).max(64).nullable().default(null),
artifactKey: z.string().min(1).max(64).nullable().default(null),
constellationLevel: z.number().int().min(0).max(6).nullable().default(null),
refinement: z.number().int().min(1).max(5).nullable().default(null),
});
const catalogItemSchema = z.discriminatedUnion("kind", [
@@ -37,16 +38,10 @@ const catalogItemSchema = z.discriminatedUnion("kind", [
z.strictObject({ kind: z.literal("weapon"), catalogKey: z.string().min(1).max(64) }),
z.strictObject({ kind: z.literal("artifact"), catalogKey: z.string().min(1).max(64) }),
z.strictObject({ kind: z.literal("element"), element: z.enum(stygianElements) }),
z.strictObject({
kind: z.literal("constellation"),
characterKey: z.string().min(1).max(64),
constellationLevel: z.number().int().min(1).max(6),
}),
]);
function recommendationKey(item: z.infer<typeof catalogItemSchema>) {
if (item.kind === "element") return `${item.kind}:${item.element}`;
if (item.kind === "constellation") return `${item.kind}:${item.characterKey}:${item.constellationLevel}`;
return `${item.kind}:${item.catalogKey}`;
}