CMS FAQ Management Extension — Delivery Review v2.0
Extension: FAQ Management (Epic 193) Source Version Reviewed: v1.0.0.57 Compiled Version in Sandbox: v1.0.0.73 Vendor: Sataware Technologies LLC Solution Design Date: December 16, 2025 Original Review Date: March 6, 2026 (v1.1 — symbol extraction only) Updated Review Date: March 19, 2026 (v2.0 — full source code review) Prepared by: Phil McCaffrey, ERP Specialist Organization: Bestway (USA) Inc.
Executive Summary
This is an updated Delivery Review of the CMS FAQ Management extension (Epic 193), replacing the v1.1 review dated March 6, 2026. The original review was conducted via symbol extraction from the compiled .app binary because source code had not been delivered. On March 19, 2026, Sataware provided source code at version 1.0.0.57 — 16 revisions behind the v1.0.0.73 binary in the sandbox. This updated review is based on a full reading of every delivered source file.
The updated review confirms and expands the original findings. The source code reveals implementation details that were not visible through symbol extraction alone — including hardcoded credentials, a double-execution defect in the Job Queue integration, and the complete absence of incremental sync logic.
The Epic defines 7 user stories with 26 acceptance criteria. The Solution Design (dated 12/16/25) specifies 6 tables in scope, 5 required fields per fault master table (20 total), 3 synchronization modes, and 6 deliverables. The delivered source implements 1 of 20 required fields, satisfies 5 of 26 acceptance criteria, and delivers 2 of 6 deliverables.
This document recommends that Bestway: (1) do not deploy this extension to production, (2) require delivery of v1.0.0.73 source code, (3) revoke the hardcoded FAQ API credentials immediately, and (4) determine whether to require Sataware to remediate or to bring the extension in-house for completion.
1. Background
The CMS 1.0 Fault Detail Sync initiative (Epic 193) was established to synchronize fault-related master data from the external FAQ API into Microsoft Dynamics 365 Business Central. The goal is to ensure BC uses only valid, active fault codes for new transactions while preserving historical Service Orders and posted data.
Sataware Technologies LLC was engaged to design and implement the extension. The Solution Design document (dated 12/16/25) was authored by Sataware, reviewed by Bestway, and explicitly approved by Phil McCaffrey on December 16:
"This updated Solution Design appears to address and satisfy all of the acceptance criteria laid out. We are good to move forward from our side."
The Solution Design is the authoritative reference for evaluating what was delivered. This review also evaluates against the Epic's 7 user stories and 26 acceptance criteria, which the Solution Design was written to satisfy.
1.1. What Changed Since v1.1
| Aspect | v1.1 Review (Mar 6) | v2.0 Review (Mar 19) |
|---|---|---|
| Source available | No — symbol extraction from .app | Yes — v1.0.0.57 source files |
| Assessment basis | Object names, field names, IDs | Full code reading of all 17 AL files |
| Deliverables marked "Unknown" | 2 (automated sync, notification) | 0 — all now assessed with evidence |
| Security findings | None (not visible via symbols) | 2 critical (hardcoded credentials) |
| Data integrity findings | None (not visible via symbols) | 3 (double execution, delete-reinsert, no transaction control) |
1.2. Source Code Version Gap
| Artifact | Version | Date |
|---|---|---|
| Source code delivered | 1.0.0.57 | File dates: Jan 27 – Feb 24, 2026 |
| Compiled .app in sandbox | 1.0.0.73 | Mar 6, 2026 |
| Gap | 16 revisions | Source for versions 58–73 not provided |
Any findings based on v1.0.0.57 source may have been addressed — or worsened — in the 16 subsequent revisions. All assessments in this document are based on the source code Sataware provided and represent the best available evidence.
1.3. Project Timeline
| Date | Event |
|---|---|
| Dec 2, 2025 | Initial effort estimate shared by Sataware (~84 hours at $28/hr) |
| Dec 5, 2025 | Bestway approves first 5 hours for Requirement Review and Solution Design |
| Dec 9, 2025 | First draft of Solution Design delivered by Sataware |
| Dec 10, 2025 | Bestway requests changes: automated sync, full rebuild approach, email notifications |
| Dec 12, 2025 | Bestway confirms automated sync was always in scope; Rob Chowdhury approves additional hours |
| Dec 16, 2025 | Updated Solution Design delivered and approved (~134 hours total) |
| Dec 23, 2025 | Sataware reports build errors (missing IWX/Innovia dependencies) |
| Feb 9, 2026 | Sataware says corrections complete; demo call scheduled |
| Feb 12, 2026 | Sataware submits Invoice #466051 |
| Feb 26, 2026 | Rob Chowdhury: testing not done; waiting for source code in repo |
| Feb 28, 2026 | v1.0.0.58 installs successfully in sandbox |
| Mar 1–3, 2026 | Versions 59–61 fail to install (BestwayUSA dependency mismatch) |
| Mar 5, 2026 | v1.0.0.73 uploaded; source code withheld pending invoice payment |
| Mar 5, 2026 | Bestway validates .app via symbol extraction; significant gaps identified |
| Mar 6, 2026 | Delivery Review v1.1 published; review call scheduled for March 9 |
| Mar 19, 2026 | Sataware delivers source code (v1.0.0.57 in zip); this review (v2.0) |
2. Requirements Inventory
2.1. Epic 193 — User Stories and Acceptance Criteria
The Epic defines 7 user stories with 26 acceptance criteria total.
| Story | Title | Acceptance Criteria |
|---|---|---|
| Story 1 | Build FAQ API Client | 3: Authentication, data fetch, update retrieval |
| Story 2 | Add Support for Sync Job with FAQ API Fields | 3: Fields added (6 fields × 6 tables), tables updated, mapping logic |
| Story 3 | Create BC Job to Fetch Updates Periodically | 3: Schedulable job, incremental fetch, configurable |
| Story 4 | Generate New BC Codes for Synced Entries | 2: Unique code generation, FAQ-to-BC mapping |
| Story 5 | Update BC to Show Only Active Records | 2: UI filtering, validation logic |
| Story 6 | Generate Email Notifications | 2: Change summary, configurable recipients |
| Story 7 | Update CSM Quality Report Submission | 3: Failure code logging, Service Item ID, fault detail logging |
Required fields per Story 2 acceptance criteria:
| Field | Type | Purpose |
|---|---|---|
| FAQ ID | Int | Links BC record to FAQ API entity |
| Active | Boolean | Controls record availability |
| Created in FAQ | Timestamp | Tracks when record was created in FAQ system |
| Updated in FAQ | Timestamp | Change detection for incremental sync |
| Created in BC | Timestamp | Tracks when record was synced into BC |
| Updated in BC | Timestamp | Tracks last BC-side update |
Tables that must receive these fields (per Story 2):
- 5915 — Fault Area
- 5916 — Symptom Code
- 5918 — Fault Code
- 5919 — Resolution Code
- 5920 — Fault/Resol. Code Relations
- 50113 — Fault Area/Symptom Code Relationship
Total required field implementations: 36 (6 fields × 6 tables).
2.2. Solution Design — Deliverables
| # | Deliverable | Source |
|---|---|---|
| D1 | Updated BC extension logic to support FAQ API synchronization | Section 4 |
| D2 | One-time full rebuild synchronization capability | Section 4, 7.1 |
| D3 | Automated incremental synchronization capability | Section 4, 7.2 |
| D4 | Stakeholder notification summary for detected changes | Section 4, 7.3 |
| D5 | Final source code delivery | Section 4, 11 |
| D6 | Supporting technical documentation | Section 4, 11 |
2.3. Solution Design — Core Design Principles (Section 6)
- No deletion of records once used in posted transactions
- Inactive records retained for historical reference
- Only active values available for new transactions
- Synchronization logic must be safe to re-run
- Existing extension boundaries must be respected
2.4. Solution Design — Data Safety Commitments (Section 9)
- No modification of posted documents
- Inactive handling ensures backward compatibility
- Partial updates are avoided
- Repeat executions do not create duplicate or invalid data
3. Delivery Analysis — Source Code Evidence
This section evaluates each requirement area against the actual source code. Every claim is backed by a specific file and line reference.
3.1. Table Extensions Delivered
| BC Table | Table ID | Extension? | Fields Added | Epic Required (6 per table) |
|---|---|---|---|---|
| Fault Area | 5915 | Yes (50076) | Status (Option: true/false) | 1 of 6 |
| Symptom Code | 5916 | NONE | — | 0 of 6 |
| Fault Code | 5918 | NONE | — | 0 of 6 |
| Resolution Code | 5919 | NONE | — | 0 of 6 |
| Fault/Resol. Relationship | 5920 | Yes (65500) | Status (Option), Source (Text) | 1 of 6 (Status only; Source not in spec) |
| Fault Area/Symptom Rel. | 50113 | NONE | — | 0 of 6 |
Result: 2 of 36 required field implementations delivered (Status on Fault Area and Status on Fault/Resol. Relationship). Missing: FAQ ID, Active, Created in FAQ, Updated in FAQ, Created in BC, Updated in BC — on all 6 tables.
Note: The Fault Area Status field uses Option type with "true"/"false" members (Field ID 50000 in PageExt/FaultAreasExt.PageExt.al, line 24). The Epic specifies an "Active (Boolean)" field. The delivered Option type with "true"/"false" does not align with the Active/Inactive semantic — "true" and "false" are not user-friendly labels and don't match any standard BC pattern.
3.2. API Client (Story 1)
| Acceptance Criterion | Status | Evidence |
|---|---|---|
| API client supports authentication | Partially implemented | GetAccessToken() exists (Codeunit 65500, line 13) but uses hardcoded credentials instead of the API Setup table |
| Can fetch data from FAQ API | Implemented | GetStandardFormat() fetches from /api/1.0/standardFormat endpoint (line 48) |
| Can retrieve updates from FAQ API | NOT implemented | No incremental fetch logic exists. GetStandardFormat() always fetches the full dataset. No "last modified" or "since" parameter is sent to the API |
Detailed assessment: The API client authenticates and fetches data, but it always performs a full fetch. There is no mechanism to request only records changed since the last sync — the /standardFormat endpoint is called with no date filter, no offset, and no pagination. The "retrieve updates" criterion requires differential fetching, which is absent.
3.3. Sync Job Fields (Story 2)
Status: 2 of 36 fields delivered. See Section 3.1 above.
The mapping logic in ProcessStandardFormatResponse (Codeunit 65500, lines 61–234) maps:
csMainCategoryId/csMainCategoryName→ Fault Area Code / DescriptioncsSubCategoryId/csSubCategoryName→ Symptom Code / DescriptionitemPartId/itemPartName→ Fault Code (keyed by Fault Area + Symptom + Code)issueTypeId/issueTypeName→ Resolution Code / Description
The mapping itself is functional for the four fault master tables. However, the FAQ API integer IDs (csMainCategoryId, etc.) are used as the BC Code values directly — they are not persisted in a separate FAQ ID field. This means the BC Code field serves double duty as both the display code and the API identifier, which violates the Solution Design's requirement (Section 7.1) that "FAQ API identifiers will be persisted as the primary reference."
3.4. Periodic Job (Story 3)
| Acceptance Criterion | Status | Evidence |
|---|---|---|
| Job can be scheduled and run periodically | Implemented | Job Queue scheduling via ScheduleMyCodeunit action (Page 65504, line 1005); supports Daily and Weekly options |
| Job fetches only updated records since last sync | NOT implemented | GetStandardFormat() always fetches all records. No incremental logic exists. No "last sync" timestamp is sent to the API |
| Scheduling is configurable | Implemented | Daily/Weekly options with time selection on the FAQ Management page |
Detailed assessment: The Job Queue scheduling works correctly for daily and weekly cadences. However, the job runs a full sync every time — it fetches the entire dataset from the FAQ API and upserts all records. This is a full rebuild on every execution, not an incremental sync. The Solution Design (Section 7.2) specifies "Detection of changes between API data and BC cache" and "Mark records Inactive when removed from the API" — neither behavior exists.
Additionally, the Job Queue integration has a critical defect: the OnAfterInsert trigger on Job Queue Log Entry (TableExt/JobQueueLogEntryExt.TableExt.al, line 7) fires after the Job Queue has already executed the codeunit, causing the sync to run twice per scheduled execution. See the Code Quality Review for full analysis.
3.5. Code Generation (Story 4)
| Acceptance Criterion | Status | Evidence |
|---|---|---|
| Code generation logic ensures uniqueness | NOT implemented | No code generation exists. FAQ API integer IDs are used directly as BC Code values |
| Code maps correctly to FAQ API ID | Partially | The API ID is the Code — there is no separate mapping |
Detailed assessment: The Epic specifies "generate unique 3–4 character codes for new entries created via sync." The delivered code uses the FAQ API's integer IDs (e.g., "7", "44", "56", "184") as the BC Code field values directly. No 3–4 character code generation algorithm exists. The ServiceItemGroupCodeBuffer table (50001) maps FAQ IDs to Service Item Group codes, but this is a manual mapping table — not an automated code generator.
3.6. Active Record Filtering (Story 5)
| Acceptance Criterion | Status | Evidence |
|---|---|---|
| UI filters out inactive records | Partially implemented | FaultAreasExt (PageExt 50001, line 16) and Faultcoderelationextpage (PageExt 65501, line 42) both filter to Status = "True" on page open |
| Validation logic respects Active flag | Partially implemented | ServiceSubformFilterExt (PageExt 50000, line 15) filters Fault Area lookup by Status = "True" on the Fault/Resol. Relationship table |
Detailed assessment: The UI filtering works on the two tables that have Status fields (Fault Area and Fault/Resol. Relationship). However, because Symptom Code, Fault Code, and Resolution Code have no Status fields, those tables cannot be filtered — all records (including any that should be inactive) remain available for selection. The filtering is structurally incomplete because it depends on table extensions that were never created.
The Service Item Worksheet Subform variant (PageExt 50005, line 44) has the Service Item Group Code filter commented out, which means it shows all active fault areas across all product categories rather than filtering by the specific service item group.
3.7. Email Notifications (Story 6)
| Acceptance Criterion | Status | Evidence |
|---|---|---|
| Email includes list of changes synced | Implemented | SendReportByEmail() and SendReportByEmailJQ() (Page 65504) generate HTML email bodies with active record counts, newly activated records, and modified record counts |
| Email sent to configured stakeholders | Implemented | Email Recipient Setup table (65550) with lookup page (65551) allows configuring recipients; emails sent via BC's Email codeunit |
Detailed assessment: Email notifications are functionally implemented. Two variants exist — a manual sync version (SendReportByEmail) and a Job Queue version (SendReportByEmailJQ). Both generate styled HTML reports and send to configured recipients.
The JQ variant tracks "newly activated" records by comparing SystemModifiedAt against the last sync timestamp from the FAQ Sync Log table (50012). This is a reasonable approach for detecting changes since the last sync, though it relies on system timestamps rather than explicit sync audit fields.
Note: The email body has a colspan mismatch (11 column header, colspan="8" fallback), and the double-execution defect means the JQ email may report incorrect counts.
3.8. CSM Quality Report Logging (Story 7)
| Acceptance Criterion | Status | Evidence |
|---|---|---|
| Log includes failure code | NOT implemented | No logging code exists for CSM Quality Report submissions |
| Log includes Service Item ID from PSI | NOT implemented | No reference to Posted Service Invoices in the source |
| Log includes Fault Area, Symptom, Fault, Resolution | NOT implemented | No verbose logging exists |
Detailed assessment: Story 7 is entirely unimplemented. There is no code that references CSM Quality Reports, Posted Service Invoices, or any logging enhancement. This story does not appear to have been addressed at all.
3.9. Solution Design — Synchronization Approaches
3.9.1. One-Time Full Rebuild Sync (Section 7.1)
| Requirement | Status | Evidence |
|---|---|---|
| All existing records marked Inactive | Partially | Report 65501 sets Status = "false" on Fault/Resol. Relationship records only. Symptom Code, Fault Code, and Resolution Code have no Status field to mark |
| Complete import from FAQ API | Implemented | GetStandardFormat() fetches and upserts all records |
| FAQ API identifiers persisted as primary reference | NOT implemented | API integer IDs used as BC Code values — no separate FAQ ID field |
| No legacy-to-API mapping logic | Compliant | No mapping logic exists |
| Historical and posted data unchanged | Appears compliant | No code touches posted documents |
3.9.2. Automated Incremental Sync (Section 7.2)
| Requirement | Status | Evidence |
|---|---|---|
| Periodic unattended execution | Implemented | Job Queue scheduling exists |
| Detection of changes between API data and BC cache | NOT implemented | Full dataset fetched every time; no change detection |
| Insert new records | Implemented | Upsert logic in ProcessStandardFormatResponse |
| Update modified records | Implemented | Description updates detected and applied |
| Mark records Inactive when removed from the API | NOT implemented | No logic to detect API-side removals |
| Maintain sync state across executions | Partially | FAQ Sync Log table tracks sync timestamps, but no per-record sync state |
3.9.3. Stakeholder Notification (Section 7.3)
| Requirement | Status | Evidence |
|---|---|---|
| Configurable recipient list | Implemented | Email Recipient Setup table and page |
| Summary of newly added records | Implemented | Insert count tracked and included in email |
| Summary of updated records | Implemented | Modify count tracked and included in email |
| Summary of records marked Inactive | NOT implemented | No logic to mark records Inactive exists, so no summary is possible |
4. Gap Analysis — Updated
4.1. Story-Level Completion
| Story | Acceptance Criteria | Satisfied | Partially | Not Implemented |
|---|---|---|---|---|
| Story 1: API Client | 3 | 1 | 1 | 1 |
| Story 2: Sync Fields | 3 | 0 | 1 | 2 |
| Story 3: Periodic Job | 3 | 2 | 0 | 1 |
| Story 4: Code Generation | 2 | 0 | 0 | 2 |
| Story 5: Active Filtering | 2 | 0 | 2 | 0 |
| Story 6: Email Notifications | 2 | 2 | 0 | 0 |
| Story 7: CSM Logging | 3 | 0 | 0 | 3 |
| Total | 18 | 5 | 4 | 9 |
4.2. Deliverable Status — Updated
| Deliverable | v1.1 Status | v2.0 Status (with source) |
|---|---|---|
| D1: BC extension logic for FAQ sync | Partially delivered | Partially delivered — core upsert works but missing 34 of 36 fields, no incremental logic, no inactive marking |
| D2: One-time full rebuild sync | Executed but unverifiable | Partially delivered — Report 65501 marks Fault/Resol. records as false, but 4 of 6 tables have no Status field to mark |
| D3: Automated incremental sync | Unknown | NOT delivered — every scheduled run is a full sync; no change detection, no API-side removal detection |
| D4: Stakeholder notification | Unknown | Delivered — email notifications work with configurable recipients and styled HTML reports |
| D5: Final source code delivery | NOT delivered | Partially delivered — v1.0.0.57 source provided but 16 revisions behind the deployed binary |
| D6: Supporting technical documentation | NOT delivered | NOT delivered — no documentation of any kind |
4.3. Required Fields Gap
| Field | Epic Spec | Tables Required | Tables Delivered | Gap |
|---|---|---|---|---|
| FAQ ID (Int) | Story 2 | 6 | 0 | 6 missing |
| Active (Boolean) | Story 2 | 6 | 0 (Status Option on 2 tables is not equivalent) | 6 missing |
| Created in FAQ (Timestamp) | Story 2 | 6 | 0 | 6 missing |
| Updated in FAQ (Timestamp) | Story 2 | 6 | 0 | 6 missing |
| Created in BC (Timestamp) | Story 2 | 6 | 0 | 6 missing |
| Updated in BC (Timestamp) | Story 2 | 6 | 0 | 6 missing |
| Total | 36 | 0 | 36 missing |
Note: While the Fault Area and Fault/Resol. Relationship tables have a "Status" Option field, this is not equivalent to the "Active (Boolean)" field specified in the Epic. The Option type uses "true"/"false" members rather than a Boolean, and the semantic meaning (Active/Inactive vs. true/false) differs. Additionally, none of the six specified fields (FAQ ID, Active, Created in FAQ, Updated in FAQ, Created in BC, Updated in BC) are present on any table.
4.4. Missing Capabilities Summary
-
Incremental sync does not exist. Every run is a full sync. There is no way to fetch only changed records, no way to detect API-side removals, and no per-record sync state to track what changed.
-
Inactive marking is incomplete. Only 2 of 6 tables have a Status field. The 4 tables without Status cannot participate in the active/inactive lifecycle.
-
Code generation does not exist. FAQ API integer IDs are used directly as BC Code values. No 3–4 character code generation algorithm was implemented.
-
CSM Quality Report logging is entirely missing. Story 7 has zero implementation.
-
FAQ API identifiers are not persisted separately. The Solution Design's requirement to persist FAQ API identifiers as the primary reference is not met — the API ID is the Code field, with no separate FAQ ID.
5. Vendor Response and Assessment
This section is unchanged from Delivery Review v1.1.
On March 5, 2026, Ashok Marimuthu (CEO, Sataware Technologies LLC) responded to the gap analysis:
"Based on our earlier discussions and the demos conducted during development, the implementation focused on adding the Status field to the Fault/Resolution table to support the inactive handling behavior required for synchronization. During those discussions, the approach was to manage the active/inactive validation through the Fault Resolution codes, since that table is the one referenced for UI validation in the service order workflow."
"From a design perspective, adding the same set of additional columns across all tables would introduce additional complexity and potential issues within the existing extension structure."
5.1. Assessment — Updated
-
5.1.1. The Solution Design lists all six tables in scope (Section 3). The Epic lists all six tables with six required fields each (Story 2). Both were authored or reviewed by Sataware. Neither limits scope to the Fault/Resolution table.
-
5.1.2. The "complexity" argument is contradicted by the effort estimate. ~134 hours at $28/hr was approved for the full scope. If only 2 tables were being extended, the effort estimate is disproportionate to the delivery.
-
5.1.3. The source code now confirms that the implementation gaps are not just missing fields — entire capabilities (incremental sync, code generation, CSM logging) are absent.
-
5.1.4. Verbal discussions do not override written, approved specifications. The Solution Design states its purpose is to "clearly define the approved scope, execution behavior, and boundaries for implementation" (Section 1).
6. Effort vs. Delivery Assessment
| Metric | Agreed | Delivered |
|---|---|---|
| Estimated effort | Invoice #466051 submitted for full amount | |
| User stories | 7 | 4 partially addressed, 1 fully addressed, 2 not addressed |
| Acceptance criteria | 18 (Stories 1–6) + 3 (Story 7) = 21 total | 5 fully satisfied, 4 partially, 9 not implemented (excl. Story 7) |
| Required field implementations | 36 (6 fields × 6 tables) | 0 of the specified fields; 2 Status fields added (not matching spec) |
| Table extensions | 6 tables | 2 tables |
| Deliverables | 6 | 1 fully delivered (notifications), 2 partially delivered, 3 not delivered |
| Core capabilities | 3 (rebuild, incremental, notification) | 1 partially delivered (rebuild runs but incomplete schema), 1 delivered (notification), 1 not delivered (incremental) |
7. Recommendations — Updated
7.1. Immediate Actions
-
7.1.1. Do not deploy to production. The security vulnerabilities documented in the companion Code Quality Review (hardcoded API credentials, hardcoded admin password) and the data integrity defects (double execution, delete-and-reinsert risk) make this extension unsafe for production use.
-
7.1.2. Revoke the FAQ API credentials (BWUFAQ / BWUFAQ123) immediately. These are now in source control and must be considered compromised.
-
7.1.3. Request the v1.0.0.73 source code. The 16-revision gap means this review may not reflect the current state. Bestway needs the matching source for any path forward.
7.2. Path Forward — Decision Required
Bestway must decide between two paths:
Option A: Require Sataware to remediate.
- Pro: Vendor accountability; they built it, they should deliver what was agreed.
- Con: Track record suggests limited responsiveness (5 source code requests over 8 days). The quality of the existing code raises questions about whether remediation will meet Bestway's standards.
- Requirement: Concrete remediation plan with dates, milestones, and acceptance criteria for each story.
Option B: Bring the extension in-house for completion.
- Pro: Full control over quality, timeline, and architecture. Bestway has the BC development capability and standards infrastructure to deliver this correctly.
- Con: Additional internal effort. Sataware's code would need to be substantially rewritten to meet Bestway's extension standards (naming, structure, telemetry, testing, documentation).
- Consideration: Invoice reconciliation — the delivered extension does not satisfy the agreed scope.
7.3. Discussion Points for Sataware
- 7.3.1. Source code gap: Provide the v1.0.0.73 source code immediately.
- 7.3.2. Scope acknowledgment: Does Sataware acknowledge the 21 acceptance criteria from the Epic and the 36 field implementations required by Story 2?
- 7.3.3. Incremental sync: Was automated incremental sync (Section 7.2) ever implemented? If so, where is the code? If not, why was it included in the effort estimate?
- 7.3.4. Code generation: Was Story 4 (unique 3–4 character codes) ever implemented?
- 7.3.5. CSM logging: Was Story 7 (CSM Quality Report verbose logging) ever started?
- 7.3.6. Invoice reconciliation: Given that 9 of 18 acceptance criteria are not implemented and 2 of 6 deliverables are not delivered, how should Invoice #466051 be reconciled?
- 7.3.7. Security: Why are API credentials hardcoded in source when the API Setup table exists?
Appendix A: Acceptance Criteria — Detailed Status
| Story | # | Acceptance Criterion | Status | Evidence |
|---|---|---|---|---|
| 1 | 1 | API client supports authentication with FAQ API | Partial | Auth works but uses hardcoded credentials (line 24) |
| 1 | 2 | Can fetch data from FAQ API | Yes | GetStandardFormat() fetches /api/1.0/standardFormat |
| 1 | 3 | Can retrieve updates from FAQ API | No | No incremental fetch — full dataset every time |
| 2 | 1 | Fields added to BC tables (6 fields × 6 tables) | No | 0 of 36 specified fields. 2 non-matching Status fields added |
| 2 | 2 | Tables updated (6 specified) | Partial | 2 of 6 tables have extensions |
| 2 | 3 | Mapping logic between FAQ API and BC tables | Partial | Mapping exists for 4 tables; missing for 2 relationship tables |
| 3 | 1 | Job can be scheduled and run periodically | Yes | Daily/Weekly Job Queue scheduling |
| 3 | 2 | Job fetches only updated records since last sync | No | Full dataset fetched every run |
| 3 | 3 | Scheduling is configurable | Yes | Time and frequency options on management page |
| 4 | 1 | Code generation ensures uniqueness | No | No code generation — API integer IDs used directly |
| 4 | 2 | Code maps correctly to FAQ API ID | No | API ID is the Code — no separate mapping |
| 5 | 1 | UI filters out inactive records | Partial | Works on 2 tables with Status; 4 tables have no Status |
| 5 | 2 | Validation logic respects Active flag | Partial | Service Order Subform lookup filters by Status on Fault/Resol. Rel. |
| 6 | 1 | Email includes list of changes synced | Yes | HTML email with active/inactive counts, change details |
| 6 | 2 | Email sent to configured stakeholders | Yes | Email Recipient Setup with user lookup |
| 7 | 1 | Log includes failure code | No | Story 7 entirely unimplemented |
| 7 | 2 | Log includes Service Item ID from PSI | No | Story 7 entirely unimplemented |
| 7 | 3 | Log includes Fault Area, Symptom, Fault, Resolution | No | Story 7 entirely unimplemented |
Appendix B: Reference Documents
| Document | Date | Location |
|---|---|---|
| Solution Design | Dec 16, 2025 | V1_CSM_1_0_Fault_Detail_Sync_Solution_Design.pdf |
| FAQ API to BC Mapping | Dec 2025 | FAQ API to BC Mapping.png |
| Epic 193 Requirements | Nov 2025 | Epic - Sync Business Central with FAQ API.docx |
| Delivery Review v1.1 | Mar 6, 2026 | CMS FAQ Management - Delivery Review v1.1.docx |
| Code Quality Review v1.0 | Mar 19, 2026 | CMS FAQ Management - Code Quality Review v1.0.docx |
| This Delivery Review v2.0 | Mar 19, 2026 | CMS FAQ Management - Delivery Review v2.0.docx |