Developer Documentation

Interface Layer

The Interface Layer is how the outside world talks to your data — the gatekeeper between users, external systems, and the database. Every update is validated, transformed and committed in a controlled and predictable way before anything reaches the database.

Overview

The JU (Journal Update) system is a data access layer that manages object updates while maintaining database consistency and integrity. It acts as an API between users and the database, ensuring all data requirements are met before persistence.

Every update to a real class in the Torro system flows through its corresponding JU class. The JU is the sole mechanism for making changes — it validates, transforms, and commits data in a controlled and predictable way.

Core Concept

For each domain class — for example Customer — a parallel JU class is created: JUCustomer. The JU class manages all updates to the original object.

Critically, the JU contains only the properties that users or external systems are permitted to modify. System-managed fields — inferences, function-calculated values, derived values, collections — are deliberately excluded. This makes the JU a self-documenting contract: if a property isn't on the JU, it isn't settable from outside.

// Real class — full object with all properties
SaleOrder_Line {
  snSaleOrder // parent reference (auto-resolved)
  rnItem // required reference to Item
  aQuantity // required attribute
  iSellPrice // inferred from Item (NOT on JU)
  eSellPrice // editable override of inference
  iCostPrice // inferred, not editable (NOT on JU)
  fTotal // calculated by system (NOT on JU)
}

// JU — only what can be set externally
JUSaleOrder_Line {
  snSaleOrder // parent — must be provided, but see if you can find it yourself
  rnItem // required — must be provided
  aQuantity // required — must be provided
  eSellPrice // optional override
}

Interface Layer Processing Lifecycle

Every JU operation follows a consistent four-phase lifecycle. Understanding this sequence is essential for working effectively with the system.

Phase 01

Initialisation

New objects: Initialise an empty JU with default values applied where defined.

Existing objects: Copy all settable properties from the persistent object into the JU, ready for modification.

Phase 02

Validation

The validate() method ensures data completeness and consistency. Business rules are applied, required fields checked, and cross-object validations executed. Objects created here are JU specifications only — they don't yet physically exist.

Phase 03

Persistence

Three methods handle the write to the database: setAttributes() for simple properties, setReferences() for object references, and setCollections() for collection references (used sparingly by design).

Phase 04

Post-Processing

Executes within the transaction boundary. At this point, all created objects physically exist and can be referenced. Preferred for complex multi-object creation. All changes can be rolled back if any issue occurs.

Key Features

Virtual Properties

Properties prefixed with v facilitate data transformation between external representations and internal objects.

v
vAccountCode

Stores a human-readable string code that validate() converts to an object reference. Users interact with codes; the system resolves them to objects.

v
vAction

Acts as a processing flag to control workflow behaviour during the JU lifecycle — for example, to trigger different post-processing paths based on user intent.

Initialise From Pattern

A powerful mapping capability that allows one object type to be transformed into another. For example, initializeFromSupplier() on JUCustomer maps supplier properties to their customer equivalents.

This pattern is used extensively for object conversions — Delivery to Invoice, Physical Transaction to GL Transaction — and for integrating with external systems that use different property naming conventions.

Collection Management Philosophy

Collections are managed from the child side. The child object declares its parent, and the system automatically maintains the parent's collection. Direct manipulation of collections from the parent side is used only when strictly necessary, keeping the design clean and referential integrity intact.

Transaction Management

The choice between validation and post-processing involves meaningful trade-offs. Understanding when to use each is key to building robust JU implementations.

Validation Phase
  • Advantages: System knows all required locks upfront, preventing lock contention. Clean and straightforward for simple object creation.
  • Limitations: Created objects don't physically exist yet. Complex multi-object relationships become difficult to manage. Forward references require workarounds.
Post-Processing Phase
  • Advantages: Objects physically exist and can be referenced immediately. Simpler handling of multi-object relationships. Newly created objects can reference each other.
  • Limitations: No advance lock acquisition. Potential for lock contention in high-concurrency scenarios.

Best Practices

Use validation for simple scenarios

Single object creation or updates where all referenced objects already exist.

Use post-processing for complex creation

When creating four or more objects that need to reference each other, post-processing is significantly simpler to reason about.

Validation Timing & Concurrency

A common pitfall in form-based systems is step-time validation — validating user input at the moment it's entered rather than at the moment it's committed. The JU system solves this.

The Race Condition Problem

User A validates that invoice number 1000 is available. User A gets distracted before saving. User B validates and saves invoice number 1000. User A returns and saves — creating a duplicate. Step-time validation cannot prevent this.

JU-level validation occurs at persistence time, within the transaction. The uniqueness check happens at the moment of commit, not the moment of entry. Database integrity is guaranteed regardless of what happened in the UI layer or how long the user took.

Integration Capabilities

The JU system serves as a natural API layer for external integrations. Because the JU exposes only what can be legitimately set — with all the validation and business rules built in — external systems interact with the same gatekeeper as internal users.

Standardised interface

Every external system uses the same JU interface regardless of how it connects. The rules are consistent and centrally maintained.

Property mapping

Virtual properties and the initialise-from pattern allow external naming conventions to be mapped cleanly to internal representations without polluting the domain model.

Example: Xero integration

Internal customer properties are mapped to Xero's format via the JU layer. The core domain model remains clean while the integration handles the translation.

Design Benefits

Benefit 01

Separation of Concerns

UI interaction is completely separate from data validation and persistence. The UI can evolve independently of the business rules.

Benefit 02

Database Integrity

Comprehensive validation occurs before any data is persisted. Bad data cannot reach the database because the JU won't let it through.

Benefit 03

Security by Design

Users and external systems cannot modify system-controlled properties. If it's not on the JU, it cannot be set — no exceptions.

Benefit 04

Integration Ready

The JU is the natural API layer. Any external system integrates through the same interface with the same rules as the UI.

Areas for Improvement

Torro is a living system. The following areas have been identified for future development.

01
Consolidate Update Methods

Merge setAttributes(), setReferences(), and setCollections() into a single unified interface.

02
Enhance Multi-Object Creation

Improve the validate() method's handling of complex multi-object relationship scenarios.

03
Documentation

Formalise patterns and create comprehensive developer guidelines beyond what exists today.

04
Error Handling

Standardise error reporting across all validation phases for a more consistent developer experience.

05
Performance

Optimise lock acquisition strategies for complex scenarios involving many concurrent users.