Exemple #1
0
def new_budget_view(request):
    if request.method == 'POST':
        form = BudgetForm(request.POST)
        if form.is_valid():
            amount = form.cleaned_data['budget_amount']
            weekly = form.cleaned_data['is_weekly']
            month = datetime.today().month
            year = datetime.today().year
            end_date = datetime.today()
            if weekly:
                today = datetime.today().weekday()
                difference = 6 - today
                delta = timedelta(days=difference)
                end_date = end_date + delta
            else:
                end_day = calendar.monthrange(year, month)[1]
                end_date = date(year, month, end_day)

            model = BudgetModel(user_account=request.user,
                                budget_amount=amount,
                                is_weekly=weekly,
                                budget_month=month,
                                budget_year=year,
                                end_date=end_date)
            model.save()
            return HttpResponseRedirect('/accounts/profile')

    context = RequestContext(request)
    context['form'] = BudgetForm()
    context.update(csrf(request))
    return render(request, 'budget/newbudget.html', context)
Exemple #2
0
def item(request, budget_id):
    budget = get_object_or_404(Budget, id=budget_id)

    if request.method == 'GET':
        form = BudgetForm(instance=budget)
    elif request.method == 'POST':
        form = BudgetForm(data=request.POST, instance=budget)
        if form.is_valid():
            data = form.cleaned_data
            form.save()
            budget.update_budgetlines()

            sum_natures = 0
            for n in ['fo', 'mi', 'sa', 'eq']:
                if n in data and data[n]:
                    sum_natures += data[n]

            if sum_natures > budget.get_amount_left():
                error_msg(
                    request,
                    u"Montant disponible insuffisant pour cette répartition.")
            else:
                for nature in ['fo', 'mi', 'sa', 'eq']:
                    if data[nature] or data[nature] == 0:
                        sub_budget, created = Budget.objects.get_or_create(
                            team=budget.team,
                            name="%s - %s" % (budget.name, nature.upper()),
                            default_origin=budget.default_origin,
                            budget_type=budget.budget_type,
                            tva_code=budget.tva_code,
                            domain=budget.domain,
                            default_nature=nature.upper())
                        if data[nature] > 0:
                            bl = sub_budget.credit(data[nature])
                            bl.product = u"Répartition"
                            bl.save()

                            bl = budget.debit(data[nature])
                            bl.product = u"Répartition vers %s" % nature.upper(
                            )
                            bl.save()

                # if budget.get_amount_left() == 0:
                #   budget.is_active = False
                #   budget.save()
                #   for bl in BudgetLine.objects.filter( budget_id = budget.id ):
                #       bl.is_active = False
                #       bl.save()
                #   info_msg( request, "Budget modifié avec succès. Il a été automatiquement archivé car son montant dispo est égal à 0.")
                # else:
                info_msg(request, "Budget modifié avec succès.")
                return redirect('budgets')
    else:
        return redirect('error')

    return render(request, 'budget/item.html', {
        'budget': budget,
        'form': form
    })
Exemple #3
0
def post_budget(request):
    if Budget.objects.last():
        budget_info = Budget.objects.last()
    else:
        budgetform = BudgetForm()

    if request.user.username:
        if request.method == "POST":
            author = Budget(author=request.user)
            budgetform = BudgetForm(request.POST, instance=author)
            if budgetform.is_valid():
                author.save()
                return redirect("/profile/")

            else:
                budgetform = BudgetForm(instance=budget_info)

            return render(request, 'expenses.html', {'budgetform': budgetform})
Exemple #4
0
def new(request):
    if request.method == 'GET':
        form = BudgetForm()
    elif request.method == 'POST':
        form = BudgetForm(data=request.POST)
        if form.is_valid():
            data = form.cleaned_data
            if data['all_natures'] or data["all_natures"] == 0:
                budget = form.save()
                if data['all_natures'] > 0:
                    bl = budget.credit(data["all_natures"])
                    bl.product = u"Initial"
                    bl.save()
            else:
                for nature in ['fo', 'mi', 'sa', 'eq']:
                    if data[nature] or data[nature] == 0:
                        budget = Budget.objects.create(
                            team=data['team'],
                            name="[%s] %s [%s] - %s" %
                            (data['team'].shortname, data['name'],
                             data['default_origin'], nature.upper()),
                            default_origin=data['default_origin'],
                            budget_type=data['budget_type'],
                            tva_code=data['tva_code'],
                            domain=data['domain'],
                            default_nature=nature.upper())
                        if data[nature] > 0:
                            bl = budget.credit(data[nature])
                            bl.product = u"Initial"
                            bl.save()

            info_msg(request, "Budget ajouté avec succès.")
            return redirect('budgets')
    else:
        return redirect('error')

    return render(request, 'budget/form.html', {'form': form})
Exemple #5
0
def expenses_page(request):
    if request.user.username:
        author_id = request.user.id
        user_expenses = Expense.objects.filter(
            author=author_id).order_by("-expense_date")
        user_name = request.user.username

        # ----------- CHARTS ------------

        # Expense pie chart
        food_amount = Expense.objects.filter(expense_type="food").\
            filter(author=author_id).aggregate(Sum("amount"))
        personal_amount = Expense.objects.filter(expense_type="personal").\
            filter(author=author_id).aggregate(Sum("amount"))
        transportation_amount = Expense.objects.filter(expense_type="transportation").\
            filter(author=author_id).aggregate(Sum("amount"))
        housing_amount = Expense.objects.filter(expense_type="housing").\
            filter(author=author_id).aggregate(Sum("amount"))
        other_amount = Expense.objects.filter(expense_type="other").\
            filter(author=author_id).aggregate(Sum("amount"))

        # Names of the pie chart segments
        groups = ["Food", "Personal", "Transportation", "Housing", "Other"]

        # Amounts of the pie chart segments
        amounts = [
            food_amount["amount__sum"], personal_amount["amount__sum"],
            transportation_amount["amount__sum"],
            housing_amount["amount__sum"], other_amount["amount__sum"]
        ]

        # Segment colors
        # colors = ["#C0ECCC", "#F6A8A6", "#F9F0C1", "#A5C8E4", "#F4CDA6"]  # Pastel colors
        colors = ["#5cb85c", "#d9534f", "#f5e83b", "#0275d8",
                  "#f0ad4e"]  # Bootstrap colors

        # Custom '$'
        text = ["$", "$", "$", "$", "$"]

        # The plot creator
        pie_plot = Figure(
            Pie(
                labels=groups,
                values=amounts,
                hoverinfo="text+value",
                text=text,
                textinfo="label+percent",
                textfont=dict(size=15),
                hole=.3,
                marker=dict(colors=colors, line=dict(color="#000000",
                                                     width=3)),
            ))

        pie_plot.update_layout(
            legend=dict(orientation="v", ),
            title={
                'text': "Overall Expenses per Type (% / $)",
                'y': 0.9,
                'x': 0.5,
                'xanchor': 'center',
                'yanchor': 'top',
            },
            # showlegend=False,
        )

        # This is needed to view the plot in a localized setting (not online)
        plot_div = plot(pie_plot, output_type="div")

        # Line Plot
        # Pandas dataframe of expense model
        expense_user_data = Expense.objects.filter(
            author=author_id).all().values()
        data = pd.DataFrame(expense_user_data)
        # Converting my dates to accepted Pandas datetime
        data["expense_date"] = pd.to_datetime(data["expense_date"])
        # Indexing via date
        data.set_index("expense_date", inplace=True)
        # Sorting by date
        data = data.sort_values(by=["expense_date"])
        # Converting data from daily to weekly and summing the amounts per week
        scatter_plot_data = data.resample("W-MON").agg({
            "amount":
            "sum",
            "expense_type":
            " - ".join
        })

        if Budget.objects.filter(author=author_id).last():
            budget_data = Budget.objects.filter(author=author_id).last()
            budget_line = budget_data.weekly_spending_total
        else:
            budget_line = None

        trace_wk_tot = Scatter(x=scatter_plot_data.index,
                               y=scatter_plot_data.amount,
                               mode="lines+markers",
                               name="lines+markers",
                               line=dict(
                                   color="#5cb85c",
                                   width=4,
                               ),
                               marker=dict(size=12, ))

        expense_weekly_data = [
            trace_wk_tot
        ]  # This format in case adding additional traces

        line_plot = Figure(expense_weekly_data)  # Line plot instance

        # Total Budget per week line for comparison
        if budget_line:
            line_plot.add_shape(
                type="line",
                x0=scatter_plot_data.index.min(),
                y0=budget_line,
                x1=scatter_plot_data.index.max(),
                y1=budget_line,
                line=dict(
                    color="#d9534f",
                    width=2,
                    dash="dash",
                ),
            )

        line_plot.update_layout(
            xaxis_title="Time (Weeks)",
            yaxis_title="Total Spent ($)",
            font=dict(size=14, ),
            yaxis_tickformat="$",
            title={
                'text': "Total Expenses per Week",
                'y': 0.9,
                'x': 0.5,
                'xanchor': 'center',
                'yanchor': 'top',
            },
            yaxis={"rangemode": "tozero"},
        )
        plot_div_line = plot(line_plot, output_type="div")

        # Bar Chart
        # Gather data: each expense type and associated budget limit via Pandas
        # expense_type filters
        food_filter = (data["expense_type"] == "food")
        personal_filter = (data["expense_type"] == "personal")
        transportation_filter = (data["expense_type"] == "transportation")
        housing_filter = (data["expense_type"] == "housing")
        other_filter = (data["expense_type"] == "other")

        # expense_date (Current Week) filter
        previous_monday = date.today() - timedelta(days=date.today().weekday())
        next_monday = previous_monday + timedelta(weeks=1)

        week_filter = ((data.index >= pd.to_datetime(previous_monday)) &
                       (data.index < pd.to_datetime(next_monday)))

        # Split Current Week data up into expense_type
        # Pulls the "amount" data based on the above filters and then sums them for the week
        week_food_amt = data["amount"].loc[week_filter & food_filter].sum()
        week_personal_amt = data["amount"].loc[week_filter
                                               & personal_filter].sum()
        week_transportation_amt = data["amount"].loc[
            week_filter & transportation_filter].sum()
        week_housing_amt = data["amount"].loc[week_filter
                                              & housing_filter].sum()
        week_other_amt = data["amount"].loc[week_filter & other_filter].sum()

        spending_array = [
            week_food_amt, week_personal_amt, week_transportation_amt,
            week_housing_amt, week_other_amt
        ]

        # Budget Type Limits
        if Budget.objects.filter(author=author_id).last():
            budget_data = Budget.objects.filter(author=author_id).last()

            budget_food = budget_data.weekly_food
            budget_personal = budget_data.weekly_personal
            budget_transportation = budget_data.weekly_transportation
            budget_housing = budget_data.weekly_housing
            budget_other = budget_data.weekly_other
        else:
            budget_food = None
            budget_personal = None
            budget_transportation = None
            budget_housing = None
            budget_other = None

        budget_array = [
            budget_food, budget_personal, budget_transportation,
            budget_housing, budget_other
        ]

        # Graph the bar chart
        types = ["Food", "Personal", "Transport", "Housing", "Other"]

        bar_trace = [
            Bar(name="Expense Totals",
                x=types,
                y=spending_array,
                marker_color=colors,
                text=spending_array,
                textposition="auto",
                showlegend=False),
            Bar(name="Budget Limits",
                x=types,
                y=budget_array,
                marker_color="#cfb3ff")
        ]

        bar_chart = Figure(bar_trace)
        bar_chart.update_layout(
            barmode="group",
            yaxis_title="Total Spent ($)",
            yaxis_tickformat="$",
            title={
                'text': "Total Expenses vs Budget Limits per Week",
                'y': 0.9,
                'x': 0.5,
                'xanchor': 'center',
                'yanchor': 'top',
            },
            legend=dict(orientation="h", ),
            # showlegend=False,
        )

        # Add the chart to the context and plot in html
        plot_div_bar = plot(bar_chart, output_type="div")

        # Budget Form Instance
        if Budget.objects.last():
            budget_info = Budget.objects.last()
            budgetform = BudgetForm(instance=budget_info)
        else:
            budgetform = BudgetForm()


# Update Expense Form
        if Expense.objects.last():
            # expense_info = Expense.objects.get(id=pk)
            # expenseform = ExpenseForm(instance=expense_info)
            expenseform = ExpenseForm()
        else:
            expenseform = ExpenseForm()

        context = {
            "user_expenses": user_expenses,
            "user_name": user_name,
            "plot_div": plot_div,
            "plot_div_line": plot_div_line,
            "plot_div_bar": plot_div_bar,
            "budgetform": budgetform,
            "expenseform": expenseform,
            "current_date": datetime.now().date(),
        }
        return render(request, "expenses/expenses.html", context)

    else:
        return HttpResponseRedirect("/signup")