While we discuss about discounts, I’m trying to edit part of my code to use your libraries as much as possible.
These were previously false/false and now are:
$config['defaults']['configuration']['display_tax_prices'] = true; //previously, I was calculating the taxed price of each product by myself. $config['defaults']['configuration']['price_inc_tax'] = false;
So when adding items to the cart with insert_items(), the value for price is 82.64 without VAT.
By using set_tax() and setting ‘rate’ to 21, I see 99.99 as price including taxes. Although, there are some rounding problems. I had them too, then I decided to use your libraries more, hoping to solve them :/
Here’s what happen:
I added that item (82.64, 99.99 with VAT).
I set the quantity to 2.
I would like to announce the release of ‘flexi cart’, a comprehensive shopping cart library for CodeIgniter.
Hi, I have been playing with your shopping cart recently. Thanks for releasing this and supporting it actively.
I have a question about this, which is found in standard_library.php in the demo:
function checkout_complete($order_number = FALSE)
// Note: This example uses the ‘get_db_order_summary_row_array()’ and ‘update_db_order_summary()’ function which are located in the flexi cart ADMIN library.
I’ve been trying to find the function get_db_order_summary_row_array() in the flexi cart libraries, models, everything, but for the life of me, I can’t find it anywhere. The closest thing I found was the function get_db_order_summary_query() in the flexi cart admin library, but get_db_order_summary_row_array() is called in the demo and it seems to work. I’m missing something and I hope it’s not something stupid.
Thanks again for creating and sharing this, I’ve been learning a lot from it.
Regarding your confusions with the discount foreign keys.
The ‘disc_item_fk’, ‘disc_location_fk’ and ‘disc_zone_fk’ columns all rely on the carts session data (As you suggested).
You seem to have worked out how they work just by what you have posted.
The ‘disc_item_fk’ is the item id that is saved to the cart when inserting an item.
This same id is what is matched in the ‘discount_group_items’ table for item group discounts.
The location and zone ids can be defined in a few different ways.
You can use the ‘update_location()’ function as you have stated, or you could alternatively define the location when using the ‘update_cart()’ function.
One important note to keep in mind, is that there are 2 different location types - a ‘shipping’ location, and a ‘tax’ location.
This allows you to define shipping rates and discounts offers via the shipping location, and taxes via the tax location.
If you need to set these 2 locations differently (Usually for tax purposes), checkout the setting data functions via the locations user guide page
Regarding the issues of stacking discounts together using the same discount code, I haven’t been able to replicate this via my own examples.
I will point out that when two or more discounts are valid, they are applied in the order defined via the ‘disc_order_by’ column in the discount table, the lower the number, the higher priority.
If you can provide a database dump of the two discount rows causing the issue, i’d be happy to look further into it.
Finally regarding the rounding issues, this was actually a large nightmare for me during development.
I managed to somewhat tighten down the inconsitencies by getting the cart to calculate values based on 4 decimals, but I could not find a 100% concrete solution or best practice of how to solve the issue.
I even tried testing other POS software systems but kept getting the same variations in rounding calculations.
This is actually something I would love to throw out there to anyone willing to offer suggestions on the best way to round up decimals when dealing with currency values containing 3 or more decimals.
These long decimals numbers are mainly caused when dealing with tax and discount percentages.
For example 2 items @ $100 each, minus a 1/3 discount (33.3333%) is $66.6666, rounded to $66.67.
So 2 discounted items now @ $66.67 equal $133.34; but if adding their values together including 4 decimals ($66.6666 x 2), it rounds to $133.33; a $0.01 difference.
Do this with more items and the difference increases.
You could suggest to just apply the 1/3 discount to the total, but the cart items need to be able to be itemised, so it needs to be calculated per item.
You seem to have sussed it out correctly yourself.
The functions (methods) you are referring to are in fact created using PHPs magic method ‘__call()’ to overload the method (e.g. get_db_order_summary_row_array() over get_db_order_summary_query()).
You can find this defined within the file ‘libraries/flexi_cart_lite.php’ @ line 38.
Thanks for the SQL dump, it helped me regenerate your example.
Technically the settings for the discount are partially at fault as the ‘disc_order_by’ column is meant to deal with this sort of issue, by defining an order priority that discounts are applied.
In you example sql dump, the order by values where both the same so the cart didn’t know which to prioritise.
However, I’ve patched the library to help prevent this happening.
The patch is available via the usual Github repo.
You can find this defined within the file ‘libraries/flexi_cart_lite.php’ @ line 38.
Thanks for this. It helped my understanding of magic methods.
I have a quick question about your tax calculation. On your online demo, I select “Example #102 : Add multiple items at once with 1 link” then go to view cart. The Item Summary Total calculates out to 74.45. The tax “VAT @20%” calculates out to 13.07… but 20% of 74.45 is 14.89. Am I missing something here?
I think you’ve made a small error in your calculations.
Your example of removing 20% from 74.45 returning 14.89 (74.45 * 0.2) is not how you calculate tax.
For example, 100 + 20% = 120, but 120 * 0.2 = 24 rather than 20.
Another point that would cause you further error, is that the price for items #102 is 74.45 plus the shipping cost which also in this example includes tax. So you would need to calculate 20% of (74.45 + 3.95), which equals 13.07.
There are two methods of how to define currency within flexi cart, either manually via the config file, or via using the currency database table. The currency table is only needed if converting prices between multiple currencies.
My little tax situation is all cleared up. I just needed to unset the “prices include tax” property in Cart Configuration.
I’m now setting up the Checkout sequence and I’m not understanding how “$this->flexi” works. Is it saving information to a cookie? I ask because I’d like to separate the shipping/billing information to its own page in the Checkout sequence. In the final Checkout page, I’d like the customer to view their shipping/billing information and all the relevant cost calculations. To transfer the shipping/billing information to this page, I was thinking of creating the array “$this->flexi->shipping_information” and using it as the data vehicle, but if it’s saving data to a cookie, I’m concerned about customer privacy… don’t want their personal data being accessible to anyone that can look at the cookie.
Trying to apply the ‘TESTUSER’ discount, it is correctly not applied, since the custom status does not match, but the status message says ‘Discount code has been set’.
Using ‘set_custom_status_1(1)’ correctly applies the discount.
This is a minor bug anyway
I also noticed that discount messages are all set in english, even if the set language is another one.
I tried emptying my cart, for example, and the returned status messages are in Italian (correct).
It seems all discount functions have this issue.
I also wanted to share the Russian language file with you. I told you I would have done it but then completely forgot.
Here it is: http://pastie.org/5648272
The variable ‘$this->flexi’ is used by the library as a global variable that CodeIgniters libraries, models and controllers can all access.
The inclusion of the variable was never intended in my initial design of the library and ideally still wouldn’t be included, but was added to fix a warning that would occur for users using PHP 5.4.
The variable has nothing to do directly with cookies or session data and is soley intended for internal use by the flexi cart library and so you shouldn’t use it to store you own data.
If you want to preserve custom user data (i.e. Data not available from the cart), then you would typically use session data.
By using sessions, you will perserve the data between page loads and it will be secured and inaccessible to other users.
Hope that helps!
Thanks for the pointers on the discount bugs you’ve noted, I’ll try and look into these when I get a spare moment.
Also many thanks for the translated language file.
When I fix the above bugs I’ll be sure to add the file to the repo with full credit listed to yourself.