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 %} - - {% endif %} - -
- {% if messages %} - {% for message in messages %} - - {% endfor %} - {% endif %} +
- -
- {% block content %}{% endblock %} + {% else %} +
+ {% block login_content %}{% block content_no_auth %}{% endblock %}{% endblock %}
- - + {% endif %} {% block extra_js %}{% endblock %} diff --git a/core/templates/core/barang_keluar.html b/core/templates/core/barang_keluar.html index 5da9a0f..f1706d8 100644 --- a/core/templates/core/barang_keluar.html +++ b/core/templates/core/barang_keluar.html @@ -1,8 +1,56 @@ {% extends 'base.html' %} {% block content %} +{% if cart %} +
+
+
+
+ Konfirmasi Import Barang Keluar +
+ +
+
+ + + + + + + + + + + + {% for item in cart %} + + + + + + + + {% endfor %} + +
Barang (SKU)Batch NumberQty KeluarCatatanStatus
+
{{ item.sku }}
+
{{ item.batch }}{{ item.qty }}{{ item.note }} + {% if item.valid %} + Ready + {% else %} + Batch/Stok Tidak Valid + {% endif %} +
+
+
+
+{% endif %} +
-
+

@@ -35,6 +83,29 @@

+ +
+
+
+
+
+ +
+ Import Excel +
+ Template +
+
+ {% csrf_token %} +
+ +
+ +
+
+
diff --git a/core/templates/core/faktur_detail.html b/core/templates/core/faktur_detail.html index 4e1a61d..72182e1 100644 --- a/core/templates/core/faktur_detail.html +++ b/core/templates/core/faktur_detail.html @@ -13,35 +13,89 @@
NOMOR FAKTUR

#{{ faktur.faktur_number }}

-
-
SUPPLIER
-
- {{ faktur.supplier.name|default:"Internal" }} +
+ + Template Excel + +
+
SUPPLIER
+
+ {{ faktur.supplier.name|default:"Internal" }} +
+{% if cart %} +
+
+
+
+ Konfirmasi Import (Keranjang) +
+ +
+
+ + + + + + + + + + + + + {% for item in cart %} + + + + + + + + + {% endfor %} + +
Barang (SKU)BatchExpiredQtyHarga BeliStatus
+
{{ item.name }}
+
{{ item.sku }}
+
{{ item.batch }}{{ item.expiry }}{{ item.qty }}Rp {{ item.buy|floatformat:2 }} + {% if item.valid %} + Ready + {% else %} + SKU Tidak Dikenal + {% endif %} +
+
+
+
+{% endif %} +
-
+
- Input Barang + Input Manual
{% csrf_token %} + {% for field in form %}
{{ field }} - {% if field.errors %} -
{{ field.errors }}
- {% endif %}
{% endfor %}
+ +
+
+
+
+ +
+ Import Excel +
+
+ {% csrf_token %} +
+ +
+ +
+
+
+ +
+
+
+
+ +
+ Scan Foto Faktur +
+
+ {% csrf_token %} +
+ +
+ +
+
+
@@ -59,9 +153,9 @@
- Rincian Barang + Rincian Barang Terinput - {{ items|length }} Item + {{ items|length }} Item Terdaftar
@@ -106,6 +200,11 @@