import { Body, Controller, Get, Param, Patch, Post, Query, UseGuards } from "@nestjs/common"; import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; import { BillingService } from "./billing.service.js"; import { CreateBillingSubscriptionDto } from "./dto/create-billing-subscription.dto.js"; import { CreateBillingRunDto } from "./dto/create-billing-run.dto.js"; import { JwtAuthGuard } from "../auth/jwt-auth.guard.js"; import { PermissionGuard } from "../auth/permission.guard.js"; import { RequirePermission } from "../auth/decorators/require-permission.decorator.js"; import { CurrentUser } from "../auth/decorators/current-user.decorator.js"; import type { EdenAuthenticatedUser } from "../auth/jwt-auth.guard.js"; import type { BillingRunStatus, BillingSubscriptionStatus, InvoiceStatus, } from "@eden/database"; /** * Billing — Master Prompt §6.10, ADR-0008. Recurring subscription -> * billing_run -> invoice MVP. Explicitly NOT Finance/AR-AP (títulos, * boletos, dunning) or Fiscal (documento fiscal) — see ADR-0008. See * billing.service.ts for the authorization rules (why run * creation/consolidation requires 'all' scope). */ @ApiTags("billing") @ApiBearerAuth() @UseGuards(JwtAuthGuard, PermissionGuard) @Controller("v1/billing") export class BillingController { constructor(private readonly billing: BillingService) {} @Get("subscriptions") @RequirePermission("billing", "view") listSubscriptions( @CurrentUser() user: EdenAuthenticatedUser, @Query("status") status?: BillingSubscriptionStatus, ) { return this.billing.listSubscriptions(user, status); } @Post("subscriptions") @RequirePermission("billing", "edit") createSubscription( @Body() dto: CreateBillingSubscriptionDto, @CurrentUser() user: EdenAuthenticatedUser, ) { return this.billing.createSubscription(dto, user); } @Patch("subscriptions/:id/cancel") @RequirePermission("billing", "edit") cancelSubscription(@Param("id") id: string, @CurrentUser() user: EdenAuthenticatedUser) { return this.billing.cancelSubscription(id, user); } @Post("runs") @RequirePermission("billing", "edit") createRun(@Body() dto: CreateBillingRunDto, @CurrentUser() user: EdenAuthenticatedUser) { return this.billing.createOrRegenerateRun(dto, user); } @Get("runs") @RequirePermission("billing", "view") listRuns( @CurrentUser() user: EdenAuthenticatedUser, @Query("referenceYear") referenceYear?: string, @Query("referenceMonth") referenceMonth?: string, @Query("status") status?: BillingRunStatus, ) { return this.billing.listRuns(user, { referenceYear: referenceYear != null ? Number(referenceYear) : undefined, referenceMonth: referenceMonth != null ? Number(referenceMonth) : undefined, status, }); } @Get("runs/:id") @RequirePermission("billing", "view") getRun(@Param("id") id: string, @CurrentUser() user: EdenAuthenticatedUser) { return this.billing.getRun(id, user); } @Post("runs/:id/consolidate") @RequirePermission("billing", "edit") consolidateRun(@Param("id") id: string, @CurrentUser() user: EdenAuthenticatedUser) { return this.billing.consolidateRun(id, user); } @Get("invoices") @RequirePermission("billing", "view") listInvoices( @CurrentUser() user: EdenAuthenticatedUser, @Query("status") status?: InvoiceStatus, @Query("referenceYear") referenceYear?: string, @Query("referenceMonth") referenceMonth?: string, @Query("resellerId") resellerId?: string, ) { return this.billing.listInvoices(user, { status, referenceYear: referenceYear != null ? Number(referenceYear) : undefined, referenceMonth: referenceMonth != null ? Number(referenceMonth) : undefined, resellerId, }); } }