import { Body,Controller,Get,Param,Post,Req,UseGuards } from '@nestjs/common';
import type { z } from 'zod';
import { AuthGuard } from '../../../common/auth/auth.guard';
import { OrganizationContextGuard } from '../../../common/auth/organization-context.guard';
import { LocationContextGuard,type LocationScopedRequest } from '../../../common/auth/location-context.guard';
import { PermissionGuard } from '../../../common/auth/permission.guard';
import { RequirePermissions } from '../../../common/auth/permissions.decorator';
import { InvoiceService } from '../application/invoice.service';
import { EInvoiceService } from '../application/einvoice.service';
import { InvoiceRenderService } from '../application/invoice-render.service';
import { AccountingReadModelService } from '../application/accounting-read-model.service';
import { ZodValidationPipe } from '../../../common/validation/zod-validation.pipe';
import { creditNoteSchema,einvoiceValidateSchema,invoiceFromCheckSchema,invoiceRenderSchema } from '../../../common/validation/critical-write.schemas';
type InvoiceFromCheckBody = z.infer<typeof invoiceFromCheckSchema>;
type CreditNoteBody = z.infer<typeof creditNoteSchema>;
type EInvoiceValidateBody = z.infer<typeof einvoiceValidateSchema>;
type InvoiceRenderBody = z.infer<typeof invoiceRenderSchema>;
@Controller('/invoices')
@UseGuards(AuthGuard,OrganizationContextGuard,LocationContextGuard,PermissionGuard)
export class InvoicesController {
constructor(
private readonly invoices:InvoiceService,
private readonly einvoice:EInvoiceService,
private readonly render:InvoiceRenderService,
private readonly read:AccountingReadModelService,
) {}
@Get()
@RequirePermissions('invoices.read')
list(@Req() req:LocationScopedRequest) {
return this.read.overview({organizationId:req.organizationId!,locationId:req.locationId!})
.then((overview)=>overview.invoices);
}
@Get('/:id')
@RequirePermissions('invoices.read')
detail(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.read.invoice({
organizationId:req.organizationId!,locationId:req.locationId!,invoiceId:id,
});
}
@Post('/from-check')
@RequirePermissions('invoices.create')
create(@Req() req:LocationScopedRequest,@Body(new ZodValidationPipe(invoiceFromCheckSchema)) body:InvoiceFromCheckBody){
return this.invoices.createFromCheck({
organizationId:req.organizationId!,locationId:req.locationId!,
checkId:body.checkId,customer:body.customer,userId:req.auth?.userId,
dueDate:body.dueDate,notes:body.notes,
});
}
@Post('/:id/credit-note')
@RequirePermissions('invoices.create')
creditNote(@Req() req:LocationScopedRequest,@Param('id') id:string,@Body(new ZodValidationPipe(creditNoteSchema)) body:CreditNoteBody){
return this.invoices.createCreditNote({
organizationId:req.organizationId!,locationId:req.locationId!,
originalInvoiceId:id,reason:body.reason,userId:req.auth?.userId,
});
}
@Post('/:id/finalize')
@RequirePermissions('invoices.finalize')
finalize(@Req() req:LocationScopedRequest,@Param('id') id:string){
return this.invoices.finalize({
organizationId:req.organizationId!,locationId:req.locationId!,invoiceId:id,userId:req.auth?.userId,
});
}
@Post('/:id/cancel-draft')
@RequirePermissions('invoices.cancel')
cancelDraft(@Req() req:LocationScopedRequest,@Param('id') id:string){
return this.invoices.cancelDraft({
organizationId:req.organizationId!,locationId:req.locationId!,invoiceId:id,userId:req.auth?.userId,
});
}
@Post('/:id/einvoice/validate')
@RequirePermissions('invoices.einvoice')
validate(@Req() req:LocationScopedRequest,@Param('id') id:string,@Body(new ZodValidationPipe(einvoiceValidateSchema)) body:EInvoiceValidateBody){
return this.einvoice.validate({
organizationId:req.organizationId!,invoiceId:id,profile:body.profile,
validatorConnectionId:body.validatorConnectionId,userId:req.auth?.userId,
});
}
@Post('/:id/render')
@RequirePermissions('invoices.read')
renderRequest(@Req() req:LocationScopedRequest,@Param('id') id:string,@Body(new ZodValidationPipe(invoiceRenderSchema)) body:InvoiceRenderBody){
return this.render.request({
organizationId:req.organizationId!,invoiceId:id,renderType:body.renderType,
});
}
}
