Files
edr-platform/apps/edr-freight-api/src/modules/rule-engine/services/yards.duplicate-label.spec.ts
Marshal b671f07ce6 fix(rule-engine): merge duplicate Sebeta yards, block dupes
Two active Sebeta yards (LEGACY_DEST/'Sebeta' and SEBETA/'sebeta')
split rates and routes across different yard ids, so route-scoped rate
lookups missed. Migration repoints every yard reference to the survivor,
retires the duplicate, and adds partial unique indexes on active label
and code. Service now rejects case-insensitive duplicate labels on
create/update - the old guard only compared generated codes, which
missed labels whose existing code differs (LEGACY_DEST).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 09:25:02 +00:00

37 lines
1.3 KiB
TypeScript

import { ConflictException } from '@nestjs/common';
import { YardsService } from './yards.service';
import type { Yard } from '../entities/yard.entity';
const sebeta = { id: 'yard-1', code: 'LEGACY_DEST', label: 'Sebeta' } as Yard;
const service = (): YardsService =>
new YardsService(
{
findById: async (id: string) => ({ ...sebeta, id }),
findByCode: async () => null,
findByLabelInsensitive: async (label: string) =>
label.trim().toLowerCase() === 'sebeta' ? sebeta : null,
create: async (d: Partial<Yard>) => d as Yard,
update: async (_id: string, d: Partial<Yard>) => d as Yard,
} as never,
{ resolveCreateOrder: async () => 1 } as never,
);
describe('duplicate yard labels are rejected', () => {
it('blocks create even when the generated code differs (Sebeta vs LEGACY_DEST)', async () => {
await expect(
service().create({ label: ' sebeta ', country: 'ET' } as never),
).rejects.toThrow(ConflictException);
});
it('blocks renaming a yard onto another yard label, allows renaming itself', async () => {
await expect(
service().update('yard-2', { label: 'SEBETA' } as never),
).rejects.toThrow(ConflictException);
await expect(
service().update('yard-1', { label: 'Sebeta' } as never),
).resolves.toBeTruthy();
});
});