Merge branch 'Aufinal/refactor_articles' into Aufinal/refactor_history
This commit is contained in:
commit
290d4ecb6e
6 changed files with 235 additions and 169 deletions
|
@ -153,13 +153,28 @@ class APIModelObject extends ModelObject {
|
||||||
*/
|
*/
|
||||||
static get url_model() {}
|
static get url_model() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request url to create an instance.
|
||||||
|
* @abstract
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
static url_create() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request url to edit an instance of this model.
|
||||||
|
* @abstract
|
||||||
|
* @param {*} api_pk - Identifier of a model instance.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
static url_update_for(api_pk) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request url to get a single model instance data.
|
* Request url to get a single model instance data.
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {*} api_pk - Identifier of a model instance in api requests.
|
* @param {*} api_pk - Identifier of a model instance.
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
static url_object_for(api_pk) {}
|
static url_read_for(api_pk) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link Models.ModelObject|new ModelObject(data)}.
|
* See {@link Models.ModelObject|new ModelObject(data)}.
|
||||||
|
@ -181,36 +196,26 @@ class APIModelObject extends ModelObject {
|
||||||
/**
|
/**
|
||||||
* Request url used to get current instance data.
|
* Request url used to get current instance data.
|
||||||
*/
|
*/
|
||||||
get url_object() {
|
get url_read() {
|
||||||
if (this._url_object === undefined)
|
if (this._url_object === undefined)
|
||||||
return this.is_empty() ? '' : this.constructor.url_object_for(this.api_pk);
|
return this.is_empty() ? '' : this.constructor.url_read_for(this.api_pk);
|
||||||
return this._url_object;
|
return this._url_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
set url_object(v) { this._url_object = v; }
|
set url_read(v) { this._url_object = v; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data of a distant model instance. It sends a GET HTTP request to
|
* Get data of a distant model instance. It sends a GET HTTP request to
|
||||||
* {@link Models.APIModelObject#url_object}.
|
* {@link Models.APIModelObject#url_read}.
|
||||||
* @param {object} [api_options] Additional data appended to the request.
|
* @param {object} [api_options] Additional data appended to the request.
|
||||||
* @param {jQueryAjaxSuccess} [on_success] A function to be called if the request succeeds.
|
|
||||||
* @param {jQueryAjaxError} [on_error] A function to be called if the request fails.
|
|
||||||
*/
|
*/
|
||||||
fromAPI(api_options, on_success, on_error) {
|
fromAPI(api_options) {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
api_options = api_options || {};
|
api_options = api_options || {};
|
||||||
on_success = on_success || $.noop;
|
|
||||||
on_error = on_error || $.noop;
|
|
||||||
|
|
||||||
api_options['format'] = 'json';
|
api_options['format'] = 'json';
|
||||||
|
|
||||||
$.getJSON(this.url_object, api_options)
|
return $.getJSON(this.url_read, api_options)
|
||||||
.done(function (json, textStatus, jqXHR) {
|
.done( (json) => this.from(json) );
|
||||||
that.from(json);
|
|
||||||
on_success(json, textStatus, jqXHR);
|
|
||||||
})
|
|
||||||
.fail(on_error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,9 +226,9 @@ class APIModelObject extends ModelObject {
|
||||||
* @param {jQueryAjaxError} [on_error]
|
* @param {jQueryAjaxError} [on_error]
|
||||||
* @see {@link Models.APIModelObject#fromAPI|fromAPI}
|
* @see {@link Models.APIModelObject#fromAPI|fromAPI}
|
||||||
*/
|
*/
|
||||||
get_by_apipk(api_pk, api_options, on_success, on_error) {
|
get_by_apipk(api_pk, api_options) {
|
||||||
this.url_object = this.constructor.url_object_for(api_pk);
|
this.url_read = this.constructor.url_read_for(api_pk);
|
||||||
this.fromAPI(api_options, on_success, on_error);
|
return this.fromAPI(api_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -283,16 +288,30 @@ class Account extends APIModelObject {
|
||||||
*/
|
*/
|
||||||
static get url_model() { return Urls['kfet.account'](); }
|
static get url_model() { return Urls['kfet.account'](); }
|
||||||
|
|
||||||
|
static url_create(trigramme) {
|
||||||
|
var url = Urls['kfet.account.create']();
|
||||||
|
if (trigramme) {
|
||||||
|
var trigramme_url = encodeURIComponent(trigramme);
|
||||||
|
url += `?trigramme=${trigramme_url}`
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @default <tt>django-js-reverse('kfet.account.read')(trigramme)</tt>
|
* @default <tt>django-js-reverse('kfet.account.read')(trigramme)</tt>
|
||||||
* @param {string} trigramme
|
* @param {string} trigramme
|
||||||
* @see {@link Models.APIModelObject.url_object_for|APIModelObject.url_object_for}
|
* @see {@link Models.APIModelObject.url_read_for|APIModelObject.url_read_for}
|
||||||
*/
|
*/
|
||||||
static url_object_for(trigramme) {
|
static url_read_for(trigramme) {
|
||||||
var trigramme_url = encodeURIComponent(trigramme);
|
var trigramme_url = encodeURIComponent(trigramme);
|
||||||
return Urls['kfet.account.read'](trigramme_url);
|
return Urls['kfet.account.read'](trigramme_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static url_update_for(trigramme) {
|
||||||
|
var trigramme_url = encodeURIComponent(trigramme);
|
||||||
|
return Urls['kfet.account.update'](trigramme_url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @default <tt>this.trigramme</tt>
|
* @default <tt>this.trigramme</tt>
|
||||||
*/
|
*/
|
||||||
|
@ -313,7 +332,7 @@ class Account extends APIModelObject {
|
||||||
/**
|
/**
|
||||||
* Balance converted to UKF according to cof status.
|
* Balance converted to UKF according to cof status.
|
||||||
*/
|
*/
|
||||||
get balance_ukf() { return amountToUKF(this.balance, this.is_cof); }
|
get balance_ukf() { return amountToUKF(this.balance, this.is_cof, true); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,10 +374,14 @@ class Checkout extends APIModelObject {
|
||||||
/**
|
/**
|
||||||
* @default <tt>django-js-reverse('kfet.kpsul.checkout_data.read')(pk)</tt>
|
* @default <tt>django-js-reverse('kfet.kpsul.checkout_data.read')(pk)</tt>
|
||||||
* @param {string} api_pk - a checkout id
|
* @param {string} api_pk - a checkout id
|
||||||
* @see {@link Models.APIModelObject.url_object_for|APIModelObject.url_object_for}
|
* @see {@link Models.APIModelObject.url_read_for|APIModelObject.url_read_for}
|
||||||
*/
|
*/
|
||||||
static url_object_for(api_pk) {
|
static url_read_for(api_pk) {
|
||||||
return Urls['kfet.kpsul.checkout_data.read'](api_pk);
|
return Urls['kfet.checkout.read'](api_pk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static url_update_for(api_pk) {
|
||||||
|
return Urls['kfet.checkout.update'](api_pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -404,6 +427,10 @@ class Statement extends ModelObject {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static url_create(checkout_pk) {
|
||||||
|
return Urls['kfet.checkoutstatement.create'](checkout_pk);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @default {@link Formatters.StatementFormatter}
|
* @default {@link Formatters.StatementFormatter}
|
||||||
*/
|
*/
|
||||||
|
@ -508,6 +535,10 @@ class Article extends ModelObject {
|
||||||
// API currently returns a string object (serialization of Decimal type within Django)
|
// API currently returns a string object (serialization of Decimal type within Django)
|
||||||
get price() { return this._price; }
|
get price() { return this._price; }
|
||||||
set price(v) { this._price = floatCheck(v); }
|
set price(v) { this._price = floatCheck(v); }
|
||||||
|
|
||||||
|
is_low_stock(nb) {
|
||||||
|
return (-5 <= this.stock - nb && this.stock - nb <= 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1040,29 +1071,14 @@ class APIModelForest extends ModelForest {
|
||||||
* Fills the instance with distant data. It sends a GET HTTP request to
|
* Fills the instance with distant data. It sends a GET HTTP request to
|
||||||
* {@link Models.APIModelForest#url_model}.
|
* {@link Models.APIModelForest#url_model}.
|
||||||
* @param {object} [api_options] Additional data appended to the request.
|
* @param {object} [api_options] Additional data appended to the request.
|
||||||
* @param {jQueryAjaxSuccess} [on_success] A function to be called if the request succeeds.
|
|
||||||
* @param {jQueryAjaxError} [on_error] A function to be called if the request fails.
|
|
||||||
*/
|
*/
|
||||||
fromAPI(api_options, on_success, on_error) {
|
fromAPI(api_options) {
|
||||||
var that = this;
|
api_options = api_options || {};
|
||||||
|
|
||||||
api_options = api_options || {}
|
|
||||||
on_success = on_success || $.noop;
|
|
||||||
on_error = on_error || $.noop;
|
|
||||||
|
|
||||||
api_options['format'] = 'json';
|
api_options['format'] = 'json';
|
||||||
|
|
||||||
$.ajax({
|
return $.getJSON(this.constructor.url_model, api_options)
|
||||||
dataType: "json",
|
.done( (json) => this.from(json) );
|
||||||
url : this.constructor.url_model,
|
|
||||||
method : "POST",
|
|
||||||
data : api_options,
|
|
||||||
})
|
|
||||||
.done(function(json, textStatus, jqXHR) {
|
|
||||||
that.from(json);
|
|
||||||
on_success(json, textStatus, jqXHR);
|
|
||||||
})
|
|
||||||
.fail(on_error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,29 @@ function booleanCheck(v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short: Equivalent to python str format.
|
||||||
|
* Source: [MDN]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals}.
|
||||||
|
* @example
|
||||||
|
* var t1Closure = template`${0}${1}${0}!`;
|
||||||
|
* t1Closure('Y', 'A'); // "YAY!"
|
||||||
|
* @example
|
||||||
|
* var t2Closure = template`${0} ${'foo'}!`;
|
||||||
|
* t2Closure('Hello', {foo: 'World'}); // "Hello World!"
|
||||||
|
*/
|
||||||
|
function template(strings, ...keys) {
|
||||||
|
return (function(...values) {
|
||||||
|
var dict = values[values.length - 1] || {};
|
||||||
|
var result = [strings[0]];
|
||||||
|
keys.forEach(function(key, i) {
|
||||||
|
var value = Number.isInteger(key) ? values[key] : dict[key];
|
||||||
|
result.push(value, strings[i + 1]);
|
||||||
|
});
|
||||||
|
return result.join('');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get and store K-Psul config from API.
|
* Get and store K-Psul config from API.
|
||||||
* <br><br>
|
* <br><br>
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
/**
|
||||||
|
* @file K-Psul JS
|
||||||
|
* @copyright 2017 cof-geek
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
class KPsulManager {
|
class KPsulManager {
|
||||||
|
|
||||||
constructor(env) {
|
constructor(env) {
|
||||||
|
@ -12,12 +19,25 @@ class KPsulManager {
|
||||||
soft = soft || false;
|
soft = soft || false;
|
||||||
|
|
||||||
this.account_manager.reset();
|
this.account_manager.reset();
|
||||||
|
this.article_manager.reset();
|
||||||
|
|
||||||
if (!soft) {
|
if (!soft) {
|
||||||
this.checkout_manager.reset();
|
this.checkout_manager.reset();
|
||||||
|
this.article_manager.reset_data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
if (this.checkout_manager.is_empty())
|
||||||
|
this.checkout_manager.focus();
|
||||||
|
else if (this.account_manager.is_empty())
|
||||||
|
this.account_manager.focus();
|
||||||
|
else
|
||||||
|
this.article_manager.focus();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +49,15 @@ class AccountManager {
|
||||||
this.account = new Account();
|
this.account = new Account();
|
||||||
this.selection = new AccountSelection(this);
|
this.selection = new AccountSelection(this);
|
||||||
this.search = new AccountSearch(this);
|
this.search = new AccountSearch(this);
|
||||||
|
|
||||||
|
// buttons: search, read or create
|
||||||
|
this._$buttons_container = this._$container.find('.buttons');
|
||||||
|
this._buttons_templates = {
|
||||||
|
create: template`<a href="${'url'}" class="btn btn-primary" target="_blank" title="Créer ce compte"><span class="glyphicon glyphicon-plus"></span></a>`,
|
||||||
|
read: template`<a href="${'url'}" class="btn btn-primary" target="_blank" title="Détails du compte"><span class="glyphicon glyphicon-info-sign"></span></a>`,
|
||||||
|
search: template`<button class="btn btn-primary search" title="Rechercher"><span class="glyphicon glyphicon-search"></span></button>`,
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is_empty() { return this.account.is_empty(); }
|
is_empty() { return this.account.is_empty(); }
|
||||||
|
@ -45,25 +74,22 @@ class AccountManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
_display_buttons() {
|
_display_buttons() {
|
||||||
// dirty
|
var buttons;
|
||||||
|
|
||||||
var buttons = '';
|
|
||||||
|
|
||||||
if (this.is_empty()) {
|
if (this.is_empty()) {
|
||||||
var trigramme = this.selection.get();
|
var trigramme = this.selection.get();
|
||||||
if (trigramme.isValidTri()) {
|
if (trigramme.isValidTri()) {
|
||||||
var url_base = Urls['kfet.account.create']();
|
var url = Account.url_create(trigramme);
|
||||||
var url = url_base + '?trigramme=' + encodeURIComponent(trigramme);
|
buttons = this._buttons_templates['create']({url: url});
|
||||||
buttons += '<a href="'+url+'" class="btn btn-primary" target="_blank" title="Créer ce compte"><span class="glyphicon glyphicon-plus"></span></a>';
|
|
||||||
} else { /* trigramme input is empty or invalid */
|
} else { /* trigramme input is empty or invalid */
|
||||||
buttons += '<button class="btn btn-primary search" title="Rechercher"><span class="glyphicon glyphicon-search"></span></button>';
|
buttons = this._buttons_templates['search']();
|
||||||
}
|
}
|
||||||
} else { /* an account is loaded */
|
} else { /* an account is loaded */
|
||||||
var url = this.account.url_object;
|
var url = this.account.url_read;
|
||||||
buttons += '<a href="'+url+'" class="btn btn-primary" target="_blank" title="Détails du compte"><span class="glyphicon glyphicon-cog"></span></a>';
|
buttons = this._buttons_templates['read']({url: url});
|
||||||
}
|
}
|
||||||
|
|
||||||
this._$container.find('.buttons').html(buttons);
|
this._$buttons_container.html(buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(trigramme) {
|
update(trigramme) {
|
||||||
|
@ -73,10 +99,9 @@ class AccountManager {
|
||||||
trigramme = trigramme || this.selection.get();
|
trigramme = trigramme || this.selection.get();
|
||||||
|
|
||||||
if (trigramme.isValidTri()) {
|
if (trigramme.isValidTri()) {
|
||||||
this.account.get_by_apipk(trigramme, {},
|
this.account.get_by_apipk(trigramme)
|
||||||
() => this._update_on_success(),
|
.done( () => this._update_on_success() )
|
||||||
() => this.reset_data()
|
.fail( () => this.reset_data() );
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
this.reset_data();
|
this.reset_data();
|
||||||
}
|
}
|
||||||
|
@ -86,7 +111,7 @@ class AccountManager {
|
||||||
$('#id_on_acc').val(this.account.id);
|
$('#id_on_acc').val(this.account.id);
|
||||||
this.display();
|
this.display();
|
||||||
|
|
||||||
kpsul._env.articleSelect.focus();
|
kpsul.focus();
|
||||||
kpsul._env.updateBasketAmount();
|
kpsul._env.updateBasketAmount();
|
||||||
kpsul._env.updateBasketRel();
|
kpsul._env.updateBasketRel();
|
||||||
}
|
}
|
||||||
|
@ -250,6 +275,12 @@ class CheckoutManager {
|
||||||
this._$laststatement_container = $('#last_statement');
|
this._$laststatement_container = $('#last_statement');
|
||||||
this.laststatement = new Statement();
|
this.laststatement = new Statement();
|
||||||
this.laststatement_display_prefix = '#checkout-last_statement_';
|
this.laststatement_display_prefix = '#checkout-last_statement_';
|
||||||
|
|
||||||
|
this._$buttons_container = this._$container.find('.buttons');
|
||||||
|
this._buttons_templates = {
|
||||||
|
read: template`<a class="btn btn-primary" href="${'url'}" title="En savoir plus" target="_blank"><span class="glyphicon glyphicon-info-sign"></span></a>`,
|
||||||
|
statement_create: template`<a href="${'url'}" title="Effectuer un relevé" class="btn btn-primary" target="_blank"><span class="glyphicon glyphicon-euro"></span></a>`,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(id) {
|
update(id) {
|
||||||
|
@ -262,15 +293,11 @@ class CheckoutManager {
|
||||||
'last_statement': true,
|
'last_statement': true,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.checkout.get_by_apipk(id, api_options,
|
this.checkout.get_by_apipk(id, api_options)
|
||||||
(data) => this._update_on_success(data),
|
.done( (data) => this._update_on_success(data) )
|
||||||
() => this.reset_data());
|
.fail( () => this.reset_data() );
|
||||||
|
|
||||||
if (kpsul.account_manager.is_empty()) {
|
kpsul.focus();
|
||||||
kpsul.account_manager.focus();
|
|
||||||
} else {
|
|
||||||
kpsul._env.articleSelect.focus().select();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_update_on_success(data) {
|
_update_on_success(data) {
|
||||||
|
@ -310,13 +337,13 @@ class CheckoutManager {
|
||||||
_display_buttons() {
|
_display_buttons() {
|
||||||
var buttons = '';
|
var buttons = '';
|
||||||
if (!this.is_empty()) {
|
if (!this.is_empty()) {
|
||||||
var id = this.checkout.id;
|
var url_newcheckout = Statement.url_create(this.checkout.id);
|
||||||
var url_details = Urls['kfet.checkout.read'](id);
|
buttons += this._buttons_templates['statement_create']({
|
||||||
var url_newcheckout = Urls['kfet.checkoutstatement.create'](id);
|
url: url_newcheckout});
|
||||||
buttons += '<a href="' + url_newcheckout + '" title="Effectuer un relevé" class="btn btn-primary" target="_blank"><span class="glyphicon glyphicon-euro"></span></a>';
|
var url_read = this.checkout.url_read;
|
||||||
buttons += '<a class="btn btn-primary" href="' + url_details + '" title="Modifier" target="_blank"><span class="glyphicon glyphicon-cog"></span></a>';
|
buttons += this._buttons_templates['read']({url: url_read});
|
||||||
}
|
}
|
||||||
this._$container.find('.buttons').html(buttons);
|
this._$buttons_container.html(buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
|
@ -335,6 +362,11 @@ class CheckoutManager {
|
||||||
|
|
||||||
this.display();
|
this.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this.selection.focus();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,6 +399,11 @@ class CheckoutSelection {
|
||||||
reset() {
|
reset() {
|
||||||
this._$input.find('option:first').prop('selected', true);
|
this._$input.find('option:first').prop('selected', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this._$input.focus();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArticleManager {
|
class ArticleManager {
|
||||||
|
@ -415,19 +452,23 @@ class ArticleManager {
|
||||||
reset_data() {
|
reset_data() {
|
||||||
this._$container.html('');
|
this._$container.html('');
|
||||||
this.list.clear();
|
this.list.clear();
|
||||||
this.list.fromAPI({}, this.display_list.bind(this), $.noop) ;
|
this.list.fromAPI()
|
||||||
|
.done( () => this.display_list() );
|
||||||
|
}
|
||||||
|
|
||||||
|
get_article(id) {
|
||||||
|
return this.list.find('article', id).content;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: filter articles before ?
|
|
||||||
update_data(data) {
|
update_data(data) {
|
||||||
for (let article_dict of data.articles) {
|
for (let article_dict of data.articles) {
|
||||||
var article = this.list.find('article', article_dict['id']);
|
var article = this.get_article(article_dict.id);
|
||||||
|
|
||||||
// For now, article additions are disregarded
|
// For now, article additions are disregarded
|
||||||
if (article) {
|
if (article) {
|
||||||
article.stock = article_dict['stock'];
|
article.stock = article_dict.stock;
|
||||||
this._$container.find('#article-'+article_dict['id']+' .stock')
|
this._$container.find('#article-'+article.id+' .stock')
|
||||||
.text(article_dict['stock']);
|
.text(article.stock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,7 +521,11 @@ class ArticleManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this._$input.focus();
|
if (this.is_empty())
|
||||||
|
this._$input.focus();
|
||||||
|
else
|
||||||
|
this._$nb.focus();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ $(document).ready(function() {
|
||||||
|
|
||||||
commentDialog.open({
|
commentDialog.open({
|
||||||
callback: confirm_callback,
|
callback: confirm_callback,
|
||||||
next_focus: articleSelect
|
next_focus: kpsul,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ $(document).ready(function() {
|
||||||
else
|
else
|
||||||
displayErrors(getErrorsHtml(response));
|
displayErrors(getErrorsHtml(response));
|
||||||
},
|
},
|
||||||
next_focus: articleSelect,
|
next_focus: kpsul,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,15 +228,6 @@ $(document).ready(function() {
|
||||||
performOperations();
|
performOperations();
|
||||||
});
|
});
|
||||||
|
|
||||||
// -----
|
|
||||||
// Articles data
|
|
||||||
// -----
|
|
||||||
|
|
||||||
var articleSelect = $('#article_autocomplete');
|
|
||||||
var articleId = $('#article_id');
|
|
||||||
var articleNb = $('#article_number');
|
|
||||||
var articlesList = [];
|
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
// Basket
|
// Basket
|
||||||
// -----
|
// -----
|
||||||
|
@ -276,17 +267,13 @@ $(document).ready(function() {
|
||||||
.find('.name').text(article.name).end()
|
.find('.name').text(article.name).end()
|
||||||
.find('.amount').text(amountToUKF(amount_euro, kpsul.account_manager.account.is_cof));
|
.find('.amount').text(amountToUKF(amount_euro, kpsul.account_manager.account.is_cof));
|
||||||
basket_container.prepend(article_basket_html);
|
basket_container.prepend(article_basket_html);
|
||||||
if (is_low_stock(article, nb))
|
if (article.is_low_stock(nb))
|
||||||
article_basket_html.find('.lowstock')
|
article_basket_html.find('.lowstock')
|
||||||
.show();
|
.show();
|
||||||
updateBasketRel();
|
updateBasketRel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_low_stock(article, nb) {
|
|
||||||
return (-5 <= article.stock - nb && article.stock - nb <= 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDeposit(amount) {
|
function addDeposit(amount) {
|
||||||
var deposit_basket_html = $(item_basket_default_html);
|
var deposit_basket_html = $(item_basket_default_html);
|
||||||
var amount = parseFloat(amount).toFixed(2);
|
var amount = parseFloat(amount).toFixed(2);
|
||||||
|
@ -419,15 +406,12 @@ $(document).ready(function() {
|
||||||
function addExistingPurchase(opeindex, nb) {
|
function addExistingPurchase(opeindex, nb) {
|
||||||
var type = formset_container.find("#id_form-"+opeindex+"-type").val();
|
var type = formset_container.find("#id_form-"+opeindex+"-type").val();
|
||||||
var id = formset_container.find("#id_form-"+opeindex+"-article").val();
|
var id = formset_container.find("#id_form-"+opeindex+"-article").val();
|
||||||
|
var article = kpsul.article_manager.get_article(parseInt(id));
|
||||||
var nb_before = formset_container.find("#id_form-"+opeindex+"-article_nb").val();
|
var nb_before = formset_container.find("#id_form-"+opeindex+"-article_nb").val();
|
||||||
var nb_after = parseInt(nb_before) + parseInt(nb);
|
var nb_after = parseInt(nb_before) + parseInt(nb);
|
||||||
var amountEuro_after = amountEuroPurchase(id, nb_after);
|
var amountEuro_after = amountEuroPurchase(article, nb_after);
|
||||||
var amountUKF_after = amountToUKF(amountEuro_after, kpsul.account_manager.account.is_cof, false);
|
var amountUKF_after = amountToUKF(amountEuro_after, kpsul.account_manager.account.is_cof, false);
|
||||||
|
|
||||||
var i = 0;
|
|
||||||
while (i<articlesList.length && id != articlesList[i][1]) i++;
|
|
||||||
var article_data = articlesList[i];
|
|
||||||
|
|
||||||
if (type == 'purchase') {
|
if (type == 'purchase') {
|
||||||
if (nb_after == 0) {
|
if (nb_after == 0) {
|
||||||
deleteFromBasket(opeindex);
|
deleteFromBasket(opeindex);
|
||||||
|
@ -435,20 +419,20 @@ $(document).ready(function() {
|
||||||
if (nb_before > 0) {
|
if (nb_before > 0) {
|
||||||
var article_html = basket_container.find('[data-opeindex='+opeindex+']');
|
var article_html = basket_container.find('[data-opeindex='+opeindex+']');
|
||||||
article_html.find('.amount').text(amountUKF_after).end()
|
article_html.find('.amount').text(amountUKF_after).end()
|
||||||
.find('.number').text('('+nb_after+'/'+article_data[4]+')').end() ;
|
.find('.number').text('('+nb_after+'/'+article.stock+')').end() ;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
article_html = $(item_basket_default_html);
|
article_html = $(item_basket_default_html);
|
||||||
article_html
|
article_html
|
||||||
.attr('data-opeindex', opeindex)
|
.attr('data-opeindex', opeindex)
|
||||||
.find('.number').text('('+nb_after+'/'+article_data[4]+')').end()
|
.find('.number').text('('+nb_after+'/'+article.stock+')').end()
|
||||||
.find('.name').text(article_data[0]).end()
|
.find('.name').text(article.name).end()
|
||||||
.find('.amount').text(amountUKF_after);
|
.find('.amount').text(amountUKF_after);
|
||||||
basket_container.prepend(article_basket_html);
|
basket_container.prepend(article_basket_html);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_low_stock(id, nb_after))
|
if (article.is_low_stock(nb_after))
|
||||||
article_html.find('.lowstock')
|
article_html.find('.lowstock')
|
||||||
.show();
|
.show();
|
||||||
else
|
else
|
||||||
|
@ -485,11 +469,9 @@ $(document).ready(function() {
|
||||||
addDeposit(amount);
|
addDeposit(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next_focus = articleSelect.val() ? articleNb : articleSelect ;
|
|
||||||
|
|
||||||
depositDialog.open({
|
depositDialog.open({
|
||||||
callback: callback,
|
callback: callback,
|
||||||
next_focus: next_focus,
|
next_focus: kpsul.article_manager,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,11 +487,9 @@ $(document).ready(function() {
|
||||||
addEdit(amount);
|
addEdit(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next_focus = articleSelect.val() ? articleNb : articleSelect ;
|
|
||||||
|
|
||||||
editDialog.open({
|
editDialog.open({
|
||||||
callback: callback,
|
callback: callback,
|
||||||
next_focus: next_focus,
|
next_focus: kpsul.article_manager,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,11 +505,9 @@ $(document).ready(function() {
|
||||||
addWithdraw(amount);
|
addWithdraw(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next_focus = articleSelect.val() ? articleNb : articleSelect ;
|
|
||||||
|
|
||||||
withdrawDialog.open({
|
withdrawDialog.open({
|
||||||
callback: callback,
|
callback: callback,
|
||||||
next_focus: next_focus,
|
next_focus: kpsul.article_manager,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,7 +712,7 @@ $(document).ready(function() {
|
||||||
} else {
|
} else {
|
||||||
// F2 - Basket reset
|
// F2 - Basket reset
|
||||||
resetBasket();
|
resetBasket();
|
||||||
articleSelect.focus();
|
kpsul.article_manager.focus();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case 114:
|
case 114:
|
||||||
|
@ -766,7 +744,6 @@ $(document).ready(function() {
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
var env = {
|
var env = {
|
||||||
articleSelect: articleSelect,
|
|
||||||
addPurchase: addPurchase,
|
addPurchase: addPurchase,
|
||||||
updateBasketAmount: updateBasketAmount,
|
updateBasketAmount: updateBasketAmount,
|
||||||
updateBasketRel: updateBasketRel,
|
updateBasketRel: updateBasketRel,
|
||||||
|
|
|
@ -169,8 +169,6 @@ urlpatterns = [
|
||||||
# -----
|
# -----
|
||||||
|
|
||||||
url('^k-psul/$', views.kpsul, name='kfet.kpsul'),
|
url('^k-psul/$', views.kpsul, name='kfet.kpsul'),
|
||||||
url(r'^k-psul/checkout_data/(?P<pk>\d+)$', views.kpsul_checkout_data,
|
|
||||||
name='kfet.kpsul.checkout_data.read'),
|
|
||||||
url('^k-psul/perform_operations$', views.kpsul_perform_operations,
|
url('^k-psul/perform_operations$', views.kpsul_perform_operations,
|
||||||
name='kfet.kpsul.perform_operations'),
|
name='kfet.kpsul.perform_operations'),
|
||||||
url('^k-psul/cancel_operations$', views.kpsul_cancel_operations,
|
url('^k-psul/cancel_operations$', views.kpsul_cancel_operations,
|
||||||
|
|
103
kfet/views.py
103
kfet/views.py
|
@ -52,6 +52,32 @@ from .statistic import daynames, monthnames, weeknames, \
|
||||||
this_morning, this_monday_morning, this_first_month_day, \
|
this_morning, this_monday_morning, this_first_month_day, \
|
||||||
tot_ventes
|
tot_ventes
|
||||||
|
|
||||||
|
|
||||||
|
# source : docs.djangoproject.com/fr/1.10/topics/class-based-views/mixins/
|
||||||
|
class JSONResponseMixin(object):
|
||||||
|
"""
|
||||||
|
A mixin that can be used to render a JSON response.
|
||||||
|
"""
|
||||||
|
def render_to_json_response(self, context, **response_kwargs):
|
||||||
|
"""
|
||||||
|
Returns a JSON response, transforming 'context' to make the payload.
|
||||||
|
"""
|
||||||
|
return JsonResponse(
|
||||||
|
self.get_data(context),
|
||||||
|
**response_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_data(self, context):
|
||||||
|
"""
|
||||||
|
Returns an object that will be serialized as JSON by json.dumps().
|
||||||
|
"""
|
||||||
|
# Note: This is *EXTREMELY* naive; in reality, you'll need
|
||||||
|
# to do much more complex handling to ensure that arbitrary
|
||||||
|
# objects -- such as Django model instances or querysets
|
||||||
|
# -- can be serialized as JSON.
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class Home(TemplateView):
|
class Home(TemplateView):
|
||||||
template_name = "kfet/home.html"
|
template_name = "kfet/home.html"
|
||||||
|
|
||||||
|
@ -618,18 +644,44 @@ class CheckoutCreate(SuccessMessageMixin, CreateView):
|
||||||
|
|
||||||
return super(CheckoutCreate, self).form_valid(form)
|
return super(CheckoutCreate, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
# Checkout - Read
|
# Checkout - Read
|
||||||
|
|
||||||
class CheckoutRead(DetailView):
|
class CheckoutRead(JSONResponseMixin, DetailView):
|
||||||
model = Checkout
|
model = Checkout
|
||||||
template_name = 'kfet/checkout_read.html'
|
template_name = 'kfet/checkout_read.html'
|
||||||
context_object_name = 'checkout'
|
context_object_name = 'checkout'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(CheckoutRead, self).get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['statements'] = context['checkout'].statements.order_by('-at')
|
checkout = self.object
|
||||||
|
if self.request.GET.get('last_statement'):
|
||||||
|
context['laststatement'] = checkout.statements.latest('at')
|
||||||
|
else:
|
||||||
|
context['statements'] = checkout.statements.order_by('-at')
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def render_to_response(self, context, **kwargs):
|
||||||
|
if self.request.GET.get('format') == 'json':
|
||||||
|
data = model_to_dict(
|
||||||
|
context['checkout'],
|
||||||
|
fields=['id', 'name', 'balance', 'valid_from', 'valid_to']
|
||||||
|
)
|
||||||
|
if 'laststatement' in context:
|
||||||
|
last_statement = context['laststatement']
|
||||||
|
last_statement_data = model_to_dict(
|
||||||
|
last_statement,
|
||||||
|
fields=['id', 'at', 'balance_new', 'balance_old', 'by']
|
||||||
|
)
|
||||||
|
last_statement_data['by'] = str(last_statement.by)
|
||||||
|
# ``at`` is not editable, so skipped by ``model_to_dict``
|
||||||
|
last_statement_data['at'] = last_statement.at
|
||||||
|
data['laststatement'] = last_statement_data
|
||||||
|
return self.render_to_json_response(data)
|
||||||
|
else:
|
||||||
|
return super().render_to_response(context, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
# Checkout - Update
|
# Checkout - Update
|
||||||
|
|
||||||
class CheckoutUpdate(SuccessMessageMixin, UpdateView):
|
class CheckoutUpdate(SuccessMessageMixin, UpdateView):
|
||||||
|
@ -897,28 +949,6 @@ def kpsul_get_settings(request):
|
||||||
return JsonResponse(data)
|
return JsonResponse(data)
|
||||||
|
|
||||||
|
|
||||||
@teamkfet_required
|
|
||||||
def kpsul_checkout_data(request, pk):
|
|
||||||
checkout = get_object_or_404(Checkout, pk=pk)
|
|
||||||
data = model_to_dict(
|
|
||||||
checkout,
|
|
||||||
fields=['id', 'name', 'balance', 'valid_from', 'valid_to']
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.GET.get('last_statement'):
|
|
||||||
last_statement = checkout.statements.latest('at')
|
|
||||||
last_statement_data = model_to_dict(
|
|
||||||
last_statement,
|
|
||||||
fields=['id', 'at', 'balance_new', 'balance_old', 'by']
|
|
||||||
)
|
|
||||||
last_statement_data['by'] = str(last_statement.by)
|
|
||||||
# ``at`` is not editable, so skipped by ``model_to_dict``
|
|
||||||
last_statement_data['at'] = last_statement.at
|
|
||||||
data['laststatement'] = last_statement_data
|
|
||||||
|
|
||||||
return JsonResponse(data)
|
|
||||||
|
|
||||||
|
|
||||||
@teamkfet_required
|
@teamkfet_required
|
||||||
def kpsul_update_addcost(request):
|
def kpsul_update_addcost(request):
|
||||||
addcost_form = AddcostForm(request.POST)
|
addcost_form = AddcostForm(request.POST)
|
||||||
|
@ -2145,29 +2175,6 @@ class SupplierUpdate(SuccessMessageMixin, UpdateView):
|
||||||
# ---------------
|
# ---------------
|
||||||
# Vues génériques
|
# Vues génériques
|
||||||
# ---------------
|
# ---------------
|
||||||
# source : docs.djangoproject.com/fr/1.10/topics/class-based-views/mixins/
|
|
||||||
class JSONResponseMixin(object):
|
|
||||||
"""
|
|
||||||
A mixin that can be used to render a JSON response.
|
|
||||||
"""
|
|
||||||
def render_to_json_response(self, context, **response_kwargs):
|
|
||||||
"""
|
|
||||||
Returns a JSON response, transforming 'context' to make the payload.
|
|
||||||
"""
|
|
||||||
return JsonResponse(
|
|
||||||
self.get_data(context),
|
|
||||||
**response_kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_data(self, context):
|
|
||||||
"""
|
|
||||||
Returns an object that will be serialized as JSON by json.dumps().
|
|
||||||
"""
|
|
||||||
# Note: This is *EXTREMELY* naive; in reality, you'll need
|
|
||||||
# to do much more complex handling to ensure that arbitrary
|
|
||||||
# objects -- such as Django model instances or querysets
|
|
||||||
# -- can be serialized as JSON.
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class JSONDetailView(JSONResponseMixin,
|
class JSONDetailView(JSONResponseMixin,
|
||||||
|
|
Loading…
Reference in a new issue