This is the part of my book that i am writing about Extending Openbravo POS.Openbravo POS lack of supplier information, so what end user need is the supplier, so they can add list of their supplier.
Work On It!
Create reason table, in order to create report that reflect the meaning of reason code on stockdiary table.
DROP TABLE IF EXISTS `openbravopos`.`reasons`;
CREATE TABLE `openbravopos`.`reasons` (
`REASON` int(11) NOT NULL,
`NOTES` varchar(45) NOT NULL,
PRIMARY KEY (`REASON`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

All value contain in reason table following the code from file MovementReason.java class, here is the code
public static final MovementReason IN_PURCHASE = new MovementReason(+1, "stock.in.purchase");
public static final MovementReason IN_REFUND = new MovementReason(+2, "stock.in.refund");
public static final MovementReason IN_MOVEMENT = new MovementReason(+4, "stock.in.movement");
public static final MovementReason OUT_SALE = new MovementReason(-1, "stock.out.sale");
public static final MovementReason OUT_REFUND = new MovementReason(-2, "stock.out.refund");
public static final MovementReason OUT_BREAK = new MovementReason(-3, "stock.out.break");
public static final MovementReason OUT_MOVEMENT = new MovementReason(-4, "stock.out.movement");
public static final MovementReason OUT_CROSSING = new MovementReason(1000, "stock.out.crossing");
Create Stock History,
I need to have form to entry from date to date of stock history to print, then which category to print of stock history, in able to do that, I need to create as follow:
RECEIVE ITEM
Several field that should input into system when receive item transaction happen as follow
- Delivery Order Number
- Supplier
- Receive Date
( the other including , item name, and receiver name )
from OpenbravoPOS all details has been recorded in StockDiary table, we only need to add header of details, Contain( DO Number , Supplier Code, Receive Date, Receiver Name ) {
each of Stock In transaction which has been entered into Stock Maintenance, each item would be store as details, and they had unique ID in StockDiary table }.
Here is the sample of StockDiary Query

RETURNING ITEM (to supplier)
The information should be printed
- Return Number document
- Delivery Order Number when receiving item
- Return Date,
- Receive Date
Changes note on OpenbravoPOS
create stockin
DROP TABLE IF EXISTS `openbravopos`.`stockin`;
CREATE TABLE `openbravopos`.`stockin` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`DELIVERYORDER` varchar(255) NOT NULL,
`SUPPLIER` varchar(45) NOT NULL,
`NOTES` varchar(255) DEFAULT NULL,
`DATEIN` datetime NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
We need to add table stockinstockdiarymap, in order not to change table stockdiary metadata.
DROP TABLE IF EXISTS `openbravopos`.`stockinstockdiarymap`;
CREATE TABLE `openbravopos`.`stockinstockdiarymap` (
`ID` varchar255) NOT NULL,
`STOCKIN` varchar(255) NOT NULL,
`STOCKDIARY` varchar(255) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
now add interaction between openbravoPOS and this table stockin , I put some code inside these file, here the code snapshoot.
File InventoryRecord.java
-Change class Inventory Record, and add
/*@Eko Subagio add Delivery Order */
private String m_deliveryorder;
private String m_supplier;
private String m_notes;
-Change InventoryRecord class constructor, add
/*@Eko Subagio add Delivery Order */
public InventoryRecord(Date d, MovementReason reason, LocationInfo location,
String deliveryorder, String supplier, String notes,
List<InventoryLine> invlines) {
m_dDate = d;
m_reason = reason;
m_locationOri = location;
m_deliveryorder = deliveryorder;
m_supplier = supplier;
m_notes = notes;
m_invlines = invlines;
}
-Change and add field getter
public String getDeliveryOrder() {
return m_deliveryorder;
}
public String getSupplier(){
return m_supplier;
}
public String getNotes(){
return m_notes;
}
File DataLogicSales.Java
/*
*@Eko Subagio, add stockinDatas declaration
*
*/
stockinDatas = new Datas[] { Datas.STRING, Datas.TIMESTAMP, Datas.STRING, Datas.STRING, Datas.STRING};
/* add @Eko Subagio July 02, 2010*/
protected Datas[] stockinDatas;
/* add @eko subagio July 02, 2010
* PreparedSentence( s is session connection, sentence i SQL data manipulation,
*/
public final SentenceExec getStockInInsert() {
return new SentenceExecTransaction(s){
public int execInTransaction(Object params) throws BasicException {
return new PreparedSentence(s
,”INSERT INTO STOCKIN (ID, DATEIN, DELIVERYORDER, SUPPLIER, NOTES) VALUES(?, ?, ?, ?, ?)”
, new SerializerWriteBasicExt(stockinDatas, new int[]{0, 1, 2, 3, 4})).exec(params);
}
};
}
File StockManagement.Java
Add Label, and TextField for DeliveryOrder Number entry, Supplier Code, Notes
declare in top of variable declaration
/* @Eko Subagio
* store UUID for StockIn
*/
private String UUIDStockIn;
-Add parameter for method that call InventoryRec constructor, because we add new parameter
/*@Eko Subagio add Delivery Order */
String deliveryorder = m_jdonumber.getText();
String supplier = m_jsupplier.getText();
String notes = m_jnotes.getText();
saveData(new InventoryRecord(
d, MovementReason.OUT_MOVEMENT,
(LocationInfo) m_LocationsModel.getSelectedItem(),
/*@Eko Subagio add DeliveryOrder */
deliveryorder, supplier, notes,
m_invlines.getLines()
));
-Change saveData()
private void saveData(InventoryRecord rec) throws BasicException {
/*
* @ Eko Subagio
* save also StockIn Head, save UUID from stockin
*/
UUIDStockIn = UUID.randomUUID().toString();
SentenceExec sentStockIn = m_dlSales.getStockInInsert();
sentStockIn.exec(new Object[] {
UUIDStockIn,
rec.getDate(),
rec.getDeliveryOrder(),
rec.getSupplier(),
rec.getNotes()
});
// A grabar.
SentenceExec sent = m_dlSales.getStockDiaryInsert();
for (int i = 0; i < m_invlines.getCount(); i++) {
InventoryLine inv = rec.getLines().get(i);
sent.exec(new Object[] {
UUID.randomUUID().toString(),
rec.getDate(),
rec.getReason().getKey(),
rec.getLocation().getID(),
inv.getProductID(),
inv.getProductAttSetInstId(),
rec.getReason().samesignum(inv.getMultiply()),
inv.getPrice()
});
}
// si se ha grabado se imprime, si no, no.
printTicket(rec);
}
NOW PROCESSING for table STOCKINSTOCKDIARYMAP
File DataLogicSales.java
-Add this declaration
protected Datas[] stockinstockdiarymapDatas;
-Add this method
/* add @eko subagio July 02, 2010
* to work with stockinstockdiarymap table
*/
public final SentenceExec getStockInStockDiaryMap() {
return new SentenceExecTransaction(s){
public int execInTransaction(Object params) throws BasicException {
return new PreparedSentence(s
,”INSERT INTO STOCKINSTOCKDIARYMAP(ID, STOCKIN, STOCKDIARY) VALUES(?, ?, ?)”
,new SerializerWriteBasicExt(stockinstockdiarymapDatas, new int[]{0, 1, 2})).exec(params);
}
};
}
File StockManagement.java
Variable Declaration
/* @Eko Subagio
* store UUID for StockIn
*/
private String m_UUIDStockIn;
private String m_UUIDStockInStockDiaryMap;
private String m_UUIDStockDiary;
Now, the declaration method of saveData() became like this:
private void saveData(InventoryRecord rec) throws BasicException {
/*
* @ Eko Subagio
* save also StockIn Head, save UUID from stockin
*/
m_UUIDStockIn = UUID.randomUUID().toString();
SentenceExec sentStockIn = m_dlSales.getStockInInsert();
sentStockIn.exec(new Object[] {
m_UUIDStockIn,
rec.getDate(),
rec.getDeliveryOrder(),
rec.getSupplier(),
rec.getNotes()
});
/*@ Eko Subagio
* Declare variable for stockinstockdiarymap table
*/
//prepare query for insert
SentenceExec sentStockInStockDiaryMap = m_dlSales.getStockInStockDiaryMap();
// A grabar.
SentenceExec sent = m_dlSales.getStockDiaryInsert();
// Save lines of row stock
for (int i = 0; i < m_invlines.getCount(); i++) {
InventoryLine inv = rec.getLines().get(i);
/*@ Eko Subagio
* Declare variable for stockinstockdiarymap table
*/
m_UUIDStockInStockDiaryMap = UUID.randomUUID().toString();
/*generate UUID for StockDiary ID column table and store it to m_UUIDStockDiary
so we can use it later for MAP with StockIn */
m_UUIDStockDiary = UUID.randomUUID().toString();
//execute now
sentStockInStockDiaryMap.exec(new Object[]{ m_UUIDStockInStockDiaryMap, m_UUIDStockIn, m_UUIDStockDiary });
sent.exec(new Object[] {
//UUID.randomUUID().toString(), <- original code from @Adrian Romero
m_UUIDStockDiary, //I @Eko Subagio change it to variable
rec.getDate(),
rec.getReason().getKey(),
rec.getLocation().getID(),
inv.getProductID(),
inv.getProductAttSetInstId(),
rec.getReason().samesignum(inv.getMultiply()),
inv.getPrice()
});
}
// si se ha grabado se imprime, si no, no.
printTicket(rec);
}
Add Clear Text Field method
/* @Eko Subagio July 02, 2010
* Clear text field
*
*/
private void clearTextField(){
m_jdocnumber.setText(“”);
m_jsupplier.setText(“”);
m_jnotes.setText(“”);
m_jdocnumber.setFocusable(true);
}
Add Supplier Form and Database Table
Create table suppliers
DROP TABLE IF EXISTS `openbravopos`.`suppliers`;
CREATE TABLE `openbravopos`.`suppliers` (
`ID` varchar(255) NOT NULL,
`CODE` varchar(45) NOT NULL,
`NAME` varchar(100) NOT NULL,
`ADDRESS` varchar(255) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
How Display new JPanel in OpenbravoPOS ?
I just learn and follow the customers package to construct supplier package.
I create new package com.openbravo.pos.suppliers:
DataLogicSuppliers.java
SupplierInfo.java
SuppliersPanel.java
SuppliersView.java,
Some returning list to fill comboBoxList still not work, I just look at the simple code in Categories section and file how to fix it, and learn the simple way using
File DataLogicSales.java, with code
public final SentenceList getCategoriesList() {
return new StaticSentence(s
, “SELECT ID, NAME, IMAGE FROM CATEGORIES ORDER BY NAME”
, null
, CategoryInfo.getSerializerRead());
}
These code implemented in DataLogicSuppliers.java as follow
public final SentenceList getSupplierList() {
return new StaticSentence(s
, “SELECT ID, CODE, NAME, ADDRESS FROM SUPPLIERS ORDER BY NAME”
, null
, SupplierInfo.getSerializerRead());
}
File CategoryInfo.java with code,
public static SerializerRead getSerializerRead() {
return new SerializerRead() { public Object readValues(DataRead dr) throws BasicException {
return new CategoryInfo(dr.getString(1), dr.getString(2), ImageUtils.readImage(dr.getBytes(3)));
}};
}
These code implemented in SupplierInfo.java as follow
public static SerializerRead getSerializerRead() {
return new SerializerRead() { public Object readValues(DataRead dr) throws BasicException {
return new SupplierInfo(dr.getString(1), dr.getString(2), dr.getString(3), dr.getString(4));
}};
}
Implementation in file CategoriesEditor.java
m_sentcat = dlSales.getCategoriesList();
these code implemented in file StockManagement.java as follow
At private field StockManagement declaration
private SentenceList m_sentSuppliers;
private ComboBoxValModel m_SuppliersModel;
At Constructor StockManagement
m_sentSuppliers = m_dlSuppliers.getSupplierList();
m_SuppliersModel = new ComboBoxValModel();
At method StockManagement.activate()
public void activate() throws BasicException {
m_cat.loadCatalog();
java.util.List l = m_sentlocations.list();
m_LocationsModel = new ComboBoxValModel(l);
m_jLocation.setModel(m_LocationsModel); // para que lo refresque
m_LocationsModelDes = new ComboBoxValModel(l);
m_jLocationDes.setModel(m_LocationsModelDes); // para que lo refresque
/* @Eko Subagio July 02, 2010 */
java.util.List listSupplier = m_sentSuppliers.list();
m_SuppliersModel = new ComboBoxValModel(listSupplier);
m_jListSuplier.setModel(m_SuppliersModel);
stateToInsert();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
jTextField1.requestFocus();
}
});
}
How To Get KeyID from ComboBox ?
you should implemented IKeyed for class, so you can get keyed.
At file SupplierInfo.java add as follow
public class SupplierInfo implements Serializable, IKeyed{
protected String id;
protected String supplierCode;
protected String name;
protected String address;
Override getKey method implementation, because getKey is abstract method, you should implemented in each class which use IKeyed.
public Object getKey(){
return id;
}
Then in implementation add,
String supplier = m_SuppliersModel.getSelectedKey().toString();
These code will assign ID key of the table as implemented on class you have been created which implement IKeyed for getKey.
How To Add Application Link To Menu?
Go to Maintenance
Roles, Administrator, add
<class name=”com.openbravo.pos.suppliers.SuppliersPanel”/>
Resources, Menu.Root, add under Title menu StockManagement
submenu.addPanel(“/com/openbravo/images/bookmark.png”, “Menu.Suppliers”, “com.openbravo.pos.suppliers.SuppliersPanel”);
JRootApp.java
Declare and put code to list the task to prepare session connection, prepare menu, etc.
All menu for each user assign from table roles column PERMISSION, this PERMISSION column contain BLOB XML configuration for each user, the menu assigned for each user define and stored here.
Using OpenbravoPOS to add menu, just click Maintenance, then click Resource, click Menu.Root, you will see the XML menu definition here.
File DataLogicAdmin.java
public final SentenceList getRolesList() {
return new StaticSentence(s
, “SELECT ID, NAME FROM ROLES ORDER BY NAME”
, null
, new SerializerReadClass(RoleInfo.class));
}
File DataLogicSystem.java
m_rolepermissions = new PreparedSentence(s, “SELECT PERMISSIONS FROM ROLES WHERE ID = ?” , SerializerWriteString.INSTANCE, SerializerReadBytes.INSTANCE);
Then how OpenbravoPOS construct roles.PERMISSION into menu and assigned it?
Using OpenbravoPOS to add menu, just click Maintenance, then click Resource, click Menu.Root, you will see the XML menu definition here.
This script menu calling java class that has been inherited from JPanel, JPanel encapsulated as field class member of java class.
Example for Customer Class:
| No |
Class File |
Notes |
| 1 |
CustomerInfo.java |
adalah class base standard yang memiliki member ID, NAME |
|
DataLogicCustomers.java |
adalah class yang mendefiniskan SQL Data Manipulation Language section. |
|
CustomersView.java |
Adalah panel customer yang di extend dari JPanel. |
|
CustomersPanel.java |
Adalah class yang membungkus class CustomerView.java, dan pendefinisan di XML menu script, memanggil class CustomersPanel untuk menampilkan customer data. |
That’s all for now Part #1.