From 561398a333d07b74d4b224c258f8053489d64655 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 23 Feb 2026 10:04:20 +0000 Subject: [PATCH] 1.1 --- config/__pycache__/__init__.cpython-311.pyc | Bin 159 -> 159 bytes config/__pycache__/settings.cpython-311.pyc | Bin 5552 -> 5552 bytes config/__pycache__/urls.cpython-311.pyc | Bin 1557 -> 1557 bytes config/__pycache__/wsgi.cpython-311.pyc | Bin 679 -> 679 bytes core/__pycache__/__init__.cpython-311.pyc | Bin 157 -> 157 bytes core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 212 bytes core/__pycache__/apps.cpython-311.pyc | Bin 524 -> 524 bytes .../context_processors.cpython-311.pyc | Bin 763 -> 763 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 3254 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 721 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 3293 bytes core/migrations/0001_initial.py | 39 +++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 2480 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 168 -> 168 bytes core/models.py | 43 +++- core/templates/base.html | 67 ++++-- core/templates/core/agreement_print.html | 110 +++++++++ core/templates/core/index.html | 226 +++++++----------- core/templates/core/job_detail.html | 71 ++++++ core/templates/core/job_form.html | 31 +++ core/templates/core/job_list.html | 50 ++++ core/urls.py | 9 +- core/views.py | 48 ++-- static/css/custom.css | 75 +++++- 24 files changed, 588 insertions(+), 181 deletions(-) create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/templates/core/agreement_print.html create mode 100644 core/templates/core/job_detail.html create mode 100644 core/templates/core/job_form.html create mode 100644 core/templates/core/job_list.html diff --git a/config/__pycache__/__init__.cpython-311.pyc b/config/__pycache__/__init__.cpython-311.pyc index 423a6362b2322713e75da67a35e209e76169dbae..aaa952ee39d3fd8dfb6abee2a3ba25a5476e6246 100644 GIT binary patch delta 19 ZcmbQwIG>SwIWI340}wQ-%$dkN1pq3N1c(3t delta 19 ZcmbQwIG>SwIWI340}xbw%b&y+NCMIWI340}wQ-%-P7jR1^R>KLtbp delta 20 acmdm>y+NCMIWI340}xbw%iqYoR1^R_83p11 diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94ece283a83ff1af1d71f1b265c943eb37a..0debe38124e782185e96e585104094b79895bc4a 100644 GIT binary patch delta 20 acmbQrGnI#XIWI340}wQ-%-P7z#RdQ_oCGES delta 20 acmbQrGnI#XIWI340}xbw%iqY&#RdQ}b_B!# diff --git a/config/__pycache__/wsgi.cpython-311.pyc b/config/__pycache__/wsgi.cpython-311.pyc index 9c49e09df194d2dbcad4868349c9177db4b15571..6e80bb7390b19de0c341e6c221ef2df5c8c73700 100644 GIT binary patch delta 20 acmZ3^x}24JIWI340}wQ-%-P62hY0{NYy`>x delta 20 acmZ3^x}24JIWI340}xbw%iqX7hY0{RMg?d9 diff --git a/core/__pycache__/__init__.cpython-311.pyc b/core/__pycache__/__init__.cpython-311.pyc index 74b111269bd81aac528770a53e2f849291524d56..20e9ee9f52bb838cfba758a47a3f068f4e68feee 100644 GIT binary patch delta 19 ZcmbQsIG2%oIWI340}wQ-%$dkN2>>cc1cCqn delta 19 ZcmbQsIG2%oIWI340}xbw%b&>mG1t0(b diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392d6714413db63120e4233d2e96cbadb5de..3c0ebca4c889e7362b68df8f643b2a6ebd80cea8 100644 GIT binary patch delta 19 Zcmcb@c!iOBIWI340}wQ-%$dl25&$wg1t$Oi delta 19 Zcmcb@c!iOBIWI340}xFAkw209Bmg!q1>^t# diff --git a/core/__pycache__/apps.cpython-311.pyc b/core/__pycache__/apps.cpython-311.pyc index 6f131d4873bc56e3763e4ed09960c6e3f34140e1..e3a68b37e0507233445c5b8a924915acf2d97dd2 100644 GIT binary patch delta 20 acmeBS>0#ks&dbZi00fOHb2f4_G64WA5CiuB delta 20 acmeBS>0#ks&dbZi00dRv@;7obG64WD>I9Vl diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 75bf2234fb21a6b62efc5cec11af9512dd0c9616..2d7677b4aa8b20f07d47fa07a3763a4c77ec1a31 100644 GIT binary patch delta 20 acmey(`kR$|IWI340}wQ-%-P8Ofe8RUj0MI3 delta 20 acmey(`kR$|IWI340}xbw%iqZTfe8RYW(H&c diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640edbdcec3e5c1744466c916e7acdd2763b..0d1a714736672b622e75911596d75cc973e596c7 100644 GIT binary patch literal 3254 zcmaJ@UrZax8K3of{SO;rAH-_U=Rg8fRvNf)5D}=Va|w{k2_h9I>G`3n#WR4NwU^AU z14oJKhg78!z4{^5rAkjiRg`iH4?N!EU7zx3M|+AjQlyjm#G6mt1G<;?n^|nIbIN%A z?e}kH=g;^1zWH}36hP3P_Wv`x>_O1Z1#_=ZQY%_FphmLwc{=u3Cv&W9-7 zwT0HD^cmQ;E+*eF78CA-iz%3DOBPeE@fXM*En{Wx6Xr>ZH)#ABBfqK>i(uxTYOq4D z6*5HEg}%WabiZ{7 z40g4SO~?Gm3Y~bI9sz<8{mJ#Srm?l>1NWvIyEnl4Kq+)zKvrkd5%nXg00!L;luuB> zvxe5?PtcmgW$fBiu=2$Hg=-V3%?>VPg_{CuU0KfGuxv_MwCQ>(eJ1b?0p*$BkS}F1 zlan7U9Pq6?;3vZ5_eXIezydjAQ7shni-c0h9Ef?1#T?04Ci58-6RIwL%9N!nH7yn} zEsa{{S{9;4&K5v%ThohVno@%@#VoE8%G{=QpCr8SCi)U{YjoLUp1W(}?b9{WQsH~d z;oz&xTOe!v^USZR8L*qGYVuI)6|MB+(C~_pC&R_XV!{&tFdY*D9JUbWO8J3W|{96Ua~k3an}n%*9oF%!??Z zBYeQnaai(Xs;ZC`FM(EUz=vW31ZD)`>BsyI2*g_BS9d9AJ$2L|rTKa%ikvT>wZnb8 zzx~Snb+HnjtA^+7@LcIe4Ge>JEoudyAm0yMuzOj5GX_MZQZs* z@9jqRfB)i6C3LGAx@CuMm1b(;0Y3J?{%9pUUJZ}i;c*!ESh;Ie!lTvjs2v_H-Ke{R z%3vM+1c^z?RfyKN5c&ZuQY<+GOtUo->ETOIoz!rsg!0LCf+!&IG$R_8_FQeXmDgxF z*R0XRpA#1w?!G6trq*^uIa|ZjMHixkv za1mhs!<+z!i?;7C5K1AlT&~xU)Ic-X((qn3)WD*8$39 z=ynRiBF;C$%?=F^U*v8*KzQmL+i^ej*}WfBy2kk98xuh=pNP;=@StOyT;W7OGjy{+ zQU(wQo=#brN-j(#uT9e%;KuwMhmMuwhRJYoV4clPRXGyrRc=v$$pdiBjIl~oV@c(y zp9QZuJ9Z3p%dlYg?(=FSmh&ZYf|REynrx7MV9d{eG~fv<3&ghu?Lhpoxx2JicrjTC z+^Gic*nvBxsanrK`L^9Nu)DISS9&I^J(G6NWNE$@jBU->!B{mIw}bK0bgjF;JY#qF zSGx!8?!nSrEi%AiJg^`6I{Ct?L{imA%8sN;AJ^TIa)l$Soj6nFvz&**>Bl*(uxt$B zMQ1OA$8yoi>LwMNrOfgBw3B(n;!=Et0+oEhKl*;<-`oZQ1xJ!!4=2VCC7%Q(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%RM0pb7xLi8T)Z diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659f6c6e0ae848e54157af197c543a09315f..fd1a42d425a45b2fa958a8921995f8b52db308a4 100644 GIT binary patch literal 721 zcma)2J8Roe6u#FwdRcWGLZS2lS~}EVqQy`gLZ%LNDP7u0OHh0djvPJAl~lJOLzY0s zY|YTYQy;WTq5U5cXfRqkWiw>U)O%%jNb%64d&PIYPv1E@=X0yoBqDx1{^*}kLVnBS zZl5^!Wv8o8lmDUA-E8#t{Q5t7V54}NrNC|fC^K;Yo8QCzKOex zTG0`hu~sorWzDsUg&MoFR%xNmHvUycs%xoVV{^IhTEnH=po+>qqm+hkqT;d0HdI%Z|Du@{Zv?TiNrmpiM}w?0mjx@p~|E?t+Z zO_e1+6@#V7qvR{O78Y{Tb>wtTc92DB=HNRVW@*fwY0Qt3i8n-N7;_L=$6o3at|-Yvy&Wp1@ubj)m(1gzufuqGKYQv{Sx{s(w^D*)8{!13K*0ySXf%S MacaqjZ;C(v0~{y7fdBvi delta 255 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 x8$enCQ50LUAdV6t - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}Aitken Spence Industrial Solutions{% endblock %} + + + + + + + + + + {% load static %} + + + {% block head %}{% endblock %} - - {% block content %}{% endblock %} - + - +
+ {% block content %}{% endblock %} +
+ +
+

© 2026 Aitken Spence Industrial Solutions. All rights reserved.

+
+ + + + \ No newline at end of file diff --git a/core/templates/core/agreement_print.html b/core/templates/core/agreement_print.html new file mode 100644 index 0000000..ef84625 --- /dev/null +++ b/core/templates/core/agreement_print.html @@ -0,0 +1,110 @@ +{% extends "base.html" %} + +{% block head %} + +{% endblock %} + +{% block content %} +
+
+

Print Preview: This layout is optimized for A4 paper printing.

+ + Back to Job +
+
+ + +{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..6caf322 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,89 @@ {% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% load static %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+

Industrial Operations Control

+

Manage jobs, agreements, and industrial solutions for Aitken Spence with precision and speed.

+
-

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

-
-
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
-{% endblock %} \ No newline at end of file +
+
+ + + + +
+
+ + +
+
+
+

{{ jobs_count }}

+

Total Jobs

+
+
+
+
+

{{ active_jobs }}

+

Active Agreements

+
+
+
+
+

100%

+

SLA Compliance

+
+
+
+ +
+
+
+
+

Recent Job Orders

+ View All +
+
+ + + + + + + + + + + + {% for job in recent_jobs %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
Job IDClientStatusCreatedAction
{{ job.job_number }}{{ job.client_name }} + + {{ job.get_status_display }} + + {{ job.created_at|date:"M d, Y" }} + Manage +
No jobs found. Start by creating one.
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/job_detail.html b/core/templates/core/job_detail.html new file mode 100644 index 0000000..8ab78b4 --- /dev/null +++ b/core/templates/core/job_detail.html @@ -0,0 +1,71 @@ +{% extends "base.html" %} + +{% block title %}Job {{ job.job_number }} - AIS Portal{% endblock %} + +{% block content %} +
+
+
+
+
+ Job Profile +

{{ job.job_number }}

+

{{ job.client_name }}

+
+ {{ job.get_status_display }} +
+ +
+
+

Creation Date

+

{{ job.created_at|date:"d F Y, H:i" }}

+
+
+

Last Update

+

{{ job.updated_at|date:"d F Y, H:i" }}

+
+
+ +
+ +

Job Description

+
+ {{ job.description|linebreaks|default:"No description provided." }} +
+
+ +
+

Agreement Status

+ {% if job.agreement %} +
+
+

Commercial Agreement Generated

+

Dated: {{ job.agreement.agreement_date }}

+
+ Preview & Print +
+ {% else %} +
+

No agreement linked to this job yet.

+ +
+ {% endif %} +
+
+ +
+
+

Workflow Actions

+
+ + +
+ +
+
+

"Ensure all client data matches the physical purchase order before printing the agreement."

+
+
+
+
+{% endblock %} diff --git a/core/templates/core/job_form.html b/core/templates/core/job_form.html new file mode 100644 index 0000000..fd21901 --- /dev/null +++ b/core/templates/core/job_form.html @@ -0,0 +1,31 @@ +{% extends "base.html" %} + +{% block title %}New Job - AIS Portal{% endblock %} + +{% block content %} +
+
+
+

Register New Industrial Job

+
+ {% csrf_token %} +
+ + +
+
+ + +
+
+ + Cancel +
+
+
+

Note: Job Number (AISXXXX) will be automatically generated upon submission.

+
+
+
+
+{% endblock %} diff --git a/core/templates/core/job_list.html b/core/templates/core/job_list.html new file mode 100644 index 0000000..df33101 --- /dev/null +++ b/core/templates/core/job_list.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} + +{% block title %}All Jobs - AIS Portal{% endblock %} + +{% block content %} +
+

Job Inventory

+ + New Job +
+ +
+
+ + + + + + + + + + + + {% for job in jobs %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
Job IDClient NameStatusDate CreatedActions
{{ job.job_number }}{{ job.client_name }} + + {{ job.get_status_display }} + + {{ job.created_at|date:"M d, Y" }} +
+ View + Print +
+
No jobs available.
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..90736d4 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,10 @@ from django.urls import path - -from .views import home +from .views import home, job_list, job_create, job_detail, agreement_print urlpatterns = [ path("", home, name="home"), -] + path("jobs/", job_list, name="job_list"), + path("jobs/new/", job_create, name="job_create"), + path("jobs//", job_detail, name="job_detail"), + path("jobs//print/", agreement_print, name="agreement_print"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..a4c4702 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,45 @@ import os import platform - from django import get_version as django_version -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect from django.utils import timezone - +from .models import Job, Agreement +from django.contrib.auth.decorators import login_required 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() - + """Modern Dashboard Landing Page""" + jobs_count = Job.objects.count() + active_jobs = Job.objects.filter(status='active').count() + recent_jobs = Job.objects.order_by('-created_at')[:5] + context = { - "project_name": "New Style", - "agent_brand": agent_brand, + "project_name": "Aitken Spence Industrial Solutions", + "jobs_count": jobs_count, + "active_jobs": active_jobs, + "recent_jobs": recent_jobs, "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) + +def job_list(request): + jobs = Job.objects.all().order_by('-created_at') + return render(request, "core/job_list.html", {"jobs": jobs}) + +def job_create(request): + if request.method == "POST": + client_name = request.POST.get("client_name") + description = request.POST.get("description") + job = Job.objects.create(client_name=client_name, description=description) + # Automatically create an empty agreement + Agreement.objects.create(job=job, terms="Standard Terms Apply", scope_of_work=description) + return redirect('job_detail', pk=job.pk) + return render(request, "core/job_form.html") + +def job_detail(request, pk): + job = get_object_or_404(Job, pk=pk) + return render(request, "core/job_detail.html", {"job": job}) + +def agreement_print(request, pk): + agreement = get_object_or_404(Agreement, job__pk=pk) + return render(request, "core/agreement_print.html", {"agreement": agreement}) \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..d8f0b01 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,73 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --primary-color: #003366; /* Deep Industrial Blue */ + --accent-color: #FF8C00; /* Safety Orange */ + --bg-color: #F8F9FA; + --text-color: #212529; + --card-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } + +body { + background-color: var(--bg-color); + color: var(--text-color); + font-family: 'Inter', sans-serif; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Outfit', sans-serif; + color: var(--primary-color); +} + +.navbar { + background-color: var(--primary-color) !important; +} + +.navbar-brand, .nav-link { + color: white !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-accent { + background-color: var(--accent-color); + color: white; + border: none; +} + +.btn-accent:hover { + background-color: #e67e00; + color: white; +} + +.card { + border: none; + border-radius: 12px; + box-shadow: var(--card-shadow); + transition: transform 0.2s; +} + +.card:hover { + transform: translateY(-5px); +} + +/* Print Styling */ +@media print { + .no-print { + display: none !important; + } + body { + background: white; + } + .print-container { + width: 100%; + margin: 0; + padding: 20px; + } + .agreement-header { + border-bottom: 2px solid var(--primary-color); + margin-bottom: 20px; + padding-bottom: 10px; + } +} \ No newline at end of file