Prestashop add custom radio button on shipping carriers on front end checkout - prestashop

I have created one custom module in Prestashop 1.7.8.7 which will add multiple shipping methods (Carrier) and will show shipping cost based on product dimensions and delivery address. So shipping carrier will look something like this on front-end checkout page. https://prnt.sc/E1avDASyJYYW
Now if someone select SameDay Courier Shipping then i need to show two radio button to select which service they want.
It will have two radio options like
Delivery pickup (by default this option will be selected)
Locker pickup
So if someone select Delivery pickup then it will have different shipping cost and if someone select Locker pickup then it will have different shipping cost.
Can anybody help me how can i achieve this functionality.
While digging, i found that we have file called DeliveryOptionsFinder.php and in that file we have one public function called getDeliveryOptions() where we have this line of code
if ($moduleId = Module::getModuleIdByName($carrier['external_module_name'])) {
$carrier['extraContent'] = Hook::exec('displayCarrierExtraContent', ['carrier' => $carrier], $moduleId);
}
}
So if i set is_module to 1 to all my carriers directly from DB then on frontend checkout page, no carriers is being displayed.
Thanks in advance.

I've already done something like this in the last 2 year as prestashop developer.
The truth is that you can't achieve what you want by "respecting" prestashop processes.
Maybe you can hook using a module the hookDisplayCarrierExtraContent($data) and then return the 2 radios if carrier is certain one (use $data).
But you can't handle a form submit or something else, or include it to prestashop checkout data.
But what you can do as workaround, for example, is the following.
In your module, as I said, hook the extra content, render a template with the 2 radios. Hook displayHeader too and use $this->context->controller->addJS() to add your own js if the current controller is the checkout one.
Then in this JS code you can handle the "change" event of the radios and send an ajax request to your module.
You can create inside {your_module}/controllers/front/ a controller called, for example, radio-choose and handle the js ajax request by saving inside your own table the choosen one.
Obviously you can disable the "next" button in checkout untill one of the two radios are selected, or maybe you can just set a radio button as default one to simplify.
For example your table "ps_cart_choosen_radio" could look like this |id_cart|choosen_radio|.
Then you have all the data you needed. When a cart is converted into an order you will have inside Order object (and ps_orders table as well) the id_cart.
Just select / join choosen radio from your own table by using order's id_cart.
"SELECT choosen_radio FROM ps_cart_choosen_radio WHERE id_cart = {$order.id_cart}"
If you need to show data depending on choosen_radio in frontend you can hook everywhere an order is present and select these data. Or maybe you can edit carrier name in ps_orders table by adding a piece of string. Let' say carrier is "express" and customer choosed "24h". You can update that column with carrier name by changing it to "express-24h" so around the whole prestashop ecosystem everybody will see that's a 24h choice.
Remember that the carrier name related to an order is not the carrier name inside the carriers table. So you can edit it without having trouble.
All these problems comes from the "need" to show some nested choices instead of listing all these in the main selections. In that case it would be easy (just create carrier in the prestashop backoffice)

Related

How to display only selected products in Spree?

Am using Spree Commerce, and right now every product I add on my backend is displayed on the homepage. Is there a way that I can display only products of my choice on the frontpage, and not display everything as it does by default?
I know deface allows me to customise the look of everything, but it is not the answer I am looking for.
Thanks
#elliot Actually it's pretty simple. Go to product's edit page on admin end and set discontinue_on for that product with a date equal to the current date or lesser.
Only those product are visible on the frontend for which available_on is lesser than the current date and discontinue_on is greater than the current date.
Deface is used to changing views not a controllers. A fetching products from DB is a controller logic.
There is a lot of options, you can add your own scopes in product model and override controller to use them, but fastest is use discontinue_on because for not admin user spree uses usually active scope on products.
Found the answer: I just changed #products = #searcher.retrieve_products to #products = Product.joins(:variants_including_master).where(:name => "Ruby on Rails Tote").uniq on my index action in home_controller_decorator.rb

Shopify: Filtering collections by custom filter

I'm new with liquid and ruby, but I would like to create a custom filter in a collection, to filter by metafields. I already have:
A dropdown in the collection.liquid, with the values I would like to filter for.
When selecting a filter, it goes to a link like: https://myshop.myshopify.com/collections/my-collection/my-filter . Basically it is like the tags, but with my filter instead
However, since it is a custom filter and not a tag, I get no results. I'm wondering where is the query that displays all the products (or filters) is in the code. I know that it depends on the theme, but I'm using the default theme: launchpad-star.
Not sure if I could do it this way or with a link like: https://myshop.myshopify.com/collections/my-collection?filter_by=my-filter , in which case, I would also need where should the logic go.
I've looked at the forums already and found two closed tickets with no responses: https://ecommerce.shopify.com/c/ecommerce-design/t/using-metafields-to-create-filter-drop-downs-in-collection-liquid-187513 and https://ecommerce.shopify.com/c/ecommerce-design/t/using-metafields-to-create-filter-drop-downs-in-collection-liquid-134401 .
Thanks in advance
Probably not the best solution, but this is what I did to solve the problem:
I changed to the second option of the url, so when a user selects an option in the combobox, it is sent to a URL like: myshop.myshopify.com/collections/my-collection?filter_by=my-filter
In product-grid-item.liquid, I'm getting the metafield value of the product and displaying it as a class, and hide all the products as default. In the collection.liquid I read with javascript the value of the parameter (filter_by) and remove the "hide" class of the products with the value of the filter_by as class, so it gets displayed.
I feel that it is not very clean, but it is working as expected. Problems with this solution:
* Not displaying all the products and then filtering them
* I need to display all the products to avoid pagination, which could be a big problem if I have a lot of products.
If anyone could post a better solution, welcome!.

How to access Customizable Text Fields From Prestashop Module?

I'm creating a new module for Prestashop where users can design their own product from a third party service. When the user later adds the product to their cart, I would like to save a ID that I get from this Third Party Service where the user designed their product.
I guess the best way to do this is to create a Customization Textfield within Prestashop called "designID". Now I want to know how I save data to this field from module development in Prestashop instead of letting the users manually fill in the data.
So basically... How do I add data to these customizable fields from within a Prestashop module, when the user adds the product to their cart?
These customization fields are used if you are simple user and you are not designing a module. Using it to save the designID will be just a hack.
Since you're creating a new module my advice is to keep the 3rd party ID in a newly created database table, which will match the id_product, id_design, id_cart, id_order, etc...
You can hook to "actionCartSave" and add the record with the matching ids, and all the other required data at your table.
If you want to stick to that Customization feature, add a sample field and review the following database tables:
ps_customization
ps_customization_field
ps_customization_field_lang
ps_customized_data
and replicate the changes when you receive the 3rd party ID.
If all your products will be customized, consider adding the required data in ps_customization_field & ps_customization_field_lang (the table for the field structure) during the module installation, so after it's installed you can just fill
ps_customization & ps_customized_data (the tables for the field data)
PrestaShop does not have proper API for adding customizations, only for retrieving data, so you'll have to write the SQL queries yourself. Just review the ProductController for the ps_customization & ps_customized_data changes and the AdminProductsController for ps_customization_field & ps_customization_field_lang.
Do not forget to remove the Customization markup code from your product & cart templates.
I was able to find this out by myself by first trying to use Customization for a couple of hours without any success.
So basically how my module work is that the customer can open a popup iframe to a third party design tool, the customer then save the design in the iframe, which then sends the data to the parent window (The Prestashop Window).
So to store this I did the following:
Add a new column to the database table ps_cart_product
Hook into any display-hook on the product page and check if any post data is send containing the data from the third party module. If so, then:
if(isset($_POST['thirdparty'])){
$id_product = (int)Tools::getValue('id_product');
if (!$this->context->cart->id){
$this->context->cart->add();
if ($this->context->cart->id)
$this->context->cookie->id_cart = (int)$this->context->cart->id;
}
$this->context->cart->updateQty(1, $id_product);
if(!Db::getInstance()->update('cart_product', array('id_design'=> pSQL(trim($_POST['thirdparty']))) ,'id_cart = '.$this->context->cart->id.' AND id_product = '.(int)Tools::getValue('id_product') ))
$this->context->controller->_errors[] = Tools::displayError('Error: ').mysql_error();
}
So basically first I check if POST is set, then I check if any cart exist, if cart does not exist then add a new cart with ->add() (This function took hours to find, 0 documentation). updateQty() is used to update the cart with the new product.
The last part is the SQL query that updates the value of id_design column with the data that is send from the third party.

Prestashop 1.5 sort product in catgory page by price lowest to heighest by default

this question can be silly to you, but i am having trouble to find a solution. I want to sort product in category page by price lowest to highest, i know there is drop by which i can see products by price but i want to set it by default so that page loads with sorted. can you tell which file i should modify? and how can i achieve this?
here is the url so you can check which things i am talking about:
http://pinstripecreative.com/nationalcapp2/5-decaffeinated
For people who are meeting such issue in Prestashop 1.6, the default sort type can be set in backend via preferences> Products > Set default sorting.
Note that some default modules, like blocksearch, can force the sorting of page by sending the orderby and orderway via a hidden input. Then you need in this case to change the view by either deleting the inputs or sending your own orderby and orderway.
Products default sort not working on search.tpl - Prestashop 1.6.0.6 - Resolved

Opencart: Pass quantity variable to success.php

I have asked this question in the Opencart forums but have yet to receive any responses, so i thought i might ask the experts here #stackoverflow :)
I am trying to see exactly how i can pass the 'quantity' of the items ordered to the success.php page so i can then pass that to another php script that will generate an array based on the quantity.
This is my goal:
Customer Buys 5 items
Customer checks out and processes CC through Paypal Pro
Paypay returns a successful transaction
Now i want the success.php page to pass a variable($quantity) to
myNewScript.php page
myNewScript.php page will generate some random strings and then i
want to attach these random strings to the confirmation email that
opencart generates and sends to the customer.
Where should i start.
You will need to do this in checkout/success controller. Get the $quantity and use redirect function to redirect to your custom page:
$this->redirect($this->url->link('checkout/myNewScript','quantity='.$quantity));