Skip to content

Commit 0e009e3

Browse files
committed
working on donate & multi-currency order
1 parent d58b4c8 commit 0e009e3

31 files changed

Lines changed: 503 additions & 46 deletions

File tree

Install.md

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55

66
Сайт работает под MacOS, Unix (протестировано на Ubuntu, Debian), но не Windows. Сам код сайта более-менее универсален, но под Windows криво работают некоторые сторонние модули.
77

8-
## 1. Поставьте Node.JS
8+
## 1. Директория
99

10-
Нужна именно последняя версия [Node.JS](https://nodejs.org).
10+
Чтобы было проще – создайте в корне директорию `/js`, и в ней работайте.
11+
Если философия не позволяет – можно другую директорию по править пути, но с `/js` не надо править пути в командах.
1112

12-
## 2. Поставьте и запустите MongoDB.
13+
## 2. Поставьте и запустите Node.JS и MongoDB
1314

14-
Если у вас Mac, то проще всего сделать это через [MacPorts](http://www.macports.org/install.php) или [Homebrew](http://brew.sh), чтобы было проще ставить дополнительные пакеты.
15+
Node.JS – последняя версия с [https://nodejs.org](https://nodejs.org).
16+
17+
Mongo – можно 2.6+. Линукс-пакет или, если у вас Mac, то проще всего сделать это через [MacPorts](http://www.macports.org/install.php) или [Homebrew](http://brew.sh), чтобы было проще ставить дополнительные пакеты.
1518

1619
Если через MacPorts, то:
1720
```
@@ -23,22 +26,26 @@ sudo port load mondogb
2326

2427
Предположу, что Git у вас уже стоит и вы умеете им пользоваться.
2528

26-
Клонируйте только ветку `master`:
29+
Клонируйте только ветку `master` движка:
2730
```
28-
git clone -b ru --single-branch https://github.com/iliakan/javascript-nodejs
31+
cd /js
32+
git clone -b master --single-branch https://github.com/iliakan/javascript-nodejs
2933
```
3034

35+
3136
## 4. Глобальные модули
3237

3338
Поставьте глобальные модули:
3439

3540
```
36-
npm install -g mocha bunyan gulp nodemon
41+
npm install -g mocha bunyan gulp nodemon
3742
```
3843

3944
## 5. Системные пакеты
4045

41-
Для работы нужны Nginx, GraphicsMagick, ImageMagick (обычно используется GM, он лучше, но иногда IM).
46+
Для работы также нужны Nginx, GraphicsMagick и ImageMagick (обычно используется GM, он лучше, но иногда IM).
47+
48+
Под Macports команды такие:
4249

4350
```
4451
sudo port install ImageMagick GraphicsMagick
@@ -49,9 +56,9 @@ sudo port load nginx
4956

5057
## 6. Конфигурация Nginx
5158

52-
Если в системе ранее не стоял nginx, то ставим настройки для сайта:
59+
Если в системе ранее не стоял nginx.
5360

54-
Например:
61+
Cтавим настройки для сайта запуском:
5562
```
5663
gulp config:nginx --prefix /opt/local/etc/nginx --root /js/javascript-nodejs --env development --clear
5764
```
@@ -61,8 +68,15 @@ gulp config:nginx --prefix /opt/local/etc/nginx --root /js/javascript-nodejs --e
6168

6269
Опция `--clear` полностью удалит старые конфиги nginx.
6370

64-
Если уже есть nginx, то можно без `--clear`. Тогда команда только скопирует файлы из директории nginx (с минимальной шаблонизацией) в указанную директорию.
65-
Основные конфиги будут перезаписаны, но в `sites-enabled` останутся и будут подключены и другие сайты.
71+
Если уже есть nginx, то можно без `--clear`.
72+
73+
```
74+
gulp config:nginx --prefix /opt/local/etc/nginx --root /js/javascript-nodejs --env development
75+
```
76+
77+
Такая команда скопирует файлы из директории nginx в указанную директорию `--prefix`. При копировании используется небольшая шаблонизация конфигов, т.е. это не просто `cp`.
78+
79+
Основные конфиги будут при этом перезаписаны, но в `sites-enabled` останутся и будут подключены и другие сайты.
6680

6781
Также рекомендуется в `/etc/hosts` добавить строку:
6882
```
@@ -87,9 +101,11 @@ npm install
87101
gulp db:load --from fixture/init
88102
```
89103

90-
Учебник находится в отдельном репозитарии:
104+
105+
Клонируйте ветку учебника, например `ru`:
91106
```
92-
git clone -b master --single-branch https://github.com/iliakan/javascript-tutorial
107+
cd /js
108+
git clone -b ru --single-branch https://github.com/iliakan/javascript-tutorial
93109
```
94110

95111
После клонирования импортируйте учебник командой:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Сайт пока на русском, на английском сделаем потом.
1515
* Сайт для разработчиков, да, кстати, они не пользуются старыми и страшными IE.
1616

17-
С элементами SPA, но не SPA, потому что нафига сове биплан. Она и так летает.
17+
Профиль юзера на Angular.JS, в остальном не SPA, так как контент-сайт.
1818

1919
## Что в опен-сорсе?
2020

handlers/courses/lib/createOrderFromTemplate.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ module.exports = function*(orderTemplate, user, requestBody) {
6767
title: group.title,
6868
amount: orderData.count * price,
6969
module: orderTemplate.module,
70+
currency: 'RUB',
7071
data: orderData,
7172
email: user.email,
7273
user: user._id

handlers/donate/client/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
var OrderForm = require('./orderForm');
2+
3+
function init() {
4+
5+
6+
var orderForm = document.querySelector('[data-order-form]');
7+
if (orderForm) {
8+
new OrderForm({
9+
elem: orderForm
10+
});
11+
}
12+
13+
}
14+
15+
init();
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
var xhr = require('client/xhr');
2+
var notification = require('client/notification');
3+
var delegate = require('client/delegate');
4+
var FormPayment = require('payments/common/client').FormPayment;
5+
6+
class OrderForm {
7+
8+
constructor(options) {
9+
this.elem = options.elem;
10+
11+
this.product = 'donate';
12+
13+
14+
15+
this.elem.addEventListener('submit', (e) => this.onSubmit(e));
16+
17+
this.delegate('[data-order-payment-change]', 'click', function(e) {
18+
e.preventDefault();
19+
this.elem.querySelector('[data-order-form-step-payment]').style.display = 'block';
20+
this.elem.querySelector('[data-order-form-step-confirm]').style.display = 'none';
21+
this.elem.querySelector('[data-order-form-step-receipt]').style.display = 'none';
22+
});
23+
24+
this.delegate('[data-order-currency]', 'change', function(event) {
25+
var newCurrency = event.delegateTarget.value;
26+
27+
28+
});
29+
}
30+
31+
32+
onSubmit(event) {
33+
event.preventDefault();
34+
new FormPayment(this, this.elem).submit();
35+
}
36+
37+
38+
// return orderData or nothing if validation failed
39+
getOrderData() {
40+
var orderData = { };
41+
42+
if (window.orderNumber) {
43+
orderData.orderNumber = window.orderNumber;
44+
} else {
45+
orderData.orderTemplate = 'webpack';
46+
orderData.amount = this.elem.amount.value;
47+
orderData.currency = this.elem.currency.value;
48+
}
49+
50+
if (this.elem.elements.email) {
51+
if (!this.elem.elements.email.value) {
52+
window.ga('send', 'event', 'payment', 'checkout-no-email', 'donate');
53+
window.metrika.reachGoal('CHECKOUT-NO-EMAIL', {product: 'donate'});
54+
new notification.Error("Введите email.");
55+
this.elem.elements.email.scrollIntoView();
56+
setTimeout(function() {
57+
window.scrollBy(0, -200);
58+
}, 0);
59+
this.elem.elements.email.focus();
60+
return;
61+
} else {
62+
orderData.email = this.elem.elements.email.value;
63+
}
64+
}
65+
66+
return orderData;
67+
}
68+
69+
}
70+
71+
72+
delegate.delegateMixin(OrderForm.prototype);
73+
74+
module.exports = OrderForm;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const payments = require('payments');
2+
var OrderTemplate = payments.OrderTemplate;
3+
4+
exports.get = function*() {
5+
this.nocache();
6+
7+
var orderTemplate = yield OrderTemplate.findOne({
8+
module: 'donate',
9+
slug: this.params.slug
10+
});
11+
12+
if (!orderTemplate) {
13+
this.throw(404);
14+
}
15+
16+
this.locals.orderTemplate = orderTemplate;
17+
18+
this.locals.sitetoolbar = true;
19+
this.locals.title = orderTemplate.title;
20+
21+
this.locals.paymentMethods = require('../lib/paymentMethods');
22+
23+
this.body = this.render('newOrder');
24+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const payments = require('payments');
2+
var Order = payments.Order;
3+
var getOrderInfo = payments.getOrderInfo;
4+
var OrderTemplate = payments.OrderTemplate;
5+
var Transaction = payments.Transaction;
6+
var assert = require('assert');
7+
8+
// Existing order page
9+
exports.get = function*() {
10+
11+
yield* this.loadOrder({
12+
ensureSuccessTimeout: 10000
13+
});
14+
15+
this.nocache();
16+
17+
this.locals.sitetoolbar = true;
18+
this.locals.title = 'Заказ №' + this.order.number;
19+
20+
this.locals.order = this.order;
21+
22+
this.locals.user = this.req.user;
23+
24+
this.locals.paymentMethods = require('../lib/paymentMethods');
25+
26+
this.locals.orderInfo = yield* getOrderInfo(this.order);
27+
28+
this.body = this.render('order');
29+
30+
};

handlers/donate/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
var mountHandlerMiddleware = require('lib/mountHandlerMiddleware');
3+
4+
exports.init = function(app) {
5+
app.use(mountHandlerMiddleware('/donate', __dirname));
6+
7+
// anon can do anything here
8+
app.csrfChecker.ignore.add('/donate/:any*');
9+
10+
};
11+
12+
exports.onPaid = require('./lib/onPaid');
13+
exports.cancelIfPendingTooLong = require('./lib/cancelIfPendingTooLong');
14+
exports.createOrderFromTemplate = require('./lib/createOrderFromTemplate');
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
var Order = require('payments').Order;
2+
3+
// pending for a week => cancel without a notice
4+
module.exports = function*(order) {
5+
if (order.created < new Date() - 7 * 24 * 86400 * 1e3) {
6+
yield order.persist({
7+
status: Order.STATUS_CANCEL
8+
});
9+
}
10+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var Order = require('payments').Order;
2+
3+
// middleware
4+
// create order from template,
5+
// use the incoming data if needed
6+
module.exports = function* (orderTemplate, user, requestBody) {
7+
8+
var currency = requestBody.currency;
9+
if (!~['USD', 'RUB', 'EUR', 'UAH'].indexOf(currency)) {
10+
throw(new Error("Unsupported currency:" + currency));
11+
}
12+
13+
var order = new Order({
14+
title: orderTemplate.title,
15+
description: orderTemplate.description,
16+
amount: +requestBody.amount,
17+
currency: currency,
18+
module: orderTemplate.module
19+
});
20+
21+
if (user) {
22+
order.user = user._id;
23+
order.email = user.email;
24+
} else {
25+
order.email = requestBody.email;
26+
}
27+
28+
yield order.persist();
29+
30+
return order;
31+
32+
};

0 commit comments

Comments
 (0)