def post_save_relation_opp_subject_activity(sender, instance, **kwargs): if instance.type_id == REL_OBJ_ACTIVITY_SUBJECT: object_entity = instance.object_entity get_ct = ContentType.objects.get_for_model if object_entity.entity_type == get_ct(get_opportunity_model()): # relations = Relation.objects.filter(subject_entity=object_entity, # type=REL_SUB_COMPLETE_GOAL, # object_entity__entity_type=get_ct(get_act_model()), # ) # # create_relation = partial(Relation.objects.create, # subject_entity=instance.subject_entity, # type_id=REL_SUB_COMPLETE_GOAL, # user=instance.user, # ) # # for relation in relations: # create_relation(object_entity=relation.object_entity) activity = instance.subject_entity user = instance.user Relation.objects.safe_multi_save( Relation( subject_entity=activity, type_id=REL_SUB_COMPLETE_GOAL, object_entity=relation.object_entity, user=user, ) for relation in Relation.objects.filter( subject_entity_id=object_entity.id, type=REL_SUB_COMPLETE_GOAL, object_entity__entity_type=get_ct(get_act_model()), ))
def get_related_opportunities(self): relopps = self._related_opportunities if relopps is None: relopps = list(get_opportunity_model().objects.filter( is_deleted=False, relations__type=REL_SUB_COMPLETE_GOAL, relations__object_entity=self.id, )) self._related_opportunities = relopps return relopps
def _execute(self, job): from creme import persons from creme.opportunities import get_opportunity_model from creme.opportunities.constants import REL_SUB_TARGETS from .models import CommercialApproach Organisation = persons.get_organisation_model() Contact = persons.get_contact_model() Opportunity = get_opportunity_model() emails = [] get_ct = ContentType.objects.get_for_model ct_orga = get_ct(Organisation) ct_contact = get_ct(Contact) ct_opp = get_ct(Opportunity) now_value = now() managed_orga_ids = [ *Organisation.objects.filter(is_managed=True).values_list( 'id', flat=True), ] opp_filter = Opportunity.objects.filter EMAIL_SENDER = settings.EMAIL_SENDER for rtype, delay in self.list_target_orga: com_apps_filter = CommercialApproach.objects.filter( creation_date__gt=now_value - timedelta(days=delay), ).filter # TODO: are 'values_list' real optimizations here ?? # ==> remove them when CommercialApproach use real ForeignKey for orga in Organisation.objects.filter( is_managed=False, relations__type=rtype, relations__object_entity__in=managed_orga_ids, ): if com_apps_filter(entity_content_type=ct_orga, entity_id=orga.id).exists(): continue if com_apps_filter( entity_content_type=ct_contact, entity_id__in=orga.get_managers().values_list( 'id', flat=True), ).exists(): continue if com_apps_filter( entity_content_type=ct_contact, entity_id__in=orga.get_employees().values_list( 'id', flat=True), ).exists(): continue if com_apps_filter( entity_content_type=ct_opp, entity_id__in=opp_filter( relations__type=REL_SUB_TARGETS, relations__object_entity=orga, ).values_list('id', flat=True), ).exists(): continue emails.append( EmailMessage( gettext( '[CremeCRM] The organisation «{}» seems neglected' ).format(orga), gettext( "It seems you haven't created a commercial approach for " "the organisation «{orga}» since {delay} days."). format( orga=orga, delay=delay, ), EMAIL_SENDER, [orga.user.email], )) # TODO: factorise jobs which send emails if emails: try: with get_connection() as connection: connection.send_messages(emails) except Exception as e: JobResult.objects.create( job=job, messages=[ gettext('An error has occurred while sending emails'), gettext('Original error: {}').format(e), ], )
from creme import commercial from .constants import REL_OBJ_COMPLETE_GOAL from .models import ( CommercialApproach, MarketSegment, MarketSegmentDescription, CommercialAsset, MarketSegmentCharm, ActObjective, ActObjectivePatternComponent, ) from .setting_keys import orga_approaches_key get_ct = ContentType.objects.get_for_model Opportunity = get_opportunity_model() Act = commercial.get_act_model() ActObjectivePattern = commercial.get_pattern_model() Strategy = commercial.get_strategy_model() class ApproachesBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('commercial', 'approaches') dependencies = (CommercialApproach, ) # order_by = 'title' order_by = '-creation_date' verbose_name = _('Commercial approaches') template_name = 'commercial/bricks/approaches.html' # TODO: factorise with assistants blocks (CremeEntity method ??) @staticmethod
def populate(self): already_populated = RelationType.objects.filter( pk=constants.REL_SUB_IS_INVITED_TO, ).exists() Event = get_event_model() Contact = get_contact_model() Opportunity = get_opportunity_model() create_rtype = RelationType.create create_rtype( (constants.REL_SUB_IS_INVITED_TO, _('is invited to the event'), [Contact]), (constants.REL_OBJ_IS_INVITED_TO, _('has invited'), [Event]), is_internal=True, ) create_rtype( ( constants.REL_SUB_ACCEPTED_INVITATION, _('accepted the invitation to the event'), [Contact], ), ( constants.REL_OBJ_ACCEPTED_INVITATION, _('prepares to receive'), [Event], ), is_internal=True, ) create_rtype( ( constants.REL_SUB_REFUSED_INVITATION, _('refused the invitation to the event'), [Contact], ), ( constants.REL_OBJ_REFUSED_INVITATION, _('do not prepare to receive any more'), [Event], ), is_internal=True, ) create_rtype( (constants.REL_SUB_CAME_EVENT, _('came to the event'), [Contact]), (constants.REL_OBJ_CAME_EVENT, _('received'), [Event]), is_internal=True, ) create_rtype( (constants.REL_SUB_NOT_CAME_EVENT, _('did not come to the event'), [Contact]), (constants.REL_OBJ_NOT_CAME_EVENT, _('did not receive'), [Event]), is_internal=True, ) create_rtype( ( constants.REL_SUB_GEN_BY_EVENT, _('generated by the event'), [Opportunity], ), ( constants.REL_OBJ_GEN_BY_EVENT, _('(event) has generated the opportunity'), [Event], ), is_internal=True, ) # --------------------------- HeaderFilter.objects.create_if_needed( pk=constants.DEFAULT_HFILTER_EVENT, name=_('Event view'), model=Event, cells_desc=[ (EntityCellRegularField, { 'name': 'name' }), (EntityCellRegularField, { 'name': 'type' }), (EntityCellRegularField, { 'name': 'start_date' }), (EntityCellRegularField, { 'name': 'end_date' }), ], ) # --------------------------- base_groups_desc = [ { 'name': _('General information'), 'layout': LAYOUT_DUAL_FIRST, 'cells': [ (EntityCellRegularField, { 'name': 'user' }), (EntityCellRegularField, { 'name': 'name' }), (EntityCellRegularField, { 'name': 'type' }), (EntityCellRegularField, { 'name': 'place' }), (EntityCellRegularField, { 'name': 'start_date' }), (EntityCellRegularField, { 'name': 'end_date' }), (EntityCellRegularField, { 'name': 'budget' }), (EntityCellRegularField, { 'name': 'final_cost' }), ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial.REMAINING_REGULARFIELDS }, ), ], }, { 'name': _('Description'), 'layout': LAYOUT_DUAL_SECOND, 'cells': [ (EntityCellRegularField, { 'name': 'description' }), ], }, { 'name': _('Custom fields'), 'layout': LAYOUT_DUAL_SECOND, 'cells': [ ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial.REMAINING_CUSTOMFIELDS }, ), ], }, ] CustomFormConfigItem.objects.create_if_needed( descriptor=custom_forms.EVENT_CREATION_CFORM, groups_desc=[ *base_groups_desc, { 'name': _('Properties'), 'cells': [ ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial.CREME_PROPERTIES }, ), ], }, { 'name': _('Relationships'), 'cells': [ ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial.RELATIONS }, ), ], }, ], ) CustomFormConfigItem.objects.create_if_needed( descriptor=custom_forms.EVENT_EDITION_CFORM, groups_desc=base_groups_desc, ) # --------------------------- SearchConfigItem.objects.create_if_needed( Event, ['name', 'description', 'type__name'], ) # --------------------------- # TODO: move to "not already_populated" section in creme2.4 if not MenuConfigItem.objects.filter( entry_id__startswith='events-').exists(): container = MenuConfigItem.objects.get_or_create( entry_id=ContainerEntry.id, entry_data={'label': _('Tools')}, defaults={'order': 100}, )[0] MenuConfigItem.objects.create( entry_id=EventsEntry.id, parent=container, order=200, ) # --------------------------- if not already_populated: for i, name in enumerate( [_('Show'), _('Conference'), _('Breakfast'), _('Brunch')], start=1, ): create_if_needed(EventType, {'pk': i}, name=name) RIGHT = BrickDetailviewLocation.RIGHT BrickDetailviewLocation.objects.multi_create( defaults={ 'model': Event, 'zone': BrickDetailviewLocation.LEFT }, data=[ { 'order': 5 }, # generic info block { 'brick': core_bricks.CustomFieldsBrick, 'order': 40 }, { 'brick': core_bricks.PropertiesBrick, 'order': 450 }, { 'brick': core_bricks.RelationsBrick, 'order': 500 }, { 'brick': bricks.ResultsBrick, 'order': 2, 'zone': RIGHT }, { 'brick': core_bricks.HistoryBrick, 'order': 20, 'zone': RIGHT }, ], ) if apps.is_installed('creme.assistants'): logger.info('Assistants app is installed' ' => we use the assistants blocks on detail view') from creme.assistants import bricks as a_bricks BrickDetailviewLocation.objects.multi_create( defaults={ 'model': Event, 'zone': RIGHT }, data=[ { 'brick': a_bricks.TodosBrick, 'order': 100 }, { 'brick': a_bricks.MemosBrick, 'order': 200 }, { 'brick': a_bricks.AlertsBrick, 'order': 300 }, { 'brick': a_bricks.UserMessagesBrick, 'order': 400 }, ]) if apps.is_installed('creme.documents'): # logger.info('Documents app is installed # => we use the Documents blocks on detail view') from creme.documents.bricks import LinkedDocsBrick BrickDetailviewLocation.objects.create_if_needed( brick=LinkedDocsBrick, order=600, zone=RIGHT, model=Event, )
# -*- coding: utf-8 -*- from django.utils.translation import gettext_lazy as _ from creme import opportunities from creme.creme_core.gui.custom_form import CustomFormDescriptor from creme.opportunities.forms import opportunity as opp_forms Opportunity = opportunities.get_opportunity_model() OPPORTUNITY_CREATION_CFORM = CustomFormDescriptor( id='opportunities-opportunity_creation', model=Opportunity, verbose_name=_('Creation form for opportunity'), base_form_class=opp_forms.BaseCustomForm, extra_sub_cells=[ opp_forms.OppEmitterSubCell(), opp_forms.OppTargetSubCell(), ], ) OPPORTUNITY_EDITION_CFORM = CustomFormDescriptor( id='opportunities-opportunity_edition', model=Opportunity, verbose_name=_('Edition form for opportunity'), base_form_class=opp_forms.BaseCustomForm, extra_sub_cells=[opp_forms.OppTargetSubCell()], ) del Opportunity
def populate(self): already_populated = RelationType.objects.filter(pk=constants.REL_SUB_IS_INVITED_TO).exists() Event = get_event_model() Contact = get_contact_model() Opportunity = get_opportunity_model() create_rtype = RelationType.create create_rtype((constants.REL_SUB_IS_INVITED_TO, _(u'is invited to the event'), [Contact]), (constants.REL_OBJ_IS_INVITED_TO, _(u'has invited'), [Event]), is_internal=True, ) create_rtype((constants.REL_SUB_ACCEPTED_INVITATION, _(u'accepted the invitation to the event'), [Contact]), (constants.REL_OBJ_ACCEPTED_INVITATION, _(u'prepares to receive'), [Event]), is_internal=True, ) create_rtype((constants.REL_SUB_REFUSED_INVITATION, _(u'refused the invitation to the event'), [Contact]), (constants.REL_OBJ_REFUSED_INVITATION, _(u'do not prepare to receive any more'), [Event]), is_internal=True, ) create_rtype((constants.REL_SUB_CAME_EVENT, _(u'came to the event'), [Contact]), (constants.REL_OBJ_CAME_EVENT, _(u'received'), [Event]), is_internal=True, ) create_rtype((constants.REL_SUB_NOT_CAME_EVENT, _(u'did not come to the event'), [Contact]), (constants.REL_OBJ_NOT_CAME_EVENT, _(u'did not receive'), [Event]), is_internal=True, ) create_rtype((constants.REL_SUB_GEN_BY_EVENT, _(u'generated by the event'), [Opportunity]), (constants.REL_OBJ_GEN_BY_EVENT, _(u'(event) has generated the opportunity'), [Event]), is_internal=True, ) # --------------------------- HeaderFilter.create(pk=constants.DEFAULT_HFILTER_EVENT, name=_(u'Event view'), model=Event, cells_desc=[(EntityCellRegularField, {'name': 'name'}), (EntityCellRegularField, {'name': 'type'}), (EntityCellRegularField, {'name': 'start_date'}), (EntityCellRegularField, {'name': 'end_date'}), ], ) # --------------------------- SearchConfigItem.create_if_needed(Event, ['name', 'description', 'type__name']) # --------------------------- if not already_populated: for i, name in enumerate([_(u'Show'), _(u'Conference'), _(u'Breakfast'), _(u'Brunch')], start=1): create_if_needed(EventType, {'pk': i}, name=name) create_bdl = BrickDetailviewLocation.create_if_needed LEFT = BrickDetailviewLocation.LEFT RIGHT = BrickDetailviewLocation.RIGHT BrickDetailviewLocation.create_4_model_brick( order=5, zone=LEFT, model=Event) create_bdl(brick_id=core_bricks.CustomFieldsBrick.id_, order=40, zone=LEFT, model=Event) create_bdl(brick_id=core_bricks.PropertiesBrick.id_, order=450, zone=LEFT, model=Event) create_bdl(brick_id=core_bricks.RelationsBrick.id_, order=500, zone=LEFT, model=Event) create_bdl(brick_id=bricks.ResutsBrick.id_, order=2, zone=RIGHT, model=Event) create_bdl(brick_id=core_bricks.HistoryBrick.id_, order=20, zone=RIGHT, model=Event) if apps.is_installed('creme.assistants'): logger.info('Assistants app is installed => we use the assistants blocks on detail view') from creme.assistants import bricks as a_bricks create_bdl(brick_id=a_bricks.TodosBrick.id_, order=100, zone=RIGHT, model=Event) create_bdl(brick_id=a_bricks.MemosBrick.id_, order=200, zone=RIGHT, model=Event) create_bdl(brick_id=a_bricks.AlertsBrick.id_, order=300, zone=RIGHT, model=Event) create_bdl(brick_id=a_bricks.UserMessagesBrick.id_, order=400, zone=RIGHT, model=Event) if apps.is_installed('creme.documents'): # logger.info('Documents app is installed => we use the Documents blocks on detail view') from creme.documents.bricks import LinkedDocsBrick create_bdl(brick_id=LinkedDocsBrick.id_, order=600, zone=RIGHT, model=Event)