diff --git a/kfet/static/kfet/js/history.js b/kfet/static/kfet/js/history.js index a41173b2..9578b83d 100644 --- a/kfet/static/kfet/js/history.js +++ b/kfet/static/kfet/js/history.js @@ -19,10 +19,10 @@ class KHistory { this.list = new OperationList(); - if (!options.no_select) + if (!options || !options.no_select) this.selection = new KHistorySelection(this); - if (options.no_trigramme) + if (options && options.no_trigramme) this.templates['opegroup'] = '
' this._init_events(); @@ -80,7 +80,7 @@ class KHistory { add_node(data) { var node = this.list.get_or_create(data, 0); - this.list.add_to_container(this._$container, node, this.templates, this.display_options); + this.list.add_to_container(this._$container, node, this.templates); } update_node(type, id, update_data) { @@ -88,8 +88,8 @@ class KHistory { if (!to_update) return false; - $.extend(to_update.content, update_data); - var $new_elt = to_update.content.display($(this.templates[type]), this.display_options); + $.extend(to_update, update_data); + var $new_elt = to_update.display($(this.templates[type]), {}); var $to_replace = this._$container.find('#'+type+'-'+id+'>:first-child'); $to_replace.replaceWith($new_elt); @@ -100,22 +100,22 @@ class KHistory { is_valid(opegroup) { var options = this.api_options; - if (options.from && dateUTCToParis(opegroup.content.at).isBefore(moment(options.from))) + if (options.from && dateUTCToParis(opegroup.at).isBefore(moment(options.from))) return false; - if (options.to && dateUTCToParis(opegroup.content.at).isAfter(moment(options.to))) + if (options.to && dateUTCToParis(opegroup.at).isAfter(moment(options.to))) return false; - if (options.transfersonly && opegroup.modelname === 'opegroup') + if (options.transfersonly && opegroup.constructor.verbose_name === 'opegroup') return false; if (options.accounts && options.accounts.length && - options.accounts.indexOf(opegroup.content.account_id) < 0) + options.accounts.indexOf(opegroup.account_id) < 0) return false; if (options.checkouts && options.checkouts.length && (opegroup.modelname === 'transfergroup' || - options.checkouts.indexOf(opegroup.content.checkout_id) < 0)) + options.checkouts.indexOf(opegroup.checkout_id) < 0)) return false; return true; diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index e08efced..6afc179f 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -565,14 +565,20 @@ class Day extends ModelObject { * @default ['id', 'date'] * @see {@link Models.ModelObject.props|ModelObject.props} */ - static get props() { return ['id', 'date'] } + static get props() { return ['id', 'date', 'opegroups'] } /** * Default values for Day model instances * @default {'id': '', 'date': moment()} * @see {@link Models.ModelObject.default_data|ModelObject.default_data} */ - static get default_data() { return {'id': '', 'date': moment()}; } + static get default_data() { return {'id': '', 'date': moment(), 'opegroups': []}; } + + /** + * Verbose name for Article model + * @default 'day' + */ + static get verbose_name() { return 'day'; } /** * @default {@link Formatters.DayFormatter} @@ -610,7 +616,7 @@ class HistoryGroup extends ModelObject { * @see {@link Models.ModelObject.props|ModelObject.props} */ static get props() { - return ['id', 'at', 'comment', 'valid_by']; + return ['id', 'at', 'comment', 'valid_by', 'day']; } /** @@ -621,7 +627,7 @@ class HistoryGroup extends ModelObject { */ static get default_data() { return {'id': 0, 'at': moment(), 'comment': '', - 'valid_by': '',}; + 'valid_by': '', 'day': new Day()}; } /** @@ -665,9 +671,17 @@ class OperationGroup extends HistoryGroup { */ static get default_data() { return $.extend({}, HistoryGroup.default_data, - {'amount': 0, 'is_cof': false, 'trigramme': ''}); + {'amount': 0, 'is_cof': false, 'trigramme': '', + 'opes': []}); } + /** + * Verbose name for OperationGroup model + * @default 'opegroup' + */ + static get verbose_name() { return 'opegroup'; } + + /** * @default {@link Formatters.OpegroupFormatter} */ @@ -686,6 +700,24 @@ class OperationGroup extends HistoryGroup { */ class TransferGroup extends HistoryGroup { + /** + * Default values for OperationGroup instances. + * @default {@link Models.HistoryGroup.default_data|HistoryGroup.default_data} + + * {'transfers': []} + * @see {@link Models.ModelObject.default_data|ModelObject.default_data} + */ + static get default_data() { + return $.extend({}, HistoryGroup.default_data, + {'transfers': []}); + } + + /** + * Verbose name for TransferGroup model + * @default 'transfergroup' + */ + static get verbose_name() { return 'transfergroup'; } + + /** * @default {@link Formatters.TransferGroupFormatter} */ @@ -707,7 +739,7 @@ class Operation extends ModelObject { * @see {@link Models.ModelObject.props|ModelObject.props} */ static get props() { - return ['id', 'amount', 'canceled_at', 'canceled_by']; + return ['id', 'amount', 'canceled_at', 'canceled_by', 'group']; } /** @@ -716,7 +748,8 @@ class Operation extends ModelObject { * @see {@link Models.ModelObject.default_data|ModelObject.default_data} */ static get default_data() { - return {'id': '', 'amount': 0, 'canceled_at': undefined, 'canceled_by': '' }; + return {'id': '', 'amount': 0, 'canceled_at': undefined, 'canceled_by': '', + 'group': new HistoryGroup()}; } get amount() { return this._amount; } @@ -765,6 +798,13 @@ class Purchase extends Operation { }); } + /** + * Verbose name for Purchase model + * @default 'purchase' + */ + static get verbose_name() { return 'purchase'; } + + /** * @default {@link Formatters.PurchaseFormatter} */ @@ -786,9 +826,16 @@ class SpecialOperation extends Operation { * @see {@link Models.ModelObject.props|ModelObject.props} */ static get props() { - return Operation.props.concat(['type', 'is_checkout']); + return Operation.props.concat(['type']); } + /** + * Verbose name for SpecialOperation model + * @default 'specialope' + */ + static get verbose_name() { return 'specialope'; } + + /** * Verbose names for operation types * @type {Object} @@ -808,7 +855,7 @@ class SpecialOperation extends Operation { * @see {@link Models.ModelObject.default_data|ModelObject.default_data} */ static get default_data() { - return $.extend({}, Operation.default_data, {'type': '', 'is_checkout': false}); + return $.extend({}, Operation.default_data, {'type': ''}); } /** @@ -835,6 +882,12 @@ class Transfer extends Operation { return Operation.props.concat(['from_acc', 'to_acc']); } + /** + * Verbose name for Transfer model + * @default 'transfer' + */ + static get verbose_name() { return 'transfer'; } + /** * Default values for Transfer model instances * @default {@link Models.Operation.default_data|Operation.default_data} + {'from_acc': '', 'to_acc': ''} @@ -873,6 +926,13 @@ class ModelForest { this.from(datalist || []); } + /** + * Return true if instance is empty + */ + is_empty() { + return this.roots.length == 0; + } + /** * Shortcut functions to get parent and children of a given node */ @@ -920,11 +980,11 @@ class ModelForest { if (direction >= 0) { var child_name = struct_data.children; - var child_struct = this.constructor.structure[child_name]; if (data.children && data.children.length) { for (let child_data of data.children) { var child = this.get_or_create(child_data, 1); - child[child_struct.parent] = node; + var child_parent = this.constructor.structure[child.constructor.verbose_name]; + child[child_parent] = node; node[child_name].push(child); } } @@ -1008,7 +1068,8 @@ class ModelForest { var $to_insert = this.render_element(first_missing, templates, options); if (existing) { - $container.find('#'+existing.modelname+'-'+existing.content.id+'>:first-child').after($to_insert); + $container.find('#'+existing.constructor.verbose_name+'-'+existing.id+'>:first-child') + .after($to_insert); } else { $container.prepend($to_insert); } @@ -1021,6 +1082,9 @@ class ModelForest { * @param {Object} [options] Options for element render method */ display($container, templates, options) { + if (this.is_empty()) + return; + if (this.constructor.root_sort) this.roots.sort(this.constructor.root_sort); else @@ -1161,14 +1225,34 @@ class OperationList extends APIModelForest { * @default [Operation, OperationGroup, Day] * @see {@link Models.ModelList.models|ModelList.models} */ - static get models() { + static get structure() { return { - 'day': Day, - 'opegroup': OperationGroup, - 'transfergroup': TransferGroup, - 'purchase': Purchase, - 'specialope': SpecialOperation, - 'transfer': Transfer, + 'day': { + 'model': Day, + 'children': 'opegroups' + }, + 'opegroup': { + 'model': OperationGroup, + 'parent': 'day', + 'children': 'opes', + }, + 'transfergroup': { + 'model': TransferGroup, + 'parent': 'day', + 'children': 'transfers' + }, + 'purchase': { + 'model': Purchase, + 'parent': 'opegroup', + }, + 'specialope': { + 'model': SpecialOperation, + 'parent': 'opegroup', + }, + 'transfer': { + 'model': Transfer, + 'parent': 'transfergroup', + }, }; } @@ -1583,10 +1667,10 @@ class OperationFormatter extends Formatter { /** * Properties renderable to html. - * @default ['amount', 'infos1', 'infos2', 'addcost', 'canceled'] + * @default ['amount', 'infos1', 'infos2', 'canceled'] */ static get props() { - return ['amount', 'infos1', 'infos2', 'addcost', 'canceled']; + return ['amount', 'infos1', 'infos2', 'canceled']; } static get attrs() { @@ -1597,19 +1681,7 @@ class OperationFormatter extends Formatter { * a.amount displayed according to a.is_cof and a.trigramme values. */ static prop_amount(a) { - return amountDisplay(a.amount, a.is_cof, a.trigramme); - } - - /** - * addcost property is displayed iff a.addcost_for is nonempty. - */ - static prop_addcost(a) { - if (a.addcost_for) { - return '('+amountDisplay(a.addcost_amount, a.is_cof) - +'UKF pour '+a.addcost_for+')'; - } else { - return ''; - } + return amountDisplay(a.amount, a.group.is_cof, a.group.trigramme); } /** @@ -1639,6 +1711,22 @@ class OperationFormatter extends Formatter { */ class PurchaseFormatter extends OperationFormatter { + static get props() { + return OperationFormatter.props.concat(['addcost']); + } + + /** + * addcost property is displayed iff a.addcost_for is nonempty. + */ + static prop_addcost(a) { + if (a.addcost_for) { + return '('+amountDisplay(a.addcost_amount, a.is_cof) + +'UKF pour '+a.addcost_for+')'; + } else { + return ''; + } + } + static prop_infos1(a) { return a.article_nb; } diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 3aefb527..c1e5fec6 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -648,72 +648,6 @@ $(document).ready(function() { } -<<<<<<< HEAD -======= - // ----- - // Cancel from history - // ----- - - khistory.$container.selectable({ - filter: 'div.opegroup, div.ope', - selected: function(e, ui) { - $(ui.selected).each(function() { - if ($(this).hasClass('opegroup')) { - var opegroup = $(this).data('opegroup'); - $(this).siblings('.ope').filter(function() { - return $(this).data('opegroup') == opegroup - }).addClass('ui-selected'); - } - }); - }, - }); - - $(document).on('keydown', function (e) { - if (e.keyCode == 46) { - // DEL (Suppr) - var opes_to_cancel = []; - khistory.$container.find('.ope.ui-selected').each(function () { - opes_to_cancel.push($(this).data('ope')); - }); - if (opes_to_cancel.length > 0) - cancelOperations(opes_to_cancel); - } - }); - - // ----- - // Synchronization - // ----- - - OperationWebSocket.add_handler(function(data) { - for (var i=0; i>>>>>> origin/aureplop/kpsul_js_refactor - // ----- // General // ----- diff --git a/kfet/views.py b/kfet/views.py index 57e7ae95..7826f31d 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1168,7 +1168,6 @@ def kpsul_perform_operations(request): websocket_data = {} websocket_data['opegroups'] = [{ 'add': True, -<<<<<<< HEAD 'modelname': 'opegroup', 'content': { 'id': operationgroup.pk, @@ -1189,48 +1188,17 @@ def kpsul_perform_operations(request): 'id': operationgroup.at.strftime('%Y%m%d'), 'date': operationgroup.at }, - 'child_sort': 'opegroup', }, 'children': [], -======= - 'id': operationgroup.pk, - 'amount': operationgroup.amount, - 'checkout__name': operationgroup.checkout.name, - 'at': operationgroup.at, - 'is_cof': operationgroup.is_cof, - 'comment': operationgroup.comment, - 'valid_by__trigramme': (operationgroup.valid_by and - operationgroup.valid_by.trigramme or None), - 'on_acc__trigramme': operationgroup.on_acc.trigramme, - 'opes': [], ->>>>>>> origin/aureplop/kpsul_js_refactor }] for ope in operations: ope_data = { -<<<<<<< HEAD 'content': { 'id': ope.id, 'amount': ope.amount, - 'canceled_at': ope.canceled_at, - 'canceled_by': - ope.canceled_by and ope.canceled_by.trigramme or None, - 'is_cof': operationgroup.is_cof, - 'trigramme': ( - operationgroup.on_acc and - operationgroup.on_acc.trigramme or None), + 'canceled_at': None, + 'canceled_by': None, }, -======= - 'id': operation.pk, 'type': operation.type, - 'amount': operation.amount, - 'addcost_amount': operation.addcost_amount, - 'addcost_for__trigramme': ( - operation.addcost_for and addcost_for.trigramme or None), - 'article__name': ( - operation.article and operation.article.name or None), - 'article_nb': operation.article_nb, - 'group_id': operationgroup.pk, - 'canceled_by__trigramme': None, 'canceled_at': None, ->>>>>>> origin/aureplop/kpsul_js_refactor } if ope.type == Operation.PURCHASE: @@ -1246,7 +1214,6 @@ def kpsul_perform_operations(request): ope_data['modelname'] = 'specialope' ope_data['content'].update({ 'type': ope.type, - 'is_checkout': ope.is_checkout, }) websocket_data['opegroups'][0]['children'].append(ope_data) # Need refresh from db cause we used update on queryset @@ -1586,7 +1553,6 @@ def history_json(request): 'id': opegroup.at.strftime('%Y%m%d'), 'date': opegroup.at }, - 'child_sort': 'opegroup', }, 'children': [], } @@ -1643,7 +1609,6 @@ def history_json(request): 'id': transfergroup.at.strftime('%Y%m%d'), 'date': transfergroup.at }, - 'child_sort': 'transfergroup', }, 'children': [], }