class OrderService {
constructor(
private prisma: PrismaClient,
private orderRepo: OrderRepository
) {}
async confirmOrder(orderId: string): Promise<void> {
// Load order
const order = await this.orderRepo.findById(orderId);
if (!order) throw new Error("Order not found");
// Business logic
order.confirm();
order.items.forEach((item) => {
if (item.quantity > 10) {
item.applyBulkDiscount(5);
}
});
// Get changes
const changes = order.getTypedChanges();
if (changes.isEmpty()) {
return; // Nothing to persist
}
// Log what's changing
console.log("Affected entities:", changes.getAffectedEntities());
console.log("Total operations:", changes.count);
// Persist
const batch = changes.toBatchOperations();
await this.prisma.$transaction(async (tx) => {
// Process in correct order
await this.processDeletes(tx, batch.deletes);
await this.processCreates(tx, batch.creates);
await this.processUpdates(tx, batch.updates);
});
// Clear change history
order.markAsClean();
}
private async processDeletes(tx: any, deletes: BatchOperations["deletes"]) {
for (const del of deletes) {
await tx[this.getTableName(del.entity)].deleteMany({
where: { id: { in: del.ids } },
});
}
}
private async processCreates(tx: any, creates: BatchOperations["creates"]) {
for (const create of creates) {
const table = this.getTableName(create.entity);
await tx[table].createMany({
data: create.items.map((item) =>
this.mapToDatabase(create.entity, item.data, item.parentId)
),
});
}
}
private async processUpdates(tx: any, updates: BatchOperations["updates"]) {
for (const update of updates) {
const table = this.getTableName(update.entity);
for (const item of update.items) {
await tx[table].update({
where: { id: item.id },
data: item.changedFields,
});
}
}
}
private getTableName(entity: string): string {
const map: Record<string, string> = {
Order: "order",
OrderItem: "orderItem",
ItemDiscount: "itemDiscount",
};
return map[entity];
}
private mapToDatabase(entity: string, data: any, parentId?: string): any {
// Map domain entity to database record
// ... implementation
}
}