Jump to content

Paul C

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Paul C

  1. Ah I think I can see the error - In the initContent() override you have OrderController::STEP_DELIVERY twice. The last one (after the parent::initContent() call) should be OrderController::STEP_PAYMENT. Not saying that it will work but it definitely won't at the moment EDIT: I just noticed another error - A typo on my part! We actually don't need to check the customer id in the last of statement anyway but it was wrong. public function _setPickupAddress($pickup_store) { $store = new Store((int)$pickup_store); // Get the store object $deliveryAddress = new Address(); // Create a new address object $deliveryAddress->id_customer = $this->context->customer->id; $deliveryAddress->id_country = $store->id_country; $deliveryAddress->id_state = $store->id_state; $deliveryAddress->firstname = 'Livré à : '; // You may need to play with these $deliveryAddress->lastname = $store->name; // for it to make sense $deliveryAddress->address1 = $store->address1; $deliveryAddress->address2 = $store->address2; $deliveryAddress->postcode = $store->postcode; $deliveryAddress->city = $store->city; $deliveryAddress->phone = $store->phone; $deliveryAddress->save(); if (Validate::isLoadedObject($deliveryAddress)) $this->context->smarty->assign('delivery', $deliveryAddress); }
  2. I don't think you should specify the full path to the template, should you? Prestashop expects your template to be: /modules/<your-module>/views/templates/front/all-products.tpl With the above your code you should just be: $this->setTemplate('all-products.tpl'); That's the standard non-overridden version of your controller's template and I believe there has to be one.
  3. OK, well the next stage should be fairly easy then, since you pretty much have all the information you need. I think the key here is to look at the delivery as being to one of your stores rather than to the customer. I don't think you actually need to save the store id as a separate field - just use it instead of the id of the delivery address. Ideally we should be able to get the id of an address for your store and just use that in $this->context->cart->id_address_delivery ... but of course it isn't that easy as the Store class doesn't use an address object but uses separate fields for the address. The simplest thing to do would be to create a new address object and use the id of that - unfortunately this will create new database entries for each order and clutter up the customer address list but I guess no worse than a standard customer order. We would also have to be careful of any cart or tax rules that depend on the delivery address, but I'm assuming customers who want to collect from store are local anyway. We modify the choice function to just: public function get_ChoixMagasin() { $retrait = $this->context->cart->id_carrier; if ($retrait == 13) /* Si le client a choisi le retrait en magasin (id : 13) */ return (int)Tools::getValue('choix_magasin'); return false; } and then the override of initContent to: public function initContent() { $pickup_store = false; if ((int)$this->step === OrderController::STEP_DELIVERY) $this->get_ListeMagasins(); // Appelle la methode pour recuperer la liste des magasins dans le tableau Livraison else if ((int)$this->step === OrderController::STEP_PAYMENT) $pickup_store = $this->get_ChoixMagasin(); parent::initContent(); if ((int)$this->step === OrderController::STEP_PAYMENT) if ($pickup_store) $this->_setPickupAddress($pickup_store) } Now we need to create a function to set the pickup address (overriding the customer address set in parent::initContent() by using the data from our Store object). Any time you need to display something different for orders that are collected from your store, then you just need to check id_carrier. Be careful though as the carrier id can change! public function _setPickupAddress($pickup_store) { $store = new Store((int)$pickup_store); // Get the store object $deliveryAddress = new Address(); // Create a new address object $deliveryAddress->id_customer = $this->context->customer->id; $deliveryAddress->id_country = $store->id_country; $deliveryAddress->id_state = $store->id_state; $deliveryAddress->firstname = 'Pickup from'; // You may need to play with these $deliveryAddress->lastname = $store->name; // for it to make sense $deliveryAddress->address1 = $store->address1; $deliveryAddress->address2 = $store->address2; $deliveryAddress->postcode = $store->postcode; $deliveryAddress->city = $store->city; $deliveryAddress->phone = $store->phone; $deliveryAddress->save(); if (Validate::isLoadedObject($deliveryAddress) && ($deliveryAddress->id_customer == $customer->id)) $this->context->smarty->assign('delivery', $deliveryAddress); }
  4. OK. Is there a specific reason you decided not to just create your own "carrier" that allowed you to choose a store as a delivery point? Prestashop already has the ability to manage multiple stores, including addresses (distinct from multi-shop). I'm asking because I think this would require less modification!
  5. What version of Prestashop are you using? If it's 1.6.1 then I think there's a bug which causes the tax to be completely messed up in the cart when there's no user logged in.
  6. Ok. Obviously I'm going to have to try and do this blind with no testing but here goes! The first "hack" to `OrderController.php` can be replaced with the following function in your `OrderController.php` override: public function initContent() { if ((int)$this->step === OrderController::STEP_DELIVERY) $this->get_ListeMagasins(); // Appelle la methode pour recuperer la liste des magasins dans le tableau Livraison parent::initContent(); } The above will get the list of stores available to your modified order-carrier.tpl template but we need to do something with that information to make it accessible to us later. It doesn't look like you need the store choice in order-payment.tpl so if not we can just extend the above to cover both "hacks": public function initContent() { if ((int)$this->step === OrderController::STEP_DELIVERY) $this->get_ListeMagasins(); // Appelle la methode pour recuperer la liste des magasins dans le tableau Livraison else if ((int)$this->step === OrderController::STEP_PAYMENT) $this->get_ChoixMagasin(); parent::initContent(); } You don't appear to actually do anything with this stored value though except save it in a smarty variable? In order to access it in later steps you're going to need to either save this data or postpone saving it by adding it as a hidden field in order-payment.tpl. That could be tricky as you're basically handing over control to the payment modules at that point. This is where you need to make a design choice All during the above processing we don't actually have an order - just a cart object. You could save the choice in the cart object but that would mean extending the cart class to add your additional property (id_store). You would still then need to add additional code to extend the order object as well (or modify it to access the data in the cart object in order to save it). Another option would be to store the data manually either in its own table or in the cart table. (a table of id_cart and id_store would be sufficient). I'm not 100% sure what you're trying to achieve though so it's hard at this point to advise one way or another! What is the store choice actually for?
  7. The best way of handling these are to use the hook functionality and add your code in a module attached to the correct function in your case: function actionValidateOrder(Array $params) { $id_lang = (int)Context::getContext()->language->id; $currency = $params['currency']; $order = $params['order']; $customer = $params['customer']; $delivery = new Address((int)$order->id_address_delivery); $invoice = new Address((int)$order->id_address_invoice); $order_date_text = Tools::displayDate($order->date_add, $id_lang); $carrier = new Carrier((int)$order->id_carrier); $message = $order->getFirstMessage(); // Do something cool here to insert your data } Conveniently there's also: hookdisplayAdminOrder(Array $params) { if (isset($params['id_order'])) $order = new Order($params['id_order']); if ($order) { // Fetch your data and display it by returning the html directly or via a template } }
  8. You can use hooks to implement additional functionality but you will need to write a module to wrap up the hook functions. Which hook you can use will depend on which template file you need the data to be available to. Basically modifications to Prestashop come in 3 forms (in my order of preference): - Hook (module) - Custom Controller - Override
  9. You may have to put the php code in a module and get it into the smarty variable space via the hook: displayPDFInvoice Although that's intended to allow you to insert a complete block in the invoice you can likely use it to insert variables too and just return nothing. Your issue is that you cannot (and shouldn't) execute php inside a smarty template.
  10. It really depends on your import script whether you need to delete them or not. The actual relationships to the products are gone and what's left should get reused when you assign attributes/groups to the new products added - but it depends on how the script is written. In general you should always try and use the delete() member function of classes so if you really need to remove them all you could try: $results = AttributeGroup::getAttributesGroups((int)$context->language->id); foreach ($results as $result) { $group = new AttributeGroup($result['id_attribute_group']); $group->delete(); } I haven't tried this but it should remove any unused attributes so doing this after the first one to delete the products should clean them out.
  11. Sorry, yes my bad. Shouldn't do these things from memory! I thought it defaulted. You'll need to get the context in the script if you don't already e.g. with : $context = Context::getContext(); So you can pass the language to the call: $results = Product::getSimpleProducts((int)$context->language->id);
  12. You shouldn't need to delete the attributes separately. Also if you're using Advanced Stock Management then there are certain conditions where the product delete will fail (stock >0 or resupply order pending I think). The product may also not be completely deleted if you have MultiShop enabled. Assuming the above is ok I would just call: $results = Product::getSimpleProducts(); foreach ($results as $result) { $product = new Product($result['id_product']); $product->delete(); } That should take care of everything (including the attributes). EDIT: I should say that this will delete EVERYTHING to do with the product including any images, discounts, specific pricing etc.
  13. Hmm. I obviously misunderstood. To be honest since you can have multiple categories for a product I don't really see how this feature would be that useful in most cases. You're in danger of using tags as just a second, separate category structure. Another way could be by using features - I've used these before and filtered with them. They are actually quite powerful in their own right and often overlooked.
  14. The simplest way would be to rename all the text references for Brand/Manufacturer to "Outlet", store the "outlet" as the brand and store the "brand/manufacturer" as a tag (again appropriately named in the theme) - that way you can use the built-in layered navigation. EDIT: The only downside is that you can have only 1 "outlet" value which may not work for you.
  15. The discount can be a percentage per product per customer group. The difficulty might come if you have a lot of products to edit as you'll have to add the special pricing for each one - unless you script some sort of import (that's essentially what I do to add the rrp during an import of XML from the POS system). You can manually edit them under the Catalog product edit page in the Prices tab (Specific Prices). I created a (misspelled!) customer group first with a discount of 0%, then went to a product: For completeness this is a snippet of code I use in the import to set a specific price for a customer group: $RRP = new SpecificPrice(); $RRP->id_product = $product->id; $RRP->id_shop = 0; $RRP->id_shop_group = 0; $RRP->id_currency = 0; // All currencies $RRP->id_country = 0; // All countries $RRP->id_group = MembershipCard::getRRPGroup(); $RRP->id_customer = 0; $RRP->price = (float)$feedRRP; $RRP->from_quantity = 1; $RRP->reduction = (float)0; $RRP->reduction_type = 'amount'; $RRP->from = 0; $RRP->to = 0; $RRP->add(); In my case I fetch the group id from a static member of a class (MembershipCard) but this can just be hardcoded, of course. The reduction type i your case would be: $RRP->reduction_type = 'percentage'; And you need to specify an amount: $RRP->reduction = (float)0.10; // 10% You also don't need to specify the price in your case.
  16. You can have multiple customer groups with different discounts so yes you can do it. It may depend on your pricing structure though how easy it will be. A straight discount on a baseline retail price is simple - all you need to do is create the customer group and discount and then assign existing customers to these groups as appropriate. I use customer groups and some custom coding to allow display of RRP pricing on a wholesale site, for example.
  17. I would first check the group of the user you're testing with (from Admin->Customers) and make sure it matches the customer group that the discount applies to. A lot of these issues arise when sites are upgraded and the groups possibly don't match up exactly. If that's the issue then you'll need to work out how to get the customer groups back on track
  18. Just remove the numbers from the ol with CSS: http://www.w3.org/TR/CSS21/generate.html#lists
  19. Did you remember to delete /cache/class_index.php? The override probably won't take effect until you do. EDIT: You beat me to it.
  20. Not that I can recommend what you're doing - you should really look at adding an additional field... but....... Wouldn't it just have been much simpler (and less destructive of the core files) just to add an override for the validation? Just stick this in a file called: /override/classes/Validate.php and stop editing those core files <?php class Validate extends ValidateCore { /* * Pretend that we're really checking an ean * but treat a string as valid * */ public static function isEan13($ean13) { return is_string($ean13); } }
  21. It is actually be the class name of the module in lower case - which is also the directory name of the module (via the naming convention).
  22. Lines 578-580 specifically https://github.com/PrestaShop/PrestaShop/blob/develop/classes/Cart.php#L578 I should add that I also had an issue with tax not showing on the cart when not logged in. I have a fix but it's a pure hack and haven't yet tracked down what's causing it (other than an issue with the context so there isn't a valid address being created to set the tax correctly).
  23. It's fixed in the version of classes/Cart.php on github
  24. The key to these is WHEN you override. I used the following in override/classes/Product.php to add an RRP (set in each product as a group price) to products: public static function getTaxesInformations($row, Context $context = null) { $row = parent::getTaxesInformations($row, $context); $module = Module::getInstanceByName('yourmodulethatcontainsthefunction'); $row['rrp_price'] = $module->getGroupPriceStatic($row['id_product'], (int)MembershipCard::getRRPGroup(), true, 6, ((isset($row['id_product_attribute']) AND !empty($row['id_product_attribute'])) ? (int)($row['id_product_attribute']) : null)); return $row; } $row is an array that contains the source data that's passed to the theme..... It's not really clear though what you're trying to achieve - is it to change the actual price charged (which the above won't achieve) or to modify how the price is displayed (which the above type of solution COULD achieve)?
  25. I find it surprising that even with a 30sec timeout limit you're facing such restrictions. How are you importing the images? Via a url? Another option might be to run the product import as a cron job. Command line utilities aren't time limited in the same way as interactive scripts, although depending on your hosting your jobs might still get killed if they take too long.
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More