diff options
Diffstat (limited to 'ishtar_common')
| -rw-r--r-- | ishtar_common/forms_common.py | 68 | ||||
| -rw-r--r-- | ishtar_common/models.py | 79 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/forms/qa_document_duplicate.html | 95 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/sheet_document.html | 2 | ||||
| -rw-r--r-- | ishtar_common/urls.py | 4 | ||||
| -rw-r--r-- | ishtar_common/views.py | 26 | 
6 files changed, 245 insertions, 29 deletions
diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 7a6f2fe72..31eb5c7d2 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -1302,9 +1302,9 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType):                  not cleaned_data.get('image', None) and \                  not cleaned_data.get('associated_file', None) and \                  not cleaned_data.get('associated_url', None): -            raise forms.ValidationError(_(u"You should at least fill one of " -                                          u"this field: title, url, image or " -                                          u"file.")) +            raise forms.ValidationError(_("You should at least fill one of " +                                          "this field: title, url, image or " +                                          "file."))          for rel in models.Document.RELATED_MODELS:              if cleaned_data.get(rel, None):                  return cleaned_data @@ -1477,6 +1477,68 @@ class QADocumentFormMulti(QAForm):          return value +class QADocumentDuplicateForm(IshtarForm): +    qa_title = forms.CharField(label=_("Reference"), max_length=500, +                               required=False) +    qa_source_type = forms.ChoiceField(label=_("Type"), choices=[], +                                       required=False) + +    TYPES = [ +        FieldType('qa_source_type', models.SourceType), +    ] + +    def __init__(self, *args, **kwargs): +        self.user = None +        if 'user' in kwargs: +            self.user = kwargs.pop('user') +            if hasattr(self.user, 'ishtaruser'): +                self.user = self.user.ishtaruser +        self.document = kwargs.pop('items')[0] +        super(QADocumentDuplicateForm, self).__init__(*args, **kwargs) + +        self.fields['qa_title'].initial = self.document.title + str( +            _(" - duplicate")) +        if self.document.source_type: +            self.fields['qa_source_type'].initial = self.document.source_type.pk + +        for related_key in models.Document.RELATED_MODELS_ALT: +            related = getattr(self.document, related_key) +            if not related.count(): +                continue +            model = models.Document._meta.get_field(related_key).related_model +            initial = [] +            for item in related.all(): +                initial.append(item.pk) +            self.fields["qa_" + related_key] = widgets.Select2MultipleField( +                model=model, remote=True, label=model._meta.verbose_name_plural, +                required=False, long_widget=True, initial=initial +            ) + +    def save(self): +        data = {"index": None} +        for k in ["title"]: +            data[k] = self.cleaned_data.get("qa_" + k, None) +        if self.cleaned_data.get("qa_source_type", None): +            try: +                data["source_type"] = models.SourceType.objects.get( +                    pk=int(self.cleaned_data["qa_source_type"]), available=True) +            except models.SourceType.DoesNotExist: +                return +        new = self.document.duplicate_item(self.user, data=data) +        for related_key in models.Document.RELATED_MODELS_ALT: +            getattr(new, related_key).clear() +            values = self.cleaned_data.get("qa_" + related_key, []) +            model = models.Document._meta.get_field(related_key).related_model +            for value in values: +                getattr(new, related_key).add(model.objects.get(pk=value)) +        new.skip_history_when_saving = True +        new._cached_label_checked = False +        new._search_updated = False +        new._no_move = True +        new.save()  # regen of labels +        return new + +  class QALockForm(forms.Form):      action = forms.ChoiceField(          label=_("Action"), choices=(('lock', _("Lock")), diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 7238d7782..dc2fef815 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1212,7 +1212,7 @@ class HistoryError(Exception):          return repr(self.value) -PRIVATE_FIELDS = ('id', 'history_modifier', 'order') +PRIVATE_FIELDS = ('id', 'history_modifier', 'order', 'uuid')  class BulkUpdatedItem(object): @@ -2127,6 +2127,34 @@ class CascasdeUpdate:                      post_save_geo(item.__class__, instance=item) +def duplicate_item(item, user=None, data=None): +    model = item.__class__ +    new = model.objects.get(pk=item.pk) + +    for field in model._meta.fields: +        # pk is in PRIVATE_FIELDS so: new.pk = None and a new +        # item will be created on save +        if field.name == "uuid": +            new.uuid = uuid.uuid4() +        elif field.name in PRIVATE_FIELDS: +            setattr(new, field.name, None) +    if user: +        new.history_user = user +    if data: +        for k in data: +            setattr(new, k, data[k]) +    new.save() + +    # m2m fields +    m2m = [field.name for field in model._meta.many_to_many +           if field.name not in PRIVATE_FIELDS] +    for field in m2m: +        for val in getattr(item, field).all(): +            if val not in getattr(new, field).all(): +                getattr(new, field).add(val) +    return new + +  class BaseHistorizedItem(StatisticItem, TemplateItem, FullSearch, Imported,                           JsonData, FixAssociated, CascasdeUpdate):      """ @@ -2194,29 +2222,7 @@ class BaseHistorizedItem(StatisticItem, TemplateItem, FullSearch, Imported,          return {}      def duplicate(self, user=None, data=None): -        model = self.__class__ -        new = model.objects.get(pk=self.pk) - -        for field in model._meta.fields: -            # pk is in PRIVATE_FIELDS so: new.pk = None and a new -            # item will be created on save -            if field.name in PRIVATE_FIELDS: -                setattr(new, field.name, None) -        if user: -            new.history_user = user -        if data: -            for k in data: -                setattr(new, k, data[k]) -        new.save() - -        # m2m fields -        m2m = [field.name for field in model._meta.many_to_many -               if field.name not in PRIVATE_FIELDS] -        for field in m2m: -            for val in getattr(self, field).all(): -                if val not in getattr(new, field).all(): -                    getattr(new, field).add(val) -        return new +        return duplicate_item(self, user, data)      def update_external_id(self, save=False):          if not self.EXTERNAL_ID_KEY or ( @@ -5233,7 +5239,12 @@ class Document(BaseHistorizedItem, QRCodeItem, OwnPerms, ImageModel,          text=_(u"Bulk update"), target="many",          rights=['change_document', 'change_own_document'])      QUICK_ACTIONS = [ -        QA_EDIT +        QA_EDIT, +        QuickAction( +            url="document-qa-duplicate", icon_class="fa fa-clone", +            text=_("Duplicate"), target="one", +            rights=['change_document', +                    'change_own_document']),      ]      SERIALIZATION_FILES = ["image", "thumbnail", "associated_file"] @@ -5321,6 +5332,8 @@ class Document(BaseHistorizedItem, QRCodeItem, OwnPerms, ImageModel,          return "{}-{:04d}".format(self.operation.code_patriarche or '',                                     self.index)      """ +    def duplicate_item(self, user=None, data=None): +        return duplicate_item(self, user, data)      def public_representation(self):          site = Site.objects.get_current() @@ -5352,6 +5365,22 @@ class Document(BaseHistorizedItem, QRCodeItem, OwnPerms, ImageModel,              "thumbnail": thumbnail,          } +    def get_extra_actions(self, request): +        """ +        For sheet template +        """ +        # url, base_text, icon, extra_text, extra css class, is a quick action +        actions = super(Document, self).get_extra_actions(request) +        # is_locked = self.is_locked(request.user) + +        can_edit_document = self.can_do(request, 'change_document') +        if can_edit_document: +            actions += [ +                (reverse("document-qa-duplicate", args=[self.pk]), +                 _("Duplicate"), "fa fa-clone", "", "", True), +            ] +        return actions +      @property      def thumbnail_path(self):          if not self.thumbnail: diff --git a/ishtar_common/templates/ishtar/forms/qa_document_duplicate.html b/ishtar_common/templates/ishtar/forms/qa_document_duplicate.html new file mode 100644 index 000000000..4dc04d15d --- /dev/null +++ b/ishtar_common/templates/ishtar/forms/qa_document_duplicate.html @@ -0,0 +1,95 @@ +{% extends "ishtar/forms/qa_base.html" %} +{% load i18n inline_formset table_form %} + +{% block main_form %} +{% if form.non_field_errors %} +<div class="alert alert-danger" role="alert"> +    {{form.non_field_errors}} +</div> +{% endif %} +{% with force_large_col=True %} +<div class="form-row"> +    {% with form.qa_title as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +<div class="form-row"> +    {% with form.qa_source_type as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endwith %} + +{% if form.qa_finds %} +<div class="form-row"> +    {% with form.qa_finds as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_context_records %} +<div class="form-row"> +    {% with form.qa_context_records as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_operations %} +<div class="form-row"> +    {% with form.qa_operations as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_sites %} +<div class="form-row"> +    {% with form.qa_sites as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_files %} +<div class="form-row"> +    {% with form.qa_files as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_warehouses %} +<div class="form-row"> +    {% with form.qa_warehouses as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_containers %} +<div class="form-row"> +    {% with form.qa_containers as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_treatments %} +<div class="form-row"> +    {% with form.qa_treatments as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% if form.qa_files %} +<div class="form-row"> +    {% with form.qa_treatment_files as field %} +    {% include "blocks/bs_field_snippet.html" %} +    {% endwith %} +</div> +{% endif %} + +{% endblock %} diff --git a/ishtar_common/templates/ishtar/sheet_document.html b/ishtar_common/templates/ishtar/sheet_document.html index 386b33a8a..93951c056 100644 --- a/ishtar_common/templates/ishtar/sheet_document.html +++ b/ishtar_common/templates/ishtar/sheet_document.html @@ -37,7 +37,7 @@      {% field_flex "Creation date" item.creation_date %}      {% field_flex "Receipt date" item.receipt_date %}      {% field_flex "Receipt date in documentation" item.receipt_date_in_documentation %} -    {% field_flex "Has a duplicate" item.duplicate %} +    {% if item.duplicate %}{% field_flex "Has a duplicate" item.duplicate %}{% endif %}      {% field_flex "Description" item.description %}      {% field_flex "Comment" item.comment %}      {% field_flex "Additional information" item.additional_information %} diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index 8c08ade06..cc8d3eed4 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -319,6 +319,10 @@ urlpatterns += [          check_rights(['change_document', 'change_own_document'])(              views.QADocumentForm.as_view()),          name='document-qa-bulk-update-confirm', kwargs={"confirm": True}), +    url(r'^document-qa-duplicate/(?P<pks>[0-9-]+)?/$', +        check_rights(['change_document', 'change_own_document'])( +            views.QADocumentDuplicateFormView.as_view()), +        name='document-qa-duplicate'),      url(r'^qa-not-available(?:/(?P<context>[0-9a-z-]+))?/$',          views.QANotAvailable.as_view(), name='qa-not-available'), diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 3563ac9db..4724d61b7 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -2264,6 +2264,8 @@ class QAItemForm(IshtarMixin, LoginRequiredMixin, FormView):          # check availability          quick_action = self.get_quick_action() +        if not quick_action: +            raise Http404()          if not quick_action.is_available(                  user=request.user, session=request.session):              for item in self.items: @@ -2379,3 +2381,27 @@ class QADocumentForm(QAItemEditForm):      form_class = forms.QADocumentFormMulti +class QADocumentDuplicateFormView(QAItemForm): +    template_name = 'ishtar/forms/qa_document_duplicate.html' +    model = models.Document +    page_name = _("Duplicate") +    form_class = forms.QADocumentDuplicateForm +    base_url = "document-qa-duplicate" + +    def get_form_kwargs(self): +        kwargs = super(QADocumentDuplicateFormView, +                       self).get_form_kwargs() +        kwargs['user'] = self.request.user +        return kwargs + +    def form_valid(self, form): +        form.save() +        return HttpResponseRedirect(reverse("success")) + +    def get_context_data(self, **kwargs): +        data = super(QADocumentDuplicateFormView, +                     self).get_context_data(**kwargs) +        data['action_name'] = _("Duplicate") +        return data + +  | 
