Commit 9d6489ef by Vedran Karacic

Invoice data validation; required field asteriks; routing of external links;…

Invoice data validation; required field asteriks; routing of external links; render invoice data on coupon details page.
parent 6c5f20ef
......@@ -62,13 +62,29 @@ define([
}
},
quantity: {pattern: 'number'},
price: {pattern: 'number'},
benefit_value: {
pattern: 'number',
required: function () {
return this.get('coupon_type') === 'Discount code';
}
},
invoice_type: {required: true},
invoice_number: {
required: function() {
return this.isPrepaidInvoiceType();
}
},
price: {
pattern: 'number',
required: function() {
return this.isPrepaidInvoiceType();
}
},
invoice_payment_date: {
required: function() {
return this.isPrepaidInvoiceType();
}
},
invoice_discount_value: {
pattern: 'number',
required: function () {
......@@ -130,6 +146,10 @@ define([
this.on('change:payment_information', this.updatePaymentInformation);
},
isPrepaidInvoiceType: function() {
return this.get('invoice_type') === 'Prepaid';
},
/**
* When user selects the 'Single use' limitation option set quantity to '1'.
*/
......
......@@ -178,7 +178,8 @@ define([], function(){
seat_type: 'verified',
course: verifiedSeat,
price: 100,
category: 4
category: 4,
invoice_type: 'Not-Applicable'
},
enrollmentCodeCouponData = {
'id': 10,
......
......@@ -84,6 +84,22 @@ define([
model.validate();
expect(model.isValid()).toBeTruthy();
});
it('should validate invoice data.', function() {
model.set('price', 'text');
model.validate();
expect(model.isValid()).toBeFalsy();
model.set('price', 100);
model.validate();
expect(model.isValid()).toBeTruthy();
model.set('invoice_discount_value', 'text');
model.validate();
expect(model.isValid()).toBeFalsy();
model.set('invoice_discount_value', 100);
model.validate();
expect(model.isValid()).toBeTruthy();
});
});
describe('test model methods', function () {
......
......@@ -30,18 +30,19 @@ define([
it('should throw an error if submitted with blank fields', function () {
var errorHTML = '<strong>Error!</strong> You must complete all required fields.';
view.formView.submit($.Event('click'));
expect(view.$el.find('.alert').length).toBe(1);
expect(view.$el.find('.alert').html()).toBe(errorHTML);
expect(view.$('.alert').length).toBe(1);
expect(view.$('.alert').html()).toBe(errorHTML);
});
it('should submit form with valid fields', function () {
view.$el.find('[name=title]').val('Test Enrollment').trigger('change');
view.$el.find('[name=code_type]').val('enrollment').trigger('change');
view.$el.find('[name=client]').val('test_client').trigger('change');
view.$el.find('[name=start_date]').val('2015-01-01T00:00').trigger('change');
view.$el.find('[name=end_date]').val('2016-01-01T00:00').trigger('change');
view.$el.find('[name=price]').val('100').trigger('change');
view.$el.find('[name=category]').val('4').trigger('change');
view.$('[name=title]').val('Test Enrollment').trigger('change');
view.$('[name=code_type]').val('enrollment').trigger('change');
view.$('[name=client]').val('test_client').trigger('change');
view.$('[name=start_date]').val('2015-01-01T00:00').trigger('change');
view.$('[name=end_date]').val('2016-01-01T00:00').trigger('change');
view.$('[name=price]').val('100').trigger('change');
view.$('[name=category]').val('4').trigger('change');
view.$('#not-applicable').prop('checked', true).trigger('change');
spyOn(view.formView, 'fillFromCourse').and.callFake(function () {
var seatTypes = [$('<option></option>')
.text('Verified')
......@@ -50,12 +51,12 @@ define([
price: '100',
stockrecords: [1]
})];
this.$el.find('[name=seat_type]')
this.$('[name=seat_type]')
.html(seatTypes)
.trigger('change');
});
view.formView.delegateEvents();
view.$el.find('[name=course_id]').val('course-v1:edX+DemoX+Demo_Course').trigger('input');
view.$('[name=course_id]').val('course-v1:edX+DemoX+Demo_Course').trigger('input');
view.formView.submit($.Event('click'));
expect(model.isValid()).toBe(true);
expect(model.save).toHaveBeenCalled();
......
......@@ -86,7 +86,6 @@ define([
});
});
describe('enrollment code', function () {
beforeEach(function () {
view.$el.find('[name=code_type]').val('enrollment').trigger('change');
......@@ -102,6 +101,16 @@ define([
});
});
describe('routing', function() {
it('should route to external link.', function() {
var href = 'http://www.google.com/';
spyOn(window, 'open');
view.$el.append('<a href="' + href + '" class="test external-link">Google</a>');
view.$('.test.external-link').click();
expect(window.open).toHaveBeenCalledWith(href);
});
});
describe('discount code', function () {
var prepaid_invoice_fields = [
'[name=invoice_number]',
......
......@@ -149,6 +149,7 @@ define([
this.$el.html(html);
this.renderVoucherTable();
this.renderCourseData();
this.renderInvoiceData();
this.delegateEvents();
this.dynamic_catalog_view = new DynamicCatalogView({
......@@ -204,6 +205,48 @@ define([
return this;
},
renderInvoiceData: function() {
var invoice_type = this.model.get('invoice_type'),
tax_deducted = this.model.get('tax_deduction'),
prepaid_fields = [
'.invoice-number',
'.invoiced-amount',
'.invoice-payment-date'
],
postpaid_fields = [
'.invoice-discount-type',
'.invoice-discount-value'
];
if (tax_deducted === 'Yes') {
this.$('.tax-deducted-source-value').removeClass('hidden');
} else if (tax_deducted === 'No') {
this.$('.tax-deducted-source-value').addClass('hidden');
}
if (invoice_type === 'Prepaid') {
_.each(prepaid_fields, function(field) {
this.$(field).removeClass('hidden');
}, this);
_.each(postpaid_fields, function(field) {
this.$(field).addClass('hidden');
}, this);
} else if (invoice_type === 'Postpaid') {
_.each(prepaid_fields, function(field) {
this.$(field).addClass('hidden');
}, this);
_.each(postpaid_fields, function(field) {
this.$(field).removeClass('hidden');
}, this);
} else if (invoice_type === 'Not-Applicable') {
_.each(prepaid_fields, function(field) {
this.$(field).addClass('hidden');
}, this);
_.each(postpaid_fields, function(field) {
this.$(field).addClass('hidden');
}, this);
}
},
downloadCouponReport: function (event) {
var url = _s.sprintf('/api/v2/coupons/coupon_reports/%d', this.model.id);
......
......@@ -217,7 +217,8 @@ define([
'change [name=benefit_type]': 'changeLimitForBenefitValue',
'change [name=invoice_discount_type]': 'changeLimitForInvoiceDiscountValue',
'change [name=invoice_type]': 'toggleInvoiceFields',
'change [name=tax_deduction]': 'toggleTaxDeductedSourceField'
'change [name=tax_deduction]': 'toggleTaxDeductedSourceField',
'click .external-link': 'routeToLink'
},
initialize: function (options) {
......@@ -330,8 +331,9 @@ define([
}, this);
this.hideField('[name=price]', 0);
this.hideField('[name=invoice_discount_value]', null);
this.hideField('[name=tax_deducted_value]', null);
this.formGroup('[name=tax_deduction]').addClass(this.hiddenClass);
this.hideField('[name=tax_deducted_source_value]', null);
this.$('#non-tax-deducted').prop('checked', true).trigger('change');
this.hideField('[name=tax_deduction]', null);
}
},
......@@ -500,6 +502,15 @@ define([
this.dynamic_catalog_view.seat_types = this.model.get('course_seat_types');
},
/* Open external links in a new tab.
* Works only for anchor elements that contain 'external-link' class.
*/
routeToLink: function(e) {
e.preventDefault();
e.stopPropagation();
window.open(e.currentTarget.href);
},
render: function () {
// Render the parent form/template
this.$el.html(this.template(this.model.attributes));
......
......@@ -85,7 +85,7 @@
<hr>
<div class="form-group">
<label><%= gettext('Invoice Type') %></label>
<label><%= gettext('Invoice Type') %> *</label>
<div class="invoice-type row">
<div class="form-inline col-md-4">
<input id="already-invoiced" type="radio" name="invoice_type" value="Prepaid">
......@@ -103,13 +103,13 @@
</div>
<div class="form-group">
<label for="invoice-number"><%= gettext('Invoice Number') %></label>
<label for="invoice-number"><%= gettext('Invoice Number') %> *</label>
<input id="invoice-number" class="form-control" type="text" name="invoice_number">
<p class="help-block"></p>
</div>
<div class="form-group">
<label for="price"><%= gettext('Invoiced Amount') %></label>
<label for="price"><%= gettext('Invoiced Amount') %> *</label>
<div class="input-group">
<div class="input-group-addon">$</div>
<input id="price" type="number" step="0.01" min="0" class="form-control" name="price">
......@@ -118,7 +118,7 @@
</div>
<div class="form-group">
<label for="invoice-payment-date"><%= gettext('Payment Date') %></label>
<label for="invoice-payment-date"><%= gettext('Payment Date') %> *</label>
<div class="input-group">
<div class="input-group-addon"><span class="fa fa-calendar" aria-hidden="true"></span></div>
<input id="invoice-payment-date" placeholder="<%- gettext('YYYY-MM-DDTHH:mm:ss') %>" class="form-control add-pikaday" name="invoice_payment_date">
......@@ -127,7 +127,7 @@
</div>
<div class="form-group hidden">
<label for="invoice-discount-value"><%= gettext('Discount per Code') %></label>
<label for="invoice-discount-value"><%= gettext('Discount per Code') %> *</label>
<div class="input-group">
<div class="invoice-discount-addon input-group-addon"></div>
<input id="invoice-discount-value" type="number" step="0.01" class="form-control invoice-discount-value" name="invoice_discount_value">
......@@ -155,8 +155,8 @@
<div class="input-group tax-deducted-source-value">
<input id="tax-deducted-source-value" type="number" step="1" min="1" max="100" class="form-control" name="tax_deducted_source_value">
<div class="input-group-addon">%</div>
<p class="help-block"></p>
</div>
<p class="help-block"></p>
</div>
</div>
......@@ -181,7 +181,7 @@
<p class="help-block"></p>
</div>
<div class="form-group catalog-query">
<label for="catalog-query"><%= gettext('Query string:') %> * <a href="https://stage-edx-discovery.edx.org/" class="normal-font-weight">(query guidelines)</a></label>
<label for="catalog-query"><%= gettext('Query string:') %> * <a href="https://stage-edx-discovery.edx.org/" class="external-link normal-font-weight">(query guidelines)</a></label>
<textarea id="catalog-query" class="form-control" name="catalog_query" rows="10"></textarea>
<p class="help-block"></p>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment