diff --git a/src/Apps/W1/SimplifiedBankStatementImport/App/CLAUDE.md b/src/Apps/W1/SimplifiedBankStatementImport/App/CLAUDE.md new file mode 100644 index 0000000000..3c907d81b5 --- /dev/null +++ b/src/Apps/W1/SimplifiedBankStatementImport/App/CLAUDE.md @@ -0,0 +1,119 @@ +# Simplified Bank Statement Import + +Wizard-based app that guides users through defining a CSV bank statement +import format. No coding required -- upload a sample CSV file and the app +detects separator, date format, amount format, and column positions, then +generates a full Data Exchange Definition. + +## Quick reference + +**Path:** `App/BCApps/src/Apps/W1/SimplifiedBankStatementImport/App/` +**ID range:** 8850-8862 +**Object count:** 23 (1 codeunit, 1 temporary table, 2 pages, 2 page extensions, 17 permission objects) +**Dependencies:** None +**Entry point:** Page 8850 "Bank Statement Import Wizard" (NavigatePage) + +## How it works + +### Wizard flow (8 steps) + +1. **Welcome** -- intro screen +2. **Upload** -- user uploads sample CSV file +3. **Header Lines** -- detect/confirm how many header lines to skip +4. **Separator & Column Count** -- detect comma vs semicolon, count columns +5. **Column Mapping** -- map which columns contain Date, Amount, Description +6. **Format Details** -- detect date and amount formats via regex +7. **Try It Out** -- preview parsed data with validation coloring (red = errors) +8. **Finish** -- create Data Exchange Definition and Bank Export/Import Setup + +### Format detection + +**Date patterns:** 11+ regex patterns including dd-MM-yyyy, MM/dd/yyyy, +yyyyMMdd, dd.MM.yyyy, yyyy-MM-dd, and variations. First valid match wins. + +**Amount patterns:** Two styles detected: +- Dot decimal (1,234.56) -- uses en-US locale +- Comma decimal (1.234,56 or 1'234,56) -- uses es-ES locale + +Single-quote thousands separator (') handled for Swiss/EU formats. + +### Data created on finish + +The wizard creates 8 records: + +- 1 Data Exch. Def (parent container) +- 1 Data Exch. Line Def (line structure) +- 1 Data Exch. Mapping (maps to Bank Acc. Reconciliation Line table) +- 3 Data Exch. Field Mapping (Date -> Transaction Date, Amount -> Statement Amount, Description -> Transaction Text) +- 3 Data Exch. Column Def (column positions and transformations) +- 1 Bank Export/Import Setup (links def to "BANKSTMT-IMPORT" code) +- Optionally updates Bank Account record if user selects one + +## Structure + +**Page 8850 Bank Statement Import Wizard** -- NavigatePage with 8 steps. +Contains all wizard logic (25 local procedures). Heavy lifting happens here: +- `ParseCsvFile()` -- splits CSV into temp table rows/columns +- `DetectSeparator()` -- tries comma and semicolon, picks best match +- `DetectHeaderLines()` -- counts lines before data starts +- `DetectDateFormat()` -- tries 11+ regex patterns +- `DetectAmountFormat()` -- tries dot/comma decimal patterns +- `CreateDataExchangeDefinition()` -- generates 8 records on finish + +**Page 8851 Bank Statement Import Preview** -- List page showing temp +table with parsed columns. Red text indicates validation failures. Used +in step 7 (Try It Out). + +**Table 8850 Temp Bank Import File Line** -- temporary table holding +parsed CSV data during wizard session. Not persisted. + +**Codeunit 8850 Bank Statement Import Wizard** -- thin wrapper (4 procedures): +- `Run()` -- opens wizard page +- `GetWizardPageID()` -- returns page ID for Guided Experience integration +- `OnBeforeUploadBankFile()` integration event for extensibility/testing +- `IsEnabled()` -- feature flag check + +**Page extensions:** +- 8850 extends Bank Account Card -- shows notification when no import format assigned, with action to launch wizard +- 8851 extends Payment Reconciliation Journal -- adds action to launch wizard + +**Permission objects:** 17 permission sets for different roles (read/execute/edit combinations) + +## Documentation + +See `SimplifiedBankStatementImport.md` in app folder for user guide and screenshots. + +## Things to know + +**All logic lives in the wizard page** -- Codeunit 8850 is just a thin +entry point. If you need to debug format detection or data creation logic, +look in Page 8850's local procedures. + +**Regex-based detection is greedy** -- first matching pattern wins. If +date/amount detection fails, add new patterns to the `DetectDateFormat()` +or `DetectAmountFormat()` procedures. + +**Preview validates live** -- Step 7 parses the CSV with the detected +format and colors errors red. If preview shows red, user must go back and +fix column mapping or format settings. + +**Locale codes matter** -- Amount format detection sets +`TransformationRule.DataExchangeType` to "POSITIVEPAY-EFT" (dot decimal, +en-US) or "SEPA" (comma decimal, es-ES). These control how the import +engine parses decimals. + +**Single Data Exch. Def per wizard run** -- Each execution creates a new +definition. No editing/updating existing defs. To change a format, re-run +the wizard and create a new def. + +**Guided Experience integration** -- Registered as Assisted Setup via +`GuidedExperience.InsertAssistedSetup()`. Appears in "Ready for Business" +group in the Assisted Setup page. + +**Extensibility hook** -- `OnBeforeUploadBankFile()` integration event +fires before file upload dialog. Extensions can inject test files or +bypass upload for automated testing. + +**No advanced features** -- Does not support multi-line statements, +conditional logic, or custom transformations. For complex imports, use +full Data Exchange Definition setup manually. diff --git a/src/Apps/W1/SimplifiedBankStatementImport/App/docs/business-logic.md b/src/Apps/W1/SimplifiedBankStatementImport/App/docs/business-logic.md new file mode 100644 index 0000000000..2c5074d588 --- /dev/null +++ b/src/Apps/W1/SimplifiedBankStatementImport/App/docs/business-logic.md @@ -0,0 +1,131 @@ +# Business Logic + +## Wizard Flow + +The Simplified Bank Statement Import wizard (Page 8850) guides users through an 8-step process to configure bank statement import from CSV files. + +```mermaid +flowchart TD + A[1. Welcome] --> B[2. File Upload] + B --> C[3. Header Lines] + C --> D[4. Separator/Count] + D --> E[5. Column Mapping] + E --> F[6. Format Details] + F --> G[7. Try It Out] + G --> H[8. Finish] + + B -->|OnBeforeUploadBankFile| I[Custom File Source] + I -->|TempBlob| J[ReadBankFile] + J -->|Detect separators| C + + E -->|Auto-detect| K[GetColumnsFromBankFile] + K -->|Header keywords| E + K -->|Data patterns| E + + F -->|Auto-detect| L[GetFormatsFromBankFile] + L -->|11 date patterns| F + L -->|2 amount patterns| F + + G -->|GeneratePreviewData| M[Preview Table] + M -->|TypeHelper.Evaluate| N[Validation] + N -->|Invalid fields| O[Red highlighting] + + H -->|StoreRecords| P[Data Exch. Def] + H -->|StoreRecords| Q[Bank Export/Import Setup] +``` + +### Step 1: Welcome + +Displays instructions and provides a sample CSV download link. The sample download is only available in demonstration companies. + +### Step 2: File Upload + +The file upload process follows this sequence: + +1. **OnBeforeUploadBankFile** integration event fires, allowing custom file sources (e.g., API integration). If handled externally, the wizard skips the standard upload dialog. +2. **BLOBImportWithFilter** prompts the user to select a CSV file from disk. +3. **ReadBankFile()** analyzes the uploaded content: + - Detects line separator (CRLF, CR, or LF) + - Reads the first 50 lines + - Uses regex to detect whether the file uses comma or semicolon as the field separator + - Identifies the number of header lines by analyzing line structure + +### Step 3: Header Lines + +The user can adjust the header line skip count. A preview pane highlights which lines are treated as headers versus data rows. + +### Step 4: Separator/Count + +The user selects the field separator (Space, Comma, or Semicolon). The wizard validates consistency by checking separator usage across 20 sample lines, then populates the column count. + +### Step 5: Column Mapping + +The user specifies which column numbers contain Date, Amount, and Description data. **GetColumnsFromBankFile()** attempts to auto-detect these columns using: + +1. **Header keyword matching**: Case-insensitive search for "Date", "Amount", and "Description" or "Detail" in the header row. +2. **Data pattern matching**: If keyword matching fails, the wizard applies regex patterns to detect: + - Date columns (using the 11 date patterns described below) + - Amount columns (numeric patterns with decimal separators) + +### Step 6: Format Details + +The user specifies the date format (free text) and decimal separator (Space, Dot, or Comma). **GetFormatsFromBankFile()** auto-detects these formats by testing: + +- **11 date regex patterns** covering: + - dd/MM/yyyy + - MM/dd/yyyy + - yyyyMMdd + - Variations with dot, dash, and slash separators +- **2 amount patterns**: + - Dot as decimal separator, with optional comma or quote thousands separators + - Comma as decimal separator, with optional dot thousands separator + - Swiss single-quote thousands separator (stripped before parsing) + +### Step 7: Try It Out + +**GeneratePreviewData()** populates the first 10 rows into the Bank Statement Import Preview table. The preview page validates each field using **TypeHelper.Evaluate()** with the appropriate culture context. Invalid fields are highlighted in red, allowing the user to adjust mappings or format settings before finalizing the configuration. + +### Step 8: Finish + +**StoreRecords()** creates the complete import configuration: + +1. **Data Exch. Def** record: + - Type: Bank Statement Import + - File Type: Fixed Text + - Reading/Writing XMLport: Data Exch. Import - CSV +2. **Data Exch. Line Def** record +3. **Data Exch. Mapping** record (target table: Bank Acc. Reconciliation Line) +4. **Three Data Exch. Field Mapping** records: + - Date -> Field 5 + - Amount -> Field 7 + - Description -> Field 23 +5. **Three Data Exch. Column Def** records (one for each mapped column) +6. **Bank Export/Import Setup** record (direction: Import) +7. Optionally updates the **Bank Account** record to link the new import format + +## Format Detection Details + +### Date Patterns + +The wizard tests 11 regex patterns to identify date columns and formats: + +- dd/MM/yyyy +- MM/dd/yyyy +- yyyy/MM/dd +- dd-MM-yyyy +- MM-dd-yyyy +- yyyy-MM-dd +- dd.MM.yyyy +- MM.dd.yyyy +- yyyy.MM.dd +- yyyyMMdd +- ddMMyyyy + +### Amount Patterns + +Two primary patterns detect amount columns: + +1. **Dot decimal**: Matches numbers with a dot as the decimal separator. Supports comma or single-quote thousands separators (e.g., 1,234.56 or 1'234.56). +2. **Comma decimal**: Matches numbers with a comma as the decimal separator. Supports dot thousands separators (e.g., 1.234,56). + +Swiss-style single-quote thousands separators are stripped from the text before parsing to ensure compatibility with TypeHelper.Evaluate(). diff --git a/src/Apps/W1/SimplifiedBankStatementImport/App/docs/extensibility.md b/src/Apps/W1/SimplifiedBankStatementImport/App/docs/extensibility.md new file mode 100644 index 0000000000..16ee3e4ce0 --- /dev/null +++ b/src/Apps/W1/SimplifiedBankStatementImport/App/docs/extensibility.md @@ -0,0 +1,71 @@ +# Extensibility + +The Simplified Bank Statement Import app is designed as a closed configuration wizard. It provides limited extensibility points for custom file sources and UI integration, but does not expose a public API for programmatic extension by ISVs. + +## Integration Events + +### OnBeforeUploadBankFile + +**Codeunit 8850** publishes the **OnBeforeUploadBankFile** integration event, allowing external code to provide custom file sources instead of the standard file upload dialog. + +**Parameters:** +- `FileName` (out, Text): The name of the file being imported +- `TempBlob` (out, Codeunit "Temp Blob"): The file content as a binary large object +- `IsHandled` (out, Boolean): Set to true to skip the standard upload dialog + +**Use cases:** +- Loading bank statements from an API endpoint +- Injecting mock CSV files during automated testing (used by the app's test framework) +- Integrating with document management systems + +**Example usage:** +```al +[EventSubscriber(ObjectType::Codeunit, Codeunit::"Bank Statement File Wizard", 'OnBeforeUploadBankFile', '', false, false)] +local procedure HandleCustomFileSource(var FileName: Text; var TempBlob: Codeunit "Temp Blob"; var IsHandled: Boolean) +begin + if not ShouldHandleUpload() then + exit; + + // Load file content into TempBlob + LoadFileFromAPI(TempBlob); + FileName := 'bank-statement.csv'; + IsHandled := true; +end; +``` + +## Guided Experience Integration + +The wizard registers itself with the Guided Experience framework by subscribing to the **OnRegisterAssistedSetup** event. + +**Registration details:** +- **Group**: "Ready for Business" +- **Object Type**: Page +- **Object ID**: 8850 (Bank Statement File Wizard) +- **Multi-language support**: Calls `AddTranslationForSetupObjectTitle()` to register translated titles for each language + +This registration makes the wizard discoverable through the standard Assisted Setup page and related UI entry points. + +## UI Entry Points + +### Bank Account Card Notification + +The **Bank Account Card** page extension creates a notification when a bank account has no import format assigned. The notification: + +- Stores the bank account code in notification data +- Displays an action that triggers **RunBankStatementFileWizard()** +- Guides users directly to the wizard from the bank account card + +### Bank Export/Import Setup Action + +The **Bank Export/Import Setup** list page extension adds a **"Bank Statement File Format Wizard"** action, providing direct access to the wizard from the setup list. + +## Design Philosophy + +This app follows a **closed configuration wizard** pattern: + +- All codeunit and page procedures are marked as `local` or `internal` +- No public API is exposed for ISVs to call +- The wizard is designed for end-user interaction, not programmatic automation +- The only extension point for external code is the **OnBeforeUploadBankFile** event + +This design ensures a consistent user experience while allowing targeted integration for custom file sources. If you need to extend the import process beyond file sourcing, consider building a separate Data Exchange Definition using the standard Business Central framework rather than extending this wizard.