Logic fixed

This commit is contained in:
2025-11-08 16:55:41 +03:00
parent 495e6ae1a2
commit b091a0e3fc
16 changed files with 788 additions and 497 deletions

View File

@@ -1,4 +1,4 @@
# Yakıt Takip Modülü # Yakıt Takip Uygulaması
Akaryakıt istasyonu için geliştirilmiş modern ve kullanıcı dostu yönetim sistemi. Akaryakıt istasyonu için geliştirilmiş modern ve kullanıcı dostu yönetim sistemi.
@@ -206,4 +206,4 @@ Proje hakkında sorularınız için lütfen iletişime geçin.
--- ---
**Yakıt Takip Modülü** - Modern Akaryakıt İstasyonu Yönetim Sistemi **Yakıt Takip Uygulaması** - Modern Akaryakıt İstasyonu Yönetim Sistemi

View File

@@ -1,4 +1,4 @@
# Yakıt Takip Modülü - Kapsamlı Proje Dokümantasyonu # Yakıt Takip Uygulaması - Kapsamlı Proje Dokümantasyonu
## 📋 İçerik Tablosu ## 📋 İçerik Tablosu
1. [Proje Genel Bakış](#proje-genel-bakış) 1. [Proje Genel Bakış](#proje-genel-bakış)
@@ -18,7 +18,7 @@
## 🎯 Proje Genel Bakış ## 🎯 Proje Genel Bakış
Yakıt Takip Modülü, akaryakıt istasyonları için geliştirilmiş, modern ve kullanıcı dostu bir yönetim sistemidir. Sistem, yakıt ikmal süreçlerini dijitalleştirerek verimliliği artırmayı ve süreç takibini kolaylaştırmayı hedefler. Yakıt Takip Uygulaması, akaryakıt istasyonları için geliştirilmiş, modern ve kullanıcı dostu bir yönetim sistemidir. Sistem, yakıt ikmal süreçlerini dijitalleştirerek verimliliği artırmayı ve süreç takibini kolaylaştırmayı hedefler.
### Ana Hedefler ### Ana Hedefler
- **Dijital Dönüşüm**: Kağıt bazlı süreçlerin dijitalleştirilmesi - **Dijital Dönüşüm**: Kağıt bazlı süreçlerin dijitalleştirilmesi
@@ -1732,6 +1732,6 @@ echo "Recovery completed. Services restarting..."
--- ---
**Bu dokümantasyon Yakıt Takip Modülü projesinin kapsamlı süreçlerini ve teknik detaylarını içermektedir. Güncel kalmak için düzenli olarak gözden geçirilmeli ve güncellenmelidir.** **Bu dokümantasyon Yakıt Takip Uygulaması projesinin kapsamlı süreçlerini ve teknik detaylarını içermektedir. Güncel kalmak için düzenli olarak gözden geçirilmeli ve güncellenmelidir.**
*Son güncelleme: 2024-11-05* *Son güncelleme: 2024-11-05*

View File

@@ -1,6 +1,6 @@
# Yakıt Takip Modülü - Dokümantasyon # Yakıt Takip Uygulaması - Dokümantasyon
Bu klasörde Yakıt Takip Modülü'nün tüm dokümantasyon dosyaları bulunmaktadır. Bu klasörde Yakıt Takip Uygulaması'nın tüm dokümantasyon dosyaları bulunmaktadır.
## 📚 Dokümantasyon Dosyaları ## 📚 Dokümantasyon Dosyaları

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⛽</text></svg>" /> <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⛽</text></svg>" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>Yakıt Takip Modülü</title> <title>Yakıt Takip Uygulaması</title>
<!-- Font Awesome CDN --> <!-- Font Awesome CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
%sveltekit.head% %sveltekit.head%

View File

@@ -2,8 +2,8 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
export let user = null; export let user = null;
let personnel = []; let personnel = [];
let units = []; let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -11,15 +11,15 @@
let selectedPersonnel = null; let selectedPersonnel = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '', unit_id: '',
is_active: true is_active: true
}; };
onMount(async () => { onMount(async () => {
const userData = localStorage.getItem('user'); const userData = localStorage.getItem('user');
@@ -36,10 +36,10 @@
async function loadPersonnel() { async function loadPersonnel() {
try { try {
const response = await fetch('/api/fuel-personnel'); const response = await fetch('/api/unit-personnel');
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
personnel = data.fuelPersonnel || []; personnel = data.goodsManagers || [];
} else { } else {
error = 'Personel bilgileri yüklenemedi.'; error = 'Personel bilgileri yüklenemedi.';
} }
@@ -68,18 +68,18 @@
return units.find((unit) => unit.id === id)?.name || 'Belirtilmemiş'; return units.find((unit) => unit.id === id)?.name || 'Belirtilmemiş';
} }
function resetForm() { function resetForm() {
formData = { formData = {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '', unit_id: '',
is_active: true is_active: true
}; };
selectedPersonnel = null; selectedPersonnel = null;
} }
function openAddModal() { function openAddModal() {
resetForm(); resetForm();
@@ -88,15 +88,15 @@
function openEditModal(person) { function openEditModal(person) {
selectedPersonnel = person; selectedPersonnel = person;
formData = { formData = {
full_name: person.full_name, full_name: person.full_name,
rank: person.rank, rank: person.rank,
registration_number: person.registration_number, registration_number: person.registration_number,
tc_kimlik: person.tc_kimlik, tc_kimlik: person.tc_kimlik,
phone: person.phone, phone: person.phone,
unit_id: person.unit_id || '', unit_id: person.unit_id || '',
is_active: person.is_active is_active: person.is_active
}; };
showEditModal = true; showEditModal = true;
} }
@@ -107,10 +107,10 @@
} }
async function handleAddPersonnel() { async function handleAddPersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
@@ -118,7 +118,7 @@
} }
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -142,10 +142,10 @@
} }
async function handleUpdatePersonnel() { async function handleUpdatePersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
@@ -153,7 +153,7 @@
} }
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -185,7 +185,7 @@
} }
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -209,7 +209,7 @@
async function togglePersonnelStatus(person) { async function togglePersonnelStatus(person) {
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@@ -5,7 +5,6 @@
export let user = null; export let user = null;
let personnel = []; let personnel = [];
let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -19,27 +18,13 @@ let formData = {
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '',
is_active: true is_active: true
}; };
onMount(async () => { onMount(async () => {
await loadUnits();
await loadPersonnel(); await loadPersonnel();
}); });
async function loadUnits() {
try {
const response = await fetch('/api/units');
if (response.ok) {
const data = await response.json();
units = data.units || [];
}
} catch (err) {
console.error('Load units error:', err);
}
}
async function loadPersonnel() { async function loadPersonnel() {
try { try {
const response = await fetch('/api/fuel-personnel'); const response = await fetch('/api/fuel-personnel');
@@ -64,7 +49,6 @@ function resetForm() {
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '',
is_active: true is_active: true
}; };
selectedPersonnel = null; selectedPersonnel = null;
@@ -83,7 +67,6 @@ function openEditModal(person) {
registration_number: person.registration_number, registration_number: person.registration_number,
tc_kimlik: person.tc_kimlik, tc_kimlik: person.tc_kimlik,
phone: person.phone, phone: person.phone,
unit_id: person.unit_id || '',
is_active: person.is_active is_active: person.is_active
}; };
showEditModal = true; showEditModal = true;
@@ -96,7 +79,7 @@ function openEditModal(person) {
} }
async function handleAddPersonnel() { async function handleAddPersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -131,7 +114,7 @@ function openEditModal(person) {
} }
async function handleUpdatePersonnel() { async function handleUpdatePersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -295,16 +278,25 @@ function openEditModal(person) {
<span class="detail-value">{person.tc_kimlik}</span> <span class="detail-value">{person.tc_kimlik}</span>
</div> </div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<div class="detail-icon"> <div class="detail-icon">
<i class="fas fa-phone"></i> <i class="fas fa-phone"></i>
</div> </div>
<div class="detail-content"> <div class="detail-content">
<span class="detail-label">İrtibat:</span> <span class="detail-label">İrtibat:</span>
<span class="detail-value">{person.phone}</span> <span class="detail-value">{person.phone}</span>
</div> </div>
</div> </div>
</div> <div class="detail-item">
<div class="detail-icon">
<i class="fas fa-gas-pump"></i>
</div>
<div class="detail-content">
<span class="detail-label">Görev Yeri:</span>
<span class="detail-value">Fuel Station</span>
</div>
</div>
</div>
<div class="personnel-actions"> <div class="personnel-actions">
<button class="btn btn-sm btn-secondary" on:click={() => openEditModal(person)}> <button class="btn btn-sm btn-secondary" on:click={() => openEditModal(person)}>
@@ -399,20 +391,6 @@ function openEditModal(person) {
required required
/> />
</div> </div>
<div class="form-group">
<label for="unit_id">Birlik</label>
<select
id="unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button> <button type="submit" class="btn btn-primary">Kaydet</button>
@@ -487,20 +465,6 @@ function openEditModal(person) {
required required
/> />
</div> </div>
<div class="form-group">
<label for="edit-unit_id">Birlik</label>
<select
id="edit-unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group"> <div class="form-group">
<label class="checkbox-label"> <label class="checkbox-label">
<input <input

View File

@@ -4,7 +4,8 @@
// Props // Props
export let user = null; export let user = null;
let vehicles = []; let vehicles = [];
let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -12,21 +13,35 @@
let selectedVehicle = null; let selectedVehicle = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
brand: '', brand: '',
model: '', model: '',
year: new Date().getFullYear(), year: new Date().getFullYear(),
plate: '', plate: '',
fuel_type: 'Benzin', unit_id: '',
fuel_capacity: 50, fuel_type: 'Benzin',
current_fuel: 0, fuel_capacity: 50,
yazlik_mukannen: 0, current_fuel: 0,
kislik_mukannen: 0 yazlik_mukannen: 0,
}; kislik_mukannen: 0
};
onMount(async () => { onMount(async () => {
await loadVehicles(); await loadUnits();
}); await loadVehicles();
});
async function loadUnits() {
try {
const response = await fetch('/api/units');
if (response.ok) {
const data = await response.json();
units = data.units || [];
}
} catch (err) {
console.error('Load units error:', err);
}
}
async function loadVehicles() { async function loadVehicles() {
try { try {
@@ -45,18 +60,19 @@
} }
} }
function resetForm() { function resetForm() {
formData = { formData = {
brand: '', brand: '',
model: '', model: '',
year: new Date().getFullYear(), year: new Date().getFullYear(),
plate: '', plate: '',
fuel_type: 'Benzin', unit_id: '',
fuel_capacity: 50, fuel_type: 'Benzin',
current_fuel: 0, fuel_capacity: 50,
yazlik_mukannen: 0, current_fuel: 0,
kislik_mukannen: 0 yazlik_mukannen: 0,
}; kislik_mukannen: 0
};
selectedVehicle = null; selectedVehicle = null;
} }
@@ -65,19 +81,20 @@
showAddModal = true; showAddModal = true;
} }
function openEditModal(vehicle) { function openEditModal(vehicle) {
selectedVehicle = vehicle; selectedVehicle = vehicle;
formData = { formData = {
brand: vehicle.brand, brand: vehicle.brand,
model: vehicle.model, model: vehicle.model,
year: vehicle.year, year: vehicle.year,
plate: vehicle.plate, plate: vehicle.plate,
fuel_type: vehicle.fuel_type || 'Benzin', unit_id: vehicle.unit_id ? vehicle.unit_id.toString() : '',
fuel_capacity: vehicle.fuel_capacity || 50, fuel_type: vehicle.fuel_type || 'Benzin',
current_fuel: vehicle.current_fuel || 0, fuel_capacity: vehicle.fuel_capacity || 50,
yazlik_mukannen: vehicle.yazlik_mukannen || 0, current_fuel: vehicle.current_fuel || 0,
kislik_mukannen: vehicle.kislik_mukannen || 0 yazlik_mukannen: vehicle.yazlik_mukannen || 0,
}; kislik_mukannen: vehicle.kislik_mukannen || 0
};
showEditModal = true; showEditModal = true;
} }
@@ -87,30 +104,43 @@
resetForm(); resetForm();
} }
function validateMukannen(value) { function validateMukannen(value) {
// Sadece pozitif tam sayı kabul et if (value === '' || value === null || value === undefined) {
return /^[0-9]*$/.test(value) && value >= 0; return true;
} }
const normalizedValue = typeof value === 'number' ? value : parseFloat(value.toString().replace(',', '.'));
return !isNaN(normalizedValue) && normalizedValue >= 0;
}
function getUnitName(unitId, unitList = units) {
const id = parseInt(unitId);
return unitList.find((unit) => unit.id === id)?.name || 'Belirtilmemiş';
}
async function handleAddVehicle() { async function handleAddVehicle() {
if (!formData.brand || !formData.model || !formData.year || !formData.plate || !formData.fuel_type || !formData.fuel_capacity) { if (!formData.brand || !formData.model || !formData.year || !formData.plate || !formData.unit_id || !formData.fuel_type || !formData.fuel_capacity) {
error = 'Tüm zorunlu alanları doldurun.'; error = 'Tüm zorunlu alanları doldurun.';
return; return;
} }
if (!validateMukannen(formData.yazlik_mukannen) || !validateMukannen(formData.kislik_mukannen)) { if (!validateMukannen(formData.yazlik_mukannen) || !validateMukannen(formData.kislik_mukannen)) {
error = 'Mukannen değerleri sadece rakam içermelidir.'; error = 'Mukannen değerleri sayısal olmalı ve negatif olamaz.';
return; return;
} }
try { try {
const response = await fetch('/api/vehicles', { const payload = {
method: 'POST', ...formData,
headers: { unit_id: parseInt(formData.unit_id)
'Content-Type': 'application/json', };
}, const response = await fetch('/api/vehicles', {
body: JSON.stringify(formData), method: 'POST',
}); headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = await response.json(); const data = await response.json();
@@ -128,27 +158,29 @@
} }
async function handleUpdateVehicle() { async function handleUpdateVehicle() {
if (!formData.brand || !formData.model || !formData.year || !formData.plate || !formData.fuel_type || !formData.fuel_capacity) { if (!formData.brand || !formData.model || !formData.year || !formData.plate || !formData.unit_id || !formData.fuel_type || !formData.fuel_capacity) {
error = 'Tüm zorunlu alanları doldurun.'; error = 'Tüm zorunlu alanları doldurun.';
return; return;
} }
if (!validateMukannen(formData.yazlik_mukannen) || !validateMukannen(formData.kislik_mukannen)) { if (!validateMukannen(formData.yazlik_mukannen) || !validateMukannen(formData.kislik_mukannen)) {
error = 'Mukannen değerleri sadece rakam içermelidir.'; error = 'Mukannen değerleri sayısal olmalı ve negatif olamaz.';
return; return;
} }
try { try {
const response = await fetch('/api/vehicles', { const payload = {
method: 'PUT', id: selectedVehicle.id,
headers: { ...formData,
'Content-Type': 'application/json', unit_id: parseInt(formData.unit_id)
}, };
body: JSON.stringify({ const response = await fetch('/api/vehicles', {
id: selectedVehicle.id, method: 'PUT',
...formData headers: {
}), 'Content-Type': 'application/json',
}); },
body: JSON.stringify(payload),
});
const data = await response.json(); const data = await response.json();
@@ -253,6 +285,9 @@
<span class="plate-badge"><i class="fas fa-car"></i> {vehicle.plate}</span> <span class="plate-badge"><i class="fas fa-car"></i> {vehicle.plate}</span>
</div> </div>
</div> </div>
<p class="vehicle-unit">
<i class="fas fa-building"></i> {vehicle.unit_name || getUnitName(vehicle.unit_id, units)}
</p>
<div class="vehicle-actions"> <div class="vehicle-actions">
<button class="btn btn-sm btn-secondary" on:click={() => openEditModal(vehicle)}> <button class="btn btn-sm btn-secondary" on:click={() => openEditModal(vehicle)}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -318,17 +353,31 @@
required required
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="plate">Plaka</label> <label for="plate">Plaka</label>
<input <input
id="plate" id="plate"
type="text" type="text"
class="form-input" class="form-input"
bind:value={formData.plate} bind:value={formData.plate}
placeholder="34ABC123" placeholder="34ABC123"
required required
/> />
</div> </div>
<div class="form-group">
<label for="unit_id">Birlik</label>
<select
id="unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group"> <div class="form-group">
<label for="fuel_type">Yakıt Tipi</label> <label for="fuel_type">Yakıt Tipi</label>
<select <select
@@ -379,10 +428,9 @@
class="form-input" class="form-input"
bind:value={formData.yazlik_mukannen} bind:value={formData.yazlik_mukannen}
min="0" min="0"
step="1" step="0.01"
placeholder="0" placeholder="0"
pattern="[0-9]*" inputmode="decimal"
inputmode="numeric"
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
@@ -393,10 +441,9 @@
class="form-input" class="form-input"
bind:value={formData.kislik_mukannen} bind:value={formData.kislik_mukannen}
min="0" min="0"
step="1" step="0.01"
placeholder="0" placeholder="0"
pattern="[0-9]*" inputmode="decimal"
inputmode="numeric"
/> />
</div> </div>
<div class="modal-actions"> <div class="modal-actions">
@@ -451,17 +498,31 @@
required required
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="edit-plate">Plaka</label> <label for="edit-plate">Plaka</label>
<input <input
id="edit-plate" id="edit-plate"
type="text" type="text"
class="form-input" class="form-input"
bind:value={formData.plate} bind:value={formData.plate}
placeholder="34ABC123" placeholder="34ABC123"
required required
/> />
</div> </div>
<div class="form-group">
<label for="edit-unit_id">Birlik</label>
<select
id="edit-unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group"> <div class="form-group">
<label for="edit-fuel_type">Yakıt Tipi</label> <label for="edit-fuel_type">Yakıt Tipi</label>
<select <select
@@ -512,10 +573,9 @@
class="form-input" class="form-input"
bind:value={formData.yazlik_mukannen} bind:value={formData.yazlik_mukannen}
min="0" min="0"
step="1" step="0.01"
placeholder="0" placeholder="0"
pattern="[0-9]*" inputmode="decimal"
inputmode="numeric"
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
@@ -526,10 +586,9 @@
class="form-input" class="form-input"
bind:value={formData.kislik_mukannen} bind:value={formData.kislik_mukannen}
min="0" min="0"
step="1" step="0.01"
placeholder="0" placeholder="0"
pattern="[0-9]*" inputmode="decimal"
inputmode="numeric"
/> />
</div> </div>
<div class="modal-actions"> <div class="modal-actions">
@@ -664,6 +723,15 @@
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.vehicle-unit {
margin: 0 0 1rem;
color: var(--text-secondary);
font-weight: 600;
display: flex;
align-items: center;
gap: 0.4rem;
}
.vehicle-info h3 { .vehicle-info h3 {
font-size: 1.2rem; font-size: 1.2rem;
font-weight: 600; font-weight: 600;
@@ -826,4 +894,4 @@
flex-direction: column; flex-direction: column;
} }
} }
</style> </style>

View File

@@ -44,7 +44,7 @@
</script> </script>
<svelte:head> <svelte:head>
<title>Yakıt Takip Modülü</title> <title>Yakıt Takip Uygulaması</title>
<meta name="description" content="Akaryakıt İstasyonu Yönetim Sistemi" /> <meta name="description" content="Akaryakıt İstasyonu Yönetim Sistemi" />
</svelte:head> </svelte:head>

View File

@@ -83,7 +83,7 @@
<img src="/logo.png" alt="YTP Logo" class="app-logo" /> <img src="/logo.png" alt="YTP Logo" class="app-logo" />
</div> </div>
<h1 class="app-title">Giriş</h1> <h1 class="app-title">Giriş</h1>
<p class="app-subtitle">Yakıt Takip Modülü</p> <p class="app-subtitle">Yakıt Takip Uygulaması</p>
</div> </div>
<form on:submit|preventDefault={handleLogin} class="space-y-6"> <form on:submit|preventDefault={handleLogin} class="space-y-6">

View File

@@ -0,0 +1,5 @@
import { json } from '@sveltejs/kit';
export function GET() {
return json({ status: 'ok' });
}

View File

@@ -159,7 +159,7 @@
fetch("/api/vehicles"), fetch("/api/vehicles"),
fetch("/api/units"), fetch("/api/units"),
fetch("/api/fuel-personnel"), fetch("/api/fuel-personnel"),
fetch("/api/goods-managers") fetch("/api/unit-personnel")
]); ]);
if (vehiclesRes.ok) { if (vehiclesRes.ok) {

View File

@@ -44,10 +44,10 @@ let formData = {
async function loadGoodsManagers() { async function loadGoodsManagers() {
try { try {
const response = await fetch('/api/fuel-personnel'); const response = await fetch('/api/unit-personnel');
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
personnel = data.fuelPersonnel || []; personnel = data.goodsManagers || [];
} else { } else {
error = 'Personel bilgileri yüklenemedi.'; error = 'Personel bilgileri yüklenemedi.';
} }
@@ -77,15 +77,15 @@ function getUnitName(unitId) {
} }
function resetForm() { function resetForm() {
formData = { formData = {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '', unit_id: '',
is_active: true is_active: true
}; };
selectedManager = null; selectedManager = null;
} }
@@ -96,15 +96,15 @@ function resetForm() {
function openEditModal(manager) { function openEditModal(manager) {
selectedManager = manager; selectedManager = manager;
formData = { formData = {
full_name: manager.full_name, full_name: manager.full_name,
rank: manager.rank, rank: manager.rank,
registration_number: manager.registration_number, registration_number: manager.registration_number,
tc_kimlik: manager.tc_kimlik, tc_kimlik: manager.tc_kimlik,
phone: manager.phone, phone: manager.phone,
unit_id: manager.unit_id || '', unit_id: manager.unit_id || '',
is_active: manager.is_active is_active: manager.is_active
}; };
showEditModal = true; showEditModal = true;
} }
@@ -120,13 +120,13 @@ async function handleAddManager() {
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
return; return;
} }
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -155,13 +155,13 @@ async function handleUpdateManager() {
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
return; return;
} }
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -193,7 +193,7 @@ async function handleUpdateManager() {
} }
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -217,7 +217,7 @@ async function handleUpdateManager() {
async function toggleManagerStatus(manager) { async function toggleManagerStatus(manager) {
try { try {
const response = await fetch('/api/fuel-personnel', { const response = await fetch('/api/unit-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -895,6 +895,6 @@ async function handleUpdateManager() {
.detail-value { .detail-value {
text-align: left; text-align: left;
}
} }
}
</style> </style>

View File

@@ -11,8 +11,7 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
let user = null; let user = null;
let personnel = []; let personnel = [];
let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -26,7 +25,6 @@
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '',
is_active: true is_active: true
}; };
@@ -38,25 +36,9 @@
} }
user = JSON.parse(userData); user = JSON.parse(userData);
await loadUnits();
await loadPersonnel(); await loadPersonnel();
}); });
async function loadUnits() {
try {
const response = await fetch('/api/units');
if (response.ok) {
const data = await response.json();
units = data.units;
} else {
error = 'Birlik listesi yüklenemedi.';
}
} catch (err) {
error = 'Bağlantı hatası.';
console.error('Load units error:', err);
}
}
async function loadPersonnel() { async function loadPersonnel() {
try { try {
const response = await fetch('/api/fuel-personnel'); const response = await fetch('/api/fuel-personnel');
@@ -81,7 +63,6 @@
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '',
is_active: true is_active: true
}; };
selectedPersonnel = null; selectedPersonnel = null;
@@ -100,7 +81,6 @@
registration_number: person.registration_number, registration_number: person.registration_number,
tc_kimlik: person.tc_kimlik, tc_kimlik: person.tc_kimlik,
phone: person.phone, phone: person.phone,
unit_id: person.unit_id || '',
is_active: person.is_active is_active: person.is_active
}; };
showEditModal = true; showEditModal = true;
@@ -113,7 +93,7 @@
} }
async function handleAddPersonnel() { async function handleAddPersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -148,7 +128,7 @@
} }
async function handleUpdatePersonnel() { async function handleUpdatePersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -328,15 +308,24 @@
<span class="detail-value">{person.tc_kimlik}</span> <span class="detail-value">{person.tc_kimlik}</span>
</div> </div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<div class="detail-icon"> <div class="detail-icon">
<i class="fas fa-phone"></i> <i class="fas fa-phone"></i>
</div>
<div class="detail-content">
<span class="detail-label">İrtibat:</span>
<span class="detail-value">{person.phone}</span>
</div>
</div> </div>
<div class="detail-content">
<span class="detail-label">İrtibat:</span>
<span class="detail-value">{person.phone}</span>
</div>
</div>
<div class="detail-item">
<div class="detail-icon">
<i class="fas fa-gas-pump"></i>
</div>
<div class="detail-content">
<span class="detail-label">Görev Yeri:</span>
<span class="detail-value">Fuel Station</span>
</div>
</div>
</div> </div>
<div class="personnel-actions"> <div class="personnel-actions">
@@ -445,20 +434,6 @@
required required
/> />
</div> </div>
<div class="form-group">
<label for="unit_id">Birlik</label>
<select
id="unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button> <button type="submit" class="btn btn-primary">Kaydet</button>
@@ -533,20 +508,6 @@
required required
/> />
</div> </div>
<div class="form-group">
<label for="edit-unit_id">Birlik</label>
<select
id="edit-unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group"> <div class="form-group">
<label class="checkbox-label"> <label class="checkbox-label">
<input <input
@@ -931,4 +892,4 @@
gap: 0.25rem; gap: 0.25rem;
} }
} }
</style> </style>

View File

@@ -12,6 +12,7 @@
let user = null; let user = null;
let vehicles = []; let vehicles = [];
let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -19,12 +20,13 @@
let selectedVehicle = null; let selectedVehicle = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
brand: '', brand: '',
model: '', model: '',
year: new Date().getFullYear(), year: new Date().getFullYear(),
plate: '' plate: '',
}; unit_id: ''
};
onMount(async () => { onMount(async () => {
const userData = localStorage.getItem('user'); const userData = localStorage.getItem('user');
@@ -33,10 +35,31 @@
return; return;
} }
user = JSON.parse(userData); user = JSON.parse(userData);
await loadVehicles(); await loadUnits();
await loadVehicles();
}); });
async function loadUnits() {
try {
const response = await fetch('/api/units');
if (response.ok) {
const data = await response.json();
units = data.units || [];
} else {
error = 'Birlikler yüklenemedi.';
}
} catch (err) {
error = 'Bağlantı hatası.';
console.error('Load units error:', err);
}
}
function getUnitName(unitId, unitList = units) {
const id = parseInt(unitId);
return unitList.find((unit) => unit.id === id)?.name || 'Belirtilmemiş';
}
async function loadVehicles() { async function loadVehicles() {
try { try {
const response = await fetch('/api/vehicles'); const response = await fetch('/api/vehicles');
@@ -55,12 +78,13 @@
} }
function resetForm() { function resetForm() {
formData = { formData = {
brand: '', brand: '',
model: '', model: '',
year: new Date().getFullYear(), year: new Date().getFullYear(),
plate: '' plate: '',
}; unit_id: ''
};
selectedVehicle = null; selectedVehicle = null;
} }
@@ -71,12 +95,13 @@
function openEditModal(vehicle) { function openEditModal(vehicle) {
selectedVehicle = vehicle; selectedVehicle = vehicle;
formData = { formData = {
brand: vehicle.brand, brand: vehicle.brand,
model: vehicle.model, model: vehicle.model,
year: vehicle.year, year: vehicle.year,
plate: vehicle.plate plate: vehicle.plate,
}; unit_id: vehicle.unit_id ? vehicle.unit_id.toString() : ''
};
showEditModal = true; showEditModal = true;
} }
@@ -87,19 +112,23 @@
} }
async function handleAddVehicle() { async function handleAddVehicle() {
if (!formData.brand || !formData.model || !formData.year || !formData.plate) { if (!formData.brand || !formData.model || !formData.year || !formData.plate || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
try { try {
const response = await fetch('/api/vehicles', { const payload = {
method: 'POST', ...formData,
headers: { unit_id: parseInt(formData.unit_id)
'Content-Type': 'application/json', };
}, const response = await fetch('/api/vehicles', {
body: JSON.stringify(formData), method: 'POST',
}); headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = await response.json(); const data = await response.json();
@@ -117,22 +146,24 @@
} }
async function handleUpdateVehicle() { async function handleUpdateVehicle() {
if (!formData.brand || !formData.model || !formData.year || !formData.plate) { if (!formData.brand || !formData.model || !formData.year || !formData.plate || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
try { try {
const response = await fetch('/api/vehicles', { const payload = {
method: 'PUT', id: selectedVehicle.id,
headers: { ...formData,
'Content-Type': 'application/json', unit_id: parseInt(formData.unit_id)
}, };
body: JSON.stringify({ const response = await fetch('/api/vehicles', {
id: selectedVehicle.id, method: 'PUT',
...formData headers: {
}), 'Content-Type': 'application/json',
}); },
body: JSON.stringify(payload),
});
const data = await response.json(); const data = await response.json();
@@ -242,6 +273,9 @@
<span class="plate-badge"><i class="fas fa-car"></i> {vehicle.plate}</span> <span class="plate-badge"><i class="fas fa-car"></i> {vehicle.plate}</span>
</div> </div>
</div> </div>
<p class="vehicle-unit">
<i class="fas fa-building"></i> {vehicle.unit_name || getUnitName(vehicle.unit_id, units)}
</p>
<div class="vehicle-actions"> <div class="vehicle-actions">
<button class="btn btn-sm btn-secondary" on:click={() => openEditModal(vehicle)}> <button class="btn btn-sm btn-secondary" on:click={() => openEditModal(vehicle)}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -318,6 +352,20 @@
required required
/> />
</div> </div>
<div class="form-group">
<label for="unit_id">Birlik</label>
<select
id="unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button> <button type="submit" class="btn btn-primary">Kaydet</button>
@@ -381,6 +429,20 @@
required required
/> />
</div> </div>
<div class="form-group">
<label for="edit-unit_id">Birlik</label>
<select
id="edit-unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Güncelle</button> <button type="submit" class="btn btn-primary">Güncelle</button>
@@ -501,6 +563,15 @@
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.vehicle-unit {
margin: 0 0 1rem;
color: var(--text-secondary);
font-weight: 600;
display: flex;
align-items: center;
gap: 0.4rem;
}
.vehicle-info h3 { .vehicle-info h3 {
font-size: 1.2rem; font-size: 1.2rem;
font-weight: 600; font-weight: 600;
@@ -657,4 +728,4 @@
flex-direction: column; flex-direction: column;
} }
} }
</style> </style>

View File

@@ -17,7 +17,8 @@
let personnel = []; let personnel = [];
let fuelSlips = []; let fuelSlips = [];
let approvedRejectedSlips = []; let approvedRejectedSlips = [];
let goodsManagers = []; let receivingPersonnel = [];
let filteredReceivingPersonnel = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showCreateModal = false; let showCreateModal = false;
@@ -37,7 +38,7 @@
liters: '', liters: '',
km: '', km: '',
personnel_id: '', personnel_id: '',
goods_manager_id: 2, // Varsayılan mal sorumlusu goods_manager_id: '',
notes: '' notes: ''
}; };
@@ -77,12 +78,12 @@
async function loadData() { async function loadData() {
try { try {
// Paralel veri yükleme // Paralel veri yükleme
const [vehiclesRes, unitsRes, personnelRes, slipsRes, goodsManagersRes] = await Promise.all([ const [vehiclesRes, unitsRes, personnelRes, slipsRes, unitPersonnelRes] = await Promise.all([
fetch('/api/vehicles'), fetch('/api/vehicles'),
fetch('/api/units'), fetch('/api/units'),
fetch('/api/fuel-personnel'), fetch('/api/fuel-personnel'),
fetch('/api/fuel-slips'), fetch('/api/fuel-slips'),
fetch('/api/goods-managers') fetch('/api/unit-personnel')
]); ]);
if (vehiclesRes.ok) { if (vehiclesRes.ok) {
@@ -117,9 +118,10 @@
}); });
} }
if (goodsManagersRes.ok) { if (unitPersonnelRes.ok) {
const goodsData = await goodsManagersRes.json(); const receiversData = await unitPersonnelRes.json();
goodsManagers = goodsData.goodsManagers?.filter(gm => gm.is_active) || []; receivingPersonnel = receiversData.unitPersonnel?.filter(person => person.is_active) || [];
syncReceiverSelection();
} }
} catch (err) { } catch (err) {
@@ -130,6 +132,41 @@
} }
} }
function getUnitPersonnelByUnit(unitId) {
if (!unitId) {
return [];
}
const normalizedUnit = parseInt(unitId);
return receivingPersonnel.filter(person => person.unit_id === normalizedUnit);
}
function syncReceiverSelection(unitId = formData.unit_id) {
const candidates = getUnitPersonnelByUnit(unitId);
filteredReceivingPersonnel = candidates;
if (!unitId) {
formData.goods_manager_id = '';
return;
}
if (candidates.length === 0) {
formData.goods_manager_id = '';
return;
}
const hasCurrent = candidates.some(person => person.id.toString() === formData.goods_manager_id?.toString());
if (!hasCurrent) {
formData.goods_manager_id = candidates[0].id.toString();
}
}
function handleUnitChange(event) {
const value = event.target.value;
formData.unit_id = value;
syncReceiverSelection(value);
}
function resetForm() { function resetForm() {
formData = { formData = {
date: new Date().toISOString().split('T')[0], date: new Date().toISOString().split('T')[0],
@@ -140,9 +177,10 @@
liters: '', liters: '',
km: '', km: '',
personnel_id: '', personnel_id: '',
goods_manager_id: goodsManagers.length > 0 ? goodsManagers[0].id : '', goods_manager_id: '',
notes: '' notes: ''
}; };
syncReceiverSelection('');
} }
function openCreateModal() { function openCreateModal() {
@@ -378,7 +416,13 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="unit_id">Birlik</label> <label for="unit_id">Birlik</label>
<select id="unit_id" class="form-select" bind:value={formData.unit_id} required> <select
id="unit_id"
class="form-select"
bind:value={formData.unit_id}
on:change={handleUnitChange}
required
>
<option value="">Birlik Seçin</option> <option value="">Birlik Seçin</option>
{#each units as unit} {#each units as unit}
<option value={unit.id}>{unit.name}</option> <option value={unit.id}>{unit.name}</option>
@@ -437,10 +481,20 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="goods_manager_id">Teslim Alan</label> <label for="goods_manager_id">Teslim Alan</label>
<select id="goods_manager_id" class="form-select" bind:value={formData.goods_manager_id} required> <select
<option value="">Mal Sorumlusu Seçin</option> id="goods_manager_id"
{#each goodsManagers as manager} class="form-select"
<option value={manager.id}>{manager.rank} {manager.full_name}</option> bind:value={formData.goods_manager_id}
disabled={!formData.unit_id || filteredReceivingPersonnel.length === 0}
required
>
{#if !formData.unit_id}
<option value="">Önce birlik seçin</option>
{:else if filteredReceivingPersonnel.length === 0}
<option value="">Bu birliğe kayıtlı personel yok</option>
{/if}
{#each filteredReceivingPersonnel as person}
<option value={person.id}>{person.rank} {person.full_name}</option>
{/each} {/each}
</select> </select>
</div> </div>
@@ -1042,4 +1096,4 @@
min-width: auto; min-width: auto;
} }
} }
</style> </style>

View File

@@ -11,7 +11,8 @@ import {
getGoodsManagers, getGoodsManagers,
addGoodsManager, addGoodsManager,
updateGoodsManager, updateGoodsManager,
deleteGoodsManager deleteGoodsManager,
findGoodsManagerById
} from './lib/data/goodsManagers.js'; } from './lib/data/goodsManagers.js';
// Units veritabanı // Units veritabanı
@@ -65,6 +66,19 @@ let units = [
let nextUnitId = 4; let nextUnitId = 4;
const getUnitById = (unitId) => {
if (unitId === null || unitId === undefined) {
return null;
}
const id = parseInt(unitId);
return units.find((unit) => unit.id === id) || null;
};
const getUnitNameById = (unitId) => {
return getUnitById(unitId)?.name || 'Belirtilmemiş';
};
// Vehicles veritabanı // Vehicles veritabanı
let vehicles = [ let vehicles = [
{ {
@@ -73,6 +87,7 @@ let vehicles = [
model: 'Actros 1851', model: 'Actros 1851',
year: 2020, year: 2020,
plate: '34 ABC 123', plate: '34 ABC 123',
unit_id: 1,
fuel_type: 'Dizel', fuel_type: 'Dizel',
fuel_capacity: 500, fuel_capacity: 500,
current_fuel: 300, current_fuel: 300,
@@ -87,6 +102,7 @@ let vehicles = [
model: 'FH16 750', model: 'FH16 750',
year: 2021, year: 2021,
plate: '34 XYZ 789', plate: '34 XYZ 789',
unit_id: 2,
fuel_type: 'Dizel', fuel_type: 'Dizel',
fuel_capacity: 600, fuel_capacity: 600,
current_fuel: 450, current_fuel: 450,
@@ -101,6 +117,7 @@ let vehicles = [
model: 'R730', model: 'R730',
year: 2019, year: 2019,
plate: '34 DEF 456', plate: '34 DEF 456',
unit_id: 3,
fuel_type: 'Dizel', fuel_type: 'Dizel',
fuel_capacity: 550, fuel_capacity: 550,
current_fuel: 200, current_fuel: 200,
@@ -111,6 +128,11 @@ let vehicles = [
} }
]; ];
vehicles = vehicles.map((vehicle) => ({
...vehicle,
unit_name: getUnitNameById(vehicle.unit_id)
}));
let nextVehicleId = 4; let nextVehicleId = 4;
// Fuel Personnel veritabanı // Fuel Personnel veritabanı
@@ -119,7 +141,7 @@ let fuelPersonnel = [
id: 1, id: 1,
full_name: 'Ahmet Demir', full_name: 'Ahmet Demir',
rank: 'Üsteğmen', rank: 'Üsteğmen',
registration_number: '111222', registration_number: 'FP-111222',
tc_kimlik: '11111111111', tc_kimlik: '11111111111',
phone: '05321112233', phone: '05321112233',
is_active: true, is_active: true,
@@ -129,7 +151,7 @@ let fuelPersonnel = [
id: 2, id: 2,
full_name: 'Mustafa Çelik', full_name: 'Mustafa Çelik',
rank: 'Astsubay', rank: 'Astsubay',
registration_number: '333444', registration_number: 'FP-333444',
tc_kimlik: '22222222222', tc_kimlik: '22222222222',
phone: '05334455566', phone: '05334455566',
is_active: true, is_active: true,
@@ -139,6 +161,59 @@ let fuelPersonnel = [
let nextFuelPersonnelId = 3; let nextFuelPersonnelId = 3;
// Unit personnel listesi (teslim alanlar)
let unitPersonnel = [
{
id: 1,
full_name: 'Serkan Yılmaz',
rank: 'Teğmen',
registration_number: 'UP-1001',
tc_kimlik: '12312312312',
phone: '05320001122',
unit_id: 1,
is_active: true,
created_at: new Date().toISOString()
},
{
id: 2,
full_name: 'Barış Aksoy',
rank: 'Astsubay',
registration_number: 'UP-2001',
tc_kimlik: '98798798798',
phone: '05323334455',
unit_id: 2,
is_active: true,
created_at: new Date().toISOString()
},
{
id: 3,
full_name: 'Hakan Güler',
rank: 'Üstçavuş',
registration_number: 'UP-3001',
tc_kimlik: '55544433322',
phone: '05324445566',
unit_id: 3,
is_active: true,
created_at: new Date().toISOString()
}
];
let nextUnitPersonnelId = 4;
function parseMukannenValue(value) {
if (value === null || value === undefined || value === '') {
return 0;
}
if (typeof value === 'number') {
return value;
}
const parsed = parseFloat(value.toString().replace(',', '.'));
return isNaN(parsed) ? 0 : parsed;
}
const app = express(); const app = express();
const server = createServer(app); const server = createServer(app);
const io = new Server(server, { const io = new Server(server, {
@@ -746,14 +821,144 @@ app.delete('/api/goods-managers', async (req, res) => {
// GET - Tüm yakıt personelini listele // GET - Tüm yakıt personelini listele
app.get('/api/fuel-personnel', (req, res) => { app.get('/api/fuel-personnel', (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session)
res.json({ fuelPersonnel }); res.json({ fuelPersonnel });
}); });
// POST - Yeni yakıt personeli ekle // POST - Yeni yakıt personeli ekle
app.post('/api/fuel-personnel', async (req, res) => { app.post('/api/fuel-personnel', async (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session) try {
const {
full_name,
rank,
registration_number,
tc_kimlik,
phone,
is_active = true
} = req.body;
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) {
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
}
if (!/^[0-9]{11}$/.test(tc_kimlik)) {
return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' });
}
const existingPersonnel = fuelPersonnel.find(p =>
p.registration_number === registration_number || p.tc_kimlik === tc_kimlik
);
if (existingPersonnel) {
return res.status(400).json({ message: 'Bu personel zaten kayıtlı.' });
}
const newPersonnel = {
id: nextFuelPersonnelId++,
full_name: full_name.trim(),
rank: rank.trim(),
registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(),
phone: phone.trim(),
is_active: Boolean(is_active),
created_at: new Date().toISOString()
};
fuelPersonnel.push(newPersonnel);
res.json({
message: 'Yakıt personeli başarıyla eklendi.',
fuelPersonnel: newPersonnel
});
} catch (error) {
res.status(500).json({ message: 'Sunucu hatası.' });
}
});
// PUT - Yakıt personeli güncelle
app.put('/api/fuel-personnel', (req, res) => {
try {
const {
id,
full_name,
rank,
registration_number,
tc_kimlik,
phone,
is_active
} = req.body;
if (!id || !full_name || !rank || !registration_number || !tc_kimlik || !phone) {
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
}
if (!/^[0-9]{11}$/.test(tc_kimlik)) {
return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' });
}
const personnelIndex = fuelPersonnel.findIndex(p => p.id === parseInt(id));
if (personnelIndex === -1) {
return res.status(404).json({ message: 'Personel bulunamadı.' });
}
const duplicate = fuelPersonnel.find(p =>
p.id !== parseInt(id) && (p.registration_number === registration_number || p.tc_kimlik === tc_kimlik)
);
if (duplicate) {
return res.status(400).json({ message: 'Aynı sicil veya TC Kimlik başka bir personelde mevcut.' });
}
fuelPersonnel[personnelIndex] = {
...fuelPersonnel[personnelIndex],
full_name: full_name.trim(),
rank: rank.trim(),
registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(),
phone: phone.trim(),
is_active: Boolean(is_active)
};
res.json({
message: 'Yakıt personeli güncellendi.',
fuelPersonnel: fuelPersonnel[personnelIndex]
});
} catch (error) {
res.status(500).json({ message: 'Sunucu hatası.' });
}
});
// DELETE - Yakıt personeli sil
app.delete('/api/fuel-personnel', (req, res) => {
try {
const { id } = req.body;
if (!id) {
return res.status(400).json({ message: 'Personel ID zorunludur.' });
}
const personnelIndex = fuelPersonnel.findIndex(p => p.id === parseInt(id));
if (personnelIndex === -1) {
return res.status(404).json({ message: 'Personel bulunamadı.' });
}
const deletedPersonnel = fuelPersonnel.splice(personnelIndex, 1)[0];
res.json({
message: 'Yakıt personeli silindi.',
fuelPersonnel: deletedPersonnel
});
} catch (error) {
res.status(500).json({ message: 'Sunucu hatası.' });
}
});
// Unit Personnel API endpoint'leri (Teslim Alan personeller)
app.get('/api/unit-personnel', (req, res) => {
res.json({ unitPersonnel });
});
app.post('/api/unit-personnel', (req, res) => {
try { try {
const { const {
full_name, full_name,
@@ -765,35 +970,23 @@ app.post('/api/fuel-personnel', async (req, res) => {
is_active = true is_active = true
} = req.body; } = req.body;
// Validasyon
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone || !unit_id) { if (!full_name || !rank || !registration_number || !tc_kimlik || !phone || !unit_id) {
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' }); return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
} }
// TC Kimlik numarası validasyonu
if (!/^[0-9]{11}$/.test(tc_kimlik)) { if (!/^[0-9]{11}$/.test(tc_kimlik)) {
return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' }); return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' });
} }
// Sicil numarası tekrar kontrolü const duplicate = unitPersonnel.find(p =>
const existingPersonnel = fuelPersonnel.find(p => p.registration_number === registration_number || p.tc_kimlik === tc_kimlik
p.registration_number === registration_number
); );
if (existingPersonnel) { if (duplicate) {
return res.status(400).json({ message: 'Bu sicil numarası zaten kayıtlı.' }); return res.status(400).json({ message: 'Bu personel zaten kayıtlı.' });
} }
// TC Kimlik numarası tekrar kontrolü
const existingTc = fuelPersonnel.find(p =>
p.tc_kimlik === tc_kimlik
);
if (existingTc) {
return res.status(400).json({ message: 'Bu TC Kimlik numarası zaten kayıtlı.' });
}
// Yeni personel oluştur
const newPersonnel = { const newPersonnel = {
id: nextFuelPersonnelId++, id: nextUnitPersonnelId++,
full_name: full_name.trim(), full_name: full_name.trim(),
rank: rank.trim(), rank: rank.trim(),
registration_number: registration_number.trim(), registration_number: registration_number.trim(),
@@ -804,46 +997,11 @@ app.post('/api/fuel-personnel', async (req, res) => {
created_at: new Date().toISOString() created_at: new Date().toISOString()
}; };
// Birlik personeli için kullanıcı oluştur unitPersonnel.push(newPersonnel);
try {
// Kullanıcı adını TC kimlik numarasından oluştur
const username = `bp_${tc_kimlik}`;
const defaultPassword = tc_kimlik.substring(0, 6); // İlk 6 hane varsayılan şifre
const hashedPassword = await bcrypt.hash(defaultPassword, 10);
// Kullanıcı adı benzersizliğini kontrol et
const existingUser = await new Promise((resolve, reject) => {
db.get('SELECT id FROM users WHERE username = ?', [username], (err, row) => {
if (err) reject(err);
else resolve(row);
});
});
if (existingUser) {
return res.status(400).json({ message: 'Bu personel için zaten kullanıcı hesabı mevcut.' });
}
// Birlik personeli olarak kullanıcı ekle
await new Promise((resolve, reject) => {
db.run('INSERT INTO users (username, password, role, full_name) VALUES (?, ?, ?, ?)',
[username, hashedPassword, 'birlik_personeli', full_name], (err) => {
if (err) reject(err);
else resolve();
});
});
console.log(`✅ Birlik personeli kullanıcı oluşturuldu: ${username}`);
} catch (userError) {
console.error('❌ Birlik personeli kullanıcı oluşturma hatası:', userError);
return res.status(500).json({ message: 'Personel için kullanıcı hesabı oluşturulamadı.' });
}
fuelPersonnel.push(newPersonnel);
res.json({ res.json({
message: 'Personel başarıyla eklendi.', message: 'Personel başarıyla eklendi.',
fuelPersonnel: newPersonnel personnel: newPersonnel
}); });
} catch (error) { } catch (error) {
@@ -851,10 +1009,7 @@ app.post('/api/fuel-personnel', async (req, res) => {
} }
}); });
// PUT - Yakıt personeli güncelle app.put('/api/unit-personnel', (req, res) => {
app.put('/api/fuel-personnel', (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session)
try { try {
const { const {
id, id,
@@ -867,41 +1022,28 @@ app.put('/api/fuel-personnel', (req, res) => {
is_active is_active
} = req.body; } = req.body;
// Validasyon
if (!id || !full_name || !rank || !registration_number || !tc_kimlik || !phone || !unit_id) { if (!id || !full_name || !rank || !registration_number || !tc_kimlik || !phone || !unit_id) {
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' }); return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
} }
// TC Kimlik numarası validasyonu
if (!/^[0-9]{11}$/.test(tc_kimlik)) { if (!/^[0-9]{11}$/.test(tc_kimlik)) {
return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' }); return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' });
} }
// Personel bul const personnelIndex = unitPersonnel.findIndex(p => p.id === parseInt(id));
const personnelIndex = fuelPersonnel.findIndex(p => p.id === parseInt(id));
if (personnelIndex === -1) { if (personnelIndex === -1) {
return res.status(404).json({ message: 'Personel bulunamadı.' }); return res.status(404).json({ message: 'Personel bulunamadı.' });
} }
// Sicil numarası tekrar kontrolü (başka personel için) const duplicate = unitPersonnel.find(p =>
const existingRegNumber = fuelPersonnel.find(p => p.id !== parseInt(id) && (p.registration_number === registration_number || p.tc_kimlik === tc_kimlik)
p.id !== parseInt(id) && p.registration_number === registration_number
); );
if (existingRegNumber) { if (duplicate) {
return res.status(400).json({ message: 'Bu sicil numarası başka bir personelde kayıtlı.' }); return res.status(400).json({ message: 'Bu sicil veya TC Kimlik başka bir personelde mevcut.' });
} }
// TC Kimlik numarası tekrar kontrolü (başka personel için) unitPersonnel[personnelIndex] = {
const existingTc = fuelPersonnel.find(p => ...unitPersonnel[personnelIndex],
p.id !== parseInt(id) && p.tc_kimlik === tc_kimlik
);
if (existingTc) {
return res.status(400).json({ message: 'Bu TC Kimlik numarası başka bir personelde kayıtlı.' });
}
// Personeli güncelle
fuelPersonnel[personnelIndex] = {
...fuelPersonnel[personnelIndex],
full_name: full_name.trim(), full_name: full_name.trim(),
rank: rank.trim(), rank: rank.trim(),
registration_number: registration_number.trim(), registration_number: registration_number.trim(),
@@ -912,8 +1054,8 @@ app.put('/api/fuel-personnel', (req, res) => {
}; };
res.json({ res.json({
message: 'Personel başarıyla güncellendi.', message: 'Personel güncellendi.',
fuelPersonnel: fuelPersonnel[personnelIndex] personnel: unitPersonnel[personnelIndex]
}); });
} catch (error) { } catch (error) {
@@ -921,10 +1063,7 @@ app.put('/api/fuel-personnel', (req, res) => {
} }
}); });
// DELETE - Yakıt personeli sil app.delete('/api/unit-personnel', (req, res) => {
app.delete('/api/fuel-personnel', (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session)
try { try {
const { id } = req.body; const { id } = req.body;
@@ -932,18 +1071,16 @@ app.delete('/api/fuel-personnel', (req, res) => {
return res.status(400).json({ message: 'Personel ID zorunludur.' }); return res.status(400).json({ message: 'Personel ID zorunludur.' });
} }
// Personel bul const personnelIndex = unitPersonnel.findIndex(p => p.id === parseInt(id));
const personnelIndex = fuelPersonnel.findIndex(p => p.id === parseInt(id));
if (personnelIndex === -1) { if (personnelIndex === -1) {
return res.status(404).json({ message: 'Personel bulunamadı.' }); return res.status(404).json({ message: 'Personel bulunamadı.' });
} }
// Personel sil const deletedPersonnel = unitPersonnel.splice(personnelIndex, 1)[0];
const deletedPersonnel = fuelPersonnel.splice(personnelIndex, 1)[0];
res.json({ res.json({
message: 'Personel başarıyla silindi.', message: 'Personel silindi.',
fuelPersonnel: deletedPersonnel personnel: deletedPersonnel
}); });
} catch (error) { } catch (error) {
@@ -951,6 +1088,7 @@ app.delete('/api/fuel-personnel', (req, res) => {
} }
}); });
// Fuel Slips API endpoint'leri // Fuel Slips API endpoint'leri
// GET - Yakıt fişlerini listele // GET - Yakıt fişlerini listele
@@ -1028,21 +1166,29 @@ app.post('/api/fuel-slips', async (req, res) => {
return res.status(400).json({ message: 'Litre ve KM değerleri geçersiz.' }); return res.status(400).json({ message: 'Litre ve KM değerleri geçersiz.' });
} }
const unitId = parseInt(slipData.unit_id);
const vehicleId = parseInt(slipData.vehicle_id);
const personnelId = parseInt(slipData.personnel_id);
const goodsManagerId = parseInt(slipData.goods_manager_id);
const fuelManagerId = parseInt(slipData.fuel_manager_id);
// Araç, personel ve mal sorumlusu bilgilerini getir // Araç, personel ve mal sorumlusu bilgilerini getir
const [vehicle, unit, person, goodsManager] = await Promise.all([ const vehicle = vehicles.find(v => v.id === vehicleId);
vehicles.find(v => v.id === parseInt(slipData.vehicle_id)), const unit = units.find(u => u.id === unitId);
units.find(u => u.id === parseInt(slipData.unit_id)), const person = fuelPersonnel.find(p => p.id === personnelId && p.is_active);
Promise.resolve({ // Temporary fuel personnel lookup const receivingPerson = unitPersonnel.find(p => p.id === goodsManagerId && p.is_active);
id: 1,
full_name: 'Ahmet Demir', if (!person) {
rank: 'Üsteğmen' return res.status(400).json({ message: 'Teslim eden personel bulunamadı veya pasif durumda.' });
}), }
Promise.resolve({ // Temporary goods manager lookup
id: slipData.goods_manager_id, if (!receivingPerson) {
full_name: 'Mal Sorumlusu', return res.status(400).json({ message: 'Teslim alan personel bulunamadı veya pasif durumda.' });
rank: 'Yüzbaşı' }
})
]); if (receivingPerson.unit_id !== unitId) {
return res.status(400).json({ message: 'Seçilen personel bu birliğe bağlı değil.' });
}
const vehicleInfo = vehicle ? { const vehicleInfo = vehicle ? {
brand: vehicle.brand, brand: vehicle.brand,
@@ -1058,15 +1204,19 @@ app.post('/api/fuel-slips', async (req, res) => {
const personnelInfo = person ? { const personnelInfo = person ? {
full_name: person.full_name, full_name: person.full_name,
rank: person.rank rank: person.rank,
unit_id: person.unit_id,
registration_number: person.registration_number
} : { } : {
full_name: 'Bilinmeyen Personel', full_name: 'Bilinmeyen Personel',
rank: '' rank: ''
}; };
const goodsManagerInfo = goodsManager ? { const goodsManagerInfo = receivingPerson ? {
full_name: goodsManager.full_name, full_name: receivingPerson.full_name,
rank: goodsManager.rank rank: receivingPerson.rank,
unit_id: receivingPerson.unit_id,
unit_name: getUnitNameById(receivingPerson.unit_id)
} : { } : {
full_name: 'Bilinmeyen Mal Sorumlusu', full_name: 'Bilinmeyen Mal Sorumlusu',
rank: '' rank: ''
@@ -1085,18 +1235,18 @@ app.post('/api/fuel-slips', async (req, res) => {
const params = [ const params = [
slipData.date, slipData.date,
slipData.force_command, slipData.force_command,
slipData.unit_id, unitId,
unit?.name || `Birim ${slipData.unit_id}`, unit?.name || `Birim ${unitId}`,
slipData.vehicle_id, vehicleId,
JSON.stringify(vehicleInfo), JSON.stringify(vehicleInfo),
slipData.fuel_type, slipData.fuel_type,
parseFloat(slipData.liters), parseFloat(slipData.liters),
parseInt(slipData.km), parseInt(slipData.km),
slipData.personnel_id, personnelId,
JSON.stringify(personnelInfo), JSON.stringify(personnelInfo),
slipData.goods_manager_id, goodsManagerId,
JSON.stringify(goodsManagerInfo), JSON.stringify(goodsManagerInfo),
slipData.fuel_manager_id, fuelManagerId,
JSON.stringify(fuelManagerInfo), JSON.stringify(fuelManagerInfo),
'pending', 'pending',
slipData.notes || '' slipData.notes || ''
@@ -1112,18 +1262,18 @@ app.post('/api/fuel-slips', async (req, res) => {
id: this.lastID, id: this.lastID,
date: slipData.date, date: slipData.date,
force_command: slipData.force_command, force_command: slipData.force_command,
unit_id: slipData.unit_id, unit_id: unitId,
unit_name: unit?.name || `Birim ${slipData.unit_id}`, unit_name: unit?.name || `Birim ${unitId}`,
vehicle_id: slipData.vehicle_id, vehicle_id: vehicleId,
vehicle_info: vehicleInfo, vehicle_info: vehicleInfo,
fuel_type: slipData.fuel_type, fuel_type: slipData.fuel_type,
liters: parseFloat(slipData.liters), liters: parseFloat(slipData.liters),
km: parseInt(slipData.km), km: parseInt(slipData.km),
personnel_id: slipData.personnel_id, personnel_id: personnelId,
personnel_info: personnelInfo, personnel_info: personnelInfo,
goods_manager_id: slipData.goods_manager_id, goods_manager_id: goodsManagerId,
goods_manager_info: goodsManagerInfo, goods_manager_info: goodsManagerInfo,
fuel_manager_id: slipData.fuel_manager_id, fuel_manager_id: fuelManagerId,
fuel_manager_info: fuelManagerInfo, fuel_manager_info: fuelManagerInfo,
status: 'pending', status: 'pending',
notes: slipData.notes || '', notes: slipData.notes || '',
@@ -1297,6 +1447,7 @@ app.post('/api/vehicles', (req, res) => {
model, model,
year, year,
plate, plate,
unit_id,
fuel_type, fuel_type,
fuel_capacity, fuel_capacity,
current_fuel, current_fuel,
@@ -1308,10 +1459,15 @@ app.post('/api/vehicles', (req, res) => {
} = req.body; } = req.body;
// Validasyon // Validasyon
if (!brand || !model || !year || !plate || !fuel_type || !fuel_capacity) { if (!brand || !model || !year || !plate || !unit_id || !fuel_type || !fuel_capacity) {
return res.status(400).json({ message: 'Tüm zorunlu alanları doldurun.' }); return res.status(400).json({ message: 'Tüm zorunlu alanları doldurun.' });
} }
const targetUnit = units.find(u => u.id === parseInt(unit_id));
if (!targetUnit) {
return res.status(400).json({ message: 'Geçerli bir birlik seçin.' });
}
if (year < 1990 || year > new Date().getFullYear() + 1) { if (year < 1990 || year > new Date().getFullYear() + 1) {
return res.status(400).json({ message: 'Geçerli bir yıl girin.' }); return res.status(400).json({ message: 'Geçerli bir yıl girin.' });
} }
@@ -1329,18 +1485,21 @@ app.post('/api/vehicles', (req, res) => {
} }
// Yeni araç oluştur // Yeni araç oluştur
const unitName = targetUnit.name;
const newVehicle = { const newVehicle = {
id: nextVehicleId++, id: nextVehicleId++,
brand: brand.trim(), brand: brand.trim(),
model: model.trim(), model: model.trim(),
year: parseInt(year), year: parseInt(year),
plate: plate.trim().toUpperCase(), plate: plate.trim().toUpperCase(),
unit_id: parseInt(unit_id),
fuel_type: fuel_type.trim(), fuel_type: fuel_type.trim(),
fuel_capacity: parseInt(fuel_capacity), fuel_capacity: parseInt(fuel_capacity),
current_fuel: parseInt(current_fuel) || 0, current_fuel: parseInt(current_fuel) || 0,
yazlik_mukannen: parseInt(yazlik_mukannen) || 0, yazlik_mukannen: parseMukannenValue(yazlik_mukannen),
kislik_mukannen: parseInt(kislik_mukannen) || 0, kislik_mukannen: parseMukannenValue(kislik_mukannen),
status: status.trim(), status: (status || 'Aktif').trim(),
unit_name: unitName,
driver_id: driver_id ? parseInt(driver_id) : null, driver_id: driver_id ? parseInt(driver_id) : null,
driver_name: driver_name ? driver_name.trim() : null, driver_name: driver_name ? driver_name.trim() : null,
created_at: new Date().toISOString() created_at: new Date().toISOString()
@@ -1369,6 +1528,7 @@ app.put('/api/vehicles', (req, res) => {
model, model,
year, year,
plate, plate,
unit_id,
fuel_type, fuel_type,
fuel_capacity, fuel_capacity,
current_fuel, current_fuel,
@@ -1380,10 +1540,15 @@ app.put('/api/vehicles', (req, res) => {
} = req.body; } = req.body;
// Validasyon // Validasyon
if (!id || !brand || !model || !year || !plate || !fuel_type || !fuel_capacity) { if (!id || !brand || !model || !year || !plate || !unit_id || !fuel_type || !fuel_capacity) {
return res.status(400).json({ message: 'Tüm zorunlu alanları doldurun.' }); return res.status(400).json({ message: 'Tüm zorunlu alanları doldurun.' });
} }
const targetUnit = units.find(u => u.id === parseInt(unit_id));
if (!targetUnit) {
return res.status(400).json({ message: 'Geçerli bir birlik seçin.' });
}
if (year < 1990 || year > new Date().getFullYear() + 1) { if (year < 1990 || year > new Date().getFullYear() + 1) {
return res.status(400).json({ message: 'Geçerli bir yıl girin.' }); return res.status(400).json({ message: 'Geçerli bir yıl girin.' });
} }
@@ -1407,18 +1572,21 @@ app.put('/api/vehicles', (req, res) => {
} }
// Araç güncelle // Araç güncelle
const unitName = targetUnit.name;
vehicles[vehicleIndex] = { vehicles[vehicleIndex] = {
...vehicles[vehicleIndex], ...vehicles[vehicleIndex],
brand: brand.trim(), brand: brand.trim(),
model: model.trim(), model: model.trim(),
year: parseInt(year), year: parseInt(year),
plate: plate.trim().toUpperCase(), plate: plate.trim().toUpperCase(),
unit_id: parseInt(unit_id),
fuel_type: fuel_type.trim(), fuel_type: fuel_type.trim(),
fuel_capacity: parseInt(fuel_capacity), fuel_capacity: parseInt(fuel_capacity),
current_fuel: parseInt(current_fuel) || 0, current_fuel: parseInt(current_fuel) || 0,
yazlik_mukannen: parseInt(yazlik_mukannen) || 0, yazlik_mukannen: parseMukannenValue(yazlik_mukannen),
kislik_mukannen: parseInt(kislik_mukannen) || 0, kislik_mukannen: parseMukannenValue(kislik_mukannen),
status: (status || 'Aktif').trim(), status: (status || 'Aktif').trim(),
unit_name: unitName,
driver_id: driver_id ? parseInt(driver_id) : null, driver_id: driver_id ? parseInt(driver_id) : null,
driver_name: driver_name ? driver_name.trim() : null driver_name: driver_name ? driver_name.trim() : null
}; };
@@ -1516,4 +1684,4 @@ async function startServer() {
} }
} }
startServer(); startServer();