diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index e3111487..e4897773 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -3270,16 +3270,6 @@ "RequiredPermissionName": null, "IsDisabled": false }, - { - "ParentCode": "App.SupplyChain", - "Code": "App.SupplyChain.Requisitions", - "DisplayName": "Satınalma İstekleri", - "Order": 6, - "Url": "/admin/supplychain/requisitions", - "Icon": "FcPlanner", - "RequiredPermissionName": null, - "IsDisabled": false - }, { "ParentCode": "App.SupplyChain", "Code": "App.SupplyChain.Quotations", diff --git a/ui/src/views/supplyChain/components/ApprovalWorkflowModal.tsx b/ui/src/views/supplyChain/components/ApprovalWorkflowModal.tsx index 674bddf0..c35c649e 100644 --- a/ui/src/views/supplyChain/components/ApprovalWorkflowModal.tsx +++ b/ui/src/views/supplyChain/components/ApprovalWorkflowModal.tsx @@ -1,20 +1,20 @@ -import React, { useState, useEffect } from "react"; -import { FaTimes, FaSave, FaUsers, FaPlus, FaTrash } from "react-icons/fa"; +import React, { useState, useEffect } from 'react' +import { FaTimes, FaSave, FaUsers, FaPlus, FaTrash } from 'react-icons/fa' import { MmApprovalWorkflow, MmApprovalWorkflowLevel, RequestTypeEnum, ApprovalLevelEnum, -} from "../../../types/mm"; -import MultiSelectEmployee from "../../../components/common/MultiSelectEmployee"; -import { mockDepartments } from "../../../mocks/mockDepartments"; +} from '../../../types/mm' +import MultiSelectEmployee from '../../../components/common/MultiSelectEmployee' +import { mockDepartments } from '../../../mocks/mockDepartments' interface ApprovalWorkflowModalProps { - isOpen: boolean; - onClose: () => void; - onSave: (workflow: MmApprovalWorkflow) => void; - workflow?: MmApprovalWorkflow | null; - mode: "create" | "view" | "edit"; + isOpen: boolean + onClose: () => void + onSave: (workflow: MmApprovalWorkflow) => void + workflow?: MmApprovalWorkflow | null + mode: 'create' | 'view' | 'edit' } const ApprovalWorkflowModal: React.FC = ({ @@ -25,119 +25,117 @@ const ApprovalWorkflowModal: React.FC = ({ mode, }) => { const [formData, setFormData] = useState>({ - name: "", - departmentId: "", + name: '', + departmentId: '', requestType: RequestTypeEnum.Material, amountThreshold: 0, approvalLevels: [], isActive: true, - }); + }) useEffect(() => { - if (mode === "create") { + if (mode === 'create') { // Reset form to initial empty state for new workflow setFormData({ - name: "", - departmentId: "", + name: '', + departmentId: '', requestType: RequestTypeEnum.Material, amountThreshold: 0, approvalLevels: [], isActive: true, - }); + }) } else if (workflow) { // Load existing workflow data for view/edit modes - setFormData(workflow); + setFormData(workflow) } - }, [workflow, mode]); + }, [workflow, mode]) const handleInputChange = ( - e: React.ChangeEvent< - HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement - > + e: React.ChangeEvent, ) => { - const { name, value, type } = e.target; + const { name, value, type } = e.target setFormData((prev) => ({ ...prev, [name]: - type === "number" + type === 'number' ? parseFloat(value) || 0 - : type === "checkbox" - ? (e.target as HTMLInputElement).checked - : value, - })); - }; + : type === 'checkbox' + ? (e.target as HTMLInputElement).checked + : value, + })) + } const addApprovalLevel = () => { const newLevel: MmApprovalWorkflowLevel = { id: `level-${Date.now()}`, - workflowId: formData.id || "", + workflowId: formData.id || '', level: ApprovalLevelEnum.Supervisor, approverUserIds: [], approverNames: [], sequence: (formData.approvalLevels?.length || 0) + 1, isRequired: true, isParallel: false, - }; + } setFormData((prev) => ({ ...prev, approvalLevels: [...(prev.approvalLevels || []), newLevel], - })); - }; + })) + } const removeApprovalLevel = (index: number) => { setFormData((prev) => ({ ...prev, approvalLevels: prev.approvalLevels?.filter((_, i) => i !== index) || [], - })); - }; + })) + } const updateApprovalLevel = ( index: number, field: keyof MmApprovalWorkflowLevel, - value: string | number | boolean | string[] | undefined + value: string | number | boolean | string[] | undefined, ) => { setFormData((prev) => ({ ...prev, approvalLevels: prev.approvalLevels?.map((level, i) => - i === index ? { ...level, [field]: value } : level + i === index ? { ...level, [field]: value } : level, ) || [], - })); - }; + })) + } const handleApproverNamesChange = (index: number, employees: string[]) => { - updateApprovalLevel(index, "approverNames", employees); - }; + updateApprovalLevel(index, 'approverNames', employees) + } const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - if (mode !== "view") { + e.preventDefault() + if (mode !== 'view') { const newWorkflow: MmApprovalWorkflow = { id: workflow?.id || `WF-${Date.now()}`, - name: formData.name || "", - departmentId: formData.departmentId || "", + name: formData.name || '', + departmentId: formData.departmentId || '', requestType: formData.requestType || RequestTypeEnum.Material, amountThreshold: formData.amountThreshold || 0, approvalLevels: formData.approvalLevels || [], isActive: formData.isActive ?? true, creationTime: workflow?.creationTime || new Date(), lastModificationTime: new Date(), - }; - onSave(newWorkflow); + } + onSave(newWorkflow) } - onClose(); - }; + onClose() + } - if (!isOpen) return null; + if (!isOpen) return null - const isReadOnly = mode === "view"; + const isReadOnly = mode === 'view' const modalTitle = - mode === "create" - ? "Yeni Onay Süreci" - : mode === "edit" - ? "Onay Sürecini Düzenle" - : "Onay Süreci Detayları"; + mode === 'create' + ? 'Yeni Onay Süreci' + : mode === 'edit' + ? 'Onay Sürecini Düzenle' + : 'Onay Süreci Detayları' return (
@@ -147,10 +145,7 @@ const ApprovalWorkflowModal: React.FC = ({ {modalTitle} -
@@ -159,18 +154,14 @@ const ApprovalWorkflowModal: React.FC = ({
{/* Temel Bilgiler */}
-

- Temel Bilgiler -

+

Temel Bilgiler

- + = ({
- + = ({
- + = ({ disabled={isReadOnly} className="mr-2" /> - - Aktif - + Aktif
@@ -266,10 +249,7 @@ const ApprovalWorkflowModal: React.FC = ({
{formData.approvalLevels?.map((level, index) => ( -
+
Seviye {level.sequence} @@ -292,30 +272,18 @@ const ApprovalWorkflowModal: React.FC = ({
@@ -325,9 +293,7 @@ const ApprovalWorkflowModal: React.FC = ({ - handleApproverNamesChange(index, employees) - } + onChange={(employees) => handleApproverNamesChange(index, employees)} disabled={isReadOnly} placeholder="Onaylayıcı seçin..." className="mt-1" @@ -340,12 +306,12 @@ const ApprovalWorkflowModal: React.FC = ({ updateApprovalLevel( index, - "timeoutDays", - parseInt(e.target.value) || undefined + 'timeoutDays', + parseInt(e.target.value) || undefined, ) } readOnly={isReadOnly} @@ -360,11 +326,7 @@ const ApprovalWorkflowModal: React.FC = ({ type="checkbox" checked={level.isRequired} onChange={(e) => - updateApprovalLevel( - index, - "isRequired", - e.target.checked - ) + updateApprovalLevel(index, 'isRequired', e.target.checked) } disabled={isReadOnly} className="mr-1" @@ -376,11 +338,7 @@ const ApprovalWorkflowModal: React.FC = ({ type="checkbox" checked={level.isParallel} onChange={(e) => - updateApprovalLevel( - index, - "isParallel", - e.target.checked - ) + updateApprovalLevel(index, 'isParallel', e.target.checked) } disabled={isReadOnly} className="mr-1" @@ -408,9 +366,9 @@ const ApprovalWorkflowModal: React.FC = ({ onClick={onClose} className="px-3 py-1.5 border border-gray-300 rounded-md text-sm text-gray-700 hover:bg-gray-50" > - {mode === "view" ? "Kapat" : "İptal"} + {mode === 'view' ? 'Kapat' : 'İptal'} - {mode !== "view" && ( + {mode !== 'view' && (
- ); -}; + ) +} -export default ApprovalWorkflowModal; +export default ApprovalWorkflowModal diff --git a/ui/src/views/supplyChain/components/ApprovalWorkflows.tsx b/ui/src/views/supplyChain/components/ApprovalWorkflows.tsx index e3851d4e..a906d13c 100644 --- a/ui/src/views/supplyChain/components/ApprovalWorkflows.tsx +++ b/ui/src/views/supplyChain/components/ApprovalWorkflows.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState } from 'react' import { FaPlus, FaSearch, @@ -10,382 +10,345 @@ import { FaClock, FaCheckCircle, FaEye, -} from "react-icons/fa"; -import { MmApprovalWorkflow } from "../../../types/mm"; -import ApprovalWorkflowModal from "./ApprovalWorkflowModal"; -import { mockApprovalWorkflows } from "../../../mocks/mockApprovalWorkflows"; +} from 'react-icons/fa' +import { MmApprovalWorkflow } from '../../../types/mm' +import ApprovalWorkflowModal from './ApprovalWorkflowModal' +import { mockApprovalWorkflows } from '../../../mocks/mockApprovalWorkflows' import { getApprovalLevelColor, getApprovalLevelText, getRequestTypeColor, getRequestTypeText, -} from "../../../utils/erp"; +} from '../../../utils/erp' +import { Container } from '@/components/shared' const ApprovalWorkflows: React.FC = () => { - const [searchTerm, setSearchTerm] = useState(""); - const [showModal, setShowModal] = useState(false); - const [editingWorkflow, setEditingWorkflow] = - useState(null); - const [selectedWorkflow, setSelectedWorkflow] = - useState(null); - const [modalMode, setModalMode] = useState<"create" | "view" | "edit">( - "create" - ); + const [searchTerm, setSearchTerm] = useState('') + const [showModal, setShowModal] = useState(false) + const [editingWorkflow, setEditingWorkflow] = useState(null) + const [selectedWorkflow, setSelectedWorkflow] = useState(null) + const [modalMode, setModalMode] = useState<'create' | 'view' | 'edit'>('create') // Mock data - replace with actual API calls - const [workflows] = useState(mockApprovalWorkflows); + const [workflows] = useState(mockApprovalWorkflows) const filteredWorkflows = workflows.filter( (workflow) => workflow.name.toLowerCase().includes(searchTerm.toLowerCase()) || - workflow.departmentId.toLowerCase().includes(searchTerm.toLowerCase()) - ); + workflow.departmentId.toLowerCase().includes(searchTerm.toLowerCase()), + ) const getTotalSteps = (workflow: MmApprovalWorkflow) => { - return workflow.approvalLevels.length; - }; + return workflow.approvalLevels.length + } const getRequiredSteps = (workflow: MmApprovalWorkflow) => { - return workflow.approvalLevels.filter((level) => level.isRequired).length; - }; + return workflow.approvalLevels.filter((level) => level.isRequired).length + } const getMaxTimeout = (workflow: MmApprovalWorkflow) => { - return Math.max( - ...workflow.approvalLevels.map((level) => level.timeoutDays || 0) - ); - }; + return Math.max(...workflow.approvalLevels.map((level) => level.timeoutDays || 0)) + } const handleEdit = (workflow: MmApprovalWorkflow) => { - setEditingWorkflow(workflow); - setModalMode("edit"); - setShowModal(true); - }; + setEditingWorkflow(workflow) + setModalMode('edit') + setShowModal(true) + } const handleView = (workflow: MmApprovalWorkflow) => { - setEditingWorkflow(workflow); - setModalMode("view"); - setShowModal(true); - }; + setEditingWorkflow(workflow) + setModalMode('view') + setShowModal(true) + } const handleAddNew = () => { - setEditingWorkflow(null); - setModalMode("create"); - setShowModal(true); - }; + setEditingWorkflow(null) + setModalMode('create') + setShowModal(true) + } const handleViewDetails = (workflow: MmApprovalWorkflow) => { - setSelectedWorkflow(workflow); - }; + setSelectedWorkflow(workflow) + } const handleSaveWorkflow = (workflow: MmApprovalWorkflow) => { // TODO: Implement save logic - console.log("Saving workflow:", workflow); - setShowModal(false); - setEditingWorkflow(null); - }; + console.log('Saving workflow:', workflow) + setShowModal(false) + setEditingWorkflow(null) + } const handleCloseModal = () => { - setShowModal(false); - setEditingWorkflow(null); - }; + setShowModal(false) + setEditingWorkflow(null) + } return ( -
- {/* Header */} -
-
-

Onay Süreçleri

-

- Departman bazlı satınalma onay süreçlerini yönetin -

-
- -
- - {/* Search Bar */} -
- - setSearchTerm(e.target.value)} - className="w-full pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" - /> -
- -
- {/* Workflow List */} -
-

- Onay Süreçleri -

- {filteredWorkflows.map((workflow) => ( -
handleViewDetails(workflow)} - > -
-
-
- -

- {workflow.name} -

- - {getRequestTypeText(workflow.requestType)} - -
-

- Departman: {workflow.department?.name} -

-

- Limit: ₺{workflow.amountThreshold.toLocaleString()} ve üzeri -

-
-
- - - -
-
- -
-
- - - Toplam Adım - - {getTotalSteps(workflow)} -
-
- - - Zorunlu Adım - - - {getRequiredSteps(workflow)} - -
-
- - - Maks. Süre - - - {getMaxTimeout(workflow)} gün - -
-
- Son Güncelleme - - {workflow.lastModificationTime.toLocaleDateString("tr-TR")} - -
-
- -
- - {workflow.isActive ? "Aktif" : "Pasif"} - -
- {workflow.approvalLevels.some( - (level) => level.isParallel - ) && ( - - - Paralel Onay - - )} -
-
-
- ))} - - {filteredWorkflows.length === 0 && ( -
- -

- Onay süreci bulunamadı -

-

- Arama kriterlerinizi değiştirin veya yeni bir onay süreci - ekleyin. -

-
- )} + +
+ {/* Header */} +
+
+

Onay Süreçleri

+

Departman bazlı satınalma onay süreçlerini yönetin

+
+
- {/* Workflow Details */} -
-

- Onay Adımları -

- {selectedWorkflow ? ( -
-
-

- {selectedWorkflow.name} -

-
-
Departman: {selectedWorkflow.departmentId}
-
- Tür: {getRequestTypeText(selectedWorkflow.requestType)} + {/* Search Bar */} +
+ + setSearchTerm(e.target.value)} + className="w-full pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+ +
+ {/* Workflow List */} +
+

Onay Süreçleri

+ {filteredWorkflows.map((workflow) => ( +
handleViewDetails(workflow)} + > +
+
+
+ +

{workflow.name}

+ + {getRequestTypeText(workflow.requestType)} + +
+

+ Departman: {workflow.department?.name} +

+

+ Limit: ₺{workflow.amountThreshold.toLocaleString()} ve üzeri +

-
- Tutar Limiti: ₺ - {selectedWorkflow.amountThreshold.toLocaleString()} +
+ + +
-
- Durum: {selectedWorkflow.isActive ? "Aktif" : "Pasif"} +
+ +
+
+ + + Toplam Adım + + {getTotalSteps(workflow)} +
+
+ + + Zorunlu Adım + + {getRequiredSteps(workflow)} +
+
+ + + Maks. Süre + + {getMaxTimeout(workflow)} gün +
+
+ Son Güncelleme + + {workflow.lastModificationTime.toLocaleDateString('tr-TR')} + +
+
+ +
+ + {workflow.isActive ? 'Aktif' : 'Pasif'} + +
+ {workflow.approvalLevels.some((level) => level.isParallel) && ( + + + Paralel Onay + + )}
+ ))} -
- {selectedWorkflow.approvalLevels - .sort((a, b) => a.sequence - b.sequence) - .map((level, index) => ( -
-
-
- - Adım {level.sequence} - - - {getApprovalLevelText(level.level)} - - {level.isRequired && ( - - Zorunlu + {filteredWorkflows.length === 0 && ( +
+ +

Onay süreci bulunamadı

+

+ Arama kriterlerinizi değiştirin veya yeni bir onay süreci ekleyin. +

+
+ )} +
+ + {/* Workflow Details */} +
+

Onay Adımları

+ {selectedWorkflow ? ( +
+
+

+ {selectedWorkflow.name} +

+
+
Departman: {selectedWorkflow.departmentId}
+
Tür: {getRequestTypeText(selectedWorkflow.requestType)}
+
Tutar Limiti: ₺{selectedWorkflow.amountThreshold.toLocaleString()}
+
Durum: {selectedWorkflow.isActive ? 'Aktif' : 'Pasif'}
+
+
+ +
+ {selectedWorkflow.approvalLevels + .sort((a, b) => a.sequence - b.sequence) + .map((level, index) => ( +
+
+
+ + Adım {level.sequence} - )} - {level.isParallel && ( - - Paralel + + {getApprovalLevelText(level.level)} + + {level.isRequired && ( + + Zorunlu + + )} + {level.isParallel && ( + + Paralel + + )} +
+ {level.timeoutDays && ( + + + {level.timeoutDays} gün )}
- {level.timeoutDays && ( - - - {level.timeoutDays} gün - + +
+
Onaylayanlar:
+
+ {level.approverNames.map((name, idx) => ( +
+ + {name} + + ({level.approverUserIds[idx]}) + +
+ ))} +
+
+ + {index < selectedWorkflow.approvalLevels.length - 1 && ( +
+
+
)}
+ ))} +
-
-
- Onaylayanlar: -
-
- {level.approverNames.map((name, idx) => ( -
- - {name} - - ({level.approverUserIds[idx]}) - -
- ))} -
+ {/* Workflow Statistics */} +
+
+
+
+ {getTotalSteps(selectedWorkflow)}
- - {index < selectedWorkflow.approvalLevels.length - 1 && ( -
-
-
- )} +
Toplam Adım
- ))} -
- - {/* Workflow Statistics */} -
-
-
-
- {getTotalSteps(selectedWorkflow)} +
+
+ {getRequiredSteps(selectedWorkflow)} +
+
Zorunlu Adım
-
Toplam Adım
-
-
-
- {getRequiredSteps(selectedWorkflow)} +
+
+ {getMaxTimeout(selectedWorkflow)} +
+
Maks. Gün
-
Zorunlu Adım
-
-
-
- {getMaxTimeout(selectedWorkflow)} -
-
Maks. Gün
-
- ) : ( -
- -

- Onay Adımlarını Görüntüle -

-

- Detaylarını görmek için sol taraftan bir onay süreci seçin. -

-
- )} + ) : ( +
+ +

+ Onay Adımlarını Görüntüle +

+

+ Detaylarını görmek için sol taraftan bir onay süreci seçin. +

+
+ )} +
@@ -397,8 +360,8 @@ const ApprovalWorkflows: React.FC = () => { workflow={editingWorkflow} mode={modalMode} /> -
- ); -}; + + ) +} -export default ApprovalWorkflows; +export default ApprovalWorkflows diff --git a/ui/src/views/supplyChain/components/DeliveryTracking.tsx b/ui/src/views/supplyChain/components/DeliveryTracking.tsx index 84dbf8bc..2d46b9e7 100644 --- a/ui/src/views/supplyChain/components/DeliveryTracking.tsx +++ b/ui/src/views/supplyChain/components/DeliveryTracking.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState } from 'react' import { FaSearch, FaFilter, @@ -9,14 +9,14 @@ import { FaBox, FaUser, FaFileAlt, -} from "react-icons/fa"; +} from 'react-icons/fa' import { DeliveryStatusEnum, MmDelivery, MmGoodsReceipt, ReceiptStatusEnum, QualityStatusEnum, -} from "../../../types/mm"; +} from '../../../types/mm' import { getConditionColor, getConditionText, @@ -24,43 +24,34 @@ import { getRequestTypeText, getDeliveryStatusColor, getDeliveryStatusIcon, -} from "../../../utils/erp"; -import { mockDeliveries } from "../../../mocks/mockDeliveries"; -import DeliveryTrackingModal from "./DeliveryTrackingModal"; -import Widget from "../../../components/common/Widget"; +} from '../../../utils/erp' +import { mockDeliveries } from '../../../mocks/mockDeliveries' +import DeliveryTrackingModal from './DeliveryTrackingModal' +import Widget from '../../../components/common/Widget' +import { Container } from '@/components/shared' const DeliveryTracking: React.FC = () => { - const [searchTerm, setSearchTerm] = useState(""); - const [statusFilter, setStatusFilter] = useState( - "all" - ); - const [selectedDelivery, setSelectedDelivery] = useState( - null - ); + const [searchTerm, setSearchTerm] = useState('') + const [statusFilter, setStatusFilter] = useState('all') + const [selectedDelivery, setSelectedDelivery] = useState(null) // Modal state - const [isModalOpen, setIsModalOpen] = useState(false); - const [modalMode, setModalMode] = useState<"create" | "view" | "edit">( - "view" - ); - const [selectedReceipt, setSelectedReceipt] = useState( - null - ); + const [isModalOpen, setIsModalOpen] = useState(false) + const [modalMode, setModalMode] = useState<'create' | 'view' | 'edit'>('view') + const [selectedReceipt, setSelectedReceipt] = useState(null) // Mock data - replace with actual API calls - const [deliveries] = useState(mockDeliveries); + const [deliveries] = useState(mockDeliveries) // Convert Delivery to GoodsReceipt for modal compatibility - const convertDeliveryToGoodsReceipt = ( - delivery: MmDelivery - ): MmGoodsReceipt => { + const convertDeliveryToGoodsReceipt = (delivery: MmDelivery): MmGoodsReceipt => { return { id: delivery.id, receiptNumber: delivery.deliveryNumber, orderId: delivery.orderNumber, receiptDate: delivery.actualDeliveryDate || delivery.expectedDeliveryDate, - receivedBy: delivery.receivedBy || "", - warehouseId: "WH001", // Default warehouse, could be mapped from delivery + receivedBy: delivery.receivedBy || '', + warehouseId: 'WH001', // Default warehouse, could be mapped from delivery status: delivery.status === DeliveryStatusEnum.Delivered ? ReceiptStatusEnum.Completed @@ -74,525 +65,450 @@ const DeliveryTracking: React.FC = () => { receivedQuantity: item.deliveredQuantity, acceptedQuantity: item.deliveredQuantity, rejectedQuantity: 0, - lotNumber: "", + lotNumber: '', expiryDate: undefined, qualityStatus: - item.condition === "Good" + item.condition === 'Good' ? QualityStatusEnum.Approved - : item.condition === "Damaged" - ? QualityStatusEnum.Rejected - : QualityStatusEnum.Pending, + : item.condition === 'Damaged' + ? QualityStatusEnum.Rejected + : QualityStatusEnum.Pending, storageLocation: undefined, })), creationTime: new Date(), lastModificationTime: new Date(), - }; - }; + } + } const handleViewDelivery = (delivery: MmDelivery) => { - const receipt = convertDeliveryToGoodsReceipt(delivery); - setSelectedReceipt(receipt); - setModalMode("view"); - setIsModalOpen(true); - }; + const receipt = convertDeliveryToGoodsReceipt(delivery) + setSelectedReceipt(receipt) + setModalMode('view') + setIsModalOpen(true) + } const handleEditDelivery = (delivery: MmDelivery) => { - const receipt = convertDeliveryToGoodsReceipt(delivery); - setSelectedReceipt(receipt); - setModalMode("edit"); - setIsModalOpen(true); - }; + const receipt = convertDeliveryToGoodsReceipt(delivery) + setSelectedReceipt(receipt) + setModalMode('edit') + setIsModalOpen(true) + } const handleSaveReceipt = (receipt: MmGoodsReceipt) => { // Handle saving the receipt // This would typically involve API calls to update the backend - console.log("Saving receipt:", receipt); - setIsModalOpen(false); - }; + console.log('Saving receipt:', receipt) + setIsModalOpen(false) + } const handleCloseModal = () => { - setIsModalOpen(false); - setSelectedReceipt(null); - }; + setIsModalOpen(false) + setSelectedReceipt(null) + } const filteredDeliveries = deliveries.filter((delivery) => { const matchesSearch = - delivery.deliveryNumber - .toLowerCase() - .includes(searchTerm.toLowerCase()) || + delivery.deliveryNumber.toLowerCase().includes(searchTerm.toLowerCase()) || delivery.orderNumber.toLowerCase().includes(searchTerm.toLowerCase()) || delivery.supplierName.toLowerCase().includes(searchTerm.toLowerCase()) || (delivery.trackingNumber && - delivery.trackingNumber - .toLowerCase() - .includes(searchTerm.toLowerCase())); - const matchesStatus = - statusFilter === "all" || delivery.status === statusFilter; - return matchesSearch && matchesStatus; - }); + delivery.trackingNumber.toLowerCase().includes(searchTerm.toLowerCase())) + const matchesStatus = statusFilter === 'all' || delivery.status === statusFilter + return matchesSearch && matchesStatus + }) const isDelayed = (delivery: MmDelivery) => { - const today = new Date(); - return ( - delivery.expectedDeliveryDate < today && !delivery.actualDeliveryDate - ); - }; + const today = new Date() + return delivery.expectedDeliveryDate < today && !delivery.actualDeliveryDate + } const getDaysDelay = (delivery: MmDelivery) => { - if (!isDelayed(delivery)) return 0; - const today = new Date(); - const diffTime = today.getTime() - delivery.expectedDeliveryDate.getTime(); - return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); - }; + if (!isDelayed(delivery)) return 0 + const today = new Date() + const diffTime = today.getTime() - delivery.expectedDeliveryDate.getTime() + return Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + } const getDeliveryProgress = (delivery: MmDelivery) => { - const totalQuantity = delivery.items.reduce( - (sum, item) => sum + item.orderedQuantity, - 0 - ); - const deliveredQuantity = delivery.items.reduce( - (sum, item) => sum + item.deliveredQuantity, - 0 - ); - return totalQuantity > 0 - ? Math.round((deliveredQuantity / totalQuantity) * 100) - : 0; - }; + const totalQuantity = delivery.items.reduce((sum, item) => sum + item.orderedQuantity, 0) + const deliveredQuantity = delivery.items.reduce((sum, item) => sum + item.deliveredQuantity, 0) + return totalQuantity > 0 ? Math.round((deliveredQuantity / totalQuantity) * 100) : 0 + } return ( -
- {/* Header */} -
-
-

Teslimat Takibi

-

- Sipariş teslimatlarını takip edin ve yönetin -

+ +
+ {/* Header */} +
+
+

Teslimat Takibi

+

Sipariş teslimatlarını takip edin ve yönetin

+
-
- {/* Summary Cards */} -
- - [ - DeliveryStatusEnum.InTransit, - DeliveryStatusEnum.OutForDelivery, - DeliveryStatusEnum.Shipped, - ].includes(d.status) - ).length - } - color="blue" - icon="FaTruck" - /> + {/* Summary Cards */} +
+ + [ + DeliveryStatusEnum.InTransit, + DeliveryStatusEnum.OutForDelivery, + DeliveryStatusEnum.Shipped, + ].includes(d.status), + ).length + } + color="blue" + icon="FaTruck" + /> - d.status === DeliveryStatusEnum.Delivered) - .length - } - color="green" - icon="FaCheckCircle" - /> + d.status === DeliveryStatusEnum.Delivered).length} + color="green" + icon="FaCheckCircle" + /> - d.status === DeliveryStatusEnum.PartiallyDelivered - ).length - } - color="orange" - icon="FaExclamationTriangle" - /> + d.status === DeliveryStatusEnum.PartiallyDelivered).length + } + color="orange" + icon="FaExclamationTriangle" + /> - d.status === DeliveryStatusEnum.Delayed || isDelayed(d) - ).length - } - color="teal" - icon="FaClock" - /> -
- - {/* Filters */} -
-
- - setSearchTerm(e.target.value)} - className="w-full pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + d.status === DeliveryStatusEnum.Delayed || isDelayed(d)) + .length + } + color="teal" + icon="FaClock" />
-
- - -
-
-
- {/* Deliveries List */} -
-

Teslimatlar

- {filteredDeliveries.map((delivery) => ( -
setSelectedDelivery(delivery)} + {/* Filters */} +
+
+ + setSearchTerm(e.target.value)} + className="w-full pl-10 pr-4 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + /> +
+
+ + +
+
+ +
+ {/* Deliveries List */} +
+

Teslimatlar

+ {filteredDeliveries.map((delivery) => ( +
setSelectedDelivery(delivery)} + > +
+
+
+

+ {delivery.deliveryNumber} +

+ + {getDeliveryStatusIcon(delivery.status)} + {getDeliveryStatusText(delivery.status)} + {isDelayed(delivery) && ( + + {getDaysDelay(delivery)} gün geç + + )} +
+

Sipariş: {delivery.orderNumber}

+

{delivery.supplierName}

+ {delivery.trackingNumber && ( +

+ Takip No: {delivery.trackingNumber} +

)}
-

- Sipariş: {delivery.orderNumber} -

-

- {delivery.supplierName} -

- {delivery.trackingNumber && ( -

- Takip No: {delivery.trackingNumber} +

+ + +
+
+ +
+
+ Beklenen Tarih +

+ {delivery.expectedDeliveryDate.toLocaleDateString('tr-TR')}

+
+
+ Teslimat Durumu +

{getDeliveryProgress(delivery)}%

+
+
+ + {/* Progress Bar */} +
+
+
+
+
+ +
+
+ + {getRequestTypeText(delivery.requestType)} +
+ {delivery.courierCompany && {delivery.courierCompany}} +
+
+ ))} + + {filteredDeliveries.length === 0 && ( +
+ +

Teslimat bulunamadı

+

Arama kriterlerinizi değiştirin.

+
+ )} +
+ + {/* Delivery Details */} +
+

Teslimat Detayları

+ {selectedDelivery ? ( +
+
+
+

+ {selectedDelivery.deliveryNumber} +

+ + {getDeliveryStatusIcon(selectedDelivery.status)} + {getDeliveryStatusText(selectedDelivery.status)} + +
+ +
+
+ Sipariş No: +

{selectedDelivery.orderNumber}

+
+
+ Tedarikçi: +

{selectedDelivery.supplierName}

+
+
+ Beklenen Tarih: +

+ {selectedDelivery.expectedDeliveryDate.toLocaleDateString('tr-TR')} +

+
+
+ Gerçek Tarih: +

+ {selectedDelivery.actualDeliveryDate + ? selectedDelivery.actualDeliveryDate.toLocaleDateString('tr-TR') + : 'Henüz teslim edilmedi'} +

+
+
+ + {selectedDelivery.trackingNumber && ( +
+
+
+ Kargo Takip No: +

+ {selectedDelivery.trackingNumber} +

+
+
+ Kargo Şirketi: +

+ {selectedDelivery.courierCompany} +

+
+
+
+ )} + +
+ + + Teslimat Adresi: + +

+ {selectedDelivery.deliveryAddress} +

+
+ + {selectedDelivery.receivedBy && ( +
+ + + Teslim Alan: + +

{selectedDelivery.receivedBy}

+
)}
-
- - -
-
-
-
- Beklenen Tarih -

- {delivery.expectedDeliveryDate.toLocaleDateString("tr-TR")} -

-
-
- Teslimat Durumu -

- {getDeliveryProgress(delivery)}% -

-
-
- - {/* Progress Bar */} -
-
-
-
-
- -
-
- - {getRequestTypeText(delivery.requestType)} -
- {delivery.courierCompany && ( - {delivery.courierCompany} - )} -
-
- ))} - - {filteredDeliveries.length === 0 && ( -
- -

- Teslimat bulunamadı -

-

- Arama kriterlerinizi değiştirin. -

-
- )} -
- - {/* Delivery Details */} -
-

- Teslimat Detayları -

- {selectedDelivery ? ( -
-
-
-

- {selectedDelivery.deliveryNumber} -

- - {getDeliveryStatusIcon(selectedDelivery.status)} - - {getDeliveryStatusText(selectedDelivery.status)} - - -
- -
-
- Sipariş No: -

- {selectedDelivery.orderNumber} -

-
-
- Tedarikçi: -

- {selectedDelivery.supplierName} -

-
-
- Beklenen Tarih: -

- {selectedDelivery.expectedDeliveryDate.toLocaleDateString( - "tr-TR" - )} -

-
-
- Gerçek Tarih: -

- {selectedDelivery.actualDeliveryDate - ? selectedDelivery.actualDeliveryDate.toLocaleDateString( - "tr-TR" - ) - : "Henüz teslim edilmedi"} -

-
-
- - {selectedDelivery.trackingNumber && ( -
-
-
- - Kargo Takip No: - -

- {selectedDelivery.trackingNumber} -

-
-
- - Kargo Şirketi: - -

- {selectedDelivery.courierCompany} -

-
-
-
- )} - -
- - - Teslimat Adresi: - -

- {selectedDelivery.deliveryAddress} -

-
- - {selectedDelivery.receivedBy && ( -
- - - Teslim Alan: - -

- {selectedDelivery.receivedBy} -

-
- )} -
- - {/* Items */} -
-
- Teslimat Kalemleri -
-
- {selectedDelivery.items.map((item) => ( -
-
-
-
- {item.material?.name} -
-

- {item.material?.id} -

+ {/* Items */} +
+
Teslimat Kalemleri
+
+ {selectedDelivery.items.map((item) => ( +
+
+
+
{item.material?.name}
+

{item.material?.id}

+
+ + {getConditionText(item.condition)} +
- - {getConditionText(item.condition)} - -
-
-
- Sipariş: -

- {item.orderedQuantity} {item.unit} -

+
+
+ Sipariş: +

+ {item.orderedQuantity} {item.unit} +

+
+
+ Teslim: +

+ {item.deliveredQuantity} {item.unit} +

+
+
+ Kalan: +

+ {item.orderedQuantity - item.deliveredQuantity} {item.unit} +

+
-
- Teslim: -

- {item.deliveredQuantity} {item.unit} -

-
-
- Kalan: -

- {item.orderedQuantity - item.deliveredQuantity}{" "} - {item.unit} -

-
-
- {item.notes && ( -
- Not: {item.notes} -
- )} -
- ))} -
-
- - {selectedDelivery.notes && ( -
- - Genel Notlar: - -

- {selectedDelivery.notes} -

-
- )} - - {selectedDelivery.attachments.length > 0 && ( -
- - - Ekler: - -
- {selectedDelivery.attachments.map((attachment, index) => ( -
- - - {attachment} - + {item.notes && ( +
+ Not: {item.notes} +
+ )}
))}
- )} -
- ) : ( -
- -

- Teslimat Detaylarını Görüntüle -

-

- Detaylarını görmek için sol taraftan bir teslimat seçin. -

-
- )} + + {selectedDelivery.notes && ( +
+ Genel Notlar: +

{selectedDelivery.notes}

+
+ )} + + {selectedDelivery.attachments.length > 0 && ( +
+ + + Ekler: + +
+ {selectedDelivery.attachments.map((attachment, index) => ( +
+ + + {attachment} + +
+ ))} +
+
+ )} +
+ ) : ( +
+ +

+ Teslimat Detaylarını Görüntüle +

+

+ Detaylarını görmek için sol taraftan bir teslimat seçin. +

+
+ )} +
@@ -604,8 +520,8 @@ const DeliveryTracking: React.FC = () => { receipt={selectedReceipt} mode={modalMode} /> -
- ); -}; + + ) +} -export default DeliveryTracking; +export default DeliveryTracking diff --git a/ui/src/views/supplyChain/components/DeliveryTrackingModal.tsx b/ui/src/views/supplyChain/components/DeliveryTrackingModal.tsx index dc350e4d..b989ae59 100644 --- a/ui/src/views/supplyChain/components/DeliveryTrackingModal.tsx +++ b/ui/src/views/supplyChain/components/DeliveryTrackingModal.tsx @@ -1,25 +1,18 @@ -import React, { useState, useEffect } from "react"; -import { - FaTimes, - FaSave, - FaTruck, - FaMapMarkerAlt, - FaCalendar, - FaBox, -} from "react-icons/fa"; +import React, { useState, useEffect } from 'react' +import { FaTimes, FaSave, FaTruck, FaMapMarkerAlt, FaCalendar, FaBox } from 'react-icons/fa' import { MmGoodsReceipt, ReceiptStatusEnum, QualityStatusEnum, MmGoodsReceiptItem, -} from "../../../types/mm"; +} from '../../../types/mm' interface DeliveryTrackingModalProps { - isOpen: boolean; - onClose: () => void; - onSave: (receipt: MmGoodsReceipt) => void; - receipt?: MmGoodsReceipt | null; - mode: "create" | "view" | "edit"; + isOpen: boolean + onClose: () => void + onSave: (receipt: MmGoodsReceipt) => void + receipt?: MmGoodsReceipt | null + mode: 'create' | 'view' | 'edit' } const DeliveryTrackingModal: React.FC = ({ @@ -30,123 +23,114 @@ const DeliveryTrackingModal: React.FC = ({ mode, }) => { const [formData, setFormData] = useState>({ - receiptNumber: "", - orderId: "", + receiptNumber: '', + orderId: '', receiptDate: new Date(), - receivedBy: "", - warehouseId: "", + receivedBy: '', + warehouseId: '', status: ReceiptStatusEnum.Pending, - notes: "", + notes: '', items: [], - }); + }) useEffect(() => { - if (mode === "create") { + if (mode === 'create') { // Reset form to initial empty state for new goods receipt setFormData({ - receiptNumber: "", - orderId: "", + receiptNumber: '', + orderId: '', receiptDate: new Date(), - receivedBy: "", - warehouseId: "", + receivedBy: '', + warehouseId: '', status: ReceiptStatusEnum.Pending, - notes: "", + notes: '', items: [], - }); + }) } else if (receipt) { // Load existing receipt data for view/edit modes - setFormData(receipt); + setFormData(receipt) } - }, [receipt, mode]); + }, [receipt, mode]) const handleInputChange = ( - e: React.ChangeEvent< - HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement - > + e: React.ChangeEvent, ) => { - const { name, value, type } = e.target; + const { name, value, type } = e.target setFormData((prev) => ({ ...prev, [name]: - type === "number" - ? parseFloat(value) || 0 - : type === "date" - ? new Date(value) - : value, - })); - }; + type === 'number' ? parseFloat(value) || 0 : type === 'date' ? new Date(value) : value, + })) + } const addReceiptItem = () => { const newItem: MmGoodsReceiptItem = { id: `item-${Date.now()}`, - receiptId: formData.id || "", - orderItemId: "", - materialId: "", + receiptId: formData.id || '', + orderItemId: '', + materialId: '', receivedQuantity: 0, acceptedQuantity: 0, rejectedQuantity: 0, qualityStatus: QualityStatusEnum.Pending, - }; + } setFormData((prev) => ({ ...prev, items: [...(prev.items || []), newItem], - })); - }; + })) + } const removeReceiptItem = (index: number) => { setFormData((prev) => ({ ...prev, items: prev.items?.filter((_, i) => i !== index) || [], - })); - }; + })) + } const updateReceiptItem = ( index: number, field: keyof MmGoodsReceiptItem, - value: string | number | QualityStatusEnum | Date | undefined + value: string | number | QualityStatusEnum | Date | undefined, ) => { setFormData((prev) => ({ ...prev, - items: - prev.items?.map((item, i) => - i === index ? { ...item, [field]: value } : item - ) || [], - })); - }; + items: prev.items?.map((item, i) => (i === index ? { ...item, [field]: value } : item)) || [], + })) + } const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - if (mode !== "view") { + e.preventDefault() + if (mode !== 'view') { const newReceipt: MmGoodsReceipt = { id: receipt?.id || `GR-${Date.now()}`, receiptNumber: formData.receiptNumber || `GR-${new Date().getFullYear()}-${Date.now().toString().slice(-3)}`, - orderId: formData.orderId || "", + orderId: formData.orderId || '', receiptDate: formData.receiptDate || new Date(), - receivedBy: formData.receivedBy || "", - warehouseId: formData.warehouseId || "", + receivedBy: formData.receivedBy || '', + warehouseId: formData.warehouseId || '', status: formData.status || ReceiptStatusEnum.Pending, notes: formData.notes, items: formData.items || [], creationTime: receipt?.creationTime || new Date(), lastModificationTime: new Date(), - }; - onSave(newReceipt); + } + onSave(newReceipt) } - onClose(); - }; + onClose() + } - if (!isOpen) return null; + if (!isOpen) return null - const isReadOnly = mode === "view"; + const isReadOnly = mode === 'view' const modalTitle = - mode === "create" - ? "Yeni Teslimat Takibi" - : mode === "edit" - ? "Teslimat Takibini Düzenle" - : "Teslimat Takibi Detayları"; + mode === 'create' + ? 'Yeni Teslimat Takibi' + : mode === 'edit' + ? 'Teslimat Takibini Düzenle' + : 'Teslimat Takibi Detayları' return (
@@ -156,10 +140,7 @@ const DeliveryTrackingModal: React.FC = ({ {modalTitle} -
@@ -174,13 +155,11 @@ const DeliveryTrackingModal: React.FC = ({
- + = ({
- + = ({ name="receiptDate" value={ formData.receiptDate - ? new Date(formData.receiptDate) - .toISOString() - .split("T")[0] - : "" + ? new Date(formData.receiptDate).toISOString().split('T')[0] + : '' } onChange={handleInputChange} readOnly={isReadOnly} @@ -225,13 +200,11 @@ const DeliveryTrackingModal: React.FC = ({
- + = ({ = ({ > - +
- +