Languages

Previous versions

1.2
1.1

Source code for plmapp.views.part

#-!- coding:utf-8 -!-

############################################################################
# openPLM - open source PLM
# Copyright 2010 Philippe Joulaud, Pierre Cosquer
#
# This file is part of openPLM.
#
#    openPLM is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    openPLM is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with openPLM.  If not, see <http://www.gnu.org/licenses/>.
#
# Contact :
#    Philippe Joulaud : ninoo.fr@gmail.com
#    Pierre Cosquer : pcosquer@linobject.com
################################################################################

from django.contrib import messages
from django.http import HttpResponseRedirect, HttpResponseBadRequest
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

import openPLM.plmapp.models as models
import openPLM.plmapp.forms as forms
from openPLM.plmapp.utils.archive import ARCHIVE_FORMATS
from openPLM.plmapp.views.base import (get_obj_from_form, handle_errors, get_generic_data, get_id_card_data, get_obj_by_id)
from openPLM.plmapp.decomposers.base import DecomposersManager
from openPLM.plmapp.utils import r2r


@handle_errors
[docs]def display_children(request, obj_type, obj_ref, obj_revi): """ BOM view. That view displays the children of the selected object that must be a part. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/bom-child/` .. include:: views_params.txt **Template:** :file:`parts/bom.html` **Context:** ``RequestContext`` ``children`` a list of :class:`.Child` ``display_form`` a :class:`.DisplayChildrenForm` ``extra_columns`` a list of extra columns that are displayed ``extension_data`` ``decomposition_msg`` a html message to decompose the part (may be empty) ``decomposable_children`` a set of child part ids that are decomposable """ if "diff" in request.GET: query = request.GET.urlencode() + "&compact=on" return HttpResponseRedirect("%sdiff/?%s" % (request.path, query)) obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if not hasattr(obj, "get_children"): return HttpResponseBadRequest("object must be a part") date = None level = "first" state = "all" show_documents = show_alternates = False if request.GET: display_form = forms.DisplayChildrenForm(request.GET) if display_form.is_valid(): date = display_form.cleaned_data["date"] level = display_form.cleaned_data["level"] state = display_form.cleaned_data["state"] show_documents = display_form.cleaned_data["show_documents"] show_alternates = display_form.cleaned_data["show_alternates"] else: display_form = forms.DisplayChildrenForm(initial={"date" : timezone.now(), "level" : "first", "state":"all"}) ctx.update(obj.get_bom(date, level, state, show_documents, show_alternates)) # decomposition if DecomposersManager.count() > 0: children_ids = (c.link.child_id for c in ctx["children"]) decomposable_children = DecomposersManager.get_decomposable_parts(children_ids) decomposition_msg = DecomposersManager.get_decomposition_message(obj) else: decomposition_msg = "" decomposable_children = [] ctx.update({'current_page' : 'BOM-child', 'decomposition_msg' : decomposition_msg, 'decomposable_children' : decomposable_children, "display_form" : display_form, }) return r2r('parts/bom.html', ctx, request)
@handle_errors(undo="..")
[docs]def edit_children(request, obj_type, obj_ref, obj_revi): """ View to edit a BOM. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/bom-child/edit/` .. include:: views_params.txt **Template:** :file:`parts/bom_edit.html` **Context:** ``RequestContext`` ``children_formset`` a formset to edit the BOM ``extra_columns`` a list of extra columns that are displayed ``extra_fields`` a list of extra fields that are editable """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if not hasattr(obj, "get_children"): return HttpResponseBadRequest("object must be a part") if request.method == "POST": formset = forms.get_children_formset(obj, request.POST) if formset.is_valid(): obj.update_children(formset) return HttpResponseRedirect("..") else: formset = forms.get_children_formset(obj) extra_columns = [] extra_fields = [] for PCLE in models.get_PCLEs(obj.object): fields = PCLE.get_visible_fields() if fields: extra_columns.extend((f, PCLE._meta.get_field(f).verbose_name) for f in fields) prefix = PCLE._meta.module_name extra_fields.extend('%s_%s' % (prefix, f) for f in fields) ctx.update({'current_page':'BOM-child', 'extra_columns' : extra_columns, 'extra_fields' : extra_fields, 'children_formset': formset, }) return r2r('parts/bom_edit.html', ctx, request)
@handle_errors(undo="../..")
[docs]def replace_child(request, obj_type, obj_ref, obj_revi, link_id): """ View to replace a child by another one. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/bom-child/replace/{link_id}/` .. include:: views_params.txt :param link_id: id of the :class:`.ParentChildLink` being replaced **Template:** :file:`parts/bom_replace.html` **Context:** ``RequestContext`` ``replace_child_form`` a form to select the replacement part ``link`` :class:`.ParentChildLink` being replaced ``link_creation`` Set to True ``attach`` set to (*obj*, "add_child") """ link_id = int(link_id) obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi, load_all=True) link = models.ParentChildLink.objects.get(id=link_id) if request.method == "POST": form = forms.AddPartForm(request.POST) if form.is_valid(): obj.replace_child(link, get_obj_from_form(form, request.user)) return HttpResponseRedirect("../..") else: form = forms.AddPartForm() if ctx["results"]: obj.precompute_can_add_child2() ctx["replace_child_form"] = form ctx["link"] = link ctx["attach"] = (obj, "add_child") ctx["link_creation"] = True return r2r("parts/bom_replace.html", ctx, request)
@handle_errors
[docs]def add_child(request, obj_type, obj_ref, obj_revi): """ View to add a child to a part. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/bom-child/add/` .. include:: views_params.txt **Template:** :file:`parts/bom_add.html` **Context:** ``RequestContext`` ``add_child_form`` a form to add a child (:class:`.AddChildForm`) ``link`` :class:`.ParentChildLink` being replaced ``link_creation`` Set to True ``attach`` set to (*obj*, "add_child") """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi, load_all=True) if request.method == "POST" and request.POST: add_child_form = forms.AddChildForm(obj.object, request.POST) if add_child_form.is_valid(): child_obj = get_obj_from_form(add_child_form, request.user) obj.add_child(child_obj, add_child_form.cleaned_data["quantity"], add_child_form.cleaned_data["order"], add_child_form.cleaned_data["unit"], **add_child_form.extensions) return HttpResponseRedirect(obj.plmobject_url + "BOM-child/") else: if "type" in request.GET and request.GET["type"] in models.get_all_parts(): # use GET params only if they seems valid initial = request.GET else: initial = None add_child_form = forms.AddChildForm(obj.object, initial=initial) ctx['current_page'] = 'BOM-child' if ctx["results"]: obj.precompute_can_add_child2() orders = list(obj.parentchildlink_parent.values_list('order', flat=True)) initial_order = max(orders) + 10 if orders else 10 ctx['order'] = initial_order ctx.update({'link_creation': True, 'add_child_form': add_child_form, 'attach' : (obj, "add_child")}) return r2r('parts/bom_add.html', ctx, request)
[docs]def compare_bom(request, obj_type, obj_ref, obj_revi): obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if not hasattr(obj, "get_children"): return HttpResponseBadRequest("object must be a part") date = date2 = None level = "first" state = "all" show_documents = show_alternates = False compact = True now = timezone.now() if request.GET: cmp_form = forms.CompareBOMForm(request.GET) if cmp_form.is_valid(): date = cmp_form.cleaned_data["date"] date2 = cmp_form.cleaned_data["date2"] level = cmp_form.cleaned_data["level"] state = cmp_form.cleaned_data["state"] show_documents = cmp_form.cleaned_data["show_documents"] show_alternates = cmp_form.cleaned_data["show_documents"] compact = cmp_form.cleaned_data.get("compact", compact) else: initial = {"date" : now, "date2" : now, "level" : "first", "state" : "all", "compact" : compact, } cmp_form = forms.CompareBOMForm(initial=initial) ctx.update(obj.cmp_bom(date, date2, level, state, show_documents, show_alternates)) ctx.update({'current_page' : 'BOM-child', "cmp_form" : cmp_form, 'compact' : compact, 'date1' : date or now, 'date2' : date2 or now, }) return r2r('parts/bom_diff.html', ctx, request)
@handle_errors
[docs]def display_parents(request, obj_type, obj_ref, obj_revi): """ Parents view. That view displays the parents of the selected object that must be a part. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/parents/` .. include:: views_params.txt **Template:** :file:`parts/parents.html` **Context:** ``RequestContext`` ``parents`` a list of :class:`.Parents` ``display_form`` a :class:`.DisplayChildrenForm` """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if not hasattr(obj, "get_parents"): return HttpResponseBadRequest("object must be a part") date = None level = "first" state = "all" if request.GET: display_form = forms.DisplayChildrenForm(request.GET) if display_form.is_valid(): date = display_form.cleaned_data["date"] level = display_form.cleaned_data["level"] state = display_form.cleaned_data["state"] else: display_form = forms.DisplayChildrenForm(initial=dict(date=timezone.now(), level="first", state="all")) # FIXME: show attached documents if asked del display_form.fields["show_documents"] max_level = 1 if level == "first" else -1 only_official = state == "official" parents = obj.get_parents(max_level, date=date, only_official=only_official) ids = set([obj.id]) if level == "last" and parents: previous_level = 0 max_parents = [] for c in parents: if max_parents and c.level > previous_level: del max_parents[-1] max_parents.append(c) previous_level = c.level parents = max_parents for level, link in parents: ids.add(link.parent_id) states = models.StateHistory.objects.at(date).filter(plmobject__in=ids) if only_official: states = states.officials() states = dict(states.values_list("plmobject", "state")) ctx.update({'current_page':'parents', 'parents' : parents, 'display_form' : display_form, 'states' : states, }) return r2r('parts/parents.html', ctx, request)
@handle_errors
[docs]def alternates(request, obj_type, obj_ref, obj_revi): obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) ctx.update({ "current_page" : "alternates", "alternates" : obj.get_alternates(), }) return r2r('parts/alternates.html', ctx, request)
@handle_errors
[docs]def add_alternate(request, obj_type, obj_ref, obj_revi): obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if request.POST: add_part_form = forms.AddPartForm(request.POST) if add_part_form.is_valid(): part_obj = get_obj_from_form(add_part_form, request.user) obj.add_alternate(part_obj) return HttpResponseRedirect(obj.plmobject_url + "alternates/") else: add_part_form = forms.AddPartForm() ctx.update({'link_creation': True, 'add_part_form': add_part_form, 'attach' : (obj, "add_alternate") }) return r2r('parts/alternates_add.html', ctx, request)
@handle_errors
[docs]def delete_alternate(request, obj_type, obj_ref, obj_revi): obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if request.POST: obj.delete_alternate(obj.object) return HttpResponseRedirect(obj.plmobject_url + "alternates/")
@handle_errors
[docs]def display_doc_cad(request, obj_type, obj_ref, obj_revi): """ Attached documents view. That view displays the documents attached to the selected object that must be a part. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/doc-cad/` .. include:: views_params.txt **Template:** :file:`parts/doccad.html` **Context:** ``RequestContext`` ``documents`` a queryset of :class:`.DocumentPartLink` bound to the part ``archive_formats`` list of available archive formats ``docs_formset`` a formset to detach documents ``forms`` a dictionary (link_id -> form) to get the form related to a link (a document may not be "detachable") """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if not hasattr(obj, "get_attached_documents"): return HttpResponseBadRequest("object must be a part") if request.method == "POST": formset = forms.get_doc_cad_formset(obj, request.POST) if formset.is_valid(): obj.update_doc_cad(formset) return HttpResponseRedirect(".") else: formset = forms.get_doc_cad_formset(obj) dforms = dict((form.instance.id, form) for form in formset.forms) documents = obj.get_attached_documents() ctx.update({'current_page':'doc-cad', 'documents': documents, 'forms' : dforms, 'archive_formats' : ARCHIVE_FORMATS, 'docs_formset': formset, }) ctx.update(get_id_card_data([d.document.id for d in documents])) return r2r('parts/doccad.html', ctx, request)
@handle_errors
[docs]def add_doc_cad(request, obj_type, obj_ref, obj_revi): """ View to attach a document to a part. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/doc-cad/add/` .. include:: views_params.txt **Template:** :file:`parts/doccad_add.html` **Context:** ``RequestContext`` ``add_doc_cad_form`` a form to attach a document (:class:`.AddDocCadForm`) ``link_creation`` Set to True ``attach`` set to (*obj*, "attach_doc") """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if request.POST: add_doc_cad_form = forms.AddDocCadForm(request.POST) if add_doc_cad_form.is_valid(): doc_cad_obj = get_obj_from_form(add_doc_cad_form, request.user) obj.attach_to_document(doc_cad_obj) return HttpResponseRedirect(obj.plmobject_url + "doc-cad/") else: add_doc_cad_form = forms.AddDocCadForm() ctx.update({'link_creation': True, 'add_doc_cad_form': add_doc_cad_form, 'attach' : (obj, "attach_doc")}) return r2r('parts/doccad_add.html', ctx, request)
@handle_errors
[docs]def delete_doc_cad(request, obj_type, obj_ref, obj_revi): """ View to detach a document referred by the POST parameter ``plmobject``. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/doc-cad/delete/` .. include:: views_params.txt """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) if request.POST: doc_id = int(request.POST["plmobject"]) doc = get_obj_by_id(doc_id, request.user) obj.detach_document(doc) msg = _("The document {doc.type}/{doc.reference}/{doc.revision} has been detached.") messages.info(request, msg.format(doc=doc)) return HttpResponseRedirect(obj.plmobject_url + "doc-cad/")