Skip to content

Commit

Permalink
Merge pull request #150 from OpenPEPPOL/2024-q2-member-review
Browse files Browse the repository at this point in the history
2024 q2 member review
  • Loading branch information
jerouris authored May 22, 2024
2 parents 0f63848 + 67d7470 commit 30bf64e
Show file tree
Hide file tree
Showing 19 changed files with 1,780 additions and 122 deletions.
2 changes: 1 addition & 1 deletion guide/bis/settings.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
:doctitle: image:../shared/images/peppol.jpg[float="right", width=100%] Peppol BIS Billing
:shared-dir: ../../shared
:snippet-dir: ../../rules/snippets
:version: 3.0.15
:version: 3.0.17
:name-op-en: OpenPeppol AISBL, Post-Award Coordinating Community


Expand Down
2 changes: 2 additions & 0 deletions guide/release-notes/main.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ IMPORTANT: Changes in code lists are also reflected by changes in the validation

:leveloffset: +1

include::v3.0.17.adoc[]

include::v3.0.16.adoc[]

include::v3.0.15.adoc[]
Expand Down
26 changes: 26 additions & 0 deletions guide/release-notes/v3.0.17.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
= Version 3.0.17
[horizontal]
Release date:: May 2024

== Changes to BIS document

None

== Changes to code lists and validation artefacts

* Added new Swedish rule (SE-R-013) for validation of the check number of a Swedish Organization number. The rule is introduced as severity warning. All rules which verify the format of Organization numbers (SE-R-003, SE-R-004 and SE-R-013) will be changed to severity fatal in the next release.
* Update for rule NL-R-007 (mandatory payment means), the check should not fire if the document is a credit note with a positive amount.
* Update of PEPPOL-COMMON-R049, which validates identifiers using ICD/EAS 0007. The change is adding validation of the check number of a Swedish Organization number.
* Removing Currency code Sierra Leone SLL, new code is SLE
* Adding Payment means code 98
* Adding Item type identification code GMN
* Adding charge code PRV
* Adding VAT Exemption reason codes VATEX-FR-FRANCHISE, VATEX-FR-CNWVAT

== EN 16931 schematrons updated
* Changes in the code lists supported
* BT-32 path check missing in BR-AE-02, BR-AE-03, and BR-AE-04 in CII
* [BR-63] fails if multiple URIUniversalCommunication are present
* BR-33 / BR-CO-21 rules validation doesn't work on CII files (OK on UBL files)
* Undocumented and missing changes in v.1.3.11 release
* missing cardinality check for Value added tax point date (BT-7) and Value added tax point date code (BT-8) in CII
2 changes: 1 addition & 1 deletion project.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Project xmlns="urn:fdc:difi.no:2017:vefa:structure:Project-1">

<Name>Peppol BIS Billing 3.0 - November 2023 Release</Name>
<Name>Peppol BIS Billing 3.0 - May 2024 Release</Name>

<Documentation path="bis/">Business Interoperability Specifications (BIS)</Documentation>
<Documentation path="compliance/">BIS compliance</Documentation>
Expand Down
104 changes: 54 additions & 50 deletions rules/sch/CEN-EN16931-CII.sch

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions rules/sch/CEN-EN16931-UBL.sch

Large diffs are not rendered by default.

37 changes: 35 additions & 2 deletions rules/sch/PEPPOL-EN16931-CII.sch
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,34 @@ Last update: 2022 May release 3.0.13.
((string-to-codepoints(substring($val,11,1)) - 48) * 19)) mod 89 = 0
"/>
</function>

<!-- Function for Swedish organisation numbers (0007) -->
<function xmlns="http://www.w3.org/1999/XSL/Transform" name="u:checkSEOrgnr" as="xs:boolean">
<param name="number" as="xs:string"/>
<choose>
<!-- Check if input is numeric -->
<when test="not(matches($number, '^\d+$'))">
<sequence select="false()"/>
</when>
<otherwise>
<!-- verify the check number of the provided identifier according to the Luhn algorithm-->
<variable name="mainPart" select="substring($number, 1, 9)"/>
<variable name="checkDigit" select="substring($number, 10, 1)"/>
<variable name="sum" as="xs:integer">
<value-of select="sum(
for $pos in 1 to string-length($mainPart) return
if ($pos mod 2 = 1)
then (number(substring($mainPart, string-length($mainPart) - $pos + 1, 1)) * 2) mod 10 +
(number(substring($mainPart, string-length($mainPart) - $pos + 1, 1)) * 2) idiv 10
else number(substring($mainPart, string-length($mainPart) - $pos + 1, 1))
)"/>
</variable>
<variable name="calculatedCheckDigit" select="(10 - $sum mod 10) mod 10"/>
<sequence select="$calculatedCheckDigit = number($checkDigit)"/>
</otherwise>
</choose>
</function>

<pattern>
<rule context="rsm:ExchangedDocumentContext">
<assert id="PEPPOL-EN16931-R001" test="ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID" flag="fatal">Business process MUST be provided.</assert>
Expand Down Expand Up @@ -304,7 +332,7 @@ Last update: 2022 May release 3.0.13.
<assert id="PEPPOL-COMMON-R048" test="u:checkPIVAseIT(normalize-space())" flag="warning">Italian VAT Code (Partita Iva) must be stated in the correct format</assert>
</rule>
<rule context="ram:URIID[@schemeID = '0007'] | ram:ID[@schemeID = '0007'] | ram:GlobalID[@schemeID = '0007']">
<assert id="PEPPOL-COMMON-R049" test="string-length(normalize-space()) = 10 and string(number(normalize-space())) != 'NaN'" flag="fatal">Swedish organization number MUST be stated in the correct format.</assert>
<assert id="PEPPOL-COMMON-R049" test="string-length(normalize-space()) = 10 and string(number(normalize-space())) != 'NaN' and u:checkSEOrgnr(normalize-space())" flag="fatal">Swedish organization number MUST be stated in the correct format.</assert>
</rule>
<rule context="ram:URIID[@schemeID = '0151'] | ram:ID[@schemeID = '0151'] | ram:GlobalID[@schemeID = '0151']">
<assert id="PEPPOL-COMMON-R050" test="u:abn(normalize-space())" flag="fatal">Australian Business Number (ABN) MUST be stated in the correct format.</assert>
Expand Down Expand Up @@ -417,6 +445,7 @@ Last update: 2022 May release 3.0.13.
<rule context="rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedLegalOrganization[../ram:PostalTradeAddress/ram:CountryID = 'SE' and ram:ID]">
<assert id="SE-R-003" test="string(number(ram:ID)) != 'NaN'" flag="warning">Swedish organisation numbers should be numeric.</assert>
<assert id="SE-R-004" test="string-length(normalize-space(ram:ID)) = 10" flag="warning">Swedish organisation numbers consist of 10 characters.</assert>
<assert id="SE-R-013" test="u:checkSEOrgnr(normalize-space(ram:ID))" flag="warning">The last digit of a Swedish organization number must be valid according to the Luhn algorithm.</assert>
</rule>
<rule context="rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty[ram:PostalTradeAddress/ram:CountryID = 'SE' and ram:SpecifiedLegalOrganization/ram:ID]/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'FC']">
<assert id="SE-R-005" test="normalize-space(upper-case(.)) = 'GODKÄND FÖR F-SKATT'" flag="fatal">For Swedish suppliers, when using Seller tax registration identifier, 'Godkänd för F-skatt' must be stated</assert>
Expand Down Expand Up @@ -482,7 +511,11 @@ Last update: 2022 May release 3.0.13.

<rule context="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation[$supplierCountryIsNL]">
<!-- Original rule in NLCIUS: BR-NL-11 -->
<assert id="NL-R-007" test="xs:decimal(ram:DuePayableAmount) &lt;= 0.0 or (/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans)" flag="fatal">[NL-R-007] For suppliers in the Netherlands, the supplier MUST provide a means of payment (ram:SpecifiedTradeSettlementPaymentMeans) if the payment is from customer to supplier</assert>
<assert id="NL-R-007" test="(normalize-space(/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:TypeCode/text()) != '381' and
xs:decimal(ram:DuePayableAmount) &lt;= 0.0) or
(normalize-space(/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:TypeCode/text()) = '381' and
xs:decimal(ram:DuePayableAmount) &gt;= 0.0) or
(/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans)" flag="fatal">[NL-R-007] For suppliers in the Netherlands, the supplier MUST provide a means of payment (ram:SpecifiedTradeSettlementPaymentMeans) if the payment is from customer to supplier</assert>
</rule>

<rule context="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans[$supplierCountryIsNL]">
Expand Down
32 changes: 30 additions & 2 deletions rules/sch/PEPPOL-EN16931-UBL.sch
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,33 @@ Last update: 2023 May release 3.0.15.
(number($digits[1])*256) "/>
<value-of select="($checksum mod 11) mod 10 = number($digits[9])"/>
</function>

<!-- Function for Swedish organisation numbers (0007) -->
<function xmlns="http://www.w3.org/1999/XSL/Transform" name="u:checkSEOrgnr" as="xs:boolean">
<param name="number" as="xs:string"/>
<choose>
<!-- Check if input is numeric -->
<when test="not(matches($number, '^\d+$'))">
<sequence select="false()"/>
</when>
<otherwise>
<!-- verify the check number of the provided identifier according to the Luhn algorithm-->
<variable name="mainPart" select="substring($number, 1, 9)"/>
<variable name="checkDigit" select="substring($number, 10, 1)"/>
<variable name="sum" as="xs:integer">
<value-of select="sum(
for $pos in 1 to string-length($mainPart) return
if ($pos mod 2 = 1)
then (number(substring($mainPart, string-length($mainPart) - $pos + 1, 1)) * 2) mod 10 +
(number(substring($mainPart, string-length($mainPart) - $pos + 1, 1)) * 2) idiv 10
else number(substring($mainPart, string-length($mainPart) - $pos + 1, 1))
)"/>
</variable>
<variable name="calculatedCheckDigit" select="(10 - $sum mod 10) mod 10"/>
<sequence select="$calculatedCheckDigit = number($checkDigit)"/>
</otherwise>
</choose>
</function>
<!-- Empty elements -->
<pattern>
<rule context="//*[not(*) and not(normalize-space())]">
Expand Down Expand Up @@ -362,7 +389,7 @@ Last update: 2023 May release 3.0.15.
<assert id="PEPPOL-COMMON-R048" test="u:checkPIVAseIT(normalize-space())" flag="warning">Italian VAT Code (Partita Iva) must be stated in the correct format</assert>
</rule> -->
<rule context="cbc:EndpointID[@schemeID = '0007'] | cac:PartyIdentification/cbc:ID[@schemeID = '0007'] | cbc:CompanyID[@schemeID = '0007']">
<assert id="PEPPOL-COMMON-R049" test="string-length(normalize-space()) = 10 and string(number(normalize-space())) != 'NaN'" flag="fatal">Swedish organization number MUST be stated in the correct format.</assert>
<assert id="PEPPOL-COMMON-R049" test="string-length(normalize-space()) = 10 and string(number(normalize-space())) != 'NaN' and u:checkSEOrgnr(normalize-space())" flag="fatal">Swedish organization number MUST be stated in the correct format.</assert>
</rule>
<rule context="cbc:EndpointID[@schemeID = '0151'] | cac:PartyIdentification/cbc:ID[@schemeID = '0151'] | cbc:CompanyID[@schemeID = '0151']">
<assert id="PEPPOL-COMMON-R050" test="matches(normalize-space(), '^[0-9]{11}$') and u:abn(normalize-space())" flag="fatal">Australian Business Number (ABN) MUST be stated in the correct format.</assert>
Expand Down Expand Up @@ -471,6 +498,7 @@ Last update: 2023 May release 3.0.15.
<rule context="//cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity[../cac:PostalAddress/cac:Country/cbc:IdentificationCode = 'SE' and cbc:CompanyID]">
<assert id="SE-R-003" test="string(number(cbc:CompanyID)) != 'NaN'" flag="warning">Swedish organisation numbers should be numeric.</assert>
<assert id="SE-R-004" test="string-length(normalize-space(cbc:CompanyID)) = 10" flag="warning">Swedish organisation numbers consist of 10 characters.</assert>
<assert id="SE-R-013" test="u:checkSEOrgnr(normalize-space(cbc:CompanyID))" flag="warning">The last digit of a Swedish organization number must be valid according to the Luhn algorithm.</assert>
</rule>
<rule context="//cac:AccountingSupplierParty/cac:Party[cac:PostalAddress/cac:Country/cbc:IdentificationCode = 'SE' and exists(cac:PartyLegalEntity/cbc:CompanyID)]/cac:PartyTaxScheme[normalize-space(upper-case(cac:TaxScheme/cbc:ID)) != 'VAT']/cbc:CompanyID">
<assert id="SE-R-005" test="normalize-space(upper-case(.)) = 'GODKÄND FÖR F-SKATT'" flag="fatal">For Swedish suppliers, when using Seller tax registration identifier, 'Godkänd för F-skatt' must be stated</assert>
Expand Down Expand Up @@ -638,7 +666,7 @@ Last update: 2023 May release 3.0.15.
</rule>
<rule context="cac:LegalMonetaryTotal[$supplierCountryIsNL]">
<!-- Original rule in NLCIUS: BR-NL-11 -->
<assert id="NL-R-007" test="xs:decimal(cbc:PayableAmount) &lt;= 0.0 or (//cac:PaymentMeans)" flag="fatal">[NL-R-007] For suppliers in the Netherlands, the supplier MUST provide a means of payment (cac:PaymentMeans) if the payment is from customer to supplier</assert>
<assert id="NL-R-007" test="(/ubl-invoice:Invoice and xs:decimal(cbc:PayableAmount) &lt;= 0.0) or (/ubl-creditnote:CreditNote and xs:decimal(cbc:PayableAmount) &gt;= 0.0) or (//cac:PaymentMeans)" flag="fatal">[NL-R-007] For suppliers in the Netherlands, the supplier MUST provide a means of payment (cac:PaymentMeans) if the payment is from customer to supplier</assert>
</rule>
<rule context="cac:PaymentMeans[$supplierCountryIsNL]">
<!-- Original rule in NLCIUS: BR-NL-12 -->
Expand Down
Loading

0 comments on commit 30bf64e

Please sign in to comment.