feat(billing,bank): capture + void web UI (plan phase 5 web)
Completes phase 5 — the ledger and chequera pages get the append+void UI on top of the phase-5 API. Web: - Shared MovementForm (customer picker + línea + cargo/abono sign + amount + moneda + concepto facet + periodo/referencia/cheque/mensaje). Used by both /estado-cuenta (cross-customer, picker) and /estado-cuenta/[id] (customer prefilled). - /estado-cuenta and /estado-cuenta/[id]: "Capturar movimiento" toggle gated ledger:create; per-row "Anular" gated ledger:void; voided rows struck-through. Save/void refresh the list + stats. - /banco: inline BankCaptureForm (ingreso/egreso sign, cheque, operado, transferencia, monto en letras) gated bank:create; per-row "Anular" gated bank:void; voided rows struck-through. - api.ts: createMovement/voidMovement, createBankMovement/voidBankMovement; CreateMovementInput/CreateBankMovementInput types; `voided` on the movement/statement/bank list items. Also: lookups.controller.ts now audit-logs provider/policy-type/adjuster create/update/delete (parity with the other write controllers). API + web compile clean. This is the last piece of the feat/crud-rbac branch — all five sections plus users are now full CRUD with role gating. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,11 +6,14 @@ import {
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { Request } from "express";
|
||||
import { AuthenticatedGuard } from "../auth/authenticated.guard";
|
||||
import { AbilityGuard } from "../auth/ability.guard";
|
||||
import { RequireAbility } from "../auth/require-ability.decorator";
|
||||
import { AuditService } from "../common/audit.service";
|
||||
import { PoliciesService } from "./policies.service";
|
||||
import {
|
||||
AdjusterDto,
|
||||
@@ -29,7 +32,14 @@ import {
|
||||
@UseGuards(AuthenticatedGuard, AbilityGuard)
|
||||
@Controller("lookups")
|
||||
export class LookupsController {
|
||||
constructor(private readonly policies: PoliciesService) {}
|
||||
constructor(
|
||||
private readonly policies: PoliciesService,
|
||||
private readonly audit: AuditService,
|
||||
) {}
|
||||
|
||||
private actingId(req: Request): string {
|
||||
return (req.user as { id: string }).id;
|
||||
}
|
||||
|
||||
@Get()
|
||||
list() {
|
||||
@@ -38,49 +48,99 @@ export class LookupsController {
|
||||
|
||||
@Post("providers")
|
||||
@RequireAbility("lookup:manage")
|
||||
createProvider(@Body() dto: ProviderDto) {
|
||||
return this.policies.createProvider(dto);
|
||||
async createProvider(@Body() dto: ProviderDto, @Req() req: Request) {
|
||||
const row = await this.policies.createProvider(dto);
|
||||
void this.audit.log(this.actingId(req), "lookup.provider.create", {
|
||||
providerId: row.id,
|
||||
name: row.name,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@Patch("providers/:id")
|
||||
@RequireAbility("lookup:manage")
|
||||
updateProvider(@Param("id") id: string, @Body() dto: UpdateProviderDto) {
|
||||
return this.policies.updateProvider(id, dto);
|
||||
async updateProvider(
|
||||
@Param("id") id: string,
|
||||
@Body() dto: UpdateProviderDto,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
const row = await this.policies.updateProvider(id, dto);
|
||||
void this.audit.log(this.actingId(req), "lookup.provider.update", {
|
||||
providerId: id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@Delete("providers/:id")
|
||||
@RequireAbility("lookup:manage")
|
||||
removeProvider(@Param("id") id: string) {
|
||||
return this.policies.removeProvider(id);
|
||||
async removeProvider(@Param("id") id: string, @Req() req: Request) {
|
||||
const row = await this.policies.removeProvider(id);
|
||||
void this.audit.log(this.actingId(req), "lookup.provider.delete", {
|
||||
providerId: id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
|
||||
@Post("policy-types")
|
||||
@RequireAbility("lookup:manage")
|
||||
createType(@Body() dto: PolicyTypeDto) {
|
||||
return this.policies.createPolicyType(dto);
|
||||
async createType(@Body() dto: PolicyTypeDto, @Req() req: Request) {
|
||||
const row = await this.policies.createPolicyType(dto);
|
||||
void this.audit.log(this.actingId(req), "lookup.policyType.create", {
|
||||
policyTypeId: row.id,
|
||||
name: row.name,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@Patch("policy-types/:id")
|
||||
@RequireAbility("lookup:manage")
|
||||
updateType(@Param("id") id: string, @Body() dto: UpdatePolicyTypeDto) {
|
||||
return this.policies.updatePolicyType(id, dto);
|
||||
async updateType(
|
||||
@Param("id") id: string,
|
||||
@Body() dto: UpdatePolicyTypeDto,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
const row = await this.policies.updatePolicyType(id, dto);
|
||||
void this.audit.log(this.actingId(req), "lookup.policyType.update", {
|
||||
policyTypeId: id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@Delete("policy-types/:id")
|
||||
@RequireAbility("lookup:manage")
|
||||
removeType(@Param("id") id: string) {
|
||||
return this.policies.removePolicyType(id);
|
||||
async removeType(@Param("id") id: string, @Req() req: Request) {
|
||||
const row = await this.policies.removePolicyType(id);
|
||||
void this.audit.log(this.actingId(req), "lookup.policyType.delete", {
|
||||
policyTypeId: id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
|
||||
@Post("adjusters")
|
||||
@RequireAbility("lookup:manage")
|
||||
createAdjuster(@Body() dto: AdjusterDto) {
|
||||
return this.policies.createAdjuster(dto);
|
||||
async createAdjuster(@Body() dto: AdjusterDto, @Req() req: Request) {
|
||||
const row = await this.policies.createAdjuster(dto);
|
||||
void this.audit.log(this.actingId(req), "lookup.adjuster.create", {
|
||||
adjusterId: row.id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@Patch("adjusters/:id")
|
||||
@RequireAbility("lookup:manage")
|
||||
updateAdjuster(@Param("id") id: string, @Body() dto: UpdateAdjusterDto) {
|
||||
return this.policies.updateAdjuster(id, dto);
|
||||
async updateAdjuster(
|
||||
@Param("id") id: string,
|
||||
@Body() dto: UpdateAdjusterDto,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
const row = await this.policies.updateAdjuster(id, dto);
|
||||
void this.audit.log(this.actingId(req), "lookup.adjuster.update", {
|
||||
adjusterId: id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@Delete("adjusters/:id")
|
||||
@RequireAbility("lookup:manage")
|
||||
removeAdjuster(@Param("id") id: string) {
|
||||
return this.policies.removeAdjuster(id);
|
||||
async removeAdjuster(@Param("id") id: string, @Req() req: Request) {
|
||||
const row = await this.policies.removeAdjuster(id);
|
||||
void this.audit.log(this.actingId(req), "lookup.adjuster.delete", {
|
||||
adjusterId: id,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user