[
https://issues.apache.org/jira/browse/FINERACT-2776?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Adam Saghy reassigned FINERACT-2776:
------------------------------------
Assignee: Farooq Ayoade
> GET /datatables response schema omits entitySubType, so generated clients
> cannot read it
> ----------------------------------------------------------------------------------------
>
> Key: FINERACT-2776
> URL: https://issues.apache.org/jira/browse/FINERACT-2776
> Project: Apache Fineract
> Issue Type: Bug
> Components: System
> Reporter: Farooq Ayoade
> Assignee: Farooq Ayoade
> Priority: Minor
>
> h3. Summary
> {{POST /datatables}} accepts an {{entitySubType}} and the platform stores it
> in
> {{x_registered_table.entity_subtype}}. Both GET routes return it at runtime:
> {{DatatableData}} carries the
> field, and {{DatatableReadServiceImpl}} selects {{entity_subtype}} and passes
> it into
> {{DatatableData.create(...)}} on the list path and the single-table path
> alike.
> The one place it does not appear is the class both routes name as their
> {{@ApiResponse}} schema.
> {{DatatablesApiResourceSwagger.PostDataTablesRequest}} declares
> {{entitySubType}};
> {{GetDataTablesResponse}} does not. The published OpenAPI document therefore
> describes a datatable as
> having only {{applicationTableName}}, {{registeredTableName}} and
> {{columnHeaderData}}.
> The asymmetry is the bug: the API lets a caller *set* a property and then
> documents a response in which
> that property does not exist.
> h3. Impact
> A hand-written client never notices, because the JSON has the field. A
> generated client cannot read it at
> all -- the member is not on the type, so the natural workaround is to cast
> away the generated type at
> exactly the point where it is most worth having.
> That matters because of what the field is for. {{entitySubType}} scopes a
> datatable to a client legal form
> (Person / Entity), so a UI rendering custom fields on a customer has to read
> it to know whether a given
> table belongs on an individual or on a corporate. Without it, every
> {{m_client}} datatable shows on every
> customer regardless of what it was registered against.
> h3. Steps to reproduce
> # {{POST /datatables}} with {{apptableName: "m_client"}} and {{entitySubType:
> "Person"}}.
> # {{GET /datatables?apptable=m_client}} -- the JSON response *does* contain
> {{"entitySubType": "Person"}}.
> # Generate a client from the published OpenAPI document (any generator).
> # The type for the GET response has no {{entitySubType}} member.
> h3. Actual
> The runtime JSON and the published schema disagree. A generated type cannot
> express a field the endpoint
> always returns.
> h3. Expected
> {{GetDataTablesResponse}} declares {{entitySubType}}, matching both the
> runtime response and the request
> DTO that already declares it.
> h3. Evidence
> All references below are against {{develop}}.
> || Where || What it shows ||
> | {{DatatableData}} | declares {{entitySubType}}, takes it in {{create(...)}}
> and assigns it; nothing excludes it from serialisation |
> | {{DatatableReadServiceImpl}} lines 72, 93, 96 | list path selects
> {{entity_subtype}} and passes it to {{DatatableData.create(...)}} |
> | {{DatatableReadServiceImpl}} lines 106, 119, 123 | single-table path does
> the same |
> | {{DatatablesApiResourceSwagger}} line 81 | {{PostDataTablesRequest}}
> declares {{entitySubType}} |
> | {{DatatablesApiResourceSwagger.GetDataTablesResponse}} | does not declare
> it |
> | {{DatatablesApiResource}} lines 101, 233 | {{getDatatables}} and
> {{getDatatable}} both name {{GetDataTablesResponse}} as their
> {{@ApiResponse}} schema, so one omission affects both endpoints |
> The clearest evidence is in Fineract's own test suite.
> {{integration-tests/.../datatable/DatatableIntegrationTest}} imports the
> *generated* client model
> {{org.apache.fineract.client.models.GetDataTablesResponse}} and sets
> {{entitySubType}} on eleven separate
> datatable creations -- and never once asserts it comes back, because the
> generated model has no getter for
> it. {{validateCreateAndEditDatatable}} creates a datatable with
> {{CLIENT_PERSON_SUBTYPE_NAME}} ("Person"),
> reads it back with {{getDataTableDetails(...)}}, and can assert on the column
> headers but not on the sub
> type it just set.
> h3. Proposed fix
> One field on {{GetDataTablesResponse}}:
> {code:java}
> @Schema(example = "Person", description = "The entity sub type the datatable
> is registered against, "
> + "when the application table supports one (for example Person or
> Entity on m_client). "
> + "Null when the registration is not scoped to a sub type.")
> public String entitySubType;
> {code}
> No runtime behaviour changes; the response body is unchanged byte for byte.
> h3. Test
> {{fineract-client}} is generated from this spec ({{inputSpec =
> file(swaggerFile)}},
> {{dependsOn(':fineract-provider:resolve')}}) and {{integration-tests}}
> depends on it, so a client-side
> assertion is a real test of this defect rather than a restatement of
> behaviour that already worked. One
> line inside the existing {{validateCreateAndEditDatatable}}, after the
> {{getDataTableDetails(...)}} call
> that is already there:
> {code:java}
> assertEquals(CLIENT_PERSON_SUBTYPE_NAME, dataTable.getEntitySubType());
> {code}
> Verified by generating the Java client both ways: from {{develop}}'s spec the
> model has three getters
> ({{getApplicationTableName}}, {{getColumnHeaderData}},
> {{getRegisteredTableName}}); regenerated with the
> fix it has four, the new one being {{getEntitySubType()}}. So the assertion
> does not compile before the
> change and passes after it.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)