import { Injectable, NotFoundException, ConflictException } from '@nestjs/common'; import { EntityManager, RequiredEntityData } from '@mikro-orm/postgresql'; import { Delivery } from '../entities/delivery.entity'; import { DeliveryRepository } from '../repositories/delivery.repository'; import { CreateDeliveryDto } from '../dto/create-delivery.dto'; import { UpdateDeliveryDto } from '../dto/update-delivery.dto'; import { RestRepository } from '../../restaurants/repositories/rest.repository'; import { DeliveryMethodEnum } from '../interface/delivery'; import { DeliveryMessage } from 'src/common/enums/message.enum'; @Injectable() export class DeliveryService { constructor( private readonly deliveryRepository: DeliveryRepository, private readonly restRepository: RestRepository, private readonly em: EntityManager, ) {} async create(restId: string, createDto: CreateDeliveryDto): Promise { const restaurant = await this.restRepository.findOne({ id: restId }); if (!restaurant) { throw new NotFoundException(DeliveryMessage.RESTAURANT_NOT_FOUND); } // Check if the delivery method with the same name already exists for this restaurant const existing = await this.deliveryRepository.findOne({ restaurant: { id: restId }, method: createDto.method, }); if (existing) { throw new ConflictException('این روش ارسال قبلاً برای این رستوران ثبت شده است.'); } const data: RequiredEntityData = { restaurant, method: createDto.method, deliveryFee: createDto.deliveryFee, minOrderPrice: createDto.minOrderPrice, description: createDto.description, enabled: createDto.enabled ?? true, order: createDto.order ?? 0, deliveryFeeType: createDto.deliveryFeeType, perKilometerFee: createDto.perKilometerFee ?? null, distanceBasedMinCost: createDto.distanceBasedMinCost ?? null, }; const delivery = this.deliveryRepository.create(data); await this.em.persistAndFlush(delivery); return delivery; } async findAllForRestaurantId(restId: string): Promise { return this.deliveryRepository.find({ restaurant: { id: restId } }, { orderBy: { order: 'asc' } }); } async findOne(restId: string, deliveryId: string): Promise { const delivery = await this.deliveryRepository.findOne({ id: deliveryId, restaurant: { id: restId }, }); if (!delivery) { throw new NotFoundException(DeliveryMessage.DELIVERY_METHOD_NOT_FOUND); } return delivery; } async update(restId: string, deliveryId: string, updateDto: UpdateDeliveryDto): Promise { const delivery = await this.deliveryRepository.findOne({ restaurant: { id: restId }, id: deliveryId, }); if (!delivery) { throw new NotFoundException(DeliveryMessage.DELIVERY_METHOD_NOT_FOUND); } // If method is being updated, check for conflicts if (updateDto.method !== undefined && updateDto.method !== delivery.method) { const existing = await this.deliveryRepository.findOne({ restaurant: { id: restId }, method: updateDto.method, id: { $ne: deliveryId }, }); if (existing) { throw new ConflictException('این روش ارسال قبلاً برای این رستوران ثبت شده است.'); } } this.em.assign(delivery, updateDto); await this.em.persistAndFlush(delivery); return delivery; } async remove(restId: string, deliveryId: string): Promise { const delivery = await this.deliveryRepository.findOne({ restaurant: { id: restId }, id: deliveryId, }); if (!delivery) { throw new NotFoundException(DeliveryMessage.DELIVERY_METHOD_NOT_FOUND); } await this.em.removeAndFlush(delivery); } findAll(): DeliveryMethodEnum[] { return Object.values(DeliveryMethodEnum); } }