fix(server): hide CLOSED rows from preview for legacy mini-program compatibility
The previous fix made publishDaySlots CLOSE rows instead of DELETE them. That works correctly on the server, but the live mini-program still ships the old schedule.vue which only knows about isPublished (no status field). It would re-render the CLOSED rows with the '已发布' badge, making it look like 'clear day' did nothing. Hide CLOSED rows from getSchedulePreview so the legacy client shows '当日暂无排课' for rest days — the same UX it had before this fix shipped. All-CLOSED days return []; days with a mix return only the non-CLOSED rows; days the cron hasn't touched still return the ghost template. The republished mini-program (with status-aware rendering) will see the same [] for rest days, which is consistent. Tests: 4 new specs covering all-OPEN / all-CLOSED / mixed / empty-day cases.
This commit is contained in:
@@ -231,6 +231,69 @@ describe('TimeSlotService', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getSchedulePreview
|
||||
// -------------------------------------------------------------------------
|
||||
describe('getSchedulePreview', () => {
|
||||
const date = '2026-04-07'
|
||||
|
||||
it('returns OPEN/FULL rows with isPublished: true', async () => {
|
||||
mockPrisma.timeSlot.findMany.mockResolvedValueOnce([
|
||||
makeSlot({ id: 'slot-1', startTime: '09:00', endTime: '10:00', status: TimeSlotStatus.OPEN }),
|
||||
makeSlot({ id: 'slot-2', startTime: '10:30', endTime: '11:30', status: TimeSlotStatus.FULL }),
|
||||
])
|
||||
|
||||
const result = await service.getSchedulePreview(date)
|
||||
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result.every((s) => s.isPublished === true)).toBe(true)
|
||||
})
|
||||
|
||||
it('HIDES CLOSED rows so the legacy client does not render them as "已发布"', async () => {
|
||||
// Simulates an admin "clear day" — DB now has 13 CLOSED rows.
|
||||
mockPrisma.timeSlot.findMany.mockResolvedValueOnce(
|
||||
Array.from({ length: 13 }, (_, i) =>
|
||||
makeSlot({
|
||||
id: `slot-${i}`,
|
||||
startTime: `${String(8 + Math.floor(i / 2)).padStart(2, '0')}:${i % 2 === 0 ? '00' : '30'}`,
|
||||
endTime: `${String(8 + Math.floor(i / 2)).padStart(2, '0')}:${i % 2 === 0 ? '30' : '30'}`,
|
||||
status: TimeSlotStatus.CLOSED,
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
const result = await service.getSchedulePreview(date)
|
||||
|
||||
// Critical for online compatibility: the legacy client must see []
|
||||
// so it shows "当日暂无排课", not 13 phantom "已发布" slots.
|
||||
expect(result).toEqual([])
|
||||
})
|
||||
|
||||
it('returns the OPEN subset and hides CLOSED when mixed', async () => {
|
||||
mockPrisma.timeSlot.findMany.mockResolvedValueOnce([
|
||||
makeSlot({ id: 'open-1', status: TimeSlotStatus.OPEN }),
|
||||
makeSlot({ id: 'closed-1', status: TimeSlotStatus.CLOSED, startTime: '10:00', endTime: '11:00' }),
|
||||
makeSlot({ id: 'open-2', status: TimeSlotStatus.OPEN, startTime: '10:30', endTime: '11:30' }),
|
||||
])
|
||||
|
||||
const result = await service.getSchedulePreview(date)
|
||||
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result.map((s) => s.id).sort()).toEqual(['open-1', 'open-2'])
|
||||
expect(result.find((s) => s.id === 'closed-1')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('returns the ghost template when the day has no rows at all', async () => {
|
||||
mockPrisma.timeSlot.findMany.mockResolvedValueOnce([])
|
||||
|
||||
const result = await service.getSchedulePreview(date)
|
||||
|
||||
// Ghost = isPublished false, id null.
|
||||
expect(result.length).toBeGreaterThan(0)
|
||||
expect(result.every((s) => s.isPublished === false && s.id === null)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// createManualSlot
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user