class RelatedBaseCreation(generic.AddingInstanceToEntityPopup): model = Base permissions: Union[str, Sequence[str], None] = 'billing' # Need creation perm too initial_status = 1 entity_id_url_kwarg = 'target_id' entity_classes = [ persons.get_organisation_model(), persons.get_contact_model(), ] entity_form_kwarg = None def get_initial(self): initial = super().get_initial() initial['status'] = self.initial_status target = self.get_related_entity() # initial['target'] = target # DEPRECATED initial[base_forms.BillingTargetSubCell( model=self.model).into_cell().key] = target return initial def get_success_url(self): if bool_from_str_extended(self.request.GET.get('redirection', '0')): return self.object.get_absolute_url() return super().get_success_url()
def test_populate(self): for pk, name in BASE_STATUS: try: status = Status.objects.get(pk=pk) except Status.DoesNotExist: self.fail("Bad populate: status with pk={} ({}) doesn't exist". format(pk, name)) else: self.assertEqual(name, status.name) self.assertFalse(status.is_custom) self.assertIsNotNone(status.order) self.assertGreaterEqual(Priority.objects.count(), 2) self.assertGreaterEqual(Criticity.objects.count(), 2) get_ct = ContentType.objects.get_for_model hf_filter = HeaderFilter.objects.filter ticket_ct = get_ct(Ticket) self.assertTrue(hf_filter(entity_type=ticket_ct).exists()) self.assertTrue(hf_filter(entity_type=get_ct(TicketTemplate)).exists()) # Contribution to activities rtype = self.get_object_or_fail(RelationType, pk=REL_SUB_ACTIVITY_SUBJECT) self.assertTrue(rtype.subject_ctypes.filter(id=ticket_ct.id).exists()) self.assertTrue( rtype.subject_ctypes.filter( id=get_ct(get_contact_model()).id).exists()) self.assertTrue( rtype.symmetric_type.object_ctypes.filter( id=ticket_ct.id).exists())
class ResourceCreateForm(CremeModelForm): contact = CreatorEntityField( label=_('Contact to be assigned to this task'), model=get_contact_model(), ) class Meta(CremeModelForm.Meta): model = Resource def __init__(self, task, *args, **kwargs): super().__init__(*args, **kwargs) instance = self.instance instance.task = task other_resources = task.resources_set.all() if instance.pk: other_resources = other_resources.exclude(pk=instance.pk) contact_f = self.fields['contact'] contact_f.q_filter = ~Q(pk__in=[ *other_resources.values_list('linked_contact_id', flat=True) ], ) # The creation view cannot create a Contact already related to Resource (& so, excluded). contact_f.force_creation = True # TODO: in constructor ? def save(self, *args, **kwargs): self.instance.linked_contact = self.cleaned_data['contact'] return super().save(*args, **kwargs)
def test_hat_card02(self): "Too many contacts to display." user = self.login() brick_cls = bricks.OpportunityCardHatBrick brick_cls.displayed_contacts_number = 1 opp = self._create_opportunity_n_organisations(name='Opp#1')[0] create_contact = partial(get_contact_model().objects.create, user=user) contact01 = create_contact(first_name='Revy', last_name='??') contact02 = create_contact(first_name='Rock', last_name='??') create_rel = partial( Relation.objects.create, user=user, subject_entity=opp, type_id=constants.REL_OBJ_LINKED_CONTACT, ) create_rel(object_entity=contact01) create_rel(object_entity=contact02) response = self.assertGET200(opp.get_absolute_url()) tree = self.get_html_tree(response.content) brick_node = self.get_brick_node(tree, brick_cls.id_) self.assertInstanceLink(brick_node, contact01) self.assertNoInstanceLink(brick_node, contact02)
def test_field_printers01(self): "Field printer with FK on Image." user = self.login() image = self._create_image() summary = image.get_entity_summary(user) self.assertHTMLEqual( '<img class="entity-summary" src="{url}" alt="{name}" title="{name}"/>' .format( # url=image.get_dl_url(), url=image.get_download_absolute_url(), name=image.title, ), summary, ) casca = get_contact_model().objects.create( user=user, image=image, first_name='Casca', last_name='Mylove', ) self.assertHTMLEqual( f'''<a onclick="creme.dialogs.image('{image.get_download_absolute_url()}').open();">''' f'''{summary}''' f'''</a>''', field_printers_registry.get_html_field_value(casca, 'image', user)) self.assertEqual( str(casca.image), field_printers_registry.get_csv_field_value(casca, 'image', user))
def _get_contact_n_factory(locale): from creme.persons import get_contact_model Contact = get_contact_model() # build_email_domain = partial(factory.Faker('free_email_domain', locale=locale).generate, {}) build_email_domain = partial( factory.Faker('free_email_domain', locale=locale).evaluate, step=None, ) def build_email(contact): # return '{0}.{1}@{2}'.format(contact.first_name, contact.last_name, build_email_domain()).lower() domain = build_email_domain(contact, extra={'locale': locale}) return '{}.{}@{}'.format(contact.first_name, contact.last_name, domain).lower() class ContactFactory(DjangoModelFactory): class Meta: model = Contact user = factory.LazyAttribute(get_user) first_name = factory.Faker('first_name', locale=locale) last_name = factory.Faker('last_name', locale=locale) email = factory.LazyAttribute(or_blank(build_email)) return Contact, ContactFactory
def test_linked_contacts(self, brick_cls, rtype_id): brick_cls.page_size = max(5, settings.BLOCK_SIZE) user = self.login() opp01, target, emitter = self._create_opportunity_n_organisations(name='Opp#1') opp02 = Opportunity.objects.create( user=user, name='Opp#2', sales_phase=opp01.sales_phase, emitter=emitter, target=target, ) create_contact = partial(get_contact_model().objects.create, user=user) contact01 = create_contact(first_name='Revy', last_name='??') contact02 = create_contact(first_name='Rock', last_name='??') contact03 = create_contact(first_name='Benny', last_name='??') contact04 = create_contact(first_name='Dutch', last_name='??') contact05 = create_contact(first_name='Balalaika', last_name='??', is_deleted=True) create_rel = partial(Relation.objects.create, user=user, type_id=rtype_id) create_rel(subject_entity=opp01, object_entity=contact01) create_rel(subject_entity=opp01, object_entity=contact02) create_rel(subject_entity=opp02, object_entity=contact04) create_rel(subject_entity=opp01, object_entity=contact05) response = self.assertGET200(opp01.get_absolute_url()) tree = self.get_html_tree(response.content) brick_node = self.get_brick_node(tree, brick_cls.id_) self.assertInstanceLink(brick_node, contact01) self.assertInstanceLink(brick_node, contact02) self.assertNoInstanceLink(brick_node, contact03) self.assertNoInstanceLink(brick_node, contact04) self.assertNoInstanceLink(brick_node, contact05)
def abstract_add_related_activity(request, entity_id, form=act_forms.RelatedActivityCreateForm): warnings.warn( 'activities.views.activity.abstract_add_related_activity() is deprecated ; ' 'use the class-based view RelatedActivityCreation instead.', DeprecationWarning) act_type_id = request.GET.get('activity_type') entity = get_object_or_404(CremeEntity, pk=entity_id).get_real_entity() if act_type_id: get_object_or_404(ActivityType, pk=act_type_id) request.user.has_perm_to_link_or_die(entity) if isinstance(entity, get_contact_model()): rtype_id = constants.REL_SUB_PART_2_ACTIVITY else: rtype = RelationType.objects.get(pk=constants.REL_SUB_ACTIVITY_SUBJECT) if rtype.is_compatible(entity.entity_type_id): rtype_id = constants.REL_SUB_ACTIVITY_SUBJECT else: rtype_id = constants.REL_SUB_LINKED_2_ACTIVITY # Not custom, & all ContentTypes should be accepted return _add_activity( request, form, related_entity=entity, relation_type_id=rtype_id, type_id=act_type_id, )
def _get_contact_n_factory(locale): from creme.persons import get_contact_model Contact = get_contact_model() build_email_domain = partial( factory.Faker('free_email_domain', locale=locale).generate, {}) def build_email(contact): return '{0}.{1}@{2}'.format(contact.first_name, contact.last_name, build_email_domain()).lower() class ContactFactory(DjangoModelFactory): class Meta: model = Contact user = factory.LazyAttribute(get_user) first_name = factory.Faker('first_name', locale=locale) last_name = factory.Faker('last_name', locale=locale) # email = factory.LazyAttribute(or_None(build_email)) email = factory.LazyAttribute(or_blank(build_email)) # email = factory.Sequence(lambda n: 'person{0}@example.com'.format(n)) # author = factory.SubFactory(UserFactory) return Contact, ContactFactory
class RelatedBaseCreation(generic.AddingInstanceToEntityPopup): model = Base # form_class = base_forms.BaseCreateForm template_name = 'billing/form/add-popup.html' permissions = 'billing' # Need creation perm too initial_status = 1 entity_id_url_kwarg = 'target_id' entity_classes = [ persons.get_organisation_model(), persons.get_contact_model(), ] entity_form_kwarg = None def get_initial(self): initial = super().get_initial() initial['status'] = self.initial_status initial['target'] = self.get_related_entity() return initial def get_success_url(self): if bool_from_str_extended(self.request.GET.get('redirection', '0')): return self.object.get_absolute_url() return super().get_success_url()
def test_field_printers01(self): "Field printer with FK on Image" user = self.login() image = self._create_image() summary = image.get_entity_summary(user) self.assertHTMLEqual( '<img class="entity-summary" src="%(url)s" alt="%(name)s" title="%(name)s"/>' % { 'url': image.get_dl_url(), 'name': image.title, }, summary) casca = get_contact_model().objects.create( user=user, image=image, first_name='Casca', last_name='Mylove', ) self.assertHTMLEqual( '''<a onclick="creme.dialogs.image('{}').open();">{}</a>'''.format( image.get_dl_url(), summary, ), field_printers_registry.get_html_field_value(casca, 'image', user)) self.assertEqual( str(casca.image), field_printers_registry.get_csv_field_value(casca, 'image', user))
class AddressesInformation(BaseAddressesInformation): entity_classes = [ persons.get_contact_model(), persons.get_organisation_model(), ] def get_info(self, request): entity_filter = self.get_efilter() user = request.user def owner_groups(): if entity_filter: # TODO: assert in self.entity_classes model = entity_filter.entity_type.model_class() yield entity_filter.filter(model.objects.all(), user=user) else: for model in self.entity_classes: yield model.objects.all() addresses = [ address for owners in owner_groups() for address in addresses_from_persons(owners, user) ] GeoAddress.populate_geoaddresses(addresses) return { 'addresses': [address_as_dict(address) for address in addresses] }
def register_menu(self, creme_menu): # from django.conf import settings from django.urls import reverse_lazy as reverse from creme.persons import get_contact_model Act = self.Act Pattern = self.Pattern Strategy = self.Strategy # if settings.OLD_MENU: # from creme.creme_core.auth import build_creation_perm as cperm # # reg_item = creme_menu.register_app('commercial', '/commercial/').register_item # reg_item(reverse('commercial__portal'), _(u'Portal of commercial strategy'), 'commercial') # reg_item(reverse('commercial__list_segments'), _(u'All market segments'), 'commercial') # reg_item(reverse('commercial__list_acts'), _(u'All commercial actions'), 'commercial') # reg_item(reverse('commercial__create_act'), Act.creation_label, cperm(Act)) # reg_item(reverse('commercial__list_strategies'), _(u'All strategies'), 'commercial') # reg_item(reverse('commercial__create_strategy'), Strategy.creation_label, cperm(Strategy)) # reg_item(reverse('commercial__list_patterns'), _(u'All objective patterns'), 'commercial') # reg_item(reverse('commercial__create_pattern'), Pattern.creation_label, cperm(Pattern)) # # reg_item = creme_menu.get_app_item('persons').register_item # reg_item(reverse('commercial__list_salesmen'), _(u'All salesmen'), 'persons') # reg_item(reverse('commercial__create_salesman'), _(u'Add a salesman'), cperm(get_contact_model())) # else: from .models import MarketSegment URLItem = creme_menu.URLItem features = creme_menu.get('features') features.get('persons-directory') \ .add(URLItem('commercial-salesmen', url=reverse('commercial__list_salesmen'), label=_(u'Salesmen'), perm='persons', ), priority=100 ) features.get_or_create(creme_menu.ContainerItem, 'opportunities-commercial', priority=30, defaults={'label': _(u'Commercial')}, ) \ .add(URLItem.list_view('commercial-acts', model=Act), priority=50) \ .add(URLItem.list_view('commercial-strategies', model=Strategy), priority=55) \ .add(URLItem.list_view('commercial-segments', model=MarketSegment), priority=60) \ .add(URLItem.list_view('commercial-patterns', model=Pattern), priority=70) creation = creme_menu.get('creation') creation.get('main_entities').add(URLItem.creation_view( 'commercial-create_act', model=Act), priority=100) any_forms = creation.get('any_forms') any_forms.get_or_create_group('persons-directory', _(u'Directory'), priority=10) \ .add_link('create_salesman', model=get_contact_model(), label=_(u'Salesman'), url=reverse('commercial__create_salesman'), priority=10, ) any_forms.get_or_create_group('opportunities-commercial', _(u'Commercial'), priority=15) \ .add_link('commercial-create_act', Act, priority=50) \ .add_link('commercial-create_strategy', Strategy, priority=55) \ .add_link('commercial-create_pattern', Pattern, priority=60)
class PersonPollRepliesBrick(_RelatedRepliesBrick): id_ = _RelatedRepliesBrick.generate_id('polls', 'person_replies') template_name = 'polls/bricks/person-preplies.html' target_ctypes = (persons.get_contact_model(), persons.get_organisation_model()) def _get_replies(self, pk): return PollReply.objects.filter(person=pk)
def register_fields_config(self, fields_config_registry): from creme import persons fields_config_registry.register_needed_fields( 'sms', persons.get_contact_model(), 'mobile', )
def test_field_printers02(self): "Field printer with FK on Image + credentials." Contact = get_contact_model() user = self.login(allowed_apps=['creme_core', 'persons', 'documents']) other_user = self.other_user self.role.exportable_ctypes.set( [ContentType.objects.get_for_model(Contact)]) SetCredentials.objects.create( role=self.role, value=(EntityCredentials.VIEW | EntityCredentials.CHANGE | EntityCredentials.DELETE | EntityCredentials.LINK | EntityCredentials.UNLINK), set_type=SetCredentials.ESET_OWN, ) create_img = self._create_image casca_face = create_img(title='Casca face', user=user, description="Casca's selfie") judo_face = create_img(title='Judo face', user=other_user, description="Judo's selfie") self.assertTrue(other_user.has_perm_to_view(judo_face)) self.assertFalse(other_user.has_perm_to_view(casca_face)) create_contact = partial(Contact.objects.create, user=other_user) casca = create_contact(first_name='Casca', last_name='Mylove', image=casca_face) judo = create_contact(first_name='Judo', last_name='Doe', image=judo_face) get_html_val = field_printers_registry.get_html_field_value url = judo_face.get_download_absolute_url() self.assertHTMLEqual( f'''<a onclick="creme.dialogs.image('{url}').open();"> {judo_face.get_entity_summary(other_user)} </a> ''', get_html_val(judo, 'image', other_user)) self.assertEqual( # '<p>Judo's selfie</p>', '<p>Judo's selfie</p>', get_html_val(judo, 'image__description', other_user), ) HIDDEN_VALUE = settings.HIDDEN_VALUE self.assertEqual(HIDDEN_VALUE, get_html_val(casca, 'image', other_user)) self.assertEqual(HIDDEN_VALUE, get_html_val(casca, 'image__description', other_user))
def register_fields_config(self, fields_config_registry): from creme import persons fields_config_registry.register_needed_fields( 'cti', persons.get_contact_model(), 'phone', 'mobile', ).register_needed_fields( 'cti', persons.get_organisation_model(), 'phone', )
def populate(self): already_populated = SettingValue.objects.filter( key_id=setting_keys.NEIGHBOURHOOD_DISTANCE.id).exists() create_skey = SettingValue.objects.get_or_create create_skey( key_id=setting_keys.NEIGHBOURHOOD_DISTANCE.id, defaults={'value': constants.DEFAULT_SEPARATING_NEIGHBOURS}) create_skey(key_id=setting_keys.GOOGLE_API_KEY.id, defaults={'value': ''}) if not already_populated: if self.verbosity: self.stdout.write('\n ', ending='') self.stdout.flush() GeolocationCommand().import_town_all(verbosity=self.verbosity) if not already_populated: Contact = persons.get_contact_model() Organisation = persons.get_organisation_model() create_bdl = BrickDetailviewLocation.create_if_needed create_bdl(brick_id=bricks.GoogleDetailMapBrick.id_, order=70, zone=BrickDetailviewLocation.LEFT, model=Organisation) create_bdl(brick_id=bricks.GoogleDetailMapBrick.id_, order=70, zone=BrickDetailviewLocation.LEFT, model=Contact) create_bdl(brick_id=bricks.GoogleNeighboursMapBrick.id_, order=600, zone=BrickDetailviewLocation.BOTTOM, model=Organisation) create_bdl(brick_id=bricks.GoogleNeighboursMapBrick.id_, order=600, zone=BrickDetailviewLocation.BOTTOM, model=Contact) BrickMypageLocation.objects.create( brick_id=bricks.GoogleFilteredMapBrick.id_, order=20, user=None) # Add this bloc only if the root user exists (creme_core populated) root = get_user_model().objects.filter(pk=1).first() if root: logger.info( 'Creme core is installed => the block PersonsFilterMap can be activated' ) BrickMypageLocation.objects.create( brick_id=bricks.GoogleFilteredMapBrick.id_, order=8, user=root)
def formfield(self, instance, user, **kwargs): field = GenericEntityField( label=self.verbose_name, models=[get_organisation_model(), get_contact_model()], user=user, ) if instance.pk: field.initial = instance.target return field
def all_apps_ready(self): from creme import persons self.Contact = persons.get_contact_model() self.Organisation = persons.get_organisation_model() self.Address = persons.get_address_model() super().all_apps_ready() self.hook_user() self.hook_user_form() from . import signals
def register_fields_config(self, fields_config_registry): from creme import persons fields_config_registry.register_needed_fields( 'emails', persons.get_contact_model(), 'email', ).register_needed_fields( 'emails', persons.get_organisation_model(), 'email', )
def get_responsibles(self): warnings.warn('AbstractOpportunity.get_responsibles() is deprecated.', DeprecationWarning) from creme.persons import get_contact_model return get_contact_model()\ .objects\ .filter(is_deleted=False, relations__object_entity=self.id, relations__type=constants.REL_SUB_RESPONSIBLE, )
def get_rtype_id(self): entity = self.related_entity if isinstance(entity, get_contact_model()): rtype_id = constants.REL_SUB_PART_2_ACTIVITY else: rtype = RelationType.objects.get( pk=constants.REL_SUB_ACTIVITY_SUBJECT) rtype_id = constants.REL_SUB_ACTIVITY_SUBJECT \ if rtype.is_compatible(entity) else \ constants.REL_SUB_LINKED_2_ACTIVITY # Not custom, & all ContentTypes should be accepted return rtype_id
class ContactsBrick(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('sms', 'contacts') verbose_name = _('Contacts recipients') dependencies = (get_contact_model(), ) template_name = 'sms/bricks/contacts.html' target_ctypes = (MessagingList, ) def _get_queryset(self, entity): # NB: entity=mlist return entity.contacts.all() def _update_context(self, context): # TODO: in a templatetag ?? context['field_hidden'] = context['fields_configs'].get_4_model( get_contact_model(), ).is_fieldname_hidden('mobile')
def register_menu(self, creme_menu): from django.urls import reverse_lazy as reverse from creme.creme_core.auth import build_creation_perm from creme.persons import get_contact_model creme_menu.get('features', 'persons-directory') \ .add(creme_menu.URLItem('vcfs-import', url=reverse('vcfs__import'), label=_('Import from a VCF file'), perm=build_creation_perm(get_contact_model()), ), priority=200, )
def all_apps_ready(self): from creme import persons self.Contact = persons.get_contact_model() self.Organisation = persons.get_organisation_model() self.Address = persons.get_address_model() super().all_apps_ready() self.hook_user() self.hook_user_form() from . import signals # NOQA if apps.is_installed('creme.reports'): self.register_reports_graph_fetchers()
def detailview_display(self, context): btc = self.get_template_context( context, UserSynchronizationHistory.objects.filter( user=context['user']).select_related('entity_ct'), history_type_verbose=USER_HISTORY_TYPE_VERBOSE, history_where_verbose=USER_HISTORY_WHERE_VERBOSE, contact_klass=get_contact_model( ), # TODO: use {% ctype_for_swappable ... %} instead ) history = btc['page'].object_list UserSynchronizationHistory.populate_entities(history) return self._render(btc)
def test_current_app_entry03(self): "Not allowed" user = self.login(is_superuser=False) contact = get_contact_model().objects.create(user=user, last_name='Doe') self.assertHTMLEqual( '<span class="ui-creme-navigation-text-entry forbidden">{}</span>'.format( escape(_('Configuration of «{app}»').format( app=_('Accounts and Contacts'), )), ), CurrentAppConfigEntry().render({ 'user': user, 'object': contact, }), )
def register_function_fields(self, function_field_registry): from creme import persons from . import function_fields as ffields register = function_field_registry.register register(self.TemplateBase, ffields.TemplateBaseVerboseStatusField) for model in (persons.get_organisation_model(), persons.get_contact_model()): register( model, ffields._TotalPendingPayment, ffields._TotalWonQuoteThisYear, ffields._TotalWonQuoteLastYear, )
class ProjectCreateForm(ProjectEditForm): responsibles = MultiCreatorEntityField(label=_('Project leaders'), model=get_contact_model()) def _get_relations_to_create(self): instance = self.instance build_relation = partial( Relation, user=instance.user, type_id=REL_OBJ_PROJECT_MANAGER, subject_entity=instance, ) return super()._get_relations_to_create().extend( build_relation(object_entity=contact) for contact in self.cleaned_data['responsibles'])