feat(ADM-018): completed feature
This commit is contained in:
62
project/src/modules/orders/application/order-service.ts
Normal file
62
project/src/modules/orders/application/order-service.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { OrderNotFoundError, OrderStateTransitionError } from '../domain/errors.js';
|
||||
import type {
|
||||
OrderEventPublisher,
|
||||
OrderRepository,
|
||||
OrderServicePort,
|
||||
CreateOrderCommand,
|
||||
} from '../domain/ports.js';
|
||||
import { isTransitionAllowed, type OrderState, type OrderView } from '../domain/order.js';
|
||||
|
||||
export class OrderService implements OrderServicePort {
|
||||
constructor(
|
||||
private readonly repo: OrderRepository,
|
||||
private readonly events: OrderEventPublisher,
|
||||
) {}
|
||||
|
||||
async create(input: CreateOrderCommand): Promise<OrderView> {
|
||||
const order = await this.repo.create({
|
||||
...input,
|
||||
idempotencyKey: input.idempotencyKey ?? null,
|
||||
});
|
||||
await this.events.emit({ type: 'OrderCreated', orderId: order.id, userId: order.userId });
|
||||
return order;
|
||||
}
|
||||
|
||||
async listOrders(): Promise<OrderView[]> {
|
||||
return this.repo.findAll();
|
||||
}
|
||||
|
||||
async transition(id: string, next: OrderState, userId: string): Promise<OrderView> {
|
||||
const existing = await this.repo.findByIdAndUserId(id, userId);
|
||||
if (!existing) throw new OrderNotFoundError();
|
||||
if (!isTransitionAllowed(existing.state, next))
|
||||
throw new OrderStateTransitionError(existing.state, next);
|
||||
const updated = await this.repo.updateState(id, next);
|
||||
if (!updated) throw new OrderNotFoundError();
|
||||
if (next === 'PAID') await this.events.emit({ type: 'OrderPaid', orderId: id, userId });
|
||||
if (next === 'CANCELLED')
|
||||
await this.events.emit({ type: 'OrderCancelled', orderId: id, userId });
|
||||
return updated;
|
||||
}
|
||||
|
||||
async getOrder(id: string, userId: string): Promise<OrderView | undefined> {
|
||||
return this.repo.findByIdAndUserId(id, userId);
|
||||
}
|
||||
|
||||
async getOrderAdmin(id: string): Promise<OrderView | undefined> {
|
||||
return this.repo.findById(id);
|
||||
}
|
||||
|
||||
async transitionAdmin(id: string, next: OrderState): Promise<OrderView> {
|
||||
const existing = await this.repo.findById(id);
|
||||
if (!existing) throw new OrderNotFoundError();
|
||||
if (!isTransitionAllowed(existing.state, next))
|
||||
throw new OrderStateTransitionError(existing.state, next);
|
||||
const updated = await this.repo.updateState(id, next);
|
||||
if (!updated) throw new OrderNotFoundError();
|
||||
if (next === 'PAID') await this.events.emit({ type: 'OrderPaid', orderId: id, userId: existing.userId });
|
||||
if (next === 'CANCELLED')
|
||||
await this.events.emit({ type: 'OrderCancelled', orderId: id, userId: existing.userId });
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user