2016年12月17日土曜日

ADempiereの受注伝票の操作と機能

ここでは、ADempiereの受注伝票の操作と機能についてご紹介します。
  参考URL : http://www.adempiere.com/Sales_Processes




①伝票タイプの入力
ADempiereで受注伝票を新規に作成するときに、まず入力するのは、伝票タイプになります。
伝票タイプとは、受注伝票の処理、特に後続の伝票である出荷伝票や請求伝票、
入金伝票などとの関連処理を決定する重要な項目で
以下のような、さまざまな業務パターンを想定した伝票タイプが用意されています。
 
 ・提案伝票(Proposal)
 ・見積伝票(Quotation)
 ・標準受注(Standard Order)
 ・倉庫受注(Warehouse Order)
 ・信用受注(On Credit Order)
 ・POS受注(Point Of Sales)
 ・前受受注(Prepay Order)
  ※返品業務については、受注伝票でなく返品伝票(RMA)を使用します。

そして、これらの伝票タイプの違いは、以下のようになります。



 詳細は、図中に記載していますが、簡潔にまとめるとすると、それぞれの伝票タイプの主な違いは、後続のどの伝票を自動で作成するかと、在庫の予約をおこなうかどうかと、取引先にひもづくかどうかの3点の違いになるかと思います。
そして、それを簡潔に表した図が以下になり、伝票タイプによって、後続のどの伝票を完成させるかの範囲が変わってくることがわかるかと思います。
 ※画像は、ADempiere.comのものです。



 上記の図のように、伝票タイプが標準受注であれば、受注伝票を完成しても、出荷伝票や請求伝票、入金伝票などは、手動で入力していくことが基本になります。
 これは、その名(標準受注)のとおり、受注伝票の標準的な入力の仕方で、後続伝票もそれぞれの業務にあわせて、ひとつひとつ手動で入力していくことになります。
 (標準受注でも、実際には自動生成プロセス画面によって各伝票を作成できる。)

 しかし、たとえば、POS受注の場合、受注伝票完成により、出荷、請求、入金までの処理が自動でおこなわれることになります。

 これは、POSという業務を考えればわかりやすいと思いますが、
たとえば、コンビニのレジでジュースを買ったとき、コンビニ店の立場からみると、
顧客からの注文をもらい(受注)、商品(ジュース)を顧客に納品し(出荷)、
お買い上げ金額を伝え(請求)、お金を受け取る(入金)といった業務が一気におこなわれています。(これがPOSの業務)
 これをシステム(ERP)における伝票という形で置き換えると、受注伝票、出荷伝票、請求伝票、入金伝票が一気に作成されることとなります。

 このように、ADempiereでは、さまざまな業務を想定して、伝票タイプをあらかじめ用意しており
ここでは、POSについて詳しく説明しましたが、その他の提案伝票(Proposal)、見積伝票(Quotation)、倉庫受注(Warehouse Order)、信用受注(On Credit Order)、前受受注(Prepay Order)の伝票タイプについても、それぞれの業務パターンを想定してあらかじめ用意されています。
 ※在庫を持たない品目を登録して、サービス受注として受注伝票を作成することも可能です。

②取引先の入力
 伝票タイプを入力した後、次に入力するのは、取引先です。
 (ADempiereでは、伝票タイプによって入力項目が変わり画面表示が自動切換えされるため
  伝票タイプによっては、取引先入力が不要のものがあったり、表示される項目に相違があるため、
  前提条件として、ここからは、標準受注の伝票タイプを入力したものとして説明を続けます。)
 
 取引先を選択することによって、取引先に設定されている情報が受注伝票の初期値として提案されます。
 たとえば、ドル建ての取引先であれば、受注伝票の通貨がドル建てで初期値提案されたり、
 支払い条件、支払い方法、出荷先住所や請求先住所など、取引先に設定されている情報が初期値として設定されます。(もちろん、伝票側で変更可能)

 これによって、ユーザが手動で入力しなければいけない項目を大きく減らしています。
 取引先から初期値提案される項目には、以下のようなものがあります。



③日付の入力
 取引先を入力した後、次に入力するのは、日付です。(ごく基本的な入力手順では)
 受注日、出荷予定日、納期などを入力します。

④品目と数量の入力
 後は、明細で、品目と数量を入力します。
 品目を選択時に、品目価格が自動で設定されたり、在庫があるかの確認がおこなわれたりもします。
  このように、ADempiereの受注伝票は、ユーザの入力負担を減らして、効率的な入力が可能なように設計されています。
 これができるのは、技術的には、ADempiereのDB設計における正規化や関連性がしっかりしており、マスタとの連携を効率的におこなえるような仕組みがあるから実現できています。

⑤伝票ステータスの更新
 ADempiereの伝票には、ステータスというものがあり、これを完成することにより、受注伝票の完成処理がおこなわれます。
 ステータスは、その受注伝票の状態をあらわしていて、たとえば作成中であれば、草案というステータスになっています。

<その他の受注伝票機能>
 その他の機能としては、直送指定、プロジェクト管理(案件管理)、代理店、EDI連携、帳票出力、レポート出力、MRPへのインプットなどの機能があり、非常に豊富な機能が実装されています。

 また、必要な項目は、ノンプログラミングで自由に追加することができますので、各業種、各会社にあった項目を後から追加できます。
 さらに、表示、非表示の切り替え、表示位置の変更なども可能になっていますので、各社にあった項目や表示順で構成された受注伝票画面を構築することが可能になっています。
 

2016年12月10日土曜日

オートバキュームがされない原因は? (Postgres)

 Postgresは、MVCC(多版式同時実行制御)の追記型なので、新規行作成(INSERT)だけでなく、
更新(UPDATE)の場合も内部では行データ(タプルという)が新たに増えていきます。
そのため、UPDATEを繰り返すだけでも、データがどんどん増えていき、
パフォーマンスが極端に落ちてしまうことがあります。

これを解決するために、Postgresでは、不要な行データを削除すること(バキュームという)が
必要となってきます。

昔は、バキュームコマンドを定期的に実行する必要がありましたが、
最近のPostgresでは、オートバキューム機能があるため、特に気にすることもなく、
勝手にバキュームしてくれます。

と、思っていましたが・・・
どういうわけか、担当プロジェクトの大量データ処理で激しい処理落ちが・・・

そして、原因調査へ


■まずは、バキューム関係のパラメータを設定
バキュームログを出力して、状況の詳細を確認する。

Postgres.confで、バキュームログを出力するように設定
autovacuum = on
log_autovacuum_min_duration = 0

※postgresの再起動が必要
※postgres.confは、デフォルトなら「C:\Program Files\PostgreSQL\9.x\data」にあるはず。

■ログの確認
そして、再実行して、処理落ちがはじまったところでログを見てみると



やはり、タプルが残っていて、バキュームされていないように見える。
※このテーブル「ad_sequence」の実際の行は1479行であり、それに対してタプルが多すぎる。
※Postgresのログは、デフォルトなら「C:\Program Files\PostgreSQL\9.x\data\pg_log」に
日時付ファイル名で出力されている。


■さらに、PGAdminで、タプル状態の確認



これを見ても、やはり、タプルが残っているようだ。


■いろいろググッてみると、
Let's Postgresの以下のサイトを見つけた。
HOT(Heap Only Tuples) ~ Let's Postgres

HOT(Heap Only Tuple)といわれる機能があって、バキューム処理をしてくれるらしいのだが・・・

だけど、処理が激落ちしているので、それすら走っていない気がする。

そして、さらに上記サイトを読み進めていくと
ロングトランザクションに気をつけようということにひっかかる。


■ロングトランザクションとコネクションプールに注意!!!
  改めて、ソースを確認していくとなんとコミット漏れがあり
それをコミットすることで状況は無事解決した。
(めでたし、めでたし、苦労のわりには、原因はイージーミスという情けない幕切れ。)

実行中のトランザクションで、更新されたテーブルは
そのトランザクションが終了するまでバキュームされないようだ。

ここでもうひとつ注意が必要なのは、コネクションプールについてである。
コネクションプールを使っていると、トランザクションがコミットされていても
バキュームされないことがあるようだ。

詳細不明だが、コネクションプールの機能は、プログラムからコネクションをクローズしても
物理的なコネクションはクローズされず、ある程度の期間(KeepAlive)、
コネクションを保持したり、使いまわしをするもののため、
そのKeepAliveの間は解放されないのではないかと推測しています。

なので、大量データ処理では、コネクションプールを使わず、コネクションの時間的コストはかかるが、適度なタイミングで、コネクションを解放して、再接続をしたほうがいいという結論に至りました。


2016年10月11日火曜日

Jasperで画像データ(Imageデータ)をDBから表示する方法

JapserReportでは、画像データ(Imageデータ)を出力することができるが、
DBに格納された画像データを出力する場合、少し工夫が必要のようだ。

ここでは、Postgresのbytea型に画像データが入っているとする。
そのデータをJasperReportで画像として出力する。

ここで、ポイントとなるのが、JasperReportからbytea列をSQLで取得したときに
果たして、どういう型で取得されるのかということである。

結論から言うと、実はbytea列がどの型で取得されるかが、DB接続に使用しているAPIによって、違うということだ。

そのため、ADempiereなどのアプリケーションからはうまく画像表示できるのに、
iReport上で実行してみると画像表示できないといったことが発生する。
これは、ADempiereのアプリから実行されるAPIとiReportから実行されるAPIで
bytea列型の扱い方法が違うから発生していると思われる。

これを解決するためには、byteaの列をBase64エンコードして、テキストデータとして扱うことがポイントである。

こうすることで、APIの仕様にかかわらず画像データをテキストデータとして扱うことが可能であり、iReport上からも、ADempiereなどのアプリケーションからも画像データを出力することが可能となる。



以下が設定方法である。

■SQLでバイナリデータ取得
☆byteaの列をBase64でエンコードして、テキストデータとして取り出す。
 
 以下のSMB_QRCode_DocNoは、bytea型でPostgresに定義されている。
 以下のSQLで、Base64でエンコードしてテキストデータとしている。

 SELECT encode(cf.SMB_QRCode_DocNo::bytea, 'base64') AS SMB_QRCode_DocNo
 FROM M_InOutConfirm cf
 ・・・・

 ※Edit Queryダイアログで、表示される該当バイナリ列(SMB_QRCode_DocNo)のDataTypeが「java.lang.String」であることを確認しておく。




■イメージオブジェクトの設定
 ①ImageExpressionプロパティに以下を設定。

new java.io.ByteArrayInputStream(javax.xml.bind.DatatypeConverter.parseBase64Binary((String)$F{smb_qrcode_docno}))

 ※DBから取得したBase64のテキストをByte配列にコンバートし、それを引数にInputStreamを作成している。




②Expressionクラス
  java.io.InputStreamを選択する。
  ※①の戻り値の型のため
 
③以下は念のため設定しておく
  UsingCacheプロパティ:チェックしておく。
  On Error Type:Blank







2016年10月9日日曜日

中小企業のITシステム導入 ~中小企業白書2016年度版より②

 前ページに引き続き、2016年度版の中小企業白書からいくつかピックアップして、中小企業のITシステム導入について考察したいと思います。
参考:2016年度版 中小企業白書 第2部 第2章 中小企業におけるITの利活用
http://www.chusho.meti.go.jp/pamflet/hakusyo/H28/h28/index.html



■中小企業がIT投資を行わない理由
 以下の統計では、現在IT投資を行っていない企業に対して、IT投資を行わない理由を調査しsています。

 この結果は、とても意外でした。
 IT投資を行っていない理由で最も多いのが「ITを導入できる人材がいない」ということのようです。
 中小企業は、IT投資を重要視しているが、ITを導入するための人材がいなくて、
その効果がわからないために投資に踏み切れていない企業が多いようです。
 コストの問題というより、むしろITに詳しい人材がいないということが理由のようです。
 



 この結果からいえることは、中小企業がITシステム導入をするために、中小企業とシステム導入・開発会社を橋渡しする人材が必要ということではないでしょうか。
 その人材を中小企業自らが内部に抱え込むのか、システム会社側にそういう人材が必要なのか、それともどちらにも属さない中立的な人材(ITコーディネータなど)がいいのかあると思いますが
 まずは、そういう人材が必要であることがこの統計からは明らかだと思います。
 
 少なからず、システム会社に属する我々がまずできることは、難しい横文字を使うのではなく、わかりやすくシステム導入について説明していくことが重要なことであるといえます。



■IT人材の活用
 第3節の統計データからは、IT人材の活用方法についての統計データがあります。
 ここでは、IT人材が不足しているという認識している企業が多く、
 また、必要とする人材像が不明といった回答も多くみられています。
 その中で、特筆すべきは、最後の統計データで、高収益企業は、外部人材を活用している割合が高いということかもしれません。
 

中小企業のITシステム導入 ~中小企業白書2016年度版より

 2016年度版の中小企業白書からいくつかピックアップして、中小企業のITシステム導入について考察したいと思います。
参考:2016年度版 中小企業白書 第2部 第2章 中小企業におけるITの利活用
http://www.chusho.meti.go.jp/pamflet/hakusyo/H28/h28/index.html


■ITシステム導入と業績の関係
まず、2016年度版の中小企業白書によると、
IT投資を行っている企業の方が、行っていない企業に比べて売上高、売上高経常利益率といった企業の業績が高い傾向が強いという結果がでています。

積極的な投資をおこなうから、業績がいいのか、業績がいいから積極的な投資をおこなうのか、鶏が先か卵が先か的なところもあるかもですが(これについては次の分析結果参照)、
結果として、やはりIT投資を積極的に行った企業のほうが業績がいいということのようです。





色の濃いほうが、IT導入ありの企業の棒グラフですべての業種において、IT導入なしの企業を上回っています。



■ITシステム導入後の業績推移

次のグラフでは、2010年以降にITシステムを導入した企業の業績がどうなったかを表しています。
ITシステム導入によって、業績が上がっていることがみてとれるようです。





■IT投資と従業者数の関係
 ここでは、IT投資によって、従業員数がどう変化したかが調査されています。
 この結果は、私としては意外な結果でした。
 ITシステム導入により、従業員は減ってコスト削減するものと思っておりましたが、
意外とそうでもないようです。

 理由は、業務効率化によって削減した人員を配置転換させるなどして、付加価値向上のための人材として活用することで、社内全体としては従業者数を変化させることなく、業績を向上させていることが推察されるようです。






■業務領域におけるIT活用
次の統計では、業務領域ごとにパッケージソフトによる導入かオーダーメイドによる導入かなどのITシステムの導入方法が調査されています。

予想通り、財務・会計、人事・給与といった会社ごとにばらつきが少ない分野では
パッケージソフトが使用されており、販売管理や購買管理、生産管理といった分野では比較的パッケージソフトの利用が少ないことがわかります。

ただ、オーダーメイドのシステムを中小企業が導入するとなると、開発費がかなり高くなることから、オーダーメイドによる導入ができる中小企業は多くないと考えられます。そのため、自社の業務にあったパッケージソフトを見つけ、それを導入して、導入費を下げたいと思う中小企業も多いと考えられます。

そういう意味ではパッケージソフトの機能充実や柔軟なカスタマイズが求められていると思いますが、近年では、機能の充実したパッケージソフトや各社にあった設定を柔軟におこなうことのできるパッケージソフトが出てきており、パッケージソフトの今後に期待がかかっているのではないでしょうか。

このサイトで紹介しているオープンソース ERPであるADempiereもそのひとつといえます。
ADempiereでは、豊富な機能、柔軟な設定により、企業によって違いのあるような多様な業務にも対応が可能なつくりとなっており、導入コストの大幅な削減が可能となっております。
















2016年9月28日水曜日

ADempiereの読み取り専用ロジック

ADempiereでは、GUIから画面やテーブルを作成できる。

テーブルの列の設定では、その項目が読み取り専用かどうかを設定できる。
ここに、「Y」を設定すれば、読み取り専用の列となり、「N」を設定すれば更新可能な列となる。

さらに、応用的な設定方法としては、ここにちょっとしたロジックを記述して、
ある条件のときだけ、読み取り専用の列としたりすることも可能である。

このロジックを読み取り専用ロジックと呼んでいるが、
ここに設定するロジックでは、なんでも記述できるわけでないので注意が必要である。
このページの最後に、詳細な定義は記述したが、まとめると以下のようになる。


・コンテキストを使うときは、普通に記述できる。
ex. @C_BPartner_ID@

・かつ条件とまたは条件は、「&」「|」のひとつでいい。
 このへんは、Javaだと「&&」「||」なので、注意が必要。

・「=」の反対の「~でない条件」は、「!」でいい。
これも、ちょっと変わっているので注意が必要。(「!=」でもなく、「<>」でもなく、「!」だけ)
ex. @C_BPartner_ID@!0


・右辺でコンテキストは使えない。(コンテキスト同士の比較はできない)
@C_BPartner_ID@=@C_BPartner2_ID@ みたいなことはできないようだ。

・結局、サンプルにあるように
   Example '@AD_Table@=Test | @Language@=GERGER
のような条件式が適当な使い方になりそう。
複雑なロジックを使う場合は、新たな列を使って、その列にロジックを埋め込んで、その結果を読み取り専用ロジックで使うといったやり方になりそう。



詳細は、以下。

=========================================================
http://wiki.adempiere.net/Read_Only_Logic
=========================================================

The content here is parsed by the AD engine as stated in the APIdoc of the code for ReadOnlyLogic (GridTab.isReadOnly() - Boolean evaluateLogic):

 *  Evaluate Logic.
 *  <code>
 *  format      := <expression> [<logic> <expression>]
 *  expression  := @<context>@<exLogic><value>
 *  logic       := <|> | <&>
 *  exLogic     := <=> | <!> | <^> | <<> | <>>
 *
 *  context     := any global or window context
 *  value       := strings can be with ' or "
 *  logic operators := AND or OR with the prevoius result from left to right
 *
 *  Example '@AD_Table@=Test | @Language@=GERGER
 *  </code>
 *  @param source class implementing get_ValueAsString(variable)
 *  @param logic logic string
 *  @return logic result

2016年3月13日日曜日

ADempiere.comのURLが変わったようです

これまで、ADempiereの使い方やインストール方法、開発方法など、
たくさんの情報が掲載されていた「ADempiere.com」だが、
アクセスしてみると、なにやら意味深なアナウンスが載っている状態だ。

どうやら、ADempiere.netに完全に移動されるようだ。
これまでのWiki情報は、「http://wiki.adempiere.net/」で無事に表示された。

しかし、adempiere.netはまだリンク切れが多い状態のようだ。
とりあえず、wikiの情報が見れるようなので影響は少なそうだ。

<詳細> ~http://wiki.adempiere.net/ADempiere_ERPの文言より
もともと、ADempiere.comは、1企業が所有するドメインのため、今回のようなことになったよう。
1企業の政治的、戦略的な理由で、ドメインが閉鎖されることがあるということ。
これは、商業的な理由で、これまでのコミュニティの資産がゼロになってしまうリスクがあるということ。
そのため、商業企業でもなく、利益ももとめない個人の集まりであるADempiereCommunityが
これを保持したほうがいいとの考えから、ADempiere.netは、ADempiereCommunityが保持することになったようだ。

2016年1月18日月曜日

Gitサイズが大きいレポジトリのクローンエラー①

Gitサイズが大きいときのクローンでは、エラーが発生することがある。


remote: Counting objects: 13751, done.
remote: Compressing objects:  78% (2213error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: warning: suboptimal pack - out of memory
remote: fatal: Out of memory, malloc failed
remote: aborting due to possible repository corruption on the remote side.
fatal: protocol error: bad pack header

git did not exit cleanly (exit code 128) (2403 ms @ 2016/01/18 18:39:49)


その場合、以下のように、depth=1で1回Cloneしたあと、Fetchすると取得できるようだ。
以下のコマンドでもできるが、トータスGitなどを使えば、 GUIからも可能。


コマンド例
git clone --depth 1 http://hoge.com/hoge.git
git fetch --depth 5
git fetch --depth 20
git fetch --unshallow


また、サーバ側での設定を変えることで対応することもできる。

サーバ側のConfigファイルに以下の設定をする。
(pack配下だけでいいかも。値はサーバに応じて設定)

[core]
    packedGitLimit = 4000m
    packedGitWindowSize = 1000m
[pack]
    windowMemory = 4000m
    SizeLimit = 4000m
    threads = 1
    window = 0