def test_create(self): controller = self.CONTROLLER.create("Grp", "description", self.user, self.DATA) self.assertEqual(controller.name, "Grp") self.assertEqual(type(controller.object), get_all_plmobjects()[self.TYPE]) obj = get_all_plmobjects()[self.TYPE].objects.get(name=controller.name) self.assertEqual(obj.owner, self.user) self.assertEqual(obj.creator, self.user) self.assertTrue(self.user.groups.filter(id=obj.id))
def test_revisions(self): response = self.get(self.base_url + "revisions/") revisions = response.context["revisions"] self.assertEqual(revisions, [self.controller.object]) # check add_revision_form add_revision_form = response.context["add_revision_form"] self.assertEqual(add_revision_form.data, {"revision": "b"}) response = self.post(self.base_url + "revisions/", {"revision": "b"}) m.get_all_plmobjects()[self.TYPE].objects.get(reference=self.controller.reference, revision="b")
def test_create_post_same_reference_and_revision(self): """ Tests that when auto is True and we intent to create an object with the same type, reference and revision: * a new and available reference is given to the new object * the object is created. """ data = self.DATA.copy() ref = self.controller.reference rev = self.controller.revision data.update({ "type" : self.TYPE, "reference" : ref, "auto" : True, "revision" : rev, "name" : "A valid object", "group" : str(self.group.id), "lifecycle" : m.get_default_lifecycle().pk, "state" : m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] response = self.post("/object/create/", data) obj = m.PLMObject.objects.get(type=self.TYPE, revision=rev, name="A valid object") self.assertNotEqual(ref, obj.reference) self.assertEqual(self.group.id, obj.group_id) self.assertEqual(self.user, obj.owner) self.assertEqual(self.user, obj.creator)
def parse_row(self, line, row): """ Method called by :meth:`import_csv` for each row. """ from openPLM.plmapp.forms import get_creation_form type_, reference, revision = self.get_values(row, "type", "reference", "revision") cls = models.get_all_plmobjects()[type_] group = models.GroupInfo.objects.get(name=self.get_value(row, "group")) lifecycle = models.Lifecycle.objects.get(name=self.get_value(row, "lifecycle")) form = get_creation_form(self.user, cls) data = { "type" : type_, "group" : str(group.id), "reference" : reference, "revision" : revision, } for field in form.fields: if field not in data and field in self.headers_dict: data[field] = self.get_value(row, field) form = get_creation_form(self.user, cls, data) if not form.is_valid(): items = (mark_safe(u"%s: %s" % item) for item in form.errors.iteritems()) self.store_errors(line, *items) else: obj = PLMObjectController.create_from_form(form, self.user, True, True) self.objects.append(obj)
def search(request, editable_only="true", with_file_only="true"): """ Returns all objects matching a query. :param editable_only: if ``"true"`` (the default), returns only editable objects :param with_file_only: if ``"true"`` (the default), returns only documents with at least one file :implements: :func:`http_api.search` """ if request.GET and "type" in request.GET: attributes_form = forms.TypeForm(request.GET) if attributes_form.is_valid(): query_dict = {} cls = models.get_all_plmobjects()[attributes_form.cleaned_data["type"]] extra_attributes_form = forms.get_search_form(cls, request.GET) results = cls.objects.all() if extra_attributes_form.is_valid(): results = extra_attributes_form.search(results) objects = [] for res in results: if editable_only == "false" or res.is_editable: if with_file_only == "true" and hasattr(res, "files") \ and not bool(res.files): continue if editable_only == "true": obj = DocumentController(res, request.user) if not obj.check_permission("owner", False): continue objects.append(object_to_dict(res)) return {"objects" : objects} return {"result": "error"}
def load(cls, type, reference, revision, user): model = models.get_all_plmobjects()[type] obj = get_object_or_404(model, type=type, reference=reference, revision=revision) return cls(obj, user)
def parse_row(self, line, row): """ Method called by :meth:`import_csv` for each row. """ from openPLM.plmapp.forms import get_creation_form type_, reference, revision = self.get_values(row, "type", "reference", "revision") cls = models.get_all_plmobjects()[type_] group = models.GroupInfo.objects.get(name=self.get_value(row, "group")) lifecycle = models.Lifecycle.objects.get(name=self.get_value(row, "lifecycle")) form = get_creation_form(self.user, cls, inbulk_cache=self.inbulk_cache) data = { "type" : type_, "group" : str(group.id), "reference" : reference, "revision" : revision, "auto" : False, } for field in form.fields: if field not in data and field in self.headers_dict: data[field] = self.get_value(row, field) form = get_creation_form(self.user, cls, data, inbulk_cache=self.inbulk_cache) if not form.is_valid(): items = (mark_safe(u"%s: %s" % item) for item in form.errors.iteritems()) self.store_errors(line, *items) else: obj = PLMObjectController.create_from_form(form, self.user, True, True) self.objects.append(obj)
def get_all_types(request): """ Returns all the subtypes of :class:`.PLMObject` managed by the server. :implements: :func:`http_api.types` """ return {"types": sorted(models.get_all_plmobjects().keys())}
def get_all_types(request): """ Returns all the subtypes of :class:`.PLMObject` managed by the server. :implements: :func:`http_api.types` """ return {"types" : sorted(models.get_all_plmobjects().keys())}
def test_create_post_same_reference_and_revision(self): """ Tests that when auto is True and we intent to create an object with the same type, reference and revision: * a new and available reference is given to the new object * the object is created. """ data = self.DATA.copy() ref = self.controller.reference rev = self.controller.revision data.update({ "type": self.TYPE, "reference": ref, "auto": True, "revision": rev, "name": "A valid object", "group": str(self.group.id), "lifecycle": m.get_default_lifecycle().pk, "state": m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] response = self.post("/object/create/", data) obj = m.PLMObject.objects.get(type=self.TYPE, revision=rev, name="A valid object") self.assertNotEqual(ref, obj.reference) self.assertEqual(self.group.id, obj.group_id) self.assertEqual(self.user, obj.owner) self.assertEqual(self.user, obj.creator)
def test_create_post_error_same_reference(self): """ Tests that the creation of an object with the same type and reference but a different revision is forbidden. """ data = self.DATA.copy() ref = self.controller.reference rev = "a new revision" data.update({ "type": self.TYPE, "reference": ref, "auto": False, "revision": rev, "name": "An invalid object", "group": str(self.group.id), "lifecycle": m.get_default_lifecycle().pk, "state": m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] response = self.post("/object/create/", data) qset = m.PLMObject.objects.filter(type=self.TYPE, reference=ref, revision=rev) self.assertFalse(response.context["creation_form"].is_valid()) self.assertFalse(qset.exists())
def test_create_redirect_post(self): data = self.DATA.copy() data.update({ "__next__": "/home/", "type": self.TYPE, "reference": "mapart", "auto": False, "revision": "a", "name": "MaPart", "group": str(self.group.id), "lifecycle": m.get_default_lifecycle().pk, "state": m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] page = "files" if issubclass(model_cls, m.Document) else "attributes" response = self.post("/object/create/", data, follow=False, status_code=302) self.assertRedirects(response, "/home/") obj = m.PLMObject.objects.get(type=self.TYPE, reference="mapart", revision="a") self.assertEqual("MaPart", obj.name) self.assertEqual(self.user, obj.owner) self.assertEqual(self.user, obj.creator)
def test_create_and_attach_post(self): doc = self.attach_to_official_document() data = self.DATA.copy() data.update({ "__next__": "/home/", "related_doc": doc.id, "type": self.TYPE, "reference": "mapart", "auto": False, "revision": "a", "name": "MaPart", "group": str(self.group.id), "lifecycle": m.get_default_lifecycle().pk, "state": m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] response = self.post("/object/create/", data, follow=False, status_code=302) self.assertRedirects(response, "/home/") obj = m.PLMObject.objects.get(type=self.TYPE, reference="mapart", revision="a") self.assertEqual("MaPart", obj.name) self.assertEqual(self.user, obj.owner) self.assertEqual(self.user, obj.creator) link = m.DocumentPartLink.current_objects.get(document=doc.object, part=obj)
def test_edit_attributes(self): data = self.DATA.copy() data.update(type=self.TYPE, name="new_name") response = self.client.post(self.base_url + "modify/", data, follow=True) obj = m.get_all_plmobjects()[self.TYPE].objects.all()[0] self.assertEqual(obj.name, "") self.assertEqual(response.template.name, "error.html")
def test_edit_attributes(self): data = self.DATA.copy() data.update(type=self.TYPE, name="new_name") response = self.client.post(self.base_url + "modify/", data, follow=True) obj = m.get_all_plmobjects()[self.TYPE].objects.all()[0] self.assertEqual(obj.name, '') self.assertTemplateUsed(response, "error.html")
def test_edit_attributes_post_error(self): # the name is too looonnnnnnngggggg name = self.controller.name data = self.DATA.copy() data.update(type=self.TYPE, name="new_name" * 300) response = self.post(self.base_url + "modify/", data) obj = m.get_all_plmobjects()[self.TYPE].objects.all()[0] self.assertEqual(obj.name, name) form = response.context["modification_form"] self.assertFalse(form.is_valid())
def get_search_fields(request, typename): """ Returns search fields associated to *typename*. :implements: :func:`http_api.search_fields` """ try: form = forms.get_search_form(models.get_all_plmobjects()[typename]) except KeyError: return {"result" : "error", "fields" : []} return {"fields" : get_fields_from_form(form)}
def get_creation_fields(request, typename): """ Returns creation fields associated to *typename* :implements: :func:`http_api.creation_fields` """ try: form = forms.get_creation_form(request.user, models.get_all_plmobjects()[typename]) except KeyError: return {"result": "error", "fields": []} return {"fields": get_fields_from_form(form)}
def display_object(request, obj_type, obj_ref, obj_revi): """ Manage html page which displays attributes of the selected object. Redirection to :func:display_object_attributes """ if obj_type in ('User', 'Group'): url = u"/%s/%s/attributes/" % (obj_type.lower(), obj_ref) else: model_cls = models.get_all_plmobjects()[obj_type] page = "files" if issubclass(model_cls, models.Document) else "attributes" url = u"/object/%s/%s/%s/%s/" % (obj_type, obj_ref, obj_revi, page) return HttpResponsePermanentRedirect(iri_to_uri(url))
def test_create(self): controller = self.create() self.assertEqual(controller.name, "") self.assertEqual(controller.type, self.TYPE) type_ = models.get_all_plmobjects()[self.TYPE] self.assertEqual(type(controller.object), type_) obj = type_.objects.get(reference=controller.reference, revision=controller.revision, type=controller.type) self.assertEqual(obj.owner, self.user) self.assertEqual(obj.creator, self.user) models.PLMObjectUserLink.current_objects.get(plmobject=obj, user=self.user, role=models.ROLE_OWNER) self.assertTrue(obj.is_editable)
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)
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)
def extra_context(self): extra = super(OpenPLMSearchView, self).extra_context() obj, ctx = get_generic_data(self.request, search=False) ctx["type"] = type = self.request.session["type"] ctx["object_type"] = _("Search") ctx["suggestion"] = self.suggestion ctx["extra_types"] = [c.__name__ for c in models.IObject.__subclasses__()] try: cls = models.get_all_plmobjects()[type] if issubclass(cls, models.PLMObject): main_cls = models.Part if issubclass(cls, models.Part) else models.Document ctx["subtypes"] = models.get_subclasses(main_cls) except KeyError: pass extra.update(ctx) return extra
def display_object(request, obj_type, obj_ref, obj_revi): """ Generic object view. Permanently redirects to the attribute page of the given object if it is a part, a user or a group and to the files page if it is a document. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/` """ if obj_type in ('User', 'Group'): url = u"/%s/%s/attributes/" % (obj_type.lower(), obj_ref) else: model_cls = models.get_all_plmobjects()[obj_type] page = "files" if issubclass(model_cls, models.Document) else "attributes" url = u"/object/%s/%s/%s/%s/" % (obj_type, obj_ref, obj_revi, page) return HttpResponsePermanentRedirect(iri_to_uri(url))
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()}
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()}
def extra_context(self): extra = super(OpenPLMSearchView, self).extra_context() obj, ctx = get_generic_data(self.request, search=False) ctx["type"] = type = self.request.session["type"] ctx["object_type"] = _("Search") ctx["suggestion"] = self.suggestion ctx["extra_types"] = [ c.__name__ for c in models.IObject.__subclasses__() ] try: cls = models.get_all_plmobjects()[type] if issubclass(cls, models.PLMObject): main_cls = models.Part if issubclass( cls, models.Part) else models.Document ctx["subtypes"] = models.get_subclasses(main_cls) except KeyError: pass extra.update(ctx) return extra
def modify_object(request, obj_type, obj_ref, obj_revi): """ Manage html page for the modification of the selected object. It computes a context dictionary based on .. include:: views_params.txt """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) cls = models.get_all_plmobjects()[obj_type] if request.method == 'POST' and request.POST: modification_form = forms.get_modification_form(cls, request.POST) if modification_form.is_valid(): obj.update_from_form(modification_form) return HttpResponseRedirect(obj.plmobject_url + "attributes/") else: modification_form = forms.get_modification_form(cls, instance=obj.object) ctx['modification_form'] = modification_form return r2r('edit.html', ctx, request)
def get_files(request, doc_id, all_files=False): """ Returns the list of files of the :class:`.Document` identified by *doc_id*. If *all_files* is False (the default), only unlocked files are returned. :implements: :func:`http_api.files` :param request: the request :param doc_id: id of a :class:`.Document` :param all_files: boolean, False if only unlocked files should be returned :returned fields: files, a list of files (see :ref:`http-api-file`) """ document = models.Document.objects.get(id=doc_id) document = models.get_all_plmobjects()[document.type].objects.get(id=doc_id) files = [] for df in document.files: if all_files or not df.locked: files.append(dict(id=df.id, filename=df.filename, size=df.size)) return {"files" : files}
def test_create_post(self): data = self.DATA.copy() data.update({ "type" : self.TYPE, "reference" : "mapart", "auto" : False, "revision" : "a", "name" : "MaPart", "group" : str(self.group.id), "lifecycle" : m.get_default_lifecycle().pk, "state" : m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] page = "files" if issubclass(model_cls, m.Document) else "attributes" response = self.post("/object/create/", data, page=page) obj = m.PLMObject.objects.get(type=self.TYPE, reference="mapart", revision="a") self.assertEqual(obj.id, response.context["obj"].id) self.assertEqual("MaPart", obj.name) self.assertEqual(self.user, obj.owner) self.assertEqual(self.user, obj.creator)
def get_files(request, doc_id, all_files=False): """ Returns the list of files of the :class:`.Document` identified by *doc_id*. If *all_files* is False (the default), only unlocked files are returned. :implements: :func:`http_api.files` :param request: the request :param doc_id: id of a :class:`.Document` :param all_files: boolean, False if only unlocked files should be returned :returned fields: files, a list of files (see :ref:`http-api-file`) """ document = models.Document.objects.get(id=doc_id) document = models.get_all_plmobjects()[document.type].objects.get( id=doc_id) files = [] for df in document.files: if all_files or not df.locked: files.append(dict(id=df.id, filename=df.filename, size=df.size)) return {"files": files}
def get_controller(cls, type_name): """ Returns the controller (subclass of :class:`.PLMObjectController`) associated to *type_name* (a string). For example, ``get_controller("Part")`` will return the class :class:`.PartController`. """ if type_name in cls.controllers_dict: return cls.controllers_dict[type_name] else: # get his model and return his parent controller if type_name == "PLMObject": # just a security to prevent an infinite recursion from openPLM.plmapp.controllers.plmobject import PLMObjectController return PLMObjectController else: model = models.get_all_plmobjects()[type_name] parents = [p for p in model.__bases__ if issubclass(p, models.PLMObject)] return cls.get_controller(parents[0].__name__)
def get_controller(cls, type_name): """ Returns the controller (subclass of :class:`.PLMObjectController`) associated to *type_name* (a string). For example, ``get_controller("Part")`` will return the class :class:`.PartController`. """ if type_name in cls.controllers_dict: return cls.controllers_dict[type_name] else: # get his model and return his parent controller if type_name == "PLMObject": # just a security to prevent an infinite recursion from openPLM.plmapp.controllers.plmobject import PLMObjectController return PLMObjectController else: model = models.get_all_plmobjects()[type_name] parents = [ p for p in model.__bases__ if issubclass(p, models.PLMObject) ] return cls.get_controller(parents[0].__name__)
def test_create_post_error_same_reference_and_revision(self): """ Tests that the creation of an object with the same type , reference and revision is forbidden when auto is not True. """ data = self.DATA.copy() ref = self.controller.reference rev = self.controller.revision data.update({ "type" : self.TYPE, "reference" : ref, "auto" : False, "revision" : rev, "name" : "An invalid object", "group" : str(self.group.id), "lifecycle" : m.get_default_lifecycle().pk, "state" : m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] response = self.post("/object/create/", data) qset = m.PLMObject.objects.filter(type=self.TYPE, reference=ref, revision=rev) self.assertFalse(response.context["creation_form"].is_valid())
def test_create_and_attach_post(self): doc = self.attach_to_official_document() data = self.DATA.copy() data.update({ "__next__" : "/home/", "related_doc" : doc.id, "type" : self.TYPE, "reference" : "mapart", "auto" : False, "revision" : "a", "name" : "MaPart", "group" : str(self.group.id), "lifecycle" : m.get_default_lifecycle().pk, "state" : m.get_default_state().pk, }) model_cls = m.get_all_plmobjects()[self.TYPE] response = self.post("/object/create/", data, follow=False, status_code=302) self.assertRedirects(response, "/home/") obj = m.PLMObject.objects.get(type=self.TYPE, reference="mapart", revision="a") self.assertEqual("MaPart", obj.name) self.assertEqual(self.user, obj.owner) self.assertEqual(self.user, obj.creator) link = m.DocumentPartLink.current_objects.get(document=doc.object, part=obj)
set_template_name(UserIndex) site.register(models.User, UserIndex) class GroupIndex(ModelSearchIndex): class Meta: pass rendered = CharField(use_template=True, indexed=False) rendered_add = CharField(use_template=True, indexed=False) set_template_name(GroupIndex) site.register(models.GroupInfo, GroupIndex) for key, model in models.get_all_plmobjects().iteritems(): if model == models.GroupInfo: continue class ModelIndex(QueuedModelSearchIndex): model = model key = key class Meta: fields = set(model.get_creation_fields()) fields.update(model.get_modification_fields()) owner = CharField(model_attr="owner") creator = CharField(model_attr="creator") state = CharField(model_attr="state__name") lifecycle = CharField(model_attr="lifecycle__name") rendered = CharField(use_template=True, indexed=False)
def get_state_class(obj): if obj.is_cancelled: cls = "cancelled" elif obj.is_official: cls = "official" elif obj.is_draft: cls = "draft" elif obj.is_deprecated: cls = "deprecated" else: cls = "proposed" return "state-" + cls for key, model in models.get_all_plmobjects().iteritems(): if model in indexed: continue class ModelIndex(QueuedModelSearchIndex): model = model key = key class Meta: fields = set(model.get_creation_fields()) fields.update(model.get_modification_fields()) owner = CharField(model_attr="owner__username") creator = CharField(model_attr="creator__username") state = CharField(model_attr="state__name") lifecycle = CharField(model_attr="lifecycle__name")
def test_edit_attributes_post(self): data = self.DATA.copy() data.update(type=self.TYPE, name="new_name") response = self.post(self.base_url + "modify/", data) obj = m.get_all_plmobjects()[self.TYPE].objects.all()[0] self.assertEqual(obj.name, data["name"])
def browse(request, type="object"): user = request.user if user.is_authenticated() and not user.profile.restricted: # only authenticated users can see all groups and users obj, ctx = get_generic_data(request, search=False) plmtypes = ("object", "part", "topassembly", "document") try: type2manager = { "object" : models.PLMObject.objects, "part" : models.Part.objects, "topassembly" : models.Part.top_assemblies, "document" : models.Document.objects, "group" : models.GroupInfo.objects, "user" : User.objects.select_related("profile"), } manager = type2manager[type] main_cls = manager.model stype = request.GET.get("stype") plmobjects = ctx["plmobjects"] = type in plmtypes if plmobjects and stype and stype != "Object": cls = models.get_all_plmobjects()[stype] if not issubclass(cls, main_cls): raise Http404 if type == "topassembly": manager = cls.top_assemblies else: manager = cls.objects else: stype = None ctx["stype"] = stype except KeyError: raise Http404 object_list = manager.all() # this is only relevant for authenticated users ctx["state"] = state = request.GET.get("state", "all") if plmobjects: ctx["subtypes"] = models.get_subclasses(main_cls) if type == "object": ctx["subtypes"][0] = (0, models.PLMObject, "Object") if state != models.get_cancelled_state().name: object_list = object_list.exclude_cancelled() if state == "official": object_list = object_list.officials() elif state == "published": object_list = object_list.filter(published=True) elif state != "all": object_list = object_list.filter(state=state) ctx["states"] = models.State.objects.order_by("name").values_list("name", flat=True) ctx["template"] = request.GET.get("template", "0") if ctx["template"] == "1": object_list = object_list.filter(lifecycle__type=models.Lifecycle.TEMPLATE) # date filters model = object_list.model ctime = "date_joined" if type == "user" else "ctime" ctime_filter = SimpleDateFilter(ctime, request, model, "ctime") object_list = ctime_filter.queryset(request, object_list) ctx["time_filters"] = [ctime_filter] if plmobjects: mtime_filter = SimpleDateFilter("mtime", request, model, "mtime") object_list = mtime_filter.queryset(request, object_list) ctx["time_filters"].append(mtime_filter) else: try: manager = { "object" : models.PLMObject.objects, "part" : models.Part.objects, "topassembly" : models.Part.top_assemblies, "document" : models.Document.objects, }[type] except KeyError: raise Http404 ctx = init_ctx("-", "-", "-") ctx.update({ 'is_readable' : True, 'is_contributor': False, 'plmobjects' : True, 'restricted' : True, 'object_menu' : [], 'navigation_history' : [], }) query = Q(published=True) if user.is_authenticated(): readable = user.plmobjectuserlink_user.now().filter(role=models.ROLE_READER) query |= Q(id__in=readable.values_list("plmobject_id", flat=True)) object_list = manager.filter(query).exclude_cancelled() ctx.update(get_pagination(request, object_list, type)) extra_types = [c.__name__ for c in models.IObject.__subclasses__()] ctx.update({ "object_type" : _("Browse"), "type" : type, "extra_types" : extra_types, }) return r2r("browse.html", ctx, request)
def get_headers_set(cls): """ Returns a set of all possible headers. """ return set().union(*(cls.get_creation_fields() for cls in models.get_all_plmobjects().itervalues()))
def browse(request, type="object"): user = request.user if user.is_authenticated() and not user.profile.restricted: # only authenticated users can see all groups and users obj, ctx = get_generic_data(request, search=False) plmtypes = ("object", "part", "topassembly", "document") try: type2manager = { "object": models.PLMObject.objects, "part": models.Part.objects, "topassembly": models.Part.top_assemblies, "document": models.Document.objects, "group": models.GroupInfo.objects, "user": User.objects.select_related("profile"), } manager = type2manager[type] main_cls = manager.model stype = request.GET.get("stype") plmobjects = ctx["plmobjects"] = type in plmtypes if plmobjects and stype and stype != "Object": cls = models.get_all_plmobjects()[stype] if not issubclass(cls, main_cls): raise Http404 if type == "topassembly": manager = cls.top_assemblies else: manager = cls.objects else: stype = None ctx["stype"] = stype except KeyError: raise Http404 object_list = manager.all() # this is only relevant for authenticated users ctx["state"] = state = request.GET.get("state", "all") if plmobjects: ctx["subtypes"] = models.get_subclasses(main_cls) if type == "object": ctx["subtypes"][0] = (0, models.PLMObject, "Object") if state != models.get_cancelled_state().name: object_list = object_list.exclude_cancelled() if state == "official": object_list = object_list.officials() elif state == "published": object_list = object_list.filter(published=True) elif state != "all": object_list = object_list.filter(state=state) ctx["states"] = models.State.objects.order_by("name").values_list( "name", flat=True) ctx["template"] = request.GET.get("template", "0") if ctx["template"] == "1": object_list = object_list.filter( lifecycle__type=models.Lifecycle.TEMPLATE) # date filters model = object_list.model ctime = "date_joined" if type == "user" else "ctime" ctime_filter = SimpleDateFilter(ctime, request, model, "ctime") object_list = ctime_filter.queryset(request, object_list) ctx["time_filters"] = [ctime_filter] if plmobjects: mtime_filter = SimpleDateFilter("mtime", request, model, "mtime") object_list = mtime_filter.queryset(request, object_list) ctx["time_filters"].append(mtime_filter) else: try: manager = { "object": models.PLMObject.objects, "part": models.Part.objects, "topassembly": models.Part.top_assemblies, "document": models.Document.objects, }[type] except KeyError: raise Http404 ctx = init_ctx("-", "-", "-") ctx.update({ 'is_readable': True, 'is_contributor': False, 'plmobjects': True, 'restricted': True, 'object_menu': [], 'navigation_history': [], }) query = Q(published=True) if user.is_authenticated(): readable = user.plmobjectuserlink_user.now().filter( role=models.ROLE_READER) query |= Q(id__in=readable.values_list("plmobject_id", flat=True)) object_list = manager.filter(query).exclude_cancelled() ctx.update(get_pagination(request, object_list, type)) extra_types = [c.__name__ for c in models.IObject.__subclasses__()] ctx.update({ "object_type": _("Browse"), "type": type, "extra_types": extra_types, }) return r2r("browse.html", ctx, request)
def test_edit_attributes(self): data = self.DATA.copy() data.update(type=self.TYPE, name="new_name") response = self.post(self.base_url + "modify/", data) obj = m.get_all_plmobjects()[self.TYPE].objects.all()[0] self.assertEqual(obj.name, data["name"])
def generate_part_doc_links(request,product, parent_ctrl,instances,doc3D, inbulk_cache): """ :param product: :class:`.Product` that represents the arborescense :param parent_ctrl: :class:`.Part` from which we want to realize the decomposition :param instances: Use to trace the items to update Parses forms and generates: - The bom-child of Parts (in relation to the **product**) - 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 Document3D has been set like the attribute PartDecompose of the Part - The attribute doc_id of every node of the arborescense(**product**) is now the relative id of :class:`.DocumentFile` generated in the previous condition - To every generated :class:`.Document3D` has been added a new empty(locked) :class:`.DocumentFile` STP ( :meth:`.generateGhostDocumentFile` ) - The attribute doc_path of every node of the arborescense(**product**) is now the path of :class:`.DocumentFile` STP generated in the previous condition """ to_delete=[] user = parent_ctrl._user company = pmodels.User.objects.get(username=settings.COMPANY) other_files = list(doc3D.files.exclude(models.is_stp)) for link in product.links: try: oq=forms.Order_Quantity_Form(request.POST,prefix=link.visited) oq.is_valid() options=oq.cleaned_data order=options["order"] quantity=options["quantity"] unit=options["unit"] if not link.product.part_to_decompose: part_ctype=forms.Doc_Part_type_Form(request.POST,prefix=link.product.visited) part_ctype.is_valid() options = part_ctype.cleaned_data cls = get_all_plmobjects()[options["type_part"]] part_form = pforms.get_creation_form(user, cls, request.POST, inbulk_cache=inbulk_cache, prefix=str(link.product.visited)+"-part") part_ctrl = parent_ctrl.create_from_form(part_form, user, True, True) instances.append((part_ctrl.object._meta.app_label, part_ctrl.object._meta.module_name, part_ctrl.object._get_pk_val())) c_link = parent_ctrl.add_child(part_ctrl.object,quantity,order,unit) models.generate_extra_location_links(link, c_link) doc_form = pforms.get_creation_form(user, models.Document3D, request.POST, inbulk_cache=inbulk_cache, prefix=str(link.product.visited)+"-document") doc_ctrl = models.Document3DController.create_from_form(doc_form, user, True, True) link.product.part_to_decompose=part_ctrl.object to_delete.append(generateGhostDocumentFile(link.product, doc_ctrl.object, company)) instances.append((doc_ctrl.object._meta.app_label, doc_ctrl.object._meta.module_name, doc_ctrl.object._get_pk_val())) part_ctrl.attach_to_document(doc_ctrl.object) new_Doc3D = doc_ctrl.object new_Doc3D.PartDecompose = part_ctrl.object new_Doc3D.no_index = True new_Doc3D.save() for doc_file in other_files: filename, ext = os.path.splitext(doc_file.filename) # add files with the same name (for example a .sldXXX # or.CATXXX file) if filename == link.product.name: f = File(doc_file.file) f.name = doc_file.filename f.size = doc_file.size df = doc_ctrl.add_file(f, False, False) if doc_file.thumbnail: doc_ctrl.add_thumbnail(df, File(doc_file.thumbnail)) instances.append((df._meta.app_label, df._meta.module_name, df.pk)) instances.append((doc_file._meta.app_label, doc_file._meta.module_name, doc_file.pk)) doc_file.no_index = True doc_file.deprecated = True doc_file.save() generate_part_doc_links(request,link.product, part_ctrl,instances,doc3D, inbulk_cache) else: c_link = parent_ctrl.add_child(link.product.part_to_decompose,quantity,order,unit) models.generate_extra_location_links(link, c_link) except Exception: raise models.Document_Generate_Bom_Error(to_delete,link.product.name)
def clean_form(request, assemblies, product, index, obj_type, inbulk_cache): """ :param assemblies: will be refill whit the information necessary the generate the forms :param product: :class:`.Product` that represents the arborescense of the :class:`~django.core.files.File` .stp contained in a :class:`.DocumentFile` :param index: Use to mark and to identify the **product** s that already have been visited :param obj_type: Type of the :class:`.Part` from which we want to realize the decomposition It checks the validity of the forms contained in **request** If the forms are not valid, it returns the information to refill the new forms contained in **assemblies**. Refill **assemblies** with the different assemblies of the file step , we use **index** to mark and to identify the **products** that already have been visited For every Assembly we have the next information: - Name of assembly - Visited , If assembly is sub-assembly of more than one assembly, this attribute will be **False** for all less one of the occurrences If visited is **False**, we will be able to modify only the attributes **Order** , **Quantity** and **Unit** refered to the :class:`.ParentChildLink` in the form If visited is not **False** , it will be a new id acording to **index** (>=1) generated to identify the assembly - Depth of assembly - **obj_type** , type of :class:`.Part` of Assembly - A list with the products that compose the assembly for each element in the list: - part_type contains the form to select the type of :class:`.Part` - ord_quantity contains the forms to select Order , Quantity and Unit refered to the :class:`.ParentChildLink` - creation_formset contains the form for the creation of the part selected in part_type and of one :class:`.Document3D` - name_child_assemblies contains the name of the element - is_assembly determine if the element is a single product or another assembly - prefix contains the **index** of the assembly if he is visited for first time , else is False - ref contains the **index** of the assembly if he was visited previously, else False """ valid=True if product.links: part_docs = [] for link in product.links: link.visited=index[0] oq = forms.Order_Quantity_Form(request.POST,prefix=index[0]) if not oq.is_valid(): valid=False is_assembly = link.product.is_assembly name = link.product.name if not link.product.visited: link.product.visited = index[0] part_type = forms.Doc_Part_type_Form(request.POST, prefix=index[0]) if not part_type.is_valid(): valid = False part = part_type.cleaned_data["type_part"] cls = get_all_plmobjects()[part] part_cform = pforms.get_creation_form(request.user, cls, request.POST, inbulk_cache=inbulk_cache, prefix=str(index[0])+"-part") doc_cform = pforms.get_creation_form(request.user, models.Document3D, request.POST, inbulk_cache=inbulk_cache, prefix=str(index[0])+"-document") if not part_cform.is_valid(): valid = False if not doc_cform.is_valid(): valid = False prefix = index[0] part_docs.append(PartDoc(part_type, oq, (part_cform, doc_cform), name, is_assembly, prefix, None)) index[0]+=1 if not clean_form(request, assemblies, link.product,index, part, inbulk_cache): valid = False else: index[0]+=1 part_docs.append(PartDoc(False, oq, False, name, is_assembly, None, link.product.visited)) assemblies.append(Assembly(part_docs, product.name , product.visited , product.deep, obj_type)) return valid
def create(cls, reference, type, revision, user, data={}, block_mails=False, no_index=False): u""" This method builds a new :class:`.PLMObject` of type *class_* and return a :class:`PLMObjectController` associated to the created object. Raises :exc:`ValueError` if *reference*, *type* or *revision* are empty. Raises :exc:`ValueError` if *type* is not valid. :param reference: reference of the objet :param type: type of the object :param revision: revision of the object :param user: user who creates/owns the object :param data: a dict<key, value> with informations to add to the plmobject :rtype: :class:`PLMObjectController` """ profile = user.profile if not (profile.is_contributor or profile.is_administrator): raise PermissionError("%s is not a contributor" % user) if not user.is_active: raise PermissionError(u"%s's account is inactive" % user) if profile.restricted: raise PermissionError( "Restricted account can not create a part or document.") if not reference or not type or not revision: raise ValueError( "Empty value not permitted for reference/type/revision") validate_reference(reference) validate_revision(revision) try: class_ = models.get_all_plmobjects()[type] except KeyError: raise ValueError("Incorrect type") # create an object reference_number = parse_reference_number(reference, class_) obj = class_(reference=reference, type=type, revision=revision, owner=user, creator=user, reference_number=reference_number) if no_index: obj.no_index = True if data: for key, value in data.iteritems(): if key not in [ "reference", "type", "revision", "auto", "pfiles" ]: setattr(obj, key, value) obj.state = models.get_default_state(obj.lifecycle) obj.save() res = cls(obj, user) if block_mails: res.block_mails() # record creation in history infos = {"type": type, "reference": reference, "revision": revision} infos.update(data) details = u" / ".join(u"%s : %s" % (k, v) for k, v in infos.items() if k not in ("auto", "pfiles", "type", "reference", "revision", "name")) res._save_histo("created", details) # add links (bulk create) ctime = obj.ctime links = [ models.PLMObjectUserLink(plmobject=obj, user=user, role="owner", ctime=ctime) ] try: l = models.DelegationLink.current_objects.select_related( "delegator").get(delegatee=user, role=models.ROLE_SPONSOR) sponsor = l.delegator if sponsor.username == settings.COMPANY: sponsor = user elif not res.check_in_group(sponsor, False): sponsor = user except models.DelegationLink.DoesNotExist: sponsor = user # the user can promote to the next state links.append( models.PLMObjectUserLink(plmobject=obj, user=user, role=level_to_sign_str(0), ctime=ctime)) # from the next state, only the sponsor can promote this object for i in range(1, obj.lifecycle.nb_states - 1): links.append( models.PLMObjectUserLink(plmobject=obj, user=sponsor, role=level_to_sign_str(i), ctime=ctime)) models.PLMObjectUserLink.objects.bulk_create(links) res._update_state_history() return res
def create(cls, reference, type, revision, user, data={}, block_mails=False, no_index=False): u""" This method builds a new :class:`.PLMObject` of type *class_* and return a :class:`PLMObjectController` associated to the created object. Raises :exc:`ValueError` if *reference*, *type* or *revision* are empty. Raises :exc:`ValueError` if *type* is not valid. :param reference: reference of the objet :param type: type of the object :param revision: revision of the object :param user: user who creates/owns the object :param data: a dict<key, value> with informations to add to the plmobject :rtype: :class:`PLMObjectController` """ profile = user.profile if not (profile.is_contributor or profile.is_administrator): raise PermissionError("%s is not a contributor" % user) if not user.is_active: raise PermissionError(u"%s's account is inactive" % user) if profile.restricted: raise PermissionError("Restricted account can not create a part or document.") if not reference or not type or not revision: raise ValueError("Empty value not permitted for reference/type/revision") validate_reference(reference) validate_revision(revision) try: class_ = models.get_all_plmobjects()[type] except KeyError: raise ValueError("Incorrect type") # create an object reference_number = parse_reference_number(reference, class_) obj = class_(reference=reference, type=type, revision=revision, owner=user, creator=user, reference_number=reference_number) if no_index: obj.no_index = True if data: for key, value in data.iteritems(): if key not in ["reference", "type", "revision", "auto", "pfiles"]: setattr(obj, key, value) obj.state = models.get_default_state(obj.lifecycle) obj.save() res = cls(obj, user) if block_mails: res.block_mails() # record creation in history infos = {"type" : type, "reference" : reference, "revision" : revision} infos.update(data) details = u" / ".join(u"%s : %s" % (k, v) for k, v in infos.items() if k not in ("auto", "pfiles", "type", "reference", "revision", "name")) res._save_histo("created", details) # add links (bulk create) ctime = obj.ctime links = [models.PLMObjectUserLink(plmobject=obj, user=user, role="owner", ctime=ctime)] try: l = models.DelegationLink.current_objects.select_related("delegator").get(delegatee=user, role=models.ROLE_SPONSOR) sponsor = l.delegator if sponsor.username == settings.COMPANY: sponsor = user elif not res.check_in_group(sponsor, False): sponsor = user except models.DelegationLink.DoesNotExist: sponsor = user # the user can promote to the next state links.append(models.PLMObjectUserLink(plmobject=obj, user=user, role=level_to_sign_str(0), ctime=ctime)) # from the next state, only the sponsor can promote this object for i in range(1, obj.lifecycle.nb_states - 1): links.append(models.PLMObjectUserLink(plmobject=obj, user=sponsor, role=level_to_sign_str(i), ctime=ctime)) models.PLMObjectUserLink.objects.bulk_create(links) res._update_state_history() return res