Skip to content

mhoennig/hs-billing-core

Repository files navigation

Hostsharing Billing Core

🔥
This software is under development and not yet usable.

This program is the core module of Hostsharing's billing system. It’s based on snapshot input CSV-files, supplied by other modules and creates a set of output-files like accounting records and invoices. These outputs are processed by subsequent steps, like mailing the invoices to the customers.

Executions are idempotent and therefore repeatable: As long as the parameters and input files are the same, each run will produce exactly the same output.

Architecture Overview

Input Files

The input-CSV-files, supplied by other modules are:

  • customer.csv - containing customer data like billing-contact and payment mode

  • multiple *-billing-items.csv - containing items to be invoiced from multiple sources

  • vat-groups.csv - specifies

Output Files

For each run it creates a set of output files through Velocity templates:

  • accounting-records.csv - accounting records including VAT-specific account numbers to be further processed by the accounting system

  • invoices in several formats like for emails and PDF-generation (not implemented yet)

  • sepa.csv - contains records for direct debiting

  • …​

Package Structure

The root-package of this program org.hostsharing.hsadmin.billing.core contains the main program.

The main program orchestrates the following modules.

It contains the following sub-packages:

domain

Types describing the domain model.

reader

Classes and functions which read and parse the input CSV-file and convert these into domain-objects.

invoicing

Actual "calculation" of the invoices using the domain objects from the reader. The output is an internal presentation of the invoices.

generator

These generators take the internal presentation of the invoices from the invoicing module and produce output domain objects for further processing by the writer

writer

Functions which convert the generated domain objects to be used as contexts in Velocity templates which then are used to generate the output files.

lib

Types functions which can be used in all other modules.

Build System

Task Overview

To see all available build tasks, run:

./gradlew tasks --all

The Gradle task dependency plugin tiTree can be used to list all gradlew tasks with their dependencies. For example to see all dependencies of the gradlew build task, run:

$ ./gradlew tiTree build

Library Dependency Management

To get a dependency graph of all used libraries, run:

$ /gradlew app:dependencies

A dependabot for automatic dependency update checking of this project is running on its github repo.

Quality Assurance

Code-Formatting and Linting

The general formatting of files is defined in .editorconfig, these settings should automatically be picked up by most code editors and IDSs.

Also, ktlint is installed and configured. To check code style, run:

$ ./gradlew ktlint

This task also bound to "gradle check".

To automatically fix code style deviations, use:

$ ./gradlew ktlintFormat

Code Quality

For checking code complexity detekt is configured:

$ ./gradlew detekt

This command will check for rule violations and create a report.

The configuration can be found in app/config/detekt/config.yml.

For more information see detekt project on Github.

Unit Testing

Running Tests

For unit-testing, JUnit 5 (Jupiter)_ is used along with assertk, a Kotlin version of assertj as a check task for gradle.

To execute the unit-tests, run:

$ ./gradlew test

Writing Tests

For writing unit-tests consider the BRIEF rules from BDD:

Business language

enables collaboration and feedback

Real data

helps to discover white spots in requirements

Intention revealing

is a way to describe the tests by focusing on what we wanted to achieve and not on how

Essential

include only relevant details in the scenario

Focused

the scenarios should illustrate a single rule only Brief — keep scenarios short

Pretty Logging

For prettier output of test results, a testlogger is configured. Find the configuration in ./app/build.gradle under testlogger.

On Windows, to get a proper output, you need to change the codepage before running gradle:

chcp 65001

Test Code Coverage

To verify a specified test code coverage minimum, jacoco is configured. The verification is a dependent of gradlew check and can be run separately with:

$ ./gradlew jacocoTestCodeCoverageVerification

A coverage report (./app/build/reports/jacoco/index.html]) can be generated with:

$ ./gradlew jacocoTestReport

Find the configuration in ./app/build.gradle

Mutation Testing

To check the quality of the assertions in the unit-tests, pitest is used as a mutation testing-tool.

The mutation-tests can be executed with:

$ ./gradlew pitest

This creates a report comprising line- and mutation-coverage of the unit-tests.

If the "mutant-kill rate" falls below a configured limit, the pitest-task will fail; in that case, please improve the unit-tests. The limits are configured in app/build.gradle. Please increase the limit according to the level we have reached, once we become better; about 2 percent points below the level we have actually reached, is a good measure.

🔥
After a successful run, you can see percentage which actually counts for the limit. The percentage shown in the report HTML-file seems to be calculated differently and is usually a bit higher.

Similar to the problem mentioned above (see chapter Test Code Coverage), some Kotlin features generate code which our tests won’t cover and should not cover because we don’t want to test the Kotlin compiler. Unfortunately pitest does not know about this fact and is going to mutate this code as well which leads to false positives. Most of these issues could only be fixed jointly by the Kotlin-compiler and pitest development teams, as mentioned in this open Kotlin-compiler issue.

Architecture Verification

There is some automatic verification of architecture rules using ArchUnit in the unit test ArchitectureTest. See there for more information, especially about the git branch archunit-rule-validation and verifying the rules themselves.

Technically this is a mal unit-test, thus run with:

$ ./gradlew test

About

CLI invoicing for Hostsharing eG

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages