# EnvelopeGenerator.Form – VB.NET Desktop Application Context
## Purpose
**Legacy Windows Forms application** for envelope creation, management, and signature field placement. Built with **DevExpress components** and **GdPicture14** for PDF manipulation. This application is being **migrated to ReceiverUI + API** architecture.
**Primary Libraries:** DevExpress XtraGrid/XtraEditors, GdPicture14, VB.NET (.NET Framework 4.6.2)
---
## Application Architecture
### Projects Structure
| Project | Purpose |
|---|---|
| **EnvelopeGenerator.Form** | Main WinForms UI (VB.NET) |
| **EnvelopeGenerator.CommonServices** | Shared services/helpers |
| **EnvelopeGenerator.Service** | Windows Service (legacy) |
| **EnvelopeGenerator.BBTests** | Tests |
### Key Forms (Pages)
#### 1. **frmMain.vb** - Envelope Overview (Dashboard)
**Route Equivalent:** `/sender` (EnvelopeSenderPage.razor)
**Purpose:** Main dashboard showing all envelopes with status filtering.
**Key Features:**
- **Tab-based layout** with 2+2 tabs:
- **Tab 0:** Active Envelopes (not sent/partially signed)
- **Tab 1:** Completed Envelopes (signed/rejected/deleted)
- **Tab 2:** Reports (Admin only)
- **Tab 3:** Additional Reports (Admin only)
**Envelope Status Colors:**
| Status | Color | Hex Code | Description |
|---|---|---|---|
| `EnvelopePartlySigned` | Green | `#81C784` (GREEN_300) | At least one receiver signed |
| `EnvelopeQueued` / `EnvelopeSent` | Orange | `#FFB74D` (ORANGE_300) | Sent to receivers, awaiting signatures |
| `EnvelopeCompletelySigned` | Green | `#81C784` (GREEN_300) | All receivers signed |
| `EnvelopeDeleted` / `EnvelopeWithdrawn` / `EnvelopeRejected` | Red | `#E57373` (RED_300) | Envelope cancelled/rejected |
**Receiver Status Colors (in detail grids):**
| Status | Color | Hex Code |
|---|---|---|
| `Signed` | Green | `#81C784` (GREEN_300) |
| `Not Signed` | Red | `#E57373` (RED_300) |
**Grid Layouts:**
1. **GridEnvelopes** (Active):
- Columns: ID, Title, Status, Created Date, Creator
- **Master-Detail:** Expands to show:
- **ViewReceivers:** Receiver list with status colors
- **ViewHistory:** Envelope history (status changes, emails sent)
2. **GridCompleted** (Completed):
- Same structure as GridEnvelopes
- **ViewReceiversCompleted** and **ViewHistoryCompleted** detail grids
**Toolbar Actions:**
| Button | Action | Enabled When |
|---|---|---|
| **Create Envelope** | Opens `frmEnvelopeEditor` | Always |
| **Edit Envelope** | Opens `frmEnvelopeEditor` with selected envelope | Envelope selected & not sent |
| **Delete Envelope** | Shows `frmRueckruf` (reason dialog) ? deletes | Envelope selected |
| **Show Document** | Opens PDF in temp folder | Envelope & document selected |
| **Contact Receiver** | Opens mailto link | Receiver selected |
| **Resend Invitation** | Resends email to receiver | Receiver selected |
| **Send Access Code** | Manually sends access code email | Receiver selected & UseAccessCode=true |
| **Info Mail** | Opens mailto to support team | Receiver selected (for issues) |
| **2FA Properties** | Shows `frm2Factor_Properties` dialog | Receiver selected & TFA enabled |
| **Export Report (EB)** | Exports completed envelope result PDF | Completed envelope selected |
| **Refresh** | Reloads data | Always |
| **Export to Excel** | Exports current grid to XLSX | Always |
**Auto-Refresh:** Timer refreshes every N seconds (configurable), but **only when `frmEnvelopeEditor` is not open**.
**Persistence:** Grid layouts saved to `{GridViewName}_UserLayout.xml` in user AppData folder.
---
#### 2. **frmEnvelopeEditor.vb** - Envelope Creation/Edit
**Route Equivalent:** `/sender/envelope/{id}` (future)
**Purpose:** Create or edit envelope details, add documents, manage receivers.
**Workflow:**
1. **On New Envelope:** Opens `frmEnvelopeMainData` popup **first** (title, type, settings)
2. **After popup OK:** Main editor loads
3. **Add Document:** Single PDF file (via Open Dialog or Drag & Drop)
4. **Add Receivers:** Grid with auto-complete from previous emails
5. **Edit Fields:** Opens `frmFieldEditor` for signature field placement
6. **Send Envelope:** Validates and sends invitations
**UI Layout:**
- **Top Ribbon:** DevExpress ribbon with actions
- **Left Panel:** Document list (thumbnail + details)
- **Right Panel:** Receiver list (name, email, access code, phone)
- **Bottom Bar:** Envelope ID, Creator Email, Info messages
**Ribbon Actions:**
| Button | Action | Enabled When |
|---|---|---|
| **Add File** | Opens file dialog | No document added |
| **Merge Files** | Opens `frmOrderFiles` to concatenate PDFs | No document added |
| **Delete File** | Removes document | Document selected |
| **Show File** | Opens PDF in default viewer | Document selected |
| **Edit Fields** | Opens `frmFieldEditor` | Document + receivers exist |
| **Edit Data** | Opens `frmEnvelopeMainData` | Always |
| **Save** | Saves envelope without validation | Always |
| **Send Envelope** | Validates & sends invitations | Document + receivers exist |
| **Cancel** | Closes with save prompt | Always |
| **Delete Receiver** | Removes receiver from list | Receiver selected |
**Receiver Grid:**
- **Columns:** Name, Email, Access Code, Phone (if TFA enabled)
- **Auto-complete:** Email field suggests previous receivers
- **Validation:** Email format, Phone format (+49... for TFA)
- **Access Code:** Auto-generated on email entry (if UseAccessCode=true)
- **Color Assignment:** Each receiver gets a unique color (for signature fields)
**Document Grid:**
- **Single file only** (currently limited to 1 PDF)
- **Thumbnail:** Generated via GdPicture14
- **Page Count:** Displayed
**Drag & Drop:**
- Drop PDF files directly onto form
- Only 1 file allowed
- Visual feedback (red bar if >1 file)
**Validation:**
- Title required
- Message required
- At least 1 document
- At least 1 receiver
- Valid email addresses
- Valid phone numbers (if TFA enabled)
- Signature fields exist for each receiver (before sending)
---
#### 3. **frmEnvelopeMainData.vb** - Envelope Settings Popup
**Route Equivalent:** Part of `/sender/envelope/{id}` (inline in ReceiverUI)
**Purpose:** Configure envelope metadata and behavior. **Shown as modal popup** before main editor.
**Fields:**
| Field | Type | Description |
|---|---|---|
| **Title** | Text | Envelope title (required) |
| **Envelope Type** | Dropdown | Template (ContractType, Language, defaults) |
| **Language** | Dropdown | de/en |
| **Use Access Code** | Checkbox | Require 6-digit code for signing |
| **2FA Enabled** | Checkbox | Require SMS verification (forces Access Code ON) |
| **Certification Type** | Dropdown | Basic / Advanced / Qualified |
| **Final Email to Creator** | Dropdown | No / OnComplete / OnCompleteOrReject |
| **Final Email to Receivers** | Dropdown | No / OnComplete / OnCompleteOrReject |
| **Send Reminder Emails** | Checkbox | Auto-send reminders |
| **First Reminder Days** | Number | Days before first reminder |
| **Reminder Interval Days** | Number | Days between reminders |
| **Expires When Days** | Number | Days until envelope expires |
| **Expires Warning Days** | Number | Days before expiry to warn |
**Layout:**
- **Compact mode:** Only Title, Type, Language visible
- **Expanded mode:** Click "All Options" to show reminder/expiry settings
**Behavior:**
- **On Type Selection:** Auto-fills all settings from template
- **On 2FA Enable:** Forces "Use Access Code" ON and disables checkbox
- **On New Envelope:** Shows before main editor
- **On Edit Envelope:** Opens as separate dialog, Type field read-only
**Validation:** Title is required (red border via Adorner).
---
#### 4. **frmFieldEditor.vb** - Signature Field Placement
**Route Equivalent:** `/sender/envelope/{id}/fields` (future, or inline in editor)
**Purpose:** Place signature fields on PDF pages using **GdPicture14** viewer with annotations.
**UI Layout:**
- **Left:** PDF Viewer (GdViewer) with annotation tools
- **Right:** Thumbnail navigator (ThumbnailEx2)
- **Top:** Toolbar with receiver selector and actions
**Toolbar:**
| Button | Action |
|---|---|
| **Receiver Selector** | Popup menu with receiver names (colored circles) |
| **Add Signature** | Draws new signature annotation |
| **Delete** | Removes selected annotation |
| **Save** | Saves signature fields to database |
**Signature Field Details:**
- **Size:** 1.77" × 1.96" (4.5cm × 5cm) - **FIXED SIZE**
- **Color:** Matches receiver color (from grid assignment)
- **Label:** "SIGNATUR" (or localized "Signature")
- **Position:** Draggable on PDF canvas
- **Database Format:** Coordinates stored in **INCHES** (GdPicture native)
**Coordinate System:**
- **Origin:** Top-left corner
- **Units:** Inches (not points or pixels)
- **Axes:** X right, Y down
- **Storage:** Direct INCHES values (no conversion)
**Evidence from Code:**
```vb
Private Const SIGNATURE_WIDTH As Single = 1.77 ' inches
Private Const SIGNATURE_HEIGHT As Single = 1.96 ' inches
Sub LoadAnnotation(pElement As DocReceiverElement, ...)
oAnnotation.Left = CSng(pElement.X) ' Direct INCHES assignment
oAnnotation.Top = CSng(pElement.Y)
End Sub
```
**Multi-Receiver Support:**
- **Receiver switcher:** Click receiver name in popup menu
- **Current receiver:** Highlighted in toolbar (name + colored circle)
- **Other receivers' fields:** Shown semi-transparent (30% opacity), not selectable
- **Save:** Saves current receiver's fields, switches receiver, reloads all annotations
**Annotation Behavior:**
- **New annotation:** User clicks "Add Signature" ? draws interactive annotation ? auto-sized to 1.77×1.96
- **Existing annotation:** Loaded from database, locked size (can move but not resize)
- **Styling:** Filled rectangle with centered text "SIGNATUR"
- **Validation:** No resize, no text edit, no rotation
**Unsaved Changes Prompt:**
- On form close: "There are unsaved changes. Save? Yes/No/Cancel"
- Yes ? Saves ? Closes
- No ? Discards ? Closes
- Cancel ? Stays open
---
#### 5. **frmRueckruf.vb** - Delete Reason Dialog
**Route Equivalent:** Inline confirmation in ReceiverUI
**Purpose:** Capture reason for envelope deletion/withdrawal.
**Fields:**
- **Envelope ID** (display only)
- **Envelope Title** (display only)
- **Reason** (required text box)
**Buttons:**
- **OK:** Confirms deletion with reason
- **Cancel:** Cancels operation
**Global Variables:**
```vb
Public CurrentEnvelopID As Long
Public CurrentEnvelopetitle As String
Public Shared Continue_Reject As Boolean = False
Public Shared Reject_reason As String = ""
```
---
#### 6. **frm2Factor_Properties.vb** - 2FA Management
**Route Equivalent:** `/admin/2fa/{email}` (future admin panel)
**Purpose:** View/manage 2FA settings for a receiver.
**Fields:**
- **Email Address** (display only)
- **TOTP Secret Key** (display only)
- **Registration Deadline** (display only)
**Usage:** Admin tool to debug 2FA issues or reset TOTP secrets.
---
#### 7. **frmOrderFiles.vb** - PDF Merge Tool
**Route Equivalent:** Inline in ReceiverUI (future)
**Purpose:** Select multiple PDFs and merge them into a single document.
**UI:**
- **File list:** Selected PDFs
- **Up/Down buttons:** Reorder files
- **Add/Remove buttons:** Manage list
**Merge Logic:**
- Uses GdPicture14 `MergeDocuments()`
- Output: Single PDF in temp folder
- Auto-loaded as envelope document
---
## Data Models (Controllers)
### EnvelopeListController
**Purpose:** Load envelope lists for dashboard grids.
**Methods:**
- `ListEnvelopes()` ? Active envelopes (not completed)
- `ListCompleted()` ? Completed envelopes (signed/rejected/deleted)
- `DeleteEnvelope(envelope, reason)` ? Soft delete with reason
- `GetPieChart()` ? DevExpress ChartControl (not used)
- `GetEnvelopeReceiverAddresses(userId)` ? List of previous receiver emails (for auto-complete)
---
### EnvelopeEditorController
**Purpose:** Manage envelope CRUD and document/receiver operations.
**Key Methods:**
| Method | Purpose |
|---|---|
| `CreateDocument(filePath)` | Imports PDF, extracts pages/thumbnail, saves to DB |
| `DeleteDocument(document)` | Removes document from envelope |
| `SaveReceivers(envelope, receivers)` | Saves/updates receivers with access codes |
| `DeleteReceiver(receiver)` | Removes receiver (checks if fields exist) |
| `ElementsExist(receiverId)` | Checks if signature fields exist for receiver |
| `SaveEnvelope()` | Persists envelope to database |
| `SendEnvelope()` | Validates, queues emails, sends invitations |
| `ValidateEnvelopeForSending(errors)` | Checks all receivers have signature fields |
| `GetLastNameByEmailAdress(email)` | Returns previous name for email (auto-fill) |
| `GetLastPhoneByEmailAdress(email)` | Returns previous phone for email (auto-fill) |
| `DeleteEnvelopeFromDisk(envelope)` | Cleans up temp files |
**ActionService Methods:**
- `ResendReceiver(envelope, receiver)` ? Resends invitation email
- `ManuallySendAccessCode(envelope, receiver)` ? Sends access code email
---
### FieldEditorController
**Purpose:** Manage signature field annotations (DocReceiverElement).
**Key Methods:**
| Method | Purpose |
|---|---|
| `LoadElements()` | Loads all signature fields from database |
| `AddOrUpdateElement(annotation, orientation)` | Converts GdPicture annotation ? DocReceiverElement |
| `SaveElements(receiverId)` | Persists signature fields for receiver |
| `DeleteElement(element)` | Removes signature field |
| `GetElement(annotation)` | Finds element by annotation tag |
| `GetElementInfo(tag)` | Parses annotation tag (receiverId\|page\|guid) |
**Annotation Tag Format:**
```
"{receiverId}|{page}|{elementId}"
Example: "42|1|-1" (receiver 42, page 1, unsaved)
Example: "42|1|137" (receiver 42, page 1, element ID 137)
```
**Element Coordinate Conversion:**
```vb
' Database stores INCHES directly (GdPicture native)
Sub AddOrUpdateElement(annotation, orientation)
element.X = annotation.Left ' INCHES
element.Y = annotation.Top ' INCHES
element.Width = annotation.Width ' INCHES
element.Height = annotation.Height ' INCHES
element.Page = currentPage
End Sub
```
---
## Migration to ReceiverUI + API
### Mapping Table
| Form Feature | ReceiverUI Equivalent | Status |
|---|---|---|
| **frmMain** (Envelope list) | `/sender` (EnvelopeSenderPage.razor) | ? Exists |
| Tab 0: Active Envelopes | `/sender` default view | ? Grid with filters |
| Tab 1: Completed Envelopes | `/sender` with status filter | ? Same grid |
| Status colors (Green/Orange/Red) | CSS classes `.status-signed`, `.status-pending`, etc. | ?? **Needs implementation** |
| Master-detail grids (Receivers/History) | Expandable rows or modal dialogs | ?? **Needs implementation** |
| Toolbar: Create Envelope | Button ? `/sender/envelope/new` | ?? **Needs implementation** |
| Toolbar: Edit Envelope | Button ? `/sender/envelope/{id}` | ?? **Needs implementation** |
| Toolbar: Delete Envelope | Button ? Shows delete reason modal | ?? **Needs implementation** |
| Toolbar: Show Document | Downloads PDF | ?? **Needs implementation** |
| Toolbar: Contact Receiver | `mailto:` link | ?? **Needs implementation** |
| Toolbar: Resend Invitation | API call ? refresh grid | ?? **Needs implementation** |
| Toolbar: Export Excel | Download XLSX | ?? **Needs implementation** |
| Auto-refresh timer | SignalR or polling | ?? **Needs implementation** |
| Grid layout persistence | LocalStorage | ?? **Needs implementation** |
| **frmEnvelopeEditor** | `/sender/envelope/{id}` | ? **Not implemented** |
| ? **frmEnvelopeMainData** popup | Inline form section or stepper | ? **Not implemented** |
| Document upload (Drag & Drop) | Blazor InputFile with drag zone | ?? **Needs implementation** |
| Receiver grid (auto-complete) | DevExpress Blazor Grid with lookup | ?? **Needs implementation** |
| Merge PDFs (frmOrderFiles) | Client-side PDF.js or server-side | ?? **Needs implementation** |
| **frmFieldEditor** | `/sender/envelope/{id}/fields` or inline | ? **Not implemented** |
| GdPicture PDF viewer | PDF.js + canvas overlay (like EnvelopeReceiverPage) | ?? **Partial (receiver side only)** |
| Signature field placement | Drag & drop signature boxes on canvas | ? **Not implemented** |
| Receiver color coding | CSS variables + signature field borders | ? **Not implemented** |
| Multi-receiver switcher | Dropdown or tabs | ? **Not implemented** |
| Thumbnail navigator | PDF.js thumbnail sidebar (like receiver) | ?? **Exists for receiver** |
| Save signature fields | API POST `/api/Envelope/{id}/Elements` | ? **Not implemented** |
| **frm2Factor_Properties** | Admin panel `/admin/2fa/{email}` | ? **Not implemented** |
| **frmRueckruf** (Delete reason) | Modal dialog in EnvelopeSenderPage | ?? **Needs implementation** |
---
## Critical Implementation Notes
### 1. **Coordinate System Consistency**
**Database (Form App):** INCHES (GdPicture native)
**ReceiverUI (PDF.js):** Pixels on canvas
**Conversion Required:**
```csharp
// Sender side (placing fields):
float xInches = canvasPixelX / (canvasWidth / pageWidthInches);
float yInches = canvasPixelY / (canvasHeight / pageHeightInches);
// Receiver side (displaying fields):
float canvasX = (xInches / pageWidthInches) * canvasWidth;
float canvasY = (yInches / pageHeightInches) * canvasHeight;
```
**A4 Page Dimensions:**
- Width: 8.27" = 595pt
- Height: 11.69" = 842pt
---
### 2. **Status Color System**
Form app uses **DevExpress CustomDrawCell** event for row coloring. ReceiverUI should use:
```css
/* Envelope status colors */
.envelope-row.status-partly-signed { background-color: #81C784; } /* GREEN_300 */
.envelope-row.status-queued,
.envelope-row.status-sent { background-color: #FFB74D; } /* ORANGE_300 */
.envelope-row.status-completed { background-color: #81C784; } /* GREEN_300 */
.envelope-row.status-deleted,
.envelope-row.status-rejected { background-color: #E57373; } /* RED_300 */
/* Receiver status colors */
.receiver-row.signed { background-color: #81C784; }
.receiver-row.unsigned { background-color: #E57373; }
```
---
### 3. **Master-Detail Grid Pattern**
Form app uses **nested GridViews** (ViewReceivers, ViewHistory). ReceiverUI options:
**Option A:** DevExpress Blazor Grid with master-detail template
```razor
Drop PDF here or click to browse