fix: 메인 예약 명령 요약과 자율 행동 상태를 복원
예약 명령 mutation 응답에도 autorunLimit을 포함해 입력 직후 색상과 상태가 사라지지 않게 한다. Ref getBrief 계약에 맞춰 명령 인자를 요약하고 자율 행동 종료 연월과 현재 시각을 표시한다.
This commit is contained in:
@@ -165,20 +165,22 @@ const loadGeneralTurns = async (db: DatabaseClient, generalId: number): Promise<
|
||||
return buildTurnListFromRows(rows, MAX_GENERAL_TURNS);
|
||||
};
|
||||
|
||||
const loadGeneralAutorunLimit = async (db: DatabaseClient, generalId: number): Promise<number | null> => {
|
||||
const general = await db.general.findUnique({ where: { id: generalId }, select: { meta: true } });
|
||||
const rawAutorunLimit = isRecord(general?.meta) ? general.meta.autorun_limit : undefined;
|
||||
return typeof rawAutorunLimit === 'number' && Number.isFinite(rawAutorunLimit) ? Math.trunc(rawAutorunLimit) : null;
|
||||
};
|
||||
|
||||
export const getGeneralTurnSnapshot = async (db: DatabaseClient, generalId: number): Promise<ReservedTurnSnapshot> => {
|
||||
const [turns, revisionRow, general] = await Promise.all([
|
||||
const [turns, revisionRow, autorunLimit] = await Promise.all([
|
||||
loadGeneralTurns(db, generalId),
|
||||
db.generalTurnRevision.findUnique({ where: { generalId } }),
|
||||
db.general.findUnique({ where: { id: generalId }, select: { meta: true } }),
|
||||
loadGeneralAutorunLimit(db, generalId),
|
||||
]);
|
||||
const rawAutorunLimit = isRecord(general?.meta) ? general.meta.autorun_limit : undefined;
|
||||
return {
|
||||
revision: revisionRow?.revision ?? 0,
|
||||
turns: serializeTurnList(turns),
|
||||
autorunLimit:
|
||||
typeof rawAutorunLimit === 'number' && Number.isFinite(rawAutorunLimit)
|
||||
? Math.trunc(rawAutorunLimit)
|
||||
: null,
|
||||
autorunLimit,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -331,7 +333,7 @@ export const setGeneralTurns = async (
|
||||
}
|
||||
}
|
||||
await persistGeneralTurns(db, generalId, turns);
|
||||
return { revision, turns: serializeTurnList(turns) };
|
||||
return { revision, turns: serializeTurnList(turns), autorunLimit: await loadGeneralAutorunLimit(db, generalId) };
|
||||
};
|
||||
|
||||
export const setGeneralTurn = async (
|
||||
@@ -357,7 +359,7 @@ export const shiftGeneralTurns = async (
|
||||
const turns = await loadGeneralTurns(db, generalId);
|
||||
const shifted = applyShift(turns, amount);
|
||||
await persistGeneralTurns(db, generalId, shifted);
|
||||
return { revision, turns: serializeTurnList(shifted) };
|
||||
return { revision, turns: serializeTurnList(shifted), autorunLimit: await loadGeneralAutorunLimit(db, generalId) };
|
||||
};
|
||||
|
||||
export const repeatGeneralTurns = async (
|
||||
@@ -372,7 +374,7 @@ export const repeatGeneralTurns = async (
|
||||
const revision = await claimGeneralRevision(db, generalId, expectedRevision);
|
||||
const turns = applyRepeat(await loadGeneralTurns(db, generalId), amount);
|
||||
await persistGeneralTurns(db, generalId, turns);
|
||||
return { revision, turns: serializeTurnList(turns) };
|
||||
return { revision, turns: serializeTurnList(turns), autorunLimit: await loadGeneralAutorunLimit(db, generalId) };
|
||||
};
|
||||
|
||||
export const setNationTurns = async (
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
ReservedTurnRevisionConflictError,
|
||||
} from '../src/turns/reservedTurns.js';
|
||||
|
||||
const buildDb = () => {
|
||||
const buildDb = (autorunLimit: number | null = null) => {
|
||||
const generalTurns = new Map<number, GeneralTurnRow[]>();
|
||||
const nationTurns = new Map<string, NationTurnRow[]>();
|
||||
const generalRevisions = new Map<number, number>();
|
||||
@@ -45,7 +45,7 @@ const buildDb = () => {
|
||||
findFirst: async () => null,
|
||||
},
|
||||
general: {
|
||||
findUnique: async () => null,
|
||||
findUnique: async () => ({ meta: autorunLimit === null ? {} : { autorun_limit: autorunLimit } }),
|
||||
},
|
||||
city: {
|
||||
findUnique: async () => null,
|
||||
@@ -200,22 +200,25 @@ const buildDb = () => {
|
||||
|
||||
describe('reservedTurns', () => {
|
||||
it('sets and shifts general turns', async () => {
|
||||
const { db } = buildDb();
|
||||
const { db } = buildDb(2408);
|
||||
|
||||
const initial = await setGeneralTurn(db, 1, 0, 'che_화계', { destCityId: 10 }, 0);
|
||||
|
||||
expect(initial.revision).toBe(1);
|
||||
expect(initial.turns).toHaveLength(MAX_GENERAL_TURNS);
|
||||
expect(initial.turns[0]?.action).toBe('che_화계');
|
||||
expect(initial.autorunLimit).toBe(2408);
|
||||
|
||||
const pushed = await shiftGeneralTurns(db, 1, 1, initial.revision);
|
||||
expect(pushed.revision).toBe(2);
|
||||
expect(pushed.turns[0]?.action).toBe('휴식');
|
||||
expect(pushed.turns[1]?.action).toBe('che_화계');
|
||||
expect(pushed.autorunLimit).toBe(2408);
|
||||
|
||||
const pulled = await shiftGeneralTurns(db, 1, -1, pushed.revision);
|
||||
expect(pulled.turns[0]?.action).toBe('che_화계');
|
||||
expect(pulled.turns[MAX_GENERAL_TURNS - 1]?.action).toBe('휴식');
|
||||
expect(pulled.autorunLimit).toBe(2408);
|
||||
|
||||
await expect(setGeneralTurn(db, 1, 2, 'che_훈련', {}, 1)).rejects.toBeInstanceOf(
|
||||
ReservedTurnRevisionConflictError
|
||||
@@ -285,7 +288,7 @@ describe('reservedTurns', () => {
|
||||
});
|
||||
|
||||
it('repeats the leading general pattern at the legacy interval', async () => {
|
||||
const { db } = buildDb();
|
||||
const { db } = buildDb(2408);
|
||||
const seeded = await setGeneralTurns(
|
||||
db,
|
||||
4,
|
||||
@@ -309,6 +312,7 @@ describe('reservedTurns', () => {
|
||||
'che_사기진작',
|
||||
'che_징병',
|
||||
]);
|
||||
expect(repeated.autorunLimit).toBe(2408);
|
||||
});
|
||||
|
||||
it('supports nation bulk/repeat and preserves the legacy amount-12 no-op', async () => {
|
||||
|
||||
@@ -869,7 +869,7 @@ describe('appRouter', () => {
|
||||
});
|
||||
|
||||
it('validates and persists general command arguments from the authenticated owner', async () => {
|
||||
const general = buildGeneralRow({ id: 13 });
|
||||
const general = buildGeneralRow({ id: 13, meta: { autorun_limit: 2408 } });
|
||||
const writes: unknown[] = [];
|
||||
const changeJournal = new ChangeJournal();
|
||||
const caller = appRouter.createCaller(
|
||||
@@ -885,6 +885,7 @@ describe('appRouter', () => {
|
||||
});
|
||||
|
||||
expect(response.turns[0]).toMatchObject({ action: 'che_화계', args: { destCityId: 7 } });
|
||||
expect(response.autorunLimit).toBe(2408);
|
||||
expect(writes).toHaveLength(1);
|
||||
const written = writes[0] as { data: unknown[] };
|
||||
expect(written.data).toHaveLength(30);
|
||||
|
||||
Reference in New Issue
Block a user