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") def __str__(self): return self.name class Meta: verbose_name_plural = "Kategori" verbose_name = "Kategori" class Supplier(models.Model): name = models.CharField(max_length=255, verbose_name="Nama Supplier") contact_person = models.CharField(max_length=100, blank=True, verbose_name="Kontak Person") phone = models.CharField(max_length=20, blank=True, verbose_name="Telepon") address = models.TextField(blank=True, verbose_name="Alamat") def __str__(self): return self.name class Meta: verbose_name_plural = "Supplier" verbose_name = "Supplier" class Medicine(models.Model): UNIT_CHOICES = [ ('Tablet', 'Tablet'), ('Kapsul', 'Kapsul'), ('Botol', 'Botol'), ('Strip', 'Strip'), ('Pcs', 'Pcs'), ('Box', 'Box'), ] name = models.CharField(max_length=255, verbose_name="Nama Barang") category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='medicines', verbose_name="Kategori") sku = models.CharField(max_length=50, unique=True, verbose_name="SKU/Kode") unit = models.CharField(max_length=20, choices=UNIT_CHOICES, default='Tablet', verbose_name="Satuan") min_stock = models.IntegerField(default=10, verbose_name="Stok Minimal") main_supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, blank=True, related_name='primary_medicines', verbose_name="Supplier Utama") alternative_supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, blank=True, related_name='alternative_medicines', verbose_name="Supplier Alternatif") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.name @property def total_stock(self): return sum(batch.quantity for batch in self.batches.all()) @property def status(self): total = self.total_stock if total <= 0: return "Habis" if total <= self.min_stock: return "Stok Menipis" return "Tersedia" class Meta: verbose_name_plural = "Barang/Obat" verbose_name = "Barang/Obat" class Faktur(models.Model): FAKTUR_TYPE_CHOICES = [ ('MASUK', 'Faktur Masuk (Supplier)'), ('KELUAR', 'Faktur Keluar'), ] faktur_number = models.CharField(max_length=100, unique=True, verbose_name="Nomor Faktur") supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Supplier") date = models.DateField(default=timezone.now, verbose_name="Tanggal") faktur_type = models.CharField(max_length=10, choices=FAKTUR_TYPE_CHOICES, default='MASUK', verbose_name="Tipe Faktur") notes = models.TextField(blank=True, verbose_name="Catatan") created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.faktur_number class Meta: verbose_name_plural = "Faktur" verbose_name = "Faktur" class Batch(models.Model): medicine = models.ForeignKey(Medicine, on_delete=models.CASCADE, related_name='batches', verbose_name="Barang") faktur = models.ForeignKey(Faktur, on_delete=models.SET_NULL, null=True, blank=True, related_name='batches', verbose_name="Faktur") batch_number = models.CharField(max_length=100, verbose_name="Nomor Batch/Lot") expiry_date = models.DateField(verbose_name="Tanggal Kadaluarsa") quantity = models.IntegerField(default=0, verbose_name="Jumlah Stok") buying_price = models.DecimalField(max_digits=12, decimal_places=2, verbose_name="Harga Beli") selling_price = models.DecimalField(max_digits=12, decimal_places=2, verbose_name="Harga Jual") created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.medicine.name} - {self.batch_number}" @property def is_expired(self): return self.expiry_date <= timezone.now().date() @property def is_near_expiry(self): today = timezone.now().date() diff = self.expiry_date - today return 0 < diff.days <= 90 # 3 months class Meta: verbose_name_plural = "Batch Barang" verbose_name = "Batch Barang" class StockTransaction(models.Model): TRANSACTION_TYPES = [ ('IN', 'Barang Masuk'), ('OUT', 'Barang Keluar'), ('ADJ', 'Penyesuaian'), ] medicine = models.ForeignKey(Medicine, on_delete=models.CASCADE, verbose_name="Barang") batch = models.ForeignKey(Batch, on_delete=models.SET_NULL, null=True, blank=True, related_name='transactions', verbose_name="Batch") faktur = models.ForeignKey(Faktur, on_delete=models.SET_NULL, null=True, blank=True, related_name='transactions', verbose_name="Faktur") transaction_type = models.CharField(max_length=3, choices=TRANSACTION_TYPES, verbose_name="Tipe Transaksi") quantity = models.IntegerField(verbose_name="Jumlah") note = models.TextField(blank=True, verbose_name="Keterangan") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Waktu") def __str__(self): return f"{self.get_transaction_type_display()} - {self.medicine.name} ({self.quantity})" class Meta: verbose_name_plural = "Transaksi Stok" verbose_name = "Transaksi Stok"