Source code documentation

Contracts

1. Introduction

The contracts describe the terms (ACTUS contract terms) of the contract agreed upon between counterparties as one part, and the payment details (payment gateways) of each of the counterparties involved in the contractual agreement.

The contracts endpoints allows adding new and managing existing contracts. The contract is described in terms of one or multiple ACTUS contract templates. For each attribute of a template is according to the ACTUS data dictionary

2. Tables and relations

Establishing relationships

  • In relational databases like PostgreSQL, relationships between tables are crucial for organizing and querying data effectively. These relationships are typically established using foreign key constraints, which define links between tables based on the values of specific columns. Common types of relationships include one-to-one, one-to-many, and many-to-many relationships, each serving different data modeling needs.

contracts ERD
Figure 1. Contracts Entity-relationship diagram

Tables

  • Schema

    1. Table business_events

      Index Name Data type

      * 🔑 ⬋

      eventid

      uuid

      *

      event_time

      timestamp

      * 🔎

      event_type

      varchar(10)

      event_body

      json

      * 🔎

      status

      varchar(10)

      * 🔎

      execution_type

      varchar(20)

      contractid

      varchar(255)

      *

      userid

      uuid

      * 🔎 ⬈

      contractuuid

      uuid

      value

      numeric

      remaining_value

      numeric

      credit_payment_channel_id

      uuid

      debit_payment_channel_id

      uuid

      units

      varchar(10)

      1. Foreign keys

        Type Name On

        fk_business_events_contracts_contractuuid

        contractuuid

      2. Constraints

        Name Definition

        business_events_event_type_check

        ((event_type)::text ~* ’^(AD/IED/FP/PR/PD/PRF/PY/PP/IP/IPCI/CE/RRF/RR/DV/PRD/MR/TD/SC/IPCB/MD/XD/STD/PI/IPFX/IPFL/ME/TP/OPS)$'::text)

        business_events_status_check

        ((status)::text ~* ’^(scheduled

        pending

        processed)$'::text)

    2. Table contracts

      Index Name Data type

      * 🔑 ⬋

      contractuuid

      uuid

      productid

      bigint

      *

      createdby

      uuid

      executedby

      uuid

      *

      system_time

      timestamp

      selection

      json

      1. Foreign keys

        Type Name On

        contracts_product_fk

        productid

    3. Table contracts_history

      Index Name Data type

      * 🔑 ⬋

      contractuuid

      uuid

      * 🔑 ⬋

      status_date

      timestamp

      productid

      bigint

      selection

      json

      *

      system_time

      timestamp

    4. Table payment_channels

      Index Name Data type

      * 🔑 ⬋

      payment_channelid

      uuid

      contractid

      uuid

      details

      json

      *

      identifier

      varchar(100)

      label

      varchar(100)

      *

      type

      varchar(50)

      * 🔎

      owner_type

      varchar(10)

      *

      units

      varchar(10)

      *

      system

      varchar(50)

      account_characteristic

      varchar(50)

      * 🔎

      ownerid

      uuid

      * 🔎

      userid

      uuid

      1. Constraints

        Name Definition

        payment_channels_owner_type_check

        ((owner_type)::text ~* ’^(root/profile)$'::text)

    5. Table payment_details

      Index Name Data type

      * 🔑

      id

      bigint GENERATED BY DEFAULT AS IDENTITY

      contract_uuid

      uuid

      record_creator_paymentchannel_id

      uuid

      counterparty_paymentchannel_id

      uuid

      contract_paymentchannel_id

      uuid

      1. Foreign keys

        Type Name On

        paymentdetails_contractuuid_fk

        contract_uuid

        paymentdetails_contract_payment_fk

        contract_paymentchannel_id

        paymentdetails_counterparty_fk

        counterparty_paymentchannel_id

        paymentdetails_record_creator_fk

        record_creator_paymentchannel_id

    6. Table products

      Idx Name Data Type

      * 🔑 ⬋

      productid

      bigint GENERATED BY DEFAULT AS IDENTITY

      *

      status

      varchar(10)

      *

      template

      json

      * 🔎

      userid

      uuid

      1. Constraints

        Name Definition

        products_status_check

        ((status)::text ~* ’^(active/inactive)$'::text)

    7. Table profile_forms

      Idx Name Data Type

      * 🔑 ⬋

      profile_formid

      bigint GENERATED BY DEFAULT AS IDENTITY

      *

      profile_form_details

      json

      *

      userid

      uuid

    8. Table profiles

      Index Name Data type

      * 🔑 ⬋

      profileid

      uuid

      profile_details

      json

      *

      status

      varchar(10)

      *

      userid

      uuid

      * ⬈

      profile_formid

      bigint

      1. Foreign keys

        Type Name On

        fk_profiles_profile_forms_profile_formid

        profile_formid

      2. Constraints

        Name Definition

        profiles_status_check

        ((status)::text ~* ’^(active/inactive)$'::text)

    9. Table terms

      Index Name Data type

      * 🔑

      id

      integer GENERATED BY DEFAULT AS IDENTITY

      accrued_interest

      numeric

      amortization_date

      timestamp

      array_cycle_anchor_date_of_interest_payment

      varchar(255)

      array_cycle_anchor_date_of_principal_redemption

      varchar(255)

      array_cycle_anchor_date_of_rate_reset

      varchar(255)

      array_cycle_of_interest_payment

      varchar(255)

      array_cycle_of_principal_redemption

      varchar(255)

      array_cycle_of_rate_reset

      varchar(255)

      array_fixed_variable

      varchar(255)

      array_increase_decrease

      varchar(255)

      array_next_principal_redemption_payment

      varchar(255)

      array_rate

      varchar(255)

      business_day_convention

      varchar(5)

      calendar

      varchar(2)

      capitalization_end_date

      timestamp

      contract_deal_date

      timestamp

      contractid

      varchar(255)

      *

      contract_role

      varchar(6)

      contract_performance

      varchar(10)

      *

      contract_type

      varchar(15)

      *

      currency

      varchar(10)

      currency2

      varchar(10)

      cycle_anchor_date_of_dividend_payment

      timestamp

      cycle_anchor_date_of_fee

      timestamp

      cycle_anchor_date_of_interest_calculation_base

      timestamp

      cycle_anchor_date_of_interest_payment

      timestamp

      cycle_anchor_date_of_optionality

      timestamp

      cycle_anchor_date_of_principal_redemption

      timestamp

      cycle_anchor_date_of_rate_reset

      timestamp

      cycle_anchor_date_of_scaling_index

      timestamp

      cycle_of_dividend_payment

      varchar(10)

      cycle_of_fee

      varchar(10)

      cycle_of_interest_calculation_base

      varchar(10)

      cycle_of_interest_payment

      varchar(10)

      cycle_of_optionality

      varchar(10)

      cycle_of_principal_redemption

      varchar(10)

      cycle_of_rate_reset

      varchar(10)

      cycle_of_scaling_index

      varchar(10)

      cycle_point_of_interest_payment

      varchar(1)

      cycle_point_of_rate_reset

      varchar(1)

      *

      day_count_convention

      varchar(10)

      delivery_settlement

      varchar(1)

      end_of_month_convention

      varchar(5)

      fee_accrued

      numeric

      fee_basis

      varchar(1)

      fee_rate

      numeric

      fixing_period

      varchar(255)

      initial_exchange_date

      timestamp

      interest_calculation_base

      varchar(10)

      interest_calculation_base_amount

      numeric

      life_cap

      numeric

      life_floor

      numeric

      market_object_code

      varchar(255)

      market_object_code_of_dividend_rate

      varchar(255)

      market_object_code_of_rate_reset

      varchar(255)

      market_object_code_of_scaling_index

      varchar(255)

      market_value_observed

      numeric

      maturity_date

      timestamp

      maximum_penalty_free_disbursement

      varchar(255)

      next_principal_redemption_payment

      numeric

      next_reset_rate

      numeric

      nominal_interest_rate

      numeric

      nominal_interest_rate2

      numeric

      notional_principal

      numeric

      notional_principal2

      numeric

      object_code_of_prepayment_model

      varchar(255)

      penalty_rate

      numeric

      penalty_type

      varchar(1)

      period_cap

      numeric

      period_floor

      numeric

      premium_discount_atied

      numeric

      price_at_purchase_date

      numeric

      price_at_termination_date

      numeric

      purchase_date

      timestamp

      quantity

      numeric

      rate_spread

      numeric

      rounding_convention

      varchar(255)

      scaling_effect

      varchar(5)

      scaling_index_at_contract_deal_date

      numeric

      settlement_period

      varchar(255)

      status_date

      timestamp

      x_day_notice

      varchar(255)

      termination_date

      timestamp

      delinquency_period

      varchar(255)

      grace_period

      varchar(255)

      market_object_code_of_dividends

      varchar(255)

      rate_multiplier

      numeric

      * ⬈

      contract_uuid

      uuid

      counterparty_id

      uuid

      * 🔎

      creator_id

      uuid

      1. Foreign keys

        Type Name On

        terms_contractuuid_fk

        contract_uuid

        terms_counterparty_id_fk

        counterparty_id

      2. Constraints

        Name Definition

        terms_business_day_convention_check

        ((business_day_convention)::text ~* ’^(NOS/SCF/SCMF/CSF/CSMF/SCP/SCMP/CSP/SCMP)$'::text)

        terms_calendar_check

        ((calendar)::text ~* ’^(NC/MF)$'::text)

        terms_fee_basis_check

        ((fee_basis)::text ~* ’^(A/N)$'::text)

        terms_delivery_settlement_check

        ((delivery_settlement)::text ~* ’^(D/S)$'::text)

        terms_cycle_of_dividend_payment_check

        cycle_of_dividend_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_interest_calculation_base_check

        cycle_of_interest_calculation_base)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_interest_payment_check

        cycle_of_interest_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_principal_redemption_check

        cycle_of_principal_redemption)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_rate_reset_check

        cycle_of_rate_reset)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_scaling_index_check

        cycle_of_scaling_index)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_point_of_interest_payment_check

        ((cycle_point_of_interest_payment)::text ~* ’^(B/E)$'::text)

        terms_contract_performance_check

        ((contract_performance)::text ~* ’^(PF/DL/DQ/DF/MA/TE/PreDeal)$'::text)

        terms_penalty_type_check

        ((penalty_type)::text ~* ’^(N/A/R/I)$'::text)

    10. Table terms_history

      Index Name Data type

      * 🔑

      terms_history_id

      bigint GENERATED BY DEFAULT AS IDENTITY

      accrued_interest

      numeric

      amortization_date

      timestamp

      array_cycle_anchor_date_of_interest_payment

      varchar(255)

      array_cycle_anchor_date_of_principal_redemption

      varchar(255)

      array_cycle_anchor_date_of_rate_reset

      varchar(255)

      array_cycle_of_interest_payment

      varchar(255)

      array_cycle_of_principal_redemption

      varchar(255)

      array_cycle_of_rate_reset

      varchar(255)

      array_fixed_variable

      varchar(255)

      array_increase_decrease

      varchar(255)

      array_next_principal_redemption_payment

      varchar(255)

      array_rate

      varchar(255)

      business_day_convention

      varchar(5)

      calendar

      varchar(2)

      capitalization_end_date

      timestamp

      contract_deal_date

      timestamp

      contractid

      varchar(255)

      *

      contract_role

      varchar(6)

      contract_performance

      varchar(10)

      *

      contract_type

      varchar(15)

      *

      currency

      varchar(10)

      currency2

      varchar(10)

      cycle_anchor_date_of_dividend_payment

      timestamp

      cycle_anchor_date_of_fee

      timestamp

      cycle_anchor_date_of_interest_calculation_base

      timestamp

      cycle_anchor_date_of_interest_payment

      timestamp

      cycle_anchor_date_of_optionality

      timestamp

      cycle_anchor_date_of_principal_redemption

      timestamp

      cycle_anchor_date_of_rate_reset

      timestamp

      cycle_anchor_date_of_scaling_index

      timestamp

      cycle_of_dividend_payment

      varchar(10)

      cycle_of_fee

      varchar(10)

      cycle_of_interest_calculation_base

      varchar(10)

      cycle_of_interest_payment

      varchar(10)

      cycle_of_optionality

      varchar(10)

      cycle_of_principal_redemption

      varchar(10)

      cycle_of_rate_reset

      varchar(10)

      cycle_of_scaling_index

      varchar(10)

      cycle_point_of_interest_payment

      varchar(1)

      cycle_point_of_rate_reset

      varchar(1)

      *

      day_count_convention

      varchar(10)

      delivery_settlement

      varchar(1)

      end_of_month_convention

      varchar(5)

      fee_accrued

      numeric

      fee_basis

      varchar(1)

      fee_rate

      numeric

      fixing_period

      varchar(255)

      initial_exchange_date

      timestamp

      interest_calculation_base

      varchar(10)

      interest_calculation_base_amount

      numeric

      life_cap

      numeric

      life_floor

      numeric

      market_object_code

      varchar(255)

      market_object_code_of_dividend_rate

      varchar(255)

      market_object_code_of_rate_reset

      varchar(255)

      market_object_code_of_scaling_index

      varchar(255)

      market_value_observed

      numeric

      maturity_date

      timestamp

      maximum_penalty_free_disbursement

      varchar(255)

      next_principal_redemption_payment

      numeric

      next_reset_rate

      numeric

      nominal_interest_rate

      numeric

      nominal_interest_rate2

      numeric

      notional_principal

      numeric

      notional_principal2

      numeric

      object_code_of_prepayment_model

      varchar(255)

      penalty_rate

      numeric

      penalty_type

      varchar(1)

      period_cap

      numeric

      period_floor

      numeric

      premium_discount_atied

      numeric

      price_at_purchase_date

      numeric

      price_at_termination_date

      numeric

      purchase_date

      timestamp

      quantity

      numeric

      rate_spread

      numeric

      rounding_convention

      varchar(255)

      scaling_effect

      varchar(5)

      scaling_index_at_contract_deal_date

      numeric

      settlement_period

      varchar(255)

      x_day_notice

      varchar(255)

      termination_date

      timestamp

      delinquency_period

      varchar(255)

      grace_period

      varchar(255)

      market_object_code_of_dividends

      varchar(255)

      rate_multiplier

      numeric

      *

      creator_id

      uuid

      contractuuid

      uuid

      status_date

      timestamp

      1. Foreign keys

        Type Name On

        fk-contracts_history-terms_history

        contractuuid, status_date

      2. Constraints

    Name Definition

    terms_history_business_day_convention_check

    ((business_day_convention)::text ~* ’^(NOS/SCF/SCMF/CSF/CSMF/SCP/SCMP/CSP/SCMP)$'::text)

    terms_history_calendar_check

    ((calendar)::text ~* ’^(NC/MF)$'::text)

    terms_history_fee_basis_check

    ((fee_basis)::text ~* ’^(A/N)$'::text)

    terms_history_delivery_settlement_check

    ((delivery_settlement)::text ~* ’^(D/S)$'::text)

    terms_history_cycle_of_dividend_payment_check

    cycle_of_dividend_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

    terms_history_cycle_of_interest_calculation_base_check

    cycle_of_interest_calculation_base)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

    terms_history_cycle_of_interest_payment_check

    cycle_of_interest_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

    terms_history_cycle_of_principal_redemption_check

    cycle_of_principal_redemption)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

    terms_history_cycle_of_rate_reset_check

    cycle_of_rate_reset)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

    terms_history_cycle_of_scaling_index_check

    cycle_of_scaling_index)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

    terms_history_cycle_point_of_interest_payment_check

    ((cycle_point_of_interest_payment)::text ~* ’^(B/E)$'::text)

    terms_history_contract_performance_check

    ((contract_performance)::text ~* ’^(PF/DL/DQ/DF/MA/TE/PreDeal)$'::text)

    terms_history_penalty_type_check

    ((penalty_type)::text ~* ’^(N/A/R/I)$'::text)

    terms_history_scaling_effect_check

    ((scaling\_effect)::text ~* '^(OOO/IOO/ONO/INO)$'::text)

(🔑) - Primary key

(*) - Mandatory

(⬈) - Foreign key

(🔎) - Constraint

3. Dependencies and libraries

3.1. Dependencies

Description

The following dependencies are used in the project to provide various functionalities and features:

  1. spring-kafka

    • Purpose: Spring for Apache Kafka for building Kafka-based messaging systems.

    • Usage: Producing and consuming messages from Kafka topics.

  2. spring-cloud-starter-openfeign

    • Purpose: The spring-cloud-starter-openfeign dependency is used in Spring Boot applications to simplify the process of creating REST clients. It integrates the Feign client library into your application, providing a declarative way to define RESTful service clients.

    • Usage: Use spring-cloud-starter-openfeign to define interfaces for RESTful services and easily make HTTP requests to those services. Feign handles the creation of the HTTP request and mapping of the response to Java objects, reducing the boilerplate code typically required for REST client implementations.

  3. spring-cloud-starter-loadbalancer

    • Purpose: The spring-cloud-starter-loadbalancer dependency is used in Spring Boot applications to provide client-side load balancing. It integrates with Spring Cloud’s load balancing features, allowing applications to distribute traffic across multiple instances of a service.

    • Usage: Use spring-cloud-starter-loadbalancer to enable client-side load balancing in your application. It provides a simple API for making requests to services registered with a service registry (e.g., Eureka), automatically handling the load balancing logic. This helps improve the availability and scalability of your application by distributing traffic evenly across service instances.

  4. modelmapper (version 0.7.5)

    • Purpose: The modelmapper dependency simplifies the process of mapping objects between different data models by automatically determining how properties should be mapped from one object to another.

    • Usage: Use modelmapper to streamline the mapping process between DTOs (Data Transfer Objects), entities, and other data models, reducing the need for manual mapping code and improving code maintainability.

  • Dependency versions are specified to ensure compatibility and stability.

  • Additional dependencies may be added or removed based on project requirements and architecture.

3.2. Libraries

Description

The following libraries are used in the project to provide various functionalities and features:

  1. actus-core (version 1.0.1)

    • Purpose: The actus-core library provides core functionality and utilities for working with financial contracts and cash flow projections based on the ACTUS standard.

    • Usage: Use to perform calculations, projections, and analysis of financial contracts and cash flows according to the ACTUS (Algorithmic Contract Types Unified Standards) standard.

  2. ariadne-contracts (version 0.0.2)

    • Purpose: The ariadne-contracts library offers functionality and utilities for working with contract data and management within financial applications.

    • Usage: Use ariadne-contracts to handle contract data, perform contract management tasks, and integrate contract-related functionalities into financial applications.

  • Library versions are specified to ensure compatibility and stability.

  • Additional libraries may be added or removed based on project requirements and architecture.

4. Exception handling

Description

The RestExceptionHandler class is responsible for handling various exceptions that may occur during the execution of RESTful API endpoints. It provides centralized exception handling to ensure consistent error responses across the application.

Exception handlers

Example usage

@ControllerAdvice
public class RestExceptionHandler {

	@ExceptionHandler({ContractsException.class, IllegalArgumentException.class}) (1)
	public ResponseEntity<ResponseDto> exceptionToDoHandler(Exception ex) {
		final ResponseDto error = new ResponseDto();
		error.setStatus(HttpStatus.BAD_REQUEST.value());
		error.setMessage(ex.getMessage());
		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

	@ExceptionHandler(value = { AccessDeniedException.class }) (2)
	public ResponseEntity<ResponseDto> exceptionHandler(Exception ex) {
		final ResponseDto error = new ResponseDto();
		error.setStatus(HttpStatus.UNAUTHORIZED.value());
		error.setMessage("Access Denied...");
		return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
	}

	@ExceptionHandler(value = { Exception.class, }) (3)
	public ResponseEntity<ResponseDto> exceptionHandlerr(Exception ex) {

		final ResponseDto error = new ResponseDto();
		error.setStatus(HttpStatus.BAD_REQUEST.value());
		error.setMessage("The request could not be understood by the server due to malformed syntax.");
		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

}
1 ContractsException and IllegalArgumentException handler
  • Handles exceptions of type ContractsException and IllegalArgumentException.

  • Returns a ResponseEntity with a status code of 400 Bad Request and an error message derived from the exception’s message.

2 AccessDeniedException handler
  • Handles exceptions of type AccessDeniedException, typically thrown when a user lacks the necessary permissions to access a resource.

  • Returns a ResponseEntity with a status code of 401 Unauthorized and a generic "Access Denied" message.

3 Generic exception handler
  • Handles any other uncaught exceptions that may occur during the execution of API endpoints.

  • Returns a ResponseEntity with a status code of 400 Bad Request and a generic error message indicating malformed syntax.

Customization

  • Additional exception handlers can be added to address specific use cases or domain-specific exceptions.

  • Error messages and status codes can be customized based on application requirements and error scenarios.

6. ContractsServiceController

6.1. Create contract

6.1.1. Sequential flow

create-contract.puml

Contract creation process

The below business process / method ‘createContract’ enables creation of a Loan account / Checking account. Here below are process steps -

  1. To fetch the product form (Product Template) with ProductID as specified in the contract object.

  2. Product template this is fetched is validated with request payload (Contract terms)

  3. Counterparty and PaymentDetails are validated.

The validation that are performed at this stage are

  1. If counterpartyIDs (Profile IDs) and Counterparty payment channel exists

  2. If creator ID (user ID) and creator payment channel ID exist

  3. If contract terms are compliant with ACTUS data dictionary

  4. If applicability rules of ACTUS are valid for the contract terms provided

After the necessary contract creation process steps and validations are completed, a new contracts with ContractStatus = “PreDeal” is created.

6.1.2. Endpoint

Description

This endpoint allows users with the appropriate permissions to create contracts based on the provided data.

URL

/contracts

Method

POST

Request body

The request body should contain a JSON array of objects, each representing data for creating a contract. The structure of each object should adhere to the CreateContractsDto format.

Example request body

[
  {
    "productID": 1,
    "terms": [
      {
        "contractPerformance": "PreDeal",
        "businessDayConvention": "SCF",
        "contractType": "ANN",
        "statusDate": "2023-07-31T06:30:00",
        "contractRole": "RPA",
        "creatorID": "a43c22ed-27df-4324-a453-3e7707c9b82d",
        "counterpartyID": "e548956c-1f3b-493e-952e-00cdcca6b599",
        "contractID": "a6b799db-c448-4aad-9382-3ae47383f5b2",
        "cycleAnchorDateOfInterestPayment": "2023-09-01T06:30:00",
        "cycleOfInterestPayment": "P1ML1",
        "nominalInterestRate": 0.02,
        "dayCountConvention": "30E360",
        "currency": "CHF",
        "contractDealDate": "2023-07-31T06:30:00",
        "initialExchangeDate": "2023-08-01T06:30:00",
        "maturityDate": "2024-08-01T06:30:00",
        "notionalPrincipal": 50000,
        "cycleAnchorDateOfPrincipalRedemption": "2023-09-01T06:30:00",
        "cycleOfPrincipalRedemption": "P1ML1",
        "nextPrincipalRedemptionPayment": 2312.7827499791606
      }
    ],
    "paymentDetails": {
      "recordCreatorPaymentChannelID": "e03c2694-71f8-48e0-a68d-8328630fd0c5",
      "counterpartyPaymentChannelID": "6963c361-1c1f-40b6-b8b4-47f604be36ef"
    },
    "selection": {
      "productCategory": "Loans",
      "department": "DeptB",
      "profitCenter": "A",
      "tenure": "12M"
    }
  }
]

Responses

  • 201 CREATED: Success. Returns a JSON response containing details of the created contracts.

Example response body

{
  "status": 201,
  "message": "Success",
  "data": [
    {
      "productID": 1,
      "terms": [
        {
          "contractPerformance": "PreDeal",
          "businessDayConvention": "SCF",
          "contractType": "ANN",
          "statusDate": "2023-07-31T06:30:00",
          "contractRole": "RPA",
          "creatorID": "a43c22ed-27df-4324-a453-3e7707c9b82d",
          "counterpartyID": "e548956c-1f3b-493e-952e-00cdcca6b599",
          "contractID": "a6b799db-c448-4aad-9382-3ae47383f5b2",
          "cycleAnchorDateOfInterestPayment": "2023-09-01T06:30:00",
          "cycleOfInterestPayment": "P1ML1",
          "nominalInterestRate": 0.02,
          "dayCountConvention": "30E360",
          "currency": "CHF",
          "contractDealDate": "2023-07-31T06:30:00",
          "initialExchangeDate": "2023-08-01T06:30:00",
          "maturityDate": "2024-08-01T06:30:00",
          "notionalPrincipal": 50000,
          "cycleAnchorDateOfPrincipalRedemption": "2023-09-01T06:30:00",
          "cycleOfPrincipalRedemption": "P1ML1",
          "nextPrincipalRedemptionPayment": 2312.7827499791606
        }
      ],
      "paymentDetails": {
        "recordCreatorPaymentChannelID": "e03c2694-71f8-48e0-a68d-8328630fd0c5",
        "counterpartyPaymentChannelID": "6963c361-1c1f-40b6-b8b4-47f604be36ef"
      },
      "selection": {
        "productCategory": "Loans",
        "department": "DeptB",
        "profitCenter": "A",
        "tenure": "12M"
      }
    }
  ]
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions to create contracts.

  • 5xx server error: If there is a server-side error while processing the request.

Example

{
  "status": 400,
  "message": "Contract creation failed",
  "data": [
    {
      "contractUUID": null,
      "contractID": null,
      "errors": [
        {
          "Product data": "Specified result type [java.lang.String] did not match Query selection type [com.solitx.contracts.entity.Terms] - multiple selections: use Tuple or array"
        }
      ]
    }
  ]
}

6.1.3. Methods

Description

The method createContract is responsible for creating contracts based on the provided list of contract data. It iterates through each contract data object, validates it using a validator (createContractValidator), and then creates the contract if there are no validation errors. It returns a list of ContractsResponseDto objects containing the result of each contract creation attempt.

Parameters

  • contractDataList (List<CreateContractsDto>): A list of objects representing contract data to be used for creating contracts.

Returns

  • List<ContractsResponseDto>: A list of ContractsResponseDto objects containing the result of each contract creation attempt.

Example usage

public List<ContractsResponseDto> createContract(List<CreateContractsDto> contractDataList) {
		List<ContractsResponseDto> contractResponseDtoList = new ArrayList<>();
		ContractsResponseDto contractResponseDto;
		for (CreateContractsDto createContractDto : contractDataList) { (1)
			// Validate the contract data using the createContractValidator. (2)
			contractResponseDto = createContractValidator.validateContractData(createContractDto);
			if (contractResponseDto.getErrors().isEmpty()) {
				// If there are no validation errors, create the contract.
				contractResponseDto = contractsWorker.createContract(createContractDto); (3)
			}
			contractResponseDtoList.add(contractResponseDto); (4)
		}
		return contractResponseDtoList; (5)
	}
Internal workflow
1 Iterates through each CreateContractsDto object in the provided contractDataList.
2 Validates the contract data using the createContractValidator.
3 If there are no validation errors (errors list in the ContractsResponseDto is empty), the contract is created using the contractsWorker.
4 Adds the resulting ContractsResponseDto object to the contractResponseDtoList.
5 Returns the list of ContractsResponseDto objects containing the result of each contract creation attempt.

Exceptions

  • None explicitly thrown by this method. However, exceptions may occur within the validator or worker methods, which are handled internally.

6.1.4. Model classes

Description

The CreateContractsDto class represents the data transfer object (DTO) used for creating contracts in the system. It encapsulates the necessary information required to initialize and configure a contract, including product ID, contract terms, payment details, and selection criteria.

Attributes
  1. productId

    • Type: Long

    • Description:Identifier of the product associated with the contract.

    • Constraints: Required field.

    • Example: 1

  2. terms

    • Type: List<Map<String, Object>>

    • Description: Collection of contract terms represented as key-value pairs.

    • Constraints: Required field.

    • Example

    {
      "terms": [
        {
          "contractPerformance": "PreDeal",
          "businessDayConvention": "SCF",
          "contractType": "ANN",
          "statusDate": "2023-07-31T06:30:00",
          "contractRole": "RPA",
          "creatorID": "a43c22ed-27df-4324-a453-3e7707c9b82d",
          "counterpartyID": "e548956c-1f3b-493e-952e-00cdcca6b599",
          "contractID": "a6b799db-c448-4aad-9382-3ae47383f5b2",
          "cycleAnchorDateOfInterestPayment": "2023-09-01T06:30:00",
          "cycleOfInterestPayment": "P1ML1",
          "nominalInterestRate": 0.02,
          "dayCountConvention": "30E360",
          "currency": "CHF",
          "contractDealDate": "2023-07-31T06:30:00",
          "initialExchangeDate": "2023-08-01T06:30:00",
          "maturityDate": "2024-08-01T06:30:00",
          "notionalPrincipal": 50000,
          "cycleAnchorDateOfPrincipalRedemption": "2023-09-01T06:30:00",
          "cycleOfPrincipalRedemption": "P1ML1",
          "nextPrincipalRedemptionPayment": 2312.7827499791606
        }
      ]
    }
  3. paymentDetails

    • Type: Map<String, Object>

    • Description: Details of the payment associated with the contract.

    • Constraints: Required field.

    • Example

    {
      "paymentDetails": {
        "recordCreatorPaymentChannelID": "e03c2694-71f8-48e0-a68d-8328630fd0c5",
        "counterpartyPaymentChannelID": "6963c361-1c1f-40b6-b8b4-47f604be36ef"
      }
    }
  4. selection

    • Type: Map<String, Object>

    • Description: Additional selection criteria or parameters for the contract (optional).

    • Example

{
  "selection": {
    "productCategory": "Loans",
    "department": "DeptB",
    "profitCenter": "A",
    "tenure": "12M"
  }
}

Constructors

  • Default Constructor: Initializes an empty CreateContractsDto object.

  • All-args Constructor: Initializes a CreateContractsDto object with all attributes.

  • Getter and Setter Methods: Accessors and mutators for the attributes of the class.

Example usage

// Create a new instance of CreateContractsDto
CreateContractsDto contractDto = new CreateContractsDto();
contractDto.setProductId((long) 1);
contractDto.setTerms(termsList);
contractDto.setPaymentDetails(paymentDetailsMap);
contractDto.setSelection(selectionMap);

Serialization and deserialization

  • The CreateContractsDto class can be serialized to and deserialized from JSON format using libraries like Jackson, Gson, or JSON-B.

6.1.5. Validation

Description

The validateContractData method is responsible for validating contract data before the creation of contracts. It ensures that the provided contract data meets the necessary criteria and constraints, performing various checks on the product associated with the contract, the contract itself, and its terms. If any validation errors are encountered, they are collected and returned in a structured format.

Parameters

  • createContractDto (CreateContractsDto): An object representing the contract data to be validated.

Returns

  • ContractsResponseDto: An object containing the result of the validation process, including any encountered errors.

Example usage

public ContractsResponseDto validateContractData(CreateContractsDto createContractDto) {
		// Initialize data structures to store validation errors.
		HashMap<String, Object> createContractErrors = new HashMap<>();
		List<Map<String, Object>> errorList = new ArrayList<>();
		String contractID;

		try {
			// Validate the product associated with the contract.
			Products products = contractsValidator.validateProduct(createContractDto.getProductId()); (1)

			// Validate the contract and product template size.
			contractsValidator.validateContractAndProductTemplateSize(products, createContractDto.getTerms()); (2)

			// Extract contract terms and ID.
			Map<String, Object> contractTerms = createContractDto.getTerms().get(0);
			contractID = String.valueOf(contractTerms.get(Constants.CONTRACTID));

			// Perform selection validation and add any errors to the error list.
			Map<String, Object> selectionValidationErrors = this.contractSelectionValidation(products,
					createContractDto); (3)
			if (!selectionValidationErrors.isEmpty()) {
				errorList.add(selectionValidationErrors);
			}

			// Perform terms validation and add any errors to the error list.
			List<Map<String, Object>> termsValidationErrors = validateContractTerms(products, createContractDto); (4)
			errorList.addAll(termsValidationErrors);

		} catch (Exception e) { (5)
			// If an exception occurs during validation, add an error entry to the error
			// list.
			createContractErrors.put("Product data", e.getMessage());
			errorList.add(createContractErrors);
			return new ContractsResponseDto(null, null, errorList);
		}

		return new ContractsResponseDto(null, contractID, errorList);

	}
Validation steps
1 Product validation
  • Validates the product associated with the contract using the contractsValidator.validateProduct method.

2 Contract and product template size validation
  • Ensures that the contract and product template sizes meet the required criteria using the contractsValidator.validateContractAndProductTemplateSize method.

3 Contract selection validation
  • Performs selection validation by invoking the contractSelectionValidation method, which validates the contract’s selection against the product’s selection template.

4 Terms validation
  • Validates the contract terms using the validateContractTerms method, checking for any discrepancies or errors and also the required terms like counterPartyID, recordCreatorID and other formats.

5 Error handling
  • If any exception occurs during the validation process, an error entry is added to the error list, indicating the nature of the issue.

  • All encountered validation errors are collected and returned in a structured format within the ContractsResponseDto object.

6.1.6. Testing

Description

This section provides an overview of the testing strategy and objectives for the create contract method.

Test methods

Example usage

@SuppressWarnings("unchecked")
	@Test
	void evaluateContractTest() throws ParseException { (1)
		CreateContractsDto createContractsDto = createContractsDtoList.get(0);
		createContractValidator.validateContractData(createContractsDto);
		final List<Map<String, Object>> productTermsList = (List<Map<String, Object>>) product.getTemplate()
				.get(Constants.TERMS);
		List<Map<String, Object>> contractTermsList = createContractsDto.getTerms();
		Map<String, Object>   selectionMap =  createContractsDto.getSelection();
		contractsHelper.evaluateContractTerms(contractTermsList, productTermsList, selectionMap);
		contracts = contractsWorker.computeContract(product, createContractsDto);
		Terms masterTerms = contracts.getContractTerms().get(0);
		PaymentDetails paymentDetails = contracts.getPaymentDetails();

		Assertions.assertEquals(contracts.getProductID().toString(), product.getProductID().toString());
		Assertions.assertEquals(50000, masterTerms.getNotionalPrincipal().doubleValue(), 0.0);
		Assertions.assertEquals(2312.7827499791606, masterTerms.getNextPrincipalRedemptionPayment().doubleValue(), 0.01);
		Assertions.assertEquals(LocalDateTime.parse("2023-08-01T00:00:00"), masterTerms.getInitialExchangeDate());
		Assertions.assertEquals(LocalDateTime.parse("2023-07-31T00:00:00"), masterTerms.getStatusDate());
		Assertions.assertEquals(profile.getProfileID(), masterTerms.getCounterpartyID());
		Assertions.assertEquals(paymentDetails.getCounterpartyPaymentChannelID(), counterPartyPaymentChannel.getPaymentChannelID());
		Assertions.assertEquals(paymentDetails.getRecordCreatorPaymentChannelID(), recordCreatorPaymentChannel.getPaymentChannelID());

	}

	@Test
	void createContractTest() { (2)

		List<ContractsResponseDto> createContractList = contractServiceImpl.createContract(createContractsDtoList);
		System.out.println("createContractList :"+createContractList);
		String contractUUID = createContractList.get(0).getContractUUID();
		Assertions.assertEquals(contracts.getContractUUID(), UUID.fromString(contractUUID));

	}
1 evaluateContractTest
  • Purpose : This test evaluates the contract creation process by validating contract terms and computing contract details.

  • Test steps

    1. Validates the contract data using the createContractValidator.

    2. Retrieves product terms and contract terms for evaluation.

    3. Evaluates contract terms using the contractsHelper.

    4. Computes the contract details using the contractsWorker.

  • Assertions

    • Validates various properties of the computed contract, such as notional principal, next principal redemption payment, initial exchange date, status date, counterparty ID, creator ID, and payment channel IDs.

2 createContractTest
  • Purpose : This test verifies the functionality of the createContract method in the ContractService implementation.

  • Test steps

    1. Invokes the createContract method with a list of contract data objects.

    2. Retrieves the created contract list.

  • Assertions

    • Verifies that the contract creation process is successful by comparing the UUID of the created contract with the expected contract UUID.

Test environment

Coverage

  • Test coverage includes both positive and negative scenarios to ensure comprehensive validation of contract creation and evaluation processes.

  • Additional test cases may be added to cover edge cases, boundary conditions, and error handling scenarios.

6.2. Get computed schedule

6.2.1. Sequential flow

get-computed-schedule-contract.puml

Getting the computed contract schedule

  • User requests the computed schedule for a contract.

  • Controller validates the contract UUID.

  • If contract not found, return error.

  • If contract status is not "PreDeal", return error.

  • Retrieve contract from repository.

  • Use FactoryWorker to generate schedule based on contract and risk factor model.

  • Return the computed schedule or error message to the user.

6.2.2. Endpoint

Description

The endpoint computes and returns the schedule of a contract based on the provided contractUUID.

URL

/contracts/compute

Method

GET

Request parameters

Parameters

Type

Required

Description

contractUUID

UUID

Yes

The UUID of the existing contract for which the schedule needs to be computed.

Responses

  • 200 OK

    • Returns a list of business events comprising the schedule.

    • Response body

      {
        "status": 200,
        "message": "Success",
        "data": [
          {
            "eventID": "23a83225-007e-47f2-8dcd-21534a0b92f4",
            "eventTime": "2023-01-01T00:00:00",
            "eventType": "IED",
            "eventBody": {
              "transaction": {
                "nominalValue": 50000.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": -50000.0,
            "remainingValue": -50000.0,
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "debitPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "423ec885-8af4-4a19-8f1f-7d707fd5eefe",
            "eventTime": "2023-01-01T00:00:00",
            "eventType": "FP",
            "eventBody": {
              "transaction": {
                "nominalValue": 0.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 5000.0,
            "remainingValue": 5000.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "Loan processing fee",
            "units": "INR"
          },
          {
            "eventID": "adbca86d-95a9-4327-bddc-71c69af1a1dc",
            "eventTime": "2023-01-01T00:00:00",
            "eventType": "FP",
            "eventBody": {
              "transaction": {
                "nominalValue": 0.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 2500.0,
            "remainingValue": 2500.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "Insurance Fee",
            "units": "INR"
          },
          {
            "eventID": "433a60c6-2429-40d1-9783-2484c90ac987",
            "eventTime": "2023-02-01T00:00:00",
            "eventType": "IP",
            "eventBody": {
              "transaction": {
                "nominalValue": 45833.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 833.0,
            "remainingValue": 833.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "1b062381-3b44-404a-afb7-d6296ca95b9e",
            "eventTime": "2023-02-01T00:00:00",
            "eventType": "PR",
            "eventBody": {
              "transaction": {
                "nominalValue": 45833.0,
                "nominalAccrued": 833.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 4167.0,
            "remainingValue": 4167.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "e0ac4b65-4584-4437-a8e3-2c4c5e3e5d67",
            "eventTime": "2023-03-01T00:00:00",
            "eventType": "IP",
            "eventBody": {
              "transaction": {
                "nominalValue": 41597.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 764.0,
            "remainingValue": 764.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "f71cbff0-1708-48d6-9ed2-d15c6534f69d",
            "eventTime": "2023-03-01T00:00:00",
            "eventType": "PR",
            "eventBody": {
              "transaction": {
                "nominalValue": 41597.0,
                "nominalAccrued": 764.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 4236.0,
            "remainingValue": 4236.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "0afd9e04-8a31-4826-886d-bdb2489dd28c",
            "eventTime": "2023-04-01T00:00:00",
            "eventType": "IP",
            "eventBody": {
              "transaction": {
                "nominalValue": 37291.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 693.0,
            "remainingValue": 693.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          }
        ]
      }
  • 400 bad request

    • If the provided contractUUID is invalid or not found, the endpoint will return an HTTP status code 404 Not Found.

  • 403 forbidden

    • If the user does not have the necessary permissions to execute contracts.

  • 404 not found

    • If the contract with the provided UUID does not exist.

  • 500 internal server error

    • If there is an unexpected error executing the contract.

Example error response

  • 400 bad request

    • If the provided contractUUID is invalid or does not exist.

    • Response body

        {
          "status": 400,
          "message": "Invalid contractUUID " + 36c7d13e-55dc-4b89-a1b8-98f1f8716698,
          "data": "null"
        }

6.2.3. Methods

Description

This method is responsible for creating a dynamic event associated with a contract.

  1. Method : computeContract

    • Purpose

      • This method computes the schedule of business events for a given contract identified by its UUID.

    • Parameters

      • contractUUID (UUID) : The UUID of the contract for which the schedule is to be computed.

    • Return type

      • List<BusinessEvents> : A list of business events representing the schedule for the contract.

        public List<BusinessEvents> computeContract(UUID contractUUID) throws ContractsException {
        		List<BusinessEvents> contractSchedule;
        		Contracts contract = contractsServiceRepo.findById(contractUUID)
        				.orElseThrow(() -> new IllegalArgumentException(CONTRACT_ERROR)); (1)
        
        		try {
        			// Compute the contract schedule.
        			contractSchedule = getContractSchedule(contract); (2)
        
        		} catch (Exception e) {
        			throw new ContractsException(e.getMessage()); (3)
        		}
        		return contractSchedule;
        	}
    • Behavior

    1 Retrieves contract information from the contracts service repository.
    2 Calls the getContractSchedule method to compute the contract schedule.
    3 Throws a ContractsException if any error occurs during computation.
  2. Method : getContractSchedule

    • Purpose

      • This method generates the schedule of business events for a given contract.

    • Parameters

      • contract (Contracts) : The contract object for which the schedule is to be generated.

    • Return type

      • List<BusinessEvents> : A list of business events representing the schedule for the contract.

        public List<BusinessEvents> getContractSchedule(Contracts contract) throws ParseException {
        		// Get the risk factor model provider for the contract.
        		RiskFactorModelProvider riskFactorModelProvider = getRiskFactorModelProvider(contract); (1)
        
        		// Generate the schedule of business events using the actusFactoryWorker.
        		return actusFactoryWorker.generateSchedule(contract, riskFactorModelProvider); (2)
        
        	}
    • Behavior

    1 Retrieves the risk factor model provider for the contract.
    2 Calls the generateSchedule method to generate the contract schedule.
  3. Method : generateSchedule

    • Purpose

      • This method generates the schedule of business events for a given contract using the provided risk factor model.

    • Parameters

      • contract (Contracts) : The contract object for which the schedule is to be generated.

      • riskFactorModelProvider (RiskFactorModelProvider) : The risk factor model provider used for generating the schedule.

    • Return type

      • List<BusinessEvents> : A list of business events representing the schedule for the contract.

        public List<BusinessEvents> generateSchedule(Contracts contract, RiskFactorModelProvider riskFactorModelProvider) {
        		List<ContractEvent> contractEvents;
        		log.info("Contract generate schedule started by UserId : {}, ContractUUID : {}", usersHelper.getUserID(),
        				contract.getContractUUID());
        		final Terms masterTerm = contract.getContractTerms().get(0);
        		LocalDateTime statusDate = masterTerm.getStatusDate();
        		LocalDateTime maturityDate = masterTerm.getMaturityDate();
        		final List<String> specialContractTypes = Arrays.asList("AINV", "ARES", "AEQT");
        		List<BusinessEvents> businessEventsList = new ArrayList<>();
        
        		if (specialContractTypes.contains(masterTerm.getContractType())) {
        			// Need to implement
        			return businessEventsList;
        
        		} else {
        			for (final Terms contractTerms : contract.getContractTerms()) {
        
        				Map<String, Object> termsMap = ContractsMapper.termsToMap(contractTerms);
        
        				// Mapping terms object to ContractModel object
        				ContractModelProvider model = getContractModel(termsMap);
        
        				// Get contract events based on the model, status date, and risk factor model
        				// provider.
        				contractEvents = getContractEvents(model, maturityDate, statusDate, riskFactorModelProvider); (1)
        
        				// Mapping contractEvent to BusinessEvents
        				List<BusinessEvents> businessEvents = getBusinessEvents(contract, contractTerms, contractEvents); (2)
        				businessEventsList.addAll(businessEvents);
        			}
        
        			Collections.sort(businessEventsList, new SortByEventTime()); (3)
        			log.info("Contract generate schedule finihed by UserId : {}, ContractUUID : {}", usersHelper.getUserID(),
        					contract.getContractUUID());
        			return businessEventsList; (4)
        		}
        
        	}
    • Behavior

    1 Processes the contract terms and generates contract events based on the provided model, maturity date, and status date.
    2 Maps contract events to business events and adds them to the list of business events.
    3 Sorts the list of business events by event time.
    4 Returns business events list.

6.2.4. Validation

Description

The method validateContract(String contractUUID) is responsible for validating a contract identified by its UUID.

  • Parameters

    • contractUUID : The UUID of the contract to validate.

  • Returns

    • This method does not return any value (void).

  • Functionality

    • Validates the contract UUID to ensure it is valid.

    • Validates the status of the contract to ensure it is in the "PreDeal" state.

  • Exceptions

    • Throws IllegalArgumentException if the contract UUID is invalid or if the contract status is not "PreDeal".

  • Example usage

/**
	 * Retrieves a contract based on its UUID.
	 *
	 * @param contractUUID The UUID of the contract to retrieve.
	 * @return The Contracts object representing the retrieved contract.
	 * @throws IllegalArgumentException If the contract UUID is invalid.
	 */
	public Contracts validateContractUUID(String contractUUID) {
		// Provides contract information based on contractUUID
		final Optional<Contracts> optionalContract = contractsRepo.findById(UUID.fromString(contractUUID)); (1)

		Assert.isTrue(optionalContract.isPresent(), "Invalid contractUUID " + contractUUID);
		return optionalContract.get(); (2)

	}
/**
	 * Validates the status of a contract.
	 *
	 * @param contract The Contracts object representing the contract data to
	 *                 validate.
	 * @throws IllegalArgumentException If the contract status is not "PreDeal".
	 */
	public void validateContractStatus(Contracts contract) {
		final Terms term = contract.getContractTerms().get(0);
		Assert.isTrue(term.getContractPerformance().equals("PreDeal"), "Contract already executed"); (3)
	}
Validation steps
1 Validating contract UUID
  • This step ensures that the provided contract UUID is valid and corresponds to an existing contract in the system.

2 Retrieving contract
  • Once the contract UUID is validated, the method retrieves the contract object associated with the UUID.

3 Validating contract status
  • The contract status is then validated to ensure it is in the "PreDeal" state, indicating that the contract has not been executed yet.

  • Ensure that the contract UUID provided is valid and corresponds to an existing contract.

  • Handle any exceptions thrown during the validation process, particularly IllegalArgumentException.

  • Developers should be aware that this method does not return any value (void), and the validation results are communicated through exceptions.

  • It is recommended to call this method before performing any operations related to a contract to ensure its validity and status.

  • Ensure that the Contracts object and its associated data structures (Terms, etc.) are properly initialized and populated before invoking the validateContract method.

  • Developers should have a clear understanding of the contract status and its implications in the system before using this method.

6.2.5. Testing

Description

This section provides an overview of the testing strategy and objectives for the get computed contract schedule method.

Test methods

Example usage

@Test
	void computeContractTest() throws ContractsException { (1)

		List<BusinessEvents> eventsList = contractServiceImpl
				.computeContract(contracts.getContractUUID());
		Assertions.assertEquals(25, eventsList.size());

	}

	@TestFactory
	Stream<DynamicTest> computeContractScheduleTest() throws IOException, ContractsException { (2)
		List<DynamicTest> dynamicTests = new ArrayList<>();

		List<BusinessEventsDto> expectedEventsList = MappingUtils
				.mapToEventsList("./src/test/resources/events/events-contract-ann.json");

		List<BusinessEvents> computedEventsList = contractServiceImpl
				.computeContract(contracts.getContractUUID());

		Assertions.assertEquals(expectedEventsList.size(), computedEventsList.size(), "Number of events should match.");

		for (int i = 0; i < expectedEventsList.size(); i++) {
			BusinessEventsDto expectedEvent = expectedEventsList.get(i);
			BusinessEvents computedEvent = computedEventsList.get(i);

			dynamicTests.add(contractUtils.createDynamicTest(expectedEvent, computedEvent));
		}

		return dynamicTests.stream();
	}
1 computeContractTest()
  • Purpose : To validate that the computeContract method produces the correct output, specifically checking the size of the generated events list.

  • Test steps

    1. Invoke the computeContract method with a known contract UUID.

    2. Retrieve the list of generated business events.

  • Assertions

    • Assert that the size of the computed events list matches the expected size (25 in this case).

2 computeContractScheduleTest()
  • Purpose : To ensure that the computeContractSchedule method generates the correct list of business events, validating against a predefined set of expected events.

  • Test steps

    1. Read the expected list of business events from a JSON file.

    2. Invoke the computeContract method with the contract UUID.

    3. Compare the expected and computed lists of business events.

    4. Create dynamic tests for each pair of expected and computed events.

  • Assertions

    • Assert that the size of the computed events list matches the size of the expected events list.

    • For each pair of expected and computed events, assert their equality.

6.3. Execute contracts

6.3.1. Sequential flow

execute-contract.puml

Contract execution process

  1. This method executes a contract identified by the given contract UUID.

  2. It validates the contract, sets its performance to "PF" (Performant).

  3. Saves the contract schedule.

  4. Creates a Metaco account for the contract, only if the contract’s selection contains a "Ledger ID" key.

  5. Updates contract payment channels, and sends a Kafka event signaling the contract execution.

  6. If successful, it returns a list of business events associated with the execution.

6.3.2. Endpoint

Description

This endpoint executes a contract and returns its schedule based on the provided contractUUID.

URL

/contracts/execute

Method

POST

Request parameters

Parameters

Type

Required

Description

contractUUID

UUID

Yes

The UUID of an existing contract to be executed.

Responses

  • 200 OK

    • Returns the schedule of the executed contract.

    • Response body

      {
        "status": 200,
        "message": "Success",
        "data": [
          {
            "eventID": "23a83225-007e-47f2-8dcd-21534a0b92f4",
            "eventTime": "2023-01-01T00:00:00",
            "eventType": "IED",
            "eventBody": {
              "transaction": {
                "nominalValue": 50000.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": -50000.0,
            "remainingValue": -50000.0,
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "debitPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "423ec885-8af4-4a19-8f1f-7d707fd5eefe",
            "eventTime": "2023-01-01T00:00:00",
            "eventType": "FP",
            "eventBody": {
              "transaction": {
                "nominalValue": 0.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 5000.0,
            "remainingValue": 5000.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "Loan processing fee",
            "units": "INR"
          },
          {
            "eventID": "adbca86d-95a9-4327-bddc-71c69af1a1dc",
            "eventTime": "2023-01-01T00:00:00",
            "eventType": "FP",
            "eventBody": {
              "transaction": {
                "nominalValue": 0.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 2500.0,
            "remainingValue": 2500.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "Insurance Fee",
            "units": "INR"
          },
          {
            "eventID": "433a60c6-2429-40d1-9783-2484c90ac987",
            "eventTime": "2023-02-01T00:00:00",
            "eventType": "IP",
            "eventBody": {
              "transaction": {
                "nominalValue": 45833.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 833.0,
            "remainingValue": 833.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "1b062381-3b44-404a-afb7-d6296ca95b9e",
            "eventTime": "2023-02-01T00:00:00",
            "eventType": "PR",
            "eventBody": {
              "transaction": {
                "nominalValue": 45833.0,
                "nominalAccrued": 833.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 4167.0,
            "remainingValue": 4167.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "e0ac4b65-4584-4437-a8e3-2c4c5e3e5d67",
            "eventTime": "2023-03-01T00:00:00",
            "eventType": "IP",
            "eventBody": {
              "transaction": {
                "nominalValue": 41597.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 764.0,
            "remainingValue": 764.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "f71cbff0-1708-48d6-9ed2-d15c6534f69d",
            "eventTime": "2023-03-01T00:00:00",
            "eventType": "PR",
            "eventBody": {
              "transaction": {
                "nominalValue": 41597.0,
                "nominalAccrued": 764.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 4236.0,
            "remainingValue": 4236.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          },
          {
            "eventID": "0afd9e04-8a31-4826-886d-bdb2489dd28c",
            "eventTime": "2023-04-01T00:00:00",
            "eventType": "IP",
            "eventBody": {
              "transaction": {
                "nominalValue": 37291.0,
                "nominalAccrued": 0.0
              }
            },
            "status": "pending",
            "executionType": "transaction",
            "value": 693.0,
            "remainingValue": 693.0,
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51",
            "contractUUID": "2d904008-f6d4-4740-8a9f-8723ff03fd45",
            "contractID": "75361862-baec-4bf1-9e05-b87539196d5b",
            "units": "INR"
          }
        ]
      }
  • 400 bad request

    • If the required parameter contractUUID is missing or invalid.

  • 403 forbidden

    • If the user does not have the necessary permissions to execute contracts.

  • 404 not found

    • If the contract with the provided UUID does not exist.

  • 500 internal server error

    • If there is an unexpected error executing the contract.

Example error response

  • 400 bad request

    • If the provided contractUUID is invalid or does not exist.

    • Response body

        {
          "status": 400,
          "message": "Invalid contractUUID provided.",
          "data": "null"
        }

6.3.3. Methods

Description

The method executeContract executes a contract identified by the given UUID. It performs various actions related to contract execution, including setting contract performance status, saving contract schedule, updating contract payment channels, saving contract execution details, and sending a Kafka event for contract execution.

Method signature

public List<BusinessEvents> executeContract(String contractUUID) throws ContractsException

Parameters

  • contractUUID (String): The UUID of the contract to execute.

Returns

  • List<BusinessEvents> : A list of BusinessEvents representing the business events generated by executing the contract.

Exceptions

  • ContractsException : Thrown if there’s an error executing the contract.

Usage example

contractsValidator.validateContract(contractUUID); (1)

public List<BusinessEvents> executeContract(String contractUUID) throws ContractsException {
		log.info("Contract execution started by UserId : {}, ContractUUID : {}", usersHelper.getUserID(), contractUUID);
		List<BusinessEvents> businessEvents;
		Contracts contract = contractsServiceRepo.findById(UUID.fromString(contractUUID))
				.orElseThrow(() -> new IllegalArgumentException(CONTRACT_ERROR)); (2)
		Terms contractTerms = contract.getContractTerms().get(0);
		// Set the contract status to "PF".
		contractTerms.setContractPerformance("PF"); (3)
		try {

			// Save the contract schedule.
			businessEvents = saveContractSchedule(contract); (4)

			// Create a Metaco account for the contract.
			contractsHelper.createMetacoAccount(contract); (5)

			// Update contract payment channels(Linking contract to paymentChannel).
			updateContractPaymentChannel(contract); (6)

			contract.setExecutedBy(usersHelper.getUserID());
			contract.setTimeStamp(UtilityHelper.dateTime());
			contractsServiceRepo.save(contract); (7)

			// Send a request to Kafka for contract execution.
			sendKafkaContractExecutedEvent(contract); (8)

			log.info("Contract execution finished by UserId : {}, ContractUUID : {}", usersHelper.getUserID(),
					contractUUID);

		} catch (Exception e) {
			throw new ContractsException(e.getMessage()); (9)
		}

		return businessEvents;
	}
Internal workflow:
1 The method validates the contract identified by contractUUID using the contractsValidator.validateContract method.
2 Retrieves the contract details from the repository based on the provided UUID.
3 Sets the contract performance status to "PF".
4 Saves the contract schedule.
5 If the contract selection contains a LedgerID key, then it creates a Metaco account for the contract.
6 Updates contract payment channels.
7 Saves contract execution details including the executor’s user ID and timestamp.
8 Sends a Kafka event indicating contract execution.
9 If any exception occurs during the execution, it is caught, and a ContractsException is thrown with the corresponding error message.
  • Ensure that the contractUUID provided is valid and corresponds to an existing contract.

  • Handle any potential errors gracefully by catching and handling the ContractsException.

  • Business events returned may vary based on the specific contract implementation.

6.3.4. Validation

Description

The method validateContract(String contractUUID) is responsible for validating a contract identified by its UUID.

  • Parameters

    • contractUUID : The UUID of the contract to validate.

  • Returns

    • This method does not return any value (void).

  • Functionality

    • Validates the contract UUID to ensure it is valid.

    • Validates the status of the contract to ensure it is in the "PreDeal" state.

  • Exceptions

    • Throws IllegalArgumentException if the contract UUID is invalid or if the contract status is not "PreDeal".

  • Example usage

/**
	 * Retrieves a contract based on its UUID.
	 *
	 * @param contractUUID The UUID of the contract to retrieve.
	 * @return The Contracts object representing the retrieved contract.
	 * @throws IllegalArgumentException If the contract UUID is invalid.
	 */
	public Contracts validateContractUUID(String contractUUID) {
		// Provides contract information based on contractUUID
		final Optional<Contracts> optionalContract = contractsRepo.findById(UUID.fromString(contractUUID)); (1)

		Assert.isTrue(optionalContract.isPresent(), "Invalid contractUUID " + contractUUID);
		return optionalContract.get(); (2)

	}
/**
	 * Validates the status of a contract.
	 *
	 * @param contract The Contracts object representing the contract data to
	 *                 validate.
	 * @throws IllegalArgumentException If the contract status is not "PreDeal".
	 */
	public void validateContractStatus(Contracts contract) {
		final Terms term = contract.getContractTerms().get(0);
		Assert.isTrue(term.getContractPerformance().equals("PreDeal"), "Contract already executed"); (3)
	}
Validation steps
1 Validating contract UUID
  • This step ensures that the provided contract UUID is valid and corresponds to an existing contract in the system.

2 Retrieving contract
  • Once the contract UUID is validated, the method retrieves the contract object associated with the UUID.

3 Validating contract status
  • The contract status is then validated to ensure it is in the "PreDeal" state, indicating that the contract has not been executed yet.

  • Ensure that the contract UUID provided is valid and corresponds to an existing contract.

  • Handle any exceptions thrown during the validation process, particularly IllegalArgumentException.

  • Developers should be aware that this method does not return any value (void), and the validation results are communicated through exceptions.

  • It is recommended to call this method before performing any operations related to a contract to ensure its validity and status.

  • Ensure that the Contracts object and its associated data structures (Terms, etc.) are properly initialized and populated before invoking the validateContract method.

  • Developers should have a clear understanding of the contract status and its implications in the system before using this method.

6.3.5. Testing

Description

This section provides an overview of the testing strategy and objectives for the execute contract method.

Test methods

Example usage

	@Test
	void executeContractTest() throws ContractsException { (1)

		List<BusinessEvents> executeContract = contractServiceImpl.executeContract(contracts.getContractUUID());
		System.err.println("gfjfg "+executeContract);
		Contracts contracts1 = contractsRepo.findById(contracts.getContractUUID()).get();
		String contractStatus = contracts1.getContractTerms().get(0).getContractPerformance();

		Assertions.assertEquals("PF", contractStatus);

	}

	@TestFactory
	Stream<DynamicTest> executeContractAfterTest() throws IOException, ContractsException { (2)
		List<DynamicTest> dynamicTests = new ArrayList<>();

		List<BusinessEventsDto> expectedEventsList = MappingUtils
				.mapToEventsList("./src/test/resources/events/events-contract-ann.json");

		List<BusinessEvents> computedEventsList = contractServiceImpl
				.executeContract(contracts.getContractUUID());

		Assertions.assertEquals(expectedEventsList.size(), computedEventsList.size(), "Number of events should match.");

		for (int i = 0; i < expectedEventsList.size(); i++) {
			int eventIndex = i;
			BusinessEventsDto expectedEvent = expectedEventsList.get(eventIndex);
			BusinessEvents computedEvent = computedEventsList.get(eventIndex);

			dynamicTests.add(contractUtils.createDynamicTest(expectedEvent, computedEvent));
		}

		return dynamicTests.stream();
	}
1 executeContractTest()
  • Purpose : To verify that executing a contract updates its status correctly.

  • Test steps

    1. Execute a contract.

    2. Retrieve the updated contract from the repository.

    3. Check that the contract performance status is updated as expected.

  • Assertions

    • Assert that the contract performance status is updated to "PF".

2 executeContractAfterTest()
  • Purpose : This test verified and validates the correctness of business events generated after executing a contract.

  • Test steps

    1. Execute a contract.

    2. Compare the generated business events with expected events.

  • Assertions

    • Assert that the number and details of computed business events match the expected events.

6.4. Get contracts

6.4.1. Sequential flow

get-contract.puml

Contract retrieval process

  1. Retrieve contracts entities : The getContracts method starts by fetching a list of Contracts entities from the data source based on the provided filtering criteria and pagination parameters.

  2. Iterate through contracts list

    • For each contract in the retrieved list

  3. Retrieve contract terms : The terms associated with each contract are retrieved to provide additional details.

  4. Optional: Update notional principle

    • If the contract’s performance is not "PreDeal" and the contract type is "COM" (commodity contract), the notional principal of the contract is updated.

  5. Map terms to DTO

    • The terms associated with each contract are mapped to a list of TermsDto objects using a mapping function.

  6. Create ContractsDto object

    • A ContractsDto object is created and populated with relevant contract information:

      • contractUUID

      • productID

      • terms (mapped to a list of TermsDto)

      • selection

      • paymentDetails

      • createdBy

      • executedBy

      • timeStamp

  7. Add ContractsDto to list : The created ContractsDto object is added to the list of ContractsDto objects representing the retrieved contracts.

  8. Return contracts list : The list of ContractsDto objects representing the retrieved contracts is returned.

6.4.2. Endpoint

Description

Retrieves a list of contract information based on specified filter parameters and pagination.

URL

/contracts

Method

GET

Request filter parameters

Parameters

Type

Required

Description

ContractsFilterDto

JSON object

No

Provided based on the requirements.

pageNumber

Integer

No

Default value is 0.

pageSize

Integer

No

Default value is 100.

Responses

  • 200 OK

    • Returns the contracts information.

    • Response body

      {
          "status": 200,
          "message": "Success",
          "data": [
              {
                  "contractUUID": "28ee9eb5-e4b9-491c-98ce-a451abbedae9",
                  "productID": 4,
                  "paymentDetails": {
                      "recordCreatorPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
                      "counterpartyPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
                      "contractPaymentChannelID": null
                  },
                  "terms": [
                      {
                          "contractPerformance": "PreDeal",
                          "businessDayConvention": "SCF",
                          "contractType": "ANN",
                          "statusDate": "2023-01-01T00:00:00",
                          "contractRole": "RPA",
                          "creatorID": "902375cc-4f72-428f-8db0-95a7baa69b51",
                          "counterpartyID": "d2c87ded-489e-4510-8fe1-95f12c048a5d",
                          "contractID": "9ec8997e-70b5-4fa1-82fe-56cbc0fc8149",
                          "cycleAnchorDateOfInterestPayment": "2023-02-02T00:00:00",
                          "cycleOfInterestPayment": "P1ML1",
                          "nominalInterestRate": 0.01,
                          "dayCountConvention": "30E360",
                          "currency": "CHF",
                          "contractDealDate": "2023-01-01T00:00:00",
                          "initialExchangeDate": "2023-01-02T00:00:00",
                          "maturityDate": "2024-01-02T00:00:00",
                          "notionalPrincipal": 20000.0,
                          "cycleAnchorDateOfPrincipalRedemption": "2023-02-02T00:00:00",
                          "cycleOfPrincipalRedemption": "P1ML1",
                          "nextPrincipalRedemptionPayment": 1260.9478399993018
                      }
                  ],
                  "selection": {
                      "tenure": "12M",
                      "department": "DeptB",
                      "profitCenter": "A",
                      "remainingValue": 5000,
                      "productCategory": "Microfinance Loan"
                  },
                  "createdBy": "902375cc-4f72-428f-8db0-95a7baa69b51",
                  "executedBy": null,
                  "timeStamp": "2024-02-26T17:15:10"
              }
          ]
      }
  • 403 forbidden

    • If the user does not have the necessary permissions to execute contracts.

  • 500 internal server error

    • If there is an unexpected error executing the contract.

6.4.3. Methods

Description

This method is responsible for retrieving a list of contract data based on specified filtering criteria and pagination.

  1. Method : getContracts

    • Purpose

      • Retrieve a list of contract data based on specified filtering criteria and pagination.

    • Parameters

      • contractsFilterDto : An object containing filtering criteria for contracts.

      • pageable : An object representing pagination settings.

    • Return type

      • List<ContractsDto> : A list of contract data transfer objects (ContractsDto).

        public List<ContractsDto> getContracts(ContractsFilterDto contractsFilterDto, Pageable pageable) {
        		List<ContractsDto> contractsModelList = new ArrayList<>();
        
        		// Retrieve a list of Contracts entities based on the filtering criteria and
        		// pagination.
        		List<Contracts> contractsList = getContractsList(contractsFilterDto, pageable);(1)
        
        		for (final Contracts contract : contractsList) { (2)
        			final Terms term = contract.getContractTerms().get(0);
        
        			// Notional principle update for commodity contracts
        			if (!term.getContractPerformance().equalsIgnoreCase("PreDeal")
        					&& term.getContractType().equalsIgnoreCase("COM")) {
        				Contracts updatedContract = contractsHelper.updateNotionalPrincipal(contract); (3)
        				contractsServiceRepo.save(updatedContract);
        
        			}
        
        			// Map terms to a list of TermsDto objects
        			List<TermsDto> termsDtoList = ContractsMapper.mapToTermsDto(contract.getContractTerms()); (4)
        			Map<String, Object> termsMap = new HashMap<>();
        			termsMap.put("Terms", termsDtoList);
        
        			// Create a ContractsDto object for the contract
        			ContractsDto contractsModel = new ContractsDto(); (5)
        			contractsModel.setContractUUID(contract.getContractUUID());
        			contractsModel.setProductUUID(contract.getProductUUID());
        			contractsModel.setTerms(termsMap);
        			contractsModel.setSelection(contract.getSelection());
        			contractsModel.setPaymentDetails(contract.getPaymentDetails());
        			contractsModel.setCreatedBy(contract.getCreatedBy());
        			contractsModel.setExecutedBy(contract.getExecutedBy());
        			contractsModel.setProfileId(contract.getProfileId());
        			contractsModel.setTimeStamp(contract.getTimeStamp());
        
        			contractsModelList.add(contractsModel);
        
        		}
        		return contractsModelList; (6)
        	}
    • Behavior

    1 Retrieves a list of contract entities based on the provided filtering criteria and pagination.
    2 Iterates through each contract entity.
    3 Updates the notional principle for commodity contracts if certain conditions are met.
    4 Maps contract terms to a list of term data transfer objects (TermsDto).
    5 Constructs a ContractsDto object for each contract entity with mapped data.
    6 Returns a list of constructed ContractsDto objects.
  2. Method : getContractsList

    • Purpose

      • Retrieve a list of contract entities based on specified filtering criteria and pagination.

    • Parameters

      • contractsFilterDto : An object containing filtering criteria for contracts.

      • pageable : An object representing pagination settings.

    • Return type

      • List<Contracts> : A list of contract entities.

        public List<Contracts> getContractsList(ContractsFilterDto contractsFilterDto, Pageable pageable) {
        		// Build a JPA query using the buildContractsQuery method.
        		TypedQuery<Tuple> contractsQuery = buildContractsQuery(contractsFilterDto, pageable); (1)
        
        		// Execute the query and retrieve a list of contract UUIDs.
        		List<UUID> contractUUIDs = contractsQuery.getResultList().stream().map(tuple -> tuple.get(0, UUID.class))
        				.toList(); (2)
        
        		return contractsServiceRepo.findByContractUUIDIn(contractUUIDs); (3)
        	}
    • Behavior

    1 Builds a JPA query using the provided filtering criteria and pagination.
    2 Executes the query to retrieve a list of contract UUIDs.
    3 Retrieves contract entities based on the retrieved UUIDs and returns the list of entities.
  3. Method : buildContractsQuery

    • Purpose

      • Build a JPA query for retrieving contract entities based on specified filtering criteria and pagination.

    • Parameters

      • contractsFilterDto : An object containing filtering criteria for contracts.

      • pageable : An object representing pagination settings.

    • Return type

      • TypedQuery<Tuple> : A typed query for retrieving contract entities.

      private TypedQuery<Tuple> buildContractsQuery(ContractsFilterDto contractsFilterDto, Pageable pageable) { (1)
      		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
      		CriteriaQuery<Tuple> query = cb.createTupleQuery();
      		Root<Contracts> rootContracts = query.from(Contracts.class);
      		Join<Contracts, Terms> joinTerms = rootContracts.join("contractTerms", JoinType.INNER);
      
      		// Select specific columns (contractUUID and timeStamp)
      		query.multiselect(rootContracts.get("contractUUID"), rootContracts.get("timeStamp"));
      
      		Predicate predicate = cb.conjunction();
      
      		predicate = cb.and(predicate, cb.equal(joinTerms.get("creatorID"), usersHelper.getUserID()));
      
      		// Apply additional filter conditions based on ContractsFilterDto
      		if (!UtilityHelper.isNullorEmpty(contractsFilterDto.getContractUUID())) { (2)
      			predicate = cb.and(predicate,
      					cb.equal(rootContracts.get("contractUUID"), contractsFilterDto.getContractUUID()));
      		}
      
      		if (!UtilityHelper.isNullorEmpty(contractsFilterDto.getProductID())) {
      			predicate = cb.and(predicate, cb.equal(rootContracts.get("productID"), contractsFilterDto.getProductID()));
      		}
      
      		if (!UtilityHelper.isNullorEmpty(contractsFilterDto.getTimestamp())) {
      			predicate = cb.and(predicate,
      					cb.like(rootContracts.get("timeStamp"), "%" + contractsFilterDto.getTimestamp() + "%"));
      		}
      
      		query.where(predicate);
      
      		// Apply ordering
      		query.orderBy(cb.desc(rootContracts.get("timeStamp"))); (3)
      		query.distinct(true);
      
      		// Create the TypedQuery
      		TypedQuery<Tuple> typedQuery = entityManager.createQuery(query);
      
      		// Apply pagination if provided
      		if (pageable != null) { (4)
      			typedQuery.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
      			typedQuery.setMaxResults(pageable.getPageSize());
      		}
      		return typedQuery; (5)
      	}
    • Behavior

1 Constructs a JPA query for retrieving contract entities.
2 Applies filtering conditions based on the provided criteria.
3 Orders the results by timestamp in descending order.
4 Applies pagination settings if provided.
5 Returns the constructed typed query.

6.4.4. Model classes

Description

The ContractsFilterDto represents a data transfer object (DTO) used for filtering contracts based on specific criteria.

Attributes
  1. contractUUID

    • Description: Represents the unique identifier of a contract.

    • Usage: Used to filter contracts by a specific UUID.

    • Type: UUID

    • Example: ad3a03d5-d109-440a-8d70-619c780d471a

  2. timestamp

    • Type: LocalDateTime

    • Description: Represents the timestamp associated with contracts.

    • Usage: Used to filter contracts by a specific timestamp.

    • Example: 2024-02-19 16:02:51

  3. productId

    • Type: Long

    • Description: Represents the identifier of the product associated with contracts.

    • Usage: Used to filter contracts by a specific product ID.

    • Example: 1

ContractsFilterDto

@Setter
@Getter
@NoArgsConstructor
@ToString
public class ContractsFilterDto {

	private UUID contractUUID;

	private LocalDateTime timestamp;

	private Long productID;

}

6.5. Update contracts

6.5.1. Sequential flow

update-contract.puml

Contract updation process

Validation process

  • The validation process ensures the accuracy and integrity of contract update requests.

  • Here, the Validator meticulously examines contract data for consistency and adherence to predefined rules.

  • If the contract UUID is valid, the updation process proceeds.

Updation process

  • The contract status and terms are verified against product specifications.

  • Error handling mechanisms swiftly address issues such as invalid UUIDs or contract term discrepancies, guaranteeing a robust validation process.

  • Subsequently, the business process meticulously executes contract updates, involving validation against product specifications and computation of contract terms.

  • This ensures accuracy and integrity throughout the operation.

6.5.2. Endpoint

Description

This endpoint allows users with the appropriate permissions to update contracts based on the provided data.

URL

/contracts

Method

PUT

Request body

The request body should contain a JSON array of objects, each representing data for updating a contract. The structure of each object should adhere to the UpdateContractDto format.

Example request body

[
  {
    "contractUUID": "28ee9eb5-e4b9-491c-98ce-a451abbedae9",
    "productID": 4,
    "terms": [
      {
        "initialExchangeDate": "2023-01-02T00:00:00",
        "notionalPrincipal": "20000"
      }
    ],
    "selection": {
      "remainingValue": 5000,
      "tenure": "18M"
    }
  }
]

Responses

  • 200 : Success. Returns a JSON response containing details of the updated contracts.

Example response body

{
    "status": 200,
    "message": "Contracts updated successfully",
    "data": [
        {
            "contractUUID": "28ee9eb5-e4b9-491c-98ce-a451abbedae9",
            "contractID": "9ec8997e-70b5-4fa1-82fe-56cbc0fc8149",
            "errors": []
        }
    ]
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions to create contracts.

  • 5xx server error: If there is a server-side error while processing the request.

Example

{
  "status": 400,
  "message": "Invalid ContractUUID 28ee9eb5-e4b9-491c-98ce-a451abbedae9",
  "data": "28ee9eb5-e4b9-491c-98ce-a451abbedae9"
}

6.5.3. Methods

Description

The method updateContract updates contracts based on the provided contract data list.

Method signature

public List<ContractsResponseDto> updateContract(List<UpdateContractDto> contractDataList)

Parameters

  • contractDataList : List of UpdateContractDto objects containing contract update information.

Returns

  • List<ContractsResponseDto> : List of ContractsResponseDto objects representing the response for each contract update.

Example usage

public List<ContractsResponseDto> updateContract(List<UpdateContractDto> contractDataList) {
		List<ContractsResponseDto> contractResponseDtoList = new ArrayList<>();
		ContractsResponseDto contractResponseDto;

		for (UpdateContractDto updateContractData : contractDataList) { (1)
			// Validate the contract data using the updateContractValidator.
			contractResponseDto = updateContractValidator.validateContractData(updateContractData); (2)

			// If there are no validation errors, proceed with the contract update.
			if (contractResponseDto.getErrors().isEmpty()) {
				contractResponseDto = contractsWorker.updateContract(updateContractData); (3)
			}
			contractResponseDtoList.add(contractResponseDto);
		}
		return contractResponseDtoList; (4)
	}
Internal workflow
1 This method iterates through the provided list of contract data.
2 It validates each contract data using the updateContractValidator.
3 If there are no validation errors, it proceeds with the contract update using the contractsWorker.
4 The method returns a list of ContractsResponseDto objects containing the response for each contract update.

Exceptions

  • None explicitly thrown by this method. However, exceptions may occur within the validator or worker methods, which are handled internally.

6.5.4. Model classes

Description

The UpdateContractDto class represents the data transfer object used for updating contract information. It encapsulates details such as the contract UUID, product ID, and terms to be updated.

Attributes
  1. contractUUID

    • Type: UUID

    • Description: Represents the universally unique identifier (UUID) of the contract to be updated.

    • Example: 3539ebf7-e93f-4e38-90d5-8c4729ed493c

  2. productID

    • Type: Long

    • Description: Represents the identifier of the product associated with the contract.

    • Example: 1

  3. terms

    • Type: List<Map<String, Object>>

    • Description: Collection of contract terms represented as key-value pairs.

    • Example:

    {
      "terms": [
        {
          "contractPerformance": "PreDeal",
          "businessDayConvention": "SCF",
          "contractType": "ANN",
          "statusDate": "2023-07-31T06:30:00",
          "contractRole": "RPA",
          "creatorID": "a43c22ed-27df-4324-a453-3e7707c9b82d",
          "counterpartyID": "e548956c-1f3b-493e-952e-00cdcca6b599",
          "contractID": "a6b799db-c448-4aad-9382-3ae47383f5b2",
          "cycleAnchorDateOfInterestPayment": "2023-09-01T06:30:00",
          "cycleOfInterestPayment": "P1ML1",
          "nominalInterestRate": 0.02,
          "dayCountConvention": "30E360",
          "currency": "CHF",
          "contractDealDate": "2023-07-31T06:30:00",
          "initialExchangeDate": "2023-08-01T06:30:00",
          "maturityDate": "2024-08-01T06:30:00",
          "notionalPrincipal": 50000,
          "cycleAnchorDateOfPrincipalRedemption": "2023-09-01T06:30:00",
          "cycleOfPrincipalRedemption": "P1ML1",
          "nextPrincipalRedemptionPayment": 2312.7827499791606
        }
      ]
    }

6.5.5. Validation

Description

The validateContractData method is responsible for validating the contract data before proceeding with the contract update process. It ensures that the contract UUID is valid and then delegates further validation to the validateContractTerms method.

  • Parameters

    • updateContractData : An instance of the UpdateContractDto class containing the contract data to be validated.

  • Returns

  • ContractsResponseDto : A data transfer object containing the result of the validation process.

  • Example usage

public ContractsResponseDto validateContractData(UpdateContractDto updateContractData) {
		String contractID = null;
		HashMap<String, Object> contractErrors = new HashMap<>();
		List<Map<String, Object>> errorList = new ArrayList<>();

		try {
			// Validate the contract UUID by calling the contractsValidator.
			contractsValidator.validateContract(updateContractData.getContractUUID()); (1)

			// If there are no errors related to the contract UUID, proceed with further
			// validation.
			return validateContractTerms(updateContractData); (2)

		} catch (Exception e) { (3)
			contractErrors.put("Contract data", e.getMessage());
			errorList.add(contractErrors);
			return new ContractsResponseDto(null, contractID, errorList);
		}

	}
Validation steps
1 Contract UUID validation
  • The method invokes the validateContract method of the contractsValidator to validate the contract UUID.

  • If no errors are encountered, the method proceeds with further validation.

  • If an exception occurs during validation, an error message is added to the error list.

2 Contract terms validation
  • Further validation of contract terms is performed by calling the validateContractTerms method.

  • The validation result is returned as a ContractsResponseDto object.

3 Error handling
  • If an exception occurs during contract UUID validation, an error message is added to the error list.

  • The method returns a ContractsResponseDto object containing any validation errors encountered.

6.5.6. Testing

Description

This section comprises two test methods: updateContractBeforeTest and updateContractAfterTest. These methods validate the behavior of the contract update process before and after execution, respectively.

Test methods

Example usage

@Test
	void updateContractBeforeTest() { (1)

		Terms masterTerms = contracts.getContractTerms().get(0);
		PaymentDetails paymentDetails = contracts.getPaymentDetails();

		System.err.println("paymentDetails"+paymentDetails);
		BigDecimal NotionalPrincipal = new BigDecimal("50000.0");
		BigDecimal NextPrincipalRedemptionPayment = new BigDecimal("2312.7827499791606");
		Assertions.assertEquals(contracts.getProductID(), 1L);
		Assertions.assertEquals(NotionalPrincipal, masterTerms.getNotionalPrincipal(), "0.0");
		Assertions.assertEquals(NextPrincipalRedemptionPayment, masterTerms.getNextPrincipalRedemptionPayment(), "0.01");
		Assertions.assertEquals(LocalDateTime.parse("2023-08-01T00:00:00"), masterTerms.getInitialExchangeDate());
		Assertions.assertEquals(LocalDateTime.parse("2023-07-31T00:00:00"), masterTerms.getStatusDate());
		Assertions.assertEquals(profile.getProfileID(), masterTerms.getCounterpartyID());
		Assertions.assertEquals(paymentDetails.getCounterpartyPaymentChannelID(),
				counterPartyPaymentChannel.getPaymentChannelID());
		Assertions.assertEquals(paymentDetails.getRecordCreatorPaymentChannelID(),
				recordCreatorPaymentChannel.getPaymentChannelID());

	}

	@Test
	void updateContractAfterTest() { (2)
		when(usersHelper.getUserID()).thenReturn(UUID.fromString("a43c22ed-27df-4324-a453-3e7707c9b82d"));
		when(productRepo.findById(product.getProductID())).thenReturn(Optional.of(product));
		BigDecimal NotionalPrincipal = new BigDecimal("47771.0");
		BigDecimal NextPrincipalRedemptionPayment = new BigDecimal("2312.7827499791606");
		Map<String, Object> termsMap = new HashMap<>();
		List<Map<String, Object>> termsList = new ArrayList<>();
		List<UpdateContractDto> updateContractDtoList = new ArrayList<>();
		termsMap.put("initialExchangeDate", "2023-01-01T00:00:00");
		termsMap.put("notionalPrincipal", "47771.0");
		termsMap.put("remainingValue", "2000");
		termsMap.put("remainingValue", "2000");

		UpdateContractDto updateContractDto = new UpdateContractDto();
		contracts.setContractUUID(contractUUID);
		updateContractDto.setContractUUID(contracts.getContractUUID());


		updateContractDto.setProductID(contracts.getProductID());
		termsList.add(termsMap);
		updateContractDto.setTerms(termsList);
		updateContractDtoList.add(updateContractDto);


		List<ContractsResponseDto> updateContractsResponse = contractServiceImpl.updateContract(updateContractDtoList);

		Contracts contracts2 = contractsRepo.findById(UUID.fromString(updateContractsResponse.get(0).getContractUUID()))
				.get();
		Terms masterTerms = contracts2.getContractTerms().get(0);
		PaymentDetails paymentDetails = contracts2.getPaymentDetails();

		Assertions.assertEquals(contracts2.getProductID(), 1L);
		Assertions.assertEquals(NotionalPrincipal, masterTerms.getNotionalPrincipal(), "0.0");
		Assertions.assertEquals(NextPrincipalRedemptionPayment, masterTerms.getNextPrincipalRedemptionPayment(), "0.01");
		Assertions.assertEquals(LocalDateTime.parse("2023-01-01T00:00"), masterTerms.getInitialExchangeDate());
		Assertions.assertEquals(LocalDateTime.parse("2022-12-31T00:00"), masterTerms.getStatusDate());
		Assertions.assertEquals(profile.getProfileID(), masterTerms.getCounterpartyID());

		Assertions.assertEquals(paymentDetails.getCounterpartyPaymentChannelID(),
				counterPartyPaymentChannel.getPaymentChannelID());
		Assertions.assertEquals(paymentDetails.getRecordCreatorPaymentChannelID(),
				recordCreatorPaymentChannel.getPaymentChannelID());

	}
1 updateContractBeforeTest
  • Purpose : Validates the contract attributes before the update process.

  • Test steps

    1. Retrieve the contract attributes before the update process.

    2. Extract and store various contract properties such as notional principal, next principal redemption payment, dates, counterparty ID, and creator ID.

  • Assertions

    • Assert that the notional principal matches the expected value.

    • Assert that the next principal redemption payment matches the expected value.

    • Assert that the dates (e.g., initial exchange date, status date) are correct.

    • Assert that the counterparty ID and creator ID are as expected.

2 updateContractAfterTest
  • *Purpose :*Verifies the updated contract attributes after the update process.

  • Test steps

    1. Construct an UpdateContractDto object with updated contract terms.

    2. Execute the updateContract method to trigger the contract update process.

    3. Retrieve the updated contract from the repository.

    4. Extract and store the updated contract attributes.

  • Assertions

    • Assert that the notional principal has been updated correctly.

    • Assert that the next principal redemption payment reflects the updated terms.

    • Assert that the dates (e.g., initial exchange date, status date) have been modified as expected.

    • Assert that the counterparty ID and creator ID remain unchanged.

6.6. Update executed contract

6.6.1. Sequential flow

update-executed-contract.puml

Executed contract updation process

  1. The User triggers the "updateExecutedContract" operation by providing updation data and the contract UUID.

  2. The Controller receives the request and activates.

  3. The Controller forwards the request to the ContractService.

  4. The ContractService activates to process the update.

  5. The ContractService delegates validation of the executed contract data to the UpdateContractValidator.

  6. If the validation of executed contract data is successful

    • The UpdateContractValidator verifies the contract UUID using ContractsValidator.

    • ContractsValidator retrieves the contract from ContractsRepository by its UUID.

    • UpdateContractValidator checks if the contract update terms are valid against master contract terms using ContractService.

    • If the validation of contract update terms is successful:

      • ContractsWorker updates the executed contract.

      • Updated contract is saved in ContractsRepository.

      • The ContractService responds with a success message to the Controller.

      • The Controller sends a ResponseEntity<ResponseDto> containing the success message to the User.

    • If the validation of contract update terms fails:

      • The ContractService responds with an error message indicating invalid contract data to the Controller.

      • The Controller sends a ResponseEntity<ResponseDto> containing the error message to the User.

  7. If the validation of executed contract data fails

    • The UpdateContractValidator responds with an error message indicating invalid contract UUID to the ContractService.

    • The ContractService responds with a ResponseEntity<ResponseDto> containing the error message to the Controller.

    • The Controller sends a ResponseEntity<ResponseDto> containing the error message to the User.

6.6.2. Endpoint

Description

This endpoint allows you to update an executed contract based on the provided contract data.

URL

/contracts/updateContract/{contractUUID}

Method

POST

Request parameters

Parameters

Type

Required

Description

contractUUID

UUID

Yes

The UUID of the contract to be updated.

Request body

The request body should contain a JSON array of objects, each representing data for updating a contract. The structure of each object should adhere to the TermsDto format.

Example request body

{
  "notionalPrincipal": 60000
}

Response

  • 200 : Success. Returns a JSON response containing details of the updated contracts.

Example response body

{
  "status": 200,
  "message": "Contract Rescheduled",
  "data": "36c7d13e-55dc-4b89-a1b8-98f1f8716698"
}
  • 400 bad request

Example

{
  "status": 400,
  "message": "Invalid contractUUID",
  "data": "36c7d13e-55dc-4b89-a1b8-98f1f8716698"
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions to create contracts.

  • 5xx server error: If there is a server-side error while processing the request.

  • The updationData should contain the necessary fields required for updating the contract.

  • The request body json only allows the values which are in the TermsDto model class.

6.6.3. Methods

Description

The updateExecutedContract method updates an executed contract based on the provided contract UUID and data.

Method signature

public void updateExecutedContract(String contractUUID, TermsDto updationData)
    throws ContractsException, IllegalAccessException, ParseException

Parameters

  • contractUUID (UUID): The UUID of the contract to be updated.

  • updationData (TermsDto): The data used for updating the contract

Returns

  • contractUUID (UUID): The contractUUID of which the contract has been updated.

Exceptions

  • ContractsException : Thrown if there is an issue with the contract.

  • IllegalAccessException : Thrown if there is illegal access during contract update.

  • ParseException : Thrown if there is an error while parsing data.

Usage example

public void updateExecutedContract(UUID contractUUID, TermsDto updationData)
			throws ContractsException, IllegalAccessException, ParseException {

		// Validate the executed contract data before updating.
		updateContractValidator.validateExecutedContractData(contractUUID, updationData); (1)

		// Perform the actual contract update.
		contractsWorker.updateExecutedContract(contractUUID, updationData); (2)

	}


public void updateExecutedContract(UUID contractUUID, TermsDto updationData)
			throws IllegalAccessException, ParseException {
		log.info("Contract update started by UserId : {}, ContractUUID : {}, Request : {}", usersHelper.getUserID(),
				contractUUID, updationData);
		// Retrieve the executed contract by its UUID.
		Contracts contract = contractsServiceRepo.findById(contractUUID)
				.orElseThrow(() -> new IllegalArgumentException(CONTRACT_ERROR)); (3)

		// Save a history snapshot of the contract before updating.
		saveContractHistory(contract); (4)

		// Update the contract data based on the provided data.
		updateContractData(contract, updationData); (5)

		// Reschedule events associated with the updated contract.
		rescheduleEvents(contract); (6)
		contractsServiceRepo.save(contract); (7)

		log.info("Contract update finished by UserId : {}, ContractUUID : {}", usersHelper.getUserID(), contractUUID);
	}
Internal workflow
1 Validates the executed contract data before updating.
2 Performs the actual contract update.
3 Retrieves the executed contract by its UUID.
4 Saves a history snapshot of the contract before updating.
5 Updates the contract data based on the provided data.
6 Reschedules events associated with the updated contract.
7 Saves the updated contract.

6.6.4. Model classes

Description

The TermsDto class serves as a data transfer object (DTO) that encapsulates various terms and details associated with a contract. It is designed to facilitate the transfer of contract-related information between different components of the application.

Attributes
  1. contractPerformance

    • Type: String

    • Description: Indicates the performance status of the contract.

    • Example: "PreDeal"

  2. calendar

    • Type: String

    • Description: Specifies the calendar system used for scheduling events related to the contract.

    • Example: "Monday to Friday"

  3. businessDayConvention

    • Type: String

    • Description: Defines the method for adjusting dates that fall on non-business days.

    • Example: "SCF"

  4. endOfMonthConvention

    • Type: String

    • Description: Specifies how end-of-month dates are handled in calculations.

    • Example: "EOM"

  5. contractType

    • Type: String

    • Description: Identifies the type or category of the contract.

    • Example: "PAM"

  6. statusDate

    • Type: LocalDateTime

    • Description: Represents the date at which the status of the contract was last updated.

    • Example: "2022-12-31 00:00:00"

  7. contractRole

    • Type: String

    • Description: Specifies the role of the contract in a transaction or relationship.

    • Example: "RPA"

  8. creatorID

    • Type: String

    • Description: Identifier of the user or system that created the contract.

    • Example: "902375cc-4f72-428f-8db0-95a7baa69b51"

  9. counterpartyID

    • Type: String

    • Description: Identifier of the counterparty involved in the contract.

    • Example: "d2c87ded-489e-4510-8fe1-95f12c048a5d"

  10. contractID

    • Type: String

    • Description: Unique identifier for the contract.

    • Example: "9ec8997e-70b5-4fa1-82fe-56cbc0fc8149"

click to see more…​.
  1. marketObjectCodeOfDividends

    • Type: String

    • Description: Code or identifier for the market object related to dividends.

    • Example: "DIV"

  2. cycleAnchorDateOfFee

    • Type: LocalDateTime

    • Description: Date used as a reference point for fee calculation cycles.

    • Example: "2023-01-01T00:00:00"

  3. cycleOfFee

    • Type: String

    • Description: Specifies the frequency or pattern of fee payments.

    • Example: "1M"

  4. feeBasis

    • Type: String

    • Description: Basis or method used for calculating fees.

    • Example: "A"

  5. feeRate

    • Type: BigDecimal

    • Description: Rate at which fees are applied, usually expressed as a percentage.

    • Example: 2500.00

  6. feeAccrued

    • Type: BigDecimal

    • Description: Total amount of fees accrued up to the present time.

    • Example: 1000.0

  7. cycleAnchorDateOfInterestPayment

    • Type: LocalDateTime

    • Description: Date serving as a reference point for interest payment cycles.

    • Example: "2023-01-21T06:30:00"

  8. arrayCycleAnchorDateOfInterestPayment

    • Type: String

    • Description: An array containing multiple cycle anchor dates of interest payments.

    • Example: ["2023-01-21T06:30:00", "2023-06-01T06:30:00", "2023-07-26T06:30:00"]

  9. cycleOfInterestPayment

    • Type: String

    • Description: Frequency or pattern of interest payments.

    • Example: "P1ML1"

  10. arrayCycleOfInterestPayment

    • Type: String

    • Description: An array containing multiple cycles of interest payments.

    • Example: ["1M", "6M"]

  11. nominalInterestRate

    • Type: BigDecimal

    • Description: Nominal interest rate applied to the principal.

    • Example: 0.01

  12. nominalInterestRate2

    • Type: BigDecimal

    • Description: Additional nominal interest rate, if applicable.

    • Example: 0.03

  13. dayCountConvention

    • Type: String

    • Description: Method used for calculating the number of days between two dates.

    • Example: "30E360"

  14. accruedInterest

    • Type: BigDecimal

    • Description: Total amount of interest accrued up to the present time.

    • Example: 500.0

  15. capitalizationEndDate

    • Type: LocalDateTime

    • Description: Date when interest capitalization ends.

    • Example: "2024-12-31T23:59:59"

  16. cycleAnchorDateOfInterestCalculationBase

    • Type: LocalDateTime

    • Description: Date used as a reference point for interest calculation.

    • Example: "2024-03-01T00:00:00"

  17. cycleOfInterestCalculationBase

    • Type: String

    • Description: Frequency or pattern of interest calculation.

    • Example: "P1ML1"

  18. interestCalculationBase

    • Type: String

    • Description: Specifies the base amount or balance used for interest calculation.

    • Example: "NT"

  19. interestCalculationBaseAmount

    • Type: BigDecimal

    • Description: Amount used as the base for interest calculation.

    • Example: 10000.0

  20. cyclePointOfInterestPayment

    • Type: String

    • Description: Specifies the point within each interest period when interest payments are made.

    • Example: "E"

  21. currency

    • Type: String

    • Description: The currency in which monetary values are expressed.

    • Example: "USD"

  22. currency2

    • Type: String

    • Description: Another currency, if applicable.

    • Example: "EUR"

  23. amortizationDate

    • Type: LocalDateTime

    • Description: Date when the principal is scheduled to be repaid.

    • Example: "2024-12-31T23:59:59"

  24. contractDealDate

    • Type: LocalDateTime

    • Description: Date when the contract was executed or agreed upon.

    • Example: "2024-03-01T00:00:00"

  25. initialExchangeDate

    • Type: LocalDateTime

    • Description: Date of the initial exchange or transaction related to the contract.

    • Example: "2024-03-01T00:00:00"

  26. maturityDate

    • Type: LocalDateTime

    • Description: Date when the contract reaches maturity or expires.

    • Example: "2024-12-31T23:59:59"

  27. notionalPrincipal

    • Type: BigDecimal

    • Description: The principal amount on which interest is calculated.

    • Example: 100000.0

  28. notionalPrincipal2

    • Type: BigDecimal

    • Description: Another principal amount, if applicable.

    • Example: 50000.0

  29. quantity

    • Type: String

    • Description: Quantity or amount associated with the contract.

    • Example: "3"

  30. cycleAnchorDateOfPrincipalRedemption

    • Type: LocalDateTime

    • Description: Date used as a reference point for principal redemption cycles.

    • Example: "2024-03-01T00:00:00"

  31. arrayCycleAnchorDateOfPrincipalRedemption

    • Type: String

    • Description: An array containing multiple cycle anchor dates of principal redemption.

    • Example: ["2024-01-01", "2024-04-01", "2024-07-01"]

  32. cycleOfPrincipalRedemption

    • Type: String

    • Description: Frequency or pattern of principal redemption.

    • Example: "P1ML1"

  33. arrayCycleOfPrincipalRedemption

    • Type: String

    • Description: An array containing multiple cycles of principal redemption.

    • Example: ["1M", "6M"]

  34. nextPrincipalRedemptionPayment

    • Type: BigDecimal

    • Description: Next scheduled payment for principal redemption.

    • Example: 1000.0

  35. arrayNextPrincipalRedemptionPayment

    • Type: String

    • Description: An array containing multiple next principal redemption payments.

    • Example: ["1000.0", "500.50", "750.25"]

  36. arrayIncreaseDecrease

    • Type: String

    • Description: An array containing information about increases or decreases in certain aspects of the contract.

    • Example: "INC"

  37. purchaseDate

    • Type: LocalDateTime

    • Description: Date when the contract was purchased or acquired.

    • Example: "2024-03-01T00:00:00"

  38. priceAtPurchaseDate

    • Type: BigDecimal

    • Description: Price of the contract at the time of purchase.

    • Example: 100.0

  39. terminationDate

    • Type: LocalDateTime

    • Description: Date when the contract is terminated or ends.

    • Example: "2024-12-31T23:59:59"

  40. priceAtTerminationDate

    • Type: BigDecimal

    • Description: Price of the contract at the time of termination.

    • Example: 90.0

  41. marketObjectCodeOfScalingIndex

    • Type: String

    • Description: Code or identifier for the market object related to scaling index.

    • Example: "SCAL-001"

  42. scalingIndexAtContractDealDate

    • Type: BigDecimal

    • Description: Scaling index value at the contract deal date.

    • Example: 120.0

  43. cycleAnchorDateOfScalingIndex

    • Type: LocalDateTime

    • Description: Date used as a reference point for scaling index cycles.

    • Example: "2024-03-01T00:00:00"

  44. cycleOfScalingIndex

    • Type: String

    • Description: Frequency or pattern of scaling index adjustments.

    • Example: "3M"

  45. scalingEffect

    • Type: String

    • Description: Effect or impact of scaling on the contract.

    • Example: "0N0"

  46. cycleAnchorDateOfRateReset

    • Type: LocalDateTime

    • Description: Date used as a reference point for rate reset cycles.

    • Example: "2024-03-01T00:00:00"

  47. arrayCycleAnchorDateOfRateReset

    • Type: String

    • Description: An array containing multiple cycle anchor dates of rate reset.

    • Example: ["2024-01-01", "2024-04-01", "2024-07-01"]

  48. cycleOfRateReset

    • Type: String

    • Description: Frequency or pattern of rate resets.

    • Example: "Monthly", "Quarterly", "Annually"

  49. arrayCycleOfRateReset

    • Type: String

    • Description: An array containing multiple cycles of rate resets.

    • Example: ["1M","1Y"]

  50. rateSpread

    • Type: BigDecimal

    • Description: Additional interest rate spread applied to a benchmark rate.

    • Example: 0.02

  51. arrayRate

    • Type: String

    • Description: An array containing multiple interest rates.

    • Example: ["0.05", "0.06", "0.04"]

  52. arrayFixedVariable

    • Type: String

    • Description: An array indicating whether interest rates are fixed or variable.

    • Example: "F"

  53. marketObjectCodeOfRateReset

    • Type: String

    • Description: Code or identifier for the market object related to rate reset.

    • Example: "e4d7d42c-f11a-4ff3-886f-5bf36db3bac9"

  54. cyclePointOfRateReset

    • Type: String

    • Description: Specifies the point within each interest period when rate resets occur.

    • Example: "B"

  55. fixingPeriod

    • Type: String

    • Description: Period during which interest rates are fixed.

    • Example: "3M"

  56. nextResetRate

    • Type: BigDecimal

    • Description: Next scheduled rate after a reset.

    • Example: 0.07

  57. rateMultiplier

    • Type: BigDecimal

    • Description: Multiplier applied to a reference rate to determine the interest rate.

    • Example: 1.5

  58. settlementPeriod

    • Type: LocalDateTime

    • Description: Period during which settlement occurs.

    • Example: "2024-03-01T00:00:00"

  59. deliverySettlement

    • Type: String

    • Description: Method or process used for delivery settlement.

    • Example: "S"

  60. marketValueObserved

    • Type: BigDecimal

    • Description: Observed market value of the contract.

    • Example: 10000.0

  61. premiumDiscountAtIED

    • Type: BigDecimal

    • Description: Premium or discount applied at the initial exchange date (IED).

    • Example: 500.0

  62. cycleAnchorDateOfOptionality

    • Type: LocalDateTime

    • Description: Date used as a reference point for optionality cycles.

    • Example: "2024-03-01T00:00:00"

  63. cycleOfOptionality

    • Type: String

    • Description: Frequency or pattern of optionality.

    • Example: "P1ML1"

  64. lifeCap

    • Type: BigDecimal

    • Description: Maximum cap on interest rates over the life of the contract.

    • Example: 0.08

  65. lifeFloor

    • Type: BigDecimal

    • Description: Minimum floor on interest rates over the life of the contract.

    • Example: 0.03

  66. penaltyType

    • Type: String

    • Description: Type or category of penalty associated with the contract.

    • Example: "N"

  67. penaltyRate

    • Type: BigDecimal

    • Description: Rate at which penalties are applied, usually expressed as a percentage.

    • Example: 0.05

  68. objectCodeOfPrepaymentModel

    • Type: String

    • Description: Code or identifier for the prepayment model object.

    • Example: "PREPAY-MODEL"

  69. periodCap

    • Type: BigDecimal

    • Description: Maximum cap on interest rates for a specific period.

    • Example: 0.08

  70. periodFloor

    • Type: BigDecimal

    • Description: Minimum floor on interest rates for a specific period.

    • Example: 0.03

  71. marketObjectCode

    • Type: String

    • Description: Code or identifier for the market object associated with the contract.

    • Example: "YC.USA.TREASURY"

  72. cycleAnchorDateOfDividendPayment

    • Type: LocalDateTime

    • Description: Date used as a reference point for dividend payment cycles.

    • Example: "2024-03-01T00:00:00"

  73. cycleOfDividendPayment

    • Type: String

    • Description: Frequency or pattern of dividend payments.

    • Example: "1Q"

  74. tenure

    • Type: String

    • Description: Duration or term of the contract.

    • Example: "5Y"

  75. roundingConvention

    • Type: String

    • Description: Method used for rounding numerical values in calculations.

    • Example: "Half Up"

  76. xDayNotice

    • Type: String

    • Description: Notice period required for certain actions or events.

    • Example: "30D"

  77. maximumPenaltyFreeDisbursement

    • Type: String

    • Description: Maximum amount that can be disbursed without incurring penalties.

    • Example: "10000"

  78. delinquencyPeriod

    • Type: String

    • Description: Period during which a payment is considered delinquent.

    • Example: "30D"

  79. gracePeriod

    • Type: String

    • Description: Period of time after a payment is due before penalties are applied.

    • Example: "7D"

  • Not all attributes may be necessary for every contract scenario, and developers should tailor the usage of attributes based on specific contract requirements.

6.6.5. Validation

Description

The validateExecutedContractData method is responsible for validating the data associated with an executed contract. This ensures the integrity and accuracy of the contract information before any further processing is performed.

Parameters

  • Contract UUID (Type: UUID) : The UUID of the executed contract to be validated.

  • updationContractTerms (Type: TermsDto) : Contains the updated contract terms to be validated.

Returns

  • Returns the master contract terms associated with the provided UUID.

Example usage

public void validateExecutedContractData(UUID contractUUID, TermsDto updationContractTerms)
			throws ContractsException {
		// Validate the contract UUID and retrieve the contract.
		Contracts contract = contractsValidator.validateContractUUID(contractUUID); (1)
		Terms masterContractTerms = contract.getContractTerms().get(0);

		// Validate the updated contract terms against the master contract terms.
		validateContractUpdateTerms(masterContractTerms, updationContractTerms); (2)
	}
1 Contract UUID validation
  • Verify that the provided contract UUID exists in the system.

  • Retrieve the master contract terms associated with the provided UUID.

2 Updated contract terms validation
  • Compare the updated contract terms (updationContractTerms) against the master contract terms (masterContractTerms) retrieved from the database.

    1. InitialExchangeDate update restriction

      1. If InitialExchangeDate is being updated, the update is disallowed.

    2. ContractDealDate update restriction

      1. If ContractDealDate is being updated, the update is disallowed.

    3. StatusDate validation

      1. If StatusDate is provided:

      2. It must not be set to a date before the current StatusDate.

      3. It must not be set to a date before InitialExchangeDate.

Error handling

  • If the contract UUID is invalid or does not exist, a ContractsException is thrown with an appropriate error message.

  • If the updated contract terms do not align with the master contract terms, validation fails and a ContractsException is thrown.

6.6.6. Testing

Description

This section provides an overview of the testing strategy and objectives for the update executed contract method.

Test methods

Example usage

@TestFactory
	Stream<DynamicTest> updatePFContractBeforeTest() throws IOException { (1)
		List<DynamicTest> dynamicTests = new ArrayList<>();

		List<BusinessEventsDto> expectedEventsList = MappingUtils
				.mapToEventsList("./src/test/resources/events/events-contract-ann.json");

		List<BusinessEvents> computedEventsList = eventsRepo.findByContractUUID(contracts);
		Assertions.assertEquals(expectedEventsList.size(), computedEventsList.size(), "Number of events should match.");

		for (int i = 0; i < expectedEventsList.size(); i++) {
			BusinessEventsDto expectedEvent = expectedEventsList.get(i);
			BusinessEvents computedEvent = computedEventsList.get(i);

			dynamicTests.add(contractUtils.createDynamicTest(expectedEvent, computedEvent));
		}

		return dynamicTests.stream();
	}

	@TestFactory
	Stream<DynamicTest> updatePFContractAfterTest()
			throws IOException, ParseException, IllegalAccessException, ContractsException, InterruptedException { (2)
		List<DynamicTest> dynamicTests = new ArrayList<>();

		List<BusinessEventsDto> expectedEventsList = MappingUtils
				.mapToEventsList("./src/test/resources/events/updated-events-contract-ann.json");

		updatePFContractTest();
		List<BusinessEvents> computedEventsList = eventsRepo.findByContractUUID(contracts);

		Assertions.assertEquals(expectedEventsList.size(), computedEventsList.size(), "Number of events should match.");

		for (int i = 0; i < expectedEventsList.size(); i++) {
			BusinessEventsDto expectedEvent = expectedEventsList.get(i);
			BusinessEvents computedEvent = computedEventsList.get(i);

			dynamicTests.add(contractUtils.createDynamicTest(expectedEvent, computedEvent));
		}

		return dynamicTests.stream();
	}
1 updatePFContractBeforeTest
  • Purpose : This test evaluates the behavior of updating a PF contract before specific events.

  • Test steps

    1. Data preparation: Load expected business events from a JSON file (events-contract-ann.json).

    2. Retrieve computed events: Fetch computed business events associated with contracts from the repository.

    3. Assertion: Verify that the number of expected events matches the number of computed events.

    4. Dynamic test generation: Iterate through each pair of expected and computed events, creating dynamic tests to compare their properties.

2 updatePFContractAfterTest
  • Purpose : This test evaluates the behavior of updating a PF contract after specific events.

  • Test steps

    1. Data preparation: Load expected business events after contract updates from a JSON file (updated-events-contract-ann.json).

    2. Invoke contract update: Call the updatePFContractTest() method to perform the contract update operation.

    3. Retrieve computed events: Fetch computed business events associated with contracts from the repository after the update.

    4. Assertion: Verify that the number of expected events matches the number of computed events.

    5. Dynamic test generation: Iterate through each pair of expected and computed events, creating dynamic tests to compare their properties.

  • Assertions

    • Number of events: Assert that the number of expected business events matches the number of computed events. This ensures that all events associated with the contracts are generated and handled correctly.

    • Properties comparison: For each pair of expected and computed events, dynamically generated tests compare their properties (e.g., event type, timestamp, associated contract UUID). Any discrepancies between expected and computed events will result in test failures, indicating potential issues with the contract update process or event handling logic.

6.7. Create dynamic event

6.7.1. Sequential flow

create-dynamic-event.puml

Steps to create dynamic event

  1. Receive request

    • The system receives a request from the user to create a dynamic event.

  2. Validate data

    • The system validates the provided contract UUID and event date.

      • If the contract UUID is invalid or doesn’t exist, an error is returned.

      • If the event date is after the maturity date or future events are already processed, an error is returned.

  3. Create dynamic event

    • If the data is valid, the system creates a dynamic event based on the provided data.

  4. Save event

    • The system saves the created dynamic event.

  5. Respond to user

    • A response containing information about the created dynamic event is sent back to the user.

6.7.2. Endpoint

Description

This endpoint is used to create a dynamic event associated with a contract.

URL

/contracts/newEvent/{contractUUID}

Method

POST

Request parameters

Parameters

Type

Required

Description

contractUUID

UUID

Yes

The unique identifier of the contract.

Request body

The request body should contain a JSON array of objects, each representing data for creating a dynamic event. The structure of each object should adhere to the DynamicEventDto format.

Example request body

{
  "time": "2024-02-23T06:30",
  "type": "TP",
  "value": 5000
}

Response

  • 200 : Success. Returns a JSON response containing UUID of the created dynamic event.

Example response body

{
  "status": 200,
  "message": "Event created successfully",
  "data": "36c7d13e-55dc-4b89-a1b8-98f1f8716698"
}
  • 400 bad request

Example

{
  "status": 400,
  "message": "Invalid contractUUID 36c7d13e-55dc-4b89-a1b8-98f1f8716698",
  "data": null
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions to create contracts.

  • 5xx server error: If there is a server-side error while processing the request.

  • Ensure the contract UUID is valid and exists in the system before creating the dynamic event.

  • The request body json only allows the values which are in the DynamicEventDto model class.

6.7.3. Methods

Description

This method is responsible for creating a dynamic event associated with a contract.

  1. Method : validateDynamicEventData

    • Purpose

      • This method validates the dynamic event data and checks for any future events already processed.

    • Parameters

      • dynamicEventData (Type: DynamicEventDto) : JSON data representing the dynamic event.

      • contractUUID (Type: String) : The unique identifier of the contract.

    • Return type

      • Contracts - The validated contract associated with the dynamic event.

        public Contracts validateDynamicEventData(DynamicEventDto dynamicEventData, UUID contractUUID) {
        		Contracts contract = validateContractUUID(contractUUID); (1)
        
        		validateEventDateWithMaturityDate(dynamicEventData, contract); (2)
        
        		final Integer futureProcessed = eventsRepo.countByContractUUIDAndStatusAndEventTimeGreaterThan(contract,
        				"processed", dynamicEventData.getTime());
        		// Check if there are any future events already processed. If so, throw an
        		// exception.
        		Assert.isTrue(futureProcessed == 0, "Future events already processed"); (3)
        		return contract; (4)
        	}
    • Behavior

    1 Calls validateContractUUID method to validate the contract UUID.
    2 Validates the event date with the maturity date of the contract.
    3 Checks if there are any future events already processed.
    4 Returns the validated contract.
  2. Method : createDynamicEvent

    • Purpose

      • This method creates a dynamic event based on the provided data and contract.

    • Parameters

      • dynamicEventData (Type: DynamicEventDto) : JSON data representing the dynamic event.

      • contract (Type: Contracts) : The contract associated with the dynamic event.

    • Return type

      • DynamicEventResponseDto : Response containing information about the created dynamic event.

        public DynamicEventResponseDto createDynamicEvent(DynamicEventDto dynamicEventData, Contracts contract) {
        		log.info("Dynamic event creation started by UserId : {}, ContractUUID : {}, Request : {} ",
        				usersHelper.getUserID(), contract.getContractUUID(), dynamicEventData);
        
        		// Create a dynamic event based on the provided data and contract.
        		BusinessEvents dynamicEvent = eventsHelper.createDynamicEvent(dynamicEventData, contract); (1)
        
        		// Update the status of the dynamic event.
        		eventsHelper.updateEventStatus(dynamicEvent); (2)
        
        		// Save the dynamic event .
        		businessEventsService.save(dynamicEvent); (3)
        
        		log.info("Dynamic event created by UserId : {}, ContractUUID : {}, EventId: {} ", usersHelper.getUserID(),
        				contract.getContractUUID(), dynamicEvent.getEventID());
        
        		return new DynamicEventResponseDto("Event created", dynamicEvent.getEventID(), dynamicEvent.getEventBody()); (4)
        	}
    • Behavior

    1 Creates a dynamic event using the provided data and contract by calling createDynamicEvent method from the EventsHelper component.
    2 Updates the status of the dynamic event using the EventsHelper component.
    3 Saves the dynamic event using the BusinessEventsService component.
    4 Returns a DynamicEventResponseDto containing information about the created dynamic event.

6.7.4. Model classes

Description

The DynamicEventDto class represents the data transfer object (DTO) for a dynamic event. It encapsulates the attributes necessary to create a dynamic event.

Attributes
  1. time

    • Type: LocalDateTime

    • Description: Represents the time of the dynamic event.

    • Constraints: Cannot be null.

    • Example: "2024-02-23T06:30"

  2. type

    • Type: String

    • Description: Represents the type of the dynamic event.

    • Constraints: Cannot be null.

    • Example: "TP"

  3. value

    • Type: BigDecimal

    • Description: Represents the value associated with the dynamic event.

    • Constraints: Cannot be null.

    • Example: 5000

  4. contractID

    • Type: String

    • Description: Represents the unique identifier of the contract associated with the dynamic event.

    • Constraints: None specified.

    • Example: "1234567890"

Usage example

		BusinessEvents businessEvents = new BusinessEvents();
		businessEvents.setEventTime(UtilityHelper.toLocalDateTime(dynamicEventData.getTime()).toString());
		businessEvents.setEventType(dynamicEventData.getType());
		businessEvents.setEventBody(determineEventBodyForDynamicEvent(contract, term, dynamicEventData));
		businessEvents.setStatus("scheduled");
		businessEvents.setExecutionType(determineExecutionTypeForDynamicEvent(dynamicEventData.getType()));
		businessEvents.setUserID(term.getCreatorID());
		businessEvents.setCreatedBy(contract.getCreatedBy());
		businessEvents.setContractUUID(contract);
		businessEvents.setContractID(contractId);
  • The DynamicEventDto class is used to create a new business events object which is used to create a dynamic event.

6.7.5. Validation

Description

The method validateContract(UUID contractUUID) validates dynamic event data against a given contract.

  • Parameters

    • dynamicEventData : A DTO representing dynamic event data.

    • contractUUID : The UUID of the contract to be validated.

  • Returns

    • Returns the validated Contracts object representing the contract associated with the provided UUID.

  • Functionality

    • It ensures that the event date is valid with respect to the contract’s maturity date.

    • It ensures that no future events have already been processed.

  • Exceptions

    • If future events are found to be already processed, an IllegalStateException is thrown with the message "Future events already processed".

  • Example usage

public Contracts validateDynamicEventData(DynamicEventDto dynamicEventData, UUID contractUUID) {
		Contracts contract = validateContractUUID(contractUUID); (1)

		validateEventDateWithMaturityDate(dynamicEventData, contract); (2)

		final Integer futureProcessed = eventsRepo.countByContractUUIDAndStatusAndEventTimeGreaterThan(contract,
				"processed", dynamicEventData.getTime());
		// Check if there are any future events already processed. If so, throw an
		// exception.
		Assert.isTrue(futureProcessed == 0, "Future events already processed"); (3)
		return contract;
	}
Validation steps
1 Contract UUID validation
  • Validates the existence of the contract associated with the provided UUID.

  • Calls validateContractUUID method to ensure the validity of the contract UUID.

2 Event date validation
  • Validates if the event date is within the maturity date of the contract.

  • Calls validateEventDateWithMaturityDate method to perform this validation.

3 Future processed events check
  • Checks if there are any future events already processed for the contract.

  • Utilizes a repository method (countByContractUUIDAndStatusAndEventTimeGreaterThan) to count the number of future processed events.

  • Throws an exception if any future events are found to be already processed.

6.7.6. Testing

Description

This section provides an overview of the testing strategy and objectives for the create dynamic event method.

Test methods

Example usage

@Test
	void createDynamicEventTest() throws ContractsException { (1)

		Response<UUID> dynamicEventResponseDto = contractServiceImpl.createDynamicEvent(dynamicEventDto,
				contractUUID);
		BusinessEvents dynamicEvent = eventsHelper.createDynamicEvent(dynamicEventDto, contract);
		BigDecimal eventValue = dynamicEvent.getValue() ;
		UUID creditPaymentChannel = dynamicEvent.getCreditPaymentChannelID();
		UUID debitPaymentChannel = dynamicEvent.getDebitPaymentChannelID();

		PaymentDetails paymentDetails = contract.getPaymentDetails();

		assertEquals("Event created successfully", dynamicEventResponseDto.getMessage());
		assertEquals(value.doubleValue(), eventValue.doubleValue(), 0.0);
		assertEquals(paymentDetails.getCounterpartyPaymentChannelID(), creditPaymentChannel);
		assertEquals(paymentDetails.getRecordCreatorPaymentChannelID(), debitPaymentChannel);

	}
1 createDynamicEventTest()
  • Purpose : The purpose of this test is to ensure that the createDynamicEvent() method correctly creates dynamic events and returns the expected response.

  • Test steps

    1. Invoke the createDynamicEvent() method with a dynamicEventDto and a contractUUID converted to string.

    2. Retrieve the event body from the response DTO.

    3. Extract the event value, credit payment channel, and debit payment channel from the event body.

    4. Retrieve payment details from the contract.

  • Assertions

    • Verify that the event value matches the expected value of 500 with a tolerance of 0.0.

    • Assert that the credit payment channel matches the payment channel ID of the counterparty in the payment details.

    • Assert that the debit payment channel matches the payment channel ID of the record creator in the payment details.

Transactions

1. Introduction

The transactions service allows registering or processing events and updating the contract accordingly.

2. Tables and relations

Establishing relationships

  • In relational databases like PostgreSQL, relationships between tables are crucial for organizing and querying data effectively. These relationships are typically established using foreign key constraints, which define links between tables based on the values of specific columns. Common types of relationships include one-to-one, one-to-many, and many-to-many relationships, each serving different data modeling needs.

transactions ERD
Figure 2. Transactions Entity-relationship diagram

Tables

  • Schema

    1. Table business_events

      Index Name Data type

      * 🔑 ⬋

      eventid

      uuid

      *

      event_time

      timestamp

      * 🔎

      event_type

      varchar(10)

      event_body

      json

      * 🔎

      status

      varchar(10)

      * 🔎

      execution_type

      varchar(20)

      contractid

      varchar(255)

      *

      userid

      uuid

      * 🔎 ⬈

      contractuuid

      uuid

      value

      numeric

      remaining_value

      numeric

      credit_payment_channel_id

      uuid

      debit_payment_channel_id

      uuid

      units

      varchar(10)

      1. Foreign keys

        Type Name On

        fk_business_events_contracts_contractuuid

        contractuuid

      2. Constraints

        Name Definition

        business_events_event_type_check

        ((event_type)::text ~* ’^(AD

        business_events_status_check

        ((status)::text ~* ’^(scheduled

    2. Table contracts

      Index Name Data type

      * 🔑 ⬋

      contractuuid

      uuid

      productid

      bigint

      *

      createdby

      uuid

      executedby

      uuid

      *

      system_time

      timestamp

      selection

      json

      1. Foreign keys

        Type Name On

        contracts_product_fk

        productid

    3. Table contracts_history

      Index Name Data type

      * 🔑 ⬋

      contractuuid

      uuid

      * 🔑 ⬋

      status_date

      timestamp

      productid

      bigint

      selection

      json

      *

      system_time

      timestamp

    4. Table payment_channels

      Index Name Data type

      * 🔑 ⬋

      payment_channelid

      uuid

      contractid

      uuid

      details

      json

      *

      identifier

      varchar(100)

      label

      varchar(100)

      *

      type

      varchar(50)

      * 🔎

      owner_type

      varchar(10)

      *

      units

      varchar(10)

      *

      system

      varchar(50)

      account_characteristic

      varchar(50)

      * 🔎

      ownerid

      uuid

      * 🔎

      userid

      uuid

      1. Constraints

        Name Definition

        payment_channels_owner_type_check

        ((owner_type)::text ~* ’^(root

    5. Table payment_details

      Index Name Data type

      * 🔑

      id

      bigint GENERATED BY DEFAULT AS IDENTITY

      contract_uuid

      uuid

      record_creator_paymentchannel_id

      uuid

      counterparty_paymentchannel_id

      uuid

      contract_paymentchannel_id

      uuid

      1. Foreign keys

        Type Name On

        paymentdetails_contractuuid_fk

        contract_uuid

        paymentdetails_contract_payment_fk

        contract_paymentchannel_id

        paymentdetails_counterparty_fk

        counterparty_paymentchannel_id

        paymentdetails_record_creator_fk

        record_creator_paymentchannel_id

    6. Table products

      Index Name Data type

      * 🔑 ⬋

      productid

      bigint GENERATED BY DEFAULT AS IDENTITY

      *

      status

      varchar(10)

      *

      template

      json

      * 🔎

      userid

      uuid

      1. Constraints

        Name Definition

        products_status_check

        ((status)::text ~* ’^(active

    7. Table profile_forms

      Index Name Data type

      * 🔑 ⬋

      profile_formid

      bigint GENERATED BY DEFAULT AS IDENTITY

      *

      profile_form_details

      json

      *

      userid

      uuid

    8. Table profiles

      Index Name Data type

      * 🔑 ⬋

      profileid

      uuid

      profile_details

      json

      *

      status

      varchar(10)

      *

      userid

      uuid

      * ⬈

      profile_formid

      bigint

      1. Foreign keys

        Type Name On

        fk_profiles_profile_forms_profile_formid

        profile_formid

      2. Constraints

        Name Definition

        profiles_status_check

        ((status)::text ~* ’^(active

    9. Table terms

      Index Name Data type

      * 🔑

      id

      bigint GENERATED BY DEFAULT AS IDENTITY

      accrued_interest

      numeric

      amortization_date

      timestamp

      array_cycle_anchor_date_of_interest_payment

      varchar(255)

      array_cycle_anchor_date_of_principal_redemption

      varchar(255)

      array_cycle_anchor_date_of_rate_reset

      varchar(255)

      array_cycle_of_interest_payment

      varchar(255)

      array_cycle_of_principal_redemption

      varchar(255)

      array_cycle_of_rate_reset

      varchar(255)

      array_fixed_variable

      varchar(255)

      array_increase_decrease

      varchar(255)

      array_next_principal_redemption_payment

      varchar(255)

      array_rate

      varchar(255)

      business_day_convention

      varchar(5)

      calendar

      varchar(2)

      capitalization_end_date

      timestamp

      contract_deal_date

      timestamp

      contractid

      varchar(255)

      *

      contract_role

      varchar(6)

      contract_performance

      varchar(10)

      *

      contract_type

      varchar(15)

      *

      currency

      varchar(10)

      currency2

      varchar(10)

      cycle_anchor_date_of_dividend_payment

      timestamp

      cycle_anchor_date_of_fee

      timestamp

      cycle_anchor_date_of_interest_calculation_base

      timestamp

      cycle_anchor_date_of_interest_payment

      timestamp

      cycle_anchor_date_of_optionality

      timestamp

      cycle_anchor_date_of_principal_redemption

      timestamp

      cycle_anchor_date_of_rate_reset

      timestamp

      cycle_anchor_date_of_scaling_index

      timestamp

      cycle_of_dividend_payment

      varchar(10)

      cycle_of_fee

      varchar(10)

      cycle_of_interest_calculation_base

      varchar(10)

      cycle_of_interest_payment

      varchar(10)

      cycle_of_optionality

      varchar(10)

      cycle_of_principal_redemption

      varchar(10)

      cycle_of_rate_reset

      varchar(10)

      cycle_of_scaling_index

      varchar(10)

      cycle_point_of_interest_payment

      varchar(1)

      cycle_point_of_rate_reset

      varchar(1)

      *

      day_count_convention

      varchar(10)

      delivery_settlement

      varchar(1)

      end_of_month_convention

      varchar(5)

      fee_accrued

      numeric

      fee_basis

      varchar(1)

      fee_rate

      numeric

      fixing_period

      varchar(255)

      initial_exchange_date

      timestamp

      interest_calculation_base

      varchar(10)

      interest_calculation_base_amount

      numeric

      life_cap

      numeric

      life_floor

      numeric

      market_object_code

      varchar(255)

      market_object_code_of_dividend_rate

      varchar(255)

      market_object_code_of_rate_reset

      varchar(255)

      market_object_code_of_scaling_index

      varchar(255)

      market_value_observed

      numeric

      maturity_date

      timestamp

      maximum_penalty_free_disbursement

      varchar(255)

      next_principal_redemption_payment

      numeric

      next_reset_rate

      numeric

      nominal_interest_rate

      numeric

      nominal_interest_rate2

      numeric

      notional_principal

      numeric

      notional_principal2

      numeric

      object_code_of_prepayment_model

      varchar(255)

      penalty_rate

      numeric

      penalty_type

      varchar(1)

      period_cap

      numeric

      period_floor

      numeric

      premium_discount_atied

      numeric

      price_at_purchase_date

      numeric

      price_at_termination_date

      numeric

      purchase_date

      timestamp

      quantity

      numeric

      rate_spread

      numeric

      rounding_convention

      varchar(255)

      scaling_effect

      varchar(5)

      scaling_index_at_contract_deal_date

      numeric

      settlement_period

      varchar(255)

      status_date

      timestamp

      x_day_notice

      varchar(255)

      termination_date

      timestamp

      delinquency_period

      varchar(255)

      grace_period

      varchar(255)

      market_object_code_of_dividends

      varchar(255)

      rate_multiplier

      numeric

      * ⬈

      contract_uuid

      uuid

      counterparty_id

      uuid

      * 🔎

      creator_id

      uuid

      1. Foreign keys

        Type Name On

        terms_contractuuid_fk

        contract_uuid

        terms_counterparty_id_fk

        counterparty_id

      2. Constraints

        Name Definition

        terms_business_day_convention_check

        ((business_day_convention)::text ~* ’^(NOS

        terms_calendar_check

        ((calendar)::text ~* ’^(NC

        terms_fee_basis_check

        ((fee_basis)::text ~* ’^(A

        terms_delivery_settlement_check

        ((delivery_settlement)::text ~* ’^(D

        terms_cycle_of_dividend_payment_check

        cycle_of_dividend_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_interest_calculation_base_check

        cycle_of_interest_calculation_base)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_interest_payment_check

        cycle_of_interest_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_principal_redemption_check

        cycle_of_principal_redemption)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_rate_reset_check

        cycle_of_rate_reset)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_of_scaling_index_check

        cycle_of_scaling_index)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_cycle_point_of_interest_payment_check

        ((cycle_point_of_interest_payment)::text ~* ’^(B

        terms_contract_performance_check

        ((contract_performance)::text ~* ’^(PF

        terms_penalty_type_check

        ((penalty_type)::text ~* ’^(N

    10. Table terms_history

      Index Name Data type

      * 🔑

      id

      bigint GENERATED BY DEFAULT AS IDENTITY

      accrued_interest

      numeric

      amortization_date

      timestamp

      array_cycle_anchor_date_of_interest_payment

      varchar(255)

      array_cycle_anchor_date_of_principal_redemption

      varchar(255)

      array_cycle_anchor_date_of_rate_reset

      varchar(255)

      array_cycle_of_interest_payment

      varchar(255)

      array_cycle_of_principal_redemption

      varchar(255)

      array_cycle_of_rate_reset

      varchar(255)

      array_fixed_variable

      varchar(255)

      array_increase_decrease

      varchar(255)

      array_next_principal_redemption_payment

      varchar(255)

      array_rate

      varchar(255)

      business_day_convention

      varchar(5)

      calendar

      varchar(2)

      capitalization_end_date

      timestamp

      contract_deal_date

      timestamp

      contractid

      varchar(255)

      *

      contract_role

      varchar(6)

      contract_performance

      varchar(10)

      *

      contract_type

      varchar(15)

      *

      currency

      varchar(10)

      currency2

      varchar(10)

      cycle_anchor_date_of_dividend_payment

      timestamp

      cycle_anchor_date_of_fee

      timestamp

      cycle_anchor_date_of_interest_calculation_base

      timestamp

      cycle_anchor_date_of_interest_payment

      timestamp

      cycle_anchor_date_of_optionality

      timestamp

      cycle_anchor_date_of_principal_redemption

      timestamp

      cycle_anchor_date_of_rate_reset

      timestamp

      cycle_anchor_date_of_scaling_index

      timestamp

      cycle_of_dividend_payment

      varchar(10)

      cycle_of_fee

      varchar(10)

      cycle_of_interest_calculation_base

      varchar(10)

      cycle_of_interest_payment

      varchar(10)

      cycle_of_optionality

      varchar(10)

      cycle_of_principal_redemption

      varchar(10)

      cycle_of_rate_reset

      varchar(10)

      cycle_of_scaling_index

      varchar(10)

      cycle_point_of_interest_payment

      varchar(1)

      cycle_point_of_rate_reset

      varchar(1)

      *

      day_count_convention

      varchar(10)

      delivery_settlement

      varchar(1)

      end_of_month_convention

      varchar(5)

      fee_accrued

      numeric

      fee_basis

      varchar(1)

      fee_rate

      numeric

      fixing_period

      varchar(255)

      initial_exchange_date

      timestamp

      interest_calculation_base

      varchar(10)

      interest_calculation_base_amount

      numeric

      life_cap

      numeric

      life_floor

      numeric

      market_object_code

      varchar(255)

      market_object_code_of_dividend_rate

      varchar(255)

      market_object_code_of_rate_reset

      varchar(255)

      market_object_code_of_scaling_index

      varchar(255)

      market_value_observed

      numeric

      maturity_date

      timestamp

      maximum_penalty_free_disbursement

      varchar(255)

      next_principal_redemption_payment

      numeric

      next_reset_rate

      numeric

      nominal_interest_rate

      numeric

      nominal_interest_rate2

      numeric

      notional_principal

      numeric

      notional_principal2

      numeric

      object_code_of_prepayment_model

      varchar(255)

      penalty_rate

      numeric

      penalty_type

      varchar(1)

      period_cap

      numeric

      period_floor

      numeric

      premium_discount_atied

      numeric

      price_at_purchase_date

      numeric

      price_at_termination_date

      numeric

      purchase_date

      timestamp

      quantity

      numeric

      rate_spread

      numeric

      rounding_convention

      varchar(255)

      scaling_effect

      varchar(5)

      scaling_index_at_contract_deal_date

      numeric

      settlement_period

      varchar(255)

      x_day_notice

      varchar(255)

      termination_date

      timestamp

      delinquency_period

      varchar(255)

      grace_period

      varchar(255)

      market_object_code_of_dividends

      varchar(255)

      rate_multiplier

      numeric

      *

      creator_id

      uuid

      contractuuid

      uuid

      status_date

      timestamp

      1. Foreign keys

        Type Name On

        fk-contracts_history-terms_history

        contractuuid, status_date

      2. Constraints

        Name Definition

        terms_history_business_day_convention_check

        ((business_day_convention)::text ~* ’^(NOS

        terms_history_calendar_check

        ((calendar)::text ~* ’^(NC

        terms_history_fee_basis_check

        ((fee_basis)::text ~* ’^(A

        terms_history_delivery_settlement_check

        ((delivery_settlement)::text ~* ’^(D

        terms_history_cycle_of_dividend_payment_check

        cycle_of_dividend_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_history_cycle_of_interest_calculation_base_check

        cycle_of_interest_calculation_base)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_history_cycle_of_interest_payment_check

        cycle_of_interest_payment)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_history_cycle_of_principal_redemption_check

        cycle_of_principal_redemption)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_history_cycle_of_rate_reset_check

        cycle_of_rate_reset)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_history_cycle_of_scaling_index_check

        cycle_of_scaling_index)::text ~ `(([-]?)P(?:([-]?)Y)?(?:([-]?)M)?(?:([-]?)W)?(?:([-]?[0-9]+)D)?L(?:([0-1]?)'::text)

        terms_history_cycle_point_of_interest_payment_check

        ((cycle_point_of_interest_payment)::text ~* ’^(B

        terms_history_contract_performance_check

        ((contract_performance)::text ~* ’^(PF

        terms_history_penalty_type_check

        ((penalty_type)::text ~* ’^(N

    11. Table transactions

      Index Name Data type

      * 🔑

      transactionid

      uuid

      additional_information

      json

      *

      user_id

      uuid

      *

      credit_payment_channel_id

      uuid

      *

      debit_payment_channel_id

      uuid

      *

      process_time

      timestamp

      *

      value

      numeric

      *

      system_time

      timestamp

      *

      status

      varchar(15)

      *

      units

      varchar(10)

      * 🔑 ⬈

      eventid

      uuid

      1. Foreign keys

      Type Name On

      fk_transactions_business_events_eventid

      eventid

    (🔑) - Primary key

    (*) - Mandatory

    (⬈) - Foreign key

    (🔎) - Constraint

3. Dependencies and libraries

3.1. Dependencies

Description

The following dependencies are used in the project to provide various functionalities and features:

  1. spring-kafka

    • Purpose: Spring for Apache Kafka for building Kafka-based messaging systems.

    • Usage: Producing and consuming messages from Kafka topics.

  2. spring-cloud-starter-openfeign

    • Purpose: The spring-cloud-starter-openfeign dependency is used in Spring Boot applications to simplify the process of creating REST clients. It integrates the Feign client library into your application, providing a declarative way to define RESTful service clients.

    • Usage: Use spring-cloud-starter-openfeign to define interfaces for RESTful services and easily make HTTP requests to those services. Feign handles the creation of the HTTP request and mapping of the response to Java objects, reducing the boilerplate code typically required for REST client implementations.

  3. spring-cloud-starter-loadbalancer

    • Purpose: The spring-cloud-starter-loadbalancer dependency is used in Spring Boot applications to provide client-side load balancing. It integrates with Spring Cloud’s load balancing features, allowing applications to distribute traffic across multiple instances of a service.

    • Usage: Use spring-cloud-starter-loadbalancer to enable client-side load balancing in your application. It provides a simple API for making requests to services registered with a service registry (e.g., Eureka), automatically handling the load balancing logic. This helps improve the availability and scalability of your application by distributing traffic evenly across service instances.

  4. modelmapper (version 0.7.5)

    • Purpose: The modelmapper dependency simplifies the process of mapping objects between different data models by automatically determining how properties should be mapped from one object to another.

    • Usage: Use modelmapper to streamline the mapping process between DTOs (Data Transfer Objects), entities, and other data models, reducing the need for manual mapping code and improving code maintainability.

  5. BlockCypher (version 2.0)

    • Purpose: Provides access to BlockCypher APIs for blockchain integration.

    • Usage: Requires a Blockcypher API token. Use the library to make API calls for tasks like:

      • Accessing blockchain data (transactions, blocks)

      • Managing wallets and addresses (create, send/receive bitcoins)

  6. iban4j (version 3.2.1)

    • Purpose: Provides utilities for working with International Bank Account Numbers (IBANs).

    • Usage: The iban4j library allows you to:

      • Validate IBANs: Verify if a string is a valid IBAN.

      • (Optional) Generate IBANs: Create a valid IBAN (less common).

      • Extract information from IBANs: Parse an IBAN to retrieve details like country code, bank code, and account number.

  • Dependency versions are specified to ensure compatibility and stability.

  • Additional dependencies may be added or removed based on project requirements and architecture.

3.2. Libraries

Description

The following libraries are used in the project to provide various functionalities and features:

  1. actus-core (version 1.0.1)

    • Purpose: The actus-core library provides core functionality and utilities for working with financial contracts and cash flow projections based on the ACTUS standard.

    • Usage: Use to perform calculations, projections, and analysis of financial contracts and cash flows according to the ACTUS (Algorithmic Contract Types Unified Standards) standard.

  • Library versions are specified to ensure compatibility and stability.

  • Additional libraries may be added or removed based on project requirements and architecture.

4. Exception handling

Description

The RestExceptionHandler class is responsible for handling various exceptions that may occur during the execution of RESTful API endpoints. It provides centralized exception handling to ensure consistent error responses across the application.

Exception handlers

Example usage

@ControllerAdvice
public class RestExceptionHandler {

	@ExceptionHandler({ TransactionException.class, IllegalArgumentException.class, TransactionSystemException.class,
			HttpMessageNotReadableException.class })
	public ResponseEntity<Response<String>> exceptionToDoHandler(Exception ex) { (1)
		final Response<String> error = new Response<>();
		error.setStatus(HttpStatus.BAD_REQUEST.value());
		error.setMessage(ex.getMessage());
		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

	@ExceptionHandler(MethodArgumentNotValidException.class)
	public ResponseEntity<Response<List<String>>> handleValidationException(MethodArgumentNotValidException ex) { (2)
		BindingResult bindingResult = ex.getBindingResult();
		List<FieldError> fieldErrors = bindingResult.getFieldErrors();

		List<String> errorMessages = fieldErrors.stream()
				.map(fieldError -> String.format("%s: %s", fieldError.getField(), fieldError.getDefaultMessage()))
				.toList();

		Response<List<String>> error = new Response<>();
		error.setStatus(HttpStatus.BAD_REQUEST.value());
		error.setMessage("Validation failed due to provided invalid data");
		error.setData(errorMessages);

		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

	@ExceptionHandler(value = { AccessDeniedException.class })
	public ResponseEntity<Response<String>> accessDeniedExceptionHandler(Exception ex) { (3)
		final Response<String> error = new Response<>();
		error.setStatus(HttpStatus.UNAUTHORIZED.value());
		error.setMessage("Access Denied...");
		return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
	}

	@ExceptionHandler(Exception.class)
	public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) { (4)
		final ErrorResponse error = new ErrorResponse();
		error.setErrorCode(HttpStatus.BAD_REQUEST.value());
		error.setMessage("The request could not be understood by the server due to malformed syntax.");
		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

	@ExceptionHandler(ConstraintViolationException.class)
	public ResponseEntity<Response<List<String>>> handleConstraintViolationException(
			ConstraintViolationException exception) { (5)
		List<String> errorMessages = new ArrayList<>();

		for (ConstraintViolation<?> violation : exception.getConstraintViolations()) {
			String propertyPath = extractPropertyPath(violation.getPropertyPath().toString());
			errorMessages.add(String.format("[%s]: %s", propertyPath, violation.getMessage()));
		}

		Response<List<String>> error = new Response<>();
		error.setStatus(HttpStatus.BAD_REQUEST.value());
		error.setMessage("Validation failed due to provided invalid data");
		error.setData(errorMessages);

		return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
	}

}
1 ExceptionToDo handler
  • Handles exceptions of type TransactionException, IllegalArgumentException, HttpMessageNotReadableException and TransactionSystemException.

  • Returns a ResponseEntity with a status code of 400 Bad Request and an error message derived from the exception’s message.

2 handleValidationException handler
  • Handles exceptions of type MethodArgumentNotValidException, typically thrown when the validation fails for method arguments.

  • Returns a ResponseEntity with a status code of 400 Bad Request and a generic "Validation failed due to provided invalid data" message.

3 AccessDeniedException handler
  • Handles exceptions of type AccessDeniedException, typically thrown when a user lacks the necessary permissions to access a resource.

  • Returns a ResponseEntity with a status code of 401 Unauthorized and a generic "Access Denied" message.

4 Generic exception handler
  • Handles any other uncaught exceptions that may occur during the execution of API endpoints.

  • Returns a ResponseEntity with a status code of 400 Bad Request and a generic error message indicating malformed syntax.

5 handleConstraintViolationException handler
  • Handles exceptions of type ConstraintViolationException, typically thrown when the validation fails for constraints.

  • Returns a ResponseEntity with a status code of 400 Bad Request and a generic error message indicating invalid data.

Customization

  • Additional exception handlers can be added to address specific use cases or domain-specific exceptions.

  • Error messages and status codes can be customized based on application requirements and error scenarios.

5. Controllers

5.1. TransactionServiceController

6. TransactionServiceController

6.1. Transfer

6.1.1. Sequential flow

transfer.puml

Transfer process

This process includes transfer of funds from one account to another based on the provided TransferDto. Here below are process steps -

Data validation

  1. The system checks if the transfer data is valid.

  2. It ensures that the transfer amount is greater than zero.

  3. It verifies the existence of sender and receiver contracts and payment channels.

Transfer process

  1. If data is valid, the system proceeds with the transfer process.

  2. It saves transaction details, initializes business events, and updates contract balances.

  3. Finally, it logs the transfer completion.

If the transfer data is invalid or any step fails, appropriate error messages are returned.

6.1.2. Endpoint

Description

This endpoint allows users with the appropriate permissions to transfer funds based on the provided data.

URL

/transfer

Method

POST

Request body

The request body should contain a JSON object. The structure of each object should adhere to the TransferDto format.

Example request body

{
    "value" : 1000,
    "contractUUID" : "a1933b07-a12c-4666-9669-8a1bda511086",
    "receiver" : "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144"
}

Responses

  • 200 OK: Transaction success. Returns a JSON response containing details of the transaction.

Example response body

{
    "status": 200,
    "message": "Transaction success",
    "data": "e9f0e281-ed53-43e4-a8a2-bc191d5e5aa5"
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions to transfer.

  • 5xx server error: If there is a server-side error while processing the request.

Example

{
  "status": 400,
  "message": "Invalid sender contactUUID",
  "data": null
}

6.1.3. Methods

Description

This method is responsible for validating a transfer request, updating the notional principal of credit and debit contracts, and saving the transaction details in the system.

Signature

public Response<UUID> transfer(TransferDto transferDto) throws URISyntaxException

Parameters

  • TransferDto (Type: TransferDto): The transfer request data containing information about the contract UUID, receiver, and transfer amount.

Returns

  • Response<UUID>: A response object indicating the success of the transfer operation. It contains the HTTP status code, a message indicating the success of the transaction, and the unique identifier of the transfer event.

Example usage

public Response<UUID> transfer(TransferDto transferDto) throws URISyntaxException {
		log.info("userID : {}, request : {}", usersHelper.getUserID(), transferDto);

		// Transfer data validation
		TransactionDetailsDto transfer = validator.validateEvent(transferDto); (1)

		// Initializing event to process transfer
		BusinessEvents event = transferHelper.initializeEvent(transfer); (2)

		// Updating creditPaymentChannel
		contractUpdateWorker.updateNotionalPrincipal(transfer.getCreditContract(), transfer.getValue(),
				event.getEventTime()); (3)

		// Updating debitPaymentChannel
		BigDecimal debitValue = transfer.getValue().multiply(BigDecimal.valueOf(-1.0));
		contractUpdateWorker.updateNotionalPrincipal(transfer.getDebitContract(), debitValue, event.getEventTime()); (4)

		// Saving transaction
		BusinessEvents transferEvent = transactionWorker.saveTransaction(event, transfer); (5)

		return new Response<>(HttpStatus.OK.value(), Messages.TRANSACTION_SUCCESS, transferEvent.getEventID()); (6)
	}
Internal workflow
1 Validates the transfer request data using the validator.validateEvent() method.
2 The method initializes an event to process the transfer using the transferHelper.initializeEvent() method.
3 It updates the notional principal of the credit payment channel by calling contractUpdateWorker.updateNotionalPrincipal() with the credit contract details, transfer value, and event time.
4 It updates the notional principal of the debit payment channel by calling contractUpdateWorker.updateNotionalPrincipal() with the debit contract details, negative transfer value, and event time.
5 The method saves the transaction details using the transactionWorker.saveTransaction() method.
6 Finally, it returns a response object with HTTP status code 200 (OK), a success message, and the unique identifier of the transfer event.

Exceptions

  • URISyntaxException is thrown by this method when parsing a malformed Uniform Resource Identifier (URI) string. However, exceptions may occur within the validator or worker methods, which are handled internally.

6.1.4. Model classes

Description

The TransferDto class represents a data transfer object used for transferring funds between contracts.

Attributes
  1. value

    • Type: BigDecimal

    • Description: Represents the amount of funds to be transferred.

    • Constraints: Not null.

    • Example: 1000

  2. contractUUID

    • Type: UUID

    • Description: Represents the UUID of the contract initiating the transfer.

    • Constraints: Not null.

    • Example: a1933b07-a12c-4666-9669-8a1bda511086

  3. receiver

    • Type: UUID

    • Description: Represents the UUID of the receiving contract.

    • Constraints: Not null.

    • Example: 2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144

Example usage

TransferDto transfer = new TransferDto();
transfer.setValue(new BigDecimal("100.00"));
transfer.setContractUUID(UUID.randomUUID());
transfer.setReceiver(UUID.randomUUID());

6.1.5. Validation

Description

The validateEvent method is responsible for validating transfer input data, including currency, balance, and contract details. It ensures that the provided transfer information is valid and meets the necessary criteria for processing the transaction.

Parameters

  • transferDto: Contains contractUUID, transaction value, and other relevant information necessary for performing the transfer.

Returns

  • TransactionDetailsDto: Contains transaction details required for processing the transfer.

Example usage

public TransactionDetailsDto validateEvent(TransferDto transferDto) {
		TransactionDetailsDto transfer = new TransactionDetailsDto();

		// Transfer amount validation
		Assert.isTrue(transferDto.getValue().doubleValue() > 0, Messages.INVALID_AMOUNT);
		transfer.setValue(transferDto.getValue()); (1)

		// Sender details validation
		this.validateSender(transferDto, transfer); (2)

		// Receiver details validation
		this.validateReceiver(transferDto, transfer); (3)

		// Sender and receiver accounts currency validation
		Assert.isTrue(validateCurrency(transfer.getDebitPaymentChannel(), transfer.getCreditPaymentChannel()),
				Messages.INVALID_CURRENCY); (4)
		transfer.setUnits(String.valueOf(transfer.getDebitPaymentChannel().getDetails().get(Constants.UNITS)));

		// Sender account balance validation
		Assert.isTrue(validateBalance(transfer.getDebitContract(), transfer.getValue()), Messages.INSUFFICIENT_BALANCE); (5)

		return transfer;
	}
Validation steps
1 Transfer amount validation
  • Validates that the transfer amount is greater than zero.

  • If the transfer amount is invalid, an assertion error with the message "INVALID_AMOUNT" is thrown.

2 Sender details validation
  • Validates the sender’s details, ensuring they meet the necessary criteria.

  • Details such as contract existence, balance, and currency are verified.

3 Receiver details validation
  • Validates the receiver’s details, ensuring they meet the necessary criteria.

  • Similar to sender validation, contract existence and other relevant details are verified.

4 Currency validation
  • Validates the currency of both the sender and receiver accounts.

  • Ensures that the currency of the sender’s account matches the currency of the receiver’s account.

  • If the currencies do not match, an assertion error with the message "INVALID_CURRENCY" is thrown.

5 Sender account balance validation
  • Validates that the sender’s account has sufficient balance to perform the transfer.

  • If the sender’s account balance is insufficient, an assertion error with the message "INSUFFICIENT_BALANCE" is thrown.

6.1.6. Testing

Description

This section provides an overview of the testing strategy and objectives for the transfer method.

Test methods

Example usage

@Test
	void transferTest() throws URISyntaxException { (1)
		TransferDto transferDto = new TransferDto();
		BigDecimal value = new BigDecimal("100");
		transferDto.setContractUUID(debitContract.getContractUUID());
		transferDto.setReceiver(creditPaymentChannel.getPaymentChannelID());
		transferDto.setValue(value);

		Response transferResponse = transferServiceImpl.transfer(transferDto);
		assertEquals(Messages.TRANSACTION_SUCCESS, transferResponse.getMessage());

		Contracts creditContracts1 = contractRepo.findById(creditContract.getContractUUID()).get();
		BigDecimal creditNotionalPrincipal = creditContracts1.getContractTerms().get(0).getNotionalPrincipal();

		Contracts debitContract1 = contractRepo.findById(debitContract.getContractUUID()).get();
		BigDecimal debitNotionalPrincipal = debitContract1.getContractTerms().get(0).getNotionalPrincipal();

		assertEquals(new BigDecimal("600.0"), creditNotionalPrincipal);
		assertEquals(new BigDecimal("400.0"), debitNotionalPrincipal);

	}
1 transferTest()
  • Purpose : The purpose of this test is to verify the functionality of the transfer operation in the TransferServiceImpl class. It ensures that funds are transferred correctly between two contracts, updating their notional principals accordingly.

  • Test steps

    1. Create a TransferDto object and set its attributes including contract UUID, receiver, and value.

    2. Execute the transfer operation using the transfer method from TransferServiceImpl.

    3. Retrieve the updated state of the credit contract’s notional principal from the database.

    4. Retrieve the updated state of the debit contract’s notional principal from the database.

  • Assertions

    • Ensure that the transfer operation is successful by verifying that the message in the response is equal to Messages.TRANSACTION_SUCCESS.

    • Assert that the notional principal of the credit contract is updated correctly to 600.0 after the transfer.

    • Assert that the notional principal of the debit contract is updated correctly to 400.0 after the transfer.

6.2. Transaction

6.2.1. Sequential flow

transaction.puml

Transaction process

This process includes transactions of different event types based on the provided TransactionDto. Here below are process steps -

Data validation

  1. Incoming requests are handled at "/transaction" endpoint.

  2. Transaction data is validated using the @Valid annotation.

  3. Event IDs are retrieved from the transaction data.

  4. Each transaction is individually validated for correctness.

Transaction process

  1. Valid transactions proceed to the processing phase.

  2. Processing involves updating contract information and performing associated event processes.

  3. Transaction details are saved alongside the associated business event.

  4. Responses are generated based on transaction success or failure.

  5. Logs track transaction progress and error handling ensures proper response generation.

6.2.2. Endpoint

Description

This endpoint allows the processing of transactions for various event types across all contract types except UMP. Transactions include events such as IP, PR, FP, IED, and more.

URL

/transaction

Method

POST

Request body

The request body should contain a JSON array. The structure of each object should adhere to the TransactionDto format.

Example request body

[
    {
        "eventID": "4e3723af-ece4-4934-963b-bfbabb510212",
        "value": 3320.8481981622112,
        "processTime": "2023-01-01T00:00"
    }
]

Responses

  • 200 OK: Transaction success. Returns a response containing a list of transaction process responses.

Example response body

{
    "status": 200,
    "message": "Transactions processed successfully",
    "data": [
        {
            "eventID": "4e3723af-ece4-4934-963b-bfbabb510212",
            "valid": "TRUE",
            "details": "Transaction success"
        }
    ]
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions for the transaction.

  • 5xx server error: If there is a server-side error while processing the request.

Example

{
  "status": 400,
  "message": "Invalid eventID",
  "data": null
}

Ensure that the request body is a JSON object containing a list of valid TransactionDto objects. The response body includes a list of TransactionResponseDto objects, providing details about the processed transactions and their validation status.

6.2.3. Methods

  1. Method: transaction

    Description

    This method processes transactions for all contract types except UMP. It receives a list of transaction data objects, executes the transactions, validates them, and returns a list of response objects indicating the status of each transaction.

    Signature

    public ResponseEntity<Response<List<TransactionResponseDto>>> transaction(
    			@Valid @RequestBody List<TransactionDto> transactionDtoList)

    Parameters

    • transactionDtoList (List of TransactionDto): A list containing information about the events to be processed.

      Returns

    • Responses with HTTP status codes indicating the success or failure of the transaction processing.

      Example usage

      public ResponseEntity<Response<List<TransactionResponseDto>>> transaction(
      			@Valid @RequestBody List<TransactionDto> transactionDtoList) {
      
      		// Execute the transactions
      		List<TransactionResponseDto> transactionResponseList = transactionsService
      				.executeTransaction(transactionDtoList); (1)
      
      		// Check if all transactions were valid
      		boolean allTransactionsValid = transactionResponseList.stream()
      				.allMatch(responseDto -> responseDto.getValid().equals(Constants.TRUE)); (2)
      
      		if (allTransactionsValid) {
      			// Return the responses with HTTP status OK
      			return new ResponseEntity<>(new Response<>(HttpStatus.OK.value(), "Transactions processed successfully",
      					transactionResponseList), HttpStatus.OK);
      		} else {
      			// Return the responses with HTTP status BAD_REQUEST
      			return new ResponseEntity<>(new Response<>(HttpStatus.BAD_REQUEST.value(),
      					"Validation failed due to provided invalid data", transactionResponseList), HttpStatus.BAD_REQUEST); (3)
      		}
      	}
      Internal workflow
      1 Executes transactions based on the provided transaction data.
      2 Checks if all transactions are valid.
      3 Returns responses with HTTP status codes indicating the success or failure of the transaction processing.
  2. Method: executeTransaction

    Description

    This method is responsible for executing transactions. It validates the input transaction data, processes valid transactions, and returns a list of response objects indicating the status of each transaction.

    Signature

    public List<TransactionResponseDto> executeTransaction(List<TransactionDto> transactionDtoList)

    Parameters

    • transactionDtoList (List of TransactionDto): The list of transaction data to be processed.

      Returns

    • List of TransactionResponseDto: A list of response objects indicating the status of each transaction.

      Example usage

      public List<TransactionResponseDto> executeTransaction(List<TransactionDto> transactionDtoList) {
      
      		// Retrieve eventIDs from input
      		List<UUID> eventIDList = transactionDtoList.stream().map(TransactionDto::getEventID).toList(); (1)
      
      		// Validate all transactions and accumulate responses
      		List<TransactionResponseDto> transactionResponseDtoList = transactionDtoList.stream()
      				.map(transactionData -> validator.validateTransactionData(transactionData, eventIDList)).toList(); (2)
      
      		// Process transactions only if all are valid
      		if (transactionResponseDtoList.stream()
      				.allMatch(responseDto -> responseDto.getValid().equals(Constants.TRUE))) { (3)
      			transactionResponseDtoList = transactionDtoList.stream().map(this::processTransaction).toList();
      		}
      		return transactionResponseDtoList; (4)
      
      	}
    Internal workflow
    1 Extracts event IDs from the input transaction data.
    2 Validates each transaction data object and accumulates the validation responses.
    3 Processes transactions only if all are valid.
    4 Returns a list of response objects indicating the status of each transaction.

6.2.4. Model classes

  1. TransactionDto

    Description

    The TransactionDto class represents a data transfer object (DTO) for a transaction. It encapsulates information about a transaction including its event ID, value, and process time.

    Attributes
    1. eventID

      • Type: UUID

      • Description: Represents the unique identifier of the event associated with the transaction.

      • Constraints: Not null.

      • Example: 4e3723af-ece4-4934-963b-bfbabb510212

    2. value

      • Type: BigDecimal

      • Description: Represents the value of the transaction.

      • Constraints: Not null.

      • Example: 3320.8481981622112

    3. processTime

      • Type: LocalDateTime

      • Description: Represents the timestamp when the transaction was processed.

      • Constraints: Not null.

      • Example: 2023-01-01T00:00

        Example usage

      TransactionDto transaction = new TransactionDto();
      transaction.setEventID(UUID.randomUUID());
      transaction.setValue(new BigDecimal("100.00"));
      transaction.setProcessTime(LocalDateTime.now());
  2. TransactionResponseDto

    Description

    The TransactionResponseDto class represents a data transfer object (DTO) for a transaction response. It encapsulates information about the status of a transaction along with any additional details.

    Attributes
    1. eventID

      • Type: UUID

      • Description: Represents the unique identifier of the event associated with the transaction.

      • Constraints: Not null.

      • Example: 4e3723af-ece4-4934-963b-bfbabb510212

    2. valid

      • Type: String

      • Description: Indicates whether the transaction is valid or not.

      • Constraints: Can take values "TRUE" or "FALSE".

      • Example: TRUE

    3. details

      • Type: String

      • Description: Provides additional details about the transaction, such as error messages or processing notes.

      • Example: Transaction success

This class is typically used to communicate the outcome of a transaction processing operation, such as whether it was successful or encountered an error.

6.2.5. Validation

Description

The validateTransactionData method is responsible for validating transaction input data, including event ID, event status, and other related parameters. It performs a series of validation checks to ensure that the transaction can be processed successfully.

Parameters

  • transactionDto (TransactionDto): Contains information about the transaction, including event ID, transaction value, etc.

  • eventIDList (List<UUID>): A list of provided event IDs to perform the transaction.

Returns

  • TransactionResponseDto: Represents the result of the transaction validation process, including the validity status and any associated details.

Example usage

public TransactionResponseDto validateTransactionData(TransactionDto transactionDto, List<UUID> eventIDList) {
		BusinessEvents businessEvent = null;
		TransactionResponseDto eventData = new TransactionResponseDto();
		try {
			// EventID validation
			businessEvent = this.validateEventID(transactionDto.getEventID()); (1)

			// Event status validation
			businessEvent = this.validateEventStatus(businessEvent); (2)

			if (!businessEvent.getEventType().equalsIgnoreCase(Constants.OPS)) {
				// Non OPS events validation
				this.validateNonOPSEvents(businessEvent, transactionDto, eventIDList); (3)
			}
			eventData.setEventID(transactionDto.getEventID());
			eventData.setValid(Constants.TRUE);
			eventData.setDetails(Constants.VALID_EVENT); (4)

		} catch (Exception e) {
			e.printStackTrace();
			eventData.setEventID(transactionDto.getEventID());
			eventData.setValid(Constants.FALSE);
			eventData.setDetails(e.getMessage());
		}
		return eventData;

	}
Validation steps
1 EventID validation
  • Validates the event ID provided in the transactionDto.

2 Event status validation
  • Validates the status of the event retrieved based on the event ID.

3 Non-OPS events validation
  • Performs additional validation checks for non-OPS (non-operational) events if applicable.

4 Setting response data
  • Sets the event ID, validity status, and details in the TransactionResponseDto object based on the validation results.

Validate the structure and content of the TransactionDto object before passing it to this method to avoid unexpected behavior.

6.2.6. Testing

Description

This section provides an overview of the testing strategy and objectives for the transaction method.

Test methods

Example usage

@Test
	void testExecuteTransaction6() { (1)
		when(eventsRepo.findById(event.getEventID())).thenReturn(Optional.of(event));
		when(paymentRepo.findById(ArgumentMatchers.<UUID>any())).thenReturn(Optional.of(debitPaymentChannel));
		when(contractRepo.findById(ArgumentMatchers.<UUID>any())).thenReturn(Optional.of(debitContract));
		TransactionResponseDto trasactionResponse = new TransactionResponseDto();
		trasactionResponse.setDetails(Messages.TRANSACTION_SUCCESS);
		trasactionResponse.setValid("TRUE");
		terms.setInitialExchangeDate(LocalDateTime.parse("2023-06-21T23:59:59"));
		BigDecimal NotionalPrincipal = new BigDecimal("20000.0");
		BigDecimal RemainingValue = new BigDecimal("18000.0");
		terms.setNotionalPrincipal(NotionalPrincipal);
		event.setStatus("Pending");
		event.setEventType("IED");
		event.setRemainingValue(RemainingValue);
		TransactionDto transactionDto = new TransactionDto();
		BigDecimal Value = new BigDecimal("-2000");
		transactionDto.setEventID(event.getEventID());
		transactionDto.setProcessTime(LocalDateTime.parse("2023-06-22T23:59:59"));
		transactionDto.setValue(Value);
		ArrayList<TransactionDto> transactionDtoList = new ArrayList<>();
		transactionDtoList.add(transactionDto);

		List<TransactionResponseDto> executeTransaction = transferServiceImpl.executeTransaction(transactionDtoList);

		TransactionResponseDto response = executeTransaction.get(0);

		assertEquals("TRUE", response.getValid());
		assertEquals(Messages.TRANSACTION_SUCCESS, response.getDetails());

	}
1 testExecuteTransaction6()
  • Purpose : This test case aims to verify the correct execution of the executeTransaction method in the TransferServiceImpl class when processing a transaction for an event with a pending status.

  • Test steps

    1. Mock the repository methods (eventsRepo, paymentRepo, contractRepo) to simulate database interactions.

    2. Set up test data including event details, initial exchange date, notional principal, remaining value, transaction details, etc.

    3. Invoke the executeTransaction method with the prepared transaction DTO list.

    4. Extract the response from the list of transaction responses.

    5. Assert that the validity status of the transaction response is "TRUE".

    6. Assert that the details of the transaction response match the expected success message.

  • Assertions

    • The transaction response should indicate a valid transaction (valid = "TRUE").

    • The details of the transaction response should match the expected success message (details = "TRANSACTION_SUCCESS").

6.3. Get transactions

6.3.1. Sequential flow

get-transactions.puml

Get transactions process

This process includes retrieval of a list of transactions based on specified filters and pagination parameters. Here below are process steps -

Data validation

  1. Upon receiving a GET request to the /txs endpoint, the server validates the query parameters including filterDto, page, and size.

Get transactions process

  1. The server parses the query parameters and sets up pagination based on the provided page and size.

  2. It generates a JPA specification from the TransactionFilterDto to filter transactions.

  3. The server executes a database query using the generated specification and pagination settings.

  4. Retrieved transactions are sent back to the client as a response.

6.3.2. Endpoint

Description

This endpoint allows developers to fetch transactions based on specified filters and pagination parameters.

URL

/txs

Method

GET

Request filter parameters

Parameters

Type

Required

Description

TransactionFilterDto

JSON object

Yes

Filter parameters for fetching transactions.

page

Integer

No

Page number for pagination. Default value is 0.

size

Integer

No

Number of transactions per page. Default value is 10.

Responses

  • 200 OK: Success. Returns a list of transactions matching the specified filters.

Example response body

{
    "status": 200,
    "message": "Success",
    "data": [
        {
            "transactionID": "78fe0787-7dd2-44b3-bc13-d67254218848",
            "eventID": "2858d468-d51c-482d-bc0a-a291438045d4",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-19T16:57:39",
            "debitPaymentChannelID": "13c3861e-bcc6-48ed-9db1-91cb6825328a",
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "value": 50000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "18d57dd4-5898-40af-aa06-52eb7cd28ebb",
            "eventID": "f771b128-c948-4dea-8359-6a43e1f4ef3f",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T12:01:03",
            "debitPaymentChannelID": "13c3861e-bcc6-48ed-9db1-91cb6825328a",
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "value": 50000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "b0936731-9b0f-4236-8c52-465490d1f6fa",
            "eventID": "61f04124-6a7c-4471-9ea5-70b82dafe225",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T12:13:51",
            "debitPaymentChannelID": "13c3861e-bcc6-48ed-9db1-91cb6825328a",
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "value": 50000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "df5bfea5-2e79-475d-96f3-1f98c05286d2",
            "eventID": "bc17d4d1-18f1-464c-8e2a-af9bfa4752be",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T13:11:28",
            "debitPaymentChannelID": "13c3861e-bcc6-48ed-9db1-91cb6825328a",
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "value": 50000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "c7d78a3d-9a4a-49d8-919e-459db44f5686",
            "eventID": "d20d11ba-eaeb-4e4c-a89f-8a16ab48f019",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T14:58:51",
            "debitPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "creditPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "value": 50000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "c7c7e576-68a1-46c9-b8d0-55af6e02016e",
            "eventID": "b06f7336-6a2c-42f5-a64e-5358085a7688",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T15:00:42",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "value": 2500,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "3c00ed45-3131-4f2e-9351-3a8f0d3508dd",
            "eventID": "b508767f-055c-46f6-a0c4-5ead61aed2b1",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T15:01:54",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "value": 3000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "43eb5e8d-6d66-44e6-be25-c089ed9ed8bb",
            "eventID": "b508767f-055c-46f6-a0c4-5ead61aed2b1",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T15:02:35",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "value": 3000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "7e96e7d6-2b18-4c9c-ba28-4a9ed8f12d10",
            "eventID": "45409163-2c2f-4c06-91a1-5b08c5a05c18",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T15:31:02",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "value": 5000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        },
        {
            "transactionID": "6b453065-d29d-4046-ba65-7caea90dac91",
            "eventID": "af4206fb-3cd9-40a9-b654-74fcfa6d118f",
            "processTime": "2023-01-01T00:00:00",
            "systemTime": "2024-02-20T15:35:45",
            "debitPaymentChannelID": "fb0fdb85-87ee-4af2-b39a-f3a23227203c",
            "creditPaymentChannelID": "2ae5b30b-3fba-4f4b-a45f-c1d0c03b4144",
            "value": 2000,
            "units": "INR",
            "status": "processed",
            "additionalInformation": null,
            "userID": "902375cc-4f72-428f-8db0-95a7baa69b51"
        }
    ]
}
  • 400 bad request: If the request body is not in the correct format or if there are validation errors.

  • 401 unauthorized: If the user is not authenticated or lacks the necessary permissions for retrieving the transactions.

  • 5xx server error: If there is a server-side error while processing the request.

6.3.3. Methods

Description

This method fetches transactions based on filters provided in the TransactionFilterDto object.

Parameters

  • filterDto (Type: TransactionFilterDto, Source: Query Parameter): Filter parameters for fetching transactions. The filter criteria are specified in the TransactionFilterDto object.

  • page (Type: int, Source: Query Parameter, Default Value: 0): Page number for pagination.

  • size (Type: int, Source: Query Parameter, Default Value: 10): Number of transactions per page.

Returns

  • ResponseEntity<Response<List<Transactions>>>: Returns a response entity containing a list of transactions matching the specified filters.

Example usage

public ResponseEntity<Response<List<Transactions>>> getTransactions(
			@Valid @ParameterObject TransactionFilterDto filterDto,
			@RequestParam(name = "page", defaultValue = "0") int page,
			@RequestParam(name = "size", defaultValue = "10") int size) {

		// Create Pageable object
		Pageable pageable = PageRequest.of(page, size); (1)

		// Get transactions based on the provided filters and pagination
		List<Transactions> finalTransactionList = transactionsService.getTransactions(filterDto, pageable); (2)

		// Return the transactions with HTTP status OK
		return new ResponseEntity<>(new Response<>(HttpStatus.OK.value(), Messages.SUCCESS, finalTransactionList),
				HttpStatus.OK); (3)
	}
Internal workflow
1 Pagination is applied to the list of transactions to improve performance and manage large data sets efficiently.
2 The method uses the provided filter parameters and pagination settings to retrieve transactions from the transactionsService.
3 Returns the list of transactions matching the specified filters.

Exceptions

  • None explicitly thrown by this method. However, ensure to handle any potential errors gracefully and provide informative error messages.

6.3.4. Model classes

Description

The TransactionFilterDto class represents a data transfer object (DTO) used for filtering transactions based on various criteria.

Attributes
  1. transactionId

    • Type: UUID

    • Description: Represents the unique identifier of the transaction.

    • Example: 18d57dd4-5898-40af-aa06-52eb7cd28ebb

  2. userID

    • Type: UUID

    • Description: Represents the unique identifier of the user associated with the transaction.

    • Example: 902375cc-4f72-428f-8db0-95a7baa69b51

  3. eventID

    • Type: UUID

    • Description: Represents the unique identifier of the event associated with the transaction.

    • Example: f771b128-c948-4dea-8359-6a43e1f4ef3f

  4. processTime

    • Type: String

    • Description: Represents the timestamp indicating the processing time of the transaction.

    • Example: 2023-01-01T00:00:00

  5. debitPaymentChannelID

    • Type: UUID

    • Description:Represents the unique identifier of the debit payment channel used in the transaction.

    • Example: 13c3861e-bcc6-48ed-9db1-91cb6825328a

  6. creditPaymentChannelID

    • Type: UUID

    • Description: Represents the unique identifier of the credit payment channel used in the transaction.

    • Example: fb0fdb85-87ee-4af2-b39a-f3a23227203c

  7. status

    • Type: String

    • Description: Represents the status of the transaction.

    • Example: processed