Last active
March 3, 2023 05:37
-
-
Save pphetra/6ccbd32178742d49ef2096eb7c575191 to your computer and use it in GitHub Desktop.
aggregate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @format */ | |
import { PrismaClient } from "@prisma/client"; | |
import { Batch, Product } from "./app.model"; | |
import { IProductRepository } from "./app.repository"; | |
import { AppService } from "./app.service"; | |
import { AbstractUnitOfWork, PrismaUnitOfWork } from "./unitOfWork"; | |
class FakeProductRepository implements IProductRepository { | |
constructor(private batches: Batch[]) {} | |
async get(sku: string): Promise<Product> { | |
const product = new Product({ sku, version: 0 }); | |
product.batches = this.batches; | |
return product; | |
} | |
async add(product: Product): Promise<Product> { | |
return product; | |
} | |
async update(product: Product): Promise<Product> { | |
return product; | |
} | |
} | |
class FakeUnitOfWork implements AbstractUnitOfWork { | |
constructor(private repo: FakeProductRepository) {} | |
get productRepository(): IProductRepository { | |
return this.repo; | |
} | |
async run<T>(fn: (uow: AbstractUnitOfWork) => Promise<T>): Promise<T> { | |
return await fn(this); | |
} | |
} | |
// interface AbstractUnitOfWork { | |
// get batchRepository(): IBatchRepository; | |
// /* | |
// * run in transaction | |
// */ | |
// run<T>(fn: (uow: AbstractUnitOfWork) => Promise<T>): Promise<T>; | |
// } | |
describe("AppService", () => { | |
const client = new PrismaClient(); | |
afterAll(async () => { | |
await client.$disconnect(); | |
}); | |
beforeEach(async () => { | |
await client.line.deleteMany(); | |
await client.batch.deleteMany(); | |
await client.product.deleteMany(); | |
}); | |
it("Fake version: should allocate", async () => { | |
const batch = new Batch({ | |
ref: "batch-001", | |
sku: "SMALL-TABLE", | |
qty: 20, | |
eta: new Date(), | |
}); | |
const repo = new FakeProductRepository([batch]); | |
const uow = new FakeUnitOfWork(repo); | |
const service = new AppService(); | |
const ref = await service.allocate("test", "SMALL-TABLE", 10, uow); | |
expect(ref).toBe("batch-001"); | |
}); | |
it("integration version: should allocate", async () => { | |
const uow = new PrismaUnitOfWork(client); | |
const batch = new Batch({ | |
ref: "batch-001", | |
sku: "SMALL-TABLE", | |
qty: 20, | |
eta: new Date(), | |
}); | |
const product = await uow.productRepository.get("SMALL-TABLE"); | |
product.addBatch(batch); | |
await uow.productRepository.update(product); | |
const service = new AppService(); | |
const ref = await service.allocate("test", "SMALL-TABLE", 10, uow); | |
expect(ref).toBe("batch-001"); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @format */ | |
import { Injectable } from "@nestjs/common"; | |
import { Line } from "./app.model"; | |
import { AbstractUnitOfWork } from "./unitOfWork"; | |
@Injectable() | |
export class AppService { | |
async allocate( | |
name: string, | |
sku: string, | |
qty: number, | |
uow: AbstractUnitOfWork | |
): Promise<string> { | |
const line = new Line({ name, sku, qty }); | |
return await uow.run(async (uow) => { | |
const product = await uow.productRepository.get(sku); | |
const batch = product.allocate(line); | |
if (batch) { | |
await uow.productRepository.update(product); | |
return batch.ref; | |
} | |
throw new Error("out of stock"); | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is your Prisma schema file, | |
// learn more about it in the docs: https://pris.ly/d/prisma-schema | |
generator client { | |
provider = "prisma-client-js" | |
previewFeatures = ["extendedWhereUnique"] | |
} | |
datasource db { | |
provider = "postgresql" | |
url = env("DATABASE_URL") | |
} | |
model Product { | |
id Int @id @default(autoincrement()) | |
sku String @unique | |
batches Batch[] | |
version Int @default(0) | |
} | |
model Batch { | |
id Int @id @default(autoincrement()) | |
ref String | |
sku String | |
qty Int | |
eta DateTime? | |
allocates Line[] | |
Product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) | |
productId Int? | |
} | |
model Line { | |
id Int @id @default(autoincrement()) | |
name String | |
sku String | |
qty Int | |
batchId Int | |
batch Batch @relation(fields: [batchId], references: [id], onDelete: Cascade) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment