class ContractorJson(BaseDatatableView): # The model we're going to show model = Contractor # define the columns that will be returned columns = ['name', 'short_hand', 'profile', 'remarks', 'id'] column_names = [x for x in capitalize(columns)] column_names[-1] = 'Option' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = ['name', 'short_hand', 'profile', 'remarks', 'id'] # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'id': button_edit = '<a href="{0}{1}" class="btn default btn-xs red-stripe">Edit</a>'.format( reverse('contract_mgt:add_edit_contractor'), row.id) button_contacts = '<a href="{0}{1}" class="btn default btn-xs green-stripe">View Contacts</a>'.format( reverse('contract_mgt:table_contact'), row.id) return button_edit + button_contacts else: return super(ContractorJson, self).render_column(row, column)
class AttendanceSummaryJson(BaseDatatableView): # The model we're going to show model = AttendanceSummary def get_initial_queryset(self): # pk here is the Contractor ID pk = self.kwargs.pop('pk', None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. return self.model.objects.filter(user__pk=pk) # define the columns that will be returned columns = [ 'created_by', 'date_day', 'date_time_in', 'date_time_out', 'total_hours', 'reason_for_excess', 'accepted', 'id' ] column_names = [x for x in capitalize(columns)] column_names[0] = 'employee' column_names[-1] = 'Option' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'id': return '<a href="{0}{1}/1" class="btn default btn-xs green-stripe">Accept</a>' \ '<a href="{0}{1}/0" class="btn default btn-xs red-stripe">Reject</a>' \ .format( reverse('user_mgt:acceptance'), row.id) elif column in ['date_time_in', 'date_time_out']: # timedelta of 4 because users are in UAE and server uses utc time = dt.datetime.combine(dt.date.today(), getattr( row, column)) + dt.timedelta(hours=4) return time.strftime('%H:%M') elif column == 'total_hours': return int(row.total_hours) else: return super(AttendanceSummaryJson, self).render_column(row, column)
class TeamTaskSummaryJson(BaseDatatableView): # The model we're going to show model = TeamTaskSummaryDashboard def get_initial_queryset(self): # pk here is the Contractor ID pk = self.kwargs.pop('pk',None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. if pk is None: return self.model.objects.filter(Q(status='Open')).order_by('-date_action').all() # return self.model.objects.filter(contractor__pk=pk) return self.model.objects.filter(Q(status='Open') & Q(contractor__pk=pk)) # define the columns that will be returned columns = ['contractor', 'contract_no', 'action_taken', 'date_action', 'team_task_id'] column_names = [x for x in capitalize(columns)] column_names[0] = 'Contractor' column_names[-2] = 'Update Date' column_names[-1] = 'Option' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'team_task_id': return '<a href="{0}{2}" class="btn default btn-xs red-stripe">Edit</a>' \ '<a href="{1}{2}" class="btn default btn-xs green-stripe">Timeline</a>' \ .format( reverse('team_mgt:add_edit_team_task'), reverse('team_mgt:timeline'), row.team_task_id) elif column == 'date_action': return row.date_action.strftime('%d-%m-%Y') else: return super(TeamTaskSummaryJson, self).render_column(row, column)
class ContractorContactJson(BaseDatatableView): # The model we're going to show model = ContractorContact def get_initial_queryset(self): # pk here is the Contractor ID pk = self.kwargs.pop('pk', None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. if pk is None: return self.model.objects.all() return self.model.objects.filter(contractor__pk=pk) # define the columns that will be returned columns = [ 'name', 'contractor_id', 'position', 'eadd', 'mobile_no', 'office_no', 'id' ] column_names = [x for x in capitalize(columns)] column_names[-1] = 'Option' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'contractor_id': return row.contractor.name if column == 'id': return '<a href="{0}{1}" class="btn default btn-xs red-stripe">Edit</a>'.format( reverse('contract_mgt:add_edit_contact'), row.id) else: return super(ContractorContactJson, self).render_column(row, column)
def get(self, request, *args, **kwargs): pk = request.GET.get('pk', None) field_arrangement = [ # 'id', 'contractor_name', 'invoice_no', 'contract_no', 'region', 'invoice_type', 'payment_type', # 'invoice_cert_date', 'invoice_amount', ] task = Task.objects.filter(pk=pk).first() df_invoice = pd.DataFrame.from_records( Invoice.objects.filter(task__pk=pk).all().values()) df_contractor = pd.DataFrame.from_records( Contractor.objects.all().values()) if len(df_invoice) == 0 or len(df_contractor) == 0: data = {} actual_total = 0 overrun = False else: mg = pd.merge(df_invoice, df_contractor, left_on='contractor_id', right_on='id', how='left') mg['decimal_str_format'] = mg['capex_amount'].map( lambda x: '{:,.2f}'.format(x)) mg.rename( columns={ 'name': 'contractor_name', # {'old_name': 'new_name'} 'id_x': 'id', 'decimal_str_format': 'amount' }, inplace=True) data = mg.to_dict('records') actual_total = task.invoice_set.all().aggregate( sum=Sum('capex_amount'))['sum'] overrun = task.is_overrun context = { 'data': data, 'columns': [i for i in capitalize(field_arrangement)], 'keys': field_arrangement, 'task_no': task.task_no, 'authorize_expenditure': task.total_authorize_expenditure, 'total_accrual': task.total_accrual, 'actual_total': actual_total, 'overrun': task.is_overrun, 'overbook': task.is_overbook, } return render(request, self.template_name, context)
class PccJson(BaseDatatableView): # The model we're going to show model = Pcc def get_initial_queryset(self): # pk here is the Contractor ID pk = self.request.GET.get('pk',None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. if pk is None: return self.model.objects.all() return self.model.objects.filter(task__pk=pk).all() # define the columns that will be returned columns = ['task.task_no', 'is_complete', 'pcc_date', 'ref_no', 'amount', 'file', 'id'] # Hide Columns hidden_columns = [ i for i, x in enumerate(columns) if x in [] ] column_names = [x for x in capitalize(columns)] column_names[0] = 'Task No' column_names[-1] = 'Option' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'amount': val = getattr(row, column) return '{0:,.2f}'.format(val) elif column == 'pcc_date': val = getattr(row, column) return '{0:%d-%b-%Y}'.format(val) elif column == 'file': val = getattr(row, column) if bool(val): status = 'info' if bool(val) else 'danger' icon = 'check' if bool(val) else 'close' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = '<a target="_blank" href="{1}pcc/{2}">{0}</a>'.format(html_indicator, reverse('main:get_file'), row.id) else: status = 'danger' icon = 'close' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = html_indicator html = html_val return html elif column == 'id': return '<a target="_blank" href="{1}?pk={0}" class="btn default btn-xs red-stripe">Edit</a>' \ .format( row.id, reverse('budget_mgt:add_edit_pcc'), ) else: return super(PccJson, self).render_column(row, column) def filter_queryset(self, qs): """ Change the default startswith filtering to contains """ if not self.pre_camel_case_notation: # get global search value search = self.request.GET.get('search[value]', None) col_data = self.extract_datatables_column_data() q = Q() for col_no, col in enumerate(col_data): # apply global search to all searchable columns if search and col['searchable']: q |= Q(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): search}) # column specific filter if col['search.value']: qs = qs.filter(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): col['search.value']}) qs = qs.filter(q) return qs
class InvoiceJson(BaseDatatableView): # The model we're going to show model = Invoice def get_initial_queryset(self): # pk here is the Contractor ID filter = self.request.GET.get('filter',None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. if filter == 'all': return self.model.objects.all() return self.model.objects.filter(~Q(state='Completed')).all() # define the columns that will be returned columns = ['contractor.name', 'task.task_no', 'region', 'invoice_no', 'invoice_amount', 'state__name', 'status', 'reject_date'] # Hide Columns hidden_columns = [ i for i, x in enumerate(columns) if x in [] ] column_names = [x for x in capitalize(columns)] column_names[0] = 'Contractor Name' column_names[1] = 'Task Number' column_names[-3] = 'Current Process' # columns to be summed sum_columns = [4] # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # define hidden columns # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'state__name': val = getattr(row, column) html_val = '<a target="_blank" href="{1}?pk={2}">{0}</a>'.format(val, reverse('budget_mgt:invoice_workflow'), row.id) return html_val elif column == 'task.task_no': status = 'danger' if row.task.is_overrun is True else 'info' icon = 'close' if row.task.is_overrun is True else 'check' value = row.task.task_no url = reverse('budget_mgt:summary_invoice') + '?pk=' + '{}'.format(row.task_id) return '<span class="label label-{2}"> <i class="icon-{1}"></i></span> <a target="_blank" href="{3}">{0}</a>'.format(value, icon, status, url) elif column == 'invoice_no': val = getattr(row, column) status = 'danger' if row.status == 'Reject' else 'info' icon = 'close' if row.status == 'Reject' else 'check' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = '<a target="_blank" href="{1}?pk={2}">{0}</a>'.format(val, reverse('budget_mgt:add_edit_invoice'), row.id) html = html_indicator + ' ' + html_val return html elif column == 'reject_date': val = getattr(row, column) if val: return '{0:%d-%b-%Y}'.format(val) return "" elif column == 'invoice_amount': val = getattr(row, column) return '<span>{:,.2f}</span>'.format(val) else: return super(InvoiceJson, self).render_column(row, column) def filter_queryset(self, qs): """ Change the default startswith filtering to contains """ if not self.pre_camel_case_notation: # get global search value search = self.request.GET.get('search[value]', None) col_data = self.extract_datatables_column_data() q = Q() for col_no, col in enumerate(col_data): # apply global search to all searchable columns if search and col['searchable']: q |= Q(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): search}) # column specific filter if col['search.value']: qs = qs.filter(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): col['search.value']}) qs = qs.filter(q) return qs
class TaskJson(BaseDatatableView): # The model we're going to show model = Task def get_initial_queryset(self): # pk here is the Contractor ID pk = self.kwargs.pop('pk',None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. if pk is None: return self.model.objects.annotate(remaining_accrual=F('total_accrual')-F('actual_expenditure'), task_progress=Case(When(total_authorize_expenditure=0, then=Value('0.00')), default=F('total_pcc_amount')/F('total_authorize_expenditure'), output_field=DecimalField(), ) ).all() return self.model.objects.filter(contractor__pk=pk) # define the columns that will be returned columns = ['task_no', 'total_authorize_commitment', 'total_authorize_expenditure', 'finance_actual_expenditure', 'total_accrual', 'total_pcc_amount', 'actual_expenditure', 'remaining_accrual', 'task_progress', 'state__name', 'tags.name'] # Hide Columns hidden_columns = [] column_names = [x for x in capitalize(columns)] column_names[1] = 'A. Commitment' column_names[2] = 'A. Expenditure' column_names[3] = 'F. Expenditure' column_names[5] = 'Total PCC' column_names[-5] = 'Invoice Paid' column_names[-4] = 'Remaining Accrual' column_names[-3] = 'Payment Type' column_names[-2] = 'Current Process' column_names[-1] = 'Tags' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # columns to be summed sum_columns = [1, 2, 3, 4, 5, 6, 7] # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'task_no': val = getattr(row, column) return '<a target="_blank" href="{1}?pk={0}">{2}</a>' \ .format( row.id, reverse('budget_mgt:add_edit_task'), val ) elif column == 'tags.name': html_label = '<span class="label bg-green-jungle">{}</span> ' html_tags = ''.join(sorted([html_label.format(i.name) for i in row.tags.all()])) return html_tags elif column == 'remaining_accrual': val = getattr(row, column) return '<span>{:,.2f}</span>'.format(val) elif column == 'total_pcc_amount': val = getattr(row, column) status = 'danger' if not row.is_pcc_complete else 'info' icon = 'close' if not row.is_pcc_complete else 'check' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = '<a class="sum" target="_blank" href="{1}?pk={2}">{0:,.2f}</a>'.format(val, reverse('budget_mgt:table_pcc'), row.id) html = html_indicator + ' ' + html_val return html elif column == 'total_authorize_expenditure': val = getattr(row, column) status = 'danger' if not row.is_expenditure_within_commitment else 'info' icon = 'close' if not row.is_expenditure_within_commitment else 'check' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = '<a class="sum" target="_blank" href="{1}?pk={2}">{0:,.2f}</a>'.format(val, reverse('budget_mgt:table_authorize_expenditure'), row.id) html = html_indicator + ' ' + html_val return html elif column == 'total_accrual': val = getattr(row, column) status = 'danger' if row.is_overbook else 'info' icon = 'close' if row.is_overbook else 'check' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = '<a class="sum" target="_blank" href="{1}?pk={2}">{0:,.2f}</a>'.format(val, reverse('budget_mgt:table_accrual'), row.id) html = html_indicator + ' ' + html_val return html elif column == 'task_progress': val = getattr(row, column) invoice = row.invoice_set.order_by('-pk').first() if invoice is None: payment_type = 'No Invoice' else: payment_type = invoice.payment_type status = 'danger' if not row.is_within_work_criteria else 'info' html_indicator = '<span class="label label-{0}">{1:.2%}</span>'.format(status, val) html_val = payment_type html = html_indicator + ' ' + html_val return html # elif column == 'total_pcc_amount': # val = getattr(row, column) # html_val = '<a target="_blank" href="{1}?pk={2}">{0:,.2f}</a>'.format(val, # reverse('budget_mgt:table_pcc'), # row.id, # ) # html = html_val # return html elif column == 'actual_expenditure': val = getattr(row, column) status = 'danger' if row.is_overrun else 'info' icon = 'close' if row.is_overrun else 'check' html_indicator = '<span class="label label-{0}"> <i class="icon-{1}"></i></span>'.format(status, icon) html_val = '<a target="_blank" href="{1}?pk={2}">{0:,.2f}</a>'.format(val, reverse('budget_mgt:summary_invoice'), row.id) html = html_indicator + ' ' +html_val return html elif column == 'total_authorize_commitment': val = getattr(row, column) html = '<a target="_blank" href="{1}?pk={2}">{0:,.2f}</a>'.format(val, reverse('budget_mgt:table_authorize_commitment'), row.id) return html elif column == 'state__name': val = getattr(row, column) html_val = '<a target="_blank" href="{1}?pk={2}">{0}</a>'.format(val, reverse('budget_mgt:task_workflow'), row.id) if row.state == "PCC to be Issued" : if isinstance(row.state_date, dt.datetime): # results is negative duration = row.state_date - dt.datetime.now(tz=utc) days = 30 + duration.days else: days = 0 label_color = 'info' if days > 0 else 'danger' html_indicator = '<h4 class="badge badge-{1}">{0}</h4>'.format(days, label_color) return html_indicator + ' ' + html_val return html_val elif column == 'overrun': return '<span class="label label-{}"> {} </span>'.\ format( 'danger' if row.is_overrun else 'success', row.is_overrun ) else: return super(TaskJson, self).render_column(row, column) def filter_queryset(self, qs): """ Change the default startswith filtering to contains """ if not self.pre_camel_case_notation: # get global search value search = self.request.GET.get('search[value]', None) col_data = self.extract_datatables_column_data() q = Q() for col_no, col in enumerate(col_data): # apply global search to all searchable columns if search and col['searchable']: q |= Q(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): search}) # column specific filter if col['search.value']: qs = qs.filter(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): col['search.value']}) qs = qs.filter(q) return qs
class TeamTaskJson(BaseDatatableView): # The model we're going to show model = TeamTask def get_initial_queryset(self): # pk here is the Contractor ID pk = self.kwargs.pop('pk',None) # return queryset used as base for futher sorting/filtering # these are simply objects displayed in datatable # You should not filter data returned here by any filter values entered by user. This is because # we need some base queryset to count total number of records. if pk is None: return self.model.objects.all() return self.model.objects.filter(contractor__pk=pk) # define the columns that will be returned columns = ['contractor.name', 'contract_no', 'description', 'severity', 'status', 'user__username', 'id'] # Hide Columns hidden_columns = [ i for i, x in enumerate(columns) if x in [] ] column_names = [x for x in capitalize(columns)] column_names[0] = 'Contractor' column_names[-2] = 'Person/s in charge' column_names[-1] = 'Option' # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables. For non sortable columns use empty # value like '' order_columns = columns # define hidden columns # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'id': return '<a href="{0}{2}" class="btn default btn-xs red-stripe">Edit</a>' \ '<a href="{1}{2}" class="btn default btn-xs green-stripe">Timeline</a>' \ .format( reverse('team_mgt:add_edit_team_task'), reverse('team_mgt:timeline'), row.id) else: return super(TeamTaskJson, self).render_column(row, column) def filter_queryset(self, qs): """ If search['value'] is provided then filter all searchable columns using istartswith """ if not self.pre_camel_case_notation: # get global search value search = self.request.GET.get('search[value]', None) col_data = self.extract_datatables_column_data() q = Q() for col_no, col in enumerate(col_data): # apply global search to all searchable columns if search and col['searchable']: q |= Q(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): search}) # column specific filter if col['search.value']: qs = qs.filter(**{'{0}__contains'.format(self.columns[col_no].replace('.', '__')): col['search.value']}) qs = qs.filter(q) return qs