ラベル XML の投稿を表示しています。 すべての投稿を表示
ラベル XML の投稿を表示しています。 すべての投稿を表示

2023年3月17日金曜日

表形式のデータからPeppolのデジタルインボイスを生成する

先日の記事Peppolのデジタルインボイスを表形式で表示するにて、XMLのデータを読み込んで表形式に変換するビューを作成しました。今度は逆に表からXMLを生成するビューを作成します。

デジタルインボイスを表形式で表示するために、20のビューを作成しています。それらを逆にXMLとして表示するためのビューとして、以下の20のビューを作成します。

PEPPOL_INVOICE_XV

PEPPOL_INVOICE_BILLING_REFERENCE_XV

PEPPOL_INVOICE_ADDITIONAL_DOCUMENT_REFERENCE_XV

PEPPOL_INVOICE_ACCOUNTING_SUPPLIER_PARTY_XV

PEPPOL_INVOICE_ACCOUNTING_CUSTOMER_PARTY_XV

PEPPOL_INVOICE_PAYEE_PARTY_XV

PEPPOL_INVOICE_TAX_REPRESENTATIVE_PARTY_XV

PEPPOL_INVOICE_DELIVERY_XV

PEPPOL_INVOICE_PAYMENT_MEANS_XV

PEPPOL_INVOICE_PAYMENT_TERMS_XV

PEPPOL_INVOICE_PREPAID_PAYMENT_XV

PEPPOL_INVOICE_ALLOWANCE_CHARGE_XV

PEPPOL_INVOICE_TAX_TOTAL_XV

PEPPOL_INVOICE_TAX_TOTAL_TAX_SUBTOTAL_XV

PEPPOL_INVOICE_INVOICE_LINE_XV

PEPPOL_INVOICE_INVOICE_LINE_DOCUMENT_REFERENCE_XV

PEPPOL_INVOICE_INVOICE_LINE_ALLOWANCE_CHARGE_XV

PEPPOL_INVOICE_INVOICE_LINE_ITEM_ADDITIONAL_ITEM_PROPERTY_XV

PEPPOL_INVOICE_INVOICE_LINE_ITEM_CLASSIFIED_TAX_CATEGORY_XV

PEPPOL_INVOICE_INVOICE_LINE_ITEM_COMMODITY_CLASSIFICATION_XV


ビューのDDLは記事の末尾に添付します。

サンプルのデジタルインボイスは、表PEPPOL_DOCUMENTSの列INVOICEにXMLTYPEとして保存しています。表形式にしたデータから再度XML形式のデータを生成し、元のデジタルインボイスと比較することで、XMLと表の間の変換が正しく行われていることを確認します。

表PEPPOL_DOCUMENTSに再変換したXMLを保存する列RESULTを追加します。

alter table peppol_documents add (result xmltype);


列RESULTに再変換したデジタルインボイスを保存します。
update peppol_documents d
set
d.result =
(
    select i."Invoice" from peppol_invoice_xv i 
    where d.id = i.invoice_id
)
;


列INVOICEと列RESULTの差分を確認します。ファンクションXMLDIFFを使用します。

select xmldiff(invoice,result) from peppol_documents


差分の情報が表示されますが、以下のようにほとんどはコメントの差分です。

<xd:delete-node xd:node-type="comment" xd:xpath="/oraxdfns_0:Invoice[1]/comment()[1]"/>

以下のSELECT文を実行し、コメントに関する差分を除いて表示します。


結果が0行であれば、元のXMLと生成したXMLに違いがないと言えます。


XMLDIFFでは、XML要素の配列の出現順序が異なると差分として報告されます。本来であれば、配列の出現順序を気に掛ける必要はありません。今回はデバッグのためサンプルのデジタルインボイスと完全に一致していることが確認できるように、XMLから表形式にするビューにrownum(列名としてはseq_id)を含めて出現順序を参照できるようにしています。逆に表形式からXMLにする際には、ファンクションXMLAGGの引数としてorder by seq_idを加えています。

上記の調整を行ったビューを使って差分の確認をやり直し、結果が0行(つまりサンプルと一致している)になることは確認しました。


あくまでデジタル庁が提供しているサンプルのデータによる確認を行っただけにはなりますが、今時JSONではなくXMLを操作するコードを書くのも大変なので、手始めになるコードを書いてみました。

Oracle APEXのアプリケーション作成の参考になれば幸いです。


ビューを作成するDDL


2023年3月15日水曜日

Peppolのデジタルインボイスを表形式で表示する

 Oracle DatabaseにはXMLを扱う機能が組み込まれています。この機能を使って、デジタル庁が提供しているPeppolのデジタルインボイスのサンプルを表形式で表示してみます。

デジタルインボイスの標準仕様(JP PINT)については、デジタル庁のサイトで説明されています。

デジタルインボイスのサンプルは、こちらのサイトからダウンロードできるファイルpint-jp-resources-dev.zipに含まれています。


pint-jp-resources-dev.zipを展開すると、trn-invoice/example以下に9つのサンプルがあります。これらのファイルをOracle Databaseに読み込み、ファンクションXMLTABLEを使ってXMLから表形式のデータに変換します。

    20945  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example6-CorrInv.xml

     9210  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example2-TaxAcctCur.xml

    16042  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example4-SumInv2.xml

    21151  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example5-AllowanceCharge.xml

    21655  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example9-SumInv1 and O.xml

    19305  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example3-SumInv1.xml

     9817  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example1-minimum.xml

    12551  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example7-Return.Quan.ItPr.xml

    29603  10-25-2022 00:35   trn-invoice/example/Japan PINT Invoice UBL Example.xml

デジタルインボイスであるXMLファイルを保存するための表PEPPOL_DOCUMENTSを作成します。

以下のDDLを実行します。


アップロードしたファイルは列CONTENTにBLOBとして保存します。アップロードしたファイルをBLOBに保存したあとに、BLOBからXMLTYPEに変換し列INVOICEに保存します。

XMLTYPEで保存されているインボイスを表形式に変換します。XMLTABLEはビューから呼び出すように実装しました。以下のビューを作成します。左がビュー名、右が対応しているXML要素です。

XPathと列名の対応の確認を容易にするため、表名や列名に長い名前を付けています。識別子が30バイトまでという制限のある、古いOracle Databaseでは実行できません。

peppol_invoice_v:/Invoice
peppol_invoice_billing_reference_v:/Invoice/cac:BillingReference
peppol_invoice_additional_document_reference_v:/Invoice/cac:AdditionalDocumentReference
peppol_invoice_accounting_supplier_party_v:/Invoice/cac:AccountingSupplierParty
peppol_invoice_accounting_customer_party_v:/Invoice/cac:AccountingCustomerParty
peppol_invoice_payee_party_v:/Invoice/cac:PayeeParty
peppol_invoice_tax_representative_party_v:/Invoice/cac:TaxRepresentativeParty
peppol_invoice_delivery_v:/Invoice/cac:Delivery
peppol_invoice_payment_means_v:/Invoice/cac:PaymentMeans
peppol_invoice_payment_terms_v:/Invoice/cac:PaymentTerms
peppol_invoice_prepaid_payment_v:/Invoice/cac:PrepaidPayment
peppol_invoice_allowance_charge_v:/Invoice/cac:AllowanceCharge
peppol_invoice_tax_total_v:/Invoice/cac:TaxTotal
peppol_invoice_tax_total_tax_subtotal_v:/Invoice/cac:TaxTotal/cac:TaxSubtotal
peppol_invoice_invoice_line_v:/Invoice/cac:InvoiceLine
peppol_invoice_invoice_line_document_reference_v:/Invoice/cac:InvoiceLine/cac:DocumentReference
peppol_invoice_invoice_line_allowance_charge_v:/Invoice/cac:InvoiceLine/cac:AllowanceCharge
peppol_invoice_invoice_line_item_additonal_item_property_v:/Invoice/cac:InvoiceLine/cal:Item/cac:AdditionalItemProperty
peppol_invoice_invoice_line_item_classified_tax_property_v:/Invoice/cac:InvoiceLine/cal:Item/cac:ClassifiedTaxProperty
peppol_invoice_invoice_line_item_commodity_classification_v:/Invoice/cac:InvoiceLine/cal:Item/cac:CommodityClassification

ビューを作成するDDLは、記事の最後に添付します。

作成した表とビューを使って、デジタルインボイスのサンプルのアップロードと表示を行うAPEXアプリケーションを作ります。

アプリケーション作成ウィザードを起動します。名前Peppolとします。


デフォルトで作成されるホーム・ページを削除し、代わりに対話モード・レポートページを追加します。

ページ名はDocumentsとします。表またはビューPEPPOL_DOCUMENTSを選択します。


上記の設定でアプリケーションの作成をクリックします。

アプリケーションが作成されたら、ファイルのアップロードに関係する設定を修正します。

対話モード・レポートのページを開き、列CONTENTを選択します。

BLOB属性MIMEタイプ列ファイル名列最終更新列文字セット列として、それぞれCONTENT_MIMETYPECONTENT_FILENAMECONTENT_LASTUPDCONTENT_CHARSETを設定します。


フォームのページを開き、ページ・アイテムP2_CONTENTに同様の設定を行ないます。


ファイルのアップロード後に、BLOBをXMLTYPEに変換し保存するプロセスを作成します。

フォームのページでプロセス・ビューを開き、プロセスの作成を実行します。

作成したプロセスはプロセス・フォームPeppol Documentsダイアログを閉じるの間に配置します。識別名前バイナリXMLで保存タイプコードを実行を選択します。

ソースPL/SQLコードとして、以下のコードを記述します。BLOBのデータを、XMLTYPEに変換して列INVOICEに保存しています。
update peppol_documents 
    set invoice = sys.xmltype(content, NLS_CHARSET_ID('AL32UTF8'))
where id = :P2_ID;
サーバー側の条件タイプリクエストは値に含まれるを選択し、としてCREATE,SAVEを指定します。ボタン作成または変更の適用を押した時に、このプロセスが実行されます。


以上でサンプルのデジタルインボイスのアップロードができるようになりました。

アプリケーションを実行し、サンプルのファイルをアップロードします。


デジタルインボイスの内容を表示するページを作成します。

ページの作成を実行します。


空白のページを選択します。


ページ番号名前Invoiceとします。ページ・モード標準で、ナビゲーションはデフォルトのまま、変更しません。

ページの作成をクリックします。


ページInvoiceが作成されます。

最初にページ・プロパティナビゲーション保存されていない変更の警告OFFにします。表示するインボイスを切り替えたときに、警告が表示されないようになります。


表示するインボイスを選択するページ・アイテムを作成します。

識別名前P3_INVOICE_IDタイプとして選択リストを選びます。ラベルInvoiceとします。

設定選択時のページ・アクションとして、Redirect and Set Valueを選択します。

LOVタイプSQL問合せを選択し、SQL問合せとして以下を記述します。

select content_filename d, id r from peppol_documents

追加値の表示OFFNULL値の表示ONNULL表示値として-- Select Invoice --を記述します。


ビューPEPPOL_INVOICE_Vをソースとした対話モード・レポートを作成します。

作成した対話モード・レポートの識別タイトルInvoiceとします。タイプ対話モード・レポートです。ソース表名PEPPOL_INVOICE_Vを選択します。

WHERE句に以下を記述し、ページ・アイテムP3_INVOICE_IDで選択されているインボイスの内容が表示されるように限定します。(サンプルは9つだけなので、未選択の場合はすべてのインボイスについて表示します。)

:P3_INVOICE_ID is null or invoice_id = :P3_INVOICE_ID

外観テンプレートStandardを選択し、テンプレート・オプションRemove Body Paddingにチェックを入れます。テンプレートIntractive Reportの場合、レポートのタイトルが表示されません。


この時点でアプリケーションを実行すると、以下のようにビューPEPPOL_INVOICE_Vから参照できる情報がレポートに表示されます。


残り16個のビューについても、同様に対話モード・レポートを作成します。

重複を使うと作業が早くできます。


以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

今回作成したAPEXアプいケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/peppol.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。


ビューを作成するDDL