SubForm and GC Template Flow
Legend
| Elements | GMS / GMS1 | Notes |
|---|---|---|
SourceOfFund | Budget Source | Same funding source concept across both applications. |
Terminology notes:
- Ingestion means parsing the Excel template, validating fields using FormMaster/FormMasterFields rules, and preparing/saving FormSubmissionData.
- Downstream handoff means the PostDTA upload path calling GMS2 process action and publishing the MQ event to TPGMS (GMS1).
High-level Flow
flowchart TD
A[User uploads Excel] --> B{Endpoint}
B -->|/elements/subform| C[SubForm flow]
B -->|/elements/postdtasubform| D[GC template flow]
C --> C1[Load IVP and scheme config]
C1 --> C2{HasSubFormIngestion / family rules}
C2 -->|true| C3[Validate scheme from Excel]
C2 -->|false| C4[Upload file only]
C3 --> C5[IngestForm]
C5 --> C6[SaveIngestedForm]
C6 --> C7[Update post-ingestion state]
D --> D1[Load IVP and scheme config]
D1 --> D2{Family = TaxCredit}
D2 -->|true| D3[Validate scheme from Excel]
D2 -->|false| D4[Upload file only]
D3 --> D5[IngestForm]
D5 --> D6[SaveIngestedForm]
D6 --> D7[Upload path triggers GMS2 + MQ]
C4 --> Z[Done]
C7 --> Z
D4 --> Z
D7 --> Z
Flow Details
1) Standard SubForm flow (/elements/subform)
Business context:
- User uploads a standard subform for an application.
- Depending on scheme rules, Elements either ingests data fields or treats it as upload-only.
Flow with code points:
- The subform is submitted either by the company in Portal or by the OIC in Elements. That submission reaches
POST /elements/subform, mapped by[Route("subform")]inFormController.IngestSubForm(Edb4.AppService.Rest/Controllers/Elements/FormController.cs#L84), which hands control toSubFormService.IngestSubForm(Elements.ServiceFacade/Service/SubFormService.cs#L54). - Elements then identifies which application this upload belongs to by loading the IVP record, and uses that IVP context to load the relevant scheme configuration through
SchemeConfigUtility.GetinSubFormService(Elements.ServiceFacade/Service/SubFormService.cs#L54). From there, it decides whether this particular scheme should perform structured ingestion or should behave as upload-only (Elements.ServiceFacade/Service/SubFormService.cs#L105). - Where ingestion is required, Elements reads the
Schemedefined name from the uploaded Excel and checks that it matches the scheme on the application itself, usingivpEntity.Typeas the application-side value, before moving into the shared ingestion path throughSubFormService → IngestForm(Elements.ServiceFacade/Service/SubFormService.cs#L174). - At the start of shared ingestion,
FormHelperService.IngestFormnarrows the available template definitions to the SubForm set, excluding PostDTA templates, so the upload is assessed against the correct type of form (Elements.ServiceFacade/Helpers/FormHelperService.cs#L145). - Elements then reads
FormVersionfrom the uploaded Excel inFormHelperService.Ingestand looks for the matchingFormMasterrow for that version (Elements.ServiceFacade/Helpers/FormHelperService.cs#L372). If no matching version exists, the process stops here and the upload is treated as an invalid template version. - Once the matching
FormMasterhas been identified, Elements loads the relatedFormMasterFieldsrows for thatFormMasterId(Elements.ServiceFacade/Helpers/FormHelperService.cs#L397). These rows are the field-by-field instructions that tell Elements what to read from the Excel file and how to interpret it. - Elements then works through those
FormMasterFieldsdefinitions inValidateIngestion, reading each configured value from Excel, validating it, and preparing SQL inserts forFormSubmissionData(Elements.ServiceFacade/Helpers/FormHelperService.cs#L579). This is the point where the uploaded subform is converted into structured data. - If no ingestion errors are found, Elements commits the prepared
FormSubmissionDatarecords throughSubFormService → SaveIngestedFormandFormHelperService.SaveIngestedForm(Elements.ServiceFacade/Service/SubFormService.cs#L183,Elements.ServiceFacade/Helpers/FormHelperService.cs#L195). - In parallel with that structured-data path, the original Excel file is also uploaded through the file service. Where the scheme is upload-only, this file-upload step still happens, but no
FormSubmissionDatais created.
2) GC template flow (/elements/postdtasubform)
Business context:
- User uploads GC template (PostDTA subform).
- In current implementation, ingestion is enabled when application family is TaxCredit.
- If ingestion succeeds, Elements persists structured values and then continues upload/handoff path.
Flow with code points:
- The GC template is uploaded by the OIC in Elements. That submission reaches
POST /elements/postdtasubform, mapped by[Route("postdtasubform")]inFormController.IngestPostDtaSubform(Edb4.AppService.Rest/Controllers/Elements/FormController.cs#L126), which hands control toPostDTASubformService.Process(Elements.ServiceFacade/Service/PostDTASubformService.cs#L31). - Elements then loads the IVP record to identify the application and uses that IVP context to load the relevant scheme configuration through
SchemeConfigUtility.GetinPostDTASubformService(Elements.ServiceFacade/Service/PostDTASubformService.cs#L31). From there, it determines whether ingestion should run, which in the current implementation means TaxCredit applications (Elements.ServiceFacade/Service/PostDTASubformService.cs#L53). - Where ingestion applies, Elements reads the
Schemedefined name from the uploaded Excel and checks that it matches the scheme on the application itself, usingivp.Typeas the application-side value, before continuing (Elements.ServiceFacade/Service/PostDTASubformService.cs#L56). - Elements then enters the shared ingestion path through
PostDTASubformService → IngestForm(Elements.ServiceFacade/Service/PostDTASubformService.cs#L82). At this point,FormHelperService.IngestFormnarrows the available template definitions to thePostDTASubFormrows for that scheme (Elements.ServiceFacade/Helpers/FormHelperService.cs#L145). - Elements reads
FormVersionfrom the uploaded Excel inFormHelperService.Ingestand tries to match that version to the correctFormMasterrow for the GC template (Elements.ServiceFacade/Helpers/FormHelperService.cs#L372). If no matching version exists inFormMaster, the process stops before any field parsing begins. - Once the matching
FormMasteris found, Elements loads the correspondingFormMasterFieldsrows for thatFormMasterId(Elements.ServiceFacade/Helpers/FormHelperService.cs#L397). These rows define the field-by-field instructions for how the GC template should be read and validated. - Elements then works through those
FormMasterFieldsdefinitions inValidateIngestion, reading each configured value from the Excel file, validating it, and preparing SQL inserts forFormSubmissionData(Elements.ServiceFacade/Helpers/FormHelperService.cs#L579). This is the point where the uploaded GC template is converted into structured data. - If no ingestion errors are found, Elements commits the prepared
FormSubmissionDatarows throughPostDTASubformService → SaveIngestedFormandFormHelperService.SaveIngestedForm(Elements.ServiceFacade/Service/PostDTASubformService.cs#L87,Elements.ServiceFacade/Helpers/FormHelperService.cs#L195). - After the structured ingestion succeeds, the original GC template file is uploaded and stored inside Elements through the
FileServicepath (Elements.ServiceFacade/Service/FileService.cs#L552). This is still part of the Elements-side upload flow. - Only after the GC template has been stored in Elements does the PostDTA process move into downstream integration:
FileServicecalls GMS2 process action (Elements.ServiceFacade/Service/FileService.cs#L565) and then publishes the TPGMS/GMS1 message queue event (Elements.ServiceFacade/Service/FileService.cs#L569).
Shared ingestion internals (used by both flows)
- PostDTA/SubForm FormMaster filtering happens in
FormHelperService.IngestForm(Elements.ServiceFacade/Helpers/FormHelperService.cs#L145). - Uploaded Excel version is matched to the correct
FormMasterrow inFormHelperService.Ingest(Elements.ServiceFacade/Helpers/FormHelperService.cs#L372). - The related
FormMasterFieldsrows are then loaded for thatFormMasterIdbefore field parsing continues (Elements.ServiceFacade/Helpers/FormHelperService.cs#L397). - Field-by-field extraction and validation happens in
FormHelperService.ValidateIngestion(Elements.ServiceFacade/Helpers/FormHelperService.cs#L579). - Prepared
FormSubmissionDataSQL commands are committed inFormHelperService.SaveIngestedForm(Elements.ServiceFacade/Helpers/FormHelperService.cs#L195).
Data Model Involved
FormMaster
- Purpose: Template metadata by type/version/scheme.
- Used to decide whether uploaded
FormVersionis valid for the current flow. - If no matching version exists, ingestion stops early.
FormMasterFields
- Purpose: Ingestion mapping rules for a specific
FormMaster. - Defines where to read each value from Excel and how to validate it.
- Key columns drive ingestion behavior:
SheetName,Source,SourceType,DataType,IsMandatory,Key, and optional custom validation.
FormSubmissionData
- Purpose: Persisted structured key-value records extracted from template.
- During
ValidateIngestion, SQL insert commands are prepared forFormSubmissionData. - During
SaveIngestedForm, those commands are executed and committed if no errors.
Ingestion Summary
- Read
FormVersionfrom Excel. - Match uploaded version to
FormMasterin scope. - Load
FormMasterFieldsfor thatFormMaster. - Parse and validate each field from Excel.
- Build SQL commands for
FormSubmissionData. - Save via
SaveIngestedFormif no errors. - On errors, rollback and return validation/error output.
What gets saved
- Parsed values are prepared as
FormSubmissionDatarows. - The original Excel file is uploaded separately through the file service.
- For PostDTA, downstream GMS2 / MQ handoff happens in the upload path.
Common failure points
- Scheme mismatch between Excel and IVP
- Uploaded template version not present in
FormMaster - Missing or incorrect
FormMasterFields - Field validation failure during
ValidateIngestion - Downstream failure after upload in PostDTA handoff path
Current logging notes
- Release branch logs are relatively minimal unless enhanced logging is deployed.
- The most useful current failure points are usually:
PostDTASubformService.Process ...ValidateIngestion error - ...GMS2Service ProcessAction failed
- With enhanced logging, you can see stage-level failures such as version match, ingestion, upload, and handoff.