Files
edx-platform/lms/static/js/commerce/views/receipt_view.js
Clinton Blackburn 9bb3f703d7 Updated receipt page to use order endpoint
The receipt page now retrieves data for orders instead of baskets. Going forward baskets will be deleted after an order has been placed, so there should be no permanent references to baskets. Orders will continue to be persisted permanently.

ECOM-2653
2015-10-28 12:12:57 -04:00

320 lines
11 KiB
JavaScript

/**
* View for the receipt page.
*/
var edx = edx || {};
(function ($, _, _s, Backbone) {
'use strict';
edx.commerce = edx.commerce || {};
edx.commerce.ReceiptView = Backbone.View.extend({
useEcommerceApi: true,
ecommerceBasketId: null,
ecommerceOrderNumber: null,
initialize: function () {
this.ecommerceBasketId = $.url('?basket_id');
this.ecommerceOrderNumber = $.url('?orderNum');
this.useEcommerceApi = this.ecommerceBasketId || this.ecommerceOrderNumber;
_.bindAll(this, 'renderReceipt', 'renderError', 'getProviderData', 'renderProvider', 'getCourseData');
/* Mix non-conflicting functions from underscore.string (all but include, contains, and reverse) into
* the Underscore namespace.
*/
_.mixin(_s.exports());
this.render();
},
renderReceipt: function (data) {
var templateHtml = $("#receipt-tpl").html(),
context = {
platformName: this.$el.data('platform-name'),
verified: this.$el.data('verified').toLowerCase() === 'true'
},
providerId;
// Add the receipt info to the template context
this.courseKey = this.getOrderCourseKey(data);
this.username = this.$el.data('username');
_.extend(context, {
receipt: this.receiptContext(data),
courseKey: this.courseKey
});
this.$el.html(_.template(templateHtml, context));
this.trackLinks();
this.renderCourseNamePlaceholder(this.courseKey);
providerId = this.getCreditProviderId(data);
if (providerId) {
this.getProviderData(providerId).then(this.renderProvider, this.renderError)
}
},
renderCourseNamePlaceholder: function (courseId) {
// Display the course Id or name (if available) in the placeholder
var $courseNamePlaceholder = $(".course_name_placeholder");
$courseNamePlaceholder.text(courseId);
this.getCourseData(courseId).then(function (responseData) {
$courseNamePlaceholder.text(responseData.name);
});
},
renderProvider: function (context) {
var templateHtml = $("#provider-tpl").html(),
providerDiv = this.$el.find("#receipt-provider");
context.course_key = this.courseKey;
context.username = this.username;
context.platformName = this.$el.data('platform-name');
providerDiv.html(_.template(templateHtml, context)).removeClass('hidden');
},
renderError: function () {
// Display an error
$('#error-container').removeClass('hidden');
},
render: function () {
var self = this,
orderId = this.ecommerceOrderNumber || this.ecommerceBasketId || $.url('?payment-order-num');
if (orderId && this.$el.data('is-payment-complete') === 'True') {
// Get the order details
self.$el.removeClass('hidden');
self.getReceiptData(orderId).then(self.renderReceipt, self.renderError);
} else {
self.renderError();
}
},
trackLinks: function () {
var $verifyNowButton = $('#verify_now_button'),
$verifyLaterButton = $('#verify_later_button');
// Track a virtual pageview, for easy funnel reconstruction.
window.analytics.page('payment', 'receipt');
// Track the user's decision to verify immediately
window.analytics.trackLink($verifyNowButton, 'edx.bi.user.verification.immediate', {
category: 'verification'
});
// Track the user's decision to defer their verification
window.analytics.trackLink($verifyLaterButton, 'edx.bi.user.verification.deferred', {
category: 'verification'
});
},
/**
* Retrieve receipt data from Oscar (via LMS).
* @param {string} orderId Identifier of the order that was purchased.
* @return {object} JQuery Promise.
*/
getReceiptData: function (orderId) {
var urlFormat = '/shoppingcart/receipt/%s/';
if (this.ecommerceOrderNumber) {
urlFormat = '/api/commerce/v1/orders/%s/';
} else if (this.ecommerceBasketId){
urlFormat = '/api/commerce/v0/baskets/%s/order/';
}
return $.ajax({
url: _.sprintf(urlFormat, orderId),
type: 'GET',
dataType: 'json'
}).retry({times: 5, timeout: 2000, statusCodes: [404]});
},
/**
* Retrieve credit provider data from LMS.
* @param {string} providerId The providerId of the credit provider.
* @return {object} JQuery Promise.
*/
getProviderData: function (providerId) {
var providerUrl = '/api/credit/v1/providers/%s/';
return $.ajax({
url: _.sprintf(providerUrl, providerId),
type: 'GET',
dataType: 'json'
}).retry({times: 5, timeout: 2000, statusCodes: [404]});
},
/**
* Retrieve course data from LMS.
* @param {string} courseId The courseId of the course.
* @return {object} JQuery Promise.
*/
getCourseData: function (courseId) {
var courseDetailUrl = '/api/course_structure/v0/courses/%s/';
return $.ajax({
url: _.sprintf(courseDetailUrl, courseId),
type: 'GET',
dataType: 'json'
});
},
/**
* Construct the template context from data received
* from the E-Commerce API.
*
* @param {object} order Receipt data received from the server
* @return {object} Receipt template context.
*/
receiptContext: function (order) {
var self = this,
receiptContext;
if (this.useEcommerceApi) {
receiptContext = {
orderNum: order.number,
currency: order.currency,
purchasedDatetime: order.date_placed,
totalCost: self.formatMoney(order.total_excl_tax),
isRefunded: false,
items: [],
billedTo: null
};
if (order.billing_address) {
receiptContext.billedTo = {
firstName: order.billing_address.first_name,
lastName: order.billing_address.last_name,
city: order.billing_address.city,
state: order.billing_address.state,
postalCode: order.billing_address.postcode,
country: order.billing_address.country
}
}
receiptContext.items = _.map(
order.lines,
function (line) {
return {
lineDescription: line.description,
cost: self.formatMoney(line.line_price_excl_tax)
};
}
);
} else {
receiptContext = {
orderNum: order.orderNum,
currency: order.currency,
purchasedDatetime: order.purchase_datetime,
totalCost: self.formatMoney(order.total_cost),
isRefunded: order.status === "refunded",
billedTo: {
firstName: order.billed_to.first_name,
lastName: order.billed_to.last_name,
city: order.billed_to.city,
state: order.billed_to.state,
postalCode: order.billed_to.postal_code,
country: order.billed_to.country
},
items: []
};
receiptContext.items = _.map(
order.items,
function (item) {
return {
lineDescription: item.line_desc,
cost: self.formatMoney(item.line_cost)
};
}
);
}
return receiptContext;
},
getOrderCourseKey: function (order) {
var length, items;
if (this.useEcommerceApi) {
length = order.lines.length;
for (var i = 0; i < length; i++) {
var line = order.lines[i],
attributeValues = _.find(line.product.attribute_values, function (attribute) {
return attribute.name === 'course_key'
});
// This method assumes that all items in the order are related to a single course.
if (attributeValues != undefined) {
return attributeValues['value'];
}
}
} else {
items = _.filter(order.items, function (item) {
return item.course_key;
});
if (items.length > 0) {
return items[0].course_key;
}
}
return null;
},
formatMoney: function (moneyStr) {
return Number(moneyStr).toFixed(2);
},
/**
* Check whether the payment is for the credit course or not.
*
* @param {object} order Receipt data received from the server
* @return {string} String of the provider_id or null.
*/
getCreditProviderId: function (order) {
var attributeValues,
line = order.lines[0];
if (this.useEcommerceApi) {
attributeValues = _.find(line.product.attribute_values, function (attribute) {
return attribute.name === 'credit_provider';
});
// This method assumes that all items in the order are related to a single course.
if (attributeValues != undefined) {
return attributeValues['value'];
}
}
return null;
}
});
new edx.commerce.ReceiptView({
el: $('#receipt-container')
});
})(jQuery, _, _.str, Backbone);
function completeOrder(event) { // jshint ignore:line
var courseKey = $(event).data("course-key"),
username = $(event).data("username"),
providerId = $(event).data("provider"),
$errorContainer = $("#error-container");
try {
event.preventDefault();
} catch (err) {
// Ignore the error as not all event inputs have the preventDefault method.
}
analytics.track(
"edx.bi.credit.clicked_complete_credit",
{
category: "credit",
label: courseKey
}
);
edx.commerce.credit.createCreditRequest(providerId, courseKey, username).fail(function () {
$errorContainer.removeClass("hidden");
});
}