Example #1
0
def get_obj(obj_type, obj_ref, obj_revi, user):
    """
    Get type, reference and revision of an object and return the related controller
    
    :param obj_type: :attr:`.PLMObject.type`
    :type obj_type: str
    :param obj_ref: :attr:`.PLMObject.reference`
    :type obj_ref: str
    :param obj_revi: :attr:`.PLMObject.revision`
    :type obj_revi: str
    :return: a :class:`PLMObjectController` or a :class:`UserController`
    """
    if obj_type == 'User':
        obj = get_object_or_404(User, username=obj_ref)
        controller_cls = UserController
    elif obj_type == 'Group':
        obj = get_object_or_404(Group, name=obj_ref)
        controller_cls = GroupController
    else:
        obj = get_object_or_404(models.PLMObject, type=obj_type,
                                reference=obj_ref,
                                revision=obj_revi)
        # guess what kind of PLMObject (Part, Document) obj is
        cls = models.PLMObject
        find = True
        while find:
            find = False
            for c in cls.__subclasses__():
                if hasattr(obj, c.__name__.lower()):
                    cls  = c
                    obj = getattr(obj, c.__name__.lower())
                    find = True
        controller_cls = get_controller(obj_type)
    return controller_cls(obj, user)
Example #2
0
    def clone(self,form, user, block_mails=False, no_index=False):
        """
        .. versionadded:: 1.1

        Clone this object and return the related controller.

        :param form: the form sent from clone view
        :param user: the user who is cloning the object
        """
        self.check_clone()
        type_= self.object.type
        ctrl_cls = get_controller(type_)
        if form.is_valid():
            creation_fields = self.get_creation_fields()
            data = {}
            for field in form.cleaned_data :
                if field in creation_fields:
                    data[field]=form.cleaned_data[field]
            ref = form.cleaned_data["reference"]
            rev = form.cleaned_data["revision"]
            new_ctrl = ctrl_cls.create(ref, type_ , rev, user, data,
                    block_mails, no_index)
            return new_ctrl
        else:
            raise ValueError("form is invalid")
Example #3
0
    def clone(self, form, user, block_mails=False, no_index=False):
        """
        .. versionadded:: 1.1

        Clone this object and return the related controller.

        :param form: the form sent from clone view
        :param user: the user who is cloning the object
        """
        self.check_clone()
        type_ = self.object.type
        ctrl_cls = get_controller(type_)
        if form.is_valid():
            creation_fields = self.get_creation_fields()
            data = {}
            for field in form.cleaned_data:
                if field in creation_fields:
                    data[field] = form.cleaned_data[field]
            ref = form.cleaned_data["reference"]
            rev = form.cleaned_data["revision"]
            new_ctrl = ctrl_cls.create(ref, type_, rev, user, data,
                                       block_mails, no_index)
            return new_ctrl
        else:
            raise ValueError("form is invalid")
Example #4
0
def _save_comment_history(sender, comment, request, **kwargs):
    """
    Save an history line when a comment is posted.
    """
    from openPLM.plmapp.controllers import get_controller
    obj = comment.content_object
    ctrl_cls = get_controller(obj.__class__.__name__)
    ctrl = ctrl_cls(comment.content_object, request.user, no_index=True)
    ctrl._save_histo("New comment", comment.comment)
Example #5
0
def _save_comment_history(sender, comment, request, **kwargs):
    """
    Save an history line when a comment is posted.
    """
    from openPLM.plmapp.controllers import get_controller
    obj = comment.content_object
    ctrl_cls = get_controller(obj.__class__.__name__)
    ctrl = ctrl_cls(comment.content_object, request.user, no_index=True)
    ctrl._save_histo("New comment", comment.comment)
Example #6
0
def get_obj_by_id(obj_id, user):
    u"""
    Returns an adequate controller for the object identify by *obj_id*.
    The returned controller is instanciate with *user* as the user
    who modify the object.

    :param obj_id: id of a :class:`.PLMObject`
    :param user: a :class:`.django.contrib.auth.models.User`
    :return: a subinstance of a :class:`.PLMObjectController`
    """

    obj = get_object_or_404(models.PLMObject, id=obj_id)
    obj = models.get_all_plmobjects()[obj.type].objects.get(id=obj_id)
    return get_controller(obj.type)(obj, user)
Example #7
0
def get_obj_by_id(obj_id, user):
    u"""
    Returns an adequate controller for the object identify by *obj_id*.
    The returned controller is instanciate with *user* as the user
    who modify the object.

    :param obj_id: id of a :class:`.PLMObject`
    :param user: a :class:`.django.contrib.auth.models.User`
    :return: a subinstance of a :class:`.PLMObjectController`
    """

    obj = get_object_or_404(models.PLMObject, id=obj_id)
    obj = models.get_all_plmobjects()[obj.type].objects.get(id=obj_id)
    return get_controller(obj.type)(obj, user)
Example #8
0
def get_obj(obj_type, obj_ref, obj_revi, user):
    """
    Get type, reference and revision of an object and return the related controller

    :param obj_type: :attr:`.PLMObject.type`
    :type obj_type: str
    :param obj_ref: :attr:`.PLMObject.reference`
    :type obj_ref: str
    :param obj_revi: :attr:`.PLMObject.revision`
    :type obj_revi: str
    :return: a :class:`PLMObjectController` or a :class:`UserController`
    """
    controller_cls = get_controller(obj_type)
    return controller_cls.load(obj_type, obj_ref, obj_revi, user)
Example #9
0
def get_obj(obj_type, obj_ref, obj_revi, user):
    """
    Get type, reference and revision of an object and return the related controller

    :param obj_type: :attr:`.PLMObject.type`
    :type obj_type: str
    :param obj_ref: :attr:`.PLMObject.reference`
    :type obj_ref: str
    :param obj_revi: :attr:`.PLMObject.revision`
    :type obj_revi: str
    :return: a :class:`PLMObjectController` or a :class:`UserController`
    """
    controller_cls = get_controller(obj_type)
    return controller_cls.load(obj_type, obj_ref, obj_revi, user)
Example #10
0
File: api.py Project: amarh/openPLM
def create(request):
    """
    Creates a :class:`.PLMObject` and returns it

    :implements: :func:`http_api.create`
    """
    try:
        type_name = request.POST["type"]
        cls = models.get_all_plmobjects()[type_name]
    except KeyError:
        return {"result" : "error", 'error' : 'bad type'}
    form = forms.get_creation_form(request.user, cls, request.POST)
    if form.is_valid():
        controller_cls = get_controller(type_name)
        controller = controller_cls.create_from_form(form, request.user)
        ret = {"object" : object_to_dict(controller)}
        return ret
    else:
        return {"result" : "error", "error" : form.errors.as_text()}
Example #11
0
def create(request):
    """
    Creates a :class:`.PLMObject` and returns it

    :implements: :func:`http_api.create`
    """
    try:
        type_name = request.POST["type"]
        cls = models.get_all_plmobjects()[type_name]
    except KeyError:
        return {"result": "error", 'error': 'bad type'}
    form = forms.get_creation_form(request.user, cls, request.POST)
    if form.is_valid():
        controller_cls = get_controller(type_name)
        controller = controller_cls.create_from_form(form, request.user)
        ret = {"object": object_to_dict(controller)}
        return ret
    else:
        return {"result": "error", "error": form.errors.as_text()}
Example #12
0
def update_child_files_BD(product, user, old_product):
    """
    :param product: :class:`.Product` that represents a sub-arborescense of the file **.stp** that was decomposed UPDATE whit the news doc_id and doc_path generating in the bomb-child
    :param old_product: :class:`.Product` that represents a sub-arborescense ORIGINAL of the file **.stp** that was decomposed



    Updates a :class:`.DocumentFile` STEP that WAS NOT root in a decomposition, to know which :class:`.DocumentFile` to update we use the attribute **product**.doc_id of the arborescense(**product**)

    This update consists in:

        Generate a new :class:`.ArbreFile` for each  :class:`.DocumentFile` STEP present in the arborescense(**product**)

        Generate news :class:`.GeometryFile` for the :class:`.DocumentFile` STEP (Copies of the GeometryFiles of the root :class:`.DocumentFile` (Identified for **old_product**.doc_id))

    """

    for link, old_link in zip(product.links, old_product.links):
        if not link.product.visited:
            link.product.visited = True
            product_copy = copy.copy(link.product)
            old_product_copy = copy.copy(old_link.product)
            product_copy.links = []  #when we decompose we delete the links
            old_product_copy.links = []
            doc_file = pmodels.DocumentFile.objects.get(id=product_copy.doc_id)
            doc_file.filename = product_copy.name + ".stp".encode("utf-8")
            doc_file.no_index = False
            doc_file.size = os.path.getsize(doc_file.file.path)
            doc_file.locked = False
            doc_file.locker = None
            doc_file.save()
            os.chmod(doc_file.file.path, 0400)

            copy_geometry(old_product_copy, doc_file)  #we utilise old_product
            ArbreFile.create_from_product(product_copy, doc_file)
            doc_file.document.no_index = False  # to reverse no_index=True make in document3D.views.generate_part_doc_links
            doc_file.document.save()
            ctrl = get_controller(doc_file.document.type)
            ctrl = ctrl(doc_file.document, user, True)
            ctrl._save_histo("File generated by decomposition",
                             "file : %s" % doc_file.filename)
            update_child_files_BD(link.product, user, old_link.product)
Example #13
0
def update_child_files_BD(product,user,old_product):
    """
    :param product: :class:`.Product` that represents a sub-arborescense of the file **.stp** that was decomposed UPDATE whit the news doc_id and doc_path generating in the bomb-child
    :param old_product: :class:`.Product` that represents a sub-arborescense ORIGINAL of the file **.stp** that was decomposed



    Updates a :class:`.DocumentFile` STEP that WAS NOT root in a decomposition, to know which :class:`.DocumentFile` to update we use the attribute **product**.doc_id of the arborescense(**product**)

    This update consists in:

        Generate a new :class:`.ArbreFile` for each  :class:`.DocumentFile` STEP present in the arborescense(**product**)

        Generate news :class:`.GeometryFile` for the :class:`.DocumentFile` STEP (Copies of the GeometryFiles of the root :class:`.DocumentFile` (Identified for **old_product**.doc_id))

    """

    for link, old_link in zip(product.links,old_product.links):
        if not link.product.visited:
            link.product.visited=True
            product_copy=copy.copy(link.product)
            old_product_copy=copy.copy(old_link.product)
            product_copy.links=[]       #when we decompose we delete the links
            old_product_copy.links=[]
            doc_file=pmodels.DocumentFile.objects.get(id=product_copy.doc_id)
            doc_file.filename=product_copy.name+".stp".encode("utf-8")
            doc_file.no_index=False
            doc_file.size=os.path.getsize(doc_file.file.path)
            doc_file.locked = False
            doc_file.locker = None
            doc_file.save()
            os.chmod(doc_file.file.path, 0400)

            copy_geometry(old_product_copy,doc_file) #we utilise old_product
            ArbreFile.create_from_product(product_copy,doc_file)
            doc_file.document.no_index=False # to reverse no_index=True make in document3D.views.generate_part_doc_links
            doc_file.document.save()
            ctrl=get_controller(doc_file.document.type)
            ctrl=ctrl(doc_file.document,user,True)
            ctrl._save_histo("File generated by decomposition", "file : %s" % doc_file.filename)
            update_child_files_BD(link.product,user,old_link.product)
Example #14
0
def select_pdf_part(request, ctx, obj):
    """
    View helper to select pdf files to download.

    :type obj: :class:`.PartController`
    """
    data = request.GET if request.GET.get("Download") else None
    # retrieve all pdf files (from documents attached to children parts)
    children = obj.get_children(-1)
    formsets = []
    self_link = FakeLink("self", child=obj.object)
    for level, link in [(0, self_link)] + list(children):
        link.formsets = []
        for l in link.child.documentpartlink_part.now():
            doc = l.document
            ctrl = get_controller(doc.type)(doc, request.user)
            if ctrl.check_readable(raise_=False):
                formset = get_pdf_formset(doc, data,
                        prefix="pdf_%s_%d" % (link.id, doc.id))
                link.formsets.append(formset)
        formsets.append((level, link))

    if data:
        # returns a pdf file if all formsets are valid
        valid = True
        files = []
        for level, link in formsets:
            for formset in link.formsets:
                if formset.is_valid():
                    for form in formset.forms:
                        selected = form.cleaned_data["selected"]
                        if selected:
                            df = form.cleaned_data["id"]
                            files.append(df)
                else:
                    valid = False
        if valid:
            return download_merged_pdf(obj, files)
    ctx["children"] = formsets
    return r2r("select_pdf_part.html", ctx, request)
Example #15
0
def create_object(request):
    """
    Manage html page for the creation of an instance of `models.PLMObject` subclass.
    It computes a context dictionnary based on
    
    :param request: :class:`django.http.QueryDict`
    :return: a :class:`django.http.HttpResponse`
    """

    obj, ctx = get_generic_data(request)

    if request.method == 'GET':
        type_form = TypeFormWithoutUser(request.GET)
        if type_form.is_valid():
            type_ = type_form.cleaned_data["type"]
            cls = models.get_all_plmobjects()[type_]
            if cls in _creation_views:
                return _creation_views[cls](request)
            creation_form = get_creation_form(request.user, cls)
    elif request.method == 'POST':
        type_form = TypeFormWithoutUser(request.POST)
        if type_form.is_valid():
            type_name = type_form.cleaned_data["type"]
            cls = models.get_all_plmobjects()[type_name]
            if cls in _creation_views:
                return _creation_views[cls](request)
            creation_form = get_creation_form(request.user, cls, request.POST)
            if creation_form.is_valid():
                user = request.user
                controller_cls = get_controller(type_name)
                controller = controller_cls.create_from_form(creation_form, user)
                return HttpResponseRedirect(controller.plmobject_url)
    ctx.update({
        'creation_form': creation_form,
        'object_type': type_form.cleaned_data["type"],
    })
    return r2r('DisplayObject4creation.htm', ctx, request)
Example #16
0
def create_object(request, from_registered_view=False, creation_form=None):
    """
    View to create a :class:`.PLMObject` or a :class:`.GroupInfo`.

    :url: ``/object/create/``

    Requests (POST and GET) must contain a ``type`` variable that validates a
    :class:`.TypeForm`.

    POST requests must validate the creation form, fields depend on the
    given type. If the creation form is valid, an object is created and
    in case of success, this view redirects to the created object.

    Requests may contain a ``__next__`` variable. A successful creation will
    redirect to this URL. Some special strings are replaced:

        * ``##type##`` with the created object's type
        * ``##ref##`` with the created object's reference
        * ``##rev##`` with the created object's reference

    Requests may also contain other special variables (at most one of
    them):

        ``related_doc``
            Id of a document. The created part will be attached to this
            document. Object's type is restricted to part types.
            Two context variables (``related_doc`` and ``related``)
            are set to the document controller.

        ``related_part``
            Id of a part. The created document will be attached to this
            part. Object's type is restricted to document types.
            Two context variables (``related_part`` and ``related``)
            are set to the part controller.

        ``related_parent``
            Id of a part. Object's type is restricted to part types.
            Two context variables (``related_parent`` and ``related``)
            are set to the part controller.

    .. note::
        If *from_registered_view* is False, this view delegates its
        treatment to a registered view that handles creation of
        objects of the given type.
        (see :func:`.get_creation_view` and :func:`.register_creation_view`)

    :param from_registered_view: True if this function is called by another
         creation view
    :param creation_form: a creation form that will be used instead of the
         default one

    **Template:**

    :file:`create.html`

    **Context:**

    ``RequestContext``

    ``creation_form``

    ``creation_type_form``
        :class:`.TypeForm` to select the type of the created object

    ``object_type``
        type of the created object

    ``next``
        value of the ``__next__`` request variable if given
    """

    obj, ctx = get_generic_data(request)
    Form = forms.TypeForm
    # it is possible that the created object must be attached to a part
    # or a document
    # related_doc and related_part should be a plmobject id
    # If the related_doc/part is not a doc/part, we let python raise
    # an AttributeError, since a user should not play with the URL
    # and openPLM must be smart enough to produce valid URLs
    attach = related = None
    if "related_doc" in request.REQUEST:
        Form = forms.PartTypeForm
        doc = get_obj_by_id(int(request.REQUEST["related_doc"]), request.user)
        attach = doc.attach_to_part
        ctx["related_doc"] = request.REQUEST["related_doc"]
        related = ctx["related"] = doc
    elif "related_part" in request.REQUEST:
        Form = forms.DocumentTypeForm
        part = get_obj_by_id(int(request.REQUEST["related_part"]),
                             request.user)
        attach = part.attach_to_document
        ctx["related_part"] = request.REQUEST["related_part"]
        related = ctx["related"] = part
    elif "related_parent" in request.REQUEST:
        Form = forms.PartTypeForm
        parent = get_obj_by_id(int(request.REQUEST["related_parent"]),
                               request.user)
        ctx["related_parent"] = request.REQUEST["related_parent"]
        related = ctx["related"] = parent
    if "pfiles" in request.REQUEST:
        Form = forms.Document2TypeForm

    if "__next__" in request.REQUEST:
        redirect_to = request.REQUEST["__next__"]
        ctx["next"] = redirect_to
    else:
        # will redirect to the created object
        redirect_to = None

    type_form = Form(request.REQUEST)
    if type_form.is_valid():
        type_ = type_form.cleaned_data["type"]
        cls = models.get_all_users_and_plmobjects()[type_]
        if not from_registered_view:
            view = get_creation_view(cls)
            if view is not None:
                # view has been registered to create an object of type 'cls'
                return view(request)
    else:
        ctx["creation_type_form"] = type_form
        return r2r('create.html', ctx, request)

    if request.method == 'GET' and creation_form is None:
        creation_form = forms.get_creation_form(request.user,
                                                cls,
                                                template="pfiles"
                                                not in request.GET)
        if related is not None:
            creation_form.fields["group"].initial = related.group
            creation_form.initial["lifecycle"] = related.lifecycle
        if "pfiles" in request.GET:
            pfiles = request.GET.getlist("pfiles")
            creation_form.initial["pfiles"] = pfiles
            try:
                name = filename_to_name(
                    obj.files.get(id=int(pfiles[0])).filename)
                creation_form.initial["name"] = name
            except Exception:
                pass
    elif request.method == 'POST':
        if creation_form is None:
            creation_form = forms.get_creation_form(request.user, cls,
                                                    request.POST)
        if creation_form.is_valid():
            ctrl_cls = get_controller(type_)
            ctrl = ctrl_cls.create_from_form(creation_form, request.user)
            message = _(u"The %(Object_type)s has been created") % dict(
                Object_type=type_)
            messages.info(request, message)
            if attach is not None:
                try:
                    attach(ctrl)
                    message = _(u"The %(Object_type)s has been attached"
                                ) % dict(Object_type=type_)
                    messages.info(request, message)
                except (ControllerError, ValueError) as e:
                    # crtl cannot be attached (maybe the state of the
                    # related object as changed)
                    # alerting the user using the messages framework since
                    # the response is redirected
                    message = _(u"Error: %(details)s") % dict(
                        details=unicode(e))
                    messages.error(request, message)
                    # redirecting to the ctrl page that lists its attached
                    # objects
                    if ctrl.is_document:
                        return HttpResponseRedirect(ctrl.plmobject_url +
                                                    "parts/")
                    else:
                        return HttpResponseRedirect(ctrl.plmobject_url +
                                                    "doc-cad/")
            if redirect_to:
                redirect_to = redirect_to.replace("##ref##", ctrl.reference)
                redirect_to = redirect_to.replace("##rev##", ctrl.revision)
                redirect_to = redirect_to.replace("##type##", ctrl.type)
            return HttpResponseRedirect(redirect_to or ctrl.plmobject_url)
    ctx.update({
        'creation_form': creation_form,
        'object_type': type_,
        'creation_type_form': type_form,
    })
    return r2r('create.html', ctx, request)
Example #17
0
def decomposer_all(stp_file_pk, arbre, part_pk, native_related_pk, user_pk,
                   old_arbre):
    """

    :param arbre: Information contained in file **.arb** that allows to generate a :class:`.Product` that represents the arborescense of the :class:`~django.core.files.File` .stp to decompose , his nodes contains doc_id and doc_path of new :class:`.DocumentFile` created in the arborescense
    :type plmobject: :class:`.Product`
    :param stp_file_pk: primery key of a :class:`.DocumentFile` that contains the :class:`~django.core.files.File` that will be decomposed
    :param part_pk: primery key of a :class:`.Part` attached to the :class:`.Document3D` that contains the :class:`.DocumentFile` that will be decomposed
    :param native_related_pk: If exists a native file related to the :class:`.DocumentFile` that will be decomposed ,  contains the primary key of the :class:`.DocumentFile` related to the native file


    This function departs from a :class:`.DocumentFile` (**stp_file_pk**) associated with a :class:`.Document3D` attached to a :class:`.Part` (``part_pk``) and from
    the :class:`.Product` related to the :class:`.DocumentFile` in order to decompose :class:`~django.core.files.File` .stp.With this purpose it realizes a call to the subprocess
    :meth:`.generateDecomposition.py`.



    -**Preconditions** ,before calling to this function, the following steps must have been realized:

        -The bom-child of Parts (in relation to the :class:`.Product` (generate across the **arbre**)) has been generated

        -For every :class:`.ParentChildLink` generated in the previous condition we attach all the :class:`.Location_link` relatives

        -To every generated :class:`.Part` a :class:`.Document3D` has been attached and the :class:`.Document3D` has been set like the attribute PartDecompose of the :class:`.Part`

        -The attribute doc_id of every node of the :class:`.Product` (generate across the **arbre**) is now the relative id of :class:`.Document3D` generated in the previous condition

        -To every generated :class:`.Document3D` has been added a new empty(locked) :class:`.DocumentFile` .stp

        -The attribute doc_path of every node of the :class:`.Product` is now the path of :class:`.DocumentFile` generated in the previous condition

        -The :class:`.DocumentFile` (**stp_file_pk**) is locked

        -If exists a native :class:`.DocumentFile` (**native_related_pk**) related to the :class:`.DocumentFile` (**stp_file_pk**), then this one was depreciated (afterwards will be promoted)




    -**Treatment**


        -The subprocess  :meth:`.generateDecomposition.py` is going to write in to doc_path of every node of the :class:`.Product` (generate across the **arbre**) the corresponding decomposed file


    -**Postconditions**

        -For every generated :class:`.Document3D` , the new :class:`.DocumentFile` added is unlocked

        -For every new :class:`.DocumentFile` , his :class:`.GeometryFile` and :class:`.ArbreFile` have been generated

        -The root :class:`.DocumentFile` (**stp_file_pk**) has been deprecated and unlocked

        -A new root :class:`.DocumentFile` has been generated according to the situation

        -If exists a native :class:`.DocumentFile` (**native_related_pk**) related to the :class:`.DocumentFile` (**stp_file_pk**), then this one was promoted

        -We set the :class:`.Part` (**part_pk**) like the attribute PartDecompose of the :class:`.Document3D` that contains the :class:`.DocumentFile` (**stp_file_pk**)
    """
    try:
        stp_file = pmodels.DocumentFile.objects.get(pk=stp_file_pk)
        ctrl = get_controller(stp_file.document.type)
        user = pmodels.User.objects.get(pk=user_pk)
        ctrl = ctrl(stp_file.document, user)
        part = pmodels.Part.objects.get(pk=part_pk)

        product = classes.Product.from_list(json.loads(
            arbre))  #whit doc_id and doc_path updated for every node
        old_product = classes.Product.from_list(
            json.loads(old_arbre))  # doc_id and doc_path original
        new_stp_file = pmodels.DocumentFile()
        name = new_stp_file.file.storage.get_available_name(
            (product.name + ".stp").encode("utf-8"))
        new_stp_path = os.path.join(new_stp_file.file.storage.location, name)
        f = File(open(new_stp_path, 'w'))
        f.close()

        product.doc_path = new_stp_path  # the old documentfile will be deprecated
        product.doc_id = new_stp_file.id  # the old documentfile will be deprecated

        temp_file = tempfile.NamedTemporaryFile(delete=True)
        temp_file.write(json.dumps(product.to_list()))
        temp_file.seek(0)
        dirname = os.path.dirname(__file__)
        if subprocess.call([
                "python",
                os.path.join(dirname, "generateDecomposition.py"),
                stp_file.file.path, temp_file.name
        ]) == 0:

            update_child_files_BD(product, user, old_product)
            update_root_BD(new_stp_file, stp_file, ctrl, product, f, name,
                           part)

        else:

            raise Document3D_decomposer_Error
    except:
        raise Document3D_decomposer_Error

    finally:
        if native_related_pk is not None:
            native_related = pmodels.DocumentFile.objects.get(
                pk=native_related_pk)
            native_related.deprecated = False
            native_related.save()
        stp_file.locked = False
        stp_file.locker = None
        stp_file.save()
Example #18
0
def create_object(request, from_registered_view=False, creation_form=None):
    """
    View to create a :class:`.PLMObject` or a :class:`.GroupInfo`.

    :url: ``/object/create/``

    Requests (POST and GET) must contain a ``type`` variable that validates a
    :class:`.TypeForm`.

    POST requests must validate the creation form, fields depend on the
    given type. If the creation form is valid, an object is created and
    in case of success, this view redirects to the created object.

    Requests may contain a ``__next__`` variable. A successful creation will
    redirect to this URL. Some special strings are replaced:

        * ``##type##`` with the created object's type
        * ``##ref##`` with the created object's reference
        * ``##rev##`` with the created object's reference

    Requests may also contain other special variables (at most one of
    them):

        ``related_doc``
            Id of a document. The created part will be attached to this
            document. Object's type is restricted to part types.
            Two context variables (``related_doc`` and ``related``)
            are set to the document controller.

        ``related_part``
            Id of a part. The created document will be attached to this
            part. Object's type is restricted to document types.
            Two context variables (``related_part`` and ``related``)
            are set to the part controller.

        ``related_parent``
            Id of a part. Object's type is restricted to part types.
            Two context variables (``related_parent`` and ``related``)
            are set to the part controller.

    .. note::
        If *from_registered_view* is False, this view delegates its
        treatment to a registered view that handles creation of
        objects of the given type.
        (see :func:`.get_creation_view` and :func:`.register_creation_view`)

    :param from_registered_view: True if this function is called by another
         creation view
    :param creation_form: a creation form that will be used instead of the
         default one

    **Template:**

    :file:`create.html`

    **Context:**

    ``RequestContext``

    ``creation_form``

    ``creation_type_form``
        :class:`.TypeForm` to select the type of the created object

    ``object_type``
        type of the created object

    ``next``
        value of the ``__next__`` request variable if given
    """

    obj, ctx = get_generic_data(request)
    Form = forms.TypeForm
    # it is possible that the created object must be attached to a part
    # or a document
    # related_doc and related_part should be a plmobject id
    # If the related_doc/part is not a doc/part, we let python raise
    # an AttributeError, since a user should not play with the URL
    # and openPLM must be smart enough to produce valid URLs
    attach = related = None
    if "related_doc" in request.REQUEST:
        Form = forms.PartTypeForm
        doc = get_obj_by_id(int(request.REQUEST["related_doc"]), request.user)
        attach = doc.attach_to_part
        ctx["related_doc"] = request.REQUEST["related_doc"]
        related = ctx["related"] = doc
    elif "related_part" in request.REQUEST:
        Form = forms.DocumentTypeForm
        part = get_obj_by_id(int(request.REQUEST["related_part"]), request.user)
        attach = part.attach_to_document
        ctx["related_part"] = request.REQUEST["related_part"]
        related = ctx["related"] = part
    elif "related_parent" in request.REQUEST:
        Form = forms.PartTypeForm
        parent = get_obj_by_id(int(request.REQUEST["related_parent"]), request.user)
        ctx["related_parent"] = request.REQUEST["related_parent"]
        related = ctx["related"] = parent
    if "pfiles" in request.REQUEST:
        Form = forms.Document2TypeForm

    if "__next__" in request.REQUEST:
        redirect_to = request.REQUEST["__next__"]
        ctx["next"] = redirect_to
    else:
        # will redirect to the created object
        redirect_to = None

    type_form = Form(request.REQUEST)
    if type_form.is_valid():
        type_ = type_form.cleaned_data["type"]
        cls = models.get_all_users_and_plmobjects()[type_]
        if not from_registered_view:
            view = get_creation_view(cls)
            if view is not None:
                # view has been registered to create an object of type 'cls'
                return view(request)
    else:
        ctx["creation_type_form"] = type_form
        return r2r('create.html', ctx, request)

    if request.method == 'GET' and creation_form is None:
        creation_form = forms.get_creation_form(request.user, cls,
             template="pfiles" not in request.GET)
        if related is not None:
            creation_form.fields["group"].initial = related.group
            creation_form.initial["lifecycle"] = related.lifecycle
        if "pfiles" in request.GET:
            pfiles = request.GET.getlist("pfiles")
            creation_form.initial["pfiles"] = pfiles
            try:
                name = filename_to_name(obj.files.get(id=int(pfiles[0])).filename)
                creation_form.initial["name"] = name
            except Exception:
                pass
    elif request.method == 'POST':
        if creation_form is None:
            creation_form = forms.get_creation_form(request.user, cls, request.POST)
        if creation_form.is_valid():
            ctrl_cls = get_controller(type_)
            ctrl = ctrl_cls.create_from_form(creation_form, request.user)
            message = _(u"The %(Object_type)s has been created") % dict(Object_type = type_)
            messages.info(request, message)
            if attach is not None:
                try:
                    attach(ctrl)
                    message = _(u"The %(Object_type)s has been attached") % dict(Object_type = type_)
                    messages.info(request, message)
                except (ControllerError, ValueError) as e:
                    # crtl cannot be attached (maybe the state of the
                    # related object as changed)
                    # alerting the user using the messages framework since
                    # the response is redirected
                    message = _(u"Error: %(details)s") % dict(details=unicode(e))
                    messages.error(request, message)
                    # redirecting to the ctrl page that lists its attached
                    # objects
                    if ctrl.is_document:
                        return HttpResponseRedirect(ctrl.plmobject_url + "parts/")
                    else:
                        return HttpResponseRedirect(ctrl.plmobject_url + "doc-cad/")
            if redirect_to:
                redirect_to = redirect_to.replace("##ref##", ctrl.reference)
                redirect_to = redirect_to.replace("##rev##", ctrl.revision)
                redirect_to = redirect_to.replace("##type##", ctrl.type)
            return HttpResponseRedirect(redirect_to or ctrl.plmobject_url)
    ctx.update({
        'creation_form' : creation_form,
        'object_type' : type_,
        'creation_type_form' : type_form,
    })
    return r2r('create.html', ctx, request)
Example #19
0
def decomposer_all(stp_file_pk,arbre,part_pk,native_related_pk,user_pk,old_arbre):
    """

    :param arbre: Information contained in file **.arb** that allows to generate a :class:`.Product` that represents the arborescense of the :class:`~django.core.files.File` .stp to decompose , his nodes contains doc_id and doc_path of new :class:`.DocumentFile` created in the arborescense
    :type plmobject: :class:`.Product`
    :param stp_file_pk: primery key of a :class:`.DocumentFile` that contains the :class:`~django.core.files.File` that will be decomposed
    :param part_pk: primery key of a :class:`.Part` attached to the :class:`.Document3D` that contains the :class:`.DocumentFile` that will be decomposed
    :param native_related_pk: If exists a native file related to the :class:`.DocumentFile` that will be decomposed ,  contains the primary key of the :class:`.DocumentFile` related to the native file


    This function departs from a :class:`.DocumentFile` (**stp_file_pk**) associated with a :class:`.Document3D` attached to a :class:`.Part` (``part_pk``) and from
    the :class:`.Product` related to the :class:`.DocumentFile` in order to decompose :class:`~django.core.files.File` .stp.With this purpose it realizes a call to the subprocess
    :meth:`.generateDecomposition.py`.



    -**Preconditions** ,before calling to this function, the following steps must have been realized:

        -The bom-child of Parts (in relation to the :class:`.Product` (generate across the **arbre**)) has been generated

        -For every :class:`.ParentChildLink` generated in the previous condition we attach all the :class:`.Location_link` relatives

        -To every generated :class:`.Part` a :class:`.Document3D` has been attached and the :class:`.Document3D` has been set like the attribute PartDecompose of the :class:`.Part`

        -The attribute doc_id of every node of the :class:`.Product` (generate across the **arbre**) is now the relative id of :class:`.Document3D` generated in the previous condition

        -To every generated :class:`.Document3D` has been added a new empty(locked) :class:`.DocumentFile` .stp

        -The attribute doc_path of every node of the :class:`.Product` is now the path of :class:`.DocumentFile` generated in the previous condition

        -The :class:`.DocumentFile` (**stp_file_pk**) is locked

        -If exists a native :class:`.DocumentFile` (**native_related_pk**) related to the :class:`.DocumentFile` (**stp_file_pk**), then this one was depreciated (afterwards will be promoted)




    -**Treatment**


        -The subprocess  :meth:`.generateDecomposition.py` is going to write in to doc_path of every node of the :class:`.Product` (generate across the **arbre**) the corresponding decomposed file


    -**Postconditions**

        -For every generated :class:`.Document3D` , the new :class:`.DocumentFile` added is unlocked

        -For every new :class:`.DocumentFile` , his :class:`.GeometryFile` and :class:`.ArbreFile` have been generated

        -The root :class:`.DocumentFile` (**stp_file_pk**) has been deprecated and unlocked

        -A new root :class:`.DocumentFile` has been generated according to the situation

        -If exists a native :class:`.DocumentFile` (**native_related_pk**) related to the :class:`.DocumentFile` (**stp_file_pk**), then this one was promoted

        -We set the :class:`.Part` (**part_pk**) like the attribute PartDecompose of the :class:`.Document3D` that contains the :class:`.DocumentFile` (**stp_file_pk**)
    """
    try:
        stp_file = pmodels.DocumentFile.objects.get(pk=stp_file_pk)
        ctrl=get_controller(stp_file.document.type)
        user=pmodels.User.objects.get(pk=user_pk)
        ctrl=ctrl(stp_file.document,user)
        part=pmodels.Part.objects.get(pk=part_pk)

        product=classes.Product.from_list(json.loads(arbre))   #whit doc_id and doc_path updated for every node
        old_product=classes.Product.from_list(json.loads(old_arbre)) # doc_id and doc_path original
        new_stp_file=pmodels.DocumentFile()
        name = new_stp_file.file.storage.get_available_name((product.name+".stp").encode("utf-8"))
        new_stp_path = os.path.join(new_stp_file.file.storage.location, name)
        f = File(open(new_stp_path, 'w'))
        f.close()

        product.doc_path=new_stp_path # the old documentfile will be deprecated
        product.doc_id=new_stp_file.id # the old documentfile will be deprecated

        temp_file = tempfile.NamedTemporaryFile(delete=True)
        temp_file.write(json.dumps(product.to_list()))
        temp_file.seek(0)
        dirname = os.path.dirname(__file__)
        if subprocess.call(["python", os.path.join(dirname, "generateDecomposition.py"),
            stp_file.file.path,temp_file.name]) == 0:

            update_child_files_BD(product,user,old_product)
            update_root_BD(new_stp_file,stp_file,ctrl,product,f,name,part)

        else:

            raise Document3D_decomposer_Error
    except:
        raise Document3D_decomposer_Error

    finally:
        if native_related_pk is not None:
            native_related = pmodels.DocumentFile.objects.get(pk=native_related_pk)
            native_related.deprecated=False
            native_related.save()
        stp_file.locked = False
        stp_file.locker = None
        stp_file.save()