Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?
  • Yardım
  • Veteriner Yönetim Uygulaması için tavsiye Lütfen

Merhabalar Ben Veteriner Hekim olarak çalışıyorum bugüne kadar bir çok firmanın yapmış olduğu hazır paketleri kullanmak zorunda kaldık. bazı paketler yeterli oldu bazıları ise tamamen yetersiz bende Laravel ile bir Hasta ve müşteri yönetim takip sistemi yapmaya karar verdim. Bu konuda tavsiyelerinize açığım. Laravel Konusunda Çok yeniyim ama kullandıkça keyif almaya başladım bunuda belirtmeliyim. şimdiden teşekkür ederim.

    Merhaba! Veteriner hekimlik için Laravel ile hasta ve müşteri yönetim takip sistemi geliştirme kararınız çok güzel. Laravel, güçlü ve esnek bir PHP framework'ü olduğundan böyle bir sistem için ideal bir seçim.

    Filament ile birlikte bir veteriner kliniği yönetim sistemi için bazı önerilerim şunlar:

    
    <?php
    
    // Ana Modeller
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    
    // Müşteri (Hayvan Sahibi) Modeli
    class Customer extends Model
    {
        use HasFactory, SoftDeletes;
    
        protected $fillable = [
            'name',
            'surname',
            'phone',
            'email',
            'address',
            'city',
            'notes',
            'tax_number',
            'tax_office',
            'balance',
            'status',
        ];
    
        public function pets()
        {
            return $this->hasMany(Pet::class);
        }
    
        public function invoices()
        {
            return $this->hasMany(Invoice::class);
        }
    
        public function appointments()
        {
            return $this->hasMany(Appointment::class);
        }
    }
    
    // Evcil Hayvan Modeli
    class Pet extends Model
    {
        use HasFactory, SoftDeletes;
    
        protected $fillable = [
            'customer_id',
            'name',
            'species',
            'breed',
            'gender',
            'date_of_birth',
            'color',
            'microchip_number',
            'weight',
            'status',
            'notes',
        ];
    
        protected $casts = [
            'date_of_birth' => 'date',
        ];
    
        public function customer()
        {
            return $this->belongsTo(Customer::class);
        }
    
        public function appointments()
        {
            return $this->hasMany(Appointment::class);
        }
    
        public function medicalRecords()
        {
            return $this->hasMany(MedicalRecord::class);
        }
    
        public function vaccinations()
        {
            return $this->hasMany(Vaccination::class);
        }
    }
    
    // Tıbbi Kayıt Modeli
    class MedicalRecord extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'pet_id',
            'veterinarian_id',
            'date',
            'diagnosis',
            'treatment',
            'notes',
            'follow_up_date',
        ];
    
        protected $casts = [
            'date' => 'datetime',
            'follow_up_date' => 'date',
        ];
    
        public function pet()
        {
            return $this->belongsTo(Pet::class);
        }
    
        public function veterinarian()
        {
            return $this->belongsTo(User::class, 'veterinarian_id');
        }
    
        public function prescriptions()
        {
            return $this->hasMany(Prescription::class);
        }
    }
    
    // Randevu Modeli
    class Appointment extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'customer_id',
            'pet_id',
            'veterinarian_id',
            'date',
            'time',
            'reason',
            'status',
            'notes',
        ];
    
        protected $casts = [
            'date' => 'date',
            'time' => 'datetime',
        ];
    
        public function customer()
        {
            return $this->belongsTo(Customer::class);
        }
    
        public function pet()
        {
            return $this->belongsTo(Pet::class);
        }
    
        public function veterinarian()
        {
            return $this->belongsTo(User::class, 'veterinarian_id');
        }
    }
    
    // Aşı Modeli
    class Vaccination extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'pet_id',
            'veterinarian_id',
            'vaccine_id',
            'date',
            'expiry_date',
            'batch_number',
            'notes',
        ];
    
        protected $casts = [
            'date' => 'date',
            'expiry_date' => 'date',
        ];
    
        public function pet()
        {
            return $this->belongsTo(Pet::class);
        }
    
        public function veterinarian()
        {
            return $this->belongsTo(User::class, 'veterinarian_id');
        }
    
        public function vaccine()
        {
            return $this->belongsTo(Vaccine::class);
        }
    }
    
    // Aşı Ürünü Modeli
    class Vaccine extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'name',
            'manufacturer',
            'type',
            'description',
            'stock',
            'price',
        ];
    
        public function vaccinations()
        {
            return $this->hasMany(Vaccination::class);
        }
    }
    
    // İlaç Modeli
    class Medication extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'name',
            'description',
            'category',
            'manufacturer',
            'stock',
            'unit',
            'price',
            'expiry_date',
            'batch_number',
        ];
    
        protected $casts = [
            'expiry_date' => 'date',
        ];
    
        public function prescriptions()
        {
            return $this->belongsToMany(Prescription::class)
                ->withPivot('dosage', 'instructions', 'quantity')
                ->withTimestamps();
        }
    }
    
    // Reçete Modeli
    class Prescription extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'medical_record_id',
            'date',
            'notes',
        ];
    
        protected $casts = [
            'date' => 'date',
        ];
    
        public function medicalRecord()
        {
            return $this->belongsTo(MedicalRecord::class);
        }
    
        public function medications()
        {
            return $this->belongsToMany(Medication::class)
                ->withPivot('dosage', 'instructions', 'quantity')
                ->withTimestamps();
        }
    }
    
    // Fatura Modeli
    class Invoice extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'customer_id',
            'invoice_number',
            'date',
            'due_date',
            'total_amount',
            'paid_amount',
            'payment_status',
            'payment_method',
            'notes',
        ];
    
        protected $casts = [
            'date' => 'date',
            'due_date' => 'date',
        ];
    
        public function customer()
        {
            return $this->belongsTo(Customer::class);
        }
    
        public function invoiceItems()
        {
            return $this->hasMany(InvoiceItem::class);
        }
    }
    
    // Fatura Kalemi Modeli
    class InvoiceItem extends Model
    {
        use HasFactory;
    
        protected $fillable = [
            'invoice_id',
            'description',
            'quantity',
            'unit_price',
            'tax_rate',
            'amount',
        ];
    
        public function invoice()
        {
            return $this->belongsTo(Invoice::class);
        }
    }
    
    // Filament Resource'ları
    
    namespace App\Filament\Resources;
    
    use App\Filament\Resources\CustomerResource\Pages;
    use App\Models\Customer;
    use Filament\Forms;
    use Filament\Resources\Form;
    use Filament\Resources\Resource;
    use Filament\Resources\Table;
    use Filament\Tables;
    
    class CustomerResource extends Resource
    {
        protected static ?string $model = Customer::class;
        protected static ?string $navigationIcon = 'heroicon-o-users';
        protected static ?string $navigationGroup = 'Müşteri Yönetimi';
    
        public static function form(Form $form): Form
        {
            return $form
                ->schema([
                    Forms\Components\Card::make()
                        ->schema([
                            Forms\Components\TextInput::make('name')
                                ->label('Ad')
                                ->required(),
                            Forms\Components\TextInput::make('surname')
                                ->label('Soyad')
                                ->required(),
                            Forms\Components\TextInput::make('phone')
                                ->label('Telefon')
                                ->tel()
                                ->required(),
                            Forms\Components\TextInput::make('email')
                                ->label('E-posta')
                                ->email(),
                            Forms\Components\Textarea::make('address')
                                ->label('Adres')
                                ->rows(3),
                            Forms\Components\TextInput::make('city')
                                ->label('Şehir'),
                            Forms\Components\TextInput::make('tax_number')
                                ->label('Vergi No'),
                            Forms\Components\TextInput::make('tax_office')
                                ->label('Vergi Dairesi'),
                            Forms\Components\Textarea::make('notes')
                                ->label('Notlar')
                                ->rows(3),
                            Forms\Components\Select::make('status')
                                ->label('Durum')
                                ->options([
                                    'active' => 'Aktif',
                                    'passive' => 'Pasif',
                                ])
                                ->default('active'),
                        ])->columns(2),
                ]);
        }
    
        public static function table(Table $table): Table
        {
            return $table
                ->columns([
                    Tables\Columns\TextColumn::make('name')
                        ->label('Ad')
                        ->searchable()
                        ->sortable(),
                    Tables\Columns\TextColumn::make('surname')
                        ->label('Soyad')
                        ->searchable()
                        ->sortable(),
                    Tables\Columns\TextColumn::make('phone')
                        ->label('Telefon'),
                    Tables\Columns\TextColumn::make('email')
                        ->label('E-posta'),
                    Tables\Columns\BadgeColumn::make('status')
                        ->label('Durum')
                        ->colors([
                            'success' => 'active',
                            'danger' => 'passive',
                        ])
                        ->enum([
                            'active' => 'Aktif',
                            'passive' => 'Pasif',
                        ]),
                    Tables\Columns\TextColumn::make('pets_count')
                        ->label('Hayvan Sayısı')
                        ->counts('pets'),
                ])
                ->filters([
                    Tables\Filters\SelectFilter::make('status')
                        ->label('Durum')
                        ->options([
                            'active' => 'Aktif',
                            'passive' => 'Pasif',
                        ]),
                ])
                ->actions([
                    Tables\Actions\EditAction::make(),
                    Tables\Actions\DeleteAction::make(),
                ])
                ->bulkActions([
                    Tables\Actions\DeleteBulkAction::make(),
                ]);
        }
    
        public static function getRelations(): array
        {
            return [
                RelationManagers\PetsRelationManager::class,
                RelationManagers\AppointmentsRelationManager::class,
                RelationManagers\InvoicesRelationManager::class,
            ];
        }
    
        public static function getPages(): array
        {
            return [
                'index' => Pages\ListCustomers::route('/'),
                'create' => Pages\CreateCustomer::route('/create'),
                'edit' => Pages\EditCustomer::route('/{record}/edit'),
            ];
        }
    }
    
    namespace App\Filament\Resources;
    
    use App\Filament\Resources\PetResource\Pages;
    use App\Models\Pet;
    use Filament\Forms;
    use Filament\Resources\Form;
    use Filament\Resources\Resource;
    use Filament\Resources\Table;
    use Filament\Tables;
    
    class PetResource extends Resource
    {
        protected static ?string $model = Pet::class;
        protected static ?string $navigationIcon = 'heroicon-o-heart';
        protected static ?string $navigationGroup = 'Hasta Yönetimi';
    
        public static function form(Form $form): Form
        {
            return $form
                ->schema([
                    Forms\Components\Card::make()
                        ->schema([
                            Forms\Components\Select::make('customer_id')
                                ->label('Müşteri')
                                ->relationship('customer', 'name')
                                ->searchable()
                                ->required(),
                            Forms\Components\TextInput::make('name')
                                ->label('Adı')
                                ->required(),
                            Forms\Components\Select::make('species')
                                ->label('Tür')
                                ->options([
                                    'dog' => 'Köpek',
                                    'cat' => 'Kedi',
                                    'bird' => 'Kuş',
                                    'rabbit' => 'Tavşan',
                                    'other' => 'Diğer',
                                ])
                                ->required(),
                            Forms\Components\TextInput::make('breed')
                                ->label('Irk'),
                            Forms\Components\Select::make('gender')
                                ->label('Cinsiyet')
                                ->options([
                                    'male' => 'Erkek',
                                    'female' => 'Dişi',
                                    'unknown' => 'Bilinmiyor',
                                ]),
                            Forms\Components\DatePicker::make('date_of_birth')
                                ->label('Doğum Tarihi'),
                            Forms\Components\TextInput::make('color')
                                ->label('Renk'),
                            Forms\Components\TextInput::make('microchip_number')
                                ->label('Mikroçip Numarası')
                                ->unique(ignoreRecord: true),
                            Forms\Components\TextInput::make('weight')
                                ->label('Ağırlık (kg)')
                                ->numeric()
                                ->step(0.01),
                            Forms\Components\Select::make('status')
                                ->label('Durum')
                                ->options([
                                    'active' => 'Aktif',
                                    'deceased' => 'Vefat Etmiş',
                                ])
                                ->default('active'),
                            Forms\Components\Textarea::make('notes')
                                ->label('Notlar')
                                ->rows(3),
                        ])->columns(2),
                ]);
        }
    
        public static function table(Table $table): Table
        {
            return $table
                ->columns([
                    Tables\Columns\TextColumn::make('name')
                        ->label('Adı')
                        ->searchable()
                        ->sortable(),
                    Tables\Columns\TextColumn::make('customer.name')
                        ->label('Müşteri')
                        ->searchable()
                        ->sortable(),
                    Tables\Columns\SelectColumn::make('species')
                        ->label('Tür')
                        ->options([
                            'dog' => 'Köpek',
                            'cat' => 'Kedi',
                            'bird' => 'Kuş',
                            'rabbit' => 'Tavşan',
                            'other' => 'Diğer',
                        ]),
                    Tables\Columns\TextColumn::make('breed')
                        ->label('Irk'),
                    Tables\Columns\TextColumn::make('date_of_birth')
                        ->label('Doğum Tarihi')
                        ->date(),
                    Tables\Columns\BadgeColumn::make('status')
                        ->label('Durum')
                        ->colors([
                            'success' => 'active',
                            'danger' => 'deceased',
                        ])
                        ->enum([
                            'active' => 'Aktif',
                            'deceased' => 'Vefat Etmiş',
                        ]),
                ])
                ->filters([
                    Tables\Filters\SelectFilter::make('species')
                        ->label('Tür')
                        ->options([
                            'dog' => 'Köpek',
                            'cat' => 'Kedi',
                            'bird' => 'Kuş',
                            'rabbit' => 'Tavşan',
                            'other' => 'Diğer',
                        ]),
                    Tables\Filters\SelectFilter::make('status')
                        ->label('Durum')
                        ->options([
                            'active' => 'Aktif',
                            'deceased' => 'Vefat Etmiş',
                        ]),
                ])
                ->actions([
                    Tables\Actions\EditAction::make(),
                    Tables\Actions\DeleteAction::make(),
                ])
                ->bulkActions([
                    Tables\Actions\DeleteBulkAction::make(),
                ]);
        }
    
        public static function getRelations(): array
        {
            return [
                RelationManagers\MedicalRecordsRelationManager::class,
                RelationManagers\VaccinationsRelationManager::class,
                RelationManagers\AppointmentsRelationManager::class,
            ];
        }
    
        public static function getPages(): array
        {
            return [
                'index' => Pages\ListPets::route('/'),
                'create' => Pages\CreatePet::route('/create'),
                'edit' => Pages\EditPet::route('/{record}/edit'),
            ];
        }
    }
    
    // Randevu Dashboard Filament Widget
    namespace App\Filament\Widgets;
    
    use App\Models\Appointment;
    use Carbon\Carbon;
    use Filament\Widgets\TableWidget as BaseWidget;
    use Filament\Tables;
    use Illuminate\Database\Eloquent\Builder;
    
    class AppointmentsToday extends BaseWidget
    {
        protected int | string | array $columnSpan = 'full';
        protected static ?string $heading = 'Bugünkü Randevular';
    
        protected function getTableQuery(): Builder
        {
            return Appointment::query()
                ->where('date', Carbon::today())
                ->orderBy('time');
        }
    
        protected function getTableColumns(): array
        {
            return [
                Tables\Columns\TextColumn::make('time')
                    ->label('Saat')
                    ->time(),
                Tables\Columns\TextColumn::make('pet.name')
                    ->label('Hasta'),
                Tables\Columns\TextColumn::make('customer.name')
                    ->label('Müşteri'),
                Tables\Columns\TextColumn::make('reason')
                    ->label('Sebep')
                    ->limit(30),
                Tables\Columns\BadgeColumn::make('status')
                    ->label('Durum')
                    ->colors([
                        'warning' => 'scheduled',
                        'success' => 'completed',
                        'danger' => 'cancelled',
                    ])
                    ->enum([
                        'scheduled' => 'Planlandı',
                        'completed' => 'Tamamlandı',
                        'cancelled' => 'İptal Edildi',
                    ]),
                Tables\Columns\TextColumn::make('veterinarian.name')
                    ->label('Veteriner'),
            ];
        }
    
        protected function getTableActions(): array
        {
            return [
                Tables\Actions\Action::make('complete')
                    ->label('Tamamla')
                    ->color('success')
                    ->icon('heroicon-o-check')
                    ->action(function (Appointment $record): void {
                        $record->update(['status' => 'completed']);
                    })
                    ->visible(fn (Appointment $record): bool => $record->status === 'scheduled'),
                
                Tables\Actions\Action::make('cancel')
                    ->label('İptal Et')
                    ->color('danger')
                    ->icon('heroicon-o-x')
                    ->action(function (Appointment $record): void {
                        $record->update(['status' => 'cancelled']);
                    })
                    ->visible(fn (Appointment $record): bool => $record->status === 'scheduled'),
            ];
        }
    }
    
    // Dashboard özeti widget'ı 
    namespace App\Filament\Widgets;
    
    use App\Models\Appointment;
    use App\Models\Customer;
    use App\Models\Pet;
    use Carbon\Carbon;
    use Filament\Widgets\StatsOverviewWidget as BaseWidget;
    use Filament\Widgets\StatsOverviewWidget\Card;
    
    class StatsOverview extends BaseWidget
    {
        protected function getCards(): array
        {
            return [
                Card::make('Toplam Müşteri', Customer::count())
                    ->description('Sistemde kayıtlı tüm müşteriler')
                    ->descriptionIcon('heroicon-s-users')
                    ->color('success'),
                
                Card::make('Toplam Hasta', Pet::count())
                    ->description('Sistemde kayıtlı tüm hayvanlar')
                    ->descriptionIcon('heroicon-s-heart')
                    ->color('primary'),
                
                Card::make('Bugünkü Randevular', Appointment::whereDate('date', Carbon::today())->count())
                    ->description('Bugün için planlanmış randevular')
                    ->descriptionIcon('heroicon-s-calendar')
                    ->color('warning'),
                
                Card::make('Bu Ayki Randevular', Appointment::whereMonth('date', Carbon::now()->month)
                    ->whereYear('date', Carbon::now()->year)
                    ->count())
                    ->description('Bu ay için planlanmış randevular')
                    ->descriptionIcon('heroicon-s-calendar')
                    ->color('danger'),
            ];
        }
    }

    Laravel ve Filament ile veteriner kliniğiniz için harika bir yönetim sistemi oluşturabilirsiniz. İşte bazı önerilerim:

    1. Ana Modüller:

      • Müşteri (Hayvan Sahipleri) Yönetimi
      • Hasta (Hayvanlar) Yönetimi
      • Randevu Sistemi
      • Tıbbi Kayıtlar
      • Aşı Takibi
      • Reçete ve İlaç Yönetimi
      • Faturalama ve Ödeme Takibi
      • Raporlama ve İstatistikler
    2. Filament Admin Panel Kullanımı:
      Filament, Laravel üzerinde hızlı ve şık admin panelleri oluşturmanıza olanak tanır. İçerdiği özellikler:

      • Hazır CRUD (Oluştur-Oku-Güncelle-Sil) işlemleri
      • İlişkisel modeller için yönetim arayüzleri
      • Dashboard widget'ları
      • Form bileşenleri ve doğrulama
      • Tablolar, filtreler ve arama özellikleri
    3. Başlarken:

         composer require filament/filament
         php artisan filament:install
    4. Performans için İpuçları:

      • İlişkili modelleri eager loading kullanarak yükleyin
      • Aşı ve randevu hatırlatmaları için önbellekleme kullanın
      • Büyük veri setleri için sayfalama uygulayın
    5. Güvenlik Önlemleri:

      • Rol ve izin tabanlı erişim kontrolü ekleyin
      • Hassas hasta verilerini şifreleyin
      • Yetkilendirme politikaları oluşturun

    Artifact'ta sisteminiz için başlangıç kodu modellerini ve Filament resource'larını oluşturdum. Bu modeller arasında müşteriler, hastalar, tıbbi kayıtlar, randevular, aşılar, ilaçlar ve faturalama bulunmakta. Ayrıca, bugünkü randevuları gösteren bir dashboard widget'ı ile temel istatistikler için bir özet widget'ı ekledim.

    Başka sorularınız veya ilave ihtiyaçlarınız olursa, lütfen sormaktan çekinmeyin. Laravel ve Filament ile veteriner kliniği yönetim sistemini geliştirme sürecinizde size yardımcı olmaktan memnuniyet duyarim

      Amacınız bir yönetim uygulaması yapmaksa cursor ai ye yaptırın. Öğrenmekse, nacizane tavsiyem neyin ne oldugunu kavrayarak ilerleyin. Örneğin laravel bir php freamworku olmasına rağmen neden node.js e ihtiyaç duyuyor gibi...

      koti42
      hocam emeğinize sağlık hemen hemen düşündüğüm modeller Müşteri formunu Daha geniş olarak düşündümbu şekilde bir Protokol No Hem Müşteri'de otomatik artan değer olacak hemde Hasta hayvan yönetiminde yapmayı planlıyorum Müşterinin birden fazla hayvanı olduğunda Protokol numarası kullanılabilir Hastanın protokol numarası ise O hastanın yapılan laboratuvar analizleri için daha uygun olur diye düşündüm.

      Tab_1 Form
      Adı Soyadı
      Protokol No
      Borç
      Ödeme
      Bakiye
      İletişim Tipi
      Sms-Email-Gsm
      Telefon
      Kimlik No
      Açıklama
      adres Tab_2 Form
      Şehir
      ilçe
      Köy-Mahalle
      adres
      özel Tab_3
      Durum
      Beni Uyar
      Meslek
      doğum Tarihi
      Tüzel mi Evet-Hayır
      Tüzel Ünvan
      Vergi No
      Vergi Dairesi

      koti42 hocam merhaba bu yazılımla ilgili bir süre ara verdim yazmaya ve bu konuda zamanınız varsa kontrol edebilir miyiz uzak bağlantıyla takıldığım bir yer vardı en son kafam karıştı.

        umutcankarce Çok fazla bir vaktim olmuyor ama takıldığın yeri paylaşabilirsen yardımcı olurum elbette