SQL-Ledger can be extended with external custom_{module}.pl scripts and with external private {login}_{module}.pl scripts.
Global scripts apply to every login, whereas {login}_{module}.pl scripts apply to one login only. For instance, if the login is 'joe' you can add a script 'joe_ar.pl' in the bin/{terminal} directory to provide a customized version for joe. So, whenever joe logs in he sees his customized version while the other users work with the stock version.
External code is pulled into the core only if it compiles cleanly. If it fails to compile you are informed about the error.
Code example to customize the footer for the AR module
add a file custom_ar.pl in bin/mozilla.
likewise if you want to have one for lynx, add
the file in bin/lynx.
# customized AR # customized form footer without the "Delete" button # check for ID, if present, you cannot post 1; # end of main sub form_footer { print qq| <input name=callback type=hidden value="$form->{callback}"> <input type=hidden name=path value=$form->{path}> <input type=hidden name=login value=$form->{login}> <input type=hidden name=password value=$form->{password}> </table> <br> <input class=submit type=submit name=action value="| .$locale->text('Update Form').qq|">|; # only show the post button if this is a new transaction # $form->{id} is only set for existing transactions if (!$form->{id}) { print qq|<input class=submit type=submit name=action value="| .$locale->text('Post Transaction').qq|">|; } print qq|</form> </body> </html> |; } # end of file
You can add, replace any function in the system this way.
IMPORTANT! If you use a foreign language follow the programming style and use $locale->text('string') instead of hardcoding strings. When you are done with your code run ./locales.pl from the appropriate locale/{countrycode} directory. This will parse your code and build the translation strings and crossreferences for function calls. If you do not run locales.pl you'll probably end up with error messages informing you to make an entry for the missing subroutine in the translation file in the self{subs} section.
Menus can also be customized globally or per login. To add a global customized menu add the file 'custom_menu.ini' in the root directory.
To customize menus per login add a '{login}_menu.ini' file in the root directory.
This is also a great way of building dynamic content from some other source or from within.
Menu entries are organized into section entries.
Here is an example of a menu file. It is called demo_menu.ini and runs on the Edmonton demo. Whenever the user demo logs on, this menu is loaded in addition to the core menu.
[ ] module=NULL [Miscellaneous] [Miscellaneous--FAQ] module=NULL href=doc/faq.html [Miscellaneous--Bug Report] module=NULL href=mailto:bugtrack@sql-ledger.org? subject=SQL-Ledger Bug Report [Miscellaneous--Lookup Exchange Rate] module=NULL href=http://www.oanda.com target=_new [Miscellaneous--Commercial Support] module=NULL href=http://abacus.sql-ledger.com/sql-ledger/login.pl?login=order [Miscellaneous--Subscribe to Mailing List] module=NULL href=http://www.sql-ledger.org/misc/mailinglist.html
In addition to custom scripts you can also setup new modules by simply creating a symlink in the root directory to am.pl and creating a library file with the same name in the bin/{terminal} directory. The general programming scheme is module.pl in the appropriate terminal directory (i.e bin/mozilla) for the frontend code and MODULE.pm in the SL directory.
Example setup for a timetool module. ln -s tt.pl am.pl create tt.pl in bin/mozilla and add your frontend code create TT.pm in SL and add the backend code
Every user can have a different stylesheet. You can set the stylesheet in your "Preferences" screen.
SQL-Ledger can also be accessed from the command line by passing all the variables to the perl script. The variable=value pairs must be separated by an ampersand.
i.e to display the search screen from the ct module. (this is the module for processing data for customers and vendors)
cd /usr/local/sql-ledger ./ct.pl "login=name&path;=bin/mozilla&password;=xxxxx&action;=search&db;=customer" password: use the encrypted password from the members file
This displays the search screen for customers on screen.
You can send the output to another application, convert to some other format or send it to a printer.
Scheduled transactions, like sending out monthly invoices, can be produced with a cronjob the same way. Or to import data send to the save (post) functions.
i.e to import a customer
Names of variables are identical to the field names in the tables../ct.pl "login=handle&path;=bin/mozilla&password;=xxxxx&action;=save_customer &name;=this is a new name&contact;=my contact" The variable string between the double quotes must be one line! It is shown here in two lines for clarity.
Do not pass the ID, it is generated by the SQL server. The ID is a unique integer to differentiate tuples.
Some function calls require a distinct variable to be passed, like db=
Functions are generally named like this
add edit save delete form_header form_footer update_form ...........
SQL-Ledger can easily be adapted for batching transactions to and from stand-alone POS terminals or off-line systems. The backend office can be synchronized on an as needed basies. The stand-alone application can simply write the transactions to a file which are then uploaded to the backend office. Inventory can be exported to a format readable by the POS software so that each terminal has current pricing information. Because there are no restrictions in which order transactions must be posted you can synchronize a backoffice from many terminals at any time.
This procedure is typically used in Franchise operations or remote operations where it is not feasable to have a direct link to the backoffice software.
The same concept as for the console interface can be used with some additional functions to generate an inventory listing with raw data instead of the html formatted lists.