Domain configuration
Entities
Time Validation

Time Validation

Time validation allows you to define constraints for entities that have time-based attributes like from and to dates. This is useful for scenarios like contracts, subscriptions, bookings, or any entity where time periods should not overlap and optionally must be consecutive.

Configuration

timeValidation?: {
  from: string;           // path to the start date attribute
  to: string;             // path to the end date attribute
  scope?: string | string[]; // attributes that define the scope for validation
  consecutive?: boolean;  // if true, periods must be consecutive without gaps
}
OptionTypeDefaultDescription
fromstringName of the attribute containing the start date/time
tostringName of the attribute containing the end date/time
scopestring | string[]undefinedFields (attribute or foreignKey) that define the scope within which validation applies; if undefined or [] the scope is all entity items
consecutivebooleanfalseIf true, time periods must be consecutive (no gaps allowed)

Validation Rules

The timeValidation configuration enforces the following rules:

1. From Before To

The from date must always be before the to date for the same entity item.

2. No Overlap

Time periods within the same scope must not overlap. This prevents conflicting entries like two contracts for the same customer being active at the same time.

3. Consecutive Periods (optional)

When consecutive: true is set, time periods must directly follow each other without gaps. The validation checks:

  • The new period's start must be consecutive to the previous period's end
  • The new period's end must be consecutive to the next period's start

For date-only values (no time component), "consecutive" means a difference of 1 day. For datetime values, it means a difference of 1 second.

Example

Basic Usage

entity:
  Contract:
    attributes:
      customerId: string!
      validFrom: date!
      validTo: date!
      description: string
    timeValidation:
      from: validFrom
      to: validTo
      scope: customerId

In this example:

  • Each contract has a validity period (validFrom to validTo)
  • Contracts for the same customer (scope: customerId) cannot overlap
  • Different customers can have overlapping contracts

With Consecutive Requirement

entity:
  Subscription:
    attributes:
      userId: string!
      planType: string!
      startDate: date!
      endDate: date!
    timeValidation:
      from: startDate
      to: endDate
      scope:
        - userId
        - planType
      consecutive: true

In this example:

  • Subscriptions for the same user and plan type cannot overlap
  • Subscription periods must be consecutive (no gaps allowed)
  • A new subscription must start exactly one day after the previous one ends

TypeScript Configuration

export const domainConfiguration: DomainConfiguration = {
  entity: {
    Booking: {
      attributes: {
        roomId: 'string!',
        checkIn: 'date!',
        checkOut: 'date!',
        guestName: 'string!'
      },
      timeValidation: {
        from: 'checkIn',
        to: 'checkOut',
        scope: 'roomId'
      }
    }
  }
}

Validation Messages

When validation fails, the following messages are returned:

ViolationMessagePath
From date is not before to date{from} must be before {to}from attribute
Time period overlaps with existingNo overlap allowedAffected attribute (from or to)
Gap before next periodMust be consecutive to next startto attribute
Gap after previous periodMust be consecutive to previous endfrom attribute

GraphQL Response Example

Request

mutation {
  createContract(
    contract: {
      customerId: "123"
      validFrom: "2024-01-01"
      validTo: "2024-06-30"
    }
  ) {
    contract { id validFrom validTo }
    validationViolations { path message }
  }
}

Response with validation error (overlap)

{
  "data": {
    "createContract": {
      "contract": null,
      "validationViolations": [
        {
          "path": "validFrom",
          "message": "No overlap allowed"
        }
      ]
    }
  }
}

Response with validation error (from after to)

{
  "data": {
    "createContract": {
      "contract": null,
      "validationViolations": [
        {
          "path": "validFrom",
          "message": "validFrom must be before validTo"
        }
      ]
    }
  }
}

Use Cases

Employment Contracts

Ensure an employee doesn't have overlapping employment periods:

timeValidation:
  from: startDate
  to: endDate
  scope: employeeId

Room Bookings

Prevent double-booking of rooms:

timeValidation:
  from: checkIn
  to: checkOut
  scope: roomId

Insurance Policies

Ensure consecutive coverage without gaps:

timeValidation:
  from: effectiveFrom
  to: effectiveTo
  scope: policyHolderId
  consecutive: true

Rental Agreements

Track rental periods per item:

timeValidation:
  from: rentalStart
  to: rentalEnd
  scope:
    - itemId
    - locationId