feat(backend): Lagerbehälter-Umlagerung für Honigchargen (Modul 32)
Neues HoneyBatchRelocation-Modell dokumentiert jede Umlagerung einer Honigcharge zwischen Lagerbehältern (von/nach, Zeitpunkt, Benutzer, Notiz). HoneyBatchesService.relocate() aktualisiert HoneyBatch.storageContainerId transaktional zusammen mit dem Historieneintrag; wirft NotFoundException bei unbekanntem Zielbehälter. Neue Endpunkte: POST /honey-batches/:id/relocate, GET /honey-batches/:id/relocations. honeyBatchInclude liefert jetzt zusätzlich den aktuell zugeordneten storageContainer mit. Unit- und E2E-Tests ergänzt (Mehrfachumlagerung, Historienreihenfolge, 404 bei unbekanntem Behälter). Migration auf Dev- und Test-Datenbank angewendet.
This commit is contained in:
1 parent
fa13543578
commit
59a320ae36
7 files changed
+284
No files matched your search
+28
@@ -0,0 +1,28 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "HoneyBatchRelocation" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"honeyBatchId" TEXT NOT NULL,
|
||||||
|
"fromStorageContainerId" TEXT,
|
||||||
|
"toStorageContainerId" TEXT NOT NULL,
|
||||||
|
"userId" TEXT,
|
||||||
|
"notes" TEXT,
|
||||||
|
"relocatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "HoneyBatchRelocation_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "HoneyBatchRelocation_honeyBatchId_relocatedAt_idx" ON "HoneyBatchRelocation"("honeyBatchId", "relocatedAt");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "HoneyBatchRelocation" ADD CONSTRAINT "HoneyBatchRelocation_honeyBatchId_fkey" FOREIGN KEY ("honeyBatchId") REFERENCES "HoneyBatch"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "HoneyBatchRelocation" ADD CONSTRAINT "HoneyBatchRelocation_fromStorageContainerId_fkey" FOREIGN KEY ("fromStorageContainerId") REFERENCES "StorageContainer"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "HoneyBatchRelocation" ADD CONSTRAINT "HoneyBatchRelocation_toStorageContainerId_fkey" FOREIGN KEY ("toStorageContainerId") REFERENCES "StorageContainer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "HoneyBatchRelocation" ADD CONSTRAINT "HoneyBatchRelocation_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
@@ -54,6 +54,7 @@ model User {
|
|||||||
queenEvaluations QueenEvaluation[]
|
queenEvaluations QueenEvaluation[]
|
||||||
webhookSubscriptions WebhookSubscription[]
|
webhookSubscriptions WebhookSubscription[]
|
||||||
documents Document[]
|
documents Document[]
|
||||||
|
honeyBatchRelocations HoneyBatchRelocation[]
|
||||||
|
|
||||||
@@index([role])
|
@@index([role])
|
||||||
}
|
}
|
||||||
@@ -563,6 +564,7 @@ model HoneyBatch {
|
|||||||
|
|
||||||
measurements HoneyMeasurement[]
|
measurements HoneyMeasurement[]
|
||||||
bottlingBatches BottlingBatch[]
|
bottlingBatches BottlingBatch[]
|
||||||
|
relocations HoneyBatchRelocation[]
|
||||||
|
|
||||||
@@index([status])
|
@@index([status])
|
||||||
@@index([extractionId])
|
@@index([extractionId])
|
||||||
@@ -609,10 +611,30 @@ model StorageContainer {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
honeyBatches HoneyBatch[]
|
honeyBatches HoneyBatch[]
|
||||||
|
relocationsFrom HoneyBatchRelocation[] @relation("RelocationFrom")
|
||||||
|
relocationsTo HoneyBatchRelocation[] @relation("RelocationTo")
|
||||||
|
|
||||||
@@index([status])
|
@@index([status])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Umlagerungshistorie einer Honigcharge zwischen Lagerbehältern (Abschnitt 26, v1.x Modul 32)
|
||||||
|
model HoneyBatchRelocation {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
honeyBatchId String
|
||||||
|
honeyBatch HoneyBatch @relation(fields: [honeyBatchId], references: [id])
|
||||||
|
fromStorageContainerId String?
|
||||||
|
fromStorageContainer StorageContainer? @relation("RelocationFrom", fields: [fromStorageContainerId], references: [id])
|
||||||
|
toStorageContainerId String
|
||||||
|
toStorageContainer StorageContainer @relation("RelocationTo", fields: [toStorageContainerId], references: [id])
|
||||||
|
userId String?
|
||||||
|
user User? @relation(fields: [userId], references: [id])
|
||||||
|
notes String?
|
||||||
|
relocatedAt DateTime @default(now())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@index([honeyBatchId, relocatedAt])
|
||||||
|
}
|
||||||
|
|
||||||
enum StockCategory {
|
enum StockCategory {
|
||||||
HONEY
|
HONEY
|
||||||
CONSUMABLE
|
CONSUMABLE
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class RelocateHoneyBatchDto {
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
storageContainerId!: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
notes?: string;
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { CurrentUser } from '../auth/decorators/current-user.decorator';
|
|||||||
import type { AuthenticatedUser } from '../auth/types/authenticated-user';
|
import type { AuthenticatedUser } from '../auth/types/authenticated-user';
|
||||||
import { CreateHoneyBatchDto } from './dto/create-honey-batch.dto';
|
import { CreateHoneyBatchDto } from './dto/create-honey-batch.dto';
|
||||||
import { CreateHoneyMeasurementDto } from './dto/create-honey-measurement.dto';
|
import { CreateHoneyMeasurementDto } from './dto/create-honey-measurement.dto';
|
||||||
|
import { RelocateHoneyBatchDto } from './dto/relocate-honey-batch.dto';
|
||||||
import { HoneyBatchesService } from './honey-batches.service';
|
import { HoneyBatchesService } from './honey-batches.service';
|
||||||
|
|
||||||
@ApiTags('honey-batches')
|
@ApiTags('honey-batches')
|
||||||
@@ -29,6 +30,21 @@ export class HoneyBatchesController {
|
|||||||
return this.honeyBatchesService.traceability(id);
|
return this.honeyBatchesService.traceability(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get(':id/relocations')
|
||||||
|
findRelocations(@Param('id') id: string) {
|
||||||
|
return this.honeyBatchesService.findRelocations(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Roles(Role.ADMIN, Role.BEEKEEPER, Role.STAFF)
|
||||||
|
@Post(':id/relocate')
|
||||||
|
relocate(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body() dto: RelocateHoneyBatchDto,
|
||||||
|
@CurrentUser() actor: AuthenticatedUser,
|
||||||
|
) {
|
||||||
|
return this.honeyBatchesService.relocate(id, dto, actor.id);
|
||||||
|
}
|
||||||
|
|
||||||
@Roles(Role.ADMIN, Role.BEEKEEPER)
|
@Roles(Role.ADMIN, Role.BEEKEEPER)
|
||||||
@Post()
|
@Post()
|
||||||
create(
|
create(
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ describe('HoneyBatchesService', () => {
|
|||||||
findMany: jest.Mock;
|
findMany: jest.Mock;
|
||||||
findUnique: jest.Mock;
|
findUnique: jest.Mock;
|
||||||
create: jest.Mock;
|
create: jest.Mock;
|
||||||
|
update: jest.Mock;
|
||||||
};
|
};
|
||||||
honeyMeasurement: { create: jest.Mock };
|
honeyMeasurement: { create: jest.Mock };
|
||||||
|
storageContainer: { findUnique: jest.Mock };
|
||||||
|
honeyBatchRelocation: { create: jest.Mock; findMany: jest.Mock };
|
||||||
|
$transaction: jest.Mock;
|
||||||
};
|
};
|
||||||
let auditLog: { record: jest.Mock };
|
let auditLog: { record: jest.Mock };
|
||||||
|
|
||||||
@@ -47,8 +51,12 @@ describe('HoneyBatchesService', () => {
|
|||||||
findMany: jest.fn(),
|
findMany: jest.fn(),
|
||||||
findUnique: jest.fn(),
|
findUnique: jest.fn(),
|
||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
},
|
},
|
||||||
honeyMeasurement: { create: jest.fn() },
|
honeyMeasurement: { create: jest.fn() },
|
||||||
|
storageContainer: { findUnique: jest.fn() },
|
||||||
|
honeyBatchRelocation: { create: jest.fn(), findMany: jest.fn() },
|
||||||
|
$transaction: jest.fn(),
|
||||||
};
|
};
|
||||||
auditLog = { record: jest.fn() };
|
auditLog = { record: jest.fn() };
|
||||||
const webhooks = { dispatch: jest.fn().mockResolvedValue(undefined) };
|
const webhooks = { dispatch: jest.fn().mockResolvedValue(undefined) };
|
||||||
@@ -98,4 +106,94 @@ describe('HoneyBatchesService', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('relocate', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
prisma.$transaction.mockImplementation(
|
||||||
|
async (
|
||||||
|
callback: (tx: typeof prisma) => Promise<unknown>,
|
||||||
|
): Promise<unknown> => callback(prisma),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws NotFoundException when the target container does not exist', async () => {
|
||||||
|
prisma.honeyBatch.findUnique.mockResolvedValue({
|
||||||
|
...honeyBatch,
|
||||||
|
storageContainerId: null,
|
||||||
|
});
|
||||||
|
prisma.storageContainer.findUnique.mockResolvedValue(null);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
service.relocate(
|
||||||
|
'batch-1',
|
||||||
|
{ storageContainerId: 'missing' },
|
||||||
|
'user-1',
|
||||||
|
),
|
||||||
|
).rejects.toBeInstanceOf(NotFoundException);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('records the relocation and updates the batch container', async () => {
|
||||||
|
prisma.honeyBatch.findUnique
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
...honeyBatch,
|
||||||
|
storageContainerId: 'container-old',
|
||||||
|
})
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
...honeyBatch,
|
||||||
|
storageContainerId: 'container-new',
|
||||||
|
});
|
||||||
|
prisma.storageContainer.findUnique.mockResolvedValue({
|
||||||
|
id: 'container-new',
|
||||||
|
});
|
||||||
|
prisma.honeyBatchRelocation.create.mockResolvedValue({
|
||||||
|
id: 'relocation-1',
|
||||||
|
honeyBatchId: 'batch-1',
|
||||||
|
fromStorageContainerId: 'container-old',
|
||||||
|
toStorageContainerId: 'container-new',
|
||||||
|
});
|
||||||
|
|
||||||
|
await service.relocate(
|
||||||
|
'batch-1',
|
||||||
|
{ storageContainerId: 'container-new', notes: 'Umzug ins Lager 2' },
|
||||||
|
'user-1',
|
||||||
|
);
|
||||||
|
|
||||||
|
const [[createArg]] = prisma.honeyBatchRelocation.create.mock.calls as [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
fromStorageContainerId: string | null;
|
||||||
|
toStorageContainerId: string;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
expect(createArg.data.fromStorageContainerId).toBe('container-old');
|
||||||
|
expect(createArg.data.toStorageContainerId).toBe('container-new');
|
||||||
|
const [[updateArg]] = prisma.honeyBatch.update.mock.calls as [
|
||||||
|
[{ data: { storageContainerId: string } }],
|
||||||
|
];
|
||||||
|
expect(updateArg.data.storageContainerId).toBe('container-new');
|
||||||
|
expect(auditLog.record).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({ entityType: 'HoneyBatchRelocation' }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('findRelocations', () => {
|
||||||
|
it('returns the relocation history ordered by date', async () => {
|
||||||
|
prisma.honeyBatch.findUnique.mockResolvedValue(honeyBatch);
|
||||||
|
prisma.honeyBatchRelocation.findMany.mockResolvedValue([
|
||||||
|
{ id: 'relocation-1', honeyBatchId: 'batch-1' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await service.findRelocations('batch-1');
|
||||||
|
|
||||||
|
expect(result).toEqual([{ id: 'relocation-1', honeyBatchId: 'batch-1' }]);
|
||||||
|
const [[findArg]] = prisma.honeyBatchRelocation.findMany.mock.calls as [
|
||||||
|
[{ where: { honeyBatchId: string } }],
|
||||||
|
];
|
||||||
|
expect(findArg.where.honeyBatchId).toBe('batch-1');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -5,9 +5,11 @@ import { WebhooksService } from '../webhooks/webhooks.service';
|
|||||||
import { HoneyBatchStatus } from '../../generated/prisma';
|
import { HoneyBatchStatus } from '../../generated/prisma';
|
||||||
import { CreateHoneyBatchDto } from './dto/create-honey-batch.dto';
|
import { CreateHoneyBatchDto } from './dto/create-honey-batch.dto';
|
||||||
import { CreateHoneyMeasurementDto } from './dto/create-honey-measurement.dto';
|
import { CreateHoneyMeasurementDto } from './dto/create-honey-measurement.dto';
|
||||||
|
import { RelocateHoneyBatchDto } from './dto/relocate-honey-batch.dto';
|
||||||
|
|
||||||
const honeyBatchInclude = {
|
const honeyBatchInclude = {
|
||||||
measurements: true,
|
measurements: true,
|
||||||
|
storageContainer: true,
|
||||||
extraction: {
|
extraction: {
|
||||||
include: {
|
include: {
|
||||||
harvests: {
|
harvests: {
|
||||||
@@ -90,6 +92,50 @@ export class HoneyBatchesService {
|
|||||||
return this.findById(id);
|
return this.findById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async relocate(id: string, dto: RelocateHoneyBatchDto, actingUserId: string) {
|
||||||
|
const honeyBatch = await this.findById(id);
|
||||||
|
const targetContainer = await this.prisma.storageContainer.findUnique({
|
||||||
|
where: { id: dto.storageContainerId },
|
||||||
|
});
|
||||||
|
if (!targetContainer) {
|
||||||
|
throw new NotFoundException('Storage container not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const relocation = await this.prisma.$transaction(async (tx) => {
|
||||||
|
const created = await tx.honeyBatchRelocation.create({
|
||||||
|
data: {
|
||||||
|
honeyBatchId: id,
|
||||||
|
fromStorageContainerId: honeyBatch.storageContainerId,
|
||||||
|
toStorageContainerId: dto.storageContainerId,
|
||||||
|
userId: actingUserId,
|
||||||
|
notes: dto.notes,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await tx.honeyBatch.update({
|
||||||
|
where: { id },
|
||||||
|
data: { storageContainerId: dto.storageContainerId },
|
||||||
|
});
|
||||||
|
return created;
|
||||||
|
});
|
||||||
|
await this.auditLog.record({
|
||||||
|
entityType: 'HoneyBatchRelocation',
|
||||||
|
entityId: relocation.id,
|
||||||
|
action: 'CREATE',
|
||||||
|
userId: actingUserId,
|
||||||
|
afterData: relocation,
|
||||||
|
});
|
||||||
|
return this.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findRelocations(id: string) {
|
||||||
|
await this.findById(id);
|
||||||
|
return this.prisma.honeyBatchRelocation.findMany({
|
||||||
|
where: { honeyBatchId: id },
|
||||||
|
include: { fromStorageContainer: true, toStorageContainer: true },
|
||||||
|
orderBy: { relocatedAt: 'desc' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async traceability(id: string) {
|
async traceability(id: string) {
|
||||||
const honeyBatch = await this.findById(id);
|
const honeyBatch = await this.findById(id);
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ interface HoneyBatchBody {
|
|||||||
id: string;
|
id: string;
|
||||||
batchNumber: string;
|
batchNumber: string;
|
||||||
measurements: { id: string }[];
|
measurements: { id: string }[];
|
||||||
|
storageContainerId: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RelocationBody {
|
||||||
|
id: string;
|
||||||
|
fromStorageContainerId: string | null;
|
||||||
|
toStorageContainerId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TraceabilityBody {
|
interface TraceabilityBody {
|
||||||
@@ -33,6 +40,8 @@ describe('Honey batches (e2e)', () => {
|
|||||||
let harvestId: string;
|
let harvestId: string;
|
||||||
let extractionId: string;
|
let extractionId: string;
|
||||||
let honeyBatchId: string;
|
let honeyBatchId: string;
|
||||||
|
let containerAId: string;
|
||||||
|
let containerBId: string;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
app = await createTestApp();
|
app = await createTestApp();
|
||||||
@@ -79,13 +88,27 @@ describe('Honey batches (e2e)', () => {
|
|||||||
await prisma.extractionHarvest.create({
|
await prisma.extractionHarvest.create({
|
||||||
data: { extractionId, harvestId },
|
data: { extractionId, harvestId },
|
||||||
});
|
});
|
||||||
|
const containerA = await prisma.storageContainer.create({
|
||||||
|
data: { code: `LB-A-${Date.now()}` },
|
||||||
|
});
|
||||||
|
containerAId = containerA.id;
|
||||||
|
const containerB = await prisma.storageContainer.create({
|
||||||
|
data: { code: `LB-B-${Date.now()}` },
|
||||||
|
});
|
||||||
|
containerBId = containerB.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (honeyBatchId) {
|
if (honeyBatchId) {
|
||||||
|
await prisma.honeyBatchRelocation.deleteMany({
|
||||||
|
where: { honeyBatchId },
|
||||||
|
});
|
||||||
await prisma.honeyMeasurement.deleteMany({ where: { honeyBatchId } });
|
await prisma.honeyMeasurement.deleteMany({ where: { honeyBatchId } });
|
||||||
await prisma.honeyBatch.deleteMany({ where: { id: honeyBatchId } });
|
await prisma.honeyBatch.deleteMany({ where: { id: honeyBatchId } });
|
||||||
}
|
}
|
||||||
|
await prisma.storageContainer.deleteMany({
|
||||||
|
where: { id: { in: [containerAId, containerBId] } },
|
||||||
|
});
|
||||||
await prisma.extractionHarvest.deleteMany({ where: { extractionId } });
|
await prisma.extractionHarvest.deleteMany({ where: { extractionId } });
|
||||||
await prisma.extraction.deleteMany({ where: { id: extractionId } });
|
await prisma.extraction.deleteMany({ where: { id: extractionId } });
|
||||||
await prisma.harvestColony.deleteMany({ where: { harvestId } });
|
await prisma.harvestColony.deleteMany({ where: { harvestId } });
|
||||||
@@ -142,4 +165,41 @@ describe('Honey batches (e2e)', () => {
|
|||||||
expect(trace.extraction.id).toBe(extractionId);
|
expect(trace.extraction.id).toBe(extractionId);
|
||||||
expect(trace.harvests[0]?.colonies[0]?.code).toBeDefined();
|
expect(trace.harvests[0]?.colonies[0]?.code).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('relocates the honey batch into a storage container', async () => {
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.post(`/api/v1/honey-batches/${honeyBatchId}/relocate`)
|
||||||
|
.set('Authorization', `Bearer ${staffToken}`)
|
||||||
|
.send({ storageContainerId: containerAId, notes: 'Erstbefüllung' })
|
||||||
|
.expect(201);
|
||||||
|
const honeyBatch = response.body as HoneyBatchBody;
|
||||||
|
expect(honeyBatch.storageContainerId).toBe(containerAId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects relocation to a nonexistent storage container', () => {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post(`/api/v1/honey-batches/${honeyBatchId}/relocate`)
|
||||||
|
.set('Authorization', `Bearer ${staffToken}`)
|
||||||
|
.send({ storageContainerId: 'does-not-exist' })
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('relocates the honey batch again and records both moves in history', async () => {
|
||||||
|
await request(app.getHttpServer())
|
||||||
|
.post(`/api/v1/honey-batches/${honeyBatchId}/relocate`)
|
||||||
|
.set('Authorization', `Bearer ${staffToken}`)
|
||||||
|
.send({ storageContainerId: containerBId })
|
||||||
|
.expect(201);
|
||||||
|
|
||||||
|
const response = await request(app.getHttpServer())
|
||||||
|
.get(`/api/v1/honey-batches/${honeyBatchId}/relocations`)
|
||||||
|
.set('Authorization', `Bearer ${staffToken}`)
|
||||||
|
.expect(200);
|
||||||
|
const relocations = response.body as RelocationBody[];
|
||||||
|
expect(relocations).toHaveLength(2);
|
||||||
|
expect(relocations[0].toStorageContainerId).toBe(containerBId);
|
||||||
|
expect(relocations[0].fromStorageContainerId).toBe(containerAId);
|
||||||
|
expect(relocations[1].toStorageContainerId).toBe(containerAId);
|
||||||
|
expect(relocations[1].fromStorageContainerId).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user