diff --git a/ai/__pycache__/__init__.cpython-311.pyc b/ai/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d7cbff1 Binary files /dev/null and b/ai/__pycache__/__init__.cpython-311.pyc differ diff --git a/ai/__pycache__/local_ai_api.cpython-311.pyc b/ai/__pycache__/local_ai_api.cpython-311.pyc new file mode 100644 index 0000000..5b7c878 Binary files /dev/null and b/ai/__pycache__/local_ai_api.cpython-311.pyc differ diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 7f66d9b..9103936 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 86948bc..0d9097d 100644 Binary files a/core/__pycache__/context_processors.cpython-311.pyc and b/core/__pycache__/context_processors.cpython-311.pyc differ diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index 74fd730..16e876c 100644 Binary files a/core/__pycache__/forms.cpython-311.pyc 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 a72c45c..8b0ae5e 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 b11b471..8853e8c 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 1004ca8..fa3a958 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 7d50940..b1ff85b 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,11 +1,21 @@ from django.contrib import admin -from .models import Category, Medicine, Batch, StockTransaction, Supplier, Faktur +from .models import Category, Medicine, Batch, StockTransaction, Supplier, Faktur, AppSetting # DN-WRS Branding admin.site.site_header = "DN-WRS Admin" admin.site.site_title = "DN-WRS Portal" admin.site.index_title = "Selamat Datang di Manajemen DN-WRS" +@admin.register(AppSetting) +class AppSettingAdmin(admin.ModelAdmin): + list_display = ('app_name', 'app_email', 'app_phone') + + def has_add_permission(self, request): + # Allow only one instance of AppSetting + if self.model.objects.exists(): + return False + return True + @admin.register(Supplier) class SupplierAdmin(admin.ModelAdmin): list_display = ('name', 'contact_person', 'phone') @@ -36,4 +46,4 @@ class BatchAdmin(admin.ModelAdmin): @admin.register(StockTransaction) class StockTransactionAdmin(admin.ModelAdmin): list_display = ('medicine', 'transaction_type', 'quantity', 'created_at') - list_filter = ('transaction_type', 'created_at') \ No newline at end of file + list_filter = ('transaction_type', 'created_at') diff --git a/core/context_processors.py b/core/context_processors.py index 0bf87c3..0d1599d 100644 --- a/core/context_processors.py +++ b/core/context_processors.py @@ -1,13 +1,23 @@ import os import time +from .models import AppSetting def project_context(request): """ - Adds project-specific environment variables to the template context globally. + Adds project-specific environment variables and settings to the template context globally. """ + settings = AppSetting.objects.first() + if not settings: + # Create default settings if none exist + settings = AppSetting.objects.create(app_name="DN-WRS") + return { - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), + "project_name": settings.app_name, + "project_description": settings.app_description or os.getenv("PROJECT_DESCRIPTION", ""), + "project_address": settings.app_address, + "project_phone": settings.app_phone, + "project_email": settings.app_email, "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), # Used for cache-busting static assets "deployment_timestamp": int(time.time()), - } + } \ No newline at end of file diff --git a/core/forms.py b/core/forms.py index ec37e48..cd5e243 100644 --- a/core/forms.py +++ b/core/forms.py @@ -1,5 +1,17 @@ from django import forms -from .models import Supplier, Faktur, Medicine, Batch, StockTransaction, Category +from .models import Supplier, Faktur, Medicine, Batch, StockTransaction, Category, AppSetting + +class AppSettingForm(forms.ModelForm): + class Meta: + model = AppSetting + fields = ['app_name', 'app_description', 'app_address', 'app_phone', 'app_email'] + widgets = { + 'app_name': forms.TextInput(attrs={'class': 'form-control'}), + 'app_description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), + 'app_address': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), + 'app_phone': forms.TextInput(attrs={'class': 'form-control'}), + 'app_email': forms.EmailInput(attrs={'class': 'form-control'}), + } class CategoryForm(forms.ModelForm): class Meta: @@ -104,4 +116,4 @@ class StockOutForm(forms.Form): except (ValueError, TypeError): pass elif self.initial.get('medicine'): - self.fields['batch'].queryset = Batch.objects.filter(medicine_id=self.initial.get('medicine'), quantity__gt=0) \ No newline at end of file + self.fields['batch'].queryset = Batch.objects.filter(medicine_id=self.initial.get('medicine'), quantity__gt=0) diff --git a/core/migrations/0004_appsetting.py b/core/migrations/0004_appsetting.py new file mode 100644 index 0000000..bf4861b --- /dev/null +++ b/core/migrations/0004_appsetting.py @@ -0,0 +1,28 @@ +# Generated by Django 5.2.7 on 2026-02-06 11:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0003_medicine_alternative_supplier_medicine_main_supplier'), + ] + + operations = [ + migrations.CreateModel( + name='AppSetting', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('app_name', models.CharField(default='DN-WRS', max_length=100, verbose_name='Nama Aplikasi')), + ('app_description', models.TextField(blank=True, verbose_name='Deskripsi Aplikasi')), + ('app_address', models.TextField(blank=True, verbose_name='Alamat')), + ('app_phone', models.CharField(blank=True, max_length=20, verbose_name='Nomor Telepon')), + ('app_email', models.EmailField(blank=True, max_length=254, verbose_name='Email')), + ], + options={ + 'verbose_name': 'Pengaturan Aplikasi', + 'verbose_name_plural': 'Pengaturan Aplikasi', + }, + ), + ] diff --git a/core/migrations/__pycache__/0004_appsetting.cpython-311.pyc b/core/migrations/__pycache__/0004_appsetting.cpython-311.pyc new file mode 100644 index 0000000..c9a9722 Binary files /dev/null and b/core/migrations/__pycache__/0004_appsetting.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 324aa1c..b0e3a39 100644 --- a/core/models.py +++ b/core/models.py @@ -1,6 +1,20 @@ from django.db import models from django.utils import timezone +class AppSetting(models.Model): + app_name = models.CharField(max_length=100, default="DN-WRS", verbose_name="Nama Aplikasi") + app_description = models.TextField(blank=True, verbose_name="Deskripsi Aplikasi") + app_address = models.TextField(blank=True, verbose_name="Alamat") + app_phone = models.CharField(max_length=20, blank=True, verbose_name="Nomor Telepon") + app_email = models.EmailField(blank=True, verbose_name="Email") + + def __str__(self): + return self.app_name + + class Meta: + verbose_name = "Pengaturan Aplikasi" + verbose_name_plural = "Pengaturan Aplikasi" + class Category(models.Model): name = models.CharField(max_length=100, verbose_name="Nama Kategori") description = models.TextField(blank=True, verbose_name="Deskripsi") diff --git a/core/templates/base.html b/core/templates/base.html index cecdb8a..12a5b04 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -18,110 +18,350 @@ + {% block extra_head %}{% endblock %}
{% if user.is_authenticated %} -