POS - How to make kitchen printing easier
This How to will show how it's possible to make kitchen printing easier. "bold"PS!"bold" For that you need to change source code!
Step 1 - edit com.openbravo.pos.inventory.ProductsEditor.java file
In designe view drag&drop checkbox (variable name: m_jKitchen) and label to Stock tab
In the code view:
public ProductsEditor(DataLogicSales dlSales, DirtyManager dirty) { ... m_jKitchen.addActionListener(dirty); ... }
public void writeValueEOF() { ... m_jKitchen.setSelected(false); reportlock = false; ... m_jKitchen.setEnabled(false); ... }
public void writeValueInsert() { ... m_jKitchen.setSelected(false); reportlock = false; ... m_jKitchen.setEnabled(true); ... }
public void writeValueDelete(Object value) { ... m_jKitchen.setSelected(((Boolean)myprod[17]).booleanValue()); txtAttributes.setCaretPosition(0); reportlock = false; ... m_jKitchen.setEnabled(false); ... }
public void writeValueEdit(Object value) { ... m_jKitchen.setSelected(((Boolean)myprod[17]).booleanValue()); txtAttributes.setCaretPosition(0); reportlock = false; ... m_jKitchen.setEnabled(true); ... }
public Object createValue() throws BasicException { Object[] myprod = new Object["bold"18"bold"]; ... myprod[17] = Boolean.valueOf(m_jKitchen.isSelected()); ... }
Step 2 - edit com.openbravo.pos.forms.DataLogicSales.java
productsRow = new Row( ... new Field("PROPERTIES", Datas.BYTES, Formats.NULL), new Field("ISKITCHEN", Datas.BOOLEAN, Formats.BOOLEAN)); }
public final ProductInfoExt getProductInfo(String id) throws BasicException { return (ProductInfoExt) new PreparedSentence(s , "SELECT ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, TAXCAT, CATEGORY, ATTRIBUTESET_ID, IMAGE, ATTRIBUTES, ISKITCHEN " + "FROM PRODUCTS WHERE ID = ?" , SerializerWriteString.INSTANCE , ProductInfoExt.getSerializerRead()).find(id); }
public final ProductInfoExt getProductInfoByCode(String sCode) throws BasicException { return (ProductInfoExt) new PreparedSentence(s , "SELECT ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, TAXCAT, CATEGORY, ATTRIBUTESET_ID, IMAGE, ATTRIBUTES, ISKITCHEN " + "FROM PRODUCTS WHERE CODE = ?" , SerializerWriteString.INSTANCE , ProductInfoExt.getSerializerRead()).find(sCode); }
public final ProductInfoExt getProductInfoByReference(String sReference) throws BasicException { return (ProductInfoExt) new PreparedSentence(s , "SELECT ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, TAXCAT, CATEGORY, ATTRIBUTESET_ID, IMAGE, ATTRIBUTES, ISKITCHEN " + "FROM PRODUCTS WHERE REFERENCE = ?" , SerializerWriteString.INSTANCE , ProductInfoExt.getSerializerRead()).find(sReference); }
public List<ProductInfoExt> getProductCatalog(String category) throws BasicException { return new PreparedSentence(s , "SELECT P.ID, P.REFERENCE, P.CODE, P.NAME, P.ISCOM, P.ISSCALE, P.PRICEBUY, P.PRICESELL, P.TAXCAT, P.CATEGORY, P.ATTRIBUTESET_ID, P.IMAGE, P.ATTRIBUTES, P.ISKITCHEN " + "FROM PRODUCTS P, PRODUCTS_CAT O WHERE P.ID = O.PRODUCT AND P.CATEGORY = ? " + "ORDER BY O.CATORDER, P.NAME" , SerializerWriteString.INSTANCE , ProductInfoExt.getSerializerRead()).list(category); }
public List<ProductInfoExt> getProductComments(String id) throws BasicException { return new PreparedSentence(s , "SELECT P.ID, P.REFERENCE, P.CODE, P.NAME, P.ISCOM, P.ISSCALE, P.PRICEBUY, P.PRICESELL, P.TAXCAT, P.CATEGORY, P.ATTRIBUTESET_ID, P.IMAGE, P.ATTRIBUTES, P.ISKITCHEN " + "FROM PRODUCTS P, PRODUCTS_CAT O, PRODUCTS_COM M WHERE P.ID = O.PRODUCT AND P.ID = M.PRODUCT2 AND M.PRODUCT = ? " + "AND P.ISCOM = " + s.DB.TRUE() + " " + "ORDER BY O.CATORDER, P.NAME" , SerializerWriteString.INSTANCE , ProductInfoExt.getSerializerRead()).list(id); }
public final SentenceList getProductList() { return new StaticSentence(s , new QBFBuilder( "SELECT ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, TAXCAT, CATEGORY, ATTRIBUTESET_ID, IMAGE, ATTRIBUTES, ISKITCHEN " + "FROM PRODUCTS WHERE ?(QBF_FILTER) ORDER BY REFERENCE", new String[] {"NAME", "PRICEBUY", "PRICESELL", "CATEGORY", "CODE"}) , new SerializerWriteBasic(new Datas[] {Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.STRING}) , ProductInfoExt.getSerializerRead()); }
public SentenceList getProductListNormal() { return new StaticSentence(s , new QBFBuilder( "SELECT ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, TAXCAT, CATEGORY, ATTRIBUTESET_ID, IMAGE, ATTRIBUTES, ISKITCHEN " + "FROM PRODUCTS WHERE ISCOM = " + s.DB.FALSE() + " AND ?(QBF_FILTER) ORDER BY REFERENCE", new String[] {"NAME", "PRICEBUY", "PRICESELL", "CATEGORY", "CODE"}) , new SerializerWriteBasic(new Datas[] {Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.STRING}) , ProductInfoExt.getSerializerRead()); }
public SentenceList getProductListAuxiliar() { return new StaticSentence(s , new QBFBuilder( "SELECT ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, TAXCAT, CATEGORY, ATTRIBUTESET_ID, IMAGE, ATTRIBUTES, ISKITCHEN " + "FROM PRODUCTS WHERE ISCOM = " + s.DB.TRUE() + " AND ?(QBF_FILTER) ORDER BY REFERENCE", new String[] {"NAME", "PRICEBUY", "PRICESELL", "CATEGORY", "CODE"}) , new SerializerWriteBasic(new Datas[] {Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.STRING}) , ProductInfoExt.getSerializerRead()); }
public final SentenceList getProductCatQBF() { return new StaticSentence(s , new QBFBuilder( "SELECT P.ID, P.REFERENCE, P.CODE, P.NAME, P.ISCOM, P.ISSCALE, P.PRICEBUY, P.PRICESELL, P.CATEGORY, P.TAXCAT, P.ATTRIBUTESET_ID, P.IMAGE, P.STOCKCOST, P.STOCKVOLUME, CASE WHEN C.PRODUCT IS NULL THEN " + s.DB.FALSE() + " ELSE " + s.DB.TRUE() + " END, C.CATORDER, P.ATTRIBUTES, P.ISKITCHEN " + "FROM PRODUCTS P LEFT OUTER JOIN PRODUCTS_CAT C ON P.ID = C.PRODUCT " + "WHERE ?(QBF_FILTER) " + "ORDER BY P.REFERENCE", new String[] {"P.NAME", "P.PRICEBUY", "P.PRICESELL", "P.CATEGORY", "P.CODE"}) , new SerializerWriteBasic(new Datas[] {Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.DOUBLE, Datas.OBJECT, Datas.STRING, Datas.OBJECT, Datas.STRING}) , productsRow.getSerializerRead()); }
public final SentenceExec getProductCatInsert() { return new SentenceExecTransaction(s) { public int execInTransaction(Object params) throws BasicException { Object[] values = (Object[]) params; int i = new PreparedSentence(s , "INSERT INTO PRODUCTS (ID, REFERENCE, CODE, NAME, ISCOM, ISSCALE, PRICEBUY, PRICESELL, CATEGORY, TAXCAT, ATTRIBUTESET_ID, IMAGE, STOCKCOST, STOCKVOLUME, ATTRIBUTES, ISKITCHEN) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" , new SerializerWriteBasicExt(productsRow.getDatas(), new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17})).exec(params); if (i > 0 && ((Boolean)values[14]).booleanValue()) { return new PreparedSentence(s , "INSERT INTO PRODUCTS_CAT (PRODUCT, CATORDER) VALUES (?, ?)" , new SerializerWriteBasicExt(productsRow.getDatas(), new int[] {0, 15})).exec(params); } else { return i; } } }; }
public final SentenceExec getProductCatUpdate() { return new SentenceExecTransaction(s) { public int execInTransaction(Object params) throws BasicException { Object[] values = (Object[]) params; int i = new PreparedSentence(s , "UPDATE PRODUCTS SET ID = ?, REFERENCE = ?, CODE = ?, NAME = ?, ISCOM = ?, ISSCALE = ?, PRICEBUY = ?, PRICESELL = ?, CATEGORY = ?, TAXCAT = ?, ATTRIBUTESET_ID = ?, IMAGE = ?, STOCKCOST = ?, STOCKVOLUME = ?, ATTRIBUTES = ?, ISKITCHEN = ? WHERE ID = ?" , new SerializerWriteBasicExt(productsRow.getDatas(), new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 0})).exec(params); if (i > 0) { if (((Boolean)values[14]).booleanValue()) { if (new PreparedSentence(s , "UPDATE PRODUCTS_CAT SET CATORDER = ? WHERE PRODUCT = ?" , new SerializerWriteBasicExt(productsRow.getDatas(), new int[] {15, 0})).exec(params) == 0) { new PreparedSentence(s , "INSERT INTO PRODUCTS_CAT (PRODUCT, CATORDER) VALUES (?, ?)" , new SerializerWriteBasicExt(productsRow.getDatas(), new int[] {0, 15})).exec(params); } } else { new PreparedSentence(s , "DELETE FROM PRODUCTS_CAT WHERE PRODUCT = ?" , new SerializerWriteBasicExt(productsRow.getDatas(), new int[] {0})).exec(params); } } return i; } }; }
Step 3 - edit com.openbravo.pos.ticket.ProductInfoExt.java
public class ProductInfoExt { ... protected boolean m_bKitchen; ...
public ProductInfoExt() { ... m_bKitchen = false; }
Add new functions:
public final boolean isKitchen() { return m_bKitchen; } public final void setKitchen(boolean bValue) { m_bKitchen = bValue; }
public static SerializerRead getSerializerRead() { ... product.m_bKitchen = dr.getBoolean(14).booleanValue(); ... }
Step 4 - edit com.openbravo.pos.ticket.TicketLineInfo.java
public TicketLineInfo(ProductInfoExt product, double dMultiply, double dPrice, TaxInfo tax, Properties attributes) { ... attributes.setProperty("product.com", product.isCom() ? "true" : "false"); attributes.setProperty("product.kitchen", product.isKitchen() ? "true" : "false"); ... }
Add new function:
public boolean isProductKitchen() { return "true".equals(attributes.getProperty("product.kitchen")); }
Build new JAR and use it!
Step 5 - add new resource called Script.SendOrder
boolean kitchen = false; for(int i= 0; i < ticket.getLinesCount(); i++){ line = ticket.getLine(i); if (line.isProductKitchen() && (line.getProperty("sendstatus") == null)){ line.setProperty("sendstatus", "No"); } if((line.isProductKitchen()) && (line.getProperty("sendstatus").equals("No"))){ kitchen = true; } } if (kitchen) { sales.printTicket("Printer.TicketKitchen"); } //Show a nice message for confirmation if (kitchen){ javax.swing.JOptionPane.showMessageDialog(null, "Order sent to kitchen."); } else { javax.swing.JOptionPane.showMessageDialog(null, "Nothing to send.", "Warning", JOptionPane.WARNING_MESSAGE); } for(int i = ticket.getLinesCount()-1; i>= 0 ; i--){ line = ticket.getLine(i); String a = line.getProperty("sendstatus"); if((line.isProductKitchen()) && (line.getProperty("sendstatus").equals("No"))){ line.setProperty("sendstatus", "OK"); } }
Step 6 - add new resource called event.total
//Stop payment when all items not sent for(int i= 0; i < ticket.getLinesCount(); i++){ line = ticket.getLine(i); // Set Discount(printkb=NULL) to N/A so it does not error on next section. if ($ticketline.isProductKitchen()){ line.setProperty("sendstatus", "No"); } if(line.getProperty("sendstatus").equals("No")){ mySent = "No"; } } if (mySent == "No"){ javax.swing.JOptionPane.showMessageDialog(null, "Before closing ticket, please send order to kitchen", "HOIATUS", JOptionPane.WARNING_MESSAGE); return "Cancel"; }else{ return null; }
Step 7 - add new resource called Printer.TicketKitchen
<?xml version="1.0" encoding="UTF-8"?> <!-- Openbravo POS is a point of sales application designed for touch screens. Copyright (C) 2008 Openbravo, S.L. http://sourceforge.net/projects/openbravopos This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --> <output> <display> <line> <text align="left" length="10">Order sent to Kitchen</text> <text align="right" length="10">${ticket.printTotal()}</text> </line> <line> <text align="center" length="20">Thank you.</text> </line> </display> <ticket printer = "2"> <line></line> <line></line> <line> <text align="center" length="42">Kitchen Order</text> </line> <line></line> <line> <text align="left" length="15">Receipt:</text> <text>${ticket.printId()}</text> </line> <line> <text align="left" length="15">Date:</text> <text>${ticket.printDate()}</text> </line> #if ($ticket.getCustomer()) <line> <text align="left" length="15">Customer:</text> <text>${ticket.getCustomer().getName()}</text> </line> <line> <text align="left" length="15"></text> <text>${ticket.getCustomer().getTaxid()}</text> </line> #end #if ($place != "") <line> <text align="left" length="15">Table:</text> <text>${place}</text> </line> #end <line></line> <line> <text align ="left" length="17">Item</text> <text align ="right" length="5"></text> </line> <line> <text>------------------------------------------</text> </line> #foreach ($ticketline in $ticket.getLines()) #if(($ticketline.isProductKitchen()) && ($ticketline.getProperty("sendstatus").equals("No"))) <line> <text align ="left" length="5" bold="true">${ticketline.printMultiply()}x</text> #if ($ticketline.isProductCom()) <text align ="left" length="37">--${ticketline.printName()}</text> #else <text align ="left" length="37" bold="true">${ticketline.printName()}</text> #end </line> #end <!-- Add the following lines only for 2.30 Attributes --> #if ($ticketline.productAttSetInstId) <line> <text align ="left" length="42"> ${ticketline.productAttSetInstDesc}</text> </line> #end <!-- Add the previous lines only for 2.30 Attributes --> #end <line> <text>------------------------------------------</text> </line> <line> <text align="left" length="15">Cashier:</text> <text>${ticket.printUser()}</text> </line> </ticket> </output>
Step 8 - add to resource ticket.buttons new line
<button key="button.sendorder" name="button.sendorder" code="Script.SendOrder"/> <event key="ticket.total" code="event.total"/>
Step 9 - add to roles new line
<class name="button.sendorder"/>
Step 10 - add to pos_messages.properties file new line
button.sendorder=Send
Restart Openbravo POS!