diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..6485af4 Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..e61d690 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..83f0568 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd6..291bdd5 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..596da42 --- /dev/null +++ b/core/forms.py @@ -0,0 +1,14 @@ +from django import forms +from .models import ProcurementProposal, Department + +class ProcurementProposalForm(forms.ModelForm): + class Meta: + model = ProcurementProposal + fields = ['proposal_number', 'title', 'description', 'estimated_cost', 'department'] + widgets = { + 'proposal_number': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'e.g., M7-2026-001'}), + 'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Proposal Title'}), + 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 4, 'placeholder': 'Detailed description...'}), + 'estimated_cost': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Amount in AFN'}), + 'department': forms.Select(attrs={'class': 'form-select'}), + } diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..d8f6152 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,49 @@ +# Generated by Django 5.2.7 on 2026-01-28 01:33 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Department', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('code', models.CharField(max_length=10, unique=True)), + ('description', models.TextField(blank=True)), + ], + ), + migrations.CreateModel( + name='ProcurementProposal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('proposal_number', models.CharField(max_length=50, unique=True)), + ('title', models.CharField(max_length=255)), + ('description', models.TextField()), + ('estimated_cost', models.DecimalField(decimal_places=2, max_digits=15)), + ('status', models.CharField(choices=[('draft', 'Draft'), ('submitted', 'Submitted'), ('under_review', 'Under Review'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='draft', max_length=20)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.department')), + ], + ), + migrations.CreateModel( + name='Document', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('doc_type', models.CharField(choices=[('M7', 'Form M-7 (Proposal)'), ('M16', 'Form M-16 (Payment)'), ('S16', 'Form S-16 (Invoice)')], max_length=10)), + ('file_path', models.CharField(blank=True, max_length=255)), + ('metadata', models.JSONField(default=dict)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('proposal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='core.procurementproposal')), + ], + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..ef66c2d Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..928b1e1 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,46 @@ from django.db import models +from django.utils.translation import gettext_lazy as _ -# Create your models here. +class Department(models.Model): + name = models.CharField(max_length=100) + code = models.CharField(max_length=10, unique=True) + description = models.TextField(blank=True) + + def __cl__(self): + return self.name + +class ProcurementProposal(models.Model): + STATUS_CHOICES = [ + ('draft', 'Draft'), + ('submitted', 'Submitted'), + ('under_review', 'Under Review'), + ('approved', 'Approved'), + ('rejected', 'Rejected'), + ] + + proposal_number = models.CharField(max_length=50, unique=True) + title = models.CharField(max_length=255) + description = models.TextField() + estimated_cost = models.DecimalField(max_digits=15, decimal_places=2) + department = models.ForeignKey(Department, on_delete=models.CASCADE) + status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"{self.proposal_number} - {self.title}" + +class Document(models.Model): + TYPE_CHOICES = [ + ('M7', 'Form M-7 (Proposal)'), + ('M16', 'Form M-16 (Payment)'), + ('S16', 'Form S-16 (Invoice)'), + ] + doc_type = models.CharField(max_length=10, choices=TYPE_CHOICES) + proposal = models.ForeignKey(ProcurementProposal, on_delete=models.CASCADE, related_name='documents') + file_path = models.CharField(max_length=255, blank=True) # Cloud path simulation + metadata = models.JSONField(default=dict) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.doc_type} for {self.proposal.proposal_number}" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..f4b0e0a 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,165 @@ - + - {% block title %}Knowledge Base{% endblock %} + + {% block title %}Qosh Tepa Project{% endblock %} + {% if project_description %} - - - {% endif %} - {% if project_image_url %} - - {% endif %} + {% load static %} + + + + + + + + + {% block head %}{% endblock %} - {% block content %}{% endblock %} + + +
+
+ + + + +
+ {% block content %}{% endblock %} +
+
+
+ + + {% block scripts %}{% endblock %} - + \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..ae2d10c 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,101 @@ {% extends "base.html" %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Dashboard | Qosh Tepa Management{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+
+
+

{{ total_budget }} AFN

+

Total Estimated Budget

-

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" }} -

-
- +
+
+
+

{{ active_proposals }}

+

Active Proposals

+
+
+
+
+
+

{{ pending_documents }}

+

Pending Documents

+
+
+ + +
+
+
+
+

Project Branches

+ New M-7 Proposal +
+
+ {% for dept in departments %} +
+
+
+
{{ dept.name }}
+ {{ dept.code }} +
+
+ {% endfor %} +
+
+
+
+ +
+
+
+

Recent Procurement Proposals

+
+ + + + + + + + + + + + {% for proposal in proposals %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
IDTitleBudgetStatusAction
{{ proposal.proposal_number }}{{ proposal.title }}{{ proposal.estimated_cost }} AFN + + {{ proposal.get_status_display }} + + View
No proposals found. Start by creating one!
+
+
+
+
+
+

Quick Actions

+
+ Create M-7 Proposal + + +
+
+
+
{% endblock %} \ No newline at end of file diff --git a/core/templates/core/proposal_form.html b/core/templates/core/proposal_form.html new file mode 100644 index 0000000..f7e2752 --- /dev/null +++ b/core/templates/core/proposal_form.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} + +{% block title %}New Proposal | Qosh Tepa Management{% endblock %} + +{% block content %} +
+
+
+
+
+

Form M-7: Procurement Proposal

+
+ +
+ {% csrf_token %} +
+
+ + {{ form.proposal_number }} +
+
+ + {{ form.department }} +
+
+ +
+ + {{ form.title }} +
+ +
+ + {{ form.description }} +
+ +
+ + {{ form.estimated_cost }} +
+ +
+ + Cancel +
+
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..f4edc99 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,7 @@ from django.urls import path - -from .views import home +from . import views urlpatterns = [ - path("", home, name="home"), -] + path('', views.home, name='home'), + path('proposal/new/', views.proposal_create, name='proposal_create'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..78219fe 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,39 @@ import os import platform - -from django import get_version as django_version -from django.shortcuts import render +from django.shortcuts import render, redirect from django.utils import timezone - +from .models import Department, ProcurementProposal, Document +from .forms import ProcurementProposalForm +from django.db.models import Sum, Count 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 Qosh Tepa Central Management Dashboard.""" + departments = Department.objects.all() + proposals = ProcurementProposal.objects.all().order_by('-created_at')[:5] + + total_budget = ProcurementProposal.objects.aggregate(Sum('estimated_cost'))['estimated_cost__sum'] or 0 + active_proposals = ProcurementProposal.objects.exclude(status='rejected').count() + pending_documents = Document.objects.count() + 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", ""), + "project_name": "Qosh Tepa Finance & Admin", + "departments": departments, + "proposals": proposals, + "total_budget": total_budget, + "active_proposals": active_proposals, + "pending_documents": pending_documents, + "current_time": timezone.now(), } return render(request, "core/index.html", context) + +def proposal_create(request): + """View to create a new M-7 Procurement Proposal.""" + if request.method == 'POST': + form = ProcurementProposalForm(request.POST) + if form.is_valid(): + form.save() + return redirect('home') + else: + form = ProcurementProposalForm() + + return render(request, "core/proposal_form.html", {"form": form})