- Edited bills report
- Fixing Database Not Loading error in Saleculator M5
- Printing reports in thermal receipt printer
- Assign product categories to user roles
- Printing encoded product cost on label
- Fixing issue, which required double tapping on touch screen to get click working
- Protecting Saleculator Database from Ransomware Attacks
- Installing AnyDesk in Saleculator
- Get quantity from price embedded barcodes
- Print Open Items in Close Cash Report
- Update cumulative stock balance in stock diary
- Using Saleculator for subscription based billing
- Automatic Billing On Events
- Printing Expiry Date On Product Labels
- Enabling Tapping To Click for touchpads
- Installing WiFi adpaters
- Enabling support for more than 4 serial devices
- Dynamic item pricing based on auxiliary item
- Applying tax on an open item
- VAT Update Resources for UAE and KSA
- Connect a network thermal printer directly with Saleculator
- Apply discount on a selected item
- Switch screen mode from portrait to landscape
- Running remote Saleculator in Windows using Putty
- Print total amount in words
- GST Update for India
- Setup HP or Samsung Laser/Deskjet Printers
- Setting offer to choose any 5 items for the price of 3
- Buy One Get One Sale
- Tag-Along items
- Happy hour sale
- Recover data from ibdata and .frm files
- Resources supporting 42 character printer
- Print accounts report on every 1st of month
- Show stock of selected item or stop selling out of stock item
- Change warehouse for current sale
- Disable Saleculator screen turning blank due to inactivity
- Fix issue of monitor turning blank while Saleculator loading
- Solving common disk errors
- IMPORTANT! Close cash report changed in version 3.8 U2 onwards
- Adding new reports in Close Cash report
- Accepting advance payment
- Stock movement in close cash report
- Persistent names for usb and serial devices
Please visit Saleculator Support youtube channel for how to videos.
Edited bills report #
Here is how you can print list of edited bills
(Note: To enable any command remove <!– at the start and –> at the end of the command lines. Disabled commands will be green in color, once enabled the color changes to black and red combination, for commands with — at the start just remove the —, for single line commands with // at the start remove the //)
Administration Menu > Maintenance > Resources
1. Enable ticket.total in Ticket.Buttons (Line 57)
2. Enable SALES_LOG; in CloseCash.Reports (Line 16)
3. Add below lines at the bottom in event.total
if (ticket.printId()=="") { ticket.setProperty("ACTUALTOTAL", ticket.printTotal()); ticket.setProperty("ACTUALDATE", ticket.printDate()); } else { ticket.setProperty("EDITED", "TRUE"); } Save
Add below lines at the bottom in Printer.CloseCash and Printer.PartialCash
<!-- EDITED BILLS REPORT START --> <line></line> <line> <text bold="true">Edited Bills</text> </line> <line> <text align="left" length="10">#</text> <text align="left" length="24">Date</text> <text align="right" length="14">Total</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $payments.getSalesTickets()) #if($line.getProperty("EDITED")== "TRUE") <line> <text align="left" length="10">${line.printTicketId()}</text> <text align="left" length="24">${line.printTicketDate()}</text> <text align="right" length="14">${line.printAmount()}</text> </line> <line> <text align="left" length="30">Edited: ${line.getProperty("ACTUALDATE")}</text> <text align="right" length="18">${line.getProperty("ACTUALTOTAL")}</text> </line> #end #end <line> <text>------------------------------------------------</text> </line> <!-- EDITED BILLS REPORT END -->
Click the save button on top and restart.
Fixing Database Not Loading error in Saleculator M5 #
Here is how to fix when you get error /var/run/mysqld/mysqld.sock (2
Press CTRL+ALT+F1 and run below command:
mysqld_safe --skip-grant-tables &
Now press CTRL+ALT+F2 and run below commands:
mysql mysql> use mysql mysql> repair table host use_frm; mysql> exit service mysql restart
If MySQL is restarted without any error, you may reboot the system.
If MySQL still not working, follow the below steps:
nano /etc/mysql/mariadb.conf.d/50-server.cnf
Now add below line after the line, inndob_fast_shutdown = 0
innodb_force_recovery = 1
Save the file by pressing, CTRL+X, Y, Enter.
Run below command.
service mysql restart
If MySQL is restarted without any error, login to the POS system, take backup, reset system and restore the backup.
Now reboot the system and remove or comment the line ‘innodb_force_recovery = 1’ and reboot the system.
Printing reports in thermal receipt printer #
Here is how to add custom reports in Saleculator which can be printed in thermal receipt printer.
This feature is available only in version 4.0 u2 onwards.
Administration Menu > Maintenance > Resources
1. Add below line in Menu.Root:
group.addPanel("/com/posics/images/posreports.png", "Menu.POSReports", "com.posics.pos.reports.JPanelPOSReports");
Save
2. Add below line in Roles:
<class name="com.posics.pos.reports.JPanelPOSReports"/>
Save
3. Now download and restore the script from below link, or follow below steps to create reports manually.
saleculator.com/download/posreports.sql
1. Create a new text resource with name POS.Reports and copy paste below lines:
<?xml version="1.0" encoding="UTF-8"?> <!-- Posics Saleculator - Billing System. Copyright (C) 2009 Posics This file is part of Posics Saleculator. --> <configuration> <button key="button.print" titlekey="Sales Log" template="POS.Report.SalesLog"/> <button key="button.print" titlekey="Product Sales" template="POS.Report.ProductSales"/> <button key="button.print" titlekey="Current Inventory" template="POS.Report.CurrentInventory"/> <button key="button.print" titlekey="Cash Closed" template="POS.Report.CashClosed"/> <button key="button.print" titlekey="Payments" template="POS.Report.Payments"/> </configuration>
Save
2. Create a new text resource with name POS.Report.SalesLog and copy paste below lines:
<?xml version="1.0" encoding="UTF-8"?> <!-- Posics Saleculator - Billing System. Copyright (C) 2009 Posics This file is part of Posics Saleculator. --> <output> <sql><![CDATA[ SELECT TICKETS.TICKETID, RECEIPTS.DATENEW, SUM((TICKETLINES.PRICE + TICKETLINES.PRICE * TAXES.RATE) * TICKETLINES.UNITS), SUM((TICKETLINES.PRICE * TAXES.RATE) * TICKETLINES.UNITS) FROM RECEIPTS JOIN TICKETS ON RECEIPTS.ID = TICKETS.ID AND (TICKETS.TICKETTYPE=0 OR TICKETS.TICKETTYPE=1) JOIN TICKETLINES ON TICKETLINES.TICKET = RECEIPTS.ID JOIN TAXES ON TICKETLINES.TAXID = TAXES.ID WHERE RECEIPTS.DATENEW >= $startDate AND RECEIPTS.DATENEW <= $endDate GROUP BY RECEIPTS.ID ORDER BY RECEIPTS.DATENEW ]]></sql> <ticket> <image>Printer.Ticket.Logo</image> <line></line> <line size="1"> <text align ="center" length="48" bold="true">Sales Log</text> </line> <line></line> <line> <text length="12">Start Date:</text> <text length="36">$startDate</text> </line> <line> <text length="12">End Date:</text> <text length="36">$endDate</text> </line> <line> </line> <line> <text align ="left" length="5">#</text> <text align ="left" length="20">Date</text> <text align ="right" length="13">Total</text> <text align ="right" length="10">Tax</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $posreport.getResult()) <line> <text align ="left" length="5">${line.printValue(0)}</text> <text align ="left" length="20">${line.printDate(1)}</text> <text align ="right" length="13">${line.printCurrency(2)}</text> <text align ="right" length="10">${line.printCurrency(3)}</text> </line> #end <line> <text>------------------------------------------------</text> </line> <line> <text align ="left" length="5">Total</text> <text align ="left" length="20"></text> <text align ="right" bold="true" length="13">$posreport.printTotal(2)</text> <text align ="right" bold="true" length="10">$posreport.printTotal(3)</text> </line> </ticket> </output>
Save
3. Create a new text resource with name POS.Report.Payments and copy paste below lines:
<?xml version="1.0" encoding="UTF-8"?> <!-- Posics Saleculator - Billing System. Copyright (C) 2009 Posics This file is part of Posics Saleculator. --> <output> <sql><![CDATA[ SELECT RECEIPTS.DATENEW, TICKETS.TICKETID, PAYMENTS.PAYMENT, PAYMENTS.TOTAL, ACCOUNTHEADS.NAME, PAYMENTS.NOTES FROM PAYMENTS JOIN RECEIPTS ON PAYMENTS.RECEIPT = RECEIPTS.ID LEFT JOIN TICKETS ON TICKETS.ID=RECEIPTS.ID JOIN ACCOUNTHEADS ON ACCOUNTHEADS.ID = RECEIPTS.ACCOUNTHEAD WHERE RECEIPTS.DATENEW >= $startDate AND RECEIPTS.DATENEW <= $endDate ORDER BY RECEIPTS.DATENEW ]]></sql> <ticket> <image>Printer.Ticket.Logo</image> <line></line> <line size="1"> <text align ="center" length="48" bold="true">Payments</text> </line> <line></line> <line> <text length="12">Start Date:</text> <text length="36">$startDate</text> </line> <line> <text length="12">End Date:</text> <text length="36">$endDate</text> </line> <line> </line> <line> <text align ="left" length="20">Date</text> <text align ="left" length="10">Receipt</text> <text align ="left" length="8">Type</text> <text align ="right" length="10">Total</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $posreport.getResult()) <line> <text align ="left" length="20">${line.printDate(0)}</text> <text align ="left" length="10">${line.printValue(1)}</text> <text align ="left" length="8">${line.printValue(2)}</text> <text align ="right" length="10">${line.printCurrency(3)}</text> </line> #if(!$line.printValue(5).equals("")) <line> <text>${line.printValue(4)} - ${line.printValue(5)}</text> </line> #end #end <line> <text>------------------------------------------------</text> </line> <line> <text align ="left" length="20">Total</text> <text align ="left" length="10"></text> <text align ="left" length="8"></text> <text align ="right" bold="true" length="10">$posreport.printTotal(3)</text> </line> </ticket> </output>
Save
4. Create a new text resource with name POS.Report.CashClosed and copy paste below lines:
<?xml version="1.0" encoding="UTF-8"?> <!-- Posics Saleculator - Billing System. Copyright (C) 2009 Posics This file is part of Posics Saleculator. --> <output> <sql><![CDATA[ SELECT CLOSEDCASH.MONEY AS ID, CLOSEDCASH.HOST, CLOSEDCASH.HOSTSEQUENCE, CLOSEDCASH.DATESTART, CLOSEDCASH.DATEEND, SUM(PAYMENTS.TOTAL) AS TOTAL FROM CLOSEDCASH LEFT JOIN RECEIPTS ON RECEIPTS.MONEY = CLOSEDCASH.MONEY LEFT JOIN PAYMENTS ON PAYMENTS.RECEIPT = RECEIPTS.ID WHERE CLOSEDCASH.DATEEND IS NOT NULL AND CLOSEDCASH.DATESTART >= $startDate AND CLOSEDCASH.DATESTART <= $endDate GROUP BY CLOSEDCASH.MONEY ORDER BY CLOSEDCASH.HOSTSEQUENCE DESC ]]></sql> <ticket> <image>Printer.Ticket.Logo</image> <line></line> <line size="1"> <text align ="center" length="48" bold="true">Cash Closed</text> </line> <line></line> <line> <text length="12">Start Date:</text> <text length="36">$startDate</text> </line> <line> <text length="12">End Date:</text> <text length="36">$endDate</text> </line> <line> </line> <line> <text align ="left" length="15">Host</text> <text align ="left" length="10">Sequence</text> <text align ="right" length="23">Total</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $posreport.getResult()) <line> <text align ="left" length="15">${line.printValue(1)}</text> <text align ="left" length="10">${line.printValue(2)}</text> <text align ="right" length="23">${line.printCurrency(5)}</text> </line> <line> <text>${line.printDate(3)} TO ${line.printDate(4)}</text> </line> #end <line> <text>------------------------------------------------</text> </line> <line> <text align ="left" length="15">Total</text> <text align ="left" length="10"></text> <text align ="right" bold="true" length="23">$posreport.printTotal(5)</text> </line> </ticket> </output>
Save
5. Create a new text resource with name POS.Report.CurrentInventory and copy paste below lines:
<?xml version="1.0" encoding="UTF-8"?> <!-- Posics Saleculator - Billing System. Copyright (C) 2009 Posics This file is part of Posics Saleculator. --> <output> <sql><![CDATA[ SELECT PRODUCTS.NAME, PRODUCTS.CODE, SUM(STOCKCURRENT.UNITS) AS UNITS, (PRODUCTS.PRICEBUY*SUM(STOCKCURRENT.UNITS)) AS COST FROM STOCKCURRENT JOIN PRODUCTS ON STOCKCURRENT.PRODUCT = PRODUCTS.ID GROUP BY PRODUCTS.ID ORDER BY PRODUCTS.NAME ]]></sql> <ticket> <image>Printer.Ticket.Logo</image> <line></line> <line size="1"> <text align ="center" length="48" bold="true">Current Inventory</text> </line> <line></line> <line> <text>Date: $posreport.printDate()</text> </line> <line> </line> <line> <text align ="left" length="20">Product</text> <text align ="right" length="10">Units</text> <text align ="right" length="18">Value</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $posreport.getResult()) <line> <text align ="left" length="20">${line.printValue(0)} (${line.printValue(1)})</text> <text align ="right" length="10">${line.printValue(2)}</text> <text align ="right" length="18">${line.printCurrency(3)}</text> </line> #end <line> <text>------------------------------------------------</text> </line> <line> <text align ="left" length="30">${posreport.printCount()} Products</text> <text align ="right" bold="true" length="18">$posreport.printTotal(3)</text> </line> </ticket> </output>
Save
6. Create a new text resource with name POS.Report.ProductSales and copy paste below lines:
<?xml version="1.0" encoding="UTF-8"?> <!-- Posics Saleculator - Billing System. Copyright (C) 2009 Posics This file is part of Posics Saleculator. --> <output> <sql><![CDATA[ SELECT CATEGORIES.NAME, PRODUCTS.NAME, PRODUCTS.CODE, SUM(TICKETLINES.UNITS) AS UNITS, SUM(TICKETLINES.UNITS * TICKETLINES.PRICE) AS TOTAL FROM RECEIPTS, TICKETS, TICKETLINES LEFT JOIN PRODUCTS ON TICKETLINES.PRODUCT = PRODUCTS.ID LEFT JOIN CATEGORIES ON CATEGORIES.ID=PRODUCTS.CATEGORY WHERE RECEIPTS.ID = TICKETS.ID AND TICKETS.ID = TICKETLINES.TICKET AND RECEIPTS.DATENEW >= $startDate AND RECEIPTS.DATENEW <= $endDate GROUP BY PRODUCTS.ID ORDER BY CATEGORIES.NAME, PRODUCTS.NAME ]]></sql> <ticket> <image>Printer.Ticket.Logo</image> <line></line> <line size="1"> <text align ="center" length="48" bold="true">Product Sales</text> </line> <line></line> <line> <text length="12">Start Date:</text> <text length="36">$startDate</text> </line> <line> <text length="12">End Date:</text> <text length="36">$endDate</text> </line> <line> </line> <line> <text align ="left" length="25">Product</text> <text align ="right" length="10">Units</text> <text align ="right" length="13">Total</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $posreport.getResult()) <line> <text align ="left" length="25">${line.printValue(1)} (${line.printValue(2)})</text> <text align ="right" length="10">${line.printValue(3)}</text> <text align ="right" length="13">${line.printCurrency(4)}</text> </line> #end <line> <text>------------------------------------------------</text> </line> <line> <text align ="left" length="25">Total</text> <text align ="right" length="10"></text> <text align ="right" bold="true" length="13">$posreport.printTotal(4)</text> </line> </ticket> </output>
Save
Methods used in POS Reports
$posreport.getResult(): Get result of the executed query $posreport.roundDouble(value, decimals): Get rounded value $posreport.formatCurrency(value): Get currency format of the value $posreport.getTotal(field_number): Get total of the field $posreport.printTotal(field_number): Print currency formatted total of the field $posreport.printCount(): Print number of records in the result $posreport.printDate(): Print current date and time $line.printValue(field_number): Print field value as text $line.printCurrency(field_number): Print field value as currency $line.printDate(field_number): Print field value as date $line.getDouble(field_number): Get double value of the field for calculation $line.getInteger(field_number): Get integer value of the field for calculation
Assign product categories to user roles #
Here is how you can restrict users from selling specific category of products
Works only in version 4.0 onwards.
Administration Menu > Maintenance > Resources
To restrict specific product categories from users, add below lines in user role.
<class name="category.breakfast"/> <class name="category.lunch"/> <class name="category.dinner"/>
Save
Here the user in this particular role can only sell products from categories Breakfast, Lunch and Dinner.
Printing encoded product cost on label #
Administration Menu > Maintenance > Resources
Use below template in Printer.Label to encode and print product cost on label. You may use some meaningful phrase for encryption key.
<?xml version="1.0" encoding="UTF-8"?> <label> <text width="20" height="20" x="280" y="20">$product.printName()</text> <barcode x="320" y="110" type="CODE128" height="50" width="2" readable="N">$product.getCode()</barcode> <text width="30" height="30" x="280" y="170">Price:$line.printPriceSellTax()</text> #set($message = $line.printPrice()) #set($key = "ABCDEFGHIJK") #set($alphabet = "0123456789") #set($coded = "") #foreach ($index in [0..$message.length()]) #set($nextChar = $index+1) #if ($nextChar <= $message.length()) #set($curChar = $message.substring($index, $nextChar)) #set($charIndex = $alphabet.indexOf($curChar)) #if ($charIndex == -1) #set($coded = $coded + $curChar) #else { #set($coded = $coded + $key.charAt($charIndex)) #end #end #end <text width="30" height="30" x="480" y="170">$coded</text> </label>
Save
Fixing issue, which required double tapping on touch screen to get click working #
We have found this issue in LG TS2009F Touchscreen. Here is how to fix this issue in Saleculator M5
> Connect POS system to internet
Press CTRL+ALT+F1
> Type below command and press enter
apt-get install xserver-xorg-input-evdev
> Type below command and press enter
nano /usr/share/X11/xorg.conf.d/40-libinput.conf
On fifth line, replace “libinput” to “evdev”
> Press CTRL+X, Press Y, Then press Enter
> Reboot
Protecting Saleculator Database from Ransomware Attacks #
Saleculators allowed for remote access with DMZ enabled are prone to attacks. Follow below notes to stop this.1. NEVER enable DMZ for remote access. It opens all the doors(ports) of router for hackers. Forward only port 80(Webin) and port 22(Putty).
2. CHANGE default MySQL root password from “password” to something else.
To change the root password,
Step 1: Under Saleculator configuration, for database password give new password and save.
Step 2: Use the command mysql_secure_installation from terminal to change root password.
Step 3: Edit Webin configuration file “nano /var/www/application/config/database.php” and set new password.
Forward port 3306 for remote database access. Execute below mysql statement for remote access.
GRANT ALL PRIVILEGES ON SALECULATOR.* TO `root`@`%` IDENTIFIED BY `newpassword` WITH GRANT OPTION;
If the new database password is saleculator, use below line in Saleculator.properties.
db.password=crypt\:85811D6FEFF95AD8424FD4E62735F122
Installing AnyDesk in Saleculator #
AnyDesk can be used to access Saleculator for remote support
Press CTRL+ALT+F1
Install below package.
apt-get install gnupg
Run the following commands as root user:
– add repository key to Trusted software providers list:
wget -qO – https://keys.anydesk.com/repos/DEB-GPG-KEY | apt-key add –
– add the repository:
echo “deb http://deb.anydesk.com/ all main” > /etc/apt/sources.list.d/anydesk-stable.list
– update apt cache:
apt update
– install anydesk:
apt install anydesk
If installation fail, repeat below commands. apt-get install -f apt-get install anydesk
Set below line in Saleculator.properties file Script.remote=anydesk Script.CMD1=xterm
If you are getting error like “desk_rt_ipc_error” or “anynet_closed”, download any older version from below repository: https://download.anydesk.com/linux/ And install using dpkg -i command, like below Example: apt-get remove anydesk wget https://download.anydesk.com/linux/anydesk_4.0.0-1_i386.deb dpkg -i anydesk_4.0.0-1_i386.deb
Save
Get quantity from price embedded barcodes #
Below script can be used to get quantity from price embedded barcodes.Copy paste below code in event.addline:
if(line.printCode()!=null && line.printCode().startsWith("210") && line.getPrice()>0) { line.setMultiply(line.getSalePrice()/line.getPrice()); line.setSalePrice(line.getPrice()); }
Save
Print Open Items in Close Cash Report #
Administrator Menu > Maintenance > Resources
Use below script in SQL.CloseCash to print open items
Copy paste below code in SQL.CloseCash:
SELECT TICKETS.TICKETID, CONVERT(ExtractValue(CAST(TICKETLINES.ATTRIBUTES AS binary), "//entry[@key=\"product.name\"]") USING utf8) AS PRODUCT, UNITS, FORMAT(PRICE,2) FROM TICKETLINES JOIN RECEIPTS ON TICKETLINES.TICKET = RECEIPTS.ID AND RECEIPTS.MONEY=? JOIN TICKETS ON TICKETS.ID = TICKETLINES.TICKET WHERE TICKETLINES.PRODUCT IS NULL GROUP BY RECEIPTS.ID ORDER BY RECEIPTS.DATENEW;
Save
Copy paste below code in Close Cash reports:
<line></line> <line> <text align ="center" length="48">OPEN ITEMS</text> </line> <line> <text length="10">Receipt</text> <text length="23">Product</text> <text length="5">Units</text> <text align="right" length="10">Price</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $payments.getSQLResult().get(0)) <line> <text length="10">${line.printValue(0)}</text> <text length="23">${line.printValue(1)}</text> <text length="5">${line.printValue(2)}</text> <text align ="right" length="10">${line.printValue(3)}</text> </line> #end <line> <text>------------------------------------------------</text> </line>
Save
Update cumulative stock balance in stock diary #
This sql script can be used to keep cumulative stock balance in stockdiary table.Execute below script once in mySQL.
ALTER TABLE STOCKDIARY ADD COLUMN STOCKBALANCE INT; DROP PROCEDURE if exists updateStockBalance; DELIMITER $$ CREATE PROCEDURE updateStockBalance() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE o_id VARCHAR(255); DECLARE balance INT; DECLARE cur1 CURSOR FOR SELECT ID FROM PRODUCTS; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur1; read_loop: LOOP FETCH cur1 INTO o_id; SET @balance = 0; SET @pid = o_id; UPDATE STOCKDIARY SET STOCKBALANCE=@balance:=@balance + UNITS WHERE PRODUCT LIKE @pid AND STOCKBALANCE IS NULL ORDER BY DATENEW; IF done THEN LEAVE read_loop; END IF; END LOOP; CLOSE cur1; END$$ DELIMITER ;
Schedule below script to keep the stockbalance column updated:
CALL updateStockBalance();
Save
Using Saleculator for subscription based billing #
This howto explains using Saleculator for subscription based billingThis method makes use of advance payment for tracking active subscriptions.
1. Accept advance payment from customers.
2. Make a sale choosing the right subscription package for the advance paid. Use Advance for payment.
Administrator Menu > Maintenance > Resources
3. Use below section in Printer.Ticket to print subscription expiry date. Change the value 30 to desired value for subscription validity in days.
#if (($ticket.getCustomer() && $ticket.getCustomer().getAdvanceDate()) #set($y = $ticket.getCustomer().getAdvanceDate().getYear() + 1900) #set($m = $ticket.getCustomer().getAdvanceDate().getMonth() + 1) #set($d = $ticket.getCustomer().getAdvanceDate().getDate()) #set($d = $d + 30) #if ((($m ==4) || ($m ==6) || ($m ==9) || ($m ==11)) && ($d > 30)) #set($m = $m + 1) #set($d = $d - 30) #elseif (($m ==2) && ($d > 28)) #set($m = $m + 1) #set($d = $d - 28) #elseif ($d > 31) #set($m = $m + 1) #set($d = $d - 31) #end #if($m > 12) #set($m = 1) #set($y = $y + 1) #end <line> <text align ="center" length="48" bold="true">Expires On: $d/$m/$y</text> </line> #end
4. Use below script in event.total to cancel billing for inactive subscribers. Change the value 30 to desired value for subscription validity in days.
if(ticket.getCustomer()!=null) { if(ticket.getCustomer().getAdvanceDate()!=null) { long diff = ticket.getDate().getTime() - ticket.getCustomer().getAdvanceDate().getTime(); int diffDays = (int) (diff / (24 * 60 * 60 * 1000)); javax.swing.JOptionPane.showMessageDialog(null, diffDays); if(diffDays>30) { return "Cancel"; } } } Save
Automatic Billing On Events #
This video shows how to set automatic billing on certain events, like on selecting a specific item, or when the total amount exceeds certain limit. This method generates a cash bill.
Administrator Menu > Maintenance > Resources
Enable ticket.change in Ticket.Buttons. Add event.change in resources and copy paste below code. Below code checks product name “ORANGE” for quick billing.
int i = ticket.getLinesCount(); if(ticket.getLine(i-1).printName().equals("ORANGE")) { sales.payCash(); } Save
Printing Expiry Date On Product Labels #
Watch the video on how to print expiry date on product labels.
https://www.youtube.com/watch?v=9JAfVFIGeIE
Enabling Tapping To Click for touchpads #
Make this small change if tapping on touchpad is not working
Ctrl + Alt + F1
Type below commands
1. nano /usr/share/X11/xorg.conf.d/40-libinput.conf
2. In the section for touchpad add below line just before EndSection
Option “Tapping” “on”
3. Press CTRL+X, then press Y, and press Enter to save the file.
4. Reboot the system
Installing WiFi adpaters #
Following a list of WiFi adapters and the steps to install itIntel 5100
Ctrl+Alt+F1
apt-get install lshw apt-get install firmware-iwlwifi modprobe -r iwlwifi modprobe iwlwifi ifconfig wlp1s0 up
Ralink RT3290
1. Download the patched file from below link
2. Open a terminal (Ctrl+Alt+F1) and cd into the folder where the file is downloaded, e.g. cd ~/Downloads.
sudo tar -xvf rt3290sta-2.6.0.0.dkms.tar -C /usr/src
sudo dkms install -m rt3290sta -v 2.6.0.0 –force
reboot
Enabling support for more than 4 serial devices #
This setting enable Saleculator support more than 4 serial devices
Ctrl+Alt+F1
1. Type below command to edit file /etc/default/grub
nano /etc/default/grub
Set below value
GRUB_CMDLINE_LINUX=”8250.nr_uarts=8″
Now press CTRL+X, Y, Enter to save file
2. Type below command and press enter
update-grub
3. Reboot
Dynamic item pricing based on auxiliary item #
This script can be used to set item options during sales. It also sets the item price based on the chosen option.
Watch below video on how to do this:
https://youtu.be/f9BFX2kIveQ
Administrator Menu > Maintenance > Resources
Use the below code in product properties:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="SMALL">0</entry> <entry key="MEDIUM">2</entry> <entry key="LARGE">4</entry> </properties>
Use the below clode in event.addline:
if (line.isProductCom() && ticket.getLinesCount() > 0) { if(ticket.getLine(index).getProperty(line.printName())!=null) { ticket.getLine(index).setSalePrice(ticket.getLine(index).getSalePrice() + ticket.parseDouble(ticket.getLine(index).getProperty(line.printName()))); } ticket.getLine(index).setProperty("product.name", ticket.getLine(index).getProductName() + " " + line.printName()); return "Cancel"; } Save
Applying tax on an open item #
Follow the below steps to apply tax on an open item (items not available in catalog).
1. Create a general item with sell price 0 and map into the right tax category. This item can be used to bill open items.
Administrator Menu > Maintenance > Resources
2. In the resource, event.addline, change the below line, line number 31 in the default configuration:
line.setSalePrice(newPrice);
to
line.setSalePrice(newPrice/(1+line.getTaxRate()));
Save
VAT Update Resources for UAE and KSA #
Here is the resources you need to update for VAT
Administrator Menu > Maintenance > Resources
Printer.Ticket and Printer.TicketPreview
<!-- TAXES START--> #if($ticket.getTax()>0) <line></line> #foreach ($taxinfo in $taxes) #set( $taxline = $ticket.getTaxLine($taxinfo)) <line> <text align="left" length="24">${taxline.getTaxInfo()}</text> <text align="right" length="12">${taxline.printSubTotal()}</text> <text align="right" length="12">${taxline.printTax()}</text> </line> #end <line> </line> <line> <text align="left" length="16">Subtotal.</text> <text align="right" length="32">${ticket.printSubTotal()}</text> </line> <line> <text align="left" length="16">Taxes.</text> <text align="right" length="32">${ticket.printTax()}</text> </line> #end <!-- TAXES END-->
Printer.CloseCash, Printer.PartialCash, Printer.CloseCashMail
<!-- TAXES REPORT START --> <line> <text bold="true">Taxes Report</text> </line> <line> <text align="right" length="48">Total</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $payments.getSaleLines()) <line> <text align="left" length="38">${line.printTaxName()}</text> <text align="right" length="10">${line.printTaxes()}</text> </line> #end <line> <text>------------------------------------------------</text> </line> <line></line> <!-- TAXES REPORT END -->
Ticket.Lines, add below line before line total
<column name="label.tax" width="80" align="right" value="${ticketline.printTax()}"/> Save
Connect a network thermal printer directly with Saleculator #
This procedure help to connect a network thermal printer with Saleculator for KOT or receipt printing.
1. Note down printer IP address by taking a test print.
Hold printer feed button and switch on printer to take a test print.
2. Connect printer to a windows system using a patch cord.
3. Change system IP address range to printer IP address range.
If printer IP address is 192.168.123.100, then change system IP address to 192.168.123.101 and system gateway to 192.168.123.1.
4. From the system, load any web browser and enter printer IP address in URL. This will load printer settings in the browser.
5. Now change the printer IP address to 192.168.1.100, and gateway to 192.168.1.1
6. Save the settings and restart printer.
7. Take test print again and confirm whether printer IP has been changed.
8. Connect printer to Saleculator and in Saleculator printer configuration use network instead of file and printer IP, 192.168.1.100, instead of port.
9. Save configuration and restart Saleculator.
Apply discount on a selected item #
This script can be used to apply a discount on a selected item.
Administrator Menu > Maintenance > Resources
Create a resource Script.DiscountOnItem and copy paste below code:
pflag = 0; if (sales.getSelectedIndex() >= 0) { String discountperc = JOptionPane.showInputDialog(null, "Please enter discount amount:\n(Add a % sign at the end for percentage discount.)"); if (discountperc.length() > 0) { double discountrate = 0.0; if (discountperc.lastIndexOf("%") == discountperc.length() - 1 && Double.parseDouble(discountperc.substring(0, discountperc.lastIndexOf("%"))) > 0.0) { discountrate = Double.parseDouble(discountperc.substring(0, discountperc.lastIndexOf("%"))); discountrate = discountrate / 100.00; pflag = 1; } else if (Double.parseDouble(discountperc) > 0.0) { discountrate = Double.parseDouble(discountperc); } line = ticket.getLine(sales.getSelectedIndex()); if (pflag == 1) { line.setSalePrice(line.getPrice() - (line.getPrice() * discountrate * 1)); } else { line.setSalePrice(line.getPrice() - discountrate); } } } else { java.awt.Toolkit.getDefaultToolkit().beep(); } Save
Switch screen mode from portrait to landscape #
For tablet screens, you may need to switch portrait screen to landscape.1. Go to terminal and type the below command
nano /etc/X11/openbox/autostart
Add the below line just befor “java -jar /opt/Saleculator/Saleculator.jar”
xrandr --output UNKNOWN1 --rotate right
Now, save the file and exit, by pressing CTRL+X, Y, Enter.
2. Type the below command in terminal
nano /usr/share/X11/xorg.conf.d/10-evdev.conf
Add below lines under the line Identifier “evdev touchscreen catchall”
Option "SwapAxes" "1" Option "InvertY" "1"
Now, save the file and exit, by pressing CTRL+X, Y, Enter.
3. Reboot the system.
Running remote Saleculator in Windows using Putty #
Here is how to open Saleculator remotely using Putty
1. In your Windows system, install Xming. Download and install Xming from below link:
https://sourceforge.net/projects/xming/
2. Keep Xming running in Windows
3. Run Putty and on the left panel of Putty, select SSH>X11>Enable X11 forwarding option.
4. Connect Putty to the remote Saleculator using IP address or DynDns address.
5. Type the below command in Putty terminal to open Saleculator:
java -jar /opt/Saleculator/Saleculator.jar
Print total amount in words #
This script can be used to print total amount in words
Administrator Menu > Maintenance > Resources
1. In Ticket.Buttons add below line:
<event key="ticket.close" code="Amount.Letter"/>
2. Add a new resource Amount.Letter and add below code:
private static String[] _groups = { "", "Millon","Billon","Trillon"}; private static String[] _units = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"}; private static String[] _ten1 = {"", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}; private static String[] _tens = {"", "Ten", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; private static String[] _hundreds = {"", "One Hundred", "Two Hundred", "Three Hundred", "Four Hundred", "Five Hundred", "Six Hundred", "Seven Hundred" , "Eight Hundred", "Nine Hundred"}; public static String thousandText( int n ) { if (n == 0) return ""; int hundreds = n / 100; n = n % 100; int tens = n / 10; int units = n % 10; String suffix = ""; if ( tens == 0 && units != 0 ) suffix = _units[units]; if ( tens == 1 && units != 0 ) suffix = _ten1[units]; if ( tens == 2 && units != 0 ) suffix = "Twenty"+_units[units]; if ( units == 0) suffix = _tens[tens]; if ( tens > 2 && units != 0) suffix = _tens[tens] + " and " + _units[units]; if (hundreds != 1) return _hundreds[hundreds] + " " + suffix; if ( units == 0 && tens == 0) return "Hundred"; return "Hundred "+suffix; } public static String NumberToLetter( long n ){ String result = ""; int group = 0; while ( n != 0 && group < _groups.length ) { long fragment = n % 1000000; int millarAlto = (int) (fragment / 1000); int underathousand = (int) (fragment % 1000); n = n / 1000000; String groupname = _groups[group]; if (fragment > 1 && group > 0) groupname += "es"; if ((millarAlto != 0) || (underathousand != 0)) { if (millarAlto > 1) result = thousandText(millarAlto) + " thousand " + thousandText(underathousand) + " " + groupname + " " + result; if (millarAlto == 0) result = thousandText(underathousand) + " " + groupname + " "+ result; if (millarAlto == 1) result = "thousand " + thousandText(underathousand) + " " + groupname + " " + result; } group++; } return result; } number = ticket.getTotal(); number = Math.round(number*Math.pow(10,2))/Math.pow(10,2); number_whole=(int)number; number_decimal=(int)((number*100)-(number_whole*100)); value1 = NumberToLetter(number_whole); value2 = NumberToLetter(number_decimal); ticket.setProperty("amount", value1); ticket.setProperty("decimal", value2);
3. In Printer.Ticket and Printer.TicketPreview use below code to print amount in words:
<line> <text align="left">${ticket.getProperty("amount")} ${ticket.getProperty("decimal")}</text> </line> Save
GST Update for India #
Script for new GST tax implementation
Download the zip file from below link, and extract to a flash drive.
http://www.saleculator.com/download/GSTUpdate.zip
After extracting the zip file, you will get 3 script files and 1 template file.
Script 1 GST12: Restore this script if only 12% GST is applicable.
Script 2 GST18: Restore this script if only 18% GST is applicable.
Script 3 GSTBasedOnCustomer: Restore this script if both 12% and 18% GST is applicable. The tax is applied based on customer category. After restoring this script, there will be 2 customers created. Before generating receipt, choose customer GST12 to apply 12% tax and choose customer GST18 to apply 18% tax.
Template TaxPrintTemplate: Load this template section at appropriate place in Printer.Ticket and Printer.TicketPreview to print tax details in receipt.
NOTE:
Take backup before restoring the script.
Tax is applied to all the products. After restoring the script, you have to manually choose Tax Exempt for tax exempted products, if you have any.
Setup HP or Samsung Laser/Deskjet Printers #
Setup desktop printers to print receipt and reports
Follow the below steps to install printer:
1: Install printer driver
For HP Printers execute the below commands:
remountrw apt-get update apt-get install task-print-server hplip cupsctl --remote-admin hp-setup -i
Complete the wizard until printer is installed.
Note: If plugin installation is failed, specify plugin location instead of automatic downloading. Plugins for HP printers can be downloaded from below link:
https://www.openprinting.org/download/printdriver/auxfiles/HP/plugins/
For Samsung Printers execute the below commands:
remountrw apt-get update apt-get install task-print-server printer-driver-splix cupsctl --remote-admin
Now connect Saleculator to a network, and from a browser, go to 192.168.1.99:631. It should show CUPS administration page. Go to the Administration section on the page and add the printer. Choose the printer model from the available list or select the PPD file fit for the connected printer.
2. Configure printer in Saleculator:
Go to Saleculator Configuration, and under Peripherals, for Printer 1 choose “printer” instead of “epson” and select the installed printer from the drop down list. Do not select Receipt printer check box.
For reports printing, choose the installed printe from the drop down list.
Now save and restart
Setting offer to choose any 5 items for the price of 3 #
This script set sales promotions for choosing X number of items for the price of Y1. Add a new product “Choice 5” with promotional price and copy paste the below code in Properties:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="group">CHOICE5</entry> <entry key="count">5</entry> </properties>
2. For all the products allowed under this promotion, copy paste the below code in Properties:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="CHOICE5"/> </properties>
Administrator Menu > Maintenance > Resources
3. Copy paste the below code in event.addline:
if(line.getProperty("group")!=null && line.getProperty("count")!=null) { ticket.setGlobalValue("GROUP-"+line.getProperty("group")+"-"+line.getProperty("count")); } else if(ticket.getGlobalValue()!=null && ticket.getGlobalValue().contains("GROUP")) { String[] values= ticket.getGlobalValue().split("-"); if(values.length==3) { i = ticket.parseInt(values[2]); if(i>0) { if(line.getProperty(values[1])!=null) { line.setSalePrice(0); line.setProperty("product.name", "--"+line.getProperty("product.name")); i=i-1; if(i==0) { ticket.setGlobalValue(null); } else { ticket.setGlobalValue("GROUP-"+values[1]+"-"+i); } } else { JOptionPane.showMessageDialog(null, "Add "+values[2]+" more items for "+ values[1], "Error", JOptionPane.PLAIN_MESSAGE); return "cancel"; } } } } Save & restart
Buy One Get One Sale #
This code allow buy one get one discount functionality
1. Add the below property for the product that needs buy one get one discount:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="BOGO">2</entry> </properties>
Here the value of BOGO is the number of product which will be discounted. Enter 0 for no discount, 2 for buy one get one, 3 for buy two get one and so on.
Administrator Menu > Maintenance > Resources
2. Enable the event ticket.change in the resource Ticket.Buttons
3. Create a new resource event.change and add the below code:
//BOGO Functionality index = sales.getSelectedIndex(); if (index != -1) { line = ticket.getLine(index); int bogo = Integer.parseInt(line.getProperty("BOGO","0")); if (bogo > 0) { int product_count = 0; String productID = line.getProductID(); for (i = 0; i < ticket.getLinesCount(); i++) { if ((productID.equals(ticket.getLine(i).getProductID()) != null) && (Integer.parseInt(ticket.getLine(i).getProperty("BOGO","0")) > 0)) { product_count++; } } if (bogo == product_count) { sales.addItemByCode(line.printCode(),1); line = ticket.getLine(ticket.getLinesCount()-1); line.setSalePrice(0); /* Remove BOGO property to start fresh */ for (i = 0; i < ticket.getLinesCount(); i++) { if (productID.equals(ticket.getLine(i).getProductID()) != null) { ticket.getLine(i).setProperty("BOGO","0"); } } sales.setSelectedIndex(ticket.getLinesCount()-1); } } } Save & restart
Tag-Along items #
Add an item automatically to the ticket, when a primary item is selected.
Tag along items are items automatically added to the ticket when a primary item is selected. It can be a product, an additional charge or a special discount.
1. Add the below property for the product that needs tag-along item:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="tacode">123</entry> </properties>
Administrator Menu > Maintenance > Resources
2. Enable the event ticket.change in the resource Ticket.Buttons
3. Create a new resource event.change and add the below code:
This code add tag along item to the ticket:
import com.posics.pos.ticket.TicketLineInfo; index = sales.getSelectedIndex(); if (index >= 0) { line = ticket.getLine(index); if(line.getProperty("tacode")!=null) { sales.addItemByQuantity(line.getProperty("tacode"),1); sales.setSelectedIndex(index + 1); } } Save & restart
Happy hour sale #
This code implement happy hour functionality.
Administrator Menu > Maintenance > Resources
Add the below lines of code in event.addline resource.
import java.util.Calendar; Calendar cal = Calendar.getInstance(); int hour = cal.get(Calendar.HOUR_OF_DAY); //Discount discountrate = 0.2; //Happy hour range start = 12; end = 16; if (hour>=start && hour<end) { p = line.getPrice(); line.setSalePrice(p - (p*discountrate)); } Save & restart
Recover data from ibdata and .frm files #
Try the below procedure to recover data from MySQL ibdata and .frm files
1. Mount a flash drive to the crashed Saleculator and give below commands
mkdir /flash/data mkdir /flash/data/SALECULATOR cp -r /data/db/ibdata* /flash/data/ cp -r /data/db/SALECULATOR/ /flash/data/SALECULATOR/ umount /flash
2. Now mount this flash drive to a running Saleculator, and give below commands
mkdir /flash/data/SALECULATOR cp -r /flash/data/ibdata* /data/db/ cp -r /flash/data/SALECULATOR/*.frm /data/db/SALECULATOR chown -R mysql:mysql /data/db/SALECULATOR service mysql restart
Resources supporting 42 character printer #
Following are the resources modified to use with 42 character printer
Download the below file. Copy the file to a flash drive and restore in Saleculator.
http://www.saleculator.com/download/42chresources.sql
Print accounts report on every 1st of month #
This report print accounts report for previous month when closing cash on every 1st of month1.
Administrator Menu > Maintenance > Resources
Create a resource SQL.CloseCash and add the below SQL statements:
SELECT A.NAME, FORMAT(SUM(P.TOTAL) ,2) FROM PAYMENTS P JOIN RECEIPTS R JOIN ACCOUNTHEADS A ON A.ID=R.ACCOUNTHEAD AND R.ID=P.RECEIPT WHERE DATE_FORMAT(CURDATE(), "%d")=1 AND R.DATENEW>=DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 1 MONTH), "%Y-%m-01 00:00:00") AND R.DATENEW<=DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 1 MONTH), "%Y-%m-%d 23:59:59") GROUP BY P.PAYMENT;
2. Add below section in Printer.PartialCash/Printer.CloseCash/Printer.CloseCashMail
<line></line> <line> <text align ="center" length="48">ACCOUNTS REPORT OF PREVIOUS MONTH</text> </line> <line> <text align ="left" length="32">Head</text> <text align ="right" length="16">Amount</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $payments.getSQLResult().get(0)) <line> <text align ="left" length="32">${line.printValue(0)}</text> <text align ="right" length="16">${line.printValue(1)}</text> </line> #end <line> <text>------------------------------------------------</text> </line> Save & restart
Show stock of selected item or stop selling out of stock item #
This script shows stock of selected item from sales screen and stops selling out of stock item
Administrator Menu > Maintenance > Resources
Below script creates a button on sales screen to to show stock of selected item.
Add the below line Ticket.Buttons:
<button key="button.print" name="stock" code="Script.Stock" shortcut="F9"/>
Create a new resource, Script.Stock, and add the below line:
javax.swing.JOptionPane.showMessageDialog(null, ticket.getLine(sales.getSelectedIndex()).getStock());
To stop selling out of stock items, add below lines in event.addline and event.setline
if(line.getStock()<=0 || line.getStock()-line.getMultiply()<=0) { javax.swing.JOptionPane.showMessageDialog(null, "Out of Stock!"); return "Cancel"; } Save & restart
Change warehouse for current sale #
This script allow changing warehouse for current sale dynamically.
Note: This feature is available in Saleculator 3.8 u4 onwards only.
Administrator Menu > Maintenance > Resources
In Ticket.Buttons add the below lines:
<button key="WH" name="WH1" code="Script.WH1"></button> <button key="WH" name="WH2" code="Script.WH2"></button>
Create a new text resource and name it Script.WH1 and add the below line
sales.setInventoryLocation("WH1"); sales.showStatus("<html>Current Warehouse <font color=blue><font size=+2><center>WH1");
Create a new text resource and name it Script.WH2 and add the below line
sales.setInventoryLocation("WH2"); sales.showStatus("<html>Current Warehouse <font color=blue><font size=+2><center>WH2");
Add the below line in Roles
<class name="WH"/> Save & restart
Execute below SQL statements from Execute SQL window:
INSERT INTO LOCATIONS VALUES("WH1", "WAREHOUSE 1", NULL); INSERT INTO LOCATIONS VALUES("WH2", "WAREHOUSE 2", NULL);
Disable Saleculator screen turning blank due to inactivity #
Screen may go blank after a few minutes of inactivity. Setting these values will disable this behaviour.
Go to Saleculator command shell (Ctrl+Alt+F1).
nano /etc/X11/openbox/autostart
Add the below values at the bottom of the file.
xset s off xset -dpms xset s noblank
Now save and exit.
Reboot the system to take the changes effect.
Fix issue of monitor turning blank while Saleculator loading #
Monitor might turn blank during Saleculator loading due to graphics card issue
First boot using Clonezilla usb drive and login to command shell. Then issue the below commands:
sudo -s mount -t auto /dev/mmcblk0p2 /mnt nano /mnt/etc/default/grub --Change splash to nomodeset, save and exit mount --bind /dev /mnt/dev mount --bind /sys /mnt/sys mount --bind /proc /mnt/proc chroot /mnt update-grub
Now remove usb drive and reboot.
If there is only issue in displaying splash, follow below steps:
nano /etc/initramfs-tools/conf.d/splash
Add below line into the file:
echo FRAMEBUFFER=y
Save the file and exit. Then issue below command:
update-initramfs -u
Now reboot the system.
Solving common disk errors #
Any of these problems can be solved by following the given procedure
It is always good to copy db folder before doing any disk error fixing.
First boot using Clonezilla bootable usb drive and login to the command shell (Ctrl+Alt+F1).
1. Solving bad sector error
sudo -s fsck.ext4 -y /dev/sda or fsck.ext4 -y /dev/mmcblk0
2. Fill disk with zeros to reset all data from disk
sudo -s dd if=/dev/zero of=/dev/mmcblk0 or dd if=/dev/zero of=/dev/sda
3. Fix corrupted superblock:
sudo -s fsck.ext4 /dev/mmcblk0p1 or fsck.ext4 /dev/sda
4. Fix mmc failure during booting. This has to be done from Saleculator command shell.
echo "options sdhci debug_quirks=0x40" >> /etc/modprobe.d/sdhci-pci.conf reboot
IMPORTANT! Close cash report changed in version 3.8 U2 onwards #
The way close cash report works has been changed. Please make these changes for getting close cash report work.
To improve close cash performance, it has been made to load only required reports on close cash. Please make this change when upgrading to 3.8 U2.
Administrator Menu > Maintenance > Resources
Create a new resource CloseCash.Reports and add below lines:
SALES_BY_ATTRIBUTE; SALES_BY_PROPERTY; SALES_BY_USER; PAYMENTS_CARD; PAYMENTS_CHEQUE; PAYMENTS_CURRENCY; PAYMENTS_CUSTOMER; PAYMENTS_VOUCHER; REMOVED_LINES; SALES_RETURNS; SALES_PRODUCTS; SALES_RECEIPTS; SALES_DELIVERY; STOCK_DIARY;
Here each line represent a report, for which data is populated when loading close cash screen. You can increase close cash performance by removing the lines corresponding to the reports which are not used in close cash report.
Adding new reports in Close Cash report #
New report sections can be added in close cash report
Note: New reports in close cash report feature is available in Saleculator 3.8 u2 onwards only.
Using SQL statement, new reports can be added to close cash report. This example add 2 reports in close cash report. One for current stock and another for a list of top sold 10 items for the current sequence.
Note that each SQL statement has to be separated by a semicolon(;).
If you want to generate a report for current sequence, use a question mark(?) on an appropriate database field.
Result of each SQL statement is accessed by the method $payments.getSQLResult().get(x), giving its sequential number as x as given in SQL.CloseCash. Value of each field is accessed by the method ${line.printValue(x)}, giving its sequential number as x as given in SQL statment.
Administrator Menu > Maintenance > Resources
1. Create a new resource SQL.CloseCash and add the below SQL statements:
SELECT P.NAME, SUM(S.UNITS) FROM STOCKCURRENT S JOIN PRODUCTS P ON S.PRODUCT=P.ID GROUP BY S.PRODUCT ORDER BY NAME; SELECT P.NAME, SUM(SD.UNITS) AS UNITS, FORMAT(SUM(SD.UNITS*PRICE),2) AS TOTAL FROM STOCKDIARY SD JOIN CLOSEDCASH ON CLOSEDCASH.MONEY = ? JOIN PRODUCTS P ON SD.PRODUCT=P.ID WHERE SD.REASON="-1" AND SD.DATENEW >=CLOSEDCASH.DATESTART AND IF(CLOSEDCASH.DATEEND IS NULL, 1, SD.DATENEW <=CLOSEDCASH.DATEEND) GROUP BY SD.PRODUCT ORDER BY UNITS, TOTAL LIMIT 10;
2. Add the below 2 sections in Printer.PartialCash/Printer.CloseCash/Printer.CloseCashMail
<line></line> <line> <text align ="center" length="48">CURRENT STOCK</text> </line> <line> <text align ="left" length="32">Name</text> <text align ="right" length="16">Units</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $payments.getSQLResult().get(0)) <line> <text align ="left" length="32">${line.printValue(0)}</text> <text align ="right" length="16">${line.printValue(1)}</text> </line> #end <line> <text>------------------------------------------------</text> </line>
<line></line> <line> <text align ="center" length="48">TOP 10 PRODUCTS</text> </line> <line> <text align ="left" length="25">Name</text> <text align ="right" length="8">Units</text> <text align ="right" length="15">Total</text> </line> <line> <text>------------------------------------------------</text> </line> #foreach ($line in $payments.getSQLResult().get(1)) <line> <text align ="left" length="25">${line.printValue(0)}</text> <text align ="right" length="8">${line.printValue(1)}</text> <text align ="right" length="15">${line.printValue(2)}</text> </line> #end <line> <text>------------------------------------------------</text> </line> Save & restart
Accepting advance payment #
Advance payment from customer can be accepted and later used for bill payment.
Note: Advance payment support is available in Saleculator 3.8 u1 Saleculator PDA 1 u16 onwards only.
1. Add below line in roles:
<class name="payment.advance"/> Administrator Menu > Maintenance > Resources 2. Add below line in payment.receipt.tabs:
payment.addPayment("Advance", "payment.icon.debt", "advance");
3. Add below line inside the payments section in Printer.Ticket and Printer.TicketPreview:
#if ($paymentline.name == "advance") <line> <text bold="true">Advance</text> </line> <line> <text align="right" length="48">$paymentline.printTotal()</text> </line> #end
Stock movement in close cash report #
Use this code to print stock movement in close cash report
Note: Stock movement report is available in Saleculator 3.8u1 onwards only.
Administrator Menu > Maintenance > Resources Add the below template into close cash reports:
<!-- STOCK REPORT START --> <line> <text bold="true">Stock Report</text> </line> <line> <text align ="left" length="18">Name</text> <text align ="right" length="6">In</text> <text align ="right" length="6">Out</text> <text align ="right" length="6">Bal</text> <text align ="right" length="12">Value</text> </line> <line> <text>------------------------------------------------</text> </line> #set($cat = "") #foreach ($line in $payments.getProductStockLines()) #if ( $cat != ${line.printCategoryName()} ) #set( $cat = ${line.printCategoryName()} ) <line></line> <line> <text align ="left" length="48">${line.printCategoryName()}</text> </line> #end <line> <text align ="left" length="18">${line.printProductName()}</text> <text align ="right" length="6">${line.printStockIn()}</text> <text align ="right" length="6">${line.printStockOut()}</text> <text align ="right" length="6">${line.printCurrentStock()}</text> <text align ="right" length="12">${line.printStockValue()}</text> </line> #end <line> <text>------------------------------------------------</text> </line> <!-- STOCK REPORT END --> Save & restart
Persistent names for usb and serial devices #
Persistent names can be set for printers and similar devices
Connect the device and from Saleculator shell, give the below command:
usb-devices
Not down the value of SerialNumber. If the above command not working, use below command:
udevadm info -a -p$(sudo udevadm info -q path -n /dev/usb/lp0)
Replace /dev/usb/lp0 to the desired device name you want to set a persistent name.
From the output of the command, note down an attribute which is unique for the device (i.e. ATTRS{serial}==”xxxxxxxxxxxxxx”).
Now give the below command:
nano /etc/udev/rules.d/99-printer.rules
Add the below line to this file:
ACTION=="add", ATTRS{serial}=="xxxxxxxxxxxxxx", SYMLINK+="ticket"
Replace “ticket” with your desired device name.
Now give the below command to apply the changes:
/etc/init.d/udev restart
Unplug and plug back the device and check the fixed device name created
ls -al /dev/ticket
Leave a Reply