Iris Debt Collection Management System

Enterprise-Grade Financial Operations Platform


Executive Summary

Iris is a sophisticated, enterprise-scale debt collection and payment processing system built on modern .NET architecture. It exemplifies professional software engineering through clean architecture, domain-driven design, and comprehensive test coverage. The system manages the complete lifecycle of debt collection operations, from case assignment through payment reconciliation and financial reporting.

Iris UI Samples

Key Differentiators:

  • Multi-platform deployment (Desktop, Web, Services) from a unified codebase
  • Rich domain model with 316+ business entities
  • Comprehensive audit trail and compliance features
  • Enterprise-grade CI/CD with Azure Pipelines
  • Extensible framework architecture supporting multiple products

Table of Contents

  1. Project Overview
  2. Technical Architecture
  3. Technology Stack
  4. System Components
  5. Domain Model
  6. Design Patterns & Best Practices
  7. Build & Deployment
  8. Notable Technical Achievements

Project Overview

What is Iris?

Iris is a comprehensive debt collection and case management platform designed for collection agencies and creditor organizations. It automates and streamlines the entire debt recovery process while maintaining compliance with financial regulations and providing detailed audit trails.

Key Features

Case Management

  • Complete job lifecycle tracking from assignment to resolution
  • Multi-party coordination (agents, coordinators, clients, debtors)
  • Task assignment and workflow automation
  • Document management and attachment tracking

Financial Operations

  • Multi-ledger accounting system
  • Payment processing integration (Bpoint gateway)
  • Transaction reconciliation and clearing
  • Xero accounting software integration
  • Comprehensive financial reporting

Communication Hub

  • Email integration with Outlook/Exchange
  • Communication template management
  • Automated email capture and tracking
  • SMS and phone call logging

Reporting & Analytics

  • Active jobs dashboard
  • Financial performance reports
  • Agent productivity tracking
  • Customizable charts and visualizations
  • Export to Word, Excel, and PDF

Batch Processing

  • Scheduled task execution via ServerActions
  • Payment file processing
  • Data synchronization with external systems
  • Automated workflow execution

Target Users

  • Debt Collection Agencies: Primary users managing collections on behalf of creditors
  • Credit Management Teams: In-house collection departments
  • Financial Coordinators: Support staff managing administrative tasks
  • Management: Executive reporting and oversight
  • Client Contacts: Creditor representatives monitoring progress

Technical Architecture

Architectural Overview

Iris employs a layered architecture with clear separation of concerns, built upon the proprietary Torq Framework. This design enables code reuse, maintainability, and testability while supporting multiple deployment targets from a single codebase.

Architectural Principles

For Software Developers:

  1. Separation of Concerns: Each layer has distinct responsibilities with minimal coupling
  2. Domain-Driven Design: Rich domain model encapsulates business rules and behavior
  3. Dependency Inversion: High-level modules don’t depend on low-level modules; both depend on abstractions
  4. Single Responsibility: Components and classes have focused, well-defined purposes
  5. Open/Closed Principle: Framework is open for extension but closed for modification

For Business Stakeholders:

  • Maintainability: Clean architecture reduces technical debt and makes updates faster and safer
  • Scalability: Layered design supports horizontal scaling and performance optimization
  • Flexibility: Multiple deployment models from one codebase reduces costs
  • Quality: Strong separation enables comprehensive testing at each layer
  • Risk Reduction: Well-defined boundaries limit the impact of changes

Framework Architecture: The Torq Foundation

The Torq Framework provides enterprise-grade infrastructure that Iris builds upon:

Why This Matters:

  • Reusability: Framework components used across multiple products
  • Consistency: Standardized patterns throughout the application
  • Productivity: Pre-built infrastructure accelerates feature development
  • Reliability: Battle-tested framework code reduces bugs

Technology Stack

Core Technologies

Programming Languages & Runtimes

Primary Language: C# 11.0

  • Modern language features (pattern matching, records, nullable reference types)
  • Language version locked to 11.0 for consistency across .NET 7.0 and .NET Framework projects
  • Defined in Directory.Build.props to prevent accidental C# 12 usage

Runtime: .NET 7.0

  • Cross-platform capability (Windows-focused deployment)
  • Performance improvements over .NET Framework
  • Modern async/await patterns throughout
  • Windows-specific builds (.NET 7.0-windows) for desktop applications

Frontend Technologies

Web: Blazor Server

  • Component-based architecture
  • Real-time server-side rendering
  • SignalR for WebSocket communication
  • Reactive patterns via Phork.Blazor.Reactivity

Desktop: Windows Forms

  • Custom controls via NineRays layout manager
  • Syncfusion chart components for visualizations
  • Rich desktop experience for power users

UI Component Libraries

  • Syncfusion (v20.1.0.50): Enterprise-grade components for charts, grids, document generation
  • Bootstrap 5: Responsive web design framework

Backend Technologies

Data Access

  • Entity Framework Core: Modern ORM with LINQ support
  • Custom Matisse Mapping: Legacy database integration
  • Change Tracking: Audit trail via Torq.Mapping.ChangeReporter
  • Multi-database Support: SQL Server (production), SQLite (dev)

Dependency Injection

  • Autofac (v6.3.0): Feature-rich IoC container
  • Constructor-based injection throughout
  • Module-based registration for clean organization
  • Integration with ASP.NET Core DI

API Integration

  • NSwag: OpenAPI/Swagger client code generation
  • Type-safe service clients: Generated from OpenAPI specs
  • REST integration: Collect API, Xero API, Bpoint gateway

Development & Build Tools

Build Orchestration: NUKE

  • Cross-platform build automation
  • Product-specific builders (IrisWindowsBuilder, IrisBlazorBuilder, etc.)
  • Local and CI consistency
  • Extensible target system

CI/CD: Azure Pipelines

  • Multi-stage pipeline (Build, Deploy)
  • Parameterized builds for flexibility
  • Environment-specific deployment (Production, Staging, Test)
  • Artifact management and versioning

Version Control

  • Git with GitVersion for semantic versioning
  • Branch-based deployment strategy
  • Automated changelog generation

External Integrations

Payment Processing

  • Bpoint gateway (SOAP web services)
  • Xero accounting (OAuth2 REST API)
  • Bank file imports (SFTP)

Communication

  • Exchange Web Services (EWS)
  • Outlook Redemption (COM interop)
  • SMTP with fallback (OpenSmtp library)

File Operations

  • SSH/SFTP (Renci.SshNet)
  • Document generation (Syncfusion DocIO/XlsIO)
  • Compression (ProDotNetZip, Xceed.Zip)

Testing Infrastructure

Unit Testing

  • NUnit 3 framework
  • Moq for mocking dependencies
  • Test coverage across domain model and services

Test Data Generation

  • Bogus library for realistic fake data
  • Iris.Faker custom extensions
  • Repeatable test scenarios

System Components

Product Architecture

Iris is delivered as multiple coordinated applications, each built from the shared codebase:

1. Iris.Windows (Desktop Application)

Purpose: Rich client application for power users requiring advanced functionality

Key Features:

  • Full CRUD operations on all domain entities
  • Advanced filtering and search capabilities
  • Bulk operations and batch updates
  • Custom report designer
  • Offline operation capability

Technology:

  • Windows Forms with custom controls
  • .NET 7.0-windows runtime
  • Supports both x86 and x64 architectures
  • ClickOnce-style deployment via network share

Deployment:

  • Published to C:\Iris.Windows\[Version] on terminal servers
  • Versioned folders enable rollback
  • Production and staging deployment paths

Entry Point: /DotNet/Iris/Products/IrisWindows/Program.cs

2. Iris.Blazor (Web Application)

Purpose: Modern web interface accessible from any device

Key Features:

  • Responsive design for mobile/tablet/desktop
  • Real-time updates via SignalR
  • Azure AD authentication
  • Session management and user tracking
  • Maintenance mode support

Technology:

  • ASP.NET Core Blazor Server
  • Azure AD authentication (Microsoft Identity Platform)
  • IIS deployment via WebDeploy
  • Docker containerization support

Configuration: Defined in IrisPages.yml for dynamic page routing

Deployment:

  • IIS website at /iris virtual application
  • Automated deployment to Azure DevOps environments
  • TakeAppOffline during deployment for zero-downtime

Entry Point: /DotNet/Iris/Products/Iris.Blazor/Program.cs:18

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory(InitializeApp))
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

3. Iris.ServerActions (Batch Processing Service)

Purpose: Execute scheduled and long-running background tasks

Key Capabilities:

  • Scheduled task execution
  • Data import/export operations
  • Email processing and sending
  • Report generation and distribution
  • Data synchronization with external systems

Technology:

  • Console application (.NET 7.0-windows)
  • Command-line interface (Iris.Cli)
  • Windows Task Scheduler integration
  • Change reporting and audit logging

Deployment:

  • Service-style deployment to C:\Iris.ServerActions\[Version]
  • Staging subfolder for testing before production
  • Scheduled via Windows Task Scheduler

Entry Point: /DotNet/Iris/Products/IrisServerActions/Program.cs

4. Iris.PaymentProcessor (Payment Service)

Purpose: Automated payment file processing and gateway integration

Key Functions:

  • Bank file import via SFTP
  • Payment reconciliation
  • Bpoint gateway submission
  • Payment clearing and posting
  • Error handling and retry logic

Technology:

  • Console application (.NET 7.0-windows)
  • SSH/SFTP connectivity (Renci.SshNet)
  • Transactional processing
  • Comprehensive logging (Serilog)

Deployment:

  • Standalone service at C:\Iris.PaymentProcessor\[Version]
  • Scheduled execution via Task Scheduler
  • Staging testing path available

Entry Point: /DotNet/Iris/Products/Iris.PaymentProcessor/Program.cs

Subsystem Interactions


Domain Model

Domain-Driven Design

Iris employs a rich domain model with 316+ business entities that encapsulate both data and behavior. This approach ensures business rules are centralized, testable, and maintainable.

Core Domain Entities

Key Domain Areas

1. Party Management

  • Agent: Collection agency staff assigned to jobs
  • Client: Creditor organizations placing debt for collection
  • Borrower: Individuals who owe debts
  • Coordinator: Support staff managing operations
  • Agency: The collection agency organization
  • ClientContact: Creditor representatives

2. Case Management

  • Job: Primary work unit representing a debt collection case
  • Task: Actionable work items within jobs
  • Communication: Recorded interactions (emails, calls, meetings)
  • Note: Documentation and status updates
  • Skip: Skip tracing activities to locate debtors

3. Financial Management

  • Account: General ledger accounts (AR, expenses, revenue)
  • Transaction: Multi-entry financial transactions
  • Entry: Individual ledger entries
  • CombinedLedger: Unified view of all financial activity
  • Payment: Payment receipts and allocations

4. Document Management

  • Attachment: File attachments linked to jobs
  • GeneratedDocument: System-created documents
  • RequestedDocument: Documents requested from parties
  • EmailMessage: Email communications and attachments

5. Configuration

  • ChecklistConfiguration: Workflow checklists
  • CommunicationTemplate: Email and letter templates
  • ContractNumberStrategy: Contract numbering rules
  • Announcement: System announcements

Authorization Model

The domain model includes attribute-based authorization for fine-grained access control:

[AllowCreate(typeof(Administrator), typeof(Manager), typeof(Coordinator))]
[AllowDelete(typeof(Administrator), typeof(Manager))]
[AllowRead(typeof(Agent), typeof(ClientContact))]
public class Job : TorqObject
{
    [AllowWrite(typeof(Administrator), typeof(Manager))]
    public Money JobFee { get; set; }

    [DenyRead(typeof(ClientContact))]
    public Money AgencyCommission { get; set; }
}

This pattern enables:

  • Role-based access control at the entity and property level
  • Declarative security that’s easy to audit
  • Automatic enforcement by the framework
  • Clear documentation of security requirements

Object Context Pattern

All domain entities exist within an IObjectContext that provides:

  • Identity Map: Ensures single instance per object ID
  • Change Tracking: Monitors modifications for persistence
  • Lazy Loading: Loads related entities on demand
  • Query Interface: LINQ-based querying
  • Transaction Management: Unit of work pattern

Example usage from Iris.Blazor:

// Context provides authenticated, change-tracked access to domain model
public class JobService
{
    private readonly ITorqIrisObjectContext _context;

    public IEnumerable<Job> GetActiveJobs()
    {
        return _context.Jobs
            .Where(j => j.DateClosed == null)
            .OrderByDescending(j => j.DateCreated);
    }

    public void AssignJob(Job job, Agent agent)
    {
        job.AssignAgent(agent);  // Business logic in domain model
        _context.SaveChanges();  // Persist changes
    }
}

Design Patterns & Best Practices

Architectural Patterns

1. Layered Architecture

The system is organized into distinct layers with one-way dependencies:

Presentation → Application → Domain → Data Access → Infrastructure

Benefits:

  • Testability: Each layer can be tested independently
  • Maintainability: Changes isolated to specific layers
  • Flexibility: Can swap implementations (e.g., database providers)

2. Domain-Driven Design (DDD)

  • Ubiquitous Language: Domain model reflects business terminology
  • Aggregates: Job is an aggregate root managing related entities
  • Value Objects: Money, Address, Phone are immutable value objects
  • Domain Services: Complex operations span multiple entities
  • Repository Pattern: Abstract data access via object context

3. Dependency Injection

Autofac container manages all dependencies:

// Service registration in Startup.cs
builder.RegisterType<JobService>().AsSelf();
builder.RegisterType<PaymentService>().AsSelf();
builder.RegisterType<SqlServerObjectContext>()
    .As<ITorqIrisObjectContext>()
    .InstancePerLifetimeScope();

Benefits:

  • Loose coupling: Components depend on interfaces
  • Testability: Can inject mocks for testing
  • Flexibility: Easy to swap implementations
  • Lifetime management: Automatic disposal of resources

4. Unit of Work

The IObjectContext implements the Unit of Work pattern:

using (var context = contextFactory.CreateContext())
{
    var job = context.Jobs.Find(jobId);
    job.Close(DateTime.Now);

    var payment = new Payment { Amount = job.Balance };
    job.Payments.Add(payment);

    context.SaveChanges();  // All changes persisted atomically
}

Benefits:

  • Transaction integrity: All-or-nothing persistence
  • Performance: Batches database operations
  • Consistency: Ensures related changes succeed together

5. Repository Pattern

Object context provides repository-like access:

// Query interface abstracts database details
var overdueJobs = context.Jobs
    .Where(j => j.DateClosed == null)
    .Where(j => j.DaysOld > 90)
    .Include(j => j.Agent)
    .Include(j => j.Client)
    .ToList();

Creational Patterns

Factory Pattern

Used for complex object creation:

public class ContractNumberFactory
{
    public string GenerateContractNumber(Client client, ContractNumberStrategy strategy)
    {
        return strategy.Type switch
        {
            StrategyType.Sequential => GenerateSequential(client),
            StrategyType.DateBased => GenerateDateBased(client),
            StrategyType.ClientPrefixed => GenerateClientPrefixed(client),
            _ => throw new ArgumentException($"Unknown strategy: {strategy.Type}")
        };
    }
}

Singleton Pattern

Application-level singletons:

// Torq application singleton
TorqApplication.DefineSingleton(new IrisBlazorApplication(builder));
var app = TorqApplication.CurrentApplication;

Structural Patterns

Adapter Pattern

Integrates external APIs:

// Xero API adapter
public class XeroPaymentAdapter : IPaymentGateway
{
    private readonly XeroClient _client;

    public PaymentResult SubmitPayment(Payment payment)
    {
        var xeroPayment = MapToXeroPayment(payment);
        var result = _client.CreatePayment(xeroPayment);
        return MapFromXeroResult(result);
    }
}

Proxy Pattern

Visual proxies for UI representation:

[VisualProxy("Iris.Images.Jobs.ico")]
[CollectionVisualProxy("Iris.Images.Jobs.ico")]
public class Job : TorqObject
{
    // Framework automatically loads icon for UI display
}

Facade Pattern

Service layer provides simplified interface:

public class JobManagementService
{
    public void CreateJobFromContract(Contract contract, Agent agent)
    {
        // Orchestrates multiple operations
        var job = CreateJob(contract);
        job.AssignAgent(agent);
        CreateInitialTasks(job);
        SendNotifications(job);
        SaveJob(job);
    }
}

Behavioral Patterns

Strategy Pattern

Contract number generation strategies:

public interface IContractNumberStrategy
{
    string Generate(Client client);
}

public class SequentialStrategy : IContractNumberStrategy { }
public class DateBasedStrategy : IContractNumberStrategy { }

Observer Pattern

Change tracking and event notifications:

public class Job : TorqObject
{
    protected override void OnPropertyChanged(string propertyName)
    {
        base.OnPropertyChanged(propertyName);

        // Notify change reporter for audit trail
        ChangeReporter.RecordChange(this, propertyName);
    }
}

Command Pattern

Server actions execute commands:

public interface IServerAction
{
    string Name { get; }
    void Execute(ActionContext context);
}

public class SendOverdueNoticesAction : IServerAction
{
    public void Execute(ActionContext context)
    {
        var jobs = GetOverdueJobs();
        foreach (var job in jobs)
        {
            SendNotice(job);
        }
    }
}

Template Method Pattern

Base builders define build workflow:

public abstract class BaseBuilder
{
    public void Publish()
    {
        PrePublish();
        DotNetPublish();
        PostPublish();
        CreateArtifact();
    }

    protected virtual void PrePublish() { }
    protected abstract void DotNetPublish();
    protected virtual void PostPublish() { }
    protected abstract void CreateArtifact();
}

Code Organization

Separation of Concerns

Each project has a focused responsibility:

  • Iris.Model: Domain entities only (no UI, no data access)
  • Iris.Services.*: Business logic and external integration
  • Iris.Blazor: Presentation logic and Blazor components
  • Iris.Windows: Windows Forms UI logic
  • Torq.Mapping.*: Data access implementations

Convention-Based Configuration

Autofac modules use conventions:

builder.RegisterAssemblyTypes(typeof(JobService).Assembly)
    .Where(t => t.Name.EndsWith("Service"))
    .AsSelf()
    .InstancePerLifetimeScope();

Error Handling

Centralized Exception Handling

  • Global exception filters in ASP.NET Core
  • Try-catch blocks at service boundaries
  • Detailed logging via Serilog
  • User-friendly error messages

Validation

  • Property-level validation in domain model
  • Service-level business rule validation
  • Client-side validation in Blazor forms
  • Server-side validation always enforced

Testing Strategies

Unit Tests

Test individual components in isolation:

[Test]
public void Job_CalculateInvoiceAmount_IncludesJobFeeAndExpenses()
{
    var job = new Job { JobFee = new Money(100) };
    job.Expenses.Add(new Expense { Amount = new Money(25) });

    Assert.That(job.InvoiceAmount, Is.EqualTo(new Money(125)));
}

Integration Tests

Test database interactions:

[Test]
public void ObjectContext_SaveJob_PersistsToDatabase()
{
    using var context = CreateTestContext();
    var job = new Job { Number = "TEST001" };
    context.Jobs.Add(job);
    context.SaveChanges();

    var loaded = context.Jobs.Single(j => j.Number == "TEST001");
    Assert.That(loaded, Is.Not.Null);
}

Test Data Generation

Bogus/Faker for realistic test data:

var jobFaker = new Faker<Job>()
    .RuleFor(j => j.Number, f => f.Random.AlphaNumeric(8))
    .RuleFor(j => j.DateCreated, f => f.Date.Past())
    .RuleFor(j => j.JobFee, f => new Money(f.Finance.Amount()));

var testJobs = jobFaker.Generate(100);

Build & Deployment

Build System Architecture

Iris uses NUKE Build for cross-platform, type-safe build automation:

NUKE Build System

Key Features:

  • Type-safe: Strongly-typed build definitions in C#
  • Cross-platform: Runs on Windows, Linux, macOS
  • Composable: Reusable build components
  • Local/CI consistency: Same build process everywhere

Build Targets:

From /Build/MainBuilder.cs:122:

Target Restore => _ => _
    .Description("Restores nuget packages referenced in the selected Iris products.")
    .Executes(() => RunSelectedBuilders(b => b.Restore()));

Target Clean => _ => _
    .Description("Cleans the temporary build file output.")
    .Executes(() => RunSelectedBuilders(b => b.Clean()));

Target Publish => _ => _
    .Description("Publishes the build output.")
    .After(Clean)
    .After(Restore)
    .Executes(() => RunSelectedBuilders(b => b.Publish()));

Target Test => _ => _
    .Description("Runs the automated tests.")
    .After(Publish)
    .Executes(() => { /* Run NUnit tests */ });

Usage:

# Build all products in Release configuration
./build.ps1 Publish --configuration Release --product All

# Build specific product for testing
./build.ps1 Publish --product IrisBlazor --configuration Debug

# Run tests
./build.ps1 Test --product All

# Generate API client code
./build.ps1 GenerateCollectApi

Product Builders

Each product has a dedicated builder:

IrisWindowsBuilder:

  • Builds x86 and x64 versions
  • Creates versioned artifacts
  • Packages as ZIP archives
  • Output: Iris.Windows-[Version]-[Platform].zip

IrisBlazorBuilder:

  • Publishes web application
  • Bundles wwwroot assets
  • Prepares for IIS deployment
  • Output: Iris.Blazor-[Version].zip

IrisServerActionsBuilder:

  • Compiles console application
  • Includes CLI configuration
  • Packages dependencies
  • Output: Iris.ServerActions-[Version].zip

IrisPaymentProcessorBuilder:

  • Builds payment service
  • Includes SSH libraries
  • Configures logging
  • Output: Iris.PaymentProcessor-[Version].zip

CI/CD Pipeline

Azure Pipelines Configuration (azure-pipelines.yml):

stages:
  - stage: Build
    jobs:
      - job: BuildApps
        steps:
          - task: PowerShell@2
            inputs:
              filePath: build.ps1
              arguments: DeepClean Publish Test BackupOpenSourceRepos
                --configuration Release
                --product All
                --artifacts-directory $(Build.ArtifactStagingDirectory)

          - task: PublishPipelineArtifact@1
            displayName: Publish Iris Blazor Artifact
            inputs:
              targetPath: $(BuildStep.IrisBlazorArtifact)
              artifact: IrisBlazor

  - stage: DeployIrisBlazor
    dependsOn: Build
    jobs:
      - deployment: DeployToWebServer
        environment: IrisBlazor-Production
        strategy:
          runOnce:
            deploy:
              steps:
                - task: IISWebAppDeploymentOnMachineGroup@0
                  inputs:
                    WebSiteName: 'Default Web Site'
                    VirtualApplication: 'iris'
                    Package: '$(Pipeline.Workspace)/IrisBlazor/Iris.Blazor-*.zip'

Pipeline Features:

  • Parameterized Builds: Configure products, configuration, verbosity
  • Agent Pools: Support for Microsoft-hosted and self-hosted agents
  • Branch-Based Deployment: Automatic environment selection
    • production branch → Production servers
    • staging branch → Staging environment
    • test branch → Test servers
  • Multi-Stage Deployment: Sequential deployment with approvals
  • Rollback Support: Versioned deployments enable quick rollback

Deployment Architecture

Deployment Targets:

From azure-pipelines.yml:49:

  • Production Branch:

    • IrisBlazor → IIS virtual application /iris
    • IrisWindows x64 → Terminal Server C:\Iris.Windows\[Version]
    • ServerActions → C:\Iris.ServerActions\[Version]
    • PaymentProcessor → C:\Iris.PaymentProcessor\[Version]
  • Staging Branch:

    • IrisBlazor → Staging IIS site
    • ServerActions/PaymentProcessor → C:\[Product]\Staging

Versioning:

  • GitVersion for semantic versioning
  • Version embedded in artifacts
  • Enables side-by-side deployment
  • Quick rollback by switching folders

Docker Support

Iris.Blazor includes Dockerfile for containerization:

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["Iris.Blazor.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build

FROM build AS publish
RUN dotnet publish -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Iris.Blazor.dll"]

Benefits:

  • Platform-independent deployment
  • Consistent runtime environment
  • Scalability via container orchestration
  • Development/production parity

Notable Technical Achievements

1. Unified Multi-Platform Architecture

Challenge: Support desktop, web, and service applications from a single codebase without code duplication.

Solution: Layered architecture with framework abstraction.

Technical Details:

  • Torq Framework provides platform-agnostic core
  • Domain model shared across all presentation layers
  • Dependency injection enables platform-specific implementations
  • 316 domain entities used by all 4 products

Business Value:

  • Reduced development costs through code reuse
  • Consistent behavior across platforms
  • Single domain model simplifies testing
  • Feature parity across desktop and web

2. Comprehensive Audit Trail System

Challenge: Financial regulations require complete audit trails of all data changes.

Solution: Automatic change tracking via Torq.Mapping.ChangeReporter.

Technical Details:

  • Property-level change detection
  • Before/after value capture
  • User and timestamp attribution
  • Async change reporting for performance

Implementation:

public class Job : TorqObject
{
    protected override void OnPropertyChanged(string propertyName)
    {
        base.OnPropertyChanged(propertyName);

        // Framework automatically captures change
        // - Old value
        // - New value
        // - User making change
        // - Timestamp
        // - Property metadata
    }
}

Business Value:

  • Regulatory compliance (financial audits)
  • Dispute resolution (who changed what when)
  • Debugging and troubleshooting
  • Security and accountability

3. Type-Safe Build System

Challenge: Traditional build scripts (batch files, shell scripts) are error-prone and platform-specific.

Solution: NUKE build system with C# build definitions.

Technical Details:

  • Strongly-typed build configuration
  • Compile-time verification of build logic
  • IDE support (IntelliSense, refactoring)
  • Cross-platform execution

From /Build/MainBuilder.cs:35:

public class MainBuilder : NukeBuild
{
    [Parameter("Which Iris products to build")]
    public readonly Product Product = Product.All;

    [Solution("DotNet/Iris/Products/IrisWindows/Iris.Windows.sln")]
    public readonly Solution IrisWindowsSolution;

    Target Publish => _ => _
        .After(Clean)
        .After(Restore)
        .Executes(() => RunSelectedBuilders(b => b.Publish()));
}

Benefits:

  • Build breaks at compile-time, not runtime
  • Refactoring build code is safe
  • Same build process locally and in CI
  • Easier to maintain than scripts

4. OAuth2 Integration with Xero

Challenge: Integrate with Xero accounting software using modern OAuth2 authentication.

Solution: Custom OAuth2 flow with token refresh management.

Technical Details:

  • Iris.Services.XeroAuth2 service library
  • Automatic token refresh before expiry
  • Secure token storage
  • Type-safe API client generation

Business Value:

  • Automated accounting synchronization
  • Reduced manual data entry
  • Real-time financial reporting
  • Improved accuracy

5. OpenAPI Code Generation

Challenge: Maintain type-safe client code for external REST APIs as they evolve.

Solution: Automated code generation from OpenAPI/Swagger specifications.

From /Build/MainBuilder.cs:146:

Target GenerateCollectApi => _ => _
    .Description("Generates CSharp client code from a Swagger/OpenAPI specification.")
    .Executes(async () =>
    {
        string json = File.ReadAllText("swaggerCollectClient.json");
        OpenApiDocument document = await OpenApiDocument.FromJsonAsync(json);

        var generator = new CSharpClientGenerator(document, settings);
        string code = generator.GenerateFile();

        File.WriteAllText("CollectClient.Generated.cs", code);
    });

Benefits:

  • Type-safe API clients
  • Compile-time verification of API calls
  • Automatic updates when API changes
  • IntelliSense support for API methods

6. Attribute-Based Authorization

Challenge: Enforce fine-grained access control across 316 domain entities.

Solution: Declarative authorization via attributes on domain model.

Technical Details: From /DotNet/Iris/Model/Domain/Job.cs:84:

[AllowCreate(typeof(Administrator), typeof(Manager), typeof(Coordinator))]
[AllowDelete(typeof(Administrator), typeof(Manager))]
public class Job : TorqObject
{
    [AllowWrite(typeof(Administrator), typeof(Manager))]
    public Money JobFee { get; set; }

    [DenyRead(typeof(ClientContact))]
    public Money AgencyCommission { get; set; }
}

Framework enforcement:

  • Automatic checks before property access
  • Runtime exceptions for unauthorized access
  • UI layer can query permissions for display logic

Benefits:

  • Security rules documented in code Challenge: Support production SQL Server, development SQLite, and legacy Oracle/Matisse databases.
  • Easy to audit and review
  • Prevents accidental data exposure Challenge: Support production SQL Server, development SQLite, and legacy Oracle/Matisse databases.

7. Multi-Database Support

Challenge: Support production SQL Server, development SQLite, and legacy Oracle/Matisse databases.

Solution: Abstract data access layer with pluggable providers.

Technical Details:

  • ITorqIrisObjectContext abstraction
  • Entity Framework Core for SQL Server/SQLite
  • Custom Matisse mapping for legacy
  • Migration support for schema evolution

Configuration:

{
  "ConnectionStrings": {
    "SqlServer": "Server=prod-sql;Database=Iris",
    "Sqlite": "Data Source=iris.db"
  },
  "Iris": {
    "Matisse": {
      "Server": "ins-irs-001",
      "Database": "Insight"
    }
  }
}

Business Value:

  • Development against lightweight SQLite
  • Production on enterprise SQL Server
  • Gradual migration from legacy systems
  • Testing flexibility

8. Comprehensive Document Generation

Challenge: Generate professional documents (letters, reports, invoices) in multiple formats.

Solution: Syncfusion DocIO and XlsIO integration.

Capabilities:

  • Word document generation and manipulation
  • Excel spreadsheet creation
  • PDF conversion
  • Mail merge with domain data
  • Chart and graph generation

Technical Integration:

  • Torq.Reports.DocIO library
  • Template-based generation
  • Dynamic data binding
  • Multi-format export (DOCX, PDF, XLSX)

Business Value:

  • Automated document workflows
  • Consistent branding and formatting
  • Reduced manual document creation
  • Professional client communications

9. Branch-Based Deployment Strategy

Challenge: Support multiple environments with different deployment needs.

Solution: Intelligent branch-based deployment in Azure Pipelines.

From azure-pipelines.yml:49:

variables:
  ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/production') }}:
    webTarget: 'IrisBlazor-Production'
    win64Target: 'IrisWindows-Production.INS-RDS-01'
    branchTitle: 'Production'

  ${{ elseif eq(variables['Build.SourceBranch'], 'refs/heads/staging') }}:
    webTarget: 'IrisBlazor-Staging'
    branchTitle: 'Staging'

  ${{ elseif eq(variables['Build.SourceBranch'], 'refs/heads/test') }}:
    webTarget: 'Iris-Test.INS-TST-01'
    branchTitle: 'Test'

Workflow:

  1. Developer merges to staging branch
  2. Pipeline automatically deploys to staging servers
  3. After testing, merge to production branch
  4. Pipeline automatically deploys to production servers

Benefits:

  • No manual deployment steps
  • Consistent deployment process
  • Environment-specific configuration
  • Fast, reliable deployments

10. Reactive Blazor Components

Challenge: Build responsive, reactive web UI without JavaScript frameworks.

Solution: Blazor Server with Phork.Blazor.Reactivity.

Technical Details:

  • Server-side rendering with SignalR
  • Reactive state management
  • Component lifecycle management
  • Real-time updates without page refresh

Integration:

public class JobDashboard : ComponentBase
{
    [Inject] private IReactiveState<JobStats> JobStatsState { get; set; }

    protected override void OnInitialized()
    {
        // Automatically re-renders when state changes
        JobStatsState.Subscribe(StateHasChanged);
    }
}

Business Value:

  • Modern web experience
  • No separate JavaScript codebase
  • Real-time collaboration features
  • Reduced development complexity

Conclusion

Iris represents a sophisticated, enterprise-grade debt collection management system built with modern software engineering practices. Its layered architecture, rich domain model, and comprehensive test coverage demonstrate professional software craftsmanship.

Key Strengths

Technical Excellence:

  • Clean architecture with clear separation of concerns
  • Domain-driven design with 316+ business entities
  • Type-safe build system and code generation
  • Comprehensive test coverage

Business Value:

  • Multi-platform support from unified codebase
  • Automated CI/CD for rapid deployment
  • Regulatory compliance with audit trails
  • Extensible framework for future products

Development Quality:

  • SOLID principles throughout
  • Design patterns applied appropriately
  • Extensive documentation (DocFx)
  • Modern development practices

Technologies Demonstrated

  • .NET 7.0 with C# 11.0
  • Blazor Server for modern web UI
  • Entity Framework Core for data access
  • Autofac for dependency injection
  • NUKE Build for type-safe builds
  • Azure Pipelines for CI/CD
  • Docker for containerization
  • NUnit for comprehensive testing

Architecture Highlights

  • Layered Architecture with framework abstraction
  • Domain-Driven Design with rich domain model
  • Dependency Injection throughout
  • Repository/Unit of Work patterns
  • Attribute-Based Authorization
  • Multi-Database Support
  • OpenAPI Code Generation
  • Comprehensive Audit Trails

Contact & Further Information

This documentation showcases the Iris system as an example of professional software development capabilities, demonstrating expertise in:

  • Enterprise application architecture
  • Domain-driven design
  • Modern .NET development
  • CI/CD automation
  • Multi-platform development
  • External system integration
  • Financial system compliance