Validate checkout field in Woocommerce without blocking user from proceeding with the order - validation

In Woocommerce I'm trying to do a validation check of the Address field in Woocommerce,
to warn customers in case they forgot to place their house or street numbers.
I am using the following snippet, which works for this exact validation and displays in real time a warning message below the field after the user clicks away from it, however there is an issue, as it forces the field to always have a number, and the point is simply to warn users but still allow them to progress with the order.
I am not sure how to proceed with this, as In my search I couldn't find anything related to "Not forcing" or making the validation check but still allowing customers to proceed with the order.
/**
* Add validation for street house adress: Verify if there is a number
*/
add_filter(
'woocommerce_default_address_fields', function( $fields ) {
unset( $fields['postcode']['custom_attributes']['data-parsley-length'] );
$fields['address_1']['custom_attributes']['data-parsley-pattern'] = '/^(?=.*\d).+$/';
$fields['address_1']['custom_attributes']['data-parsley-error-message'] = __( 'It seems your address has no street or door number', 'your-translation-domain' );
return $fields;
},
100001 );
Thank you in advance for the attention and advice.

Related

Laravel Validation Issue with Messages and Excludes

I have a validator I am trying to work through and I don't understand where I am going wrong.
$validator = Validator::make($request->all(), [
'birth_year'=>'exclude_if:type,parking|nullable',
'citation_number'=>'nullable|required_without:last_name',
'last_name'=>'exclude_if:type,parking|nullable|required_without:citation_number',
'issue_date'=>'exclude_unless:type,parking|required',
'type'=>'required',
],
[
'citation_number.required_without'=> trans('court-checkin.number_required'),
'last_name.required_without' => trans('court-checkin.last_name_required'),
'birth_year.exclude_if'=> trans('court-checkin.birth_year_required'),
'issue_date.required'=> trans('court-checkin.issue_date_required'),
],
);
So basically if the type is parking then only the citation number and issue_date are taken in, the others should be ignored.
But if it is anything else, then birth_year, last_name and citation_number are taken in, and citation_number and last_name are only required if the other isn't present.
But what is odd is that if I send the following:
citation_number "AU20-99999"
issue_date ""
type "parking"
I should only expect the issue date error, but all errors come back:
A citation or case file number is required.
A last name is required if a case or ticket number is not provided.
A birth year is required.
A citation date is required.
But if I add the issue_date, the validator passes it. Can anyone explain what I am missing?

Filtering Shipping Options In Woocommerce Based on Date

So, I have a complex Shipping issue I need to solve in woocommerce.
The three things I need to accomplish are:
Filter shipping methods based on a datepicker.
Reset the WC()->session->set('chosen_shipping_methods') with the lowest available shipping method after filtering based on the above date, AND THEN set the selected method as the $chosen_method.
Filter shipping methods based on price.
So, out of these three, #1 and #3 have been simple. I am firing off a $('body').trigger('update_checkout'); when a date is picked, and that sends it to the WC_AJAX->update_order_review method. This then recalculates all the relevant data/methods, and returns the snippets.
However, after filtering my shipping methods and trying to set the cheapest as the first one, AND change the session to match, i'm having problems. It seems that I'm not able to change the session value early enough to be calculated into the correct totals ON THE FIRST TRY. On the second ajax request or page refresh, the session gets set to the correct method.
So, how far up the stack do i need to be to reset that session to get it to listen to that new value on the first try? I need to be able to access the $_POST data, the current available methods, AND be able to reset the session all in one place if possible, but if not, I can run the same code in two places to hopefully get the correct checkout totals and methods set.
Currently, I've been working in cart-shipping.php and i've overwritten one of the functions there to apply some custom filtering, as seen below.
This accomplishes #1 and #3, but I have trouble with the session here. If anybody knows any way to reliably reset that session here, that'd solve all my problems.
function woo_new_cart_shipping_html()
{
global $woocommerce;
$data_stream = extract_data_from_str( $_POST['post_data'] );
$packages = $woocommerce->shipping->get_packages();
$chosen_method = isset( $woocommerce->session->chosen_shipping_methods[0] ) ? $woocommerce->session->chosen_shipping_methods[0] : '';
foreach ( $packages as $i => $package )
{
$methods = apply_filters( 'woo_filter_available_methods_by_date', $package['rates'], $data_stream );
wc_get_template( 'cart/cart-shipping.php', array('package' => $package,
'available_methods' => apply_filters( 'woo_sort_shipping_methods_by_cost', $methods ),
'show_package_details' => ( sizeof( $packages ) > 1 ),
'index' => $i,
'chosen_method' => apply_filters( 'woo_set_lowest_shipping_method', $chosen_method, $methods, $data_stream ) ) );
}
}

Sending POST data from Codeigniter controller

I am currently developing a small shopping cart where payment options are cash on delivery and other prepaid payment options using a payment gateway. Now my cart's flow chart is like
Places order,enters address
Selects payment options ( COD or Prepaid )
If COD confirm order
If prepaid, redirect to the payment gateway page
So when the customer selects an option , the controller function handlePayment() checks if its COD or Prepaid. If its COD it shows a view page, or if its prepaid, it should redirect to the payment gateway with all necessary data in POST.
So how will I be able to accomplish this task?
You have to write if COD then $this->view->load('pagename); else you have to call another function $this->functionname($_POST);
Try this, Its a rough assumption of what you need:
function handlePayment(){
if($this->input->post('type') == "COD"){
$data = array();
$data = $this->input->post(null);
$this->load->view('cod', $data);
}else if($this->input->post('type') == "prepaid"){
$data = array();
$data = $this->input->post(null);
$this->prepaidPayment($data);
}
}
function prepaidPayment($data){
//do something with the data which contains all the post variables
}
different angle -- can you ask them the COD or Prepaid question -- first?
and then make each 'path' completely separate.
Long term that could be better for your application especially if it grows.
and might help if you can do more stringent form validation on the Prepaid track,
( like if some of that information is used as part of the credit card validation )
versus COD where the payment happens in person

Magento abandoned cart for guest/unconfirmed users

In Magento abandoned cart only works for verified registered users. Is there a way to capture it for guest and unconfirmed users programmaticaly?
Also is there a way to email alert for the same?
Please tell me atleast where should I start on this. I found on a forum that with below SQL you can get all the abandoned carts, but I found some of them missing from there as well.
SELECT entity_id, customer_firstname, customer_email, items_count, grand_total, created_at
FROM sales_flat_quote
WHERE entity_id NOT IN (SELECT quote_item_id AS quote_id FROM sales_flat_order_item)
AND items_count >0
AND customer_email IS NOT NULL
ORDER BY `sales_flat_quote`.`created_at` DESC
I use a third party system for doing something like this. They cost but can be a valuable tool, especially if you have impulsive buy items. As the user is not logged in on the site, Magento can only store their basket as a quote using their session, so you are not able to get any details about the customer or the abandoned cart other than the contents of it.
If you are only interested in the items added to peoples abandoned baskets you can create custom SQL looking at the two tables you have identified in your example. Magento creates a quote for every cart which gets converted into an order when the customer purchases so the sales_quotes are table are where you need to start.
Regarding third party services, they normally involve having listeners on text boxes on the site such as email text box, name etc which post data using ajax when the field is modified. Good for capturing data during guest checkout if you have it enabled and the customer fails to finalize purchase. They do the same for add to cart buttons and start to build up a custom profile of the customer and the items in their cart as they use the site.
When somebody orders you then call another ajax request which tells the third party the customer has purchased, and those that it does not get this final request from is what it classifies as an abandoned cart. Most of these systems will email the customer after a set amount of time and days which you can define and you can normally send many emails at different time periods. You can normally also view all the abandoned carts and customer data that has been collected.
Magento's built in abandoned cart is ok for basic use but I wouldn't rely upon it. AFAIK it has no way of triggering emails for abandoned carts. E-Mail retargeting as described above can be very effective at re-capturing abandoned sales.
Have a look at somebody like exacttarget or search for magento email abandoned cart modules as I believe there are a few around that will plug and play with magento.
I was having same issue and able to solve it into magento 1.9.2 by following method:
Step-1:
Copy Collection.php file from
app/code/core/Mage/Reports/Model/Resource/Quote/
to
app/code/local/Mage/Reports/Model/Resource/Quote/
Step-2:
replace following code from line no: 194
$customerName = $adapter->getConcatSql(array('cust_fname.value', 'cust_mname.value', 'cust_lname.value',), ' ');
$this->getSelect()
->joinInner(
array('cust_email' => $attrEmailTableName),
'cust_email.entity_id = main_table.customer_id',
array('email' => 'cust_email.email')
)
->joinInner(
array('cust_fname' => $attrFirstnameTableName),
implode(' AND ', array(
'cust_fname.entity_id = main_table.customer_id',
$adapter->quoteInto('cust_fname.attribute_id = ?', (int) $attrFirstnameId),
)),
array('firstname' => 'cust_fname.value')
)
->joinInner(
array('cust_mname' => $attrMiddlenameTableName),
implode(' AND ', array(
'cust_mname.entity_id = main_table.customer_id',
$adapter->quoteInto('cust_mname.attribute_id = ?', (int) $attrMiddlenameId),
)),
array('middlename' => 'cust_mname.value')
)
->joinInner(
array('cust_lname' => $attrLastnameTableName),
implode(' AND ', array(
'cust_lname.entity_id = main_table.customer_id',
$adapter->quoteInto('cust_lname.attribute_id = ?', (int) $attrLastnameId)
)),
array(
'lastname' => 'cust_lname.value',
'customer_name' => $customerName
)
);
$this->_joinedFields['customer_name'] = $customerName;
$this->_joinedFields['email'] = 'cust_email.email';
with
$customerName = $adapter->getConcatSql(array('main_table.customer_firstname', 'main_table.customer_middlename', 'main_table.customer_lastname',), ' ');
$this->getSelect()
->columns(
array(
'email' => new Zend_Db_Expr('main_table.customer_email'),
'firstname' => new Zend_Db_Expr('main_table.customer_firstname'),
'middlename' => new Zend_Db_Expr('main_table.customer_middlename'),
'lastname' => new Zend_Db_Expr('main_table.customer_lastname'),
'customer_name' => $customerName
)
)
->where('main_table.customer_email IS NOT NULL');
$this->_joinedFields['customer_name'] = $customerName;
$this->_joinedFields['email'] = 'main_table.customer_email';
You can load cart for a guest if you know quote id. Try the following code:
$quote = Mage::getModel('sales/quote')->loadByIdWithoutStore($quoteId);
if ($quote) {
Mage::getSingleton('checkout/session')->setQuoteId($quoteId);
Mage::getSingleton('checkout/cart')->setQuote($quote);
}

getRate() and Magento tax percentage

I'm trying to get the tax rate (percentage, not currency) for a given postcode so I can display it in a third-party quote PDF printout (no relation to the "quote" Magento uses as the shopping cart pre-checkout). While I'm still relatively new to Magento it appears that getRateRequest() and getRate() are the two main functions which get the tax rate based on all the variables (product tax class, customer tax class, etc.).
Since this is for a third-party extension and all our products are taxable I figured I would just use getRate() with the correct Varien Object input and it would return the tax rate. After a week of trial and error I can't figure out why I'm always getting a rate of zero. I've confirmed I'm calling the getRate() function and that it's not returning zero from the first if() statement checking for Country and Customer/Product class ID. In addition I've confirmed all the variables are being passed on and accessible in the getRate() function itself.
I've created an object with the below input (based on the output of getRateRequest()) that I call with getRate() and am hoping someone can shed light on what is wrong with my data input or why the getRate() function is always returning a result of zero. (I'm actually setting with $variables below, they are just defined earlier up and one of my test case values are below)
// UPDATED CODE (variable values come from 3rd party quote extension)
$country = 'US'; // use short country code
$region = '12'; // must be numeric!
$postcode = '95050';
// our quote extension stores the customer id ('2') which we use to get the tax class
$customer = Mage::getModel('customer/customer')->load( '2' );
$custTax = $customer->getTaxClassId();
$TaxRequest = new Varien_Object();
$TaxRequest->setCountryId( $country );
$TaxRequest->setRegionId( $region );
$TaxRequest->setPostcode( $postcode );
$TaxRequest->setStore( Mage::app()->getStore() );
$TaxRequest->setCustomerClassId( $custTax );
$TaxRequest->setProductClassId(2); // 2=taxable id (all our products are taxable)
$taxCalculationModel = Mage::getSingleton('tax/calculation');
$rate = $taxCalculationModel->getRate($TaxRequest);
My backup plan is to just do a direct SQL lookup formula although that will probably get a bit messy. Since our web development team didn't exactly follow good coding standards an eventual site re-write is in my future anyway once the initial launch fixes are in (all 4 pages of them).
Thanks for any help and taking the time to read this.
EDIT - Stack Overflow is awesome :)
You can also try this
$store = Mage::app()->getStore('default');
$request = Mage::getSingleton('tax/calculation')->getRateRequest(null, null, null, $store);
$taxclassid = $product->getData('tax_class_id');
$percent = Mage::getSingleton('tax/calculation')->getRate($request->setProductClassId($taxclassid));
If you change:
$TaxRequest->setRegionId(California);
to
$TaxRequest->setRegionId($stateId);
where $stateId is numeric region id. Your code should work then.

Resources