mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 14:33:17 +00:00
Implementa el módulo integral de costos según el plan acordado: - Esquema Liquibase: expense_entries, almacén (central + obra), IVA, tenant_cost_settings, permisos IAM y RLS - Funciones RPC core: gastos, almacén, control presupuestal, sync nómina, cierre de almacén al concluir proyecto - API HTTP: expenses_http, warehouse_http, cost_control_http, iam_http - Middleware requirePermission con matriz IAM - UI web-panel: /gastos, /almacen, /control-presupuesto, /usuarios - Componentes BudgetItemPicker, CostSemaphore y semáforos CSS - Smoke tests extendidos para gastos/almacén/control Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
53 lines
2.1 KiB
TypeScript
53 lines
2.1 KiB
TypeScript
import type { Hono } from "hono";
|
|
import type { AuthUser } from "./auth.ts";
|
|
import { tenantScope } from "./auth.ts";
|
|
import { requireCoreAuth } from "./scope.ts";
|
|
import type { Db } from "./db.ts";
|
|
import { callCoreFn } from "./rpc.ts";
|
|
import { respondRpc, routeLabel } from "./http_errors.ts";
|
|
import { requireAnyPermission } from "./permissions.ts";
|
|
|
|
type App = Hono<{ Variables: { user: AuthUser; db: Db } }>;
|
|
|
|
function tid(c: { get: (k: "user") => AuthUser }): number {
|
|
return tenantScope(c.get("user")) ?? 0;
|
|
}
|
|
|
|
export function registerCostControlRoutes(app: App) {
|
|
app.get("/v1/projects/:id/cost-control/summary", ...requireCoreAuth, requireAnyPermission("view_expenses", "manage_expenses"), async (c) => {
|
|
const db = c.get("db");
|
|
const env = await callCoreFn(db, "core.fn_cost_control_project_summary", {
|
|
tenant_id: tid(c),
|
|
project_id: Number(c.req.param("id")),
|
|
}, { route: routeLabel(c) });
|
|
return respondRpc(c, env);
|
|
});
|
|
|
|
app.get("/v1/projects/:id/cost-control/items", ...requireCoreAuth, requireAnyPermission("view_expenses", "manage_expenses"), async (c) => {
|
|
const db = c.get("db");
|
|
const env = await callCoreFn(db, "core.fn_cost_control_by_item", {
|
|
tenant_id: tid(c),
|
|
project_id: Number(c.req.param("id")),
|
|
}, { route: routeLabel(c) });
|
|
return respondRpc(c, env);
|
|
});
|
|
|
|
app.get("/v1/projects/:id/cost-control/chapters", ...requireCoreAuth, requireAnyPermission("view_expenses", "manage_expenses"), async (c) => {
|
|
const db = c.get("db");
|
|
const env = await callCoreFn(db, "core.fn_cost_control_by_chapter", {
|
|
tenant_id: tid(c),
|
|
project_id: Number(c.req.param("id")),
|
|
}, { route: routeLabel(c) });
|
|
return respondRpc(c, env);
|
|
});
|
|
|
|
app.get("/v1/projects/:id/cost-control/deviations", ...requireCoreAuth, requireAnyPermission("view_expenses", "manage_expenses"), async (c) => {
|
|
const db = c.get("db");
|
|
const env = await callCoreFn(db, "core.fn_cost_control_top_deviations", {
|
|
tenant_id: tid(c),
|
|
project_id: Number(c.req.param("id")),
|
|
limit: c.req.query("limit"),
|
|
}, { route: routeLabel(c) });
|
|
return respondRpc(c, env);
|
|
});
|
|
}
|