From dd65b220bd652b4a1af9289ad623cb3649b06e7a Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 10 Jan 2026 17:02:25 +0000 Subject: [PATCH] 01 --- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 1105 bytes core/__pycache__/forms.cpython-311.pyc | Bin 0 -> 855 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 2217 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 2039 bytes core/admin.py | 12 +- core/forms.py | 7 + core/migrations/0001_initial.py | 39 +++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 2201 bytes core/models.py | 27 +- core/templates/base.html | 44 +++- core/templates/core/index.html | 237 +++++++----------- core/views.py | 57 +++-- static/css/custom.css | 60 ++++- staticfiles/css/custom.css | 71 ++++-- 14 files changed, 367 insertions(+), 187 deletions(-) create mode 100644 core/__pycache__/forms.cpython-311.pyc create mode 100644 core/forms.py create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cd6f855b12f4883b1ba9de01c54245c53aacd714..40d07e7f361ab850166b005ed98eb17cc710a9f0 100644 GIT binary patch literal 1105 zcma)4J5Ss|5Z+zecfJ>pa3lu`1SwFs2v?;_6e)^GiiB&@xv`9Q0TVwiYg^&EEBFC) z`~#whpAjiFNLO68LP|w<2r8<~_%PyCWNm+*-I@J%=G*zvXjBP|KfCMxAtmH5PKr^w zGR}X4u}?VRG$0|hDJ7h7EnuN$YoTuIlrSRbwoz;p+5vDO-*_FKe;zjH`)l~fsUq~@y63=s zr)~yyYqr64sNGQYE7``S8%pOOs4~4m){+~>kTk4hQi{myDWmK5gtT90#{RaJu96G0-e*Cn>HGNssrn-fx1*U*tuv%9co9@E(YogFbo z7e?eh?5z%(OK0e~KseI~o4bxT37g7U%Ez=dpsf+p=<(dOIRgvcgRqZ5IFcROt@8y3_=($)?+AAnhP`VNhfF*Bxk}4xW~AP` zqe5n-jEu3tHqz`B%4ZVS-wE{_V=3%)=r(t%I>&X zr!IYJ6;0GS!p_iE0}@sU9=FHp32}|p8gacA=z_{EgntR9mgRh4Q@9^*n)BNSv?c{b zr>VK(FwAhO^n$e8Or|trTG*yB(e0X2y5-ILn`Xvu)N^#D2Uf-iQ_dKh!1}nmCh%l}u8XDw2eJ$PCrxiY$>3Ss+w?La4%| zO=W1j2dlk;S5PG!XoW#5@;_P;8eJi|*dZF_BtKHODKj15lr@L(+F-HZGu)`Z4B|7w zNJXNg5(*I}pEyA!8aj~oLf{I#f+}IEJRz0Hi9=)aQQ?FiE9gzOZu9L!3YM$6ke{gQ zTbjwN_2z~jX<5d@7OP3ab>WLV9=U%O;2C*LFmQt4SW+1eV(E4E621;I?>lIaJ<88+ z*mXABs7$Bz-j0;He0hfn-#IhH@5w#ra4WnX**|!9_9xlQCQEx z3vH9GdhY4A8=LIo{v(kadfd;z%t_>^RFP>2{FIN<$Lro@P2EonM1wiyoZ`nc4G*Dd zenQj0tCop;O4A;;baOCs?h)fv+hIbpVYaw#z9byu!p{Ks3a-r219aE90MI`Eb>IKk zjZKM1*j$A9axTUv;LFb=pasWZ`|-kt&gTtgQl7*?6#)(SB*O8YJc1&E0da_WWi`ZG6qqm#VhC2zEgJw*y%?2%)LNZ}b2$KfrGy*p(>Y>%6c+yQ!k)W@7T zxr22mv7g}{Ad8jFVfjI+QTad_%TmZ+(7_82h=!Sb5E;{n1v>Ge4oiRqhA5ze=$LkD zOgjzQcvq)utAREKH=sShR|B4q%6q{qUT;7&b`al#lfD|}9;uw838=yenuLr?`O(r= zgINyC$xvo;VR30kE!d`AuNu0QU1E;y;CN|m*$4Zx>1{qUKUX5mQliGq4@MgzyP~ zpO}Y!Wvp9w*mh8EespPhakW%f<=0RLbKj2^=2i-G#gZRx=-Z6@@gkg1tcK3}@m03f z3}in^nN#CNqiNWdDDJVkzKp9Pq~Ue`063}ZUPzgY^vDogWuliNXFk}y=cTjzU;Xyb zP0w}Gb6$F`J>ONY>^}0;EBl|i*XLbzp`$K%>O%WgSIy#h_QmAudvCsR)nZ32dTJ3S zQq#NhUTXSBx_|$`a#J@usheKvX1mlKG?Pwp+DlHii`~rC?>_P}SNA8}Oum!JdzpOu z4z`vh37g4jDEbB-s+^1Zak{Bn>vo=2Mffib#8v{6UEDhVSA(r|5V= zct%5Z6#GIn?l1Z0um$F=^8-LnmL#c5F1w>om&~}MPfv+T&;$PsyN{keev9MpP9`&| VghxCbcke$n-v)E<{zD@O#owZY{i6T? literal 209 zcmZ3^%ge<81S>LrWmp2~#~=<2FhLogg@BCd3@HpLj5!Rsj8Tk?3@J>(44TX@K?*b( zZ?Wa(r=;c-`)M-W;!Md(%uCPLOGzqX21>4E_zY6>OHV%|KQ~psG^sSNq*On(A~m_R zB)>?%JijQrxF9h(RX;huC{-U~j9x+IFAf_ZyEG@&u80Guoe_wOWr4&8W=2NF8w@fR Ku%RM0pb7xTsWln^ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 6867ddf286a519cf1754ac97038f9f1e4605fbf2..3977a45e81a77f46835c29c31f474f9f46399217 100644 GIT binary patch literal 2039 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 literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 71a8362..7780abd 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,28 @@ from django.db import models +from django.contrib.auth.models import User -# Create your models here. +class Category(models.Model): + name = models.CharField(max_length=100, unique=True) + + def __str__(self): + return self.name + + class Meta: + verbose_name_plural = "Categories" + +class Expense(models.Model): + CURRENCY_CHOICES = [ + ('COP', 'Colombian Pesos'), + ('EUR', 'Euros'), + ('USD', 'US Dollars'), + ] + + amount = models.DecimalField(max_digits=10, decimal_places=2) + currency = models.CharField(max_length=3, choices=CURRENCY_CHOICES) + category = models.ForeignKey(Category, on_delete=models.PROTECT) + payer = models.ForeignKey(User, on_delete=models.CASCADE) + date = models.DateField() + description = models.TextField(blank=True) + + def __str__(self): + return f'{self.amount} {self.currency} - {self.category} - {self.date}' \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..38d947a 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,9 +1,10 @@ - + - {% block title %}Knowledge Base{% endblock %} + + {% block title %}Gastos Familiares{% endblock %} {% if project_description %} @@ -13,13 +14,50 @@ {% endif %} + + + + + + {% load static %} + {% block head %}{% endblock %} - {% block content %}{% endblock %} + + +
+ {% block content %}{% endblock %} +
+ + + + diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..d2e428d 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,102 @@ -{% extends "base.html" %} +{% extends 'base.html' %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Inicio - Gastos Familiares{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+
+

Agregar Nuevo Gasto

+
+ {% csrf_token %} +
+ {{ form.payer.label_tag }} + {{ form.payer }} +
+
+ {{ form.amount.label_tag }} + {{ form.amount }} +
+
+ {{ form.currency.label_tag }} + {{ form.currency }} +
+
+ {{ form.category.label_tag }} + {{ form.category }} +
+
+ {{ form.description.label_tag }} + {{ form.description }} +
+
+ {{ form.date.label_tag }} + {{ form.date }} +
+ +
+
+
+
+
+

Tus Gastos Recientes

+ +
+
+ +
+
+ +
+
+ +
+
+ + {% if expenses %} +
    + {% for expense in expenses %} +
  • +
    + {{ expense.category }} - {{ expense.description }} + ({{ expense.date|date:"d/m/Y" }}) +
    + ${{ expense.amount }} +
  • + {% endfor %} +
+ {% else %} + + {% endif %} +
+
+

Análisis de Gastos

+
+
+
Total de Gastos
+

${{ total_expenses|floatformat:2 }}

+
+
+ +
Gastos por Categoría
+
    + {% for item in category_summary %} +
  • + {{ item.category__name }} + ${{ item.total|floatformat:2 }} +
  • + {% endfor %} +
+
+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
- -{% endblock %} \ No newline at end of file + +{% endblock %} diff --git a/core/views.py b/core/views.py index c9aed12..68a0713 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,38 @@ -import os -import platform - -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone - +from django.shortcuts import render, redirect +from .forms import ExpenseForm +from .models import Expense, Category +from django.db.models import Sum def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + """Render the landing screen and handle expense form submission.""" + if request.method == 'POST': + form = ExpenseForm(request.POST) + if form.is_valid(): + form.save() + return redirect('home') + else: + form = ExpenseForm() + + expenses = Expense.objects.all() + + # Filtering logic + category_id = request.GET.get('category') + if category_id: + expenses = expenses.filter(category_id=category_id) + + expenses = expenses.order_by('-date') + + # Analysis + total_expenses = expenses.aggregate(Sum('amount'))['amount__sum'] or 0 + category_summary = expenses.values('category__name').annotate(total=Sum('amount')).order_by('-total') + + categories = Category.objects.all() + + return render(request, "core/index.html", { + 'form': form, + 'expenses': expenses, + 'categories': categories, + 'total_expenses': total_expenses, + 'category_summary': category_summary, + }) - context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), - } - return render(request, "core/index.html", context) diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..b095735 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,58 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --bs-primary: #0D47A1; + --bs-secondary: #42A5F5; + --bs-accent: #FFC107; + --bs-background: #F5F5F5; + --bs-text: #212121; } + +body { + font-family: 'Roboto', sans-serif; + background-color: var(--bs-background); + color: var(--bs-text); + display: flex; + flex-direction: column; + min-height: 100vh; +} + +h1, h2, h3, h4, h5, h6, .navbar-brand { + font-family: 'Montserrat', sans-serif; +} + +.bg-primary { + background-color: var(--bs-primary) !important; +} + +.navbar-brand { + font-weight: 700; +} + +.hero-section { + background: linear-gradient(45deg, var(--bs-primary), var(--bs-secondary)); + color: white; + padding: 100px 0; + text-align: center; +} + +.hero-section h1 { + font-weight: 700; + font-size: 3.5rem; +} + +.hero-section .btn-accent { + background-color: var(--bs-accent); + color: var(--bs-text); + font-weight: 700; + padding: 15px 30px; + font-size: 1.2rem; + border-radius: 50px; + transition: transform 0.2s; +} + +.hero-section .btn-accent:hover { + transform: scale(1.05); +} + +.content-section { + padding: 60px 0; +} \ No newline at end of file diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..b095735 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,58 @@ - :root { - --bg-color-start: #6a11cb; - --bg-color-end: #2575fc; - --text-color: #ffffff; - --card-bg-color: rgba(255, 255, 255, 0.01); - --card-border-color: rgba(255, 255, 255, 0.1); + --bs-primary: #0D47A1; + --bs-secondary: #42A5F5; + --bs-accent: #FFC107; + --bs-background: #F5F5F5; + --bs-text: #212121; } + body { - margin: 0; - font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); - color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + font-family: 'Roboto', sans-serif; + background-color: var(--bs-background); + color: var(--bs-text); + display: flex; + flex-direction: column; + min-height: 100vh; } + +h1, h2, h3, h4, h5, h6, .navbar-brand { + font-family: 'Montserrat', sans-serif; +} + +.bg-primary { + background-color: var(--bs-primary) !important; +} + +.navbar-brand { + font-weight: 700; +} + +.hero-section { + background: linear-gradient(45deg, var(--bs-primary), var(--bs-secondary)); + color: white; + padding: 100px 0; + text-align: center; +} + +.hero-section h1 { + font-weight: 700; + font-size: 3.5rem; +} + +.hero-section .btn-accent { + background-color: var(--bs-accent); + color: var(--bs-text); + font-weight: 700; + padding: 15px 30px; + font-size: 1.2rem; + border-radius: 50px; + transition: transform 0.2s; +} + +.hero-section .btn-accent:hover { + transform: scale(1.05); +} + +.content-section { + padding: 60px 0; +} \ No newline at end of file