ก็ถึงเวลาที่ต้องทดลองเสียหน่อย (โหลดมาทิ้งไว้นานแล้ว แต่ไม่ได้เริ่มสักที)
การ install และ run คงไม่ต้องพูดถึง เพราะค่อนข้างง่าย
เริ่มเล่าบรรยากาศที่ได้จากการใช้ดีกว่า
ผมเริ่มด้วยการใช้ module accounting/Chart of Accounts ก่อน
เรื่องแรกที่พยายามจะทำก็คือ การบันทึก Journal Entry
ดูจากหน้าตาที่ OFBiz ให้มาแล้ว ช่างเป็น minimum feature เสียนี่กระไร
ให้ป้อน entry ได้แค่แบบ 1 debit ต่อ 1 credit เท่านั้น
ทดลองใส่ข้อมูล ก็พบว่ามันเกิด error แดงเถือก
อ่าน message ดูแล้ว ก็พบว่ามันเป็น error ที่ระดับ database
violation of foreign key constraint 'ACCTTXENT_GLACOG' for key (121900,Company).
ตามไปดูใน model definition (applications/accounting/entitydef/entitymodel.xml)
ก็จะเห็นดังนี้
<relation type="one" fk-name="ACCTTXENT_GLACOG" rel-entity-name="GlAccountOrganization">
<key-map field-name="glAccountId"/>
<key-map field-name="organizationPartyId"/>
</relation>
จะเห็นว่ามัน link กับ entity GlAccountOrganization
ถ้าตามไปดูต่อ ก็จะเห็น definition ดังนี้
<entity entity-name="GlAccountOrganization"
package-name="org.ofbiz.accounting.ledger"
title="GL Account Organization Entity">
<field name="glAccountId" type="id-ne"></field>
<field name="organizationPartyId" type="id-ne"></field>
<field name="roleTypeId" type="id-ne"></field>
<field name="fromDate" type="date-time"></field>
<field name="thruDate" type="date-time"></field>
<field name="postedBalance" type="currency-amount"></field>
...
อ้าฮ้า มันคือ table ที่เก็บความสัมพันธ์ระหว่างหน่วยงาน กับ รหัสบัญชี
ลอง select ข้อมูลดูโดยใช้ webtool ก็พบว่า มันมีข้อมูลมาให้รายการเดียว
ดังนั้นเป้าหมายแรก ก็คือต้องเพิ่มรายการลงไป
อันนี้หาง่ายหน่อย อยู่ในกลุ่มงาน Chart of Account
ชื่อหัวข้องานว่า Assign GL Account
ส่วนหน้าจอ listing ก็อยู่ในข้อข้องานว่า List GL Organize
หลังจากใส่ข้อมูลแล้ว ก็ insert ข้อมูลผ่านฉลุย
ขั้นถัดไป ก็คือ อยากทดลอง add บัญชีใหม่ๆเข้าไป
ตรงนี้พบว่า ไม่ว่าจะ click หาหัวข้อใน menu ไหน ก็หาไม่เจอ
สุดท้ายก็ต้องตามไปแกะที่ applications/accounting/webapp/accounting/WEB-INF/controller.xml
พบว่ามีการ define uri ไว้ดังนี้
<request-map uri="AddGlAccount">
<security https="true" auth="true"/>
<response name="success" type="view" value="AddGlAccount"/>
</request-map>
ก็เลยลองเอาไปใส่ url ตรงๆดู
ได้ผลแฮะ ได้หน้าจอมาหนึ่งหน้าจอ
ทดลองป้อนข้อมูลดู กด save
ได้ error มาใหม่อีกหนึ่งตัว
คราวนี้มันบอกว่า
GlAccountId ไม่ได้ระบุ
อ้าว ก็ไม่มี field ให้ป้อนนี่น่า แล้วมันจะระบุที่ไหนหล่ะ
ตามไปดู view definition
<view-map name="AddGlAccount" type="screen" page="component://accounting/widget/AccountingScreens.xml#AddGlAccount"/>
เห็นว่าชี้ไปที่ applications/accounting/widget/AccountingScreens.xml#AddGlAccount
ตามไปดูก็จะเห็น define ไว้แบบนี้
<screen name="AddGlAccount">
<section>
<actions>
<set field="titleProperty" value="PageTitleAddGlAccount"/>
<set field="tabButtonItem" value=""/>
<set field="labelTitleProperty" value=""/>
</actions>
<widgets>
<decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
<decorator-section name="body">
<include-form name="EditGlAccount" location="component://accounting/webapp/accounting/chartofaccounts/GlAccountForms.xml"/>
<!-- include-screen screen-name="ListGlAccounts" name="ListGlAccounts" / -->
<!-- tree name="GlAccountTree" location="component://accounting/widget/AccountingTrees.xml"/ -->
</decorator-section>
</decorator-screen>
</widgets>
</section>
</screen>
จะเห็นว่ามันเป็นแค่ decorator
ตัว form จริงๆอยู่ใน applications/accounting/webapp/accounting/chartofaccounts/GlAcountForms.xml
<form name="EditGlAccount" type="single" target="updateGlAccount" title="" default-map-name="glAccount">
<alt-target use-when="glAccount==null" target="createGlAccount"/>
<auto-fields-service service-name="updateGlAccount" map-name=""/>
<field use-when="glAccount!=null" name="glAccountId" tooltip="${uiLabelMap.AccountingNotModificationRecrationGlAccount}"><display/></field>
<field use-when="glAccount==null&&glAccountId!=null" name="glAccountId" tooltip="${uiLabelMap.AccountingCouldNotFindGlAccount} [${glAccountId}]"><text size="20" maxlength="20"/></field>
<!-- this to be taken care of with auto-fields-service as soon as it uses entity field info too -->
<field use-when="glAccount==null&&glAccountId==null" name="glAccountId"><text size="20" maxlength="20"/></field>
<field name="glAccountTypeId">
<drop-down allow-empty="false">
<entity-options entity-name="GlAccountType" description="${description}">
<entity-order-by field-name="description"/>
</entity-options>
</drop-down>
</field>
...
อืมม์มัน reuse ใช้ form ทั้งหน้าจอ insert และ update
จะเห็นว่ามันตั้งเงื่อนไขในการแสดง field glAccountId ไว้ดังนี้
1. กรณี glAccount ไม่เป็น null แสดงว่าเป็น mode update
ก็ให้แสดงค่า glAccountId โดยใช้ display tag และอนุญาติให้ดูได้อย่างเดียว ห้ามแก้ไข
2. กรณี glAccount เป็น null และมีหรือไม่มีค่า glAccountId
หน้าจอจะแสดง textfield ให้ใส่
อืมม์ case ของเรามันน่าจะตกข้อ 2, แต่มันทำไม่ไม่แสดง textfield ให้เราใส่
ผมก็เลยไปลองดูในหน้าจอ update ดูว่ามันทำงานอย่างไร
โดยดูใน applications/accounting/widget/AccountingScreens.xml#GlAccountNavigate
ปรากฎว่า flow ก่อนที่จะเข้าหน้าจอ update
มันทำแบบนี้
<screen name="GlAccountNavigate">
<section>
<actions>
...
<!-- parameters includes requestAttributes and parameter map -->
<!-- requestParameters is just the parameter map -->
<set field="glAccountId" from-field="requestParameters.glAccountId"/>
...
<entity-one entity-name="GlAccount" value-name="glAccount"/>
</actions>
<widgets>
...
</widgets>
</section>
</screen>
ลองกลับไปดู flow ในหน้าจอ AddGlAccount มันไม่ได้ set entity นี่หน่า
ทดลองใส่บรรทัดนี้เพิ่มลงไป
<screen name="AddGlAccount">
<section>
<actions>
<set field="titleProperty" value="PageTitleAddGlAccount"/>
<set field="tabButtonItem" value=""/>
<set field="labelTitleProperty" value=""/>
<entity-one entity-name="GlAccount" value-name="glAccount"/>
</actions>
...
ลอง restart OFBiz แล้วเปิด browser ดู
พบว่าได้ผลแฮะ มี textfield ให้ป้อนแล้ว
ทดลองป้อนแล้ว submit ดู ก็พบว่ามันบันทึกลง Database ได้แล้ว
น่าสนใจมาก ใช้ OFBiz ครั้งแรกก็เจอ bug เลย
แต่คิดว่าเป็น bug เนื่องจากเป็นหน้าจอนี้เป็นหน้าจอที่ไม่มีคนใช้ (สังเกตได้จากไม่มี menu ให้เลือก)