Skip to content

Commit

Permalink
Merge pull request #1 from easybill/dev
Browse files Browse the repository at this point in the history
Initialize project
  • Loading branch information
BolZer authored Jun 10, 2024
2 parents 7272a8a + b4f8b17 commit e7b5afc
Show file tree
Hide file tree
Showing 42 changed files with 4,159 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*
!build/*-runner
!build/*-runner.jar
!build/lib/*
!build/quarkus-app/*
28 changes: 28 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: "Build"

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '20'
cache: 'gradle'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
with:
gradle-version: 8.6

- name: Test Gradle Build
run: ./gradlew build --dry-run
28 changes: 28 additions & 0 deletions .github/workflows/codestyle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: "Codestyle"

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '20'
cache: 'gradle'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
with:
gradle-version: 8.6

- name: Check codestyle with Gradle Wrapper
run: ./gradlew spotlessCheck
38 changes: 38 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: publish release

on:
push:
tags:
- '*.*.*'

jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '20'
cache: 'gradle'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
with:
gradle-version: 8.6

- name: Create new buildx builder
run: docker buildx create --name custom_builder --use

- name: Build application
run: ./gradlew build -Dquarkus.package.jar.type=uber-jar

- name: Build images
run: docker buildx build --platform=linux/amd64 --platform=linux/arm64 -t easybill/peppol-bis-billing-validator:${{github.ref_name}} -t easybill/peppol-bis-billing-validator:latest . --push
31 changes: 31 additions & 0 deletions .github/workflows/spotbugs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "Spotbugs"

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '20'
cache: 'gradle'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
with:
gradle-version: 8.6

- name: Main Spotbugs with Gradle Wrapper
run: ./gradlew spotbugsMain

- name: Test Spotbugs with Gradle Wrapper
run: ./gradlew spotbugsTest
35 changes: 35 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: "Tests"

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
include:
- { operating-system: 'ubuntu-latest', java-version: '19' }
- { operating-system: 'ubuntu-latest', java-version: '21' }

steps:
- uses: actions/checkout@v4

- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: ${{ matrix.java-version }}
cache: 'gradle'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
with:
gradle-version: 8.6

- name: Run tests with gradle wrapper
run: ./gradlew test
39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Gradle
.gradle/
build/

# Eclipse
.project
.classpath
.settings/
bin/

# IntelliJ
.idea
*.ipr
*.iml
*.iws

# NetBeans
nb-configuration.xml

# Visual Studio Code
.vscode
.factorypath

# OSX
.DS_Store

# Vim
*.swp
*.swo

# patch
*.orig
*.rej

# Local environment
.env

# Plugin directory
/.quarkus/cli/plugins/
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM openjdk:21

WORKDIR .

COPY ./build/peppol-bis-billing-validator--runner.jar .

ENTRYPOINT ["java", "-Xmx512m", "-jar", "peppol-bis-billing-validator--runner.jar"]
123 changes: 123 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# peppol-bis-billing-validator
[![Generic badge](https://img.shields.io/badge/Version-0.1.0-important.svg)]()
[![Generic badge](https://img.shields.io/badge/License-MIT-blue.svg)]()

## Introduction
`peppol-bis-billing-validator` is a small service for validating XML against the official
Peppol BIS Billing 3.0 schematron rules. It exposes an validating endpoint which takes the
to be validated XML and returns the schematron report. The HTTP status code indicates if the
provided XML is valid (200) or has issues (400).

## Usage
This service was mainly designed with docker in mind. So general idea is to use the following
docker image and make HTTP-Requests from the main application to the service for validation the
XML.

- modifying / creating docker-compose.yaml

> The service exposes a health endpoint which can be used to check if the service ready to be used
> You can find a OpenAPI documentation after you started the service at /swagger
```yaml
peppol-validator:
image: 'bolzerdev/peppol-bis-billing-validator:latest'
ports:
- '8081:8080'
healthcheck:
test: curl --fail http://localhost:8081/health || exit 0
interval: 10s
retries: 6
```
- starting docker compose
```
docker compose up --detach --wait --wait-timeout 30
```

- Example of using the service (PHP)
```PHP
<?php

declare(strict_types=1);

final class PeppolValidator
{
public function isValid(string $xml): ?bool
{
$httpClient = new Client();

$response = $httpClient->request('POST', 'http://localhost:8081/validation', [
RequestOptions::HEADERS => [
'Content-Type' => 'application/xml',
],
RequestOptions::BODY => $xml,
RequestOptions::TIMEOUT => 10,
RequestOptions::CONNECT_TIMEOUT => 10,
RequestOptions::HTTP_ERRORS => false,
]);

return 200 === $response->getStatusCode();
}
}
```

- Example response in case the XML is invalid

> The `svrl:failed-assert` elements are relevant to be inspected. They contain the error message. The
```xml
<?xml version="1.0" encoding="UTF-8"?>
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl" title="Rules for Peppol BIS 3.0 Billing" schemaVersion="iso">
<svrl:ns-prefix-in-attribute-values prefix="cbc" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" />
<svrl:ns-prefix-in-attribute-values prefix="cac" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" />
<svrl:ns-prefix-in-attribute-values prefix="ubl-creditnote" uri="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2" />
<svrl:ns-prefix-in-attribute-values prefix="ubl-invoice" uri="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" />
<svrl:ns-prefix-in-attribute-values prefix="xs" uri="http://www.w3.org/2001/XMLSchema" />
<svrl:ns-prefix-in-attribute-values prefix="u" uri="utils" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:fired-rule context="ubl-creditnote:CreditNote | ubl-invoice:Invoice" />
<svrl:failed-assert id="PEPPOL-EN16931-R007" location="/*:Invoice[namespace-uri()='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'][1]" test="$profile != 'Unknown'" flag="fatal">
<svrl:text>Business process MUST be in the format 'urn:fdc:peppol.eu:2017:poacc:billing:NN:1.0' where NN indicates the process number.</svrl:text>
</svrl:failed-assert>
<svrl:fired-rule context="cac:AccountingSupplierParty/cac:Party" />
<svrl:fired-rule context="cbc:EndpointID[@schemeID = '0088'] | cac:PartyIdentification/cbc:ID[@schemeID = '0088'] | cbc:CompanyID[@schemeID = '0088']" />
<svrl:fired-rule context="cac:AccountingCustomerParty/cac:Party" />
<svrl:fired-rule context="cbc:EndpointID[@schemeID = '0184'] | cac:PartyIdentification/cbc:ID[@schemeID = '0184'] | cbc:CompanyID[@schemeID = '0184']" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cac:InvoiceLine | cac:CreditNoteLine" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:active-pattern document="" />
<svrl:fired-rule context="cbc:IssueDate | cbc:DueDate | cbc:TaxPointDate | cbc:StartDate | cbc:EndDate | cbc:ActualDeliveryDate" />
<svrl:fired-rule context="cbc:InvoiceTypeCode" />
<svrl:fired-rule context="cbc:EndpointID[@schemeID]" />
<svrl:fired-rule context="cbc:EndpointID[@schemeID]" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cac:TaxCategory[upper-case(cbc:TaxExemptionReasonCode)='VATEX-EU-F']" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
<svrl:fired-rule context="cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount" />
</svrl:schematron-output>
```

## Issues & Contribution
Feel free to create pull-requests or an issue if you have trouble with this service or any related resource.
Loading

0 comments on commit e7b5afc

Please sign in to comment.