Uganda users only enter monthly figures today. In Accounting-Next as built, a user who fills in a month in the questionnaire and records daily operations for the same month sees that month counted twice in every report. We propose to fix that, load Uganda’s chart of accounts, tax rates and institutions, and add ratios and a cash-flow statement. We are asking for a green light to open three pull requests. Nothing has been pushed yet. Hoy los usuarios de Uganda solo cargan cifras mensuales. En Accounting-Next tal como está, si un usuario llena un mes en el cuestionario y registra operaciones diarias de ese mismo mes, ese mes sale contado dos veces en todos los informes. Proponemos arreglar eso, cargar el plan de cuentas, las tasas y las instituciones de Uganda, y agregar ratios y un estado de flujo de caja. Pedimos luz verde para abrir tres pull requests. Todavía no se ha subido nada.
Nelson decided these on 24 Sep 2026:Nelson las tomó el 24-sep-2026:
| FindingHallazgo | WhereDónde |
|---|---|
A questionnaire actual posts one real Operation per (item, month), dated the last day of the month.Un valor real del cuestionario crea una Operation real por (ítem, mes), con fecha del último día del mes. | src/actions/budget-actuals.ts · setBudgetActual |
| Reports and totals sum all operations on an account, whatever their source.Informes y totales suman todas las operaciones de una cuenta, sin importar el origen. | src/actions/reports.ts:368 · src/actions/budget-totals.ts:136 |
JournalLine.fromBudgetActual is written but never read. “Subsystem B” (spec 2026-06-22 §9) was never built.JournalLine.fromBudgetActual se escribe pero nunca se lee. El “subsistema B” (spec 2026-06-22 §9) nunca se construyó. | src/lib/ledger/persist.ts:220 |
Questionnaire operations carry no businessId, but reports filter by the active business, so monthly figures can drop out of reports.Las operaciones del cuestionario no llevan businessId, pero los informes filtran por negocio activo, así que las cifras mensuales pueden desaparecer de los informes. | budget-actuals.ts · src/lib/business/scope.ts:17 |
For each (user, business, item/account, month):Para cada (usuario, negocio, ítem/cuenta, mes):
gap = declared total − Σ daily operations
budgetActualItemId op) posts that amount. Reports show it as “Unsupported amount”.diferencia > 0: una operación de diferencia (la op actual con budgetActualItemId) registra ese monto. Los informes la muestran como “Unsupported amount”.| ChangeCambio | DetailDetalle |
|---|---|
| Store the declared totalGuardar el total declarado | New table UserBudgetActualDeclaration(userId, itemId, period, businessId, amount, currency), unique on (user, item, period, business). Additive migration. Backfill from existing questionnaire ops (declared = current op amount).Tabla nueva UserBudgetActualDeclaration(userId, itemId, period, businessId, amount, currency), única por (usuario, ítem, período, negocio). Migración aditiva. Relleno inicial desde las ops del cuestionario existentes (declarado = monto actual de la op). |
| One helper that recomputes the gapUn helper que recalcula la diferencia | reconcileBudgetActualGap(tx, {userId, businessId, accountId, month}), run inside the same transaction as any operation write.reconcileBudgetActualGap(tx, {userId, businessId, accountId, month}), dentro de la misma transacción que cualquier escritura de operación. |
| Call it from every path that writes an operationLlamarlo desde toda ruta que escribe una operación | operations.ts create / update / delete (lines 268, 475, 666), recurring posting, AI-created and aid-created operations, e-invoice acceptance. For an update that changes account or date, both the old and the new (account, month) are reconciled. Open question: hook it centrally in the ledger post path instead?operations.ts crear / editar / borrar (líneas 268, 475, 666), registro de recurrentes, operaciones creadas por IA y por ayudas, aceptación de e-factura. Si una edición cambia la cuenta o la fecha, se reconcilian el (cuenta, mes) viejo y el nuevo. Pregunta abierta: ¿engancharlo centralmente en la ruta de posteo del libro? |
| Attach the businessPoner el negocio | setBudgetActual sets businessId = active business. Backfill: existing questionnaire ops get the user’s active business.setBudgetActual guarda businessId = negocio activo. Relleno: las ops del cuestionario existentes reciben el negocio activo del usuario. |
| Questionnaire UIPantalla del cuestionario | questionnaire.tsx: show “Already recorded daily: X” per flow row. The field edits the declared total. Warning on total < daily.questionnaire.tsx: mostrar “Ya registrado día a día: X” en cada fila de flujo. El campo edita el total declarado. Aviso si total < diario. |
| ReportsInformes | ACCOUNT_FLOW aggregation (reports.ts:368) groups also by budgetActualItemId IS NULL, and renders the non-null part as an amber sub-line “Unsupported amount”. Totals unchanged. Balance sheet lines can use the existing fromBudgetActual flag.La agregación ACCOUNT_FLOW (reports.ts:368) agrupa también por budgetActualItemId IS NULL y muestra la parte no nula como sub-línea ámbar “Unsupported amount”. Los totales no cambian. El balance puede usar la marca fromBudgetActual que ya existe. |
| i18n | New keys in src/messages/*.json; must pass npm run i18n:check.Claves nuevas en src/messages/*.json; debe pasar npm run i18n:check. |
Today the code has no Uganda content at all (no hits for Uganda, UGX, URA, EFRIS or NSSF outside the ISO currency list). The deployment boots one global catalog, so most of this is configuration.Hoy el código no tiene nada de Uganda (cero resultados para Uganda, UGX, URA, EFRIS o NSSF fuera de la lista ISO de monedas). Cada instalación arranca con un solo catálogo global, así que casi todo esto es configuración.
| ItemElemento | SourceFuente | HowCómo |
|---|---|---|
| Chart of accounts (~110 accounts)Plan de cuentas (~110 cuentas) | Uganda/ugchart.txt | Convert to the default-chart.json shape, including the roles (AR, AP, VAT payable/recoverable, opening equity).Convertir al formato de default-chart.json, con sus roles (cuentas por cobrar y por pagar, IVA por pagar/recuperable, patrimonio de apertura). |
| Currency UGXMoneda UGX | ISO 4217 | Already in iso-4217.json; enable as the default.Ya está en iso-4217.json; activarla como predeterminada. |
| VAT 18% (standard), 0% and exemptIVA 18 % (general), 0 % y exento | Uganda VAT ActLey de IVA de Uganda | TaxRate rows(filas) |
| Institutions: URA (tax), NSSF (social security), KCCA / local government (municipal), URSB (registry)Instituciones: URA (impuestos), NSSF (seguridad social), KCCA / gobierno local (municipal), URSB (registro) | — | Rename the four global rows (ensure-default-institutions.ts already supports admin renames).Renombrar las cuatro filas globales (ensure-default-institutions.ts ya admite renombrarlas desde admin). |
| Report models: URA VAT return, NSSF contributions (5% employee + 10% employer)Modelos de informe: declaración de IVA de URA, aportes NSSF (5 % empleado + 10 % empleador) | URA / NSSF formsFormularios de URA / NSSF | Report definitions (existing engine: IVA_SUM, FORMULA). The exact form layout needs URA input.Definiciones de informe (motor existente: IVA_SUM, FORMULA). El formato exacto necesita datos de URA. |
FORMULA report lines, computed from the ledger. Closes Uganda issues 009, 011–014.Ratios (liquidez, actividad, deuda, rentabilidad, punto de equilibrio): sobre todo configuración con las líneas FORMULA que ya existen, calculadas desde el libro. Cierra los reclamos 009 y 011–014.SPECIAL keys for changes in working capital). Closes issue 010.Estado de flujo de caja (método indirecto, un solo método): necesita unos agregados del motor (claves SPECIAL para variación del capital de trabajo). Cierra el reclamo 010.The existing e-invoice module already has per-jurisdiction formats (EInvoiceFormat) and an emitted/received lifecycle with an institution acknowledgment number. That is the natural hook for EFRIS later. It needs URA sandbox credentials and URA approval, so we propose requesting that access now, in parallel with the pilot.El módulo de e-factura ya tiene formatos por jurisdicción (EInvoiceFormat) y un ciclo emitida/recibida con número de acuse de la institución. Ese es el enganche natural para EFRIS más adelante. Hacen falta credenciales de prueba de URA y su aprobación, así que proponemos pedir ese acceso ya, en paralelo al piloto.
feature/uganda-a-monthly-daily, feature/uganda-b-country-pack, feature/uganda-c-ratios-cashflow off main. One PR each, A first. Nobody pushes to main.Ramas feature/uganda-a-monthly-daily, feature/uganda-b-country-pack, feature/uganda-c-ratios-cashflow desde main. Un PR por rama, A primero. Nadie sube a main.npm run typecheck, lint, test, build and i18n:check. Anything we cannot run is reported in the PR.Cada PR pasa npm run typecheck, lint, test, build e i18n:check. Lo que no podamos correr se informa en el PR.| WorkTrabajo | Agent timeTiempo de agente | Human / external timeTiempo humano / externo |
|---|---|---|
| PR A | ~4–6 h~4–6 h | Frank’s team reviewRevisión del equipo de Frank |
| PR B | ~2–3 h~2–3 h | URA form layouts, NSSF confirmationFormatos de URA, confirmación de NSSF |
| PR C | ~1 day~1 día | Review; accountant check of the ratio formulasRevisión; control de un contador sobre las fórmulas |