Updating shipping/tax info based on address

This commit is contained in:
Paul Driver 2010-04-29 17:35:43 -07:00
parent 0f69d4fdf0
commit 9a827affc4
2 changed files with 163 additions and 52 deletions

View file

@ -794,6 +794,57 @@ sub updateFromForm {
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 www_ajaxPrices
Input: shippingId (an addressId)
billingId (an addressId)
Output: {
tax : 1.25,
subtotal : 12.00,
shipping : {
slfjaldjfalfja: {
label : 'USPS',
price : 12.50,
hasPrice : 1 || 0
},
{ ... },
{ ... }
}
}
Takes an addressId and returns JSON shipping options for it, in the form .
=cut
sub www_ajaxPrices {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
my $billing = $form->get('billingId');
my $shipping = $form->get('shippingId');
my $response = {
subtotal => $self->calculateSubtotal(),
tax => eval {
my $addr = $shipping || $billing or die;
$self->update({ shippingAddressId => $addr });
$self->calculateTaxes();
} || 0,
shipping => eval {
die unless $shipping;
$self->update({ shippingAddressId => $shipping });
my $ship = WebGUI::Shop::Ship->new($self->session);
$ship->getOptions($self);
} || [],
};
$session->http->setMimeType('text/plain');
return JSON->new->encode($response);
}
#-------------------------------------------------------------------
=head2 www_continueShopping ( ) =head2 www_continueShopping ( )
Update the cart and the return the user back to the asset. Update the cart and the return the user back to the asset.
@ -1160,6 +1211,9 @@ sub www_view {
my $yui = $url->extras('/yui/build'); my $yui = $url->extras('/yui/build');
$style->setScript("$yui/yahoo/yahoo-min.js"); $style->setScript("$yui/yahoo/yahoo-min.js");
$style->setScript("$yui/json/json-min.js"); $style->setScript("$yui/json/json-min.js");
$style->setScript("$yui/event/event-min.js");
$style->setScript("$yui/connection/connection-min.js");
$style->setScript($url->extras('underscore/underscore-min.js'));
$style->setScript($url->extras('shop/cart.js'), undef, 1); $style->setScript($url->extras('shop/cart.js'), undef, 1);
return $session->style->userStyle($template->process(\%var)); return $session->style->userStyle($template->process(\%var));
} }

View file

@ -1,62 +1,120 @@
/*global window, document, YAHOO */ /*global _, window, document, YAHOO */
(function () { (function () {
var $event = YAHOO.util.Event, var $event = YAHOO.util.Event,
$connect = YAHOO.util.Connect, $connect = YAHOO.util.Connect,
$json = YAHOO.lang.JSON, $json = YAHOO.lang.JSON,
prices = null,
addressCache = {}, addressCache = {},
elements = { elements = {
dropdowns: { shipper : 'shipperId_formId',
billing: 'billingAddressId_formId', tax : 'taxWrap',
total : 'totalPriceWrap',
credit : {
available : 'inShopCreditAvailableWrap',
used : 'inShopCreditDeductionWrap'
},
dropdowns : {
billing : 'billingAddressId_formId',
shipping: 'shippingAddressId_formId' shipping: 'shippingAddressId_formId'
} }
}, },
addressParts = [ addressParts = [
'label', 'firstName', 'lastName', 'organization', 'address1', 'label', 'firstName', 'lastName', 'organization', 'address1',
'address2', 'address3', 'city', 'state', 'code', 'country', 'address2', 'address3', 'city', 'state', 'code', 'country',
'phoneNumber', 'email' 'phoneNumber', 'email'
]; ];
function omap(o, fn) { function formatCurrency(n) {
var r = [], k; return parseFloat(n.toString()).toFixed(2);
for (k in o) {
if (o.hasOwnProperty(k)) {
r.push(fn.call(o, k, o[k]));
}
}
return r;
}
function oeach(o, fn) {
omap(o, fn);
return;
} }
function addAddressKind(name) { function addAddressKind(name) {
var i, key, obj = elements[name] = {}; var obj = elements[name] = {};
for (i = 0; i < addressParts.length; i += 1) { _.each(addressParts, function (key) {
key = addressParts[i];
obj[key] = name + '_' + key + '_formId'; obj[key] = name + '_' + key + '_formId';
} });
} }
function getDomElements(o) { function getDomElements(o) {
oeach(o, function (k, v) { _.each(o, function (v, k) {
if (typeof v === 'object') { if (typeof v === 'object') {
getDomElements(v); getDomElements(v);
} }
else { else {
this[k] = document.getElementById(v); o[k] = document.getElementById(v);
} }
}); });
} }
function sameChange() { function sameChange() {
var d = elements.same.checked; var d = elements.same.checked;
oeach(elements.shipping, function (k, v) { _.each(elements.shipping, function (v, k) {
v.disabled = d; v.disabled = d;
}); });
elements.dropdowns.shipping.disabled = d; elements.dropdowns.shipping.disabled = d;
}
function calculateSummary() {
var shipping = prices.shipping[elements.shipper.value],
shipPrice = (shipping ?
(shipping.hasPrice ?
parseFloat(shipping.price) :
0)
: 0),
tax = parseFloat(prices.tax),
subtotal = parseFloat(prices.subtotal),
beforeCredit = tax + subtotal + shipPrice,
creditAvail = parseFloat(elements.credit.available.innerHTML),
creditUsed = Math.min(beforeCredit, creditAvail),
afterCredit = beforeCredit - creditUsed;
elements.credit.used.innerHTML = formatCurrency(creditUsed);
elements.total.innerHTML = formatCurrency(afterCredit);
}
function updatePrices() {
var selectedShipper = elements.shipper.value,
shipping = elements.dropdowns.shipping.value,
billing = elements.dropdowns.billing.value,
shipper = elements.shipper,
url = window.location.pathname +
'?shop=cart;method=ajaxPrices;' +
( shipping === 'new_address' ?
'' : 'shippingId=' + shipping) +
( billing === 'new_address' ?
'' : 'billingId=' + billing);
cb = {
success: function (o) {
var response = $json.parse(o.responseText);
if (response.error) {
return;
}
prices = response;
elements.tax.innerHTML = formatCurrency(response.tax);
_(shipper.options)
.chain()
.map(_.identity)
.each(function (o) {
if (o.value) {
o.parentNode.removeChild(o);
}
});
_.each(response.shipping, function (o, id) {
var opt = document.createElement('option'),
label = o.label;
if (o.hasPrice) {
label += ' (' + formatCurrency(o.price) + ')';
}
opt.innerHTML = label;
opt.value = id;
shipper.appendChild(opt);
});
shipper.value = selectedShipper;
calculateSummary();
}
};
$connect.asyncRequest('GET', url, cb);
} }
function updateAddressDropdowns(o) { function updateAddressDropdowns(o) {
@ -64,24 +122,22 @@
id = o.responseText; id = o.responseText;
function updateOne(dropdown) { function updateOne(dropdown) {
var options = dropdown.options, i, opt; var opt = _.detect(dropdown.options, function (o) {
for (i = 0; i < options.length; i += 1) { return o.text === label;
opt = options[i]; });
if (opt.text === label) {
opt.value = id;
return;
}
}
opt = document.createElement('option'); if (!opt) {
opt = document.createElement('option');
opt.text = label;
dropdown.appendChild(opt);
}
opt.value = id; opt.value = id;
opt.text = label;
dropdown.appendChild(opt);
} }
updateOne(elements.dropdowns.billing); updateOne(elements.dropdowns.billing);
updateOne(elements.dropdowns.shipping); updateOne(elements.dropdowns.shipping);
elements.dropdowns[o.argument.name].value = id; elements.dropdowns[o.argument.name].value = id;
updatePrices();
} }
function saveAddress(a, name) { function saveAddress(a, name) {
@ -89,7 +145,7 @@
success: updateAddressDropdowns, success: updateAddressDropdowns,
argument: { address: a, name: name } argument: { address: a, name: name }
}, },
post = 'shop=address;method=ajaxSave;address=' + post = 'shop=address;method=ajaxSave;address=' +
$json.stringify(a), $json.stringify(a),
url = window.location.pathname; url = window.location.pathname;
@ -97,13 +153,13 @@
} }
function validAddress(a) { function validAddress(a) {
return a.label && return a.label &&
a.firstName && a.firstName &&
a.lastName && a.lastName &&
a.address1 && a.address1 &&
a.city && a.city &&
a.state && a.state &&
a.code && a.code &&
a.country; a.country;
} }
@ -122,7 +178,7 @@
cached = addressCache[label] = {}; cached = addressCache[label] = {};
} }
oeach(elements[name], function (k, v) { _.each(elements[name], function (v, k) {
v = v.value; v = v.value;
address[k] = v; address[k] = v;
if (cached[k] !== v) { if (cached[k] !== v) {
@ -142,12 +198,13 @@
function addressUpdater(name) { function addressUpdater(name) {
var elems = elements[name]; var elems = elements[name];
function update(address) { function update(address) {
oeach(address, function (k, v) { _.each(address, function (v, k) {
var dom = elems[k]; var dom = elems[k];
if (dom) { if (dom) {
dom.value = v; dom.value = v;
} }
}); });
updatePrices();
} }
return function () { return function () {
var id = this.value, var id = this.value,
@ -159,8 +216,8 @@
return update(cached); return update(cached);
} }
url = window.location.pathname + url = window.location.pathname +
'?shop=address;method=ajaxGetAddress;addressId=' + '?shop=address;method=ajaxGetAddress;addressId=' +
id; id;
cb = { cb = {
@ -175,10 +232,7 @@
} }
function handleBlur(name) { function handleBlur(name) {
var values = omap(elements[name], function (k, v) { $event.on(_.values(elements[name]), 'focusout', addressChange(name));
return v;
});
$event.on(values, 'focusout', addressChange(name));
} }
function handleDropdown(name) { function handleDropdown(name) {
@ -207,6 +261,9 @@
else { else {
delete elements.shipping; delete elements.shipping;
} }
$event.on(elements.shipper, 'change', calculateSummary);
updatePrices();
} }
$event.onDOMReady(main); $event.onDOMReady(main);