示例#1
0
    def key(self, value: str) -> None:
        self._key = value

        if value.startswith('-'):
            attr_name = value[1:]
            self._reverse_order = True
        else:
            attr_name = value
            self._reverse_order = False

        field_info = FieldInfo(self.queryset.model, attr_name)

        if any(f.many_to_many for f in field_info):
            raise ValueError(
                'Invalid key: ManyToManyFields cannot be used as key.')

        # TODO: if related_model is not None ?
        last_field = field_info[-1]

        if last_field.is_relation:
            subfield_model = last_field.remote_field.model
            subfield_ordering = subfield_model._meta.ordering

            if not subfield_ordering:
                raise ValueError(
                    f'Invalid key: related field model "{subfield_model}" '
                    f'should have Meta.ordering')

            attr_name += '__' + subfield_ordering[0]
            field_info = FieldInfo(self.queryset.model, attr_name)

        self._attr_name = attr_name
        self._key_field_info = field_info
示例#2
0
    def test_localcache_is_fieldinfo_hidden05(self):
        "Field in CremeEntity."
        hidden = 'description'
        FieldsConfig.objects.create(
            content_type=FakeImage,
            descriptions=[(hidden, {FieldsConfig.HIDDEN: True})],
        )

        is_hidden = FieldsConfig.LocalCache().is_fieldinfo_hidden
        self.assertTrue(is_hidden(FieldInfo(FakeImage, hidden)))
        self.assertFalse(is_hidden(FieldInfo(FakeContact, 'image')))
        self.assertTrue(is_hidden(FieldInfo(FakeContact, f'image__{hidden}')))
示例#3
0
    def test_localcache_is_fieldinfo_hidden04(self):
        "Sub-field hidden."
        hidden = 'exif_date'

        FieldsConfig.objects.create(
            content_type=FakeImage,
            descriptions=[
                (hidden,  {FieldsConfig.HIDDEN: True}),
            ],
        )

        is_hidden = FieldsConfig.LocalCache().is_fieldinfo_hidden
        self.assertFalse(is_hidden(FieldInfo(FakeContact, 'first_name')))
        self.assertFalse(is_hidden(FieldInfo(FakeContact, 'image')))
        self.assertTrue(is_hidden(FieldInfo(FakeContact, f'image__{hidden}')))
示例#4
0
    def __new__(cls, report_field):
        try:
            field_info = FieldInfo(report_field.model, report_field.name)
        except FieldDoesNotExist as e:
            raise ReportHand.ValueError('Invalid field: "{}" (does not exist)'.format(report_field.name)) from e

        info_length = len(field_info)
        if info_length > 1:
            if info_length > 2:
                raise ReportHand.ValueError('Invalid field: "{}" (too deep)'.format(report_field.name))

            second_part = field_info[1]

            if (isinstance(second_part, (ForeignKey, ManyToManyField)) and
               issubclass(second_part.remote_field.model, CremeEntity)):
                raise ReportHand.ValueError('Invalid field: "{}" (no entity at depth=1)'.format(report_field.name))

        first_part = field_info[0]
        klass = RHForeignKey if isinstance(first_part, ForeignKey) else \
                RHManyToManyField if isinstance(first_part, ManyToManyField) else \
                RHRegularField

        instance = ReportHand.__new__(klass)
        instance._field_info = field_info

        return instance
示例#5
0
    def validate_fieldname(graph, field_name):
        try:
            field_info = FieldInfo(graph.model, field_name)
        except FieldDoesNotExist:
            return 'invalid field "{}"'.format(field_name)

        if len(field_info) > 1:
            return 'field "{}" with deep > 1'.format(field_name)

        field = field_info[0]

        if not (isinstance(field, ForeignKey) and issubclass(field.remote_field.model, CremeEntity)):
            return 'field "{}" is not a ForeignKey to CremeEntity'.format(field_name)
示例#6
0
    def get_q(self, *, model, field_name, values):
        # As default, set isnull operator (always true, negate is done later)
        query = Q(**{self.key_pattern.format(field_name): True})

        # Add filter for text fields, "isEmpty" should mean null or empty string
        finfo = FieldInfo(model, field_name)  # TODO: what about CustomField ?!
        if isinstance(finfo[-1], (models.CharField, models.TextField)):
            query |= Q(**{field_name: ''})

        # Negate filter on false value
        if not values[0]:
            query.negate()

        return query
示例#7
0
    def test_localcache_is_fieldinfo_hidden06(self):
        "Sub-field with depth > 1."
        hidden = 'description'
        FieldsConfig.objects.create(
            content_type=FakeFolder,
            descriptions=[(hidden, {FieldsConfig.HIDDEN: True})],
        )

        is_hidden = FieldsConfig.LocalCache().is_fieldinfo_hidden
        self.assertTrue(is_hidden(FieldInfo(FakeFolder, hidden)))
        self.assertFalse(is_hidden(FieldInfo(FakeDocument, hidden)))
        self.assertFalse(is_hidden(FieldInfo(FakeDocument, 'linked_folder')))
        self.assertTrue(is_hidden(FieldInfo(FakeDocument, f'linked_folder__{hidden}')))
        self.assertFalse(is_hidden(FieldInfo(FakeDocument, 'linked_folder__parent')))
        self.assertTrue(is_hidden(FieldInfo(FakeDocument, f'linked_folder__parent__{hidden}')))
示例#8
0
 def test_localcache_is_fieldinfo_hidden01(self):
     "No field configured."
     is_hidden = FieldsConfig.LocalCache().is_fieldinfo_hidden
     self.assertFalse(is_hidden(FieldInfo(FakeContact, 'first_name')))
     self.assertFalse(is_hidden(FieldInfo(FakeContact, 'image')))
     self.assertFalse(is_hidden(FieldInfo(FakeContact, 'image__exif_date')))
示例#9
0
    def create_report_n_graphes(self, rt_obj_emit_orga):
        "Create the report 'Opportunities' and 2 ReportGraphs."
        from django.contrib.auth import get_user_model

        from creme import reports
        from creme.creme_core.utils.meta import FieldInfo
        # from creme.reports import constants as rep_constants
        from creme.reports.constants import RFT_FIELD, RFT_RELATION
        from creme.reports.core.graph.fetcher import SimpleGraphFetcher
        from creme.reports.models import Field

        admin = get_user_model().objects.get_admin()

        if reports.report_model_is_custom():
            logger.info(
                'Report model is custom => no Opportunity report is created.')
            return

        # Create the report ----------------------------------------------------
        report = reports.get_report_model().objects.create(
            name=_('Opportunities'),
            user=admin,
            ct=Opportunity,
        )

        # TODO: helper method(s) (see EntityFilterCondition)
        create_field = partial(Field.objects.create,
                               report=report,
                               type=RFT_FIELD)
        create_field(name='name', order=1)
        create_field(name='estimated_sales', order=2)
        create_field(name='made_sales', order=3)
        create_field(name='sales_phase__name', order=4)
        create_field(name=rt_obj_emit_orga.id, order=5, type=RFT_RELATION)

        # Create 2 graphs ------------------------------------------------------
        if reports.rgraph_model_is_custom():
            logger.info('ReportGraph model is custom'
                        ' => no Opportunity report-graph is created.')
            return

        sales_cell = EntityCellRegularField.build(Opportunity,
                                                  'estimated_sales')
        if sales_cell is None:
            logger.warning(
                'Opportunity seems not having a field "estimated_sales"'
                ' => no ReportGraph created.')
            return

        ReportGraph = reports.get_rgraph_model()

        # TODO: helper method (range only on DateFields etc...)
        create_graph = partial(
            ReportGraph.objects.create,
            linked_report=report,
            user=admin,
            # ordinate_type=rep_constants.RGA_SUM,
            ordinate_type=ReportGraph.Aggregator.SUM,
            ordinate_cell_key=sales_cell.key,
        )
        esales_vname = FieldInfo(Opportunity, 'estimated_sales').verbose_name
        rgraph1 = create_graph(
            name=_('Sum {estimated_sales} / {sales_phase}').format(
                estimated_sales=esales_vname,
                sales_phase=FieldInfo(Opportunity, 'sales_phase').verbose_name,
            ),
            # abscissa_type=rep_constants.RGT_FK,
            abscissa_type=ReportGraph.Group.FK,
            abscissa_cell_value='sales_phase',
        )
        rgraph2 = create_graph(
            name=_(
                'Sum {estimated_sales} / Quarter (90 days on {closing_date})').
            format(
                estimated_sales=esales_vname,
                closing_date=FieldInfo(Opportunity,
                                       'closing_date').verbose_name,
            ),
            # abscissa_type=rep_constants.RGT_RANGE,
            abscissa_type=ReportGraph.Group.RANGE,
            abscissa_cell_value='closing_date',
            abscissa_parameter='90',
        )

        # Create 2 instance block items for the 2 graphs -----------------------
        brick_id1 = SimpleGraphFetcher(
            rgraph1).create_brick_config_item().brick_id
        brick_id2 = SimpleGraphFetcher(
            rgraph2).create_brick_config_item().brick_id

        create_bdl = partial(
            BrickDetailviewLocation.objects.create_if_needed,
            zone=BrickDetailviewLocation.RIGHT,
            model=Opportunity,
        )
        create_bdl(brick=brick_id1, order=4)
        create_bdl(brick=brick_id2, order=6)

        create_hbl = BrickHomeLocation.objects.create
        create_hbl(brick_id=brick_id1, order=5)
        create_hbl(brick_id=brick_id2, order=6)
示例#10
0
    def create_report_n_graphes(self, rt_obj_emit_orga):
        "Create the report 'Opportunities' and 2 ReportGraphs."
        from django.contrib.auth import get_user_model

        from creme.creme_core.utils.meta import FieldInfo

        from creme import reports
        from creme.reports import constants as rep_constants
        from creme.reports.models import Field

        admin = get_user_model().objects.get_admin()

        if reports.report_model_is_custom():
            logger.info(
                'Report model is custom => no Opportunity report is created.')
            return

        # Create the report ----------------------------------------------------
        report = reports.get_report_model() \
                        .objects.create(name=_('Opportunities'), user=admin, ct=Opportunity)

        # TODO: helper method(s) (see EntityFilterCondition)
        create_field = partial(Field.objects.create,
                               report=report,
                               type=rep_constants.RFT_FIELD)
        create_field(name='name', order=1)
        create_field(name='estimated_sales', order=2)
        create_field(name='made_sales', order=3)
        create_field(name='sales_phase__name', order=4)
        create_field(name=rt_obj_emit_orga.id,
                     order=5,
                     type=rep_constants.RFT_RELATION)

        # Create 2 graphs -----------------------------------------------------
        if reports.rgraph_model_is_custom():
            logger.info(
                'ReportGraph model is custom => no Opportunity report-graph is created.'
            )
            return

        # TODO: helper method ('sum' => is_count=False, range only on DateFields etc...)
        create_graph = partial(
            reports.get_rgraph_model().objects.create,
            linked_report=report,
            user=admin,
            is_count=False,
            ordinate='estimated_sales__sum',
        )
        esales_vname = FieldInfo(Opportunity, 'estimated_sales').verbose_name
        rgraph1 = create_graph(
            name=_('Sum {estimated_sales} / {sales_phase}').format(
                estimated_sales=esales_vname,
                sales_phase=FieldInfo(Opportunity, 'sales_phase').verbose_name,
            ),
            abscissa='sales_phase',
            type=rep_constants.RGT_FK,
        )
        rgraph2 = create_graph(
            name=_(
                'Sum {estimated_sales} / Quarter (90 days on {closing_date})').
            format(
                estimated_sales=esales_vname,
                closing_date=FieldInfo(Opportunity,
                                       'closing_date').verbose_name,
            ),
            abscissa='closing_date',
            type=rep_constants.RGT_RANGE,
            days=90,
        )

        # Create 2 instance block items for the 2 graphs ----------------------
        brick_id1 = rgraph1.create_instance_brick_config_item().brick_id
        brick_id2 = rgraph2.create_instance_brick_config_item().brick_id

        create_bdl = partial(
            BrickDetailviewLocation.objects.create_if_needed,
            zone=BrickDetailviewLocation.RIGHT,
            model=Opportunity,
        )
        create_bdl(brick=brick_id1, order=4)
        create_bdl(brick=brick_id2, order=6)

        BrickHomeLocation.objects.create(brick_id=brick_id1, order=5)
        BrickHomeLocation.objects.create(brick_id=brick_id2, order=6)