creme-crm 2.7.3__py3-none-any.whl → 2.7.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- creme/__init__.py +1 -1
- creme/creme_config/bricks.py +2 -0
- creme/creme_config/tests/test_custom_form.py +13 -0
- creme/creme_config/views/custom_form.py +5 -4
- creme/creme_core/forms/enumerable.py +24 -10
- creme/creme_core/models/fields_config.py +3 -4
- creme/creme_core/tests/forms/test_enumerable.py +143 -0
- creme/creme_core/tests/forms/test_widgets.py +3 -2
- creme/reports/locale/fr/LC_MESSAGES/django.mo +0 -0
- creme/reports/locale/fr/LC_MESSAGES/django.po +4 -1
- creme/reports/templates/reports/bricks/report-hat-bar.html +6 -2
- creme/reports/templates/reports/preview_report.html +6 -1
- creme/reports/tests/test_report.py +37 -1
- creme/reports/views/export.py +2 -1
- {creme_crm-2.7.3.dist-info → creme_crm-2.7.4.dist-info}/METADATA +2 -2
- {creme_crm-2.7.3.dist-info → creme_crm-2.7.4.dist-info}/RECORD +20 -20
- {creme_crm-2.7.3.dist-info → creme_crm-2.7.4.dist-info}/WHEEL +0 -0
- {creme_crm-2.7.3.dist-info → creme_crm-2.7.4.dist-info}/entry_points.txt +0 -0
- {creme_crm-2.7.3.dist-info → creme_crm-2.7.4.dist-info}/licenses/LICENSE.txt +0 -0
- {creme_crm-2.7.3.dist-info → creme_crm-2.7.4.dist-info}/top_level.txt +0 -0
creme/__init__.py
CHANGED
creme/creme_config/bricks.py
CHANGED
|
@@ -358,6 +358,8 @@ class CustomFieldsBrick(Brick):
|
|
|
358
358
|
_ContentTypeWrapper(get_ct(ct_id), ct_cfields)
|
|
359
359
|
for ct_id, ct_cfields in cfields_per_ct_id.items()
|
|
360
360
|
]
|
|
361
|
+
sort_key = collator.sort_key
|
|
362
|
+
ctypes.sort(key=lambda wrp: sort_key(str(wrp.ctype)))
|
|
361
363
|
|
|
362
364
|
return self._render(self.get_template_context(
|
|
363
365
|
context,
|
|
@@ -1598,6 +1598,19 @@ class CustomFormTestCase(BrickTestCaseMixin, CremeTestCase):
|
|
|
1598
1598
|
reverse('creme_config__delete_custom_form_cell', args=(cfci.id,)),
|
|
1599
1599
|
data={'cell_key': cell_to_dell.key},
|
|
1600
1600
|
)
|
|
1601
|
+
self.assertListEqual(
|
|
1602
|
+
[
|
|
1603
|
+
{
|
|
1604
|
+
'name': 'General', 'layout': LAYOUT_REGULAR,
|
|
1605
|
+
'cells': [
|
|
1606
|
+
{'type': 'regular_field', 'value': 'user'},
|
|
1607
|
+
{'type': 'regular_field', 'value': 'name'},
|
|
1608
|
+
]
|
|
1609
|
+
},
|
|
1610
|
+
{'group_id': FakeAddressGroup.extra_group_id},
|
|
1611
|
+
],
|
|
1612
|
+
self.refresh(cfci).groups_as_dicts(),
|
|
1613
|
+
)
|
|
1601
1614
|
|
|
1602
1615
|
@parameterized.expand([
|
|
1603
1616
|
(0, LAYOUT_DUAL_FIRST),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
################################################################################
|
|
2
2
|
# Creme is a free/open-source Customer Relationship Management software
|
|
3
|
-
# Copyright (C) 2020-
|
|
3
|
+
# Copyright (C) 2020-2026 Hybird
|
|
4
4
|
#
|
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
|
@@ -318,8 +318,9 @@ class CustomFormCellDeletion(BaseCustomFormDeletion):
|
|
|
318
318
|
desc = self.get_customform_descriptor()
|
|
319
319
|
|
|
320
320
|
groups = []
|
|
321
|
-
found = False
|
|
321
|
+
found = False # Found in any group
|
|
322
322
|
for group in self.get_groups():
|
|
323
|
+
found_in_group = False
|
|
323
324
|
cells = []
|
|
324
325
|
|
|
325
326
|
# TODO: better API for group.cells ?
|
|
@@ -327,11 +328,11 @@ class CustomFormCellDeletion(BaseCustomFormDeletion):
|
|
|
327
328
|
if cell.key != cell_key:
|
|
328
329
|
cells.append(cell)
|
|
329
330
|
else:
|
|
330
|
-
found = True
|
|
331
|
+
found = found_in_group = True
|
|
331
332
|
|
|
332
333
|
groups.append(
|
|
333
334
|
FieldGroup(name=group.name, cells=cells, layout=group.layout)
|
|
334
|
-
if
|
|
335
|
+
if found_in_group else
|
|
335
336
|
group
|
|
336
337
|
)
|
|
337
338
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
################################################################################
|
|
2
2
|
# Creme is a free/open-source Customer Relationship Management software
|
|
3
|
-
# Copyright (C) 2022-
|
|
3
|
+
# Copyright (C) 2022-2026 Hybird
|
|
4
4
|
#
|
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
|
@@ -260,30 +260,35 @@ class EnumerableSelect(widgets.Select):
|
|
|
260
260
|
|
|
261
261
|
def get_context(self, name, value, attrs):
|
|
262
262
|
context = super().get_context(name, value, attrs)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
choices, more = enumerable.groups(
|
|
266
|
-
selected_values=[value] if value else None
|
|
267
|
-
) if enumerable is not None else ((), False)
|
|
263
|
+
choices, more = self.get_enum_groups(value)
|
|
268
264
|
|
|
269
265
|
context['widget']['choices'] = choices
|
|
270
266
|
self.build_enum_attrs(context['widget']['attrs'], more)
|
|
271
267
|
|
|
272
268
|
return context
|
|
273
269
|
|
|
270
|
+
def get_enum_groups(self, value):
|
|
271
|
+
enumerable = self.enumerable
|
|
272
|
+
|
|
273
|
+
return enumerable.groups(
|
|
274
|
+
selected_values=[value] if value else None
|
|
275
|
+
) if enumerable is not None else ((), False)
|
|
276
|
+
|
|
274
277
|
def build_enum_attrs(self, attrs, more):
|
|
278
|
+
enumerable = self.enumerable
|
|
279
|
+
|
|
275
280
|
if more:
|
|
276
281
|
attrs.update({
|
|
277
|
-
'data-enum-url':
|
|
278
|
-
'data-enum-limit':
|
|
282
|
+
'data-enum-url': enumerable.url,
|
|
283
|
+
'data-enum-limit': enumerable.limit,
|
|
279
284
|
})
|
|
280
285
|
attrs.setdefault('data-enum-cache', 'true')
|
|
281
286
|
attrs.setdefault('data-enum-debounce', self.ENUMERABLE_DEFAULT_DEBOUNCE_DELAY)
|
|
282
287
|
|
|
283
288
|
attrs['data-allow-clear'] = str(not self.is_required).lower()
|
|
284
289
|
|
|
285
|
-
if
|
|
286
|
-
attrs['data-placeholder'] =
|
|
290
|
+
if enumerable.empty_label:
|
|
291
|
+
attrs['data-placeholder'] = enumerable.empty_label
|
|
287
292
|
|
|
288
293
|
if self.create_url:
|
|
289
294
|
attrs['data-create-url'] = self.create_url
|
|
@@ -294,6 +299,15 @@ class EnumerableSelect(widgets.Select):
|
|
|
294
299
|
class EnumerableSelectMultiple(EnumerableSelect):
|
|
295
300
|
allow_multiple_selected = True
|
|
296
301
|
|
|
302
|
+
def get_enum_groups(self, value):
|
|
303
|
+
# The value is already a list here, so we need to override the default
|
|
304
|
+
# behaviour
|
|
305
|
+
enumerable = self.enumerable
|
|
306
|
+
|
|
307
|
+
return enumerable.groups(
|
|
308
|
+
selected_values=value if value else None
|
|
309
|
+
) if enumerable is not None else ((), False)
|
|
310
|
+
|
|
297
311
|
def value_from_datadict(self, data, files, name):
|
|
298
312
|
try:
|
|
299
313
|
getter = data.getlist
|
|
@@ -427,12 +427,11 @@ class FieldsConfig(CremeModel):
|
|
|
427
427
|
try:
|
|
428
428
|
form_fields[field_name].required = True
|
|
429
429
|
except KeyError:
|
|
430
|
-
|
|
431
|
-
logger.info(
|
|
430
|
+
logger.warning(
|
|
432
431
|
'The field "%s" has been configured to be required '
|
|
433
|
-
'but the
|
|
432
|
+
'but the form %s does not use this field; '
|
|
434
433
|
'so we add it.',
|
|
435
|
-
field_name,
|
|
434
|
+
field_name, type(form),
|
|
436
435
|
)
|
|
437
436
|
# TODO: is it possible that field does not exist any more ?
|
|
438
437
|
form_fields[field_name] = (
|
|
@@ -19,6 +19,7 @@ from creme.creme_core.forms.enumerable import (
|
|
|
19
19
|
EnumerableChoice,
|
|
20
20
|
EnumerableModelChoiceField,
|
|
21
21
|
EnumerableSelect,
|
|
22
|
+
EnumerableSelectMultiple,
|
|
22
23
|
FieldEnumerableChoiceSet,
|
|
23
24
|
)
|
|
24
25
|
from creme.creme_core.models import (
|
|
@@ -451,6 +452,148 @@ class EnumerableSelectTestCase(CremeTestCase):
|
|
|
451
452
|
)
|
|
452
453
|
|
|
453
454
|
|
|
455
|
+
@override_settings(FORM_ENUMERABLE_LIMIT=100)
|
|
456
|
+
class EnumerableSelectMultipleTestCase(CremeTestCase):
|
|
457
|
+
maxDiff = None
|
|
458
|
+
|
|
459
|
+
def test_render_no_url(self):
|
|
460
|
+
farming, industry, software = FakeSector.objects.order_by('pk')[:3]
|
|
461
|
+
sector_A = FakeSector.objects.create(title='Sector A')
|
|
462
|
+
sector_B = FakeSector.objects.create(title='Sector B')
|
|
463
|
+
sector_C = FakeSector.objects.create(title='Sector C')
|
|
464
|
+
|
|
465
|
+
enumerable = FieldEnumerableChoiceSet(FakeContact._meta.get_field('sector'))
|
|
466
|
+
widget = EnumerableSelectMultiple(enumerable)
|
|
467
|
+
|
|
468
|
+
self.assertHTMLEqual(
|
|
469
|
+
f'''
|
|
470
|
+
<select class="ui-creme-input ui-creme-widget ui-creme-dselect widget-auto is-enum"
|
|
471
|
+
widget="ui-creme-dselect"
|
|
472
|
+
name="testfield" autocomplete
|
|
473
|
+
data-allow-clear="true" multiple>
|
|
474
|
+
<option value="{farming.pk}">Farming</option>
|
|
475
|
+
<option selected value="{industry.pk}">Industry</option>
|
|
476
|
+
<option value="{software.pk}">Software</option>
|
|
477
|
+
<option value="{sector_A.pk}">Sector A</option>
|
|
478
|
+
<option value="{sector_B.pk}">Sector B</option>
|
|
479
|
+
<option selected value="{sector_C.pk}">Sector C</option>
|
|
480
|
+
</select>
|
|
481
|
+
''',
|
|
482
|
+
widget.render('testfield', value=(industry.pk, sector_C.pk)),
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
def test_render_url(self):
|
|
486
|
+
farming, industry, software = FakeSector.objects.order_by('pk')[:3]
|
|
487
|
+
|
|
488
|
+
enumerable = FieldEnumerableChoiceSet(FakeContact._meta.get_field('sector'))
|
|
489
|
+
widget = EnumerableSelectMultiple(enumerable)
|
|
490
|
+
widget.create_url = url = reverse(
|
|
491
|
+
'creme_config__create_instance_from_widget', args=('creme_core', 'fake_sector'),
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
self.assertHTMLEqual(
|
|
495
|
+
f'''
|
|
496
|
+
<select class="ui-creme-input ui-creme-widget ui-creme-dselect widget-auto is-enum"
|
|
497
|
+
widget="ui-creme-dselect"
|
|
498
|
+
name="testfield" autocomplete
|
|
499
|
+
data-create-url="{url}"
|
|
500
|
+
data-allow-clear="true" multiple>
|
|
501
|
+
<option value="{farming.pk}">Farming</option>
|
|
502
|
+
<option selected value="{industry.pk}">Industry</option>
|
|
503
|
+
<option selected value="{software.pk}">Software</option>
|
|
504
|
+
</select>
|
|
505
|
+
''',
|
|
506
|
+
widget.render('testfield', value=(industry.pk, software.pk)),
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
def test_render__more(self):
|
|
510
|
+
farming, industry, software = FakeSector.objects.order_by('pk')[:3]
|
|
511
|
+
sector_A = FakeSector.objects.create(title='Sector A')
|
|
512
|
+
FakeSector.objects.create(title='Sector B')
|
|
513
|
+
FakeSector.objects.create(title='Sector C')
|
|
514
|
+
|
|
515
|
+
enumerable = FieldEnumerableChoiceSet(FakeContact._meta.get_field('sector'), limit=4)
|
|
516
|
+
widget = EnumerableSelectMultiple(enumerable)
|
|
517
|
+
|
|
518
|
+
self.assertHTMLEqual(
|
|
519
|
+
f'''
|
|
520
|
+
<select class="ui-creme-input ui-creme-widget ui-creme-dselect widget-auto is-enum"
|
|
521
|
+
widget="ui-creme-dselect"
|
|
522
|
+
name="testfield" autocomplete
|
|
523
|
+
data-allow-clear="true"
|
|
524
|
+
data-enum-url="{enumerable.url}"
|
|
525
|
+
data-enum-limit="{enumerable.limit}"
|
|
526
|
+
data-enum-cache="true"
|
|
527
|
+
data-enum-debounce="300"
|
|
528
|
+
multiple>
|
|
529
|
+
<option value="{farming.pk}">Farming</option>
|
|
530
|
+
<option selected value="{industry.pk}">Industry</option>
|
|
531
|
+
<option value="{software.pk}">Software</option>
|
|
532
|
+
<option selected value="{sector_A.pk}">Sector A</option>
|
|
533
|
+
</select>
|
|
534
|
+
''',
|
|
535
|
+
widget.render('testfield', value=(industry.pk, sector_A.pk)),
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
def test_render__more__outside_limit(self):
|
|
539
|
+
"""Selected values outside the choice limit are added anyway"""
|
|
540
|
+
farming, industry, software = FakeSector.objects.order_by('pk')[:3]
|
|
541
|
+
sector_A = FakeSector.objects.create(title='Sector A')
|
|
542
|
+
FakeSector.objects.create(title='Sector B')
|
|
543
|
+
sector_C = FakeSector.objects.create(title='Sector C')
|
|
544
|
+
|
|
545
|
+
enumerable = FieldEnumerableChoiceSet(FakeContact._meta.get_field('sector'), limit=4)
|
|
546
|
+
widget = EnumerableSelectMultiple(enumerable)
|
|
547
|
+
|
|
548
|
+
self.assertHTMLEqual(
|
|
549
|
+
f'''
|
|
550
|
+
<select class="ui-creme-input ui-creme-widget ui-creme-dselect widget-auto is-enum"
|
|
551
|
+
widget="ui-creme-dselect"
|
|
552
|
+
name="testfield" autocomplete
|
|
553
|
+
data-allow-clear="true"
|
|
554
|
+
data-enum-url="{enumerable.url}"
|
|
555
|
+
data-enum-limit="{enumerable.limit}"
|
|
556
|
+
data-enum-cache="true"
|
|
557
|
+
data-enum-debounce="300"
|
|
558
|
+
multiple>
|
|
559
|
+
<option value="{farming.pk}">Farming</option>
|
|
560
|
+
<option selected value="{industry.pk}">Industry</option>
|
|
561
|
+
<option value="{software.pk}">Software</option>
|
|
562
|
+
<option value="{sector_A.pk}">Sector A</option>
|
|
563
|
+
<option selected value="{sector_C.pk}">Sector C</option>
|
|
564
|
+
</select>
|
|
565
|
+
''',
|
|
566
|
+
widget.render('testfield', value=(industry.pk, sector_C.pk)),
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
def test_render__more_custom_attrs(self):
|
|
570
|
+
farming, industry, software = FakeSector.objects.order_by('pk')[:3]
|
|
571
|
+
|
|
572
|
+
enumerable = FieldEnumerableChoiceSet(FakeContact._meta.get_field('sector'), limit=2)
|
|
573
|
+
widget = EnumerableSelectMultiple(enumerable, attrs={
|
|
574
|
+
'data-enum-cache': 'false',
|
|
575
|
+
'data-enum-debounce': 500,
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
self.assertHTMLEqual(
|
|
579
|
+
f'''
|
|
580
|
+
<select class="ui-creme-input ui-creme-widget ui-creme-dselect widget-auto is-enum"
|
|
581
|
+
widget="ui-creme-dselect"
|
|
582
|
+
name="testfield" autocomplete
|
|
583
|
+
data-allow-clear="true"
|
|
584
|
+
data-enum-url="{enumerable.url}"
|
|
585
|
+
data-enum-limit="{enumerable.limit}"
|
|
586
|
+
data-enum-cache="false"
|
|
587
|
+
data-enum-debounce="500"
|
|
588
|
+
multiple>
|
|
589
|
+
<option value="{farming.pk}">Farming</option>
|
|
590
|
+
<option selected value="{industry.pk}">Industry</option>
|
|
591
|
+
</select>
|
|
592
|
+
''',
|
|
593
|
+
widget.render('testfield', value=(industry.pk,)),
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
|
|
454
597
|
@override_settings(FORM_ENUMERABLE_LIMIT=100)
|
|
455
598
|
class EnumerableModelChoiceFieldTestCase(CremeTestCase):
|
|
456
599
|
maxDiff = None
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import difflib
|
|
2
|
+
from datetime import date
|
|
2
3
|
from json import loads as json_load
|
|
3
4
|
from unittest.util import safe_repr
|
|
4
5
|
|
|
@@ -79,7 +80,7 @@ class CalendarWidgetTestCase(CremeTestCase):
|
|
|
79
80
|
def test_render__en(self):
|
|
80
81
|
name = 'my_calendar'
|
|
81
82
|
value = self.formfield_value_date(2023, 3, 26)
|
|
82
|
-
help_text = _('E.g. {}').format('
|
|
83
|
+
help_text = _('E.g. {}').format(f'{date.today().year}-12-31')
|
|
83
84
|
self.assertHTMLEqual(
|
|
84
85
|
f'<div class="creme-datepicker">'
|
|
85
86
|
f' <div class="help-text-format">{help_text}</div>'
|
|
@@ -96,7 +97,7 @@ class CalendarWidgetTestCase(CremeTestCase):
|
|
|
96
97
|
def test_render__fr(self):
|
|
97
98
|
name = 'calendar'
|
|
98
99
|
value = self.formfield_value_date(2024, 4, 27)
|
|
99
|
-
help_text = _('E.g. {}').format('31/12/
|
|
100
|
+
help_text = _('E.g. {}').format(f'31/12/{date.today().year}')
|
|
100
101
|
self.assertHTMLEqual(
|
|
101
102
|
f'<div class="creme-datepicker">'
|
|
102
103
|
f' <div class="help-text-format">{help_text}</div>'
|
|
Binary file
|
|
@@ -8,7 +8,7 @@ msgid ""
|
|
|
8
8
|
msgstr ""
|
|
9
9
|
"Project-Id-Version: Creme Reports 2.7\n"
|
|
10
10
|
"Report-Msgid-Bugs-To: \n"
|
|
11
|
-
"POT-Creation-Date:
|
|
11
|
+
"POT-Creation-Date: 2026-01-09 18:30+0100\n"
|
|
12
12
|
"Last-Translator: Hybird <contact@hybird.org>\n"
|
|
13
13
|
"Language: fr\n"
|
|
14
14
|
"MIME-Version: 1.0\n"
|
|
@@ -613,6 +613,9 @@ msgstr "Type de graphique"
|
|
|
613
613
|
msgid "Download CSV"
|
|
614
614
|
msgstr "Télécharger CSV"
|
|
615
615
|
|
|
616
|
+
msgid "You cannot export this type of entity"
|
|
617
|
+
msgstr "Vous ne pouvez pas exporter ce type de fiche"
|
|
618
|
+
|
|
616
619
|
msgid "Go to the configuration of Reports' filters"
|
|
617
620
|
msgstr "Aller à la configuration des filtres de Rapports"
|
|
618
621
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% extends 'creme_core/bricks/generic/hat-bar.html' %}
|
|
2
|
-
{% load i18n creme_bricks creme_widgets %}
|
|
2
|
+
{% load i18n creme_bricks creme_perms creme_widgets %}
|
|
3
3
|
{% load url from creme_core_tags %}
|
|
4
4
|
|
|
5
5
|
{% block buttons %}
|
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
</a>
|
|
10
10
|
</div>
|
|
11
11
|
<div class='bar-action'>
|
|
12
|
-
|
|
12
|
+
{% if user|has_perm_to_export:object.ct %}
|
|
13
|
+
{% brick_bar_button action='reports-export' url='reports__export_report_filter'|url:object.id label=_('Download CSV') icon='document_csv' %}
|
|
14
|
+
{% else %}
|
|
15
|
+
{% brick_bar_button action='reports-export' url='' label=_('Download CSV') icon='document_csv' help_text=_('You cannot export this type of entity') enabled=False %}
|
|
16
|
+
{% endif%}
|
|
13
17
|
</div>
|
|
14
18
|
{{block.super}}
|
|
15
19
|
{% endblock %}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{% extends 'creme_core/detailview.html' %}
|
|
2
2
|
{% load i18n creme_widgets reports_tags %}
|
|
3
|
+
{% load i18n creme_perms creme_widgets %}{# reports_tags #}
|
|
3
4
|
|
|
4
5
|
{% block page_title %}{% blocktranslate %}Preview {{object}}{% endblocktranslate %} - {% endblock %}
|
|
5
6
|
|
|
@@ -34,7 +35,11 @@
|
|
|
34
35
|
<form>{% include 'reports/frags/report_preview_format.html' %}</form>
|
|
35
36
|
<div class="report-preview-buttons">
|
|
36
37
|
<button class="ui-creme-actionbutton" type="button" name="generate">{% translate 'Preview' context 'reports-preview' %}</button>
|
|
37
|
-
|
|
38
|
+
{% if user|has_perm_to_export:object.ct %}
|
|
39
|
+
<button class="ui-creme-actionbutton" type="button" name="download">{% translate 'Download as file' %}</button>
|
|
40
|
+
{% else %}
|
|
41
|
+
<button disabled class="ui-creme-actionbutton" type="button" name="download" title="{% translate 'You cannot export this type of entity'%}" >{% translate 'Download as file' %}</button>
|
|
42
|
+
{% endif %}
|
|
38
43
|
</div>
|
|
39
44
|
</div>
|
|
40
45
|
|
|
@@ -1545,8 +1545,44 @@ class ReportTestCase(BrickTestCaseMixin, BaseReportsTestCase):
|
|
|
1545
1545
|
response.text,
|
|
1546
1546
|
)
|
|
1547
1547
|
|
|
1548
|
+
def test_perms(self):
|
|
1549
|
+
user = self.login_as_standard(
|
|
1550
|
+
allowed_apps=['creme_core'], # 'reports'
|
|
1551
|
+
# exportable_models=[FakeContact],
|
|
1552
|
+
)
|
|
1553
|
+
role = user.role
|
|
1554
|
+
self.add_credentials(role=role, own=['VIEW'])
|
|
1555
|
+
|
|
1556
|
+
report = self._create_contacts_report(user=user, name='trinita')
|
|
1557
|
+
url = self._build_export_url(report)
|
|
1558
|
+
data = {'doc_type': 'csv'}
|
|
1559
|
+
|
|
1560
|
+
# App permission --
|
|
1561
|
+
response1 = self.client.get(url, data=data)
|
|
1562
|
+
self.assertContains(
|
|
1563
|
+
response1,
|
|
1564
|
+
status_code=403,
|
|
1565
|
+
text=_('You are not allowed to access to the app: {}').format(_('Reports')),
|
|
1566
|
+
html=True,
|
|
1567
|
+
)
|
|
1568
|
+
|
|
1569
|
+
# Export permission --
|
|
1570
|
+
role.allowed_apps = ['creme_core', 'reports']
|
|
1571
|
+
role.save()
|
|
1572
|
+
response2 = self.client.get(url, data=data)
|
|
1573
|
+
self.assertContains(
|
|
1574
|
+
response2,
|
|
1575
|
+
status_code=403,
|
|
1576
|
+
text=_('You are not allowed to export: {}').format('Test Contact'),
|
|
1577
|
+
html=True,
|
|
1578
|
+
)
|
|
1579
|
+
|
|
1548
1580
|
def test_report_csv__no_filter(self):
|
|
1549
|
-
user = self.
|
|
1581
|
+
user = self.login_as_standard(
|
|
1582
|
+
allowed_apps=['creme_core', 'reports'],
|
|
1583
|
+
exportable_models=[FakeContact],
|
|
1584
|
+
)
|
|
1585
|
+
self.add_credentials(role=user.role, own=['VIEW'])
|
|
1550
1586
|
|
|
1551
1587
|
self._create_persons(user=user)
|
|
1552
1588
|
self.assertEqual(3, FakeContact.objects.count())
|
creme/reports/views/export.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
################################################################################
|
|
2
2
|
# Creme is a free/open-source Customer Relationship Management software
|
|
3
|
-
# Copyright (C) 2009-
|
|
3
|
+
# Copyright (C) 2009-2026 Hybird
|
|
4
4
|
#
|
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU Affero General Public License as published by
|
|
@@ -123,6 +123,7 @@ class Export(generic.base.EntityRelatedMixin, generic.CheckedView):
|
|
|
123
123
|
|
|
124
124
|
def check_related_entity_permissions(self, entity, user):
|
|
125
125
|
user.has_perm_to_view_or_die(entity)
|
|
126
|
+
user.has_perm_to_export_or_die(entity.ct)
|
|
126
127
|
|
|
127
128
|
def get_form(self, *, report, request):
|
|
128
129
|
form = self.form_class(instance=report, user=request.user, data=request.GET)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: creme-crm
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.4
|
|
4
4
|
Summary: A CRM software using the django web framework
|
|
5
5
|
Home-page: https://www.cremecrm.com
|
|
6
6
|
Author: hybird.org
|
|
@@ -29,7 +29,7 @@ Classifier: Topic :: Office/Business
|
|
|
29
29
|
Requires-Python: >=3.10
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
License-File: LICENSE.txt
|
|
32
|
-
Requires-Dist: django~=5.2.
|
|
32
|
+
Requires-Dist: django~=5.2.10
|
|
33
33
|
Requires-Dist: redis~=6.2.0
|
|
34
34
|
Requires-Dist: Pillow~=11.3.0
|
|
35
35
|
Requires-Dist: python-dateutil~=2.8.2
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
creme/__init__.py,sha256
|
|
1
|
+
creme/__init__.py,sha256=O_PlMR2sO4yyk5-hZtInHBsTaCywaqbBxCrbXWL8Q_I,1078
|
|
2
2
|
creme/manage.py,sha256=9TahLBSSW_WbL1SZnDw0l1vM69w7MZ7P2BIfLLzquIw,968
|
|
3
3
|
creme/settings.py,sha256=vFdSBTywLk_rJehLv643xAYJuuwY8nFcaKhUfTEwq-A,62248
|
|
4
4
|
creme/urls.py,sha256=Dz1YwuwAKPpI3LmI8YdCuS3-2fZtX48xMhJajmqMe5o,2681
|
|
@@ -398,7 +398,7 @@ creme/commercial/views/salesman.py,sha256=NpGdoift5OOQl8IIPxi1E1SH8DcQyXffjs41sj
|
|
|
398
398
|
creme/commercial/views/strategy.py,sha256=uLiuQVyLJ64TfU74SxE_wrq9nW2hdlszbw_1gK4nNo4,11603
|
|
399
399
|
creme/creme_config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
400
400
|
creme/creme_config/apps.py,sha256=x-JNOK3sbL3syiV0FELoWwG5cdvl41JUp8DxGNrrJuw,5677
|
|
401
|
-
creme/creme_config/bricks.py,sha256=
|
|
401
|
+
creme/creme_config/bricks.py,sha256=X4d8V62O3QcZO1XeI_zh5cDvRHNducUkEwlE0mKtSDE,54289
|
|
402
402
|
creme/creme_config/constants.py,sha256=wsFnrmpPHXQIV_OtHU-6PZZXE6zmXzgsNe5bzj9LtTY,894
|
|
403
403
|
creme/creme_config/menu.py,sha256=I0wTo9Dv0gX9n5210UFNUNL3-Y7MdWKkNzTP7k9zLVg,10344
|
|
404
404
|
creme/creme_config/models.py,sha256=4vcd-aQDdDv1prId1rzWZ_sAhEQoIbDtlw0MAsi0CiQ,119
|
|
@@ -534,7 +534,7 @@ creme/creme_config/tests/test_button_menu.py,sha256=geq3jRGDt4APzjnN5WInw0u699Je
|
|
|
534
534
|
creme/creme_config/tests/test_creme_property_type.py,sha256=G_l-z-ODN0nfGDAUGG83XHSLwYZbBuWHx46Wj_jCRqs,6381
|
|
535
535
|
creme/creme_config/tests/test_custom_entity.py,sha256=OK4PSvxTSId4eL764l309-bkeISGDuuzo2FWrRvLdkQ,18723
|
|
536
536
|
creme/creme_config/tests/test_custom_field.py,sha256=tj0QLpZZJ50lu5hAdL9iYUQrkRer8qxjVgGMRZMA0A8,53479
|
|
537
|
-
creme/creme_config/tests/test_custom_form.py,sha256=
|
|
537
|
+
creme/creme_config/tests/test_custom_form.py,sha256=B0MlxsP9rTdiqUhZu59a1M5P0BNnAb3bPdW1mWvGO5c,76738
|
|
538
538
|
creme/creme_config/tests/test_entity_filter.py,sha256=PuQKubj-FHngpei9h36Rv-oiKzP29t9yqYhuL8DNsHo,7990
|
|
539
539
|
creme/creme_config/tests/test_fields.py,sha256=rknpgYv-cy0Jk9icsc2arngxvlQo6KGTislnbK38rV8,45769
|
|
540
540
|
creme/creme_config/tests/test_fields_config.py,sha256=QHWdHT4A2qzCYxjgboY9_4l1lHHAMyAkhO4W8x2oplI,12250
|
|
@@ -565,7 +565,7 @@ creme/creme_config/views/button_menu.py,sha256=QmoLBAgPWLQ6WQglDL62LIlZBmspRxGeR
|
|
|
565
565
|
creme/creme_config/views/creme_property_type.py,sha256=k_5HecMK5gPOnTekrYSUyTxRIhKID1zVaejO9MThPjw,2562
|
|
566
566
|
creme/creme_config/views/custom_entity.py,sha256=B6ZTJSdWVXK1002vRdPhm62Q0roS0hW6EaPZMVQPLCA,12199
|
|
567
567
|
creme/creme_config/views/custom_field.py,sha256=m2yUatZXgq8JFoYPX5QZ5ssEey41nZzUzntMESGlfFE,11284
|
|
568
|
-
creme/creme_config/views/custom_form.py,sha256=
|
|
568
|
+
creme/creme_config/views/custom_form.py,sha256=fdxOldQfOqljIORnMX-pHJqa1VU1znHuDNSpUde90Sg,15398
|
|
569
569
|
creme/creme_config/views/entity_filter.py,sha256=A81rgXhPg0-Do7VWoAjGDG6CfXqQY-maY5oaMK150sU,3575
|
|
570
570
|
creme/creme_config/views/fields_config.py,sha256=p60cnPymn7iiSpQOfOBVozgOz2cPYDkWm4KckpePrz8,3470
|
|
571
571
|
creme/creme_config/views/file_ref.py,sha256=I48H3RcEW_Zw6eK52LOeCiydKdzLMmo_1SRWMsX_K3E,1221
|
|
@@ -680,7 +680,7 @@ creme/creme_core/forms/__init__.py,sha256=DffGY4x0CW3CY0AJmZQIQ8HtQvawnbpULkHvdE
|
|
|
680
680
|
creme/creme_core/forms/base.py,sha256=9YNPWqQsOWXnj2d9vUhkUMlzeSwjpq8munS123A-s24,31857
|
|
681
681
|
creme/creme_core/forms/batch_process.py,sha256=E48GUXM33XORmF_k0Pft6gRgxeffXyq7CwTuj6sOzLU,9462
|
|
682
682
|
creme/creme_core/forms/creme_property.py,sha256=_3XO6SRIC6nrS0_NsTYeUq6uEgwcorm0bRU4aZeRJe8,3323
|
|
683
|
-
creme/creme_core/forms/enumerable.py,sha256=
|
|
683
|
+
creme/creme_core/forms/enumerable.py,sha256=7f3m7MGh5zL5kXxlteq8eSwRUtzkBRM1DhTDBGOXr-U,14540
|
|
684
684
|
creme/creme_core/forms/fields.py,sha256=P-2_72s-qZTBK5t_hmM_Hn6RRWRLDhzJGBZy0qWlgDU,76380
|
|
685
685
|
creme/creme_core/forms/header_filter.py,sha256=XmnVcCLasyNPg5ZKwBvn0JPtVOZPAPcYlU3rG3ZQWwo,25331
|
|
686
686
|
creme/creme_core/forms/job.py,sha256=tAQFFrgeAYCJ4kpCNg2gx84v3XujVb9VtcXi_RvwOwU,1105
|
|
@@ -782,7 +782,7 @@ creme/creme_core/models/deletion.py,sha256=QfkRm8b27mzJK8NOCC5rMz1A8Oy3wLCxU_rYW
|
|
|
782
782
|
creme/creme_core/models/entity.py,sha256=hY73BUAXqLYbrbpjfnpJKzyQcJBNZxoiL4TLnN9bXg4,22228
|
|
783
783
|
creme/creme_core/models/entity_filter.py,sha256=Pc6aUZSdD5IaW_d2VWJ9Y1vtSBfEaIlOcchiW8cQ5cc,41896
|
|
784
784
|
creme/creme_core/models/fields.py,sha256=PUxRq5LgxexSxOUhMifixkGrFb72dSZP64zN0537fR0,26037
|
|
785
|
-
creme/creme_core/models/fields_config.py,sha256=
|
|
785
|
+
creme/creme_core/models/fields_config.py,sha256=bax6o0XH8PAtty9J21JXuiv2h_wa8dm_bIr-2TBa1qI,16139
|
|
786
786
|
creme/creme_core/models/file_ref.py,sha256=7YFpTmWcTmWFMmP173TwjUubAl5k4DXo3OaJ0SpqfZ0,2946
|
|
787
787
|
creme/creme_core/models/header_filter.py,sha256=y_UKiGARQZ0sosd5cWYTruFVbq810Gue9UpKpx6X5rs,10986
|
|
788
788
|
creme/creme_core/models/history.py,sha256=ijN8wxU9x2njdakGPE1AhtipPSad_9nAW0PkaO_UHjw,46468
|
|
@@ -1416,14 +1416,14 @@ creme/creme_core/tests/forms/test_base.py,sha256=yEMNSA59sD2AJJF0mn8h8ZWWEqCVfB6
|
|
|
1416
1416
|
creme/creme_core/tests/forms/test_batch_process.py,sha256=UrtshBZS-NEWtN4LDpP0ZOkVUTSFG0k5eawvHck24Aw,6657
|
|
1417
1417
|
creme/creme_core/tests/forms/test_entity_cell.py,sha256=nVq_feD7iqhOAYkFlHHLI9UBQypZuUfBc8VgLRCZJHc,44861
|
|
1418
1418
|
creme/creme_core/tests/forms/test_entity_filter.py,sha256=h0uQjX2tXVlR4N1Ai-r-P6bNrtnpoSyBzWidcgsIyLA,126917
|
|
1419
|
-
creme/creme_core/tests/forms/test_enumerable.py,sha256=
|
|
1419
|
+
creme/creme_core/tests/forms/test_enumerable.py,sha256=0cXiHIt-DZ6XhGOPK2CxRr1z79x9NQUdpE1ISCyg7nI,30500
|
|
1420
1420
|
creme/creme_core/tests/forms/test_field_block_manager.py,sha256=iMI3Lmw3SC6E5IsWSKtrvvaRMw50IGzSRndcMKP0cPY,19952
|
|
1421
1421
|
creme/creme_core/tests/forms/test_fields.py,sha256=OdeabNEav7WGnRGKPaXrblxCZUZX9qula9MfSfr4kOs,67607
|
|
1422
1422
|
creme/creme_core/tests/forms/test_json_fields.py,sha256=l2QrextXbu0DSvEakaHRZtFuaJ4T8HL4w5x3GqdVmrI,107513
|
|
1423
1423
|
creme/creme_core/tests/forms/test_listview.py,sha256=rBp0jAsO_FGZQS9GLO5TV5W-etOiWVD3BdytVYdFKxs,51278
|
|
1424
1424
|
creme/creme_core/tests/forms/test_mass_import.py,sha256=9uqDy-df123Ix_EpanlCzL8w30y3l8D3_oQm8agYXDs,19192
|
|
1425
1425
|
creme/creme_core/tests/forms/test_validators.py,sha256=DIXAScNc63encmGmfQ8gc22LTBFCZiIFpKvG8En-3to,20340
|
|
1426
|
-
creme/creme_core/tests/forms/test_widgets.py,sha256=
|
|
1426
|
+
creme/creme_core/tests/forms/test_widgets.py,sha256=oQ-58ptQMLmukEa6CpJwMKnocVuJlYYMbXDHcvZG4yA,61981
|
|
1427
1427
|
creme/creme_core/tests/forms/test_workflows.py,sha256=cROnaQ_mQ5etjq0yeygNgWkHXJ92L0huNHQJ2lRayQk,46980
|
|
1428
1428
|
creme/creme_core/tests/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1429
1429
|
creme/creme_core/tests/gui/test_actions.py,sha256=ywx4S8FJclLfUXqJxCu9BP1hh9RpelPCc4qiWlj98Po,40363
|
|
@@ -2706,8 +2706,8 @@ creme/reports/forms/bulk.py,sha256=wKFywtkPCDG--o4kbu6WLIYNPn8Cyiqjie9Y3hvKQ0M,5
|
|
|
2706
2706
|
creme/reports/forms/entity_filter.py,sha256=t3FYluAudOcZRDEDoa9FS9XMnIAW23NQenLVnt4XszQ,1142
|
|
2707
2707
|
creme/reports/forms/graph.py,sha256=2Vc_YeNOtJ332DokrGT_US_TbyTsjYmnyt8nipES4MY,26076
|
|
2708
2708
|
creme/reports/forms/report.py,sha256=oV2OjZANjjCTD5nBDu5U7x2gcrBSn98dqGbMiRIQ1NM,26186
|
|
2709
|
-
creme/reports/locale/fr/LC_MESSAGES/django.mo,sha256=
|
|
2710
|
-
creme/reports/locale/fr/LC_MESSAGES/django.po,sha256=
|
|
2709
|
+
creme/reports/locale/fr/LC_MESSAGES/django.mo,sha256=zQyK7YYEntRTFMm2m3dvJJWY8_iohB7iVfws9Z6CAKI,16590
|
|
2710
|
+
creme/reports/locale/fr/LC_MESSAGES/django.po,sha256=TEJ6Q6b6poyyMfldVqreLd4hAgToUe7RUhCixScJZ9k,20689
|
|
2711
2711
|
creme/reports/locale/fr/LC_MESSAGES/djangojs.mo,sha256=7nlj4So9k-ErHv0mgk82SpHiBQkKmQmLIQnahmdhbfw,449
|
|
2712
2712
|
creme/reports/locale/fr/LC_MESSAGES/djangojs.po,sha256=eyCK6yLKRSFPciluW5Ws6DiC7L5f_PatH72jsueWdw4,1220
|
|
2713
2713
|
creme/reports/migrations/0001_initial.py,sha256=w1cZ4Wk_5e3r2hnE-2dem80HW7fj4odBSaqMc8vGzUo,10570
|
|
@@ -2727,7 +2727,7 @@ creme/reports/static/reports/js/tests/reports-actions.js,sha256=TowXAbsTbbbExIkO
|
|
|
2727
2727
|
creme/reports/static/reports/js/tests/reports-brick.js,sha256=JocsI4VWwjtGWt8NeHYHVup-MiKhVwNcjrgE_ZGkSCo,19412
|
|
2728
2728
|
creme/reports/static/reports/js/tests/reports-listview.js,sha256=VPsK_ZfGFVT920L31EGQd8CvegNJngQynbOLHL-I0Ek,9161
|
|
2729
2729
|
creme/reports/static/reports/js/tests/tube-chart.js,sha256=vkqy56Ub_TQaPT7AdGNi0Oaf8QFqLERzX6B6mpk7G-g,3260
|
|
2730
|
-
creme/reports/templates/reports/preview_report.html,sha256=
|
|
2730
|
+
creme/reports/templates/reports/preview_report.html,sha256=eawDGCNGJdkIjZhwN4-Ph3wQngQqeWypU3YnsP2ppeg,2092
|
|
2731
2731
|
creme/reports/templates/reports/view_graph.html,sha256=qwlC-eJ0A3MkJOHl8Y1Y5JO3FA49AgrWYHukalUgL8Q,731
|
|
2732
2732
|
creme/reports/templates/reports/view_report.html,sha256=9Z4NGocyzS-77PajoSlQLBQzSFOwrD1GnlIsoub97FA,53
|
|
2733
2733
|
creme/reports/templates/reports/bricks/entity-filters.html,sha256=ghr9rUFig1qAjq5_uVDEFyKtX5DNxuVuMNu0neNlQgI,1019
|
|
@@ -2736,7 +2736,7 @@ creme/reports/templates/reports/bricks/instance-bricks-info.html,sha256=iBAsw-Pr
|
|
|
2736
2736
|
creme/reports/templates/reports/bricks/preview.html,sha256=cRdq80WTwq75eS0YwJ9WQJMQAeqWMWzVO1gaRVgnDN0,1230
|
|
2737
2737
|
creme/reports/templates/reports/bricks/report-chart-list.html,sha256=sYHI7BLRdl3yBWc5eYXvdOj7ngpn5d2Qp9L7mxl2c34,8115
|
|
2738
2738
|
creme/reports/templates/reports/bricks/report-chart.html,sha256=sJI8xDi_MNuNUwG4fg_7Hg27kjuBGX_b2AESLiXDWto,4527
|
|
2739
|
-
creme/reports/templates/reports/bricks/report-hat-bar.html,sha256=
|
|
2739
|
+
creme/reports/templates/reports/bricks/report-hat-bar.html,sha256=K0x2Z6NOnomV8eTPRW6lR5yEjsQbbXxvP394P7F8eAg,949
|
|
2740
2740
|
creme/reports/templates/reports/detail/entity-filter.html,sha256=9Co16RLUYRlSuA21Y2Ep-u4SrGKMv7pVK5LOv1pZKrQ,435
|
|
2741
2741
|
creme/reports/templates/reports/forms/report-export-filter.html,sha256=QjPyjkvHqS7yIL9h3WwboXOPYACbkB8MHovAowKX4xw,639
|
|
2742
2742
|
creme/reports/templates/reports/forms/widgets/report-hands/custom-aggregates.html,sha256=ejTaJdmGcX5TFEWdT3BjXFslZC0QHfwdw4m5fjN6Vi4,514
|
|
@@ -2757,7 +2757,7 @@ creme/reports/tests/test_entity_filter.py,sha256=Bm2WkW5CeeDAoQh2IOFfoG2K6vdbycK
|
|
|
2757
2757
|
creme/reports/tests/test_forms.py,sha256=d7Sz3UfsdFW5GspuABA5DNk_Hl5V3IjW6H32Vq713gc,81698
|
|
2758
2758
|
creme/reports/tests/test_graph.py,sha256=N2896eLl6baw0lG22LmOCWoxrv0Hs50OgwRgGRcTKnc,133541
|
|
2759
2759
|
creme/reports/tests/test_registries.py,sha256=_BtYECcKIMxAzFZRxeNBD_lWCgY0xRToVEc5d6HOzg0,4992
|
|
2760
|
-
creme/reports/tests/test_report.py,sha256=
|
|
2760
|
+
creme/reports/tests/test_report.py,sha256=BAfyEUQgG1Rl2dulsiwqCr11-pcg03_dDblxG_E9mJE,143971
|
|
2761
2761
|
creme/reports/tests/test_templatetags.py,sha256=Sr0eNuqB2zSwcFZKIj-vEhOXKwMznL1VxDYhv0a6w-Q,3395
|
|
2762
2762
|
creme/reports/tests/test_utils.py,sha256=3ImrZueMK-xqgXHjlui-zMvQjMQFcwWcX7E27aI6RHc,2512
|
|
2763
2763
|
creme/reports/tests/test_views.py,sha256=v_PlsSXSMc9RkhWxXY9-s4aIWHoIQSgLVkWWm0leF2U,6333
|
|
@@ -2771,7 +2771,7 @@ creme/reports/tests/core/graph/test_hand.py,sha256=LJb6nVwWVK5-49DvBjNnHQ6I6xL1s
|
|
|
2771
2771
|
creme/reports/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2772
2772
|
creme/reports/views/bricks.py,sha256=MdeUZKFAJaRmb_Sk-Py-ojh1fUgMw6fCjEeJwca8x3Q,2442
|
|
2773
2773
|
creme/reports/views/entity_filter.py,sha256=4cF2stqj-fQuFs2lvrGUyCeVc5d8Lb5Ua6J6zMT1fYE,2514
|
|
2774
|
-
creme/reports/views/export.py,sha256=
|
|
2774
|
+
creme/reports/views/export.py,sha256=eCM29j8nFEXxc-zGgLnWjW-ZJhP7gcD4yzQAQ7xABDQ,5757
|
|
2775
2775
|
creme/reports/views/graph.py,sha256=0VUTaTAJUOx0LXlPg5mBO2kHOFyL_x9RyiZmNUbpcDI,5581
|
|
2776
2776
|
creme/reports/views/report.py,sha256=UoZHXekGWWb77Oj1g8TsmXpVf6vmgQY7J6cMjBkNNr4,7853
|
|
2777
2777
|
creme/sketch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -3822,7 +3822,7 @@ creme/vcfs/vcf_lib/utils.py,sha256=rofX2grUVZLg1qSYrvVLQe832rX9QDDqjqSfq9_rpnA,2
|
|
|
3822
3822
|
creme/vcfs/vcf_lib/vcard.py,sha256=EIDdegf8HC5f4j19tfJYQ1NKc_-NZO8NaYinpVwj7vQ,8275
|
|
3823
3823
|
creme/vcfs/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3824
3824
|
creme/vcfs/views/vcf.py,sha256=7rsRCL7U0cgwtYghN6yAAbNN_e5lJVGrLH5IpSOIPYI,3795
|
|
3825
|
-
creme_crm-2.7.
|
|
3825
|
+
creme_crm-2.7.4.dist-info/licenses/LICENSE.txt,sha256=fvS1_rSUtxH8CO9sMpw9BQFU3nLMK6ssGpyZU6ZVPMU,1130
|
|
3826
3826
|
mediagenerator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3827
3827
|
mediagenerator/api.py,sha256=58FqOcH2NCJVdtKN_MxyW3xydWAYPBexTDa2LQTaMsY,1883
|
|
3828
3828
|
mediagenerator/base.py,sha256=2zr8DCnL48UgVM1M9LILuHTgT_xvKLMSwVnzGa47zCc,1003
|
|
@@ -3853,8 +3853,8 @@ mediagenerator/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
|
|
|
3853
3853
|
mediagenerator/management/commands/generatemedia.py,sha256=3-uIk3h83F16n2z7vG_xBteWiq7JWoB7d0vWSxVn-po,328
|
|
3854
3854
|
mediagenerator/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3855
3855
|
mediagenerator/templatetags/media.py,sha256=6EeohgP8srqzNRxgGr47BARO6Vx4AMn_dQuHwEQnnHE,1495
|
|
3856
|
-
creme_crm-2.7.
|
|
3857
|
-
creme_crm-2.7.
|
|
3858
|
-
creme_crm-2.7.
|
|
3859
|
-
creme_crm-2.7.
|
|
3860
|
-
creme_crm-2.7.
|
|
3856
|
+
creme_crm-2.7.4.dist-info/METADATA,sha256=PW3EMhddVcgAKsxeoyWs2UpfbK69YCSRgJdEaWEaWTY,12233
|
|
3857
|
+
creme_crm-2.7.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
3858
|
+
creme_crm-2.7.4.dist-info/entry_points.txt,sha256=GWm5VHgyz1DROd4UbhrelZ8d581uQNOtbjPz2TWfi_A,47
|
|
3859
|
+
creme_crm-2.7.4.dist-info/top_level.txt,sha256=y_WAe0QGma0mhzRFEOIVJsB-xJrvhHV6MEk862EMweA,21
|
|
3860
|
+
creme_crm-2.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|