import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import Order, { OrderType } from 'App/Models/Order' import PaginationService from 'App/Services/PaginationService' import { schema } from '@ioc:Adonis/Core/Validator' import { BadRequestException } from 'App/Exceptions/Common' import Series from 'App/Models/Series' import Episode from 'App/Models/Episode' import UserBalanceService from 'App/Services/UserBalanceService' import Decimal from 'decimal.js' import BalanceRecord, { BalanceRecordType } from 'App/Models/BalanceRecord' export default class OrdersController { private paginationService = new PaginationService(Order) public async index({ request, auth }: HttpContextContract) { const page = await this.paginationService.paginate({ ...request.all(), userId: auth.user!.id }) const seriesIds = new Set( page .all() .map((record) => record.seriesId) .filter((id) => !!id) ) const series = await Series.findMany(Array.from(seriesIds)) const episodeIds = new Set( page .all() .map((record) => record.episodeId) .filter((id) => !!id) ) const episodes = await Episode.findMany(Array.from(episodeIds)) page.all().forEach((record) => { if (record.seriesId) { record.series = series.find((s) => s.id === record.seriesId) } if (record.episodeId) { record.episode = episodes.find((e) => e.id === record.episodeId) } }) return page } public async store({ request, auth }: HttpContextContract) { const user = auth.user! const data = await request.validate({ schema: schema.create({ seriesId: schema.number.optional(), episodeId: schema.number.optional() }) }) if (!data.seriesId && !data.episodeId) { throw new BadRequestException('seriesId or episodeId must be provided') } const userBalance = await UserBalanceService.getBalance(user.id) const order = new Order() order.userId = user.id if (data.seriesId) { const series = await Series.findOrFail(data.seriesId) if (series.price.comparedTo(userBalance.balance) > 0) { throw new Error('not enough balance') } order.price = series.price order.type = OrderType.Series order.seriesId = data.seriesId } else { const episode = await Episode.findOrFail(data.episodeId) if (episode.price.comparedTo(userBalance.balance) > 0) { throw new Error('not enough balance') } order.price = episode.price order.type = OrderType.Episode order.seriesId = episode.seriesId order.episodeId = data.episodeId! } await UserBalanceService.modifiyBalance({ userId: user.id, amount: order.price.negated(), type: BalanceRecordType.Purchase, seriesId: data.seriesId, episodeId: data.episodeId }) return await order.save() } public async show({ params }: HttpContextContract) { return await Order.findOrFail(params.id) } public async update({ response }: HttpContextContract) { response.notImplemented() } public async destroy({ response }: HttpContextContract) { response.notImplemented() } }