Views: 131
BIS Billing 3.0からJP PINT 0.9.3に引き継がれなかった検証ルール

pint-jp-resources-dev\trn-invoice\ディレクトリの下にはサンプルのデジタルインボイスが入ったexampleフォルダのほかスキーマトロンファイルが入ったschematronディレクトリがあり、ここに、AlignedルールファイルPINT-jurisdiction-aligned-rules.sch 及び SharedルールファイルPINT-UBL-validation-preprocessed.sch も含まれています。
残念ですが、これらのスキーマトロンでは、今回使用したテスト用のデジタルインボイスの不正を報告できません。

課税対象額の検算ルール
CEN-EN16931-UBL.sch には、Taxable amount per tax rateについての検算ルールBR-S-08が提供されていましたがJP PINT 0.9.3では引き継がれていませんので、C4利用事業者は改めて検算しなくてはいけません。
ここでは、どのようなルールだったか紹介します。
明細行の金額計算方法と検証ルールについての記事もお読みください。
ルールBR-S-08は、次のページからその定義内容が確認できます。
BIS Billing 3.0 EN16931 model bound to UBL BR-S-08
BR-S-08
For each different value of VAT category rate (BT-119) where the VAT category code (BT-118) is “Standard rated”, the VAT category taxable amount (BT-116) in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts (BT-131) plus the sum of document level charge amounts (BT-99) minus the sum of document level allowance amounts (BT-92) where the VAT category code (BT-151, BT-102, BT-95) is “Standard rated” and the VAT rate (BT-152, BT-103, BT-96) equals the VAT category rate (BT-119).
「課税分類コードが’s’の標準税率の課税分類ごとの税内訳情報(ibg-23)の課税基準額(ibt-131)は、課税分類コードが’s’の値引き後請求書明細行金額(税抜き)(ibt-131)の合計から課税分類コードが’s’の請求書レベルの返金(ibt-092)の合計金額を差し引いた金額に課税分類コードが’s’の請求書レベルの追加請求(ibt-099)の合計金額を加えた金額と等しいこと。」
スクリプトでは、InvoiceだけでなくCredit Noteも対象にしているうえに改行や段落付けもないので、とても読む気になれません。
定義内容を見やすく整理した内容を次に示します。
ここでは、Tax category codeが’S’のものについて、その税率ごとにTaxable amountが正しく計算されているか検証しています。
税区分及び税率ごとの課税対象額は、適格請求書の記載事項でもあり重要な値です。
欧州では、標準税率の中に複数の税率が定義されていますので、every $rate in xs:decimal(cbc:Percent) satisfies ( … )という計算で税区分及び税率ごとに値が正しいか判定しています。
税区分が’S’の明細行と税区分が’S’の文書単位の返金と税区分が’S’の文書単位の追加請求を合計した金額が課税対象額の値と比較して±1の範囲に収まっているか確認しています。
<rule context="/*/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory[normalize-space(cbc:ID)='S'][cac:TaxScheme/normalize-space(upper-case(cbc:ID))='VAT']">
<assert id="BR-S-08" flag="fatal" test="
every $rate in xs:decimal(cbc:Percent) satisfies (
(
(
exists(/*/cac:InvoiceLine[cac:Item/cac:ClassifiedTaxCategory/normalize-space(cbc:ID)='S'][cac:Item/cac:ClassifiedTaxCategory/xs:decimal(cbc:Percent)=$rate]) or
exists(/*/cac:AllowanceCharge[cac:TaxCategory/normalize-space(cbc:ID)='S'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate])
) and
(
(
../xs:decimal(cbc:TaxableAmount - 1) <
(
sum(/*/cac:InvoiceLine[cac:Item/cac:ClassifiedTaxCategory/normalize-space(cbc:ID)='S'][cac:Item/cac:ClassifiedTaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:LineExtensionAmount)) +
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=true()][cac:TaxCategory/normalize-space(cbc:ID)='S'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount)) -
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=false()][cac:TaxCategory/normalize-space(cbc:ID)='S'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount))
)
) and
(
../xs:decimal(cbc:TaxableAmount + 1) >
(
sum(/*/cac:InvoiceLine[cac:Item/cac:ClassifiedTaxCategory/normalize-space(cbc:ID)='S'][cac:Item/cac:ClassifiedTaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:LineExtensionAmount)) +
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=true()][cac:TaxCategory/normalize-space(cbc:ID)='S'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount)) -
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=false()][cac:TaxCategory/normalize-space(cbc:ID)='S'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount))
)
)
)
)) ">[BR-S-08]-For each different value of VAT category rate (BT-119) where the VAT category code (BT-118) is "Standard rated", the VAT category taxable amount (BT-116) in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts (BT-131) plus the sum of document level charge amounts (BT-99) minus the sum of document level allowance amounts (BT-92) where the VAT category code (BT-151, BT-102, BT-95) is "Standard rated" and the VAT rate (BT-152, BT-103, BT-96) equals the VAT category rate (BT-119).</assert>
</rule></code>
日本では、軽減税率’AA’もありますので、次のようなルールが必要と思います。
<rule context="/*/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory[normalize-space(cbc:ID)='AA'][cac:TaxScheme/normalize-space(upper-case(cbc:ID))='VAT']">
<assert id="BR-AA-08" flag="fatal" test="
every $rate in xs:decimal(cbc:Percent) satisfies (
(
(
exists(/*/cac:InvoiceLine[cac:Item/cac:ClassifiedTaxCategory/normalize-space(cbc:ID)='AA'][cac:Item/cac:ClassifiedTaxCategory/xs:decimal(cbc:Percent)=$rate]) or
exists(/*/cac:AllowanceCharge[cac:TaxCategory/normalize-space(cbc:ID)='AA'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate])
) and
(
(
../xs:decimal(cbc:TaxableAmount - 1) <
(
sum(/*/cac:InvoiceLine[cac:Item/cac:ClassifiedTaxCategory/normalize-space(cbc:ID)='AA'][cac:Item/cac:ClassifiedTaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:LineExtensionAmount)) +
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=true()][cac:TaxCategory/normalize-space(cbc:ID)='AA'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount)) -
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=false()][cac:TaxCategory/normalize-space(cbc:ID)='AA'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount))
)
) and
(
../xs:decimal(cbc:TaxableAmount + 1) >
(
sum(/*/cac:InvoiceLine[cac:Item/cac:ClassifiedTaxCategory/normalize-space(cbc:ID)='AA'][cac:Item/cac:ClassifiedTaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:LineExtensionAmount)) +
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=true()][cac:TaxCategory/normalize-space(cbc:ID)='AA'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount)) -
sum(/*/cac:AllowanceCharge[cbc:ChargeIndicator=false()][cac:TaxCategory/normalize-space(cbc:ID)='AA'][cac:TaxCategory/xs:decimal(cbc:Percent)=$rate]/xs:decimal(cbc:Amount))
)
)
)
)) ">[BR-AA-08]-For each different value of VAT category rate (BT-119) where the VAT category code (BT-118) is "Reduced rated", the VAT category taxable amount (BT-116) in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts (BT-131) plus the sum of document level charge amounts (BT-99) minus the sum of document level allowance amounts (BT-92) where the VAT category code (BT-151, BT-102, BT-95) is "Reduced rated" and the VAT rate (BT-152, BT-103, BT-96) equals the VAT category rate (BT-119).</assert>
</rule></code>
これらのチェックは、BIS Billing 3.0ではC2で実施されていましたが、JP PINT 0.9.3では実施されずにC4に届きますので、C4では後続アプリの処理に渡す前にこうしたチェックプロセスが必要です。また、このチェックで問題が発見された際には、その旨連絡するメッセージを返送したいものです。Open Peppolでは、メッセージレベルの応答も可能なので、検討いただきたいと思います。
BISインボイス応答については、こちらの記事をお読みください。
明細行の合計金額
ibt−131 値引後請求書明細行金額(税抜き) =
ibt-146 品目単価(値引/割引後)(税抜き) × (ibt-129 請求される数量 ÷ ibt-149 品目単価基準数量) + Σ ibt-141 請求書明細行の追加請求金額(税抜き) − Σ ibt-136 請求書明細行の返金金額(税抜き)
欧州規格では、消費税課税対象金額(税抜き)は小数点以下第2位に四捨五入する必要があるため、計算のさまざまな部分を個別に四捨五入する必要があることに注意。
請求される金額は、小数点以下第2位に四捨五入する必要があります。また、請求書明細行の追加請求金額(税抜き)の合計 及び請求書明細行の追加請求金額(税抜き)の合計も個別に四捨五入されます。次のスクリプト中の100倍した金額にround()関数で丸めた金額を求めた後100で割っている箇所を確認してください。allowancesTotalおよびchargesTotalです。
PEPPOL-EN16931-R120
Invoice line net amount MUST equal (Invoiced quantity * (Item net price/item price base quantity) + Sum of invoice line charge amount - sum of invoice line allowance amount
Rules for Peppol BIS 3.0 Billing PEPPOL-EN16931-R120
このルールでは、記載された値と計算結果を比較し妥当性を判定する関数 slack() が使用されています。また、判定ルールは変数を使用して見やすい表記となっています。
<function xmlns="http://www.w3.org/1999/XSL/Transform" name="u:slack" as="xs:boolean">
<param name="exp" as="xs:decimal"/>
<param name="val" as="xs:decimal"/>
<param name="slack" as="xs:decimal"/>
<value-of select="xs:decimal($exp + $slack) >= $val and xs:decimal($exp - $slack) <= $val"/>
</function>
<rule context="cac:InvoiceLine | cac:CreditNoteLine">
<let name="lineExtensionAmount" value="
if (cbc:LineExtensionAmount) then
xs:decimal(cbc:LineExtensionAmount)
else
0"/>
<let name="quantity" value="
if (/ubl-invoice:Invoice) then
(if (cbc:InvoicedQuantity) then
xs:decimal(cbc:InvoicedQuantity)
else
1)
else
(if (cbc:CreditedQuantity) then
xs:decimal(cbc:CreditedQuantity)
else
1)"/>
<let name="priceAmount" value="
if (cac:Price/cbc:PriceAmount) then
xs:decimal(cac:Price/cbc:PriceAmount)
else
0"/>
<let name="baseQuantity" value="
if (cac:Price/cbc:BaseQuantity and xs:decimal(cac:Price/cbc:BaseQuantity) != 0) then
xs:decimal(cac:Price/cbc:BaseQuantity)
else
1"/>
<let name="allowancesTotal" value="
if (cac:AllowanceCharge[normalize-space(cbc:ChargeIndicator) = 'false']) then
round(sum(cac:AllowanceCharge[normalize-space(cbc:ChargeIndicator) = 'false']/cbc:Amount/xs:decimal(.)) * 10 * 10) div 100
else
0"/>
<let name="chargesTotal" value="
if (cac:AllowanceCharge[normalize-space(cbc:ChargeIndicator) = 'true']) then
round(sum(cac:AllowanceCharge[normalize-space(cbc:ChargeIndicator) = 'true']/cbc:Amount/xs:decimal(.)) * 10 * 10) div 100
else
0"/>
<assert id="PEPPOL-EN16931-R120" test="u:slack($lineExtensionAmount, ($quantity * ($priceAmount div $baseQuantity)) + $chargesTotal - $allowancesTotal, 0.02)" flag="fatal">Invoice line net amount MUST equal (Invoiced quantity * (Item net price/item price base quantity) + Sum of invoice line charge amount - sum of invoice line allowance amount</assert>
</rule>
ここでは、判定基準のslack値が0.02となっていますが、円単位の金額表示では0.02円でなく1円か2円を基準とした判定が妥当と思います。
次のファイルは、JP PINT SharedルールおよびAlignedルールではエラーは報告されませんが、上記ルールを適用するとエラーが報告されます。
テスト用デジタルインボイス(データ不正あり)
このファイルは、AlignedルールファイルPINT-jurisdiction-aligned-rules.sch 及び SharedルールファイルPINT-UBL-validation-preprocessed.schではエラーは報告されません。
<ubl:Invoice
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 http://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-Invoice-2.1.xsd">
<!-- tag::profile[] -->
<cbc:CustomizationID>urn:fdc:peppol:jp:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<!-- end::profile[] -->
<cbc:ID>000016</cbc:ID>
<cbc:IssueDate>2023-11-10</cbc:IssueDate>
<cbc:IssueTime>19:36:55</cbc:IssueTime>
<cbc:DueDate>2023-11-30</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>JPY</cbc:DocumentCurrencyCode>
<cac:InvoicePeriod>
<cbc:StartDate>2023-10-02</cbc:StartDate>
<cbc:EndDate>2023-10-31</cbc:EndDate>
</cac:InvoicePeriod>
<!-- tag::seller[] -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0188">1234567890123</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID schemeID="0188">1234567890123</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>株式会社 ○○商事 △△部</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>四谷4</cbc:StreetName>
<cbc:AdditionalStreetName>29-X</cbc:AdditionalStreetName>
<cbc:CityName>新宿区</cbc:CityName>
<cbc:PostalZone>160-0044</cbc:PostalZone>
<cbc:CountrySubentity>東京都</cbc:CountrySubentity>
<cac:AddressLine>
<cbc:Line>〇〇商事ビル</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>JP</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>T1234567890123</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>株式会社 ○○商事</cbc:RegistrationName>
<cbc:CompanyID>1234567890123</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<!-- end::seller[] -->
<!-- tag::buyer[] -->
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0188">1234567890123</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>株式会社 □□物産 ◇◇支社_2</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>北区</cbc:StreetName>
<cbc:AdditionalStreetName>北十二条西76-X</cbc:AdditionalStreetName>
<cbc:CityName>札幌市</cbc:CityName>
<cbc:PostalZone>001-0012</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>JP</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyLegalEntity>
<cbc:RegistrationName>株式会社 □□物産_1</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<!-- end::buyer[] -->
<cac:PaymentMeans>
<cbc:PaymentMeansCode name="Credit transfer">30</cbc:PaymentMeansCode>
<cac:PayeeFinancialAccount>
<cbc:ID>0005:064:1:0123456</cbc:ID>
<cbc:Name>マルマルショウジカブシキガイシャ</cbc:Name>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:TaxTotal>
<!-- 合計税額-->
<cbc:TaxAmount currencyID="JPY">40400</cbc:TaxAmount>
<!-- 軽減税率(リンゴ)-->
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="JPY">500000</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="JPY">40000</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>AA</cbc:ID>
<cbc:Percent>8</cbc:Percent>
<cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<!-- 通常税率(商品ポップ)-->
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="JPY">4000</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="JPY">400</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>10</cbc:Percent>
<cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="JPY">54000</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="JPY">54000</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="JPY">94400</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="JPY">94400</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<!-- tag::invoice line[] -->
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="H87">5</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="JPY">50000</cbc:LineExtensionAmount>
<cac:DocumentReference>
<cbc:ID>2031</cbc:ID>
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
</cac:DocumentReference>
<cac:Item>
<cbc:Description>津軽産リンゴ高級贈答用</cbc:Description>
<cbc:Name>りんご</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>AA</cbc:ID>
<cbc:Percent>8.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
<cac:AdditionalItemProperty>
<cbc:Name>個</cbc:Name>
<cbc:Value>1</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="JPY">1000</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
<!-- end::invoice line[] -->
<!-- tag::invoice line[] -->
<cac:InvoiceLine>
<cbc:ID>2</cbc:ID>
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="JPY">4000</cbc:LineExtensionAmount>
<cac:DocumentReference>
<cbc:ID>2021</cbc:ID>
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
</cac:DocumentReference>
<cac:Item>
<cbc:Description>吹き出し付きポップ</cbc:Description>
<cbc:Name>商品ポップ</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>10.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
<cac:AdditionalItemProperty>
<cbc:Name>個</cbc:Name>
<cbc:Value>1</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="JPY">200</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
<!-- end::invoice line[] -->
</ubl:Invoice>
検証結果 XML ValidatorBuddy on Windows 10
BR-AA-08

PEPPOL-EN16931-R120
