diff --git a/project/docs/consts.py b/project/docs/consts.py index d984ef5..3d60337 100644 --- a/project/docs/consts.py +++ b/project/docs/consts.py @@ -19,9 +19,9 @@ NDS_TYPE_CHOICES = ( ) # ставка НДС -NDS_VALUE_0 = 1 -NDS_VALUE_10 = 2 -NDS_VALUE_18 = 3 +NDS_VALUE_0 = 0 +NDS_VALUE_10 = 0.1 +NDS_VALUE_18 = 0.18 NDS_VALUE_CHOICES = ( (NDS_VALUE_0, u'Без НДС'), diff --git a/project/docs/views/base_views.py b/project/docs/views/base_views.py index f16c18d..e70c10c 100644 --- a/project/docs/views/base_views.py +++ b/project/docs/views/base_views.py @@ -526,7 +526,8 @@ class BaseItemsViews(BaseViews): parent_model = self.MODEL, model = self.ITEM_MODEL, form = self.ITEM_FORM_CLASS, - extra=2 + extra=2, + can_delete=True, ) def get_list_qs(self): @@ -555,19 +556,15 @@ class BaseItemsViews(BaseViews): return redirect(self.REDIRECT_AFTER_ADD) if self.pformset: pformset = self.pformset(self.request.POST or None) + else: + pformset = None if self.request.method == 'POST': form = self.FORM_CLASS(self.request.user, data=self.request.POST) - if '_add_line' in self.request.POST: - post_copy = self.request.POST.copy() - total_forms_key = '%s-TOTAL_FORMS' % self.ITEM_FORM_PREFIX - post_copy[total_forms_key] = int(post_copy[total_forms_key]) + 1 - formset = self.ITEM_FORMSET_CLASS(data=post_copy, prefix=self.ITEM_FORM_PREFIX) - else: - formset = self.ITEM_FORMSET_CLASS(data=self.request.POST, prefix=self.ITEM_FORM_PREFIX) + formset = self.ITEM_FORMSET_CLASS(self.request.POST or None, prefix=self.ITEM_FORM_PREFIX) - if '_add_line' not in self.request.POST and form.is_valid() and formset.is_valid(): + if form.is_valid() and formset.is_valid() and ((not pformset) or (pformset and pformset.is_valid())): new_obj = form.save(commit=False) new_obj.user = self.request.user new_obj.save() @@ -577,13 +574,13 @@ class BaseItemsViews(BaseViews): for item in new_items: item.parent = new_obj item.save() - if pformset.is_valid(): + if pformset and pformset.is_valid(): new_items = pformset.save(commit=False) for item in new_items: item.parent = new_obj item.save() self.update_parent_on_items_save(new_obj, new_items) - return redirect(self.REDIRECT_AFTER_ADD) + return redirect(self.REDIRECT_AFTER_ADD) else: initial = kwargs.get('initial') or self.init_form() initial_items = kwargs.get('initial_items') @@ -645,39 +642,31 @@ class BaseItemsViews(BaseViews): return redirect(self.REDIRECT_AFTER_EDIT) obj = self.get_obj(kwargs['id']) - print self.pformset + if self.pformset: pformset = self.pformset(self.request.POST or None, instance=obj) - if self.request.method == 'POST': - form = self.FORM_CLASS(self.request.user, data=self.request.POST, instance=obj) - - if '_add_line' in self.request.POST: - post_copy = self.request.POST.copy() - total_forms_key = '%s-TOTAL_FORMS' % self.ITEM_FORM_PREFIX - post_copy[total_forms_key] = int(post_copy[total_forms_key]) + 1 - formset = self.ITEM_FORMSET_CLASS(data=post_copy, prefix=self.ITEM_FORM_PREFIX, instance=obj) - else: - formset = self.ITEM_FORMSET_CLASS(data=self.request.POST, prefix=self.ITEM_FORM_PREFIX, instance=obj) - - if '_add_line' not in self.request.POST and form.is_valid() and formset.is_valid(): - new_obj = form.save() - # сохранить табличную часть - if formset.is_valid(): - items = formset.save(commit=False) - for item in items: - item.parent = new_obj - item.save() - self.update_parent_on_items_save(new_obj, items) - if pformset.is_valid(): - items = pformset.save(commit=False) - for item in items: - item.parent = new_obj - item.save() - self.update_parent_on_items_save(new_obj, items) - return redirect(self.REDIRECT_AFTER_EDIT) else: - form = self.FORM_CLASS(self.request.user, instance=obj) - formset = self.ITEM_FORMSET_CLASS(instance=obj) + pformset = None + + formset = self.ITEM_FORMSET_CLASS(self.request.POST or None, prefix=self.ITEM_FORM_PREFIX, instance=obj) + form = self.FORM_CLASS(self.request.user, data=self.request.POST or None, instance=obj) + + if form.is_valid() and formset.is_valid() and ((not pformset) or (pformset and pformset.is_valid())): + new_obj = form.save() + # сохранить табличную часть + if formset.is_valid(): + items = formset.save(commit=False) + for item in items: + item.parent = new_obj + item.save() + self.update_parent_on_items_save(new_obj, items) + if pformset and pformset.is_valid(): + items = pformset.save(commit=False) + for item in items: + item.parent = new_obj + item.save() + self.update_parent_on_items_save(new_obj, items) + return redirect(self.REDIRECT_AFTER_EDIT) dictionary = { 'padeji': self.PADEJI, diff --git a/project/static/js/formset-events.js b/project/static/js/formset-events.js new file mode 100644 index 0000000..d7cc250 --- /dev/null +++ b/project/static/js/formset-events.js @@ -0,0 +1,43 @@ +$(function($) { + var calc_summa = function (e) { + var $this = $(this); + var qty = parseFloat($this.closest('tr.row').find('td.qty input').val()); + var price = parseFloat($this.closest('tr.row').find('td.price input').val()); + var total_price = qty * price; + if (total_price) { + $this.closest('tr.row').find('td.total_price input').val(qty * price); + } + } + window.calc_itogo = function (e) { + var itogo_sum = 0; + $('#tbl_items').find('.total_price input:visible').each(function(){ + var itogo_sum_row = $(this).val()? parseInt($(this).val()) : 0; + itogo_sum += itogo_sum_row; + }) + $('#itogo').html(itogo_sum); + } + var calc_itogo_nds = function() { + $('#itogo_nds_text').html('НДС ' + $('#id_nds_value option:selected').text()); + $('#itogo_nds').html($('#id_nds_value').val() * parseInt($('#itogo').html())); + } + + window.set_events = function set_events() { + $("#tbl_items tr.row td.qty input").on('keyup', calc_summa); + $("#tbl_items tr.row td.price input").on('keyup', calc_summa); + + $("#tbl_items tr.row td.qty input").blur(window.calc_itogo); + $("#tbl_items tr.row td.price input").blur(window.calc_itogo); + $("#tbl_items tr.row td.total_price input").blur(window.calc_itogo); + + //$('input[name=nds_type]').change(calc_itogo_nds); + $('#id_nds_value').change(calc_itogo_nds); + +// + //$("#tbl_items tr.row td.qty input").blur(calc_itogo_nds); + //$("#tbl_items tr.row td.price input").blur(calc_itogo_nds); + //$("#tbl_items tr.row td.total_price input").blur(calc_itogo_nds); + } + window.set_events(); + window.calc_itogo(); + calc_itogo_nds(); +}) \ No newline at end of file diff --git a/project/static/js/lib/jquery.formset.js b/project/static/js/lib/jquery.formset.js new file mode 100644 index 0000000..a659276 --- /dev/null +++ b/project/static/js/lib/jquery.formset.js @@ -0,0 +1,212 @@ +/** + * jQuery Formset 1.2.1 + * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com) + * @requires jQuery 1.2.6 or later + * + * Copyright (c) 2009, Stanislaus Madueke + * All rights reserved. + * + * Licensed under the New BSD License + * See: http://www.opensource.org/licenses/bsd-license.php + */ +;(function($) { + $.fn.formset = function(opts) + { + var options = $.extend({}, $.fn.formset.defaults, opts), + flatExtraClasses = options.extraClasses.join(' '), + $$ = $(this), + $$formsetContainer = $$.parent(), + + applyExtraClasses = function(row, ndx) { + if (options.extraClasses) { + row.removeClass(flatExtraClasses); + row.addClass(options.extraClasses[ndx % options.extraClasses.length]); + } + }, + + updateElementIndex = function(elem, prefix, ndx) { + var idRegex = new RegExp('(' + prefix + '-\\d+-)'), + replacement = prefix + '-' + ndx + '-'; + if (elem.attr("for")) elem.attr("for", elem.attr("for").replace(idRegex, replacement)); + if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement)); + if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement)); + }, + + hasChildElements = function(row) { + return row.find('input,select,textarea,label').length > 0; + }, + + insertDeleteLink = function(row) { + if (row.is('TR')) { + // If the forms are laid out in table rows, insert + // the remove button into the last table cell: + row.children(':last').append('' + options.deleteText + ''); + } else if (row.is('UL') || row.is('OL')) { + // If they're laid out as an ordered/unordered list, + // insert an
  • after the last list item: + row.append('
  • ' + options.deleteText +'
  • '); + } else { + // Otherwise, just insert the remove button as the + // last child element of the form's container: + row.append('' + options.deleteText +''); + } + row.find('a.' + options.deleteCssClass).click(function() { + var row = $(this).parents('.' + options.formCssClass), + del = row.find('input:hidden[id $= "-DELETE"]'); + if (options.beforeremove) options.beforeremove(row) + if (del.length) { + // We're dealing with an inline formset; rather than remove + // this form from the DOM, we'll mark it as deleted and hide + // it, then let Django handle the deleting: + del.val('on'); + row.hide(); + } else { + row.remove(); + // Update the TOTAL_FORMS form count. + // Also update names and IDs for all remaining form controls so they remain in sequence: + var forms = $('.' + options.formCssClass).not('.formset-custom-template'); + $('#id_' + options.prefix + '-TOTAL_FORMS').val(forms.length); + for (var i=0, formCount=forms.length; i 0) { + if (formCount <= options.min_num) { + $$formsetContainer.find('.'+options.deleteCssClass).hide() + } else { + $$formsetContainer.find('.'+options.deleteCssClass+':gt('+(options.min_num-1)+')').show() + } + } + if (max_num > 0) { + if (formCount >= max_num) { + $$formsetContainer.find('.'+options.addCssClass).hide() + } else { + $$formsetContainer.find('.'+options.addCssClass).show() + } + } + }; + + $$.each(function(i) { + var row = $(this), + del = row.find('input:checkbox[id $= "-DELETE"]'); + if (del.length) { + // If you specify "can_delete = True" when creating an inline formset, + // Django adds a checkbox to each form in the formset. + // Replace the default checkbox with a hidden field: + del.before(''); + del.remove(); + } + if (hasChildElements(row)) { + insertDeleteLink(row); + row.addClass(options.formCssClass); + applyExtraClasses(row, i); + } + checkActionButtons() + }); + + if ($$.length) { + var addButton, template; + if (options.formTemplate) { + // If a form template was specified, we'll clone it to generate new form instances: + template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate); + template.removeAttr('id').addClass(options.formCssClass).addClass('formset-custom-template'); + template.find('input,select,textarea,label').each(function() { + updateElementIndex($(this), options.prefix, 2012); + }); + insertDeleteLink(template); + } else { + // Otherwise, use the last form in the formset; this works much better if you've got + // extra (>= 1) forms (thnaks to justhamade for pointing this out): + template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id'); + template.find('input:hidden[id $= "-DELETE"]').remove(); + template.find('input,select,textarea,label').each(function() { + var elem = $(this); + // If this is a checkbox or radiobutton, uncheck it. + // This fixes Issue 1, reported by Wilson.Andrew.J: + if (elem.is('input:checkbox') || elem.is('input:radio')) { + elem.attr('checked', false); + } else { + elem.val(''); + } + }); + } + // FIXME: Perhaps using $.data would be a better idea? + options.formTemplate = template; + + if ($$.attr('tagName') == 'TR') { + // If forms are laid out as table rows, insert the + // "add" button in a new table row: + var numCols = $$.eq(0).children().length; + $$.parent().append('' + options.addText + ''); + addButton = $$.parent().find('tr:last a'); + addButton.parents('tr').addClass(options.formCssClass + '-add'); + } else { + // Otherwise, insert it immediately after the last form: + $$.filter(':last').after('' + options.addText + ''); + addButton = $$.filter(':last').next(); + } + addButton.click(function() { + var formCount = parseInt($('#id_' + options.prefix + '-TOTAL_FORMS').val()), + row = options.formTemplate.clone(true).removeClass('formset-custom-template'), + buttonRow = $(this).parents('tr.' + options.formCssClass + '-add').get(0) || this; + applyExtraClasses(row, formCount); + console.log(options); + if (options.beforeadd) options.beforeadd(row); + row.insertBefore($(buttonRow)).show(); + row.find('input,select,textarea,label').each(function() { + var elem = $(this); + updateElementIndex(elem, options.prefix, formCount); + if (elem.is('input:checkbox') || elem.is('input:radio')) { + elem.attr('checked', false); + } else { + elem.val(''); + } + }); + $('#id_' + options.prefix + '-TOTAL_FORMS').val(formCount + 1); + // If a post-add callback was supplied, call it with the added form: + checkActionButtons(); + if (options.added) options.added(row); + return false; + }); + checkActionButtons(); + } + + return $$; + } + + /* Setup plugin defaults */ + var clearErrors = function(row) { + $(row).find('.errorlist').remove(); + } + var calc_itogo = function(row) { + window.calc_itogo(); + } + $.fn.formset.defaults = { + prefix: 'form', // The form prefix for your django formset + min_num: 0, // Minimum count rows + formTemplate: null, // The jQuery selection cloned to generate new form instances + addText: '+ Добавить строку', // Text for the add link + deleteText: 'Удалить', // Text for the delete link + addCssClass: 'add-row', // CSS class applied to the add link + deleteCssClass: 'delete-row', // CSS class applied to the delete link + formCssClass: 'dynamic-form', // CSS class applied to each form in a formset + extraClasses: [], // Additional CSS classes, which will be applied to each form in turn + beforeadd: clearErrors, // Function called each time before a new form is added + added: window.set_events, // Function called each time a new form is added + beforeremove: null, // Function called each time before a new form is added + removed: calc_itogo // Function called each time a form is deleted + }; +})(jQuery) diff --git a/project/templates/base.html b/project/templates/base.html index aa21ecf..9f7394a 100644 --- a/project/templates/base.html +++ b/project/templates/base.html @@ -58,6 +58,8 @@ + + diff --git a/project/templates/docs/faktura/form.html b/project/templates/docs/faktura/form.html index 0da7ff6..78faee2 100644 --- a/project/templates/docs/faktura/form.html +++ b/project/templates/docs/faktura/form.html @@ -39,26 +39,4 @@ {% endblock %} {% block js %} -{% comment %}{% endcomment %} {% endblock %} diff --git a/project/templates/docs/faktura/stub_js.html b/project/templates/docs/faktura/stub_js.html new file mode 100644 index 0000000..4e3bc1d --- /dev/null +++ b/project/templates/docs/faktura/stub_js.html @@ -0,0 +1,11 @@ +{# заглушка js #} + \ No newline at end of file diff --git a/project/templates/docs/parts/faktura_form_plat_doc_items.html b/project/templates/docs/parts/faktura_form_plat_doc_items.html index f991edf..4336c11 100644 --- a/project/templates/docs/parts/faktura_form_plat_doc_items.html +++ b/project/templates/docs/parts/faktura_form_plat_doc_items.html @@ -1,17 +1,20 @@ {# табличная часть документа #} - +
    + {% for pform in pformset %} - + {{ pform.id }} @@ -20,13 +23,7 @@ {% endfor %} - - - - - +
    К плат. документу От
    + {{ pform.num.errors }} {{ pform.num }} + {{ pform.doc_date.errors }} {{ pform.doc_date }}
    - -
    {{ pformset.management_form }} diff --git a/project/templates/docs/parts/faktura_form_tbl_items.html b/project/templates/docs/parts/faktura_form_tbl_items.html index 4adf663..81bb9d4 100644 --- a/project/templates/docs/parts/faktura_form_tbl_items.html +++ b/project/templates/docs/parts/faktura_form_tbl_items.html @@ -12,29 +12,37 @@ {% for iform in formset %} - + + {{ iform.name.errors }} {{ iform.name }} + {{ iform.units.errors }} {{ iform.units }} + {{ iform.units_kod.errors }} {{ iform.units_kod }} + {{ iform.qty.errors }} {{ iform.qty }} + {{ iform.price.errors }} {{ iform.price }} + {{ iform.total_price.errors }} {{ iform.total_price }} - + + {{ iform.country_code.errors }} {{ iform.country_code }} - + + {{ iform.country_name.errors }} {{ iform.country_name }} {{ iform.id }} @@ -47,7 +55,6 @@ - Итого diff --git a/project/templates/docs/parts/form_tbl_items.html b/project/templates/docs/parts/form_tbl_items.html index 1068069..893021f 100644 --- a/project/templates/docs/parts/form_tbl_items.html +++ b/project/templates/docs/parts/form_tbl_items.html @@ -11,23 +11,27 @@ {% for iform in formset %} - + {% for field in iform %} {% if field.name == "id" or field.name == "parent" %} {{ field }} {% else %} - + {% if field.name != "DELETE" %} + {{ field.errors }} {{ field }} + {% endif %} {% endif %} {% endfor %} + + {{ iform.DELETE }} + {% endfor %} - Итого diff --git a/project/templates/docs/stub_js.html b/project/templates/docs/stub_js.html index 9673769..4e3bc1d 100644 --- a/project/templates/docs/stub_js.html +++ b/project/templates/docs/stub_js.html @@ -1 +1,11 @@ {# заглушка js #} + \ No newline at end of file