Saturday, November 16, 2013

Timing your PHP Code in BlueBox

If you think a piece of PHP code is inefficient but don't know where, there is a BlueBox function that can give you time-splits as the code progresses.

bb_timer([optional __LINE__ number],[optional return_value]);

The simplest use would be bb_timer(__LINE__); which will print to the screen the time taken to get to that specific line of code.

If you would rather have the value returned then enter a 'true' value into the second value.

Thursday, October 24, 2013

Including Sales Orders and Purchase Orders in Stock Returns

BlueBox2.0 has an automated stock returns module which allows you to return stock to a supplier via the GRN which received the stock, or to return stock from a customer via the Despatch Note that shipped the stock.

Recently added has been the ability to do that one document further up the chain, namely via the Purchase Order or via the Sales Order. These 2 new additions, complete with 'quick action' buttons in the views of each document type, are a logical starting point when wanting to process a supplier or customer return, and will make the returns process even easier to handle.

The new quick link on the Purchase Order view screen.
The new quick link on the Sales Order view screen.

Tuesday, October 22, 2013

BlueBox Despatch Notes - Including Backorder Status

Despatch Notes in BlueBox2.0 have been upgraded to include backorder status of items relating to the parent Sales Order if one exists. The Despatch Note has also had all financial info removed from it, and purely relates to item and qty despatched.

Note: if you want to access the financial view of the despatch note (ie the old view) you can still do so by using the special view in the Output menu.

Tuesday, October 1, 2013

BlueBox General Ledger Document Map Conditions

The GL in BlueBox is driven by  set of document maps. These are essentially a set of GL account instructions which tell the GL which account to credit or debit for each document in the document layer of BlueBox. 

So, for example, the document map for 'Creditors Invoices' tells the GL to credit the Liabilities account called 'Accounts Payable' and to debit the Expense account called 'Cost of Sales'. It also includes a 3rd instruction for the VAT/Tax account. The sum of all 3 'movements' balances the double entry for each line in the document being processed.

There are times when you may want a different set of movements depending on what has been entered into the document. For example, you may want to debit or credit a different account depending on which business unit the document was captured in.

Document and line conditions are the way to achieve this. These conditions are evaluated for each document map and, as their names suggest, are evaluated at 'header' or 'document' level, or at 'line' level.

The most basic way of entering a condition is to simply include the field name that you are evaluating. This implies that if that variable exists in the data being posted it will be seen as applicable.

Most likely though, will be the case where you require an evaluation of the value being passed through a field, and for this we need a bit more syntax.

The correct syntax for evaluated conditions is:

eval:$conf[fields][SESSION_business_unitISbb_business_unitsID]==2

Note the eval: which triggers the evaluation, and the double =='s which are programatical for ='s
In this case you would replace the 2 with the ID you required.

Also: Doc Maps require that ALL entries for that specific doc type need a condition if any of them have one... this way it eliminates which ones to ignore, so for the 'general one' you will need a condition like this:

eval:!in_array($conf[fields][SESSION_business_unitISbb_business_unitsID],array(2,4,6)) 

Note: it starts with a ! which means 'not' and the list of ID's mentioned in the other lines needs to be comma separated in the array at the end.

Friday, September 20, 2013

Searching All Documents in BlueBox

BlueBox2.0 has recently had an upgrade in the form of 2 search facilities which cover all financial documents in the system.

The first is the new bb_userdocs module which lists all the documents in the system linked to a particular user. This new module can be accessed via Admin > Users > Userdocs or you can access it via a quick link when doing a 'find a person' lookup:


The second is a new quick document lookup added to the old 'find a person' and 'find an item' area:


This searches document number and total amount, and will only take a numeric input. It then lists all the matching documents across all Debtor and Creditor financial documents.

Tuesday, September 10, 2013

Auto Generated Codes for Users etc in BlueBox

In BlueBox2.0 we have a bbsetting called bbsetting_autogen_alphanum_fields which allows you to define the auto-generation of 'code' fields for data that is added to a module.

A typical application of this would be the bb_users table where the 'code' field may need to be autogenerated. If this is the case, then using module settings (data-functions>module settings in the desired module), set bbsetting_autogen_alphanum_fields as follows.

A comma separated list of field names and their desired prefixes:

{field_name}={prefix},{second_field_name}={prefix} etc

If you require the prefix to be auto-created from data that is submitted, then use square brackets with the field/s required separated by |'s pipes).

So, a real-world example would be, to set the 'code' field in the bb_users table to use the company name or the last name (if company name is not entered)

code=[company_name|last_name],

Saturday, September 7, 2013

Getting the latest currency values for despatch/invoice when using forex

BlueBox2.0 is a multi-currency platform, and uses a strict parent-to-child value transfer when migrating data from document to document. This is handy in most instances, but can cause come discrepancy when the document is captured in a forex currency.

If the time difference between the date a Sales Order is captured varies significantly from the date the subsequent Despatch or Invoice are generated you can find that the forex variation is great. The 'spot rate' is stored in the original Sales Order and is then copied onto the downline documents (Despatch/Invoice) causing a widening forex difference if the IMF sport rate changed between the dates of the documents.

To get around this we have introduced a new bbsetting called bbsetting_force_latest_forex_currency_when_copying_from_parent which, when set on a module like bb_sales_despatch_notes and/or bb_sales_debtors_invoices will force the system to check the date and value of the most recent currency entries and warn the user if the currency table is out of date. 

It then also forces the latest currency value into the 'forward rate' box, thereby retaining the original 'spot rate' captured in the Sales Order and overriding this with the latest rate as the 'forward rate'.

Though this is not strictly a 'forward rate' it does the job perfectly. Obviously if a forward rate were set in the Sales Order originally then this override would not kick in as it would not be required.

Auto allocation of Sales Order Items via Replenishment (MRP) Module

In BlueBox2.0 we recently made some amendments to the way SO's link automatically via the POs generated by the Replenishment/MRP report. 
  • SO auto-allocation is switched on using the 'attempt to auto allocate' switch in the filter - the wording is important here as this is an 'approximate method' - the system tries to find the list of hungry SO items and marry then to the items ordered, however, there are many outside factors that can affect this (ie if the items are ordered manually outside of this process) - so it remains an 'attempt'.
  • If this switch is ON, the system builds a list of hungry SO items and counts their total. It then checks to see that the amount to order (ie the input QTY on each line) is more than or equal to this qty.
  • If the qty to order is sufficient, an icon shows with a page stack which indicates that the auto-allocation is ON for that line. Clicking on the page stack shows all the SOs and what is being allocated for each one.
  • If the qty to order is not enough to supply the hungry SOs the icon changes to an 'alert' and the auto-allocation will be 'disabled' for that line. Clicking on the icon will show the qty required for this to be changed to a 'page stack' and if the qty to order is manually adjusted to this qty the icon will change and the auto-allocation will be switched on.
  • If 'no icon' is showing next to the SO backorder qty, this indicates that there were no hungry SOs found for that line (or the new setting in the filter has not been switched on);.

Tuesday, September 3, 2013

Bulk Allocation for Sales Order Items - Now Specific

A powerful feature in BlueBox2.0 has always been the bulk-allocation of stock to Sales Orders where they are short of stock. A nifty new add-on in the Item Data View makes this more specific - allowing you to 'Bulk Allocate' only that specific item:


Friday, August 9, 2013

Update Customer Order Number in Debtors Invoices

BlueBox ERP now includes a feature which allows you to updated the customer order number on debtor's invoices.

As expected from a formal ERP system, you cannot edit invoices - and as was recently raised by a customer, often the order number arrives after the invoice has been generated.

To update this info on the invoice simply edit the linked sales order and set the customer order number. Then view the debtor's invoice and click 'update values'. Where this function normally only updated the financial values on the document with relation to it's up line and down line documents, it now looks through the despatch note to the linked sales order, and if a customer order number exists will now stamp this on the invoice.

Thursday, August 8, 2013

BlueBox Web Stores with Responsive Design

Bluebox includes a nifty backoffice web-store publishing engine which allows you to split your inventory catalogue between different key customers and then give them access to their own private web ordering micro-site.

These micro-sites work out-the-box with BlueBox and are hosted on the same system/server as the backoffice system.

These sites are mobile-responsive, meaning that they re-shape themselves to fit mobile devices. They can also very easily be wrapped into mobile apps for all platforms, something we do via PhoneGap.

Each micro-site can have it's own web-address, or can be accessed via a unique key for security reasons. Alternatively you can place all your micro-sites on a front page menu and have your customers choose which site to access.

Link each site to a backoffice customer and you'll find that the system automatically creates the Sales Orders for you, handles the stock allocation and procurement and finishes off the process by despatching and invoicing the customer.

This accommodates 2 models - where the 'house account' pays for all the orders via our backoffice accounts system, or where the shopper pays via card at time of purchase. Using these 2 models we are able to provide the infrastructure for centralised headoffice ordering schemes where branches order their items individually but the bill is sent to headoffice, or where the bill is sent to the branch, or where the branch pays with a card at the time of purchase.



Friendly Naming for PDFs

BlueBox PDF's have always been named with the date/time stamp at the time of creation.

Today, happily, this has changed to incorporate the short-name of the document type, the customer company name and the document number. Much easier to read and recognise.

Tuesday, July 23, 2013

Supplier Pre-Defined Delivery Charges

In BlueBox each supplier is entered as a 'standard user' and then by adding them to the 'Creditors' user group they become enabled as a 'supplier' in the procurement module/s of the system.

Newly added fields in the bb_users table relating to suppliers and delivery charges are:

'delivery method' now with an additional field 'delivery method cost'

'delivery method two' also with its cost field 'delivery method two cost'

and finally 'free delivery over value'.

These new fields will help in defining the procurement relationship with the supplier, and the following rules apply to Purchase Orders only. Essentially what they are doing is determining if an automatic delivery charge should be applied to all PO's for this specific supplier. If either of the 'cost' values are entered, and a new PO is created with a corresponding delivery method, then the system will take that as an instruction to automatically add a delivery charge to the PO for the specified value (ex VAT).

If there is a 'free delivery over value' setting for that supplier, and the PO's grand total (inc VAT) is greater than the amount specified, then a zero-charge delivery item is added, indicating that there is no delivery to be charged for the order.

Lastly, if a delivery related item was added to the order manually, determined by the item_data name containing the words 'delivery', 'freight' or 'postage' then this process is skipped altogether, assumning that delivery has already been accounted for on the order.

Tuesday, July 9, 2013

New Ajax Lookup Feature for Creditor Invoice Numbers

Similar to the previous post, BlueBox now includes a Creditors Invoice Number validator which checks to see if the number entered has been used for that creditor previously.

If no supplier/creditor is entered in the form then this feature will not run. If one has been entere it will verify the uniqueness of the number entered and come back with a positive or negative message.

New Ajax Lookup Feature for SKU Codes

Maintaining a unique alphanumeric SKU code sequence is a bit of a pain. BlueBox now includes an automated alphanumeric SKU sequencer:

This new feature appears in the bb_item_data and bb_item_data_options menu.
It checks the sequence you have entered and strips out the numeric portion, looking for the next highest number to suggest. If no numbers exist for that alpha-prefix then it starts at 0001.

Sunday, June 23, 2013

Setting up your BlueBox2.0 ePOS as a Customer Survey Kiosk

BlueBox ePOS terminals have a setting called Kiosk-mode which allows a touch-screen PC to be set up as a customer survey kiosk with touch screen keyboard.

Benefiting from offline/online syncronisation technology, this feature will work offline all day and then sync the survey results when it gets a connection.

The purpose of this survey kiosk mode is to capture customer feedback on a few questions, capture their basic contact details and then to issue an optional voucher code so that can benefit from providing you with the information.

To set up your BlueBox ePOS as a kiosk follow these steps:

1) Set up a dedicated ePOS till and set the following settings:

  • Upload an image for the background (suggest 1024 x 768 px) - remember to leave a patch in the middle blank/tinted for the text to display on top of. A block 724px wide and 350px tall positioned at 150px left and 120px down from the top left corner, is optimal.
  • Add your survey questions - these are formatted as follows:

    This is a question?Answer One|Answer Two|Answer 3;

    The question must end in a ? and the answers must be separated with |'s, finally end the question with a semicolon.
  • Add some 'end text' for the survey - this will display to the customer once they complete the survey.
  • If you want the survey to send a text/sms message to the customer on completion enter the message you want sent. You can use the tag {vouchercode} if you want to include their unique discount voucher code in the message.
  • If you want the survey to send an email message to the customer on completion enter the subject and email message you want sent. You can use the tag {vouchercode} if you want to include their unique discount voucher code in the message.
2) If you are sending sms/text messages, remember to set the bbsettings for sending text messages in the admin > modules > module settings section. For the Gateway, you have a choice of clickatell.com (SA, UK and Global), txtlocal.com (UK and Global), logicsms.co.za, strikemedia.co.za and bulksms.2way.co.za.
  •  
3) If you intend issuing discount vouchers with unique voucher codes, you will need to add a voucher to the ePOS 'Discount Vouchers' module. Go to sales > point of sale > discount vouchers and add a new voucher. The only pre-requisite here is that the voucher name must have the word 'kiosk' in it:


 4) Open up the ePOS till and ensure that the latest till settings have been syncronised with the offline database. If you are unsure, click on extra > system > Delete Local Data and Refresh.

  •  
5) Once you are sure the till settings have been syncronised, click on extra > system Kiosk Mode to switch to the Kiosk. You will see the following screens (with your own background image and survey questions):
  •  
 6) Test the settings by clicking on the various answers, entering test user details and check that you receive the sms/test message and/or the email.

7) You can switch back to the 'main' ePOS screen by clicking on a hidden 'button' in the bottom right corner of the kiosk screen:
8) You can see the status of your captured surveys by clicking on the 'All Sales' button. Each survey is sent to the server as a 'zero value' sale. The customer details and survey answers are sent along with it as notes for analysis later on.

Thursday, June 20, 2013

Extending User Login Period per User

Up until now, BlueBox2.0 has had a user-session length control in the configuration file. This applied to all users of the system. If left at zero it would mean that a user's session would never expire and if set to a number, that would represent the number of minutes that a session would last for.

Now there is a field in the bb_user table called session_force_timeout_minutesNUM which allows you to set the session-life per user. Once set, on next login the specific user will have a forced logout after the number of minutes specified.

A handy implementation of this would be to add the following checkbox to the standard login form -

<input type=checkbox name=global[fields][session_force_timeout_minutesNUM] value=3>


This would instruct the security wrapper to updated the account with the specified number of minutes if the box was checked.

Overriding Ability to Change Price, Qty and Discount in BB2.0 Forms

In BlueBox2.0, we have a 6 settings at item_data level which control whether their item price/qty/discount can be edited in forms. This protects the buying or selling price of an item, as well as stopping staff from discounting items that they shouldn't or changing the tax/vat codes on items that they shouldn't.

Up until now this setting has been global and no user was able to get around these controls if they were set. Now we have a new permission at bb_sales and bb_procurement level which allows this to be bypassed.

Simply setting a user with the permissions bb_sales-can_change_form_prices_qty_and_discount or bb_procurement-can_change_form_prices_qty_and_discount will then allow them to edit these fields where others cannot.

Note that any users who currently have bb_sales-all/admin and bb_procurement-all/admin will also inherit this new ability.

Tuesday, June 18, 2013

Multiple Delivery Addresses in BlueBox

BlueBox2.0 now accommodates multiple delivery addresses via the bb_users module.

When viewing a user you will notice at the bottom of the plugins that there is a plugin called 'User Delivery Addresses and Contacts'. This is intended to be an area where unlimited additional addresses and contact details for this user can be stored.

It's immediate implication in the system is that for Sales Orders and Despatch Notes, if the selected customer file has multiple delivery addresses, they will appear via an ajax insertion just above the manual entry area for 'delivery address' and will allow the author to select any address as required which will be populated into the free-text area in the form.

Sunday, June 9, 2013

Introduction of Multiple Base Currencies in BlueBox

One of the strengths of BlueBox is it's multi-business-unit, mult-location, multi-tax, multi-currency nature. This powerful matrix makes allows us to create extremely flexible, scalable business structures on one database.

One of the historical issues or limitations has been that the currencies table has been a global feature, limiting the entire system for a certain groups of companies to a single base currency. This has now been improved to allow the setting of base/currency values at each BU/Location level. Essentially, this means that you can have a different currency table for each business/country of operation.

This has one key limitation. That is the fact that there is no 'super base' currency sitting at 'group/global' level. Any financial reporting higher than any 'currency point' in the BU/Location matrix will be useless, as it will combine base numeric values that span multiple base-currencies, thereby blurring the various values together and making the totals useless.

This should not detract from the newly found capacity that BlueBox has to allow regions to transact in any number of currencies, and now, to be able to store their base-transactions in the currency of their choice.

For older systems, the currency table will continue to operate as before (essentially at global/global level). But for new installs, there is now this option to set the currency table at various BU/Locations under global, as long as no currency table then exists above these points.


Friday, May 31, 2013

Time for lighter documents

A while ago I blogged about the introduction of font-reducing CSS to standard BlueBox documents.

The purpose of this was to force certain docs, via the Database Templates Module, to show their font at a reduced size and in a lighter font. This was suggested as a manual intervention at the time.

I have decided to make this standard on Sales Orders, Debtors Invoices and StockTake Sheets, for now. This will be added to more documents as they need it over the next few months. If Database Templates already exist for these modules then there will not be any change, but any updates on sites which do not have override templates in place will notice this improvement automatically.

Essentially the change involves wrapping the document print template with this html:

Notice the addition of class=tbl to the table tag as well.

<style>
.tbl table{
   font-family:sans-serif;
   font-size:8pt;
}
.tbl tr{
   font-family:sans-serif;
   font-size:8pt;
}
.tbl tr td{
   font-family:sans-serif;
   font-size:8pt;
}
.tbl td{
   font-family:sans-serif;
   font-size:8pt;
}
</style>
<div style="font-family:Arial,sans-serif;font-size:9pt;">

<!-- old template starts here -->
<!--:template:letterhead_one:-->

<table width=100% bgcolor=(#COLOR2#) cellspacing=1 cellpadding=3 class=tbl>

<!-- old template ends here -->
</div>

Wednesday, May 22, 2013

Sales Orders and Automated Lead Times

Recently added to BlueBox 2.0 a new setting at Sales Order Category level whereby the number of days lead-time for the delivery of the SO can be auto-set.

If you edit the Sales Order Category, you will see a new field called 'Default Lead Time Days' - this number will be added to today's date to determine the ship-date for the associated Sales Order.

A small routine then determines if the ship-date falls on a Saturday or Sunday, or if bank/public holidays are set in the calendar (Publishing->CMS->Public Holidays) these are avoided too.

If a ship-date is manually set when adding the Sales Order this automated process is skipped.

Friday, May 17, 2013

Password Reset Request Tokens

Just a small bit of code to explain the use of password reset request tokens.

If a user forgets their password there are numerous methods of helping them.

I suggest using bb_users_passwd_reset_request_tokens as this method allows the user to verify their reset before actually triggering it.

The approach would be something like this:

if($global[reset_password]){
                $u=new bb_users();
                $u=$u->get(array("where"=>"

                             name=".sqlstr($global[reset_password])." OR email=".sqlstr($global[reset_password])."
                             "));
                if($u){


                    $new_token=new bb_users_passwd_reset_request_tokens();
                    $new_token=$new_token->add(array(

                         "do_not_redirect"=>"true",
                         "this_class"=>"bb_users_passwd_reset_request_tokens",
                         "fields"=>array("userISbb_usersID"=>$u[_id])));

                    $reload_token=new bb_users_passwd_reset_request_tokens();
                    $reload_token=$reload_token->get(array("_id"=>$new_token[_id]));


                    bb_sendmail(array("subject"=>"Your Password Reset Token - ".date("YmdHis"),
                        "from"=>"some@email.com",
                        "to"=>$u[email],
                        "body"=>
                        "
                        <html>
                        <head>
                        </head>
                        <body>
                        <table align=center width=640>
                        <tr>
                        <td align=left>
                        Dear ".$u[first_name].",<br>
                        <br>
                        You have requested a password reset token.<br>
                        <br>
                        Click on this link to reset your password:<br>
                        <br>
                        http://".$_SERVER[HTTP_HOST]."/?somepage&global[pwrs]=$reload_token[_apikey]
                        <br>
                        <br>
                        from<br>
                        Support
                        </td>
                        </tr>
                        </table>
                        </body>
                        </html>
                        "));

                }else{
                   //error no user found for email
                }
            }


Then, the link they click on will trigger:


if($global[pwrs]){
                $reload_token=new bb_users_passwd_reset_request_tokens();
                $reload_token=$reload_token->get(array("_apikey"=>$global[pwrs]));
                if($reload_token){
                    $u=new bb_users();
                    $u=$u->get(array("_id"=>$reload_token[userISbb_usersID]));
                    if($u){


                        $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
                        $pass = array(); //remember to declare $pass as an array
                        $alphaLength = strlen($alphabet) - 1;
                        for ($i = 0; $i < 8; $i++) {
                            $n = rand(0, $alphaLength);
                            $pass[] = $alphabet[$n];
                        }
                        $pwd= implode($pass);


                        $update_password=new bb_users();
                        $update_password=$update_password->edit(array(

                              "do_not_redirect"=>"true",
                              "this_class"=>"bb_users",
                              "fields"=>array("_id"=>$u[_id],"password"=>$pwd,"password_reminder"=>"set_by_password_reset")));

                        bb_sendmail(array("subject"=>"Your New Password - ".date("YmdHis"),
                            "from"=>"support@domain.com",
                            "to"=>$u[email],
                            "body"=>
                            "
                            <html>
                            <head>
                            </head>
                            <body>
                            <table align=center width=640>
                            <tr>
                            <td align=left>
                            Dear ".$u[first_name].",<br>
                            <br>
                            You have requested a password reset.<br>
                            <br>
                            Your new password is $pwd
                            <br><br>
                            Please be sure to change this to something secure, which you will remember, when you log in next.
                            <br>
                            from<br>

                            Support
                            </td>
                            </tr>
                            </table>
                            </body>
                            </html>
                            "));
                    }
                }else{
                    //error: token failed
                }
            }

Friday, April 26, 2013

New BlueBox2.0 Accounts Summary Widget

There is a new widget which you can install into your BlueBox2.0 dashboard which allows you to view a summary of your accounts - specifically your debtors and creditors.

The tag to use in the Home Boxes module is

<!--:class:bb_finance:accounts_summary_widget:-->

This produces a widget with your current debtors (accounts receivable) total, as well as a graph of the debtors ageing totals at current, 30 days, 60 days, 120 days etc. Finally it also produces a list of the 10 biggest current debtors with links to their accounts.

The same is produced for the creditors.

Monday, April 8, 2013

New BlueBox2.0 Form Builder

The new BlueBox2.0 Form Builder allows you to select which fields to include in the standard forms for each BB2.0 module in your system. To access it go to Admin > Modules > Form Builder.

The interface starts with a module selector, and once you have selected the module you want to create a form for you are presented with the option of editing an existing form for that module, or creating a new one:
When adding or editing a new form you are able to select whether it only applies to a certain group, or if it applies to all users who do not have 'admin' permissions for the selected module. This feature determines whether your new form will be used when the system tries to show the 'standard' add/edit form for the module, so if either of these are selected it will attempt to show the new form if the user qualifies for either 'group' or 'non admin' status as selected.
Lastly, you need to select which fields are to be shown in your new form.

This is the first version of this new module, and it will soon be updated to include these additional features:
  • selection of 'linked' data to be included in the form (ie user group, or item category etc)
  • form layout via drag-n-drop
  • setting form field titles and tooltip help boxes

Wednesday, March 27, 2013

How BlueBox meets the needs of the Retail Sector

ABOUT THE BLUEBOX
The BlueBox has been providing ePOS, inventory, logistics and procurement software solutions since 1996. Our strengths are the flexibility of our platform combined with our ability to fit it to the bespoke requirements of our customers quickly and affordably. We charge a single monthly fee per store (from £50 per month) which includes unlimited tills, software upgrades and free support via our UK support team.

POWER OF THE CLOUD COMBINED WITH OFFLINE ACCESS
Our systems are next-generation, 100% web/cloud based. No software installation is required and your data is live and central at all times. Our ePOS module works online and offline ensuring you don’t have any downtime.

SIZES, OPTIONS AND STYLES
We have been working in the garment retail sector for over 8 years and our system features powerful size/colour/style options. Our retail reporting includes automated replenishment and supplier/item league tables which keep you informed about winners and losers in your catalogue.

INTEGRATED LOYALTY SYSTEM
We have a powerful integrated Loyalty System which issues reward vouchers and points automatically and offers online self-help services to your members. Our Promotions Engine features unlimited combinations of ‘buy-x-get-y- free’ type deals.

E-COMMERCE & WEB DEVELOPMENT
We also offer e-commerce/web-development solutions that dove-tail seamlessly with your stores, allowing you to run your on-line store as an ‘extra branch’ and click-and-collect features as well as traditional shipping options.

FULL FREE DEMO
You can get full access to your own demo copy of our full system at our website -  www.blueboxonline.com.

Monday, March 25, 2013

A small neat PHP Captcha Script

I cannot stand the way some Captcha scripts look and work. Personally I give up very quickly when signing onto a web-service if I cannot 'identify' the Captcha characters easily. making hard for spider-bots is one thing, but making it impossible for humans is quite another.

So, here is a simple, clear captcha script written in PHP that makes it harder for bots to submit your forms, but obviously it not impenetrable (I would presume).

I have called it 'Matcha' to differentate it from other Captcha scripts (at least for us BlueBox-ers).

Invoke the Matcha session string at the top of your form like this:
  • $_SESSION["matcha"]=strtoupper(chr(65+rand(0,25)).chr(65+rand(0,25)).chr(65+rand(0,25)).chr(65+rand(0,25)).chr(65+rand(0,25)));
  • This will create a string of 5 uppercase A-Z characters.
In your form add these 2 rows to the layout:
  • <div class=cr_form_label>
    Characters to Match:
    </div>
    <div>
    <img src=\"<!--:class:bb_mymodule:matcha:-->\" >
    </div>

    <div class=cr_form_label>
    Enter Characters*:
    </div>
    <div>
    <input class=cr_form_field id=matcha name=global[matcha]>
    </div>
  • Remember to create a new BlueBox2.0 module called bb_mymodule (use the module name here, not this example name)
In the PHP BlueBox2.0 module (bb_mymodule) create a function as follows:
  • function matcha($err){
            global $global;
            $im = @imagecreatetruecolor(257, 36);
            $text_color = imagecolorallocate($im, 140, 140, 140);
            $white = imagecolorallocate($im, 255, 255, 255);
            imagefilledrectangle($im, 0, 0, 257, 36, $white);
            $font_file = 'portal/database_name/custom_modules/captcha.ttf';
            imagefttext($im, 15, 3, 70, 30, $text_color, $font_file, $_SESSION["matcha"]);
            imagepng($im,"portal/database_name/custom_modules/c/$_SESSION[matcha].jpg");
            imagedestroy($im);
            resp("portal/database_name/custom_modules/c/$_SESSION[matcha].jpg?".uniqid());
        }
  • You will need to upload a TTF font to the server that is suitably difficult to read for a bot-scanner.
 Finally, do a check when your form gets posted, to see if the entered amount matches the Matcha string:
  • if(strtoupper($global[matcha])!=$_SESSION[matcha]){
         resp("The characters you have entered do no match the string shown.");
         return;
    }

Wednesday, March 20, 2013

What a small Samsung Android Phone can do.

I recently spent a few days on-site doing an ERP implementation of BlueBox for a new customer, and was reminded how powerful a simple Android phone can be in business systematisation.

Our clients run a small sports and schoolwear clothing manufacturing and sales business and required point of sale, inventory, production control and integrated accounts with xero.com.

Easy enough with BlueBox, I had a 3 days scoping session with them, followed by a week of bespoke PHP/MySQL programming, and this last visit was the final implementation of another 3 days. (Side note - it always amazes me how long it takes for 'big ERP systems' to eventually fail in their implementations, while BlueBox quietly achieves what to most in the industry would consider impossible when it comes to speed and success of deployment.)

In this process we identified that bespoke order-taking facilities would be required at the front-desk (ePOS) and have implemented sales order creation facilities within our ePOS to allow sales people to take the order, amongst normal sales items, which then creates the required sales orders in the back-office.

These are then displayed on a dashboard for production control and visibility, and various automated customer communication triggers (SMS/text message and email) are sent at points in the process.

Now to the phone. In order to track and simplify jobs through the production process, we added QR codes to the bottom of each Sales Order, one for 'previous stage' and one for 'next stage'. Stages are mapped to Sales Order categories which essentially become production process maps. Initially I thought we'd need small tablets to scan the barcodes/QR codes at each stage, but, strangely, we found that tablets (no names mentioned because it seems to apply across the board) have notoriously poor cameras, which do not seem to offer the ability to macro-focus on barcodes. Who came to the rescue? A dirt-cheap Samsung Galaxy Ace (old model!) for under £80 with a 5MP camera scanned the QR codes from stage to stage perfectly.

So our final implementation used web-served QR codes on each sales order, delivered by Qrickit.com, and these were scanned into the Samsung Galaxy Ace using the Barcode Scanner App by Zxing Team, which neatly bounces each scan onto our BlueBox cloud based system to a bespoke script that moves the sales order forwards or backwards in the production process.

So quick. So affordable. So powerful. And... so easy!

Friday, March 8, 2013

What does BlueBox do?

I get asked to prepare a short summary on 'what does BlueBox do' quite regularly, and wanted to blog this answer here this week, as I feel it can assist some of our partners and staff for future reference.

It is difficult to answer this question generically, as we are a multi-disciplinary platform that appeals to many business sectors. When putting together a statement like this you want to bear your target audience in mind. In retail, for example, somebody may be looking for ePOS or Inventory Control, whereas in manufacturing they would be looking for Bills of Materials and MRP functionality.

BlueBox2.0's feature list is extensive and growing all the time, so it is always worth referring there as well.

Here is a recent summary I put together with a focus on the para-statal market:



"The BlueBox has been providing bespoke business system and database solutions since 1996 for large brands like Old Mutual, KFC, Barclays/ABSA, Skype and Standard Bank as well as small to medium sized businesses. 

We are a small, customer-focused company who do not believe in the one-size-fits-all approach to system implementation. Our systems are 100% web/cloud based, requiring no software installation and ensuring all data is live and central at all times.  We take great care to fit our solutions to your requirements while using all the tools at our disposal to ensure this can be done quickly and affordably.

Included in our modules are Stock Control and Asset Management, Sales Orders and Billing, CRM, Procurement Management with MRP and Replenishment, Loyalty and Customer Retention, Human Resources, Manufacturing, Marketing Campaigns and Communications.

Recently added to this list is our Process Management module. This allows us to map business processes within your organisation to system generated procedures. 

If you would like an introduction to BlueBox please do not hesitate to visit our website at www.BlueBoxOnline.com where a full free demo of our system is available to you."

Monday, March 4, 2013

New Ajax/JSON Functionality for BB2.0

From Steven de Klerk, Senior Developer at BlueBox:

New Ajax functionality has been added to BB2 this week, allowing for any PHP function to be easily accessed via JavaScript through the use of Ajax and optional JSON objects, without the need for additional coding. The function to call via Ajax is simply called "ajax" and is available on all BB2 modules. This function accepts a few parameters, listed below:
  • global[ajax_method] - Required. Sets the function to be called within the module
  • global[param] - Optional. The parameters to be passed to the called function, as an indexed array. So, param[0], would be the first parameter. param[1] the second, and so on. e.g. $_class->method(param[0], param[1]);
  • global[json_encode] - Optional. Sets the response to the Ajax call. Default is a basic "success" response, otherwise when this param is set to "1", it will return a JSON encoded object.
The new "ajax" function does a permission check to ensure the user can run the "ajax_method" listed, and then either returns a basic "success" if the function was run without problems, or returns a JSON object, which would be the primary use for this new functionality.
Let's say we wanted to add a new user with the user name of "testuser" and the first name of "Paul". To do this, we'd simply call the following url:
/?class=bb_users&method=ajax&global[ajax_method]=add&global[param][0][this_class]=bb_users&global[param][0][fields][name]=testuser&global[param][0][fields][first_name]=Paul
Breaking that up, you'll see we've called "ajax" on the class "bb_users", and set the PHP function as "add". We then pass through the parameters. Since the "add" function only takes one mixed array, we're going to set global[param][0] with our array of data. In this case, it's just the "this_class" parameter, and then the "name" and "first_name" fields. Since we haven't set it to return a JSON encoded object, it will just print out the text "success" on completing. If you use this method, make sure to check that the response text only contains the word "success" (responseText == 'success'), as an error could also be present, and should be displayed to the user in that case.
This, however, doesn't fully utilize the new functionality. To do this, "global[json_encode]=1" should be passed in the url, telling the ajax function to return a usable JSON object, which provides far more information. For example, running the same url above, but with the included JSON encoding switch, we see the returned data is:
{"response":{"this_class":"bb_users","fields":{"name":"testuser","first_name":"Paul"},"do_not_redirect":"true","_id":"52"},"rows":4,"html":"","status":"success","error":""}
This is a JSON encoded string, and thanks to JavaScript libraries such as Prototype, we can turn this into an easy to use object by calling "evalJSON()" on the reponseText. The JSON object contains a few parameters:
  • response - the response from the function called. This can be anything, depending on what the function returns
  • rows - the number of rows. If there's only 1 result (such as a "get" or "add" call), it will list the number of elements.
  • html - any outputted HTML while running the function. Useful if the function does resp/print calls
  • status - whether the function completed successfully or not
  • error - any errors that may have been caught while running the function
The first thing to do when checking the response, is to make sure that the "status" parameter == 'success', and if it doesn't, then check the "error" parameter to see if any errors were caught. If it was successful, you can now check the function response and use the returned data. So, if we wanted to alert the new _id of the user we added, we can do so like this (assuming that the variable "data" is the evaluated JSON object):
if (data.status == 'success') {
     alert(data.response._id);
} else {
     alert('Error: ' + data.error);
}
Handling and calling the new "ajax" function can all be done fairly easily through Prototype's Ajax.Request functionality, however, to make things even easier, there's a new BB2 ajax function which handles most of the leg work described above.
The new JavaScript function is called "ajax2json", and is a quick and easy gateway to the above functionality.
The new function takes the following parameters:
ajax2json(callback, className, method, param, loaderElm, largeLoader)
  • callback - Required. (function) The callback function when the response has arrived from the request
  • className - Required. (string) The BB2 class/module to call
  • method - Required. (string) The BB2 method to call on the above class
  • param - Optional. (object) An object containing the parameters to be passed to the above class->method
  • loaderElm - Optional. (string) The HTML element to add a loading spinner during the request
  • largeLoader - Optional. (bool) Whether or not to use a large spinner
So, let's do the same user add as above, and then get a list of users with the same name as what we've added. To start off with, we'll create a callback handler and then an "add" function:
 function handleAddResponse(data) {
  if (data.status == 'success') {
   alert('New record added with _id: ' + data.response._id);
  } else {
   alert('Error: ' + data.error);
  }
 }
 function addUser() {
  var param = {
   0: {
    fields: {
     name: 'testuser',
     first_name: 'Paul'
    }
   }
  };

  ajax2json(handleAddResponse, 'bb_users', 'add', param);
 }
Breaking down the above, we call "ajax2json" with the callback function "handleAddResponse", which checks to make sure the response was successful, and if so, it alerts the new _id. We then set the class, method and parameters which is a basic JavaScript object, made up of the fields we want to set.
Once we've added our user, we want to get a list of users with the name "Paul" and then handle that data. This can be done like so:
 function handleListResponse(data) {
  if (data.status == 'success') {
   alert('Found ' + data.rows + ' row(s).');
   data.response.each(function (row) {
    var output = '';
    for (var field in row) {
     output += field + ': ' + row[field] + '\n';
    }
    alert(output);
   });
  } else {
   alert('Error: ' + data.error);
  }
 }
 function listUsers() {
  var param = {
   0: {
    where: 'first_name LIKE \'%paul%\''
   }
  };

  ajax2json(
handleListResponse, 'bb_users', 'getList', param);
 }
This time our callback function is a bit more advanced, as we're going to run through the response data and alert the values. If we do the add before the list, we'll get back at least one row containing all of the data for our new user record. We can now display this data in a table, use it in another add, and more.
With this new functionality, there should no longer be a need to create additional BB2 functions to act as "proxies" between standard and custom BB2 functions and the browser, as we can now pass and receive data between the PHP side of BB2 and the client/browser side seamlessly.

Sunday, March 3, 2013

New sales discount by user group (and item category)

BlueBox20 now has the option of managing sales discount by user group (previously only possible at user level).

Any discount applied at user group level will automatically apply to any sales item added to sales orders (and their subsequent downstream documents despatch notes, debtor invoices etc), as well as point of sale till slips.

A further level of control is available whereby you can now link a user group to a specific Item category, and at that point specify the sales discount that applies to that user group for all items in that item category.


Sunday, February 24, 2013

Handling 'Page Not Found' Errors in BB2

A new config setting in BlueBox2.0 allows for bespoke handling of 'page not found' errors.

This is not to be confused with traditional server-side 404 errors, and only applies to /?page_name allocations withing the BB2.0 database templates engine.

In this case, if you wanted to create a new BB2.0 'page' in the template engine, this would be assigned a page_name.page title in the database templates module. To access your page you would use '/?page_name' and this would then call the page commands contained therein.

Up till recently, if page_name.page did not exist, the fail-over response in BB2 was to attempt to load /?class=page_name and if that failed it would revert to /? (the home page).

So, this new setting, found in the config file (admin->config) is called $system_default_no_page_found, and it take a setting as a string with the class_name:method_name to run in the event that /?some_url is not verified using the above 2 standard methods.

For example, you could set it to run 'bb_come_class:some_method' and it would be invoked as such.

This new approach is very handy in 'url friendly' sites where you want the user to be interpreted based on it's contents. So a user like '/?Run Report One' would then be able to be parsed and run a specific report, or '/?plumbers_in_london' could be parsed to show filtered results.