Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release-2021-01-29 #6

Merged
merged 5 commits into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2021-01-27 13:22
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('catalogue', '0036_coupon_notify_email_attribute'),
('basket', '0012_basketchallanvoucher'),
]

operations = [
migrations.AddField(
model_name='basketchallanvoucher',
name='product',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='catalogue.Product', verbose_name='Product'),
),
]
8 changes: 8 additions & 0 deletions ecommerce/extensions/basket/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,15 @@ class Meta(object):


class BasketChallanVoucher(TimeStampedModel):
"""
Used to record the challan form created for a lumsxpay payment processor,
voucher is created through lumsx payment API and its code is stored in voucher__number
cron job is run over certain time that will update the pending orders.
model used in payment > views > lumsxpay view
"""
basket = models.ForeignKey('basket.Basket', verbose_name=_("Basket"), on_delete=models.CASCADE)
product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"), null=True)
voucher_number = models.CharField(max_length=32, unique=True)
is_paid = models.BooleanField(default=False, null=False)
due_date = models.DateTimeField(null=False)

47 changes: 19 additions & 28 deletions ecommerce/extensions/payment/views/lumsxpay.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import datetime

from django.contrib.auth.views import redirect_to_login
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import transaction
from django.http import HttpResponseNotFound
from django.shortcuts import render_to_response
Expand All @@ -26,7 +27,7 @@
Product = get_model('catalogue', 'Product')


class LumsxpayExecutionView(EdxOrderPlacementMixin, View):
class LumsxpayExecutionView(LoginRequiredMixin, EdxOrderPlacementMixin, View):
@property
def payment_processor(self):
return Lumsxpay(self.request.site)
Expand All @@ -44,16 +45,11 @@ def extract_items_from_basket(self, basket):
for l in basket.all_lines()
]

def get_existing_basket(self, request):
courses = [i['id'] for i in self.extract_items_from_basket(request.basket)]
course_ids = []
def get_existing_basket_challan(self, request):
basket = request.basket
product = basket.lines.first().product

for course in courses:
product = Product.objects.filter(structure='child', course_id=course).first()
if product:
course_ids.append(product.id)

return Basket.objects.filter(owner_id=request.user, lines__product_id__in=course_ids).first()
return BasketChallanVoucher.objects.filter(basket=basket, product=product)

def get_due_date(self, configuration_helpers):
due_date_span_in_weeks = configuration_helpers.get('PAYMENT_DUE_DATE_SPAN', 52)
Expand All @@ -79,11 +75,9 @@ def fetch_context(self, request, response, configuration_helpers):
"support_email": request.site.siteconfiguration.payment_support_email,
}

def request_already_existing_challan(self, request):
challan_basket = BasketChallanVoucher.objects.filter(basket=self.get_existing_basket(request)).first()

def request_existing_challan_context(self, request, basket_challan):
configuration_helpers = request.site.siteconfiguration.edly_client_theme_branding_settings
url = '{}/{}'.format(configuration_helpers.get('LUMSXPAY_VOUCHER_API_URL'), challan_basket.voucher_number)
url = '{}/{}'.format(configuration_helpers.get('LUMSXPAY_VOUCHER_API_URL'), basket_challan.voucher_number)
headers = {
"Authorization": configuration_helpers.get('PAYMENT_AUTHORIZATION_KEY'),
"Content-Type": "application/json"
Expand All @@ -96,32 +90,28 @@ def request_already_existing_challan(self, request):
return {}

def get(self, request):
basket = request.basket
configuration_helpers = request.site.siteconfiguration.edly_client_theme_branding_settings
url = configuration_helpers.get('LUMSXPAY_VOUCHER_API_URL')

if request.user.is_anonymous or not (url and request.basket):
msg = 'user is anonymous cannot proceed to checkout page so redirecting to login. '
if not url:
msg = 'LUMSXPAY_VOUCHER_API_URL is not defined in site configurations'
logger.info(msg)

if not url:
msg = 'Site configuration in ecommerce does not include payment API url'
logger.info(msg)

return redirect_to_login(get_lms_dashboard_url)

if BasketChallanVoucher.objects.filter(basket=self.get_existing_basket(request)).exists():
context = self.request_already_existing_challan(request)
existing_basket_challan = self.get_existing_basket_challan(request)
if existing_basket_challan.exists():
context = self.request_existing_challan_context(request, existing_basket_challan.first())
if not context:
logger.exception('challan status API not working, no context found')
return HttpResponseNotFound()

return render_to_response('payment/lumsxpay.html', context)

items = self.extract_items_from_basket(request.basket)
items = self.extract_items_from_basket(basket)
payload = {
"name": request.user.username,
"email": request.user.email,
"order_id": request.basket.order_number,
"order_id": basket.order_number,
"items": items,
"due_date": self.get_due_date(configuration_helpers)
}
Expand All @@ -145,10 +135,11 @@ def get(self, request):
due_date = voucher_details['data']['due_date']

_, created = BasketChallanVoucher.objects.get_or_create(
basket=request.basket,
basket=basket,
voucher_number=voucher_number,
due_date=due_date,
is_paid=False
is_paid=False,
product=basket.lines.first().product
)

if created:
Expand Down
3 changes: 3 additions & 0 deletions ecommerce/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,3 +745,6 @@
EDLY_USER_INFO_COOKIE_NAME = 'edly-user-info'
EDLY_COOKIE_SECRET_KEY = 'EDLY-COOKIE-SECRET-KEY'
EDLY_JWT_ALGORITHM = 'HS256'

OSCAR_DEFAULT_CURRENCY = 'PKR'
OSCAR_DEFAULT_CURRENCY_SYMBOL = 'Rs.'
4 changes: 4 additions & 0 deletions ecommerce/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,7 @@ def get_env_setting(setting):

# Edly configuration
EDLY_COOKIE_SECRET_KEY = config_from_yaml.get('EDLY_COOKIE_SECRET_KEY', EDLY_COOKIE_SECRET_KEY)

# Currency
OSCAR_DEFAULT_CURRENCY = config_from_yaml.get('OSCAR_DEFAULT_CURRENCY', OSCAR_DEFAULT_CURRENCY)
OSCAR_DEFAULT_CURRENCY_SYMBOL = config_from_yaml.get('OSCAR_DEFAULT_CURRENCY_SYMBOL', OSCAR_DEFAULT_CURRENCY_SYMBOL)
26 changes: 14 additions & 12 deletions ecommerce/static/js/pages/basket_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,35 +266,37 @@ define([
disclaimerPrefix;

// when the price value has a USD prefix, replace it with a $
price = price.replace('USD', '$');
price = price.replace(currency, currency_symbol);
disclaimerPrefix = '* This total contains an approximate conversion. You will be charged ';

if (BasketPage.isValidLocalCurrencyCookie(countryData) && countryData.countryCode !== 'USA') {
$('<span>').attr('class', 'price-disclaimer')
.text(gettext(disclaimerPrefix) + price + ' USD.')
.text(gettext(disclaimerPrefix) + price + ' '+ currency +'.')
.appendTo('div[aria-labelledby="order-details-region"]');
}
},

formatToLocalPrice: function(prefix, priceInUsd) {
formatToLocalPrice: function(prefix, priceInDefaultCurrency) {
var countryData = Cookies.getJSON('edx-price-l10n'),
parsedPriceInUsd;
parsedPriceInDefaultCurrency;

// Default to USD when the exchange rate cookie doesn't exist
// Use default currency when the exchange rate cookie doesn't exist
if (BasketPage.isValidLocalCurrencyCookie(countryData) && countryData.countryCode !== 'USA') {
// assumes all formatted prices have a comma every three places
parsedPriceInUsd = parseFloat(priceInUsd.replace(',', ''));
return countryData.symbol + Math.round(parsedPriceInUsd * countryData.rate).toLocaleString() + ' '
parsedPriceInDefaultCurrency = parseFloat(priceInDefaultCurrency.replace(',', ''));
return countryData.symbol + Math.round(parsedPriceInDefaultCurrency * countryData.rate).toLocaleString() + ' '
+ countryData.code + ' *';
} else {
return prefix + priceInUsd;
return prefix + priceInDefaultCurrency;
}
},

generateLocalPriceText: function(usdPriceText) {
// Assumes price value is prefixed by $ or USD with optional sign followed by optional string
var localPriceText = usdPriceText,
prefixMatch = localPriceText.match(/(\$|USD)?(([1-9][0-9]{0,2}(,[0-9]{3})*)|[0-9]+)?\.[0-9]{1,2}/),
generateLocalPriceText: function(defaultCurrencyPriceText) {
// Assumes price value is prefixed by currency symbol i.e. $
// or by currency i.e USD with optional sign followed by optional string
var re = new RegExp('(\\' + currency_symbol + '|' + currency + ')?(([1-9][0-9]{0,2}(,[0-9]{3})*)|[0-9]+)?\\.[0-9]{1,2}')
var localPriceText = defaultCurrencyPriceText,
prefixMatch = localPriceText.match(re),
entireMatch,
groupMatch,
startIndex,
Expand Down
2 changes: 1 addition & 1 deletion ecommerce/static/js/views/coupon_form_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ define([
if (val === 'Percentage') {
icon = '%';
} else if (val === 'Absolute') {
icon = '$';
icon = currency_symbol;
}
return icon;
},
Expand Down
2 changes: 1 addition & 1 deletion ecommerce/static/js/views/offer_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ define([
if (benefit.type === 'Percentage') {
benefitValue += '%';
} else {
benefitValue = '$' + benefitValue;
benefitValue = currency_symbol + benefitValue;
}

course.set({benefit_value: benefitValue});
Expand Down
4 changes: 2 additions & 2 deletions ecommerce/static/templates/_course_credit_seats.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<thead>
<tr>
<th><%= gettext('Credit Provider') %></th>
<th><%= gettext('Price (USD)') %></th>
<th><%= gettext('Price ('+ currency +')') %></th>
<th><%= gettext('Credit Hours') %></th>
<th><%= gettext('Upgrade Deadline') %></th>
</tr>
Expand All @@ -21,7 +21,7 @@
<% _.each(creditSeats, function (seat) { %>
<tr class="course-seat">
<td class="seat-credit-provider"><%= seat.get('credit_provider_display_name') %></td>
<td class="seat-price"><%= '$' + Number(seat.get('price')).toLocaleString() %></td>
<td class="seat-price"><%= currency_symbol + Number(seat.get('price')).toLocaleString() %></td>
<td class="seat-credit-hours"><%= seat.get('credit_hours') %></td>
<td class="seat-expires"><% var expires = seat.get('expires');
if (expires) {
Expand Down
3 changes: 1 addition & 2 deletions ecommerce/static/templates/_course_seat.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
<div class="seat-type"><%= seat.getSeatTypeDisplayName() %></div>
</div>
<div class="col-sm-4">
<div class="seat-price"><%= gettext('Price:') + ' $' + Number(seat.get('price')).toLocaleString() %></div>
<% var expires = seat.get('expires');
<div class="seat-price"><%= gettext('Price: ') + currency_symbol + Number(seat.get('price')).toLocaleString() %></div> <% var expires = seat.get('expires');
if(expires) {
print(gettext('Upgrade Deadline:') + ' ' + moment.utc(expires).format('lll z'));
}
Expand Down
4 changes: 2 additions & 2 deletions ecommerce/static/templates/_offer_course_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ <h4 class="pagination-range pull-right hidden-xs">Showing <%= (courses.lowerLimi
<% } else { %>
<div class="pull-left">
<p class="course-price">
<span>$<%= course.attributes.stockrecords.price_excl_tax %></span>
<span><%= currency_symbol + course.attributes.stockrecords.price_excl_tax %></span>
</p>
</div>
<div class="pull-left">
<p class="course-new-price">
<span><%- gettext('Now') %> $<%= course.attributes.new_price %></span>
<span><%- gettext('Now') %> <%= currency_symbol + course.attributes.new_price %></span>
</p>
</div>
<% } %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="seat-type"><%= gettext('Audit') %></div>
</div>
<div class="col-sm-4">
<span class="price-label"><%= gettext('Price (in USD)') %>:</span> <span class="seat-price">$0.00</span>
<span class="price-label"><%= gettext('Price (in ' + currency + ')') %>:</span> <span class="seat-price"><%= currency_symbol %>0.00</span>
<input type="hidden" name="price" value="0">
<input type="hidden" name="certificate_type">
<input type="hidden" name="id_verification_required" value="false">
Expand Down
8 changes: 5 additions & 3 deletions ecommerce/static/templates/coupon_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
<input id="benefit-percent" type="radio" class="non-editable" name="benefit_type" value="Percentage">
<label for="benefit-percent" class="normal-font-weight"><%= gettext('Percent') %></label>
<input id="benefit-fixed" type="radio" class="non-editable" name="benefit_type" value="Absolute">
<label for="benefit-fixed" class="normal-font-weight"><%= gettext('Fixed ($USD)') %></label>
<label for="benefit-fixed" class="normal-font-weight"><%= gettext('Fixed ('+ currency_symbol + currency + ')') %></label>
</div>
<p class="help-block"></p>
</div>
Expand Down Expand Up @@ -108,7 +108,7 @@
<div class="form-group">
<label for="price"><%= gettext('Invoiced Amount') %> *</label>
<div class="input-group">
<div class="input-group-addon">$</div>
<div class="input-group-addon"><%= currency_symbol %></div>
<input id="price" type="number" step="0.01" min="0" class="form-control" name="price">
</div>
<p class="help-block"></p>
Expand All @@ -133,7 +133,9 @@
<input id="invoice-discount-percent" type="radio" name="invoice_discount_type" value="Percentage">
<label for="invoice-discount-percent" class="normal-font-weight"><%= gettext('Percent') %></label>
<input id="invoice-discount-fixed" type="radio" name="invoice_discount_type" value="Absolute">
<label for="invoice-discount-fixed" class="normal-font-weight"><%= gettext('Fixed ($USD)') %></label>
<label for="invoice-discount-fixed" class="normal-font-weight">
<%= gettext('Fixed (' + currency_symbol + currency + ')') %>
</label>
</div>
<p class="help-block"></p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<thead>
<tr>
<th id="credit-provider-label"><%= gettext('Credit Provider') %></th>
<th id="price-label"><%= gettext('Price (USD)') %></th>
<th id="price-label"><%= gettext('Price (' + currency + ')') %></th>
<th id="credit-hours-label"><%= gettext('Credit Hours') %></th>
<th id="expires-label"><%= gettext('Upgrade Deadline') %></th>
<th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</td>
<td class="price">
<div class="input-group">
<div class="input-group-addon">$</div>
<div class="input-group-addon"><%= currency_symbol %></div>
<input type="number" class="form-control" id="price" name="price" aria-labelledby="price-label"
min="5" step="1" pattern="\d+" value="<%= price %>">
</div>
Expand Down
6 changes: 3 additions & 3 deletions ecommerce/static/templates/enterprise_coupon_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
<input id="benefit-percent" type="radio" class="non-editable" name="benefit_type" value="Percentage">
<label for="benefit-percent" class="normal-font-weight"><%= gettext('Percent') %></label>
<input id="benefit-fixed" type="radio" class="non-editable" name="benefit_type" value="Absolute">
<label for="benefit-fixed" class="normal-font-weight"><%= gettext('Fixed ($USD)') %></label>
<label for="benefit-fixed" class="normal-font-weight"><%= gettext('Fixed (' + currency_symbol + currency + ')') %></label>
</div>
<p class="help-block"></p>
</div>
Expand Down Expand Up @@ -102,7 +102,7 @@
<div class="form-group">
<label for="price"><%= gettext('Invoiced Amount') %> *</label>
<div class="input-group">
<div class="input-group-addon">$</div>
<div class="input-group-addon"><%= currency_symbol %></div>
<input id="price" type="number" step="0.01" min="0" class="form-control" name="price">
</div>
<p class="help-block"></p>
Expand All @@ -127,7 +127,7 @@
<input id="invoice-discount-percent" type="radio" name="invoice_discount_type" value="Percentage">
<label for="invoice-discount-percent" class="normal-font-weight"><%= gettext('Percent') %></label>
<input id="invoice-discount-fixed" type="radio" name="invoice_discount_type" value="Absolute">
<label for="invoice-discount-fixed" class="normal-font-weight"><%= gettext('Fixed ($USD)') %></label>
<label for="invoice-discount-fixed" class="normal-font-weight"><%= gettext('Fixed (' + currency_symbol + currency + ')') %></label>
</div>
<p class="help-block"></p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="seat-type"><%= gettext('Honor') %></div>
</div>
<div class="col-sm-4">
<span class="price-label"><%= gettext('Price (in USD)') %>:</span> <span class="seat-price">$0.00</span>
<span class="price-label"><%= gettext('Price (in ' + currency + ')') %>:</span> <span class="seat-price"><%= currency_symbol %>0.00</span>
<input type="hidden" name="price" value="0">
<input type="hidden" name="certificate_type" value="honor">
<input type="hidden" name="id_verification_required" value="false">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

<div class="seat-price">
<div class="form-group">
<label for="price"><%= gettext('Price (in USD)') %></label>
<label for="price"><%= gettext('Price (in ' + currency + ')') %></label>

<div class="input-group">
<div class="input-group-addon">$</div>
<div class="input-group-addon"><%= currency_symbol %></div>
<input type="number" class="form-control" name="price" id="price" min="5" step="1" pattern="\d+"
value="<%= price %>">
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

<div class="seat-price">
<div class="form-group">
<label for="price"><%= gettext('Price (in USD)') %></label>
<label for="price"><%= gettext('Price (in ' + currency + ')') %></label>

<div class="input-group">
<div class="input-group-addon">$</div>
<div class="input-group-addon"><%= currency_symbol %></div>
<input type="number" class="form-control" name="price" id="price" min="5" step="1" pattern="\d+"
value="<%= price %>">
</div>
Expand Down
Loading