Direct Debit Processing Calendar

Single page web application developed for Cancer Research UK to calculate Direct Debit processing days for a selected year by accounting for weekends, bank holidays and other non-work days. Uses the UK Government's Bank Holidays API to fetch data dynamically.

Stack

  • HTML/CSS
  • JavaScript
  • React
  • React-BootStrap
  • Vitest / Jest

Code & Docs

Direct Debit Processing Calendar home page

The purpose

This is v2 of a browser app that can be used to determine Direct Debit processing days for a selected year by accounting for weekends, bank holidays and other non-work days. The original repo can be found here.

Companies who operate a Direct Debit scheme will rely on a processing calendar to determine their schedule for specific Direct Debit processes, in order to meet the Direct Debit guarantee). Processing dates for both Service User and bank are determined by working days, and therefore need to be adjusted to account for bank holidays, weekends, and office closures. Determining when these dates are had proven to be a manual, surprisingly complex and error-prone process, and so this app was created to meet a real challenge / need for automation.

Ultimately this app is designed to provide a reliable means of determining Direct Debit processing days, mitigating error and risk - failure to generate this data correctly may result in multiple negative impacts that are difficult and/or costly to fix: missed or delayed submissions, payment reconciliation issues, knock-on impact on future claims, damage to reputation or the company's Service User status.

The results are laid out in a format that fits the exact requirements of the Apps Support team for data loading, and can be copied to the clipboard with a single click.

Direct Debit Processing Calendar features

Features

  • Calculates and displays non-processing days (bank holidays and weekends) for a given year
  • User can manually add and delete company-specific non-processing days (e.g. Christmas or other holiday office closures). The results table will update dynamically to account for changes.
  • Displays results as processing dates for the organisation, broken down by type
  • 'Copy to clipboard' button for easy export of results table
  • 'Toast' notifications for each user interaction, providing visual feedback. These stack with repeated actions, and auto-clear after a set time interval.
  • Test suite built using Vitest, the Jest API for assertions, and MC-FIRE principles

Web Stack & Tech

For the app's core logic and functionality, I worked extensively with vanilla JavaScript, focusing on the JS Date object to make calculations.

The app makes calls to the UK Government's Bank Holidays API, which ensures that dates can be provided dynamically - for example, when extra bank holidays are created.

This app was originally built using vanilla JS, with a basic BootStrap interface, focusing on functionality over form. It has since undergone a major revamp - the UI has been refactored to use React components (including CRUK's React component library, built using styled-components), and the app's functional layer now makes use of React state management instead of traditional JS DOM manipulation. This has greatly improved the visual interface and provides a robust user experience, allowing for results to be updated dynamically without the need to refresh the browser.

To bridge the gap between the original app's UI elements and React, I made use of some of the original BootStrap components, rebuilt for React with the React-BootStrap library.

Unit tests (originally Mocha/Chai) have been been rewritten in Vitest, due to its integration with my React build tool of choice, Vite, and compatibility with the popular Jest API. Further advantages of this setup included clear assertions, integrated mocking, and visualisation of code coverage.

For a simplified deployment process and built-in continuous integration and continuous deployment(CI/CD), I deployed with Netlify.

You can find the original repo here, and see below for a visual comparison:

Direct Debit Processing Calendar tech

Challenges

To generate results, the app is comparing potential processing dates against the non-working days provided via API call (weekends and bank holidays), as well as company-specific holiday dates input by the user. If the 2 match, the app needs to not only shift the date backwards or forwards, but re-calculate the shift until there is no longer a clash. This required some complex nested looping logic, and testing for edge cases, including those where a non-processing day (or days) land(s) between dates where one needs to be 3 working days prior to another.

The dates calculated in each column are dependent on each other - results are not always isolated to a specific calendar year, but can be impacted by e.g. non-processing dates in the previous calendar year, or can impact the subsequent calendar year. This therefore needed to be built into the app's logic as well.

Updating from vanilla JS/BootStrap to a fully-fledged React application meant not only a refactoring of UI elements (taking advantage of modular component structure and dynamic rendering), but restructuring the app's functionality, as React works with a virtual DOM rather than the traditional DOM. This was a challenge but at the same time, a great exercise in design thinking - analysing the app's process flow, simplifying and breaking down functions and UI elements further where necessary, improving clarity and reusability.

Refactoring was helped by having already written unit tests, expressing what each function should achieve. Conditional rendering logic could now be handled by components themselves, rather than arising from other functions, allowing for a clearer separation of concerns. The React Context API also allowed me to maintain greater control and a clearer overview of state management throughout the app, without overly complicated interactions and unwanted side effects.

Testing the 'copy to clipboard' function in Vitest involved some extra complexity without certain DOM elements in a testing environment. I nonetheless managed this by:

  • Mocking the navigator object using 'vi' in Vitest;
  • Mocking the document object using JSDOM
  • To make the app's output more predictable, I opted to change the data structure of each function's returned output so that they followed a consistent schema. In turn, my tests greatly supported my overall debugging process, as they involved checking the data structure as well as type-checking.

    For some further app-specific challenges, as well as complications and lessons from working with the JavaScript Date object, see my original repo here.

    Direct Debit Processing Calendar challengesDirect Debit Processing Calendar challengesDirect Debit Processing Calendar challenges

    Lessons

    While I gained a lot of experience working with the Date object in JavaScript, I discovered that there are JS date libraries which could simplify the process of converting and working with dates, thereby speeding up production. For example, date-fns or Moment.js.

    While my eventual unit-test coverage was close to 100%, I learned first-hand that this is not the only metric for effective tests - there is always room to improve their quality and handling of edge cases. An app can also benefit from integration and end-to-end testing where possible. In this case, I mocked integration testing using data to ensure the app's output would be correct. I am looking to further explore the possibilities of integration and end-to-end testing using faking/stubbing tools such as Sinon.js, and E2E testing suites such as Cypress, while also testing React components with React Testing Library.

    Other Projects

    Schillinger Rhythm Generator

    Sliding Puzzle