Search Posts

Visits: 640

ibt-150でそれぞれH87, XIK, XBOと異なる数量単位コードを指定していたのは誤りでした。
BIS Billing 3.0では、次のルールがあり、同じ数量単位でないといけません。ここでは、全てH87。
PEPPOL-EN16931-R130
Unit code of price base quantity MUST be same as invoiced quantity.

この前提の上で、
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
という計算での(Item net price/item price base quantity)が使用できます。


計算方法

荷姿が異なる場合(再考)

ビール等の販売で1缶単位・1パックもしくは1カートンでの電子インボイスのデータ設定はどうなるでしょうか。
荷姿に応じて商品番号を個別に設定せず、共通の商品番号としているときには、荷姿に応じて異なる数量単位コードを指定し、そのコードから単位当たりの数量を求める必要があるとしていましたが、実務上の大幅な負担になりかねないので、再考しました。

例えば、40缶購入するときに、1カートン、2パック、4缶購入したとします。
このときには、1カートン、2パック、6缶と数量単位が異なるので明細行をそれそれ記載しますが請求数量の単位は全て同じ値を指定します。

40[缶] = 24[缶/カートン] × 1[カートン] + 6[缶/パック] × 2[パック] + 1×4[缶]
= 24[缶] + 12[缶] + 4[缶]

単位としてH87(Piece)を使用し表示用の荷姿単位を別の項目で指定する

この場合は、ibg-32 ITEM ATTRIBUTESに荷姿の数量単位を記載します。単位が、Piece(個数)ですので、請求数量がそれぞれ24、12、4と入っている缶の数が記載されていますので、データを表示する際にibt-129Invoiced quantityをibt-149Item price base quantityで割った値を画面や超表情に表示変換する必要があります。

荷姿ごとに明細行を分けると次のような設定です。
請求数量がデータに記載された値としては不自然な感じになりますが、表示変換で馴染みある表記に変換する対応が可能です。

Value
ID Business Term
  カートン パック
ibg-25 INVOICE LINE
ibt-129 • Invoiced quantity 24 12 4
ibt-130 • Invoiced quantity unit of measure code H87 H87 H87
ibt-131 • Invoice line net amount 4800 2400 800
ibg-29 • PRICE DETAILS
ibt-146 • • Item net price 4800 1200 200
ibt-149 • • Item price base quantity 24 6 1
ibt-150 • • Item price base quantity unit of measure code H87 H87 H87
ibg-31 • ITEM INFORMATION
ibt-153 • • Item name ビール ビール ビール
ibg-31 • • ITEM ATTRIBUTES
ibt-149 • • • Item attribute name 単位 単位 単位
ibt-150 • • • Item attribute value カートン パック

100gあたり800円の牛肉

この牛肉を320g購入するときには、次のような値を設定します。
次の表のValue欄に記載しているCTGは、数量単位コード(Unit of measurement)でRecommendation 20, including Recommendation 21 codes – prefixed with X (UN/ECE)で規定されています。
数量単位コードの代表的な値は、Peppol BIS Billing JP 0.9 8.9 Unit of measure にも記載されています。

注意:
既存の請求業務ソフトでこのような標準コードを使用していないときには、Open Peppol対応のために、商品マスターの数量単位コードの設定追加が必要となります。
設定された値が標準コードの値でないと、アクセスポイントでの電子インボイスの形式検証ルールチェックでエラーとなり、受け付けられません。
数量単位コードの他にも、標準コードリストからの値を設定しなければいけない項目があります。
売り手、買い手それぞれで取引先相互で各種マスターの設定内容を共通な値に設定しておくことが必要があります。
運用上の調整が必要な事項の一つです。

ID Business Term Value
ibg-25 INVOICE LINE
ibt-129 • Invoiced quantity 320
ibt-130 • Invoiced quantity unit of measure code CTG
ibt-131 • Invoice line net amount 2560
ibg-29 • PRICE DETAILS
ibt-146 • • Item net price 800
ibt-149 • • Item price base quantity 100
ibt-150 • • Item price base quantity unit of measure code CTG

7.2.2. Invoice line net amount (IBT-131)で明細行の金額計算方法が規定されています。
Item line net amount (IBT-131) =
(Item net price (IBT-146) ÷ Item price base quantity (IBT-149)) × (Invoiced Quantity (IBT-129)) + Invoice line charge amount (IBT-141) − Invoice line allowance amount (IBT-136)
従って、(800 ÷ 100) × 320 = 2560 ですので、2560円です。

3個で1000円

このときには、ibt-149 Item price base quantityが3で、数量単位は個(H87)です。
この商品を12個購入するときの金額は、(1000 ÷ 3) × 12 = 4000となります。

ID Business Term Value
ibg-25 INVOICE LINE
ibt-129 • Invoiced quantity 12
ibt-130 • Invoiced quantity unit of measure code H87
ibt-131 • Invoice line net amount 4000
ibg-29 • PRICE DETAILS
ibt-146 • • Item net price 1000
ibt-149 • • Item price base quantity 3
ibt-150 • • Item price base quantity unit of measure code H87

さて、12個でなく10個買ったときの計算はどうなるでしょうか。
(1000 ÷ 3) × 10 = 3333.3333 … となりますが、通常、切り上げるか四捨五入するか切り捨てるかして端数のない金額に丸めます。四捨五入して3333としたときの例を次に示します。

明細行の金額の検証ルールについては後述します。

ID Business Term Value
ibg-25 INVOICE LINE
ibt-129 • Invoiced quantity 10
ibt-130 • Invoiced quantity unit of measure code H87
ibt-131 • Invoice line net amount 3333
ibg-29 • PRICE DETAILS
ibt-146 • • Item net price 1000
ibt-149 • • Item price base quantity 3
ibt-150 • • Item price base quantity unit of measure code H87

荷姿が異なる場合

ビール等の販売で1缶単位・1パックもしくは1カートンでのデータ設定ではどうでしょうか。
例えば、40缶購入するときに、1カートン、2パック、4缶購入したとします。
このときには、1カートン、2パック、6缶と数量単位が異なるので明細行をそれそれ記載します。

Code Name 数量
XCT Carton 24
XIK Package, cardboard, with bottle grip-holes
Packaging material made out of cardboard that facilitates the separation of individual glass or plastic bottles.
6
XBO Bottle, non-protected, cylindrical
A narrow-necked cylindrical shaped vessel without external protective packing material.
1

40[缶] = 24[缶/カートン] × 1[カートン] + 6[缶/パック] × 2[パック] + 1×4[缶]

注意:
荷姿に応じて商品番号を個別に設定せず、共通の商品番号としているときには、数量単位コードから単位当たりの数量を求める必要があるかもしてません。

荷姿ごとに明細行を分けると次のような設定です。

ID Business Term Value
  カートン パック
ibg-25 INVOICE LINE
ibt-129 • Invoiced quantity 1 2 4
ibt-130 • Invoiced quantity unit of measure code XCT XIK XBO
ibt-131 • Invoice line net amount 4800 2400 800
ibg-29 • PRICE DETAILS
ibt-146 • • Item net price 4800 1200 200
ibt-149 • • Item price base quantity 1 1 1
ibt-150 • • Item price base quantity unit of measure code XCT XIK XBO

荷姿に応じて値引きが設定されているときには、次のようになります。
値引額は、1カートン当たり800、1パックあたり100とします。

ID Business Term Value
  カートン パック
ibg-25 INVOICE LINE
ibt-129 • Invoiced quantity 1 2 4
ibt-130 • Invoiced quantity unit of measure code XCT XIK XBO
ibt-131 • Invoice line net amount 4000 2200 800
ibg-29 • PRICE DETAILS
ibt-146 • • Item net price 4000 1100 200
ibt-147 • • Item price discount 800 100 0
ibt-148 • • Item gross price 4800 1200 200
ibt-149 • • Item price base quantity 1 1 1
ibt-150 • • Item price base quantity unit of measure code XCT XIK XBO

合計金額と消費税額の記載方法

5.11 Invoice examplesの例をインボイスデータの階層がわかる形式で表示したページが5.11 Invoice examplesです。こちらも合わせてご確認ください。

計算金額に対するチェックルール

https://www.wuwei.space/jp_pint/billing-japan/syntax/ubl-invoice/cac-InvoiceLine/cbc-LineExtensionAmount/en/
チェック対象の指定
Context
/ubl:Invoice[cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cac:Country/cbc:IdentificationCode = ‘JP’ ]/cac:InvoiceLine
チェック条件
Test

( exists(cac:Price/cbc:BaseQuantity) and
  ( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) and
    exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) and
    ( cbc:LineExtensionAmount =
      cbc:InvoicedQuantity * (cac:Price/cbc:PriceAmount div cac:Price/cbc:BaseQuantity) +
      cac:AllowanceCharge[cbc:ChargeIndicator=true()]/cbc:Amount -
      cac:AllowanceCharge[cbc:ChargeIndicator=false()]/cbc:Amount 
    )
  ) or
  ( not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) ) and
    exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) and
    ( cbc:LineExtensionAmount = 
      cbc:InvoicedQuantity * (cac:Price/cbc:PriceAmount div cac:Price/cbc:BaseQuantity) +
      cac:AllowanceCharge[cbc:ChargeIndicator=true()]/cbc:Amount
    )
  ) or 
  ( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) and
    not(exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()])) and
    ( cbc:LineExtensionAmount =
      cbc:InvoicedQuantity * (cac:Price/cbc:PriceAmount div cac:Price/cbc:BaseQuantity) -
      cac:AllowanceCharge[cbc:ChargeIndicator=false()]/cbc:Amount
    )
  ) or 
  ( not(exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()])) and
    not(exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()])) and 
    ( cbc:LineExtensionAmount = 
      cbc:InvoicedQuantity * (cac:Price/cbc:PriceAmount div cac:Price/cbc:BaseQuantity)
    )
  )
) or 
( not(exists(cac:Price/cbc:BaseQuantity)) and
  ( 
    ( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) and
      exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) and
      ( cbc:LineExtensionAmount =
        cbc:InvoicedQuantity * cac:Price/cbc:PriceAmount +
        cac:AllowanceCharge[cbc:ChargeIndicator=true()]/cbc:Amount -
        cac:AllowanceCharge[cbc:ChargeIndicator=false()]/cbc:Amount 
      )
    ) or 
    ( not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) ) and
      exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) and 
      ( cbc:LineExtensionAmount =
        cbc:InvoicedQuantity * cac:Price/cbc:PriceAmount + 
        cac:AllowanceCharge[cbc:ChargeIndicator=true()]/cbc:Amount
      )
    ) or 
    ( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) and
      not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) ) and 
      ( cbc:LineExtensionAmount = 
        cbc:InvoicedQuantity * cac:Price/cbc:PriceAmount - 
        cac:AllowanceCharge[cbc:ChargeIndicator=false()]/cbc:Amount
      )
    ) or 
    ( not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) ) and 
      not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) ) and 
      ( cbc:LineExtensionAmount = 
        cbc:InvoicedQuantity * cac:Price/cbc:PriceAmount
      )
    ) or
    ( not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=false()]) ) and 
      not( exists(cac:AllowanceCharge[cbc:ChargeIndicator=true()]) ) and 
      ( cbc:LineExtensionAmount = 
        cbc:InvoicedQuantity * cac:Price/cbc:PriceAmount
      )
    )
  )
)

ibt-149 Item price base quantityは任意項目なので、指定されないときには、1 として扱います。
この箇所のBIS Billing 3.0ルール定義(PEPPOL-EN16931-UBL.sch)は、次のように変数を使用して簡潔な定義です。

    <!-- Line level - line extension amount -->
    <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>
      <assert id="PEPPOL-EN16931-R121" test="not(cac:Price/cbc:BaseQuantity) or xs:decimal(cac:Price/cbc:BaseQuantity) &gt; 0" flag="fatal">Base quantity MUST be a positive number above zero.</assert>
    </rule>

また、金額計算には、slack()関数を用いており、計算結果が0.02の単位金額の範囲内に収まっているかを検証しています。

u:slack(exp,val,slack)は、次の判定を行う関数です。
(exp + slack) >= val and (exp – $slack) <= val
つまり、
val – slack <= exp <= val + slack
上記の例では、
exp = $lineExtensionAmount
val = ($quantity * ($priceAmount div $baseQuantity)) + $chargesTotal – $allowancesTotal
slack = 0.02
なので、計算結果が、lineExtensionAmount ± 0.02 の範囲内かを判定しています。

	<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) &gt;= $val and xs:decimal($exp - $slack) &lt;= $val"/>
	</function>