Пример #1
0
def expense_edit(request, pk):
    expense = get_object_or_404(Expense, pk=pk, user=request.user)
    if expense.is_bill:
        return HttpResponseRedirect(expense.get_absolute_url())
    form = ExpenseForm(instance=expense, user=request.user)

    if request.method == "POST":
        form = ExpenseForm(request.POST, instance=expense, user=request.user)
        if form.is_valid():
            expense = form.save(commit=False)
            expense.user = request.user
            expense.is_bill = False
            expense.save()
            form.save_m2m()
            return HttpResponseRedirect(expense.get_absolute_url())

    return render(
        request,
        "expenses/expense_add_edit.html",
        {
            "htmltitle": str(expense),
            "pid": "expense_edit",
            "expense": expense,
            "form": form,
            "mode": "edit",
        },
    )
Пример #2
0
    def post(self, request):
        form = ExpenseForm(request.POST)
        jsonstr = request.POST['json_string']
        if form.is_valid():
            exp_date = form.cleaned_data['date']
            comment = form.cleaned_data['comment']
            total_cost = form.cleaned_data['total']
        else:
            return HttpResponse('invalid form')

        expense_dict = json.loads(jsonstr)
        self.context['expense_form'] = ExpenseForm()
        try:
            category = Category.objects.filter(name=expense_dict['category'])[0]
            itm = None
            qty= None
            cst=None
            for item in expense_dict['items']:
                itm_name = str(list(item.keys())[0])
                itm = Item.objects.all().filter(name=itm_name)[0]

                qty = float(item[itm_name]['quantity'])
                cst = int(item[itm_name]['cost'])
                if qty==0 or cst==0:
                    self.context['message'] = 'Zero value for some items'
                    return render(request, 'expenses/index.html', self.context)
                                
            expenses = Expense.objects.filter(date=exp_date, category=category)
            expense=None
            if len(expenses) == 0: # means no expense yet for the day on the same category
                expense = Expense(date=exp_date, category=category, comment=comment, cost=total_cost)
                expense.save()
            else: # already exists, add total
                expense = expenses[0]
                expense.cost+=total_cost
                expense.comment+='<br>'+comment
                expense.save()
            # save the item expense ( as it depends on expense)
            if len(expense_dict['items']) > 0:
                itm_exp = ItemExpense(expense=expense, item=itm, 
                            quantity=qty, cost=cst)
                itm_exp.save()

            self.context['message'] = 'Expense added'
            return render(request, 'expenses/index.html', self.context)
        except Exception as e:
            return HttpResponse(repr(e))
Пример #3
0
def expense(request, id=0):
    """ Get or Create/Update an expense """

    status = 400
    expense = None
    errors = {}

    if request.method == 'PUT':
        data = json.loads(request.body)
        expense = get_object_or_404(Expense, pk=id, user=request.user)
        form = ExpenseForm(data, instance=expense)
        if form.is_valid():
            balance = Balance.objects.get(user=request.user)
            # Reset balance because we're updating an expense.
            balance.amount -= expense.amount

            form.save()
            balance.amount += expense.amount
            balance.save()
            status = 200
        else:
            errors = {'errors':form.errors}
    elif request.method == 'POST':
        data = json.loads(request.body)
        form = ExpenseForm(data)
        if form.is_valid():
            form.cleaned_data['user'] = request.user
            expense = Expense(**form.cleaned_data)
            expense.save()
            try:
                balance = Balance.objects.get(user=request.user)
            except Balance.DoesNotExist:
                # This user doesn't have a balance yet, create one.
                balance = Balance.objects.create(amount=0.0, user=request.user)

            balance.amount += expense.amount
            balance.save()
            status = 201
        else:
            errors = {'errors':form.errors}
    elif request.method == 'DELETE':
        expense = get_object_or_404(Expense, pk=id, user=request.user)
        try:
            # Make sure to update balance depending on the transaction type.
            balance = Balance.objects.get(user=request.user)
            balance.amount -= expense.amount
            balance.save()
            expense.delete()
        except:
            status = 500
        return HttpResponse(status=status)
    else:
        try:
            expense = get_object_or_404(Expense, pk=id)
        except Expense.DoesNotExist:
            logging.error('expense does not exist: ' + id)
            status = 404

    response = errors if errors else serialize(expense, ignore=[auth.models.User])
    return HttpResponse(content=json.dumps(response), status=status, content_type='application/json')
Пример #4
0
def create(request):
    if request.method == 'POST':
        form = ExpenseForm(request.POST)
        if form.is_valid():
            expense = form.save()
            expense.payment = constants.CASH
            expense.save()
            messages.success(request, 'Expense created')
            return redirect('expenses:create')
    else:
        form = ExpenseForm()
    context = {
        'form': form,
    }

    return render(
        request,
        'expenses/create.html',
        context)
Пример #5
0
def create(request):
	""" Create an expense. Update the current Balance. """

	status = 201
	form = ExpenseForm(request.POST)
	if form.is_valid():
		expense = form.save()
		try:
			balance = Balance.objects.get(pk=1)
		except Balance.DoesNotExist:
			# We're just now starting the app or something happened to the db, create the expense record.
			balance = Balance.objects.create(amount=0.0)

		balance.amount += expense.amount
		balance.save()
	else:
		status = 500
		logging.error(form.errors)
	return HttpResponse(status=status)
Пример #6
0
def new_expense(request):
    if request.method == 'POST':
        form = ExpenseForm(request.POST)
        if form.is_valid():
            form.save()
            request.user.message_set.create(message="Expense added!")
            return redirect('expense_new')
    else:
        form = ExpenseForm()
    return render(request, 'expenses/expense.html', {'form': form})
Пример #7
0
def update(request, id):
	status = 201
	expense = get_object_or_404(Expense, pk=id)

	old_amount = expense.amount
	form = ExpenseForm(request.POST, instance=expense)
	if form.is_valid():
		new_expense = form.save()
		try:
			balance = Balance.objects.get(pk=1)
		except Balance.DoesNotExist:
			logging.error('Missing Balance record. What happened? Panic!')
			status = 500
		else:
			balance.amount -= old_amount
			balance.amount += new_expense.amount
			balance.save()
	else:
		logging.error(form.errors)
		status = 500
	return HttpResponse(status=status)
Пример #8
0
    def test_create_form(self):
        form_data = {}
        form = ExpenseForm(data=form_data)
        self.assertFalse(form.is_valid())

        form_data = {
            'amount': Decimal('10.12'),
            'date': datetime.now().strftime('%Y-%m-%d'),
            'description': 'Testing expense',
            'category': self.category.id,
        }
        form = ExpenseForm(data=form_data)
        self.assertTrue(form.is_valid())
        self.assertEqual(Expense.objects.count(), 1)
        form.save()
        self.assertEqual(Expense.objects.count(), 2)
def expense_add(request):
    form = ExpenseForm(user=request.user)
    if request.method == "POST":
        form = ExpenseForm(request.POST, user=request.user)
        if form.is_valid():
            inst = form.save(commit=False)
            inst.user = request.user
            inst.is_bill = False
            inst.save()
            form.save_m2m()
            return HttpResponseRedirect(reverse("expenses:expense_list"))

    return render(
        request,
        "expenses/expense_add_edit.html",
        {"htmltitle": _("Add an expense"), "pid": "expense_add", "form": form, "mode": "add",},
    )
Пример #10
0
def create(request):
    if request.method == "POST":
        form = ExpenseForm(request.POST)
        if form.is_valid():
            o = form.save()
            return redirect(reverse("expenses:detail", args=(o.id, )))
    else:
        form = ExpenseForm()

    return render(request, "expenses/expense_form.html", {
        'form': form,
    })
Пример #11
0
def update(request, id):
    o = get_object_or_404(models.Expense, id=id, user=request.user)
    if request.method == "POST":
        form = ExpenseForm(request.POST, request.FILES, instance=o)
        if form.is_valid():
            o = form.save()
            return redirect(reverse("expenses:detail", args=(o.id,)))
    else:
        form = ExpenseForm(instance=o)

    return render(request, "expenses/expense_form.html", {
        'form': form,
    })
Пример #12
0
def dashboard(request):
    msg = ''
    form = ExpenseForm()
    if request.method == 'POST':
        form = ExpenseForm(request.POST)
        if form.is_valid():
            expenses = Expenses()
            expenses.client = request.user
            expenses.title = form.cleaned_data['title']
            expenses.description = form.cleaned_data['description']
            expenses.amount = form.cleaned_data['amount']
            expenses.currency = form.cleaned_data['currency']
            expenses.date = form.cleaned_data['date']
            expenses.save()
            form = ExpenseForm()
            msg = 'Expense added successfully'
    return render(request, 'dashboard.html', {'form': form, 'msg': msg})
Пример #13
0
def create(request):
    if request.method == "POST":
        form = ExpenseForm(request.POST)
        if form.is_valid():
            o = form.save()
            return redirect("expenses:detail", id=o.id)
    else:
        # method = GET
        form = ExpenseForm()

    d = {
        'form': form,
    }
    return render(request, "expenses/form.html", d)
Пример #14
0
def update_expense(request, pk):
    expense_info = Expense.objects.get(id=pk)
    expenseform = ExpenseForm(instance=expense_info)

    if request.user.username:
        if request.method == "POST":
            expenseform = ExpenseForm(request.POST, instance=expense_info)
            if expenseform.is_valid():
                expenseform.save()
                return redirect("/profile/")

        else:
            context = {
                "expenseform": expenseform,
                "current_date": datetime.now().date(),
                "expense_info": expense_info,
            }
            return render(request, "expenses/update_expense.html", context)
Пример #15
0
def create(request):
    if request.method == 'POST':
        form = ExpenseForm(request.POST)
        if form.is_valid():
            expense = form.save()
            expense.payment = constants.CASH
            expense.save()
            messages.success(request, 'Expense created')
            return redirect('expenses:create')
    else:
        form = ExpenseForm()
    context = {
        'form': form,
    }

    return render(request, 'expenses/create.html', context)
Пример #16
0
    def test_create_form(self):
        form_data = {}
        form = ExpenseForm(data=form_data)
        self.assertFalse(form.is_valid())

        form_data = {
            'amount': Decimal('10.12'),
            'date': datetime.now().strftime('%Y-%m-%d'),
            'description': 'Testing expense',
            'category': self.category.id,
        }
        form = ExpenseForm(data=form_data)
        self.assertTrue(form.is_valid())
        self.assertEqual(Expense.objects.count(), 1)
        form.save()
        self.assertEqual(Expense.objects.count(), 2)
Пример #17
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")