Prestashop 1.7.4.2 - free shipping based on final total price - prestashop

I need shipping calculation after discount applied
Ex.
Total cart : 65$
Free shipping start : 65$
Discount : 5%
After discount it become under 65$ and still get free shipping
I need it to calculate discount before shipping

First set your ranges by carrier (0-65: X EUR, above 65: 0 EUR)
Do an override of the class Cart.php
Rewrite function getPackageShippingCost
After line
// Order total in default currency without fees
$order_total = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list);
Add this
//Recalcul total pour panier et livraison gratuite
$listeDiscounts = $this->getCartRules();
$total_discounts = 0;
if (is_array($listeDiscounts)) {
if (isset($listeDiscounts[0]['value_real']))
$total_discounts = $listeDiscounts[0]['value_real'];
}
$price_to_apply_shipment = floatval($order_total) - floatval($total_discounts);
Replace
//$check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $total_order, (int)$id_zone, (int)$this->id_currency);
by
$check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $price_to_apply_shipment, (int)$id_zone, (int)$this->id_currency);
And
//$shipping_cost += $carrier->getDeliveryPriceByPrice($the_total_price, $id_zone, (int)$this->id_currency);
By
$shipping_cost += $carrier->getDeliveryPriceByPrice($price_to_apply_shipment, $id_zone, (int)$this->id_currency);
Clear the cache and run

The bottom two changes can be replaced by:
$total_package_without_shipping_tax_inc
= $order_total
= $orderTotalwithDiscounts
= $price_to_apply_shipment;
These variables are only used in these two places along the way

Related

Shopify API Paginate Through Orders to Get Accurate Count

In Shopify ORDERS API, I use
/admin/api/2021-01/orders/count.json
In order to get the orders count, so I wanted to get all the orders. And by followign the REST API Documentation, I used two endpoints to do this.
/admin/api/2021-01/orders.json?status=any
/admin/api/2021-01/orders.json?limit=250&status=any; rel=next
First I would request the orders using the first endpoint where I get up to 50 orders/items in a list.
Then by using the counter as a limit, lets say I have 550 orders that I got from the response of orders/count.json
I do:
accumulated = []
iter = 0
while True:
if len(accumulated) > count:
break
if iter != 1:
url = #user first url
else:
url = $use second url that has next
items = #make a request here for that url and save each order item
accumulated+=items #this saves each list to the accumulated list so we know that we hit the count
But for some reason im only getting a fraction of the count. Lets say out of 550 on count, I only get 350 that are not duplicates of each other. Im thinking that maybe the second url, only requests the second page and doesnt proceed to the third page. Hence I was doing
first iteration = first page
second iteration = second page
third iteration = second page
all those gets into the accumulated list and stops the loop because of the condition that when accumulated exceeds count the loop will stop.
How can I make it so when I request ORDERS Endpoint in shopify. I go from the next pages properly?
I tried following shopify's tutorial in making paginated requests, but its unclear for me. on how to use it. THeres this page_info variable thats hard to me to understand where to find it and how to use it.
Hy! In Shopify REST api you can get max 250 orders per api call and if there are more orders you get LINK from header which contain URL for your next page request like
Here you can see I have LINK variable in my response headers you just need to get this LINK and check for rel='next' flag
But keep in mind when you hit the new URL and still you have more orders to fetch then the Header sent LINK with two URL 1 for Previous and 1 for the next.
run this snippet to get LINK from headers
var flag = false;
var next_url = order.headers.link;
if(next_url){
flag = true
next_url = next_url.replace("<","");
next_url = next_url.replace(">", "");
var next_url_array = next_url.split('; ');
var link_counter_start = next_url_array[0].indexOf("page_info=")+10;
var link_counter_length = (next_url_array[0].length);
var next_cursor="";
var link_counter;
for(link_counter=link_counter_start; link_counter<link_counter_length; link_counter++){
next_cursor+=(next_url_array[0][link_counter])
}
}
for the very first api But if you have more then two pages use the following code to seprate next link from previos and next flag
next_url = order.headers.link;
var next_url_array,
link_counter_start, link_counter_length,
link_counter;
if(next_url.includes(',')){
next_url = next_url.split(',');
next_url = next_url[1];
}
next_url = next_url.replace("<","");
next_url = next_url.replace(">", "");
next_url_array = next_url.split('; ');
link_counter_start = next_url_array[0].indexOf("page_info=")+10;
link_counter_length = (next_url_array[0].length);
next_cursor="";
for(link_counter=link_counter_start; link_counter<link_counter_length; link_counter++){
next_cursor+=(next_url_array[0][link_counter])
}
if(next_url_array[1] != 'rel="next"'){
flag = false;
}

Credit card number is garbled when testing Stripe.js in Mink

I am trying to use Behat/Mink to test Stripe on my Drupal site.
I have a Stripe testing payment gateway configured. My
My FeatureContext.php looks like this:
/**
* #Then I enter my US JCB credit card info
*/
public function iEnterMyUsJcbCreditCardInfo() {
$this->enterCardDetails('3566 0020 2036 0505', '11 / 21', '777');
}
private function enterCardDetails($card_number, $exp_date, $cvc) {
$this->getSession()->wait(2000);
// Switch to the payment iframe.
$this->getSession()->switchToIFrame(self::STRIPE_CARDNO_IFRAME);
$this->getSession()->wait(1000);
$this->fillField('cardnumber', "$card_number");
$this->getSession()->wait(2000);
I added the wait() because the credit card number is being filled out incorrectly.
For example, when I have the step And I enter my US JCB credit card info, then instead of the correct test card number (3566 0020 2036 0505), I get this: 3566 0000 3605 5022.
The incorrect card number is not consistent; when I re-ran the test three times, I got these numbers:
3566 0022 3005 5600
3566 0002 0360 5502
3566 0006 5500 3220
So it seems like something with stripe.js is interfering with my credit card number input.
The credit card expiration date and CVC/security code input do not have this problem.
When I eliminate the spaces in the credit card number, I still have the same problem (the number is randomly garbled during input).
Even when I set the wait time before and after card number input to 5 seconds each, the card number still gets garbled.
How can I input the credit card number in behat/mink without garbling the number?
I don't know anything about behat or mink, but I would suggest you remove the spaces; those all look like they contain the same numbers, just in different orders, so the spaces might be causing issues as the cursor might be moving around a bit.
Summary: You have to input the credit card number one digit at a time because Stripe.js will screw up the spacing if you try to input it all at once.
Here's the relevant code I've been using for the past couple weeks:
// Handle randomized iframe numbers by targeting the div above them.
const STRIPE_CARDNO_IFRAME = 'card-number-element';
const STRIPE_EXP_IFRAME = 'expiration-element';
const STRIPE_CVC_IFRAME = 'security-code-element';
/**
* #Then I enter my credit card number :cc_number
*/
public function iEnterMyCreditCardNumber($cc_number) {
$payment_errors_element = $this->getSession()->getPage()->find('css', 'div#payment-errors');
if ($payment_errors_element->getText()) {
throw new Exception($payment_errors_element->getText());
}
echo "Test credit card number: $cc_number\n";
$this->switchToMyIframe(self::STRIPE_CARDNO_IFRAME);
$this->getSession()->wait(5000);
$credit_card_field = $this->getSession()->getPage()->findField('cardnumber');
$cc_number_nospaces = str_replace(' ', '', "$cc_number");
$creditcard_singledigits = str_split("$cc_number_nospaces", 1);
foreach ($creditcard_singledigits as $creditcard_singledigit) {
$this->getSession()->wait(2000);
$credit_card_field->sendKeys("$creditcard_singledigit");
}
// Take a screenshot for debugging when the card number is entered incorrectly.
$this->saveScreenshot();
$this->getSession()->switchToIFrame(null);
}
/*
* Helper function to find the iframe.
*/
private function switchToMyIframe($selector) {
$iframe_selector = "div#$selector iframe";
$iframe = $this->getSession()->getPage()->find('css', $iframe_selector);
$iframe_name = $iframe->getAttribute('name');
echo "Switching to iframe $iframe_name\n";
$this->getSession()->switchToIFrame("$iframe_name");
}

How to create Prestashop product with custom attributes programatically?

Maybe some of you who uses prestashop core classes know how to create product with custom attributes? I mean add new product in prestashop system by creating script that uses prestashop class for this purpose programatically.
#Santo Boldižar
His code working fine.if you create new attribute programmatically use below code to add a new attribute and get $idProductAttribute
use PrestaShop\PrestaShop\Adapter\Import\ImportDataFormatter;
$newGroup = new AttributeGroup();
$newGroup->name = ImportDataFormatter::createMultiLangField('test');
$newGroup->public_name = ImportDataFormatter::createMultiLangField('test');
$newGroup->group_type = 'select';
$newGroup->add();
$newAttribute = new Attribute();
$newAttribute->name = ImportDataFormatter::createMultiLangField('test');
$newAttribute->id_attribute_group = $newGroup->id;
$newAttribute->add();
$idProductAttribute = $product->addProductAttribute($price,
$weight,
$unit_impact,
$ecotax,
$quantity,
$id_images,
$reference,
$id_supplier,
$ean13,
$default,
$location,
$upc,
$minimal_quantity,
$isbn,
$low_stock_threshold,
$low_stock_alert);
$product->addAttributeCombinaison($idProductAttribute, array($newAttribute->id_attribute_group));
This is working for me.
I created products with attributes in PrestaShop 1.7.5, here a part of my code.
First load the product:
$product = new \Product($productId);
Then, add an attribute to this product:
// The $data array contains all of the required data for an attribute.
$idProductAttribute = $product->addProductAttribute(
(float)$data['price'], // Product price (+/-) - If the base product price is 50 and you set here -5, the new price will be 45
(float)$data['weight'], // Product weight
$data['unit_impact'],
$data['ecotax'],
(int)$data['quantity'], // Products available in stock
$data['id_images'], // Image ids
$data['reference'],
strval($data['suppliers']),
strval($data['ean13']), // Barcode
$data['default'], // Default product or not (1/0)
$data['location'],
$data['upc'],
$data['minimal_quantity'], // Default 1
$data['isbn']
);
$product->addAttributeCombinaison($idProductAttribute, $data['attribute_ids']); // $data['attribute_ids'] - id(s) of existing attribute(s).
And voilá, you have a product with a new attribute.

Integration Quickbook online api to rails app

I am integrating
rails application to Quickbooks online
using API.
Use gem Quickbooks-ruby
But want to add discount, add taxes into invoice but not success even not found how to pass in API.
invoice = Quickbooks::Model::Invoice.new
invoice.customer_id = 1
invoice.txn_date = Date.civil(2014, 3, 27)
invoice.doc_number = "001"
transaction_tax = Quickbooks::Model::TransactionTaxDetail.new
# Point to a saved tax code in QBO, e.g. this points to id = 2,
# which is a NYC tax code saved on QBO account = 10% sales tax
transaction_tax.txn_tax_code_id = 2
transaction_tax.total_tax = 134.10
invoice.txn_tax_detail = transaction_tax
sales_line_item = Quickbooks::Model::InvoiceLineItem.new
sales_line_item.amount = 1490
sales_line_item.description = "CCM ice skates"
sales_line_item.sales_item! do |detail|
detail.unit_price = 149
detail.quantity = 10
detail.item_id = 1 # Item ID here
detail.tax_code_id = 'TAX' # for US must be 'NON' or 'TAX'
end
discount_line_item = Quickbooks::Model::InvoiceLineItem.new
discount_line_item.amount = 149
discount_line_item.discount_item! do |detail|
detail.discount_percent = 10
detail.percent_based = true
detail.discount_account_id = 99
end
invoice.line_items << sales_line_item
invoice.line_items << discount_line_item
service = Quickbooks::Service::Invoice.new
service.access_token = OAuth::AccessToken.new($qb_oauth_consumer, "token", "secret")
service.company_id = "9991111222"
created_invoice = service.create(invoice)
There should be something like JAXB in ruby for object serialization/deserialization.
From the following link, you can download QB endpoint definations and data class defination(as XSD). You need to generate data classes from it.
https://developer.intuit.com/docs/#api/deki/files/2466/v3.1_dataservices.zip
Then using any standard ruby based OAuth lib, you can make call to QB API Endpoints.
You can use the setter methods of the data class( in your case - invoice ) to populate data/to construct the payload. ( I don't have any ready example of this. But I guess it is not hard to find in net)
For doc, you can refer the following two links.
https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/030_entity_services_reference/invoice
https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/030_entity_services_reference/invoice#DiscountLineDetail
Thanks

PayPal classic API express checkout - tax issue

I am trying to create a payment using Express Checkout. it works fine if I don't include the TaxTotal. As soon as I do I get an error "Tax total is invalid".
var itemTotal = new BasicAmountType(Enum.GetValues(typeof(CurrencyCodeType)).Cast<CurrencyCodeType>().FirstOrDefault(t => t.ToString() == cart.Item.Currency.ToString()), cart.NetTotal.ToString());
var orderTotal = new BasicAmountType(Enum.GetValues(typeof(CurrencyCodeType)).Cast<CurrencyCodeType>().FirstOrDefault(t => t.ToString() == cart.Item.Currency.ToString()), cart.GrossTotal.ToString());
var taxTotal = new BasicAmountType(Enum.GetValues(typeof(CurrencyCodeType)).Cast<CurrencyCodeType>().FirstOrDefault(t => t.ToString() == cart.Item.Currency.ToString()), cart.TaxTotal.ToString());
paymentDetails.ItemTotal = itemTotal;
paymentDetails.OrderTotal = orderTotal;
paymentDetails.TaxTotal = taxTotal;
If I remove the ItemTotal and TaxTotal the payment processes fine, but I need to show the tax breakdown.
FYI, the amounts are, ItemTotal = 175, OrderTotal = 210, TaxTotal = 35.
Can anyone confirm what the problem is or what is missing from my code?
Thanks,
Andy
Try adding the decimals so it becomes 175.00. I would do that for all amount fields when using PayPal's API's.
If that doesn't work, post a copy of the actual request that you're sending so we can verify what is actually getting sent.
I solved the problem, it was similar to the solution suggested by Andrew.
I was using a decimal for the order total which was 210.000. I rounded this to 210.00 to knock a decimal off and it worked fine.