class TargettingOpportunitiesBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('opportunities', 'target_organisations') dependencies = (Relation, Opportunity) relation_type_deps = (constants.REL_OBJ_TARGETS, ) verbose_name = _('Opportunities which target the organisation / contact') template_name = 'opportunities/bricks/opportunities.html' target_ctypes = (Organisation, Contact) order_by = 'name' def detailview_display(self, context): entity = context['object'] is_hidden = context['fields_configs'].get_4_model( Opportunity).is_fieldname_hidden return self._render( self.get_template_context( context, # TODO: filter deleted ?? Opportunity.objects.filter( relations__object_entity=entity.id, relations__type=constants.REL_SUB_TARGETS, ), predicate_id=self.relation_type_deps[0], hidden_fields={ fname for fname in ('estimated_sales', 'made_sales') if is_hidden(fname) }, is_organisation=isinstance(object, Organisation), is_contact=isinstance(object, Contact), ))
class LinkedDocsBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('documents', 'linked_docs') verbose_name = _('Linked documents') description = _('Allows to add Documents, linked with relationships ' '«related to the document».') dependencies = (Relation, Document) relation_type_deps = (REL_SUB_RELATED_2_DOC, ) template_name = 'documents/bricks/linked-docs.html' order_by = 'id' # For consistent ordering between 2 queries (for pages) def detailview_display(self, context): entity = context['object'] btc = self.get_template_context( context, Relation.objects.filter(subject_entity=entity.id, type=REL_SUB_RELATED_2_DOC), predicate_id=REL_SUB_RELATED_2_DOC, ) relations = btc['page'].object_list docs = Document.objects.filter(pk__in=[ r.object_entity_id for r in relations ], ).select_related('linked_folder').in_bulk() for relation in relations: relation.object_entity = docs[relation.object_entity_id] return self._render(btc)
class FavoritePersonsBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('mobile', 'favorite_persons') dependencies = (MobileFavorite,) verbose_name = _('Favorite Contacts & Organisations (for mobile)') template_name = 'mobile/bricks/favorite.html' target_ctypes = (Contact, Organisation) def detailview_display(self, context): person = context['object'] btc = self.get_template_context( context, get_user_model().objects.filter(mobile_favorite__entity=person.id), is_contact=isinstance(person, Contact), is_orga=isinstance(person, Organisation), ) page = btc['page'] current_user = context['user'] current_user_fav = any(current_user == user for user in page.object_list) if not current_user_fav and page.paginator.num_pages > 1: current_user_fav = MobileFavorite.objects.filter(entity=person.id, user=current_user).exists() btc['current_user_fav'] = current_user_fav return self._render(btc)
class ReceivedInvoicesBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('billing', 'received_invoices') dependencies = (Relation, Invoice) relation_type_deps = (constants.REL_OBJ_BILL_RECEIVED, ) verbose_name = _(u'Received invoices') template_name = 'billing/bricks/received-invoices.html' target_ctypes = (Contact, Organisation) order_by = '-expiration_date' def detailview_display(self, context): person_id = context['object'].id is_hidden = context['fields_configs'].get_4_model( Invoice).is_fieldname_hidden return self._render( self.get_template_context( context, Invoice.objects.filter( relations__object_entity=person_id, relations__type=constants.REL_SUB_BILL_RECEIVED, ), hidden_fields={ fname for fname in ('expiration_date', ) if is_hidden(fname) }, ))
class AlertsBrick(_AssistantsBrick): id_ = QuerysetBrick.generate_id('assistants', 'alerts') verbose_name = _('Alerts') description = _( 'Allows to add Alerts to the current entity, which help you to remind ' 'some important things to achieve before a trigger date.\n' 'E-mails are sent to the owners of the Alerts which are not marked as validated and ' 'near of their deadline (see the job «Reminders»).\n' 'Hint: if the owner of an Alert is a team, e-mails are sent to all the ' 'teammates.') dependencies = (Alert, ) order_by = '-trigger_date' template_name = 'assistants/bricks/alerts.html' def _get_queryset_for_detailview(self, entity, context): return Alert.objects.filter( is_validated=False, entity_id=entity.id, ).select_related('user') def _get_queryset_for_home(self, context): return Alert.objects.filter_by_user(context['user'], ).filter( is_validated=False, entity__is_deleted=False, ).select_related('user')
class DetailedOtherAddressesBrick(_OtherAddressesBrick): # TODO: rename 'other_addresses' id_ = QuerysetBrick.generate_id('persons', 'other_address') dependencies = (Address, ) verbose_name = _('Other addresses (detailed)') template_name = 'persons/bricks/other-addresses-detailed.html' target_ctypes = (Contact, Organisation)
class BillingPaymentInformationBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('billing', 'billing_payment_information') verbose_name = _(u'Default payment information') template_name = 'billing/bricks/billing-payment-information.html' target_ctypes = (Invoice, CreditNote, Quote, SalesOrder, TemplateBase) dependencies = (Relation, PaymentInformation) relation_type_deps = ( constants.REL_OBJ_BILL_ISSUED, constants.REL_SUB_BILL_ISSUED, constants.REL_OBJ_BILL_RECEIVED, constants.REL_SUB_BILL_RECEIVED, ) order_by = 'name' def detailview_display(self, context): billing = context['object'] pi_qs = PaymentInformation.objects.none() hidden = context['fields_configs'].get_4_model(billing.__class__)\ .is_fieldname_hidden('payment_info') organisation = billing.get_source() if not hidden and organisation is not None: pi_qs = PaymentInformation.objects.filter( organisation=organisation) return self._render( self.get_template_context( context, pi_qs, organisation=organisation, field_hidden=hidden, ))
class PaymentInformationBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('billing', 'payment_information') verbose_name = _(u'Payment information') template_name = 'billing/bricks/orga-payment-information.html' target_ctypes = (Organisation, ) order_by = 'name' def detailview_display(self, context): organisation = context['object'] # has_to_be_displayed = True # # try: # if not organisation.is_managed and SettingValue.objects.get(key_id=payment_info_key.id).value: # has_to_be_displayed = False # except SettingValue.DoesNotExist: # # Populate error ? # pass # # if not has_to_be_displayed: # return '' # todo: in template ? empty <table> ? if not organisation.is_managed and SettingValue.objects.get_4_key( payment_info_key, default=True).value: return '' # TODO: in template ? empty <table> ? return self._render( self.get_template_context( context, PaymentInformation.objects.filter(organisation=organisation), ))
class MailsHistoryBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('emails', 'mails_history') dependencies = (EntityEmail, Relation) order_by = '-sending_date' verbose_name = _('Emails history') template_name = 'emails/bricks/mails-history.html' relation_type_deps = ( constants.REL_OBJ_MAIL_SENDED, constants.REL_OBJ_MAIL_RECEIVED, constants.REL_OBJ_RELATED_TO, ) _RTYPE_IDS = [ constants.REL_SUB_MAIL_SENDED, constants.REL_SUB_MAIL_RECEIVED, constants.REL_SUB_RELATED_TO, ] def detailview_display(self, context): pk = context['object'].pk entityemail_ids = Relation.objects.filter(type__pk__in=self._RTYPE_IDS, object_entity=pk, ) \ .values_list('subject_entity', flat=True) \ .distinct() return self._render(self.get_template_context( context, EntityEmail.objects.filter(is_deleted=False, pk__in=entityemail_ids), rtype_ids=self.relation_type_deps, creation_perm=context['user'].has_perm_to_create(EntityEmail), ))
class UserSynchronizationHistoryBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('activesync', 'user_synchronization_history') dependencies = (UserSynchronizationHistory, ) verbose_name = u'User synchronization history' # template_name = 'activesync/templatetags/block_user_synchronization_history.html' template_name = 'activesync/bricks/sync-history.html' configurable = False order_by = '-created' 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)
class SendingHTMLBodyBrick(_HTMLBodyBrick): id_ = QuerysetBrick.generate_id('emails', 'sending_html_body') dependencies = (EmailSending,) configurable = False def _get_body_url(self, instance): return reverse('emails__sending_body', args=(instance.id,))
class ManagersBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('persons', 'managers') verbose_name = _('Organisation managers') dependencies = (Relation, Contact) relation_type_deps = (constants.REL_OBJ_MANAGES, ) template_name = 'persons/bricks/managers.html' target_ctypes = (Organisation, ) def _get_people_qs(self, orga): return orga.get_managers() def _get_add_title(self): return _('Create a manager') # Lazy -> translated only if used def detailview_display(self, context): orga = context['object'] is_hidden = context['fields_configs'].get_4_model( Contact).is_fieldname_hidden return self._render( self.get_template_context( context, self._get_people_qs(orga).select_related('civility'), rtype_id=self.relation_type_deps[0], add_title=self._get_add_title(), hidden_fields={ fname for fname in ('phone', 'mobile', 'email') if is_hidden(fname) }, ))
class ApproachesBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('commercial', 'approaches') dependencies = (CommercialApproach, ) order_by = 'title' verbose_name = _('Commercial approaches') template_name = 'commercial/bricks/approaches.html' # TODO: factorise with assistants blocks (CremeEntity method ??) @staticmethod def _populate_related_real_entities(comapps, user): entities_ids_by_ct = defaultdict(set) for comapp in comapps: entities_ids_by_ct[comapp.entity_content_type_id].add( comapp.entity_id) entities_map = {} get_ct = ContentType.objects.get_for_id for ct_id, entities_ids in entities_ids_by_ct.items(): entities_map.update( get_ct(ct_id).model_class().objects.in_bulk(entities_ids)) for comapp in comapps: comapp.creme_entity = entities_map[comapp.entity_id] def detailview_display(self, context): entity = context['object'] pk = entity.pk if isinstance(entity, get_organisation_model()) and \ not SettingValue.objects.get_4_key(orga_approaches_key, default=True).value: # TODO: regroup the queries managers_ids = entity.get_managers().values_list('id', flat=True) employees_ids = entity.get_employees().values_list('id', flat=True) opportunities_ids = Opportunity.objects.filter(relations__type=REL_SUB_TARGETS, relations__object_entity=entity, ) \ .values_list('id',flat=True) approaches = CommercialApproach.objects.filter(entity_id__in=chain( [pk], managers_ids, employees_ids, opportunities_ids), ) else: approaches = CommercialApproach.get_approaches(pk) return self._render(self.get_template_context( context, approaches, )) def home_display(self, context): btc = self.get_template_context( context, CommercialApproach.get_approaches(), ) self._populate_related_real_entities(btc['page'].object_list, context['user']) return self._render(btc)
class ReceivedSalesOrdersBrick(_ReceivedBillingDocumentsBrick): id_ = QuerysetBrick.generate_id('billing', 'received_sales_orders') dependencies = (Relation, SalesOrder) verbose_name = _(u'Received sales orders') _billing_model = SalesOrder _title = _(u'{count} Received sales order') _title_plural = _(u'{count} Received sales orders') _empty_title = _(u'Received sales orders') _empty_msg = _(u'No received sales order for the moment')
class ReceivedCreditNotesBrick(_ReceivedBillingDocumentsBrick): id_ = QuerysetBrick.generate_id('billing', 'received_credit_notes') dependencies = (Relation, CreditNote) verbose_name = _(u'Received credit notes') _billing_model = CreditNote _title = _(u'{count} Received credit note') _title_plural = _(u'{count} Received credit notes') _empty_title = _(u'Received credit notes') _empty_msg = _(u'No received credit note for the moment')
class PastActivitiesBrick(FutureActivitiesBrick): id_ = QuerysetBrick.generate_id('activities', 'past_activities') verbose_name = _(u'Past activities') template_name = 'activities/bricks/past-activities.html' def _get_queryset_for_entity(self, entity, context): if isinstance(entity, Organisation): return Activity.get_past_linked_for_orga(entity, context['today']) else: return Activity.get_past_linked(entity, context['today'])
class AttachmentsBrick(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('emails', 'attachments') dependencies = (Document,) verbose_name = _('Attachments') template_name = 'emails/bricks/attachments.html' target_ctypes = (EmailTemplate,) order_by = 'title' def _get_queryset(self, entity): # entity=mailtemplate return entity.attachments.all()
class ParentListsBrick(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('emails', 'parent_lists') dependencies = (MailingList,) verbose_name = _('Parent mailing lists') template_name = 'emails/bricks/parent-lists.html' target_ctypes = (MailingList,) order_by = 'name' def _get_queryset(self, entity): # entity=mailing_list return entity.parents_set.all()
class ChildListsBrick(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('emails', 'child_lists') dependencies = (MailingList,) verbose_name = _('Child mailing lists') template_name = 'emails/bricks/child-lists.html' target_ctypes = (MailingList,) order_by = 'name' def _get_queryset(self, entity): # entity=mailing_list return entity.children.all()
class MessagingListsBlock(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('sms', 'messaging_lists') verbose_name = _('Messaging lists') dependencies = (MessagingList, ) template_name = 'sms/bricks/messaging-lists.html' target_ctypes = (SMSCampaign, ) order_by = 'name' def _get_queryset(self, entity): # NB: entity=campaign return entity.lists.all()
class MailingListsBrick(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('emails', 'mailing_lists') dependencies = (MailingList,) verbose_name = _('Mailing lists') template_name = 'emails/bricks/mailing-lists.html' target_ctypes = (EmailCampaign,) order_by = 'name' def _get_queryset(self, entity): # entity=campaign return entity.mailing_lists.all()
class GenericModelBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('creme_config', 'model_config') dependencies = (CremeModel, ) page_size = _PAGE_SIZE verbose_name = 'Model configuration' template_name = 'creme_config/bricks/configurable-model.html' configurable = False # NB: credentials are OK : we are sure to use the custom reloading view because of the specific constructor. # def __init__(self, app_name, model_name, model): def __init__(self, app_name, model_config): super().__init__() self.app_name = app_name # self.model_name = model_name # self.model = model self.model_config = model_config def detailview_display(self, context): # model = self.model model_config = self.model_config model = model_config.model meta = model._meta # TODO: (must declare in the template what fields can be used to sort) # ordering = meta.ordering # if ordering: # self.order_by = ordering[0] displayable_fields = [] is_reorderable = False for field in meta.fields: fieldname = field.name.lower() if fieldname == 'is_custom': continue elif fieldname == 'order': is_reorderable = True else: displayable_fields.append(field) displayable_fields.extend(meta.many_to_many) return self._render( self.get_template_context( context, model.objects.all(), model=model, meta=meta, app_name=self.app_name, model_config=model_config, # model_name=self.model_name, model_is_reorderable=is_reorderable, displayable_fields=displayable_fields, ))
class TaskActivitiesBrick(PaginatedBrick): id_ = QuerysetBrick.generate_id('projects', 'task_activities') dependencies = (Activity, Resource, Relation) relation_type_deps = (REL_OBJ_LINKED_2_PTASK, ) verbose_name = _('Activities for this task') template_name = 'projects/bricks/activities.html' target_ctypes = (ProjectTask,) def detailview_display(self, context): task = context['object'] return self._render(self.get_template_context(context, task.related_activities))
class ParentTasksBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('projects', 'parent_tasks') dependencies = (ProjectTask,) verbose_name = _('Parents of a task') template_name = 'projects/bricks/parent-tasks.html' target_ctypes = (ProjectTask,) def detailview_display(self, context): task = context['object'] return self._render(self.get_template_context(context, task.parent_tasks.all()))
class EmployeesBrick(ManagersBrick): id_ = QuerysetBrick.generate_id('persons', 'employees') verbose_name = _('Organisation employees') relation_type_deps = (constants.REL_OBJ_EMPLOYED_BY, ) template_name = 'persons/bricks/employees.html' def _get_people_qs(self, orga): return orga.get_employees() def _get_add_title(self): return _('Create an employee') # Lazy -> translated only if used
class MessagesBrick(QuerysetBrick): id_ = QuerysetBrick.generate_id('sms', 'messages') dependencies = (Message, ) page_size = 12 verbose_name = _('Sent messages') template_name = 'sms/bricks/messages.html' def detailview_display(self, context): sending = context['object'] return self._render( self.get_template_context(context, sending.messages.all()))
class ActionsNotOnTimeBrick(_ActionsBrick): id_ = QuerysetBrick.generate_id('assistants', 'actions_nit') verbose_name = _('Reactions not in time') template_name = 'assistants/bricks/actions-not-on-time.html' def _get_queryset_for_detailview(self, entity, context): return super()._get_queryset_for_detailview(entity, context) \ .filter(deadline__lte=context['today']) def _get_queryset_for_home(self, context): return super()._get_queryset_for_home(context) \ .filter(deadline__lte=context['today'])
class LinkedContactsBrick(_RelatedToOpportunity, _LinkedStuffBrick): id_ = QuerysetBrick.generate_id('opportunities', 'linked_contacts') dependencies = (Relation, Contact) relation_type_deps = (constants.REL_OBJ_LINKED_CONTACT, ) verbose_name = _('Linked Contacts') template_name = 'opportunities/bricks/contacts.html' def _get_queryset(self, entity): return self.get_related_contacts( opportunity=entity, rtype_id=constants.REL_SUB_LINKED_CONTACT, )
class BusinessManagersBrick(_RelatedToOpportunity, _LinkedStuffBrick): id_ = QuerysetBrick.generate_id('opportunities', 'responsibles') dependencies = (Relation, Contact) relation_type_deps = (constants.REL_OBJ_RESPONSIBLE, ) verbose_name = _('Business managers') template_name = 'opportunities/bricks/managers.html' def _get_queryset(self, entity): return self.get_related_contacts( opportunity=entity, rtype_id=constants.REL_SUB_RESPONSIBLE, )
class OrganisationsBrick(_RelatedEntitesBrick): id_ = QuerysetBrick.generate_id('emails', 'organisations') dependencies = (Organisation,) verbose_name = _('Organisations recipients') template_name = 'emails/bricks/organisations.html' target_ctypes = (MailingList,) def _get_queryset(self, entity): # entity=mailing_list return entity.organisations.all() def _update_context(self, context): context['field_hidden'] = context['fields_configs'].get_4_model(Organisation) \ .is_fieldname_hidden('email')