def hook_activities(self): from creme.activities import custom_forms as act_cforms from creme.activities import get_activity_model from creme.commercial.forms.activity import IsCommercialApproachSubCell Activity = get_activity_model() for cform_desc in ( act_cforms.ACTIVITY_CREATION_CFORM, act_cforms.ACTIVITY_CREATION_FROM_CALENDAR_CFORM, ): cform_desc.extra_sub_cells = [ *cform_desc.extra_sub_cells, IsCommercialApproachSubCell(model=Activity), ]
def detailview_display(self, context): opportunity = context['object'] is_hidden = context['fields_configs'].get_4_model( Opportunity).is_fieldname_hidden if apps.is_installed('creme.activities'): from creme.activities import get_activity_model # is_neglected = not get_activity_model().get_future_linked(opportunity, # today=context['today'] - timedelta(days=30), # ).exists() is_neglected = not get_activity_model().objects.future_linked( entity=opportunity, today=context['today'] - timedelta(days=30), ).exists() else: is_neglected = None target = opportunity.target return self._render( self.get_template_context( context, hidden_fields={ fname for fname in ('estimated_sales', 'made_sales') if is_hidden(fname) }, is_neglected=is_neglected, target=target, target_is_organisation=isinstance(target, Organisation), contacts=Paginator( self.get_related_contacts( opportunity=opportunity, rtype_id=constants.REL_SUB_LINKED_CONTACT, ), per_page=self.displayed_contacts_number, ).page(1), activities=Activities4Card.get(context, opportunity), acts=CommercialActs4Card.get(context, opportunity), ))
def save_meeting(data, user, folder, *args, **kwargs): """Save a meeting from a populated data dict @Returns : A saved meeting instance """ # meeting = Activity(user=user, type_id=ACTIVITYTYPE_MEETING) meeting = get_activity_model()(user=user, type_id=ACTIVITYTYPE_MEETING) calendar = get_calendar(folder, user) _set_meeting_from_data(meeting, data, user, folder) meeting.calendars.add(calendar) meeting.save() # TODO is the except really usefull (can be the related contact deleted?) try: Relation.objects.create( object_entity=meeting, type_id=REL_SUB_PART_2_ACTIVITY, subject_entity=meeting.user.related_contact.all()[0], user=meeting.user) except Exception: pass return meeting
from creme.activities import get_activity_model from ..constants import SETTING_CRUDITY_SANDBOX_BY_USER from ..backends.models import CrudityBackend from ..fetchers.base import CrudityFetcher from ..inputs.base import CrudityInput from .fake_crudity_register import FakeContactBackend, SwallowInput, SwallowFetcher Document = get_document_model() Folder = get_folder_model() Contact = get_contact_model() Organisation = get_organisation_model() Activity = get_activity_model() class FakeFetcher(CrudityFetcher): def fetch(self, *args, **kwargs): return [] class FakeInput(CrudityInput): pass class ContactFakeBackend(CrudityBackend): model = Contact
# -*- coding: utf-8 -*- from django.utils.translation import gettext_lazy as _ from creme import activities from creme.activities.forms import activity from creme.creme_core.gui.custom_form import CustomFormDescriptor Activity = activities.get_activity_model() ACTIVITY_CREATION_CFORM = CustomFormDescriptor( id='activities-activity_creation', model=Activity, verbose_name=_('Creation form for activity'), base_form_class=activity.BaseCreationCustomForm, excluded_fields=('start', 'end', 'type', 'sub_type'), extra_sub_cells=[ activity.ActivitySubTypeSubCell(model=Activity), activity.NormalStartSubCell(model=Activity), activity.NormalEndSubCell(model=Activity), activity.MyParticipationSubCell(model=Activity), activity.ParticipatingUsersSubCell(model=Activity), activity.OtherParticipantsSubCell(model=Activity), activity.ActivitySubjectsSubCell(model=Activity), activity.LinkedEntitiesSubCell(model=Activity), activity.DatetimeAlertSubCell(model=Activity), activity.PeriodAlertSubCell(model=Activity), activity.UserMessagesSubCell(model=Activity), ], ) ACTIVITY_CREATION_FROM_CALENDAR_CFORM = CustomFormDescriptor(
# Catching the save of the relation between an activity and an opportunity as a subject @receiver(post_save, sender=Relation) 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()): 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()), )) @receiver(post_save, sender=get_activity_model()) def sync_with_activity(sender, instance, created, **kwargs): # TODO: optimise (only if title has changed - factorise with HistoryLine ??) if not created: CommercialApproach.objects.filter(related_activity=instance).update( title=instance.title)
def populate(self): already_populated = RelationType.objects.filter( pk=constants.REL_SUB_PROJECT_MANAGER, ).exists() Contact = get_contact_model() Activity = get_activity_model() Project = get_project_model() ProjectTask = get_task_model() create_rtype = RelationType.create create_rtype( ( constants.REL_SUB_PROJECT_MANAGER, _('is one of the leaders of this project'), [Contact], ), ( constants.REL_OBJ_PROJECT_MANAGER, _('has as leader'), [Project], ), ) create_rtype( ( constants.REL_SUB_LINKED_2_PTASK, _('is related to the task of project'), [Activity], ), ( constants.REL_OBJ_LINKED_2_PTASK, _('includes the activity'), [ProjectTask], ), is_internal=True, minimal_display=(False, True), ) create_rtype( (constants.REL_SUB_PART_AS_RESOURCE, _('is a resource of'), [Contact]), (constants.REL_OBJ_PART_AS_RESOURCE, _('has as a resource'), [Activity]), is_internal=True, ) # --------------------------- for pk, statusdesc in constants.TASK_STATUS.items(): create_if_needed( TaskStatus, {'pk': pk}, name=str(statusdesc.name), order=pk, description=str(statusdesc.verbose_name), is_custom=False, ) # --------------------------- create_hf = HeaderFilter.objects.create_if_needed create_hf( pk=constants.DEFAULT_HFILTER_PROJECT, model=Project, name=_('Project view'), cells_desc=[ (EntityCellRegularField, { 'name': 'name' }), (EntityCellRegularField, { 'name': 'start_date' }), (EntityCellRegularField, { 'name': 'end_date' }), (EntityCellRegularField, { 'name': 'status' }), (EntityCellRegularField, { 'name': 'description' }), ], ) # Used in form create_hf( pk='projects-hf_task', name=_('Task view'), model=ProjectTask, cells_desc=[ (EntityCellRegularField, { 'name': 'title' }), (EntityCellRegularField, { 'name': 'description' }), ], ) # --------------------------- common_groups_desc = [ { 'name': _('Description'), 'layout': LAYOUT_DUAL_SECOND, 'cells': [ (EntityCellRegularField, { 'name': 'description' }), ], }, { 'name': _('Custom fields'), 'layout': LAYOUT_DUAL_SECOND, 'cells': [ ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial.REMAINING_CUSTOMFIELDS }, ), ], }, ] only_creation_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.PROJECT_CREATION_CFORM, groups_desc=[ { 'name': _('General information'), 'layout': LAYOUT_DUAL_FIRST, 'cells': [ (EntityCellRegularField, { 'name': 'user' }), (EntityCellRegularField, { 'name': 'name' }), (EntityCellRegularField, { 'name': 'status' }), ProjectLeadersSubCell(model=Project).into_cell(), (EntityCellRegularField, { 'name': 'start_date' }), (EntityCellRegularField, { 'name': 'end_date' }), (EntityCellRegularField, { 'name': 'currency' }), ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial. REMAINING_REGULARFIELDS }, ), ], }, *common_groups_desc, *only_creation_groups_desc, ], ) CustomFormConfigItem.objects.create_if_needed( descriptor=custom_forms.PROJECT_EDITION_CFORM, groups_desc=[ { 'name': _('General information'), 'layout': LAYOUT_DUAL_FIRST, 'cells': [ (EntityCellRegularField, { 'name': 'user' }), (EntityCellRegularField, { 'name': 'name' }), (EntityCellRegularField, { 'name': 'status' }), (EntityCellRegularField, { 'name': 'start_date' }), (EntityCellRegularField, { 'name': 'end_date' }), (EntityCellRegularField, { 'name': 'currency' }), ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial. REMAINING_REGULARFIELDS }, ), ], }, *common_groups_desc, ], ) task_rfields_cells = [ (EntityCellRegularField, { 'name': 'user' }), (EntityCellRegularField, { 'name': 'title' }), (EntityCellRegularField, { 'name': 'start' }), (EntityCellRegularField, { 'name': 'end' }), (EntityCellRegularField, { 'name': 'duration' }), (EntityCellRegularField, { 'name': 'tstatus' }), ] CustomFormConfigItem.objects.create_if_needed( descriptor=custom_forms.TASK_CREATION_CFORM, groups_desc=[ { 'name': _('General information'), 'cells': [ *task_rfields_cells, ParentTasksSubCell(model=ProjectTask).into_cell(), ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial. REMAINING_REGULARFIELDS }, ), ], }, *common_groups_desc, *only_creation_groups_desc, ], ) CustomFormConfigItem.objects.create_if_needed( descriptor=custom_forms.TASK_EDITION_CFORM, groups_desc=[ { 'name': _('General information'), 'cells': [ *task_rfields_cells, ( EntityCellCustomFormSpecial, { 'name': EntityCellCustomFormSpecial. REMAINING_REGULARFIELDS }, ), ], }, *common_groups_desc, ], ) # --------------------------- create_searchconf = SearchConfigItem.objects.create_if_needed create_searchconf( Project, ['name', 'description', 'status__name'], ) create_searchconf( ProjectTask, ['linked_project__name', 'duration', 'tstatus__name'], ) # --------------------------- # TODO: move to "not already_populated" section in creme2.4 if not MenuConfigItem.objects.filter( entry_id__startswith='projects-').exists(): container = MenuConfigItem.objects.get_or_create( entry_id=ContainerEntry.id, entry_data={'label': _('Tools')}, defaults={'order': 100}, )[0] MenuConfigItem.objects.create( entry_id=ProjectsEntry.id, parent=container, order=50, ) # --------------------------- if not already_populated: for pk, (name, description) in enumerate([ ( _('Invitation to tender'), _('Response to an invitation to tender'), ), ( _('Initialization'), _('The project is starting'), ), ( _('Preliminary phase'), _('The project is in the process of analysis and design'), ), ( _('Achievement'), _('The project is being implemented'), ), ( _('Tests'), _('The project is in the testing process (unit / integration / functional)' ), ), ( _('User acceptance tests'), _('The project is in the user acceptance testing process'), ), (_('Finished'), _('The project is finished')), ], start=1): create_if_needed( ProjectStatus, {'pk': pk}, name=name, order=pk, description=description, ) # --------------------------- TOP = BrickDetailviewLocation.TOP LEFT = BrickDetailviewLocation.LEFT RIGHT = BrickDetailviewLocation.RIGHT BrickDetailviewLocation.objects.multi_create( defaults={ 'model': Project, 'zone': LEFT }, data=[ { 'brick': bricks.ProjectTasksBrick, 'order': 2, 'zone': TOP }, { 'order': 5 }, { 'brick': bricks.ProjectExtraInfoBrick, 'order': 30 }, { 'brick': core_bricks.CustomFieldsBrick, 'order': 40 }, { 'brick': core_bricks.PropertiesBrick, 'order': 450 }, { 'brick': core_bricks.RelationsBrick, 'order': 500 }, { 'brick': core_bricks.HistoryBrick, 'order': 20, 'zone': RIGHT }, ], ) BrickDetailviewLocation.objects.multi_create( defaults={ 'model': ProjectTask, 'zone': LEFT }, data=[ { 'brick': bricks.TaskResourcesBrick, 'order': 2, 'zone': TOP }, { 'brick': bricks.TaskActivitiesBrick, 'order': 4, 'zone': TOP }, { 'order': 5 }, { 'brick': bricks.TaskExtraInfoBrick, 'order': 30 }, { 'brick': core_bricks.CustomFieldsBrick, 'order': 40 }, { 'brick': bricks.ParentTasksBrick, 'order': 50 }, { 'brick': core_bricks.PropertiesBrick, 'order': 450 }, { 'brick': core_bricks.RelationsBrick, 'order': 500 }, { '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 views') from creme.assistants import bricks as a_bricks for model in (Project, ProjectTask): BrickDetailviewLocation.objects.multi_create( defaults={ 'model': model, '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 block on detail views') from creme.documents.bricks import LinkedDocsBrick BrickDetailviewLocation.objects.multi_create( defaults={ 'brick': LinkedDocsBrick, 'order': 600, 'zone': RIGHT }, data=[{ 'model': model } for model in (Project, ProjectTask)], )
def populate(self): already_populated = RelationType.objects.filter(pk=constants.REL_SUB_PROJECT_MANAGER).exists() Contact = get_contact_model() Activity = get_activity_model() Project = get_project_model() ProjectTask = get_task_model() create_rtype = RelationType.create create_rtype( (constants.REL_SUB_PROJECT_MANAGER, _('is one of the leaders of this project'), [Contact]), (constants.REL_OBJ_PROJECT_MANAGER, _('has as leader'), [Project]), ) create_rtype( (constants.REL_SUB_LINKED_2_PTASK, _('is related to the task of project'), [Activity]), (constants.REL_OBJ_LINKED_2_PTASK, _('includes the activity'), [ProjectTask]), is_internal=True, minimal_display=(False, True), ) create_rtype( (constants.REL_SUB_PART_AS_RESOURCE, _('is a resource of'), [Contact]), (constants.REL_OBJ_PART_AS_RESOURCE, _('has as a resource'), [Activity]), is_internal=True, ) # --------------------------- for pk, statusdesc in constants.TASK_STATUS.items(): create_if_needed(TaskStatus, {'pk': pk}, name=str(statusdesc.name), order=pk, description=str(statusdesc.verbose_name), is_custom=False, ) # --------------------------- create_hf = HeaderFilter.create create_hf(pk=constants.DEFAULT_HFILTER_PROJECT, model=Project, name=_('Project view'), cells_desc=[(EntityCellRegularField, {'name': 'name'}), (EntityCellRegularField, {'name': 'start_date'}), (EntityCellRegularField, {'name': 'end_date'}), (EntityCellRegularField, {'name': 'status'}), (EntityCellRegularField, {'name': 'description'}), ], ) # Used in form create_hf(pk='projects-hf_task', name=_('Task view'), model=ProjectTask, cells_desc=[(EntityCellRegularField, {'name': 'title'}), (EntityCellRegularField, {'name': 'description'}), ], ) # Used in form create_hf(pk='projects-hf_resource', name=_('Resource view'), model=Resource, cells_desc=[(EntityCellRegularField, {'name': 'linked_contact'}), (EntityCellRegularField, {'name': 'hourly_cost'}), ], ) # --------------------------- create_searchconf = SearchConfigItem.create_if_needed create_searchconf(Project, ['name', 'description', 'status__name']) create_searchconf(Resource, ['linked_contact__last_name', 'linked_contact__first_name', 'hourly_cost']) create_searchconf(ProjectTask, ['linked_project__name', 'duration', 'tstatus__name']) # --------------------------- if not already_populated: create_if_needed(ProjectStatus, {'pk': 1}, name=_('Invitation to tender'), order=1, description=_('Response to an invitation to tender')) create_if_needed(ProjectStatus, {'pk': 2}, name=_('Initialization'), order=2, description=_('The project is starting')) create_if_needed(ProjectStatus, {'pk': 3}, name=_('Preliminary phase'), order=3, description=_('The project is in the process of analysis and design')) create_if_needed(ProjectStatus, {'pk': 4}, name=_('Achievement'), order=4, description=_('The project is being implemented')) create_if_needed(ProjectStatus, {'pk': 5}, name=_('Tests'), order=5, description=_('The project is in the testing process (unit / integration / functional)')) create_if_needed(ProjectStatus, {'pk': 6}, name=_('User acceptance tests'), order=6, description=_('The project is in the user acceptance testing process')) create_if_needed(ProjectStatus, {'pk': 7}, name=_('Finished'), order=7, description=_('The project is finished')) # --------------------------- create_bdl = BrickDetailviewLocation.objects.create_if_needed create_bdl_4_model = BrickDetailviewLocation.objects.create_for_model_brick TOP = BrickDetailviewLocation.TOP LEFT = BrickDetailviewLocation.LEFT RIGHT = BrickDetailviewLocation.RIGHT create_bdl(brick=bricks.ProjectTasksBrick, order=2, zone=TOP, model=Project) create_bdl_4_model( order=5, zone=LEFT, model=Project) create_bdl(brick=bricks.ProjectExtraInfoBrick, order=30, zone=LEFT, model=Project) create_bdl(brick=core_bricks.CustomFieldsBrick, order=40, zone=LEFT, model=Project) create_bdl(brick=core_bricks.PropertiesBrick, order=450, zone=LEFT, model=Project) create_bdl(brick=core_bricks.RelationsBrick, order=500, zone=LEFT, model=Project) create_bdl(brick=core_bricks.HistoryBrick, order=20, zone=RIGHT, model=Project) create_bdl(brick=bricks.TaskResourcesBrick, order=2, zone=TOP, model=ProjectTask) create_bdl(brick=bricks.TaskActivitiesBrick, order=4, zone=TOP, model=ProjectTask) create_bdl_4_model( order=5, zone=LEFT, model=ProjectTask) create_bdl(brick=bricks.TaskExtraInfoBrick, order=30, zone=LEFT, model=ProjectTask) create_bdl(brick=core_bricks.CustomFieldsBrick, order=40, zone=LEFT, model=ProjectTask) create_bdl(brick=bricks.ParentTasksBrick, order=50, zone=LEFT, model=ProjectTask) create_bdl(brick=core_bricks.PropertiesBrick, order=450, zone=LEFT, model=ProjectTask) create_bdl(brick=core_bricks.RelationsBrick, order=500, zone=LEFT, model=ProjectTask) create_bdl(brick=core_bricks.HistoryBrick, order=20, zone=RIGHT, model=ProjectTask) if apps.is_installed('creme.assistants'): logger.info('Assistants app is installed => we use the assistants blocks on detail views') from creme.assistants import bricks as a_bricks for model in (Project, ProjectTask): create_bdl(brick=a_bricks.TodosBrick, order=100, zone=RIGHT, model=model) create_bdl(brick=a_bricks.MemosBrick, order=200, zone=RIGHT, model=model) create_bdl(brick=a_bricks.AlertsBrick, order=300, zone=RIGHT, model=model) create_bdl(brick=a_bricks.UserMessagesBrick, order=400, zone=RIGHT, model=model) if apps.is_installed('creme.documents'): # logger.info('Documents app is installed => we use the documents block on detail views') from creme.documents.bricks import LinkedDocsBrick for model in (Project, ProjectTask): create_bdl(brick=LinkedDocsBrick, order=600, zone=RIGHT, model=model)