# App Sample
Version: 1.0 | Release Date: 30/6/2018
# Things to know
Our app example is a simple book borrowing program that contains two main objects:  Book and Member
- The member's profile stores his borrowing history
 - The 
AvailableProperty of Book decided whether it can be borrowed or not - Each book has an ISBN number that checks its validity each time it is saved.
 - Users can also manually check the ISBN before saving.
 - Add a Printing Report to the 
Member - Add a EBI Report to the 
Member 
You can download the runable code of the entire app from github (opens new window)
# Define App in App.xml
p-share\src\main\resources\META-INF\app.xml
<?xml version="1.0"?>
<app xmlns="http://www.multiable.com/app">
	<name>opcq</name>
	<version>1.0</version>
	<description>Opcq App</description>
	<dependences>
		<dependence id="caw" versions="1.0" />
	</dependences>	
	<ear>caw_ear</ear>
	<ejb>p-ejb</ejb>	
</app>
See App.xml for other available setting parameters.
# Define Table Structure in datadict.xml
p-share\src\main\resources\META-INF\datadict.xml
<?xml version="1.0"?>
<dd xmlns="http://www.multiable.com/datadict">
	
	<table name="opcqbookcat" mess="opcq.bookCat" pk="id">
		<inherit name="module_fm" />
		<column name="code" type="varchar" mess="core.code" length="20" defPattern="fmCode" required="true" batchUpdate="false"/>
		<column name="desc" type="varchar" mess="core.description" length="100" defPattern="charDesc" i18nField="true" batchUpdate="true"/>
		
		<index name="module_code" columns="code" />
	</table>
	
	<table name="opcqbook" mess="opcq.book" pk="id" >
		<inherit name="module_fm" />
		<column name="code" type="varchar" mess="opcq.bookCode" length="40" defPattern="fmCode" required="true" batchUpdate="false"/>
		<column name="isbn" type="varchar" mess="opcq.isbn" length="40" defPattern="char20" required="true" batchUpdate="false"/>
		<column name="desc" type="varchar" mess="opcq.title" length="200" defPattern="charDesc" i18nField="true" batchUpdate="true"/>
		<column name="author" type="varchar" mess="opcq.author" length="100" defPattern="char60" i18nField="true" batchUpdate="true"/>
		<column name="publisher" type="varchar" mess="opcq.publisher" length="100" defPattern="char100" i18nField="true" batchUpdate="true"/>
		<column name="pDate" type="datetime" mess="opcq.pDate" defValue="NOW()" defPattern="date"/>
		<column name="photoCode" type="varchar" mess="opcq.coverImg" length="60" defPattern="imgCode" />
		<column name="bookCatId" type="int_unsigned" mess="opcq.bookCat" defValue="0" defPattern="opcqBookCat" batchUpdate="false"/>
		<column name="avail" type="bit" mess="opcq.avail" defValue="0" defPattern="check"/>
		
		<index name="module_isbn" columns="isbn" unique="true"/>
	</table>
	
	<table name="opcqmem" mess="opcq.mem" pk="id" >
		<inherit name="module_fm" />
		<column name="code" type="varchar" mess="opcq.memNo" length="60" defPattern="fmCode" required="true" batchUpdate="false"/>
		<column name="desc" type="varchar" mess="opcq.name" length="200" defPattern="char50" i18nField="true" required="true" batchUpdate="true"/>
		<column name="card" type="varchar" mess="opcq.cardNum" length="60" defPattern="char30" required="true" batchUpdate="false"/>
		<column name="email" type="varchar" mess="opcq.email" length="200" defPattern="char100" batchUpdate="true"/>
		<column name="addr" type="varchar" mess="opcq.address" length="-1" defPattern="char2000" i18nField="true"/>
		
		<index name="module_code" columns="code"/>
	</table>
	
	<table name="opcqmemt" mess="opcq.memt" pk="id">
		<inherit name="id_irev" />
		<column name="hId" type="int_unsigned" mess="opcq.mem" defValue="0" defPattern="opcqMem" dataImport="false" dataExport="false" buildin="true"/>
		<column name="itemNo" type="varchar" mess="core.itemNo" length="12" defPattern="char6" dataEasy="true" dataImport="false" dataExport="false"/>
		<column name="bookId" type="int_unsigned" mess="opcq.bookCode" defValue="0" defPattern="opcqBook" required="true"/>
		<column name="bDate" type="datetime" mess="opcq.bDate" defValue="NOW()" defPattern="date"/>
		<column name="rDate" type="datetime" mess="opcq.rDate" defValue="NOW()" defPattern="date"/>
		
		<fk name="book" columns="bookId" refTable="opcqbook" refColumns="id" />		
	</table>
</dd>
See Datadict.xml for other available setting parameters.
For reuse purposes, the properties of the field can be defined by Pattern.xml
<?xml version="1.0"?>
<pattern xmlns="http://www.multiable.com/pattern">
	<record code="opcqBookCat" type="lookup">
		<lookup searchType="opcqBookCat"/>
	</record>
	
	<record code="opcqBook" type="lookup">
		<lookup searchType="opcqBook"/>
	</record>			
	
	<record code="opcqMem" type="lookup">
		<lookup searchType="opcqMem"/>
	</record>
</pattern>
# Define Module in module.xml
This app has a total of three modules, they are:
Book CategoryBookMember
p-share\src\main\resources\META-INF\module.xml
<?xml version="1.0"?>
<md xmlns="http://www.multiable.com/module" app="opcq">
	<module name="opcqBookCat" mess="opcq.bookCat" extend="false" mainTable="opcqbookcat" recType="" useAccess="true" useAttach="true" useBeShare="true" useApv="true" useChangenote="true" fmShare="Y" genCode_Type="BC">
		<table name="opcqbookcat" key="id" c="true" r="true" d="true" u="true" initRow="1" hpk="" fKey="" order=""/>
	</module>		
	
	<module name="opcqBook" mess="opcq.book" extend="false" mainTable="opcqbook" recType="" useAccess="true" useAttach="true" useBeShare="true" useApv="true" useChangenote="true" fmShare="Y" genCode_Type="BK">
		<table name="opcqbook" key="id" c="true" r="true" d="true" u="true" initRow="1" hpk="" fKey="" order=""/>
		
		<checker class="com.multiable.opcq.ejb.checker.OpcqBookChecker"/>
	</module>
	
	<module name="opcqMem" mess="opcq.mem" extend="false" mainTable="opcqmem" recType="" useAccess="true" useAttach="true" useBeShare="true" useApv="true" useChangenote="true" fmShare="Y" importThreadMode="false" genCode_Type="MEM">
		<table name="opcqmem" key="id" c="true" r="true" d="true" u="true" initRow="1" hpk="" fKey="" order=""/>
		<table name="opcqmemt" key="id" c="true" r="true" d="true" u="true" initRow="0" hpk="hId" fKey="" order="" cpnType="table"/>
	</module>
</md>
See Module.xml for other available setting parameters.
# Define Menu in navmenu.xml
This app has a total of four menus, they are:
Book CategoryBookMember- EBI for 
Member 
p-share\src\main\resources\META-INF\navmenu.xml
<?xml version="1.0"?>
<nm xmlns="http://www.multiable.com/navmenu" app="opcq">
	
	<folder code="m18Opcq" messCode="opcq.opcqApp">
		<menu code="opcqBookCat" messCode="opcq.bookCat" src="view/opcq/module/opcqBookCat" module="opcqBookCat" mType="FM" order="1000">			
			<inherit name ="module_fc" />
		</menu>	
		<menu code="opcqBook" messCode="opcq.book" src="view/opcq/module/opcqBook" module="opcqBook" mType="FM" order="2000">			
			<inherit name ="module_fc" />
		</menu>	
		<menu code="opcqMem" messCode="opcq.mem" src="view/opcq/module/opcqMem" module="opcqMem" mType="FM" order="3000">			
			<inherit name ="module_fc" />
		</menu>		
		<folder code="biOpcq" messCode="opcq.ebi" order="4000">
			<icon name="cicon-ebi" library="font/cawIcon"/>
			<menu code="M18_EBI_OPCQMEM" messCode="opcq.memRep" src="view/module/ebi/ebi" mType="EBI" order="1000">
				<icon name="cicon-ebi-report" library="font/cawIcon"/>
				<inherit name="module_ebi"/>
			</menu>
		</folder>
	</folder>	
</nm>
See NavMenu.xml for other available setting parameters.
# i18N Support
In order to avoid conflicts with other apps, the Key of each translation item is prefixed with Appname.
p-share\src\main\resources\META-INF\lang\Message_en.properties
p-share\src\main\resources\META-INF\lang\Message_zh-CN.properties
p-share\src\main\resources\META-INF\lang\Message_zh-TW.properties

# App Screenshot
Book Category

Book

Add books to Member

