You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@fineract.apache.org by "Aman-Mittal (via GitHub)" <gi...@apache.org> on 2026/08/08 18:49:01 UTC

[I] Data table columns cannot be marked unique or indexed, so every custom-field lookup is a full table scan [fineract-backoffice-ui]

Aman-Mittal opened a new issue, #281:
URL: https://github.com/apache/fineract-backoffice-ui/issues/281

   ## Business value
   
   A data table is how an institution adds its own fields to clients, loans and savings accounts — a national ID, a branch-specific reference, a survey answer. Two properties decide whether those fields are usable at scale, and neither can be set from the UI.
   
   `src/app/features/system/data-tables/datatables-form.component.ts` binds four column properties — `name`, `type`, `length`/`code`, and `mandatory` (`:183-190`). The request model supports six. From `src/app/api/model/postColumnHeaderData.ts`:
   
   ```ts
   export interface PostColumnHeaderData {
       code?: string;
       indexed?: boolean;     // ← not bound
       length?: number;
       mandatory?: boolean;
       name: string;
       type: string;
       unique?: boolean;      // ← not bound
   }
   ```
   
   The read side is equally ready — `ResultsetColumnHeaderData` returns `isColumnIndexed` and `isColumnUnique`, and `loadDatatableData()` (`:330-336`) currently drops both on the floor.
   
   What that costs:
   
   - **No index.** Fineract indexes the foreign key automatically, but a custom column gets nothing. A "find the client with this national ID" query becomes a full scan of the data table. On a few hundred rows nobody notices; on a few hundred thousand, the screen that uses it becomes unusable, and the only remedy is a hand-written `ALTER TABLE` against production by someone with database access.
   - **No unique constraint.** Nothing stops two clients being registered against the same national ID. Duplicate-identity prevention is exactly what a field like that exists for, and the constraint has to be declared when the column is created — the platform will not add it retroactively once duplicates are already in the table.
   
   Both are one checkbox each. The gap is only in the form.
   
   ## Reproducing it
   
   ```
   grep -n "unique\|indexed" src/app/features/system/data-tables/datatables-form.component.ts   # nothing
   grep -n "unique\|indexed" src/app/api/model/postColumnHeaderData.ts                          # both present
   ```
   
   ## Describing the change
   
   Two checkboxes in the column row next to the existing `mandatory` one (`:181-190`), bound to `column.unique` and `column.indexed`. The form's signal is already typed `PostDataTablesRequest` (`:303`), so the properties are there and type-check without any model change.
   
   Three small pieces:
   
   1. **The template** — add to the `.column-checkboxes` block. Note the grid at `:256` is `grid-template-columns: 2fr 1.5fr 1.5fr 1fr auto`; two more checkboxes in the existing cell will need the widths looking at, which is the only fiddly part of this issue.
   2. **`addColumn()` (`:341`)** — seed `unique: false, indexed: false` so a new row starts defined rather than `undefined`.
   3. **`loadDatatableData()` (`:330`)** — read them back:
      ```ts
      unique: col.isColumnUnique,
      indexed: col.isColumnIndexed,
      ```
      Without this the edit screen shows every existing column as neither unique nor indexed, which is worse than not showing it at all.
   
   Two i18n keys under `SYSTEM.*`, alongside `SYSTEM.MANDATORY`. `npm run i18n:check` is a CI gate and will catch a missing one.
   
   **One thing to be careful about.** Every field in this form is `[disabled]="isEditMode"`, because Fineract only permits narrow kinds of change to an existing table. Follow that — the new checkboxes should be disabled in edit mode too. Declaring a column unique *after* rows exist is not something the platform will honour, and a control that looks editable but silently does nothing is worse than a disabled one. Read them back for display; do not make them editable.
   
   ## Testing
   
   The platform's own acceptance tests specify this behaviour precisely. From `fineract-e2e-tests-runner/src/test/resources/features/Datatables.feature` in `apache/fineract` (`develop`):
   
   ```gherkin
   @TestRailId:C3008
   Scenario: Datatable with unique constrained column is indexed
     When A datatable for "Loan" is created with the following extra columns:
       | Name | Type   | Length | Unique | Indexed |
       | col1 | string | 10     | true   | false   |
     Then The following column definitions match:
       | Name | Primary key | Unique | Indexed |
       | col1 | false       | true   | true    |
   
   @TestRailId:C3009
   Scenario: Datatable with indexed column
     When A datatable for "Loan" is created with the following extra columns:
       | Name | Type   | Length | Unique | Indexed |
       | col1 | string | 10     | false  | true    |
     Then The following column definitions match:
       | Name | Primary key | Unique | Indexed |
       | col1 | false       | false  | true    |
   ```
   
   **Read C3008 carefully — it is the interesting case.** The column is submitted `Unique: true, Indexed: false` and comes back `Unique: true, Indexed: true`. The platform indexes a unique column implicitly. So a round-trip test that asserts "what I sent is what I get back" will fail on a correct implementation, and the edit screen will legitimately show `indexed` ticked for a column the user never ticked it on. Do not "fix" that.
   
   What to write:
   
   - **A unit spec** on the form asserting the submitted body carries `unique` and `indexed` per column, and that `loadDatatableData()` maps `isColumnUnique`/`isColumnIndexed` back onto the signal. There is no spec file for this component yet.
   - **A mocked e2e** that fills a column, ticks both boxes, and asserts the intercepted `POST /datatables` body — the `Probe` pattern in `e2e/client-servicing-gaps.spec.ts` is the model.
   
   For ticking an `ion-checkbox` inside a form, and especially for any `ion-select`, use the helpers in `e2e/utils/` rather than clicking directly — `select-in-dialog.ts` documents at length why the obvious approach fails against Ionic overlays.
   
   ## Scope
   
   In scope: the two checkboxes, seeding them, reading them back, and the i18n keys.
   
   Out of scope: making the edit screen genuinely editable (it currently disables everything and PUTs an unchanged body — a real gap, but a separate and much larger one), and the datatable query/filter screen.
   
   ## Getting started
   
   - Form: `src/app/features/system/data-tables/datatables-form.component.ts`
   - Request model: `src/app/api/model/postColumnHeaderData.ts`
   - Response model: `src/app/api/model/resultsetColumnHeaderData.ts`
   - `npm test`, `npm run lint:prune`, `npm run i18n:check` and `npm run build` must pass.
   - Do not edit anything under `src/app/api` — it is generated, and a CI job fails if it drifts from the spec.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] Data table columns cannot be marked unique or indexed, so every custom-field lookup is a full table scan [fineract-backoffice-ui]

Posted by "Aman-Mittal (via GitHub)" <gi...@apache.org>.
Aman-Mittal closed issue #281: Data table columns cannot be marked unique or indexed, so every custom-field lookup is a full table scan
URL: https://github.com/apache/fineract-backoffice-ui/issues/281


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org