예제 #1
0
def graph_bar_jqp(request):
    """Nice graph bar of lead state during time using jqplot"""
    data = defaultdict(list)  # Raw data collected
    graph_data = []  # Data that will be returned to jqplot

    # Gathering data
    subsidiary = get_subsidiary_from_session(request)
    leads = Lead.objects.filter(creation_date__gt=date.today() -
                                timedelta(3 * 365))
    if subsidiary:
        leads = leads.filter(subsidiary=subsidiary)
    for lead in leads:
        # Using first day of each month as key date
        kdate = date(lead.creation_date.year, lead.creation_date.month, 1)
        data[kdate].append(lead)

    if not data:
        return HttpResponse('')

    kdates = list(data.keys())
    kdates.sort()
    isoKdates = [a.isoformat()
                 for a in kdates]  # List of date as string in ISO format

    # Draw a bar for each state
    for state in Lead.STATES:
        ydata = [
            len([i for i in x if i.state == state[0]])
            for x in sortedValues(data)
        ]
        ydata_detailed = [[
            "%s (%s)" % (i.name, i.deal_id) for i in x if i.state == state[0]
        ] for x in sortedValues(data)]
        graph_data.append(list(zip(isoKdates, ydata, ydata_detailed)))

    # Draw lead amount by month
    yAllLead = [
        float(sum([i.sales for i in x if i.sales])) for x in sortedValues(data)
    ]
    yWonLead = [
        float(sum([i.sales for i in x if (i.sales and i.state == "WON")]))
        for x in sortedValues(data)
    ]
    graph_data.append(list(zip(isoKdates, yAllLead)))
    graph_data.append(list(zip(isoKdates, yWonLead)))
    if kdates:
        min_date = (kdates[0] - timedelta(30)).isoformat()
    else:
        min_date = ""

    return render(
        request, "leads/graph_bar_jqp.html", {
            "graph_data": json.dumps(graph_data),
            "series_label": [i[1] for i in Lead.STATES],
            "series_colors": COLORS,
            "min_date": min_date,
            "user": request.user
        })
예제 #2
0
파일: views.py 프로젝트: digitalfox/pydici
def graph_bar_jqp(request):
    """Nice graph bar of lead state during time using jqplot
    @todo: per year, with start-end date"""
    data = defaultdict(list)  # Raw data collected
    graph_data = []  # Data that will be returned to jqplot

    # Gathering data
    for lead in Lead.objects.filter(creation_date__gt=date.today() - timedelta(2 * 365)):
        # Using first day of each month as key date
        kdate = date(lead.creation_date.year, lead.creation_date.month, 1)
        data[kdate].append(lead)

    if not data:
        return HttpResponse('')

    kdates = list(data.keys())
    kdates.sort()
    isoKdates = [a.isoformat() for a in kdates]  # List of date as string in ISO format

    # Draw a bar for each state
    for state in Lead.STATES:
        ydata = [len([i for i in x if i.state == state[0]]) for x in sortedValues(data)]
        ydata_detailed = [["%s (%s)" % (i.name, i.deal_id) for i in x if i.state == state[0]] for x in sortedValues(data)]
        graph_data.append(list(zip(isoKdates, ydata, ydata_detailed)))

    # Draw lead amount by month
    yAllLead = [float(sum([i.sales for i in x if i.sales])) for x in sortedValues(data)]
    yWonLead = [float(sum([i.sales for i in x if (i.sales and i.state == "WON")])) for x in sortedValues(data)]
    graph_data.append(list(zip(isoKdates, yAllLead)))
    graph_data.append(list(zip(isoKdates, yWonLead)))
    if kdates:
        min_date = (kdates[0] - timedelta(30)).isoformat()
    else:
        min_date = ""

    return render(request, "leads/graph_bar_jqp.html",
                  {"graph_data": json.dumps(graph_data),
                   "series_label": [i[1] for i in Lead.STATES],
                   "series_colors": COLORS,
                   "min_date": min_date,
                   "user": request.user})
예제 #3
0
def graph_company_business_activity_jqp(request, company_id):
    """Business activity (leads and bills) for a company
    @todo: extend this graph to multiple companies"""
    graph_data = []
    billsData = dict()
    allLeadsData = dict()
    wonLeadsData = dict()
    minDate = date.today()
    company = Company.objects.get(id=company_id)

    for bill in ClientBill.objects.filter(lead__client__organisation__company=company):
        kdate = bill.creation_date.replace(day=1)
        if kdate in billsData:
            billsData[kdate] += int(float(bill.amount) / 1000)
        else:
            billsData[kdate] = int(float(bill.amount) / 1000)

    for lead in Lead.objects.filter(client__organisation__company=company):
        kdate = lead.creation_date.date().replace(day=1)
        if lead.state == "WON":
            datas = (allLeadsData, wonLeadsData)
        else:
            datas = (allLeadsData,)
        for data in datas:
            if kdate in data:
                data[kdate] += 1
            else:
                data[kdate] = 1

    for data in (billsData, allLeadsData, wonLeadsData):
        kdates = data.keys()
        kdates.sort()
        isoKdates = [a.isoformat() for a in kdates]  # List of date as string in ISO format
        if len(kdates) > 0 and kdates[0] < minDate:
            minDate = kdates[0]
        data = zip(isoKdates, sortedValues(data))
        if not data:
            data = ((0, 0))
        graph_data.append(data)

    minDate = previousMonth(minDate)

    return render(request, "crm/graph_company_business_activity_jqp.html",
                  {"graph_data": json.dumps(graph_data),
                   "series_colors": COLORS,
                   "min_date": minDate.isoformat(),
                   "user": request.user})
예제 #4
0
파일: views.py 프로젝트: agateau/pydici
def graph_company_business_activity_jqp(request, company_id):
    """Business activity (leads and bills) for a company
    @todo: extend this graph to multiple companies"""
    graph_data = []
    billsData = dict()
    lostLeadsData = dict()
    currentLeadsData = dict()
    wonLeadsData = dict()
    minDate = date.today()
    company = Company.objects.get(id=company_id)

    for bill in ClientBill.objects.filter(lead__client__organisation__company=company):
        kdate = bill.creation_date.replace(day=1)
        if kdate in billsData:
            billsData[kdate] += int(float(bill.amount) / 1000)
        else:
            billsData[kdate] = int(float(bill.amount) / 1000)

    for lead in Lead.objects.filter(client__organisation__company=company):
        kdate = lead.creation_date.date().replace(day=1)
        for data in (lostLeadsData, wonLeadsData, currentLeadsData, billsData):
            data[kdate] = data.get(kdate, 0)  # Default to 0 to avoid stacking weirdness in graph
        if lead.state == "WON":
            wonLeadsData[kdate] += 1
        elif lead.state in ("LOST", "FORGIVEN"):
            lostLeadsData[kdate] += 1
        else:
            currentLeadsData[kdate] += 1

    for data in (billsData, lostLeadsData, wonLeadsData, currentLeadsData):
        kdates = data.keys()
        kdates.sort()
        isoKdates = [a.isoformat() for a in kdates]  # List of date as string in ISO format
        if len(kdates) > 0 and kdates[0] < minDate:
            minDate = kdates[0]
        data = zip(isoKdates, sortedValues(data))
        if not data:
            data = ((0, 0))
        graph_data.append(data)

    minDate = previousMonth(minDate)

    return render(request, "crm/graph_company_business_activity_jqp.html",
                  {"graph_data": json.dumps(graph_data),
                   "series_colors": COLORS,
                   "min_date": minDate.isoformat(),
                   "user": request.user})
예제 #5
0
파일: views.py 프로젝트: yurivital/pydici
def graph_billing_jqp(request):
    """Nice graph bar of incomming cash from bills
    @todo: per year, with start-end date"""
    billsData = defaultdict(list)  # Bill graph Data
    tsData = {}  # Timesheet done work graph data
    staffingData = {}  # Staffing forecasted work graph data
    wStaffingData = {}  # Weighted Staffing forecasted work graph data
    today = date.today()
    start_date = today - timedelta(
        24 * 30)  # Screen data about 24 month before today
    end_date = today + timedelta(6 * 30)  # No more than 6 month forecasted
    graph_data = []  # Data that will be returned to jqplot

    # Gathering billsData
    bills = ClientBill.objects.filter(creation_date__gt=start_date)
    if bills.count() == 0:
        return HttpResponse()

    for bill in bills:
        # Using first day of each month as key date
        kdate = bill.creation_date.replace(day=1)
        billsData[kdate].append(bill)

    # Collect Financial conditions as a hash for further lookup
    financialConditions = {
    }  # First key is consultant id, second is mission id. Value is daily rate
    # TODO: filter FC on timesheet date to forget old fc (perf)
    for fc in FinancialCondition.objects.filter(mission__nature="PROD"):
        if not fc.consultant_id in financialConditions:
            financialConditions[fc.consultant_id] = {
            }  # Empty dict for missions
        financialConditions[fc.consultant_id][fc.mission_id] = fc.daily_rate

    # Collect data for done work according to timesheet data
    for ts in Timesheet.objects.filter(
            working_date__lt=today,
            working_date__gt=start_date,
            mission__nature="PROD").select_related():
        kdate = ts.working_date.replace(day=1)
        if kdate not in tsData:
            tsData[kdate] = 0  # Create key
        tsData[kdate] += ts.charge * financialConditions.get(
            ts.consultant_id, {}).get(ts.mission_id, 0) / 1000

    # Collect data for forecasted work according to staffing data
    for staffing in Staffing.objects.filter(
            staffing_date__gte=today.replace(day=1),
            staffing_date__lt=end_date,
            mission__nature="PROD").select_related():
        kdate = staffing.staffing_date.replace(day=1)
        if kdate not in staffingData:
            staffingData[kdate] = 0  # Create key
            wStaffingData[kdate] = 0  # Create key
        staffingData[kdate] += staffing.charge * financialConditions.get(
            staffing.consultant_id, {}).get(staffing.mission_id, 0) / 1000
        wStaffingData[kdate] += staffing.charge * financialConditions.get(
            staffing.consultant_id,
            {}).get(staffing.mission_id,
                    0) * staffing.mission.probability / 100 / 1000

    # Set bottom of each graph. Starts if [0, 0, 0, ...]
    billKdates = billsData.keys()
    billKdates.sort()
    isoBillKdates = [a.isoformat() for a in billKdates
                     ]  # List of date as string in ISO format

    # Draw a bar for each state
    for state in ClientBill.CLIENT_BILL_STATE:
        ydata = [
            sum([float(i.amount) / 1000 for i in x if i.state == state[0]])
            for x in sortedValues(billsData)
        ]
        graph_data.append(zip(isoBillKdates, ydata))

    # Sort keys
    tsKdates = tsData.keys()
    tsKdates.sort()
    isoTsKdates = [a.isoformat()
                   for a in tsKdates]  # List of date as string in ISO format
    staffingKdates = staffingData.keys()
    staffingKdates.sort()
    isoStaffingKdates = [a.isoformat() for a in staffingKdates
                         ]  # List of date as string in ISO format
    wStaffingKdates = staffingData.keys()
    wStaffingKdates.sort()
    isoWstaffingKdates = [a.isoformat() for a in wStaffingKdates
                          ]  # List of date as string in ISO format

    # Sort values according to keys
    tsYData = sortedValues(tsData)
    staffingYData = sortedValues(staffingData)
    wStaffingYData = sortedValues(wStaffingData)

    # Draw done work
    graph_data.append(zip(isoTsKdates, tsYData))

    # Draw forecasted work
    graph_data.append(zip(isoStaffingKdates, staffingYData))
    graph_data.append(zip(isoWstaffingKdates, wStaffingYData))

    return render(
        request,
        "billing/graph_billing_jqp.html",
        {
            "graph_data": json.dumps(graph_data),
            "series_label": [i[1] for i in ClientBill.CLIENT_BILL_STATE],
            "series_colors": COLORS,
            # "min_date": min_date,
            "user": request.user
        })
예제 #6
0
파일: views.py 프로젝트: tuxella/pydici
def graph_billing_jqp(request):
    """Nice graph bar of incomming cash from bills
    @todo: per year, with start-end date"""
    billsData = defaultdict(list)  # Bill graph Data
    tsData = {}  # Timesheet done work graph data
    staffingData = {}  # Staffing forecasted work graph data
    wStaffingData = {}  # Weighted Staffing forecasted work graph data
    today = date.today()
    start_date = today - timedelta(24 * 30)  # Screen data about 24 month before today
    end_date = today + timedelta(6 * 30)  # No more than 6 month forecasted
    graph_data = []  # Data that will be returned to jqplot

    # Gathering billsData
    bills = ClientBill.objects.filter(creation_date__gt=start_date)
    if bills.count() == 0:
        return HttpResponse()

    for bill in bills:
        # Using first day of each month as key date
        kdate = bill.creation_date.replace(day=1)
        billsData[kdate].append(bill)

    # Collect Financial conditions as a hash for further lookup
    financialConditions = {}  # First key is consultant id, second is mission id. Value is daily rate
    # TODO: filter FC on timesheet date to forget old fc (perf)
    for fc in FinancialCondition.objects.filter(mission__nature="PROD"):
        if not fc.consultant_id in financialConditions:
            financialConditions[fc.consultant_id] = {}  # Empty dict for missions
        financialConditions[fc.consultant_id][fc.mission_id] = fc.daily_rate

    # Collect data for done work according to timesheet data
    for ts in Timesheet.objects.filter(working_date__lt=today, working_date__gt=start_date, mission__nature="PROD").select_related():
        kdate = ts.working_date.replace(day=1)
        if kdate not in tsData:
            tsData[kdate] = 0  # Create key
        tsData[kdate] += ts.charge * financialConditions.get(ts.consultant_id, {}).get(ts.mission_id, 0) / 1000

    # Collect data for forecasted work according to staffing data
    for staffing in Staffing.objects.filter(staffing_date__gte=today.replace(day=1), staffing_date__lt=end_date, mission__nature="PROD").select_related():
        kdate = staffing.staffing_date.replace(day=1)
        if kdate not in staffingData:
            staffingData[kdate] = 0  # Create key
            wStaffingData[kdate] = 0  # Create key
        staffingData[kdate] += staffing.charge * financialConditions.get(staffing.consultant_id, {}).get(staffing.mission_id, 0) / 1000
        wStaffingData[kdate] += staffing.charge * financialConditions.get(staffing.consultant_id, {}).get(staffing.mission_id, 0) * staffing.mission.probability / 100 / 1000

    # Set bottom of each graph. Starts if [0, 0, 0, ...]
    billKdates = billsData.keys()
    billKdates.sort()
    isoBillKdates = [a.isoformat() for a in billKdates]  # List of date as string in ISO format

    # Draw a bar for each state
    for state in ClientBill.CLIENT_BILL_STATE:
        ydata = [sum([float(i.amount) / 1000 for i in x if i.state == state[0]]) for x in sortedValues(billsData)]
        graph_data.append(zip(isoBillKdates, ydata))

    # Sort keys
    tsKdates = tsData.keys()
    tsKdates.sort()
    isoTsKdates = [a.isoformat() for a in tsKdates]  # List of date as string in ISO format
    staffingKdates = staffingData.keys()
    staffingKdates.sort()
    isoStaffingKdates = [a.isoformat() for a in staffingKdates]  # List of date as string in ISO format
    wStaffingKdates = staffingData.keys()
    wStaffingKdates.sort()
    isoWstaffingKdates = [a.isoformat() for a in wStaffingKdates]  # List of date as string in ISO format

    # Sort values according to keys
    tsYData = sortedValues(tsData)
    staffingYData = sortedValues(staffingData)
    wStaffingYData = sortedValues(wStaffingData)

    # Draw done work
    graph_data.append(zip(isoTsKdates, tsYData))

    # Draw forecasted work
    graph_data.append(zip(isoStaffingKdates, staffingYData))
    graph_data.append(zip(isoWstaffingKdates, wStaffingYData))

    return render(request, "billing/graph_billing_jqp.html",
                  {"graph_data": json.dumps(graph_data),
                   "series_label": [i[1] for i in ClientBill.CLIENT_BILL_STATE],
                   "series_colors": COLORS,
                   # "min_date": min_date,
                   "user": request.user})
예제 #7
0
def graph_leads_activity(request):
    """some graph and figures about current leads activity"""
    subsidiary = get_subsidiary_from_session(request)

    # lead stat
    current_leads = Lead.objects.active()
    if subsidiary:
        current_leads = current_leads.filter(subsidiary=subsidiary)
    leads_state_data = leads_state_stat(current_leads)

    leads = Lead.objects.all()
    if subsidiary:
        leads = leads.filter(subsidiary=subsidiary)

    # lead creation rate per week
    first_lead_creation_date = leads.aggregate(Min("creation_date")).get(
        "creation_date__min", datetime.now()).date()
    today = date.today()
    lead_creation_rate_data = []
    max_creation_rate = 0
    for timeframe in (30, 30 * 6, 365):
        start = today - timedelta(timeframe)
        if start > first_lead_creation_date:
            rate = 7 * leads.filter(
                creation_date__gte=start).count() / timeframe
            rate = round(rate, 2)
            lead_creation_rate_data.append(
                [_("Last %s days") % timeframe, rate])
            max_creation_rate = max(rate, max_creation_rate)

    # lead duration
    d_leads = leads.filter(creation_date__gt=(datetime.today() -
                                              timedelta(2 * 365)))
    d_leads = d_leads.annotate(
        timesheet_start=Min("mission__timesheet__working_date"))
    leads_duration = defaultdict(list)
    for lead in d_leads:
        end_date = lead.timesheet_start or lead.start_date or lead.update_date.date(
        )
        duration = (end_date - lead.creation_date.date()).days
        leads_duration[lead.creation_date.date().replace(
            day=1)].append(duration)

    leads_duration_per_month = to_int_or_round(
        [sum(i) / len(i) for i in sortedValues(leads_duration)], 1)
    leads_duration_data = [
        ["x"] + [d.isoformat() for d in sorted(leads_duration.keys())],
        [_("duration")] + leads_duration_per_month,
        [_("average duration 6 months")] +
        moving_average(leads_duration_per_month, 6, round_digits=1)
    ]

    return render(
        request, "leads/graph_leads_activity.html", {
            "leads_state_data": leads_state_data,
            "leads_state_title":
            _("%s leads in progress") % len(current_leads),
            "lead_creation_rate_data": json.dumps(lead_creation_rate_data),
            "max_creation_rate": max_creation_rate,
            "leads_duration_data": json.dumps(leads_duration_data),
            "user": request.user
        })
예제 #8
0
def graph_stat_bar(request):
    """Nice graph bar of incomming cash from bills
    @todo: per year, with start-end date"""
    billsData = defaultdict(list)  # Bill graph Data
    tsData = {}  # Timesheet done work graph data
    staffingData = {}  # Staffing forecasted work graph data
    wStaffingData = {}  # Weighted Staffing forecasted work graph data
    plots = []  # List of plots - needed to add legend
    today = date.today()
    start_date = today - timedelta(24 * 30)  # Screen data about 24 month before today
    end_date = today + timedelta(6 * 30)  # No more than 6 month forecasted
    colors = itertools.cycle(COLORS)

    # Setting up graph
    fig = Figure(figsize=(12, 8))
    fig.set_facecolor("white")
    ax = fig.add_subplot(111)

    # Gathering billsData
    bills = ClientBill.objects.filter(creation_date__gt=start_date)
    if bills.count() == 0:
        return print_png(fig)

    for bill in bills:
        # Using first day of each month as key date
        kdate = bill.creation_date.replace(day=1)
        billsData[kdate].append(bill)

    # Collect Financial conditions as a hash for further lookup
    financialConditions = {}  # First key is consultant id, second is mission id. Value is daily rate
    # TODO: filter FC on timesheet date to forget old fc (perf)
    for fc in FinancialCondition.objects.filter(mission__nature="PROD"):
        if not fc.consultant_id in financialConditions:
            financialConditions[fc.consultant_id] = {}  # Empty dict for missions
        financialConditions[fc.consultant_id][fc.mission_id] = fc.daily_rate

    # Collect data for done work according to timesheet data
    for ts in Timesheet.objects.filter(working_date__lt=today, working_date__gt=start_date, mission__nature="PROD").select_related():
        kdate = ts.working_date.replace(day=1)
        if kdate not in tsData:
            tsData[kdate] = 0  # Create key
        tsData[kdate] += ts.charge * financialConditions.get(ts.consultant_id, {}).get(ts.mission_id, 0) / 1000

    # Collect data for forecasted work according to staffing data
    for staffing in Staffing.objects.filter(staffing_date__gte=today.replace(day=1), staffing_date__lt=end_date, mission__nature="PROD").select_related():
        kdate = staffing.staffing_date.replace(day=1)
        if kdate not in staffingData:
            staffingData[kdate] = 0  # Create key
            wStaffingData[kdate] = 0  # Create key
        staffingData[kdate] += staffing.charge * financialConditions.get(ts.consultant_id, {}).get(ts.mission_id, 0) / 1000
        wStaffingData[kdate] += staffing.charge * financialConditions.get(ts.consultant_id, {}).get(ts.mission_id, 0) * staffing.mission.probability / 100 / 1000

    # Set bottom of each graph. Starts if [0, 0, 0, ...]
    billKdates = billsData.keys()
    billKdates.sort()
    bottom = [0] * len(billKdates)

    # Draw a bar for each state
    for state in ClientBill.CLIENT_BILL_STATE:
        ydata = [sum([i.amount / 1000 for i in x if i.state == state[0]]) for x in sortedValues(billsData)]
        b = ax.bar(billKdates, ydata, bottom=bottom, align="center", width=15,
               color=colors.next())
        plots.append(b[0])
        for i in range(len(ydata)):
            bottom[i] += ydata[i]  # Update bottom

    # Sort keys
    tsKdates = tsData.keys()
    tsKdates.sort()
    staffingKdates = staffingData.keys()
    staffingKdates.sort()
    wStaffingKdates = staffingData.keys()
    wStaffingKdates.sort()
    # Sort values according to keys
    tsYData = sortedValues(tsData)
    staffingYData = sortedValues(staffingData)
    wStaffingYData = sortedValues(wStaffingData)
    # Draw done work
    plots.append(ax.plot(tsKdates, tsYData, '-o', ms=10, lw=4, color="green"))
    for kdate, ydata in tsData.items():
        ax.text(kdate, ydata + 5, int(ydata))
    # Draw forecasted work
    plots.append(ax.plot(staffingKdates, staffingYData, ':o', ms=10, lw=2, color="magenta"))
    plots.append(ax.plot(wStaffingKdates, wStaffingYData, ':o', ms=10, lw=2, color="cyan"))

    # Add Legend and setup axes
    kdates = list(set(tsKdates + staffingKdates))
    ax.set_xticks(kdates)
    ax.set_xticklabels([d.strftime("%b %y") for d in kdates])
    if tsYData:
        ax.set_ylim(ymax=max(int(max(bottom)), int(max(tsYData))) + 10)
    ax.set_ylabel(u"k€")
    ax.legend(plots, [i[1] for i in ClientBill.CLIENT_BILL_STATE] + [_(u"Done work"), _(u"Forecasted work"), _(u"Weighted forecasted work")],
              bbox_to_anchor=(0., 1.02, 1., .102), loc=4,
              ncol=4, borderaxespad=0.)
    ax.grid(True)
    fig.autofmt_xdate()

    return print_png(fig)