trả/mượn vtth
This commit is contained in:
1158
backend/server.js
1158
backend/server.js
File diff suppressed because it is too large
Load Diff
@@ -244,7 +244,8 @@ BEGIN
|
||||
ConsumableName NVARCHAR(255) NOT NULL,
|
||||
Unit NVARCHAR(50) NULL,
|
||||
ExportQuantity INT NOT NULL DEFAULT 1,
|
||||
RecipientName NVARCHAR(100) NOT NULL,
|
||||
RecipientUserId INT NULL,
|
||||
RecipientName NVARCHAR(100) NULL,
|
||||
ProjectName NVARCHAR(150) NULL,
|
||||
ExportedByName NVARCHAR(100) NOT NULL,
|
||||
ExportNote NVARCHAR(1000) NULL,
|
||||
@@ -287,6 +288,16 @@ BEGIN
|
||||
ALTER TABLE ConsumableExportHistory ADD RecipientName NVARCHAR(100) NULL;
|
||||
END
|
||||
|
||||
IF COL_LENGTH('dbo.ConsumableExportHistory', 'RecipientUserId') IS NULL
|
||||
BEGIN
|
||||
ALTER TABLE ConsumableExportHistory ADD RecipientUserId INT NULL;
|
||||
END
|
||||
|
||||
IF COL_LENGTH('dbo.ConsumableExportHistory', 'RecipientName') IS NOT NULL
|
||||
BEGIN
|
||||
ALTER TABLE ConsumableExportHistory ALTER COLUMN RecipientName NVARCHAR(100) NULL;
|
||||
END
|
||||
|
||||
IF COL_LENGTH('dbo.ConsumableExportHistory', 'ProjectName') IS NULL
|
||||
BEGIN
|
||||
ALTER TABLE ConsumableExportHistory ADD ProjectName NVARCHAR(150) NULL;
|
||||
@@ -358,6 +369,25 @@ BEGIN
|
||||
FOREIGN KEY (ConsumableId) REFERENCES ConsumableInventory(ConsumableId) ON DELETE CASCADE;
|
||||
END
|
||||
|
||||
UPDATE exports
|
||||
SET RecipientUserId = matchedUser.UserId
|
||||
FROM ConsumableExportHistory exports
|
||||
CROSS APPLY (
|
||||
SELECT TOP 1 users.UserId
|
||||
FROM Users users
|
||||
WHERE NULLIF(LTRIM(RTRIM(exports.ProjectName)), '') IS NULL
|
||||
AND (
|
||||
LOWER(LTRIM(RTRIM(ISNULL(users.FullName, '')))) = LOWER(LTRIM(RTRIM(ISNULL(exports.RecipientName, ''))))
|
||||
OR LOWER(LTRIM(RTRIM(ISNULL(users.Username, '')))) = LOWER(LTRIM(RTRIM(ISNULL(exports.RecipientName, ''))))
|
||||
)
|
||||
ORDER BY CASE
|
||||
WHEN LOWER(LTRIM(RTRIM(ISNULL(users.FullName, '')))) = LOWER(LTRIM(RTRIM(ISNULL(exports.RecipientName, '')))) THEN 0
|
||||
ELSE 1
|
||||
END,
|
||||
users.UserId
|
||||
) matchedUser
|
||||
WHERE exports.RecipientUserId IS NULL;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM sys.foreign_key_columns fkc
|
||||
@@ -374,6 +404,88 @@ BEGIN
|
||||
FOREIGN KEY (CreatedBy) REFERENCES Users(UserId) ON DELETE SET NULL;
|
||||
END
|
||||
|
||||
-- ===========================================
|
||||
-- 6B. CREATE CONSUMABLE RETURN HISTORY TABLE
|
||||
-- ===========================================
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ConsumableReturnHistory')
|
||||
BEGIN
|
||||
CREATE TABLE ConsumableReturnHistory (
|
||||
ReturnHistoryId INT PRIMARY KEY IDENTITY(1,1),
|
||||
ExportHistoryId INT NOT NULL,
|
||||
ConsumableId INT NOT NULL,
|
||||
ReturnQuantity INT NOT NULL DEFAULT 1,
|
||||
ReturnedByName NVARCHAR(100) NOT NULL,
|
||||
ReturnNote NVARCHAR(1000) NULL,
|
||||
PreviousExportInPeriod INT NOT NULL DEFAULT 0,
|
||||
NextExportInPeriod INT NOT NULL DEFAULT 0,
|
||||
PreviousEndingBalance INT NOT NULL DEFAULT 0,
|
||||
NextEndingBalance INT NOT NULL DEFAULT 0,
|
||||
CreatedBy INT NULL,
|
||||
ReturnedDate DATETIME NOT NULL DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
CreatedDate DATETIME NOT NULL DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
UpdatedDate DATETIME NOT NULL DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
FOREIGN KEY (ExportHistoryId) REFERENCES ConsumableExportHistory(ExportHistoryId) ON DELETE CASCADE,
|
||||
FOREIGN KEY (CreatedBy) REFERENCES Users(UserId) ON DELETE SET NULL
|
||||
);
|
||||
PRINT 'Table ConsumableReturnHistory created successfully.';
|
||||
END
|
||||
|
||||
-- ===========================================
|
||||
-- 6C. CREATE CONSUMABLE BORROW REQUESTS TABLE
|
||||
-- ===========================================
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ConsumableBorrowRequests')
|
||||
BEGIN
|
||||
CREATE TABLE ConsumableBorrowRequests (
|
||||
BorrowRequestId INT PRIMARY KEY IDENTITY(1,1),
|
||||
ConsumableId INT NOT NULL,
|
||||
RequestType NVARCHAR(20) NOT NULL DEFAULT 'borrow',
|
||||
BorrowerName NVARCHAR(100) NOT NULL,
|
||||
BorrowQuantity INT NOT NULL DEFAULT 1,
|
||||
Unit NVARCHAR(50) NULL,
|
||||
BorrowDate DATE NOT NULL DEFAULT (CAST(DATEADD(HOUR, 7, SYSUTCDATETIME()) AS DATE)),
|
||||
RequestStatus NVARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
RequestNote NVARCHAR(500) NULL,
|
||||
RejectReason NVARCHAR(1000) NULL,
|
||||
ExportHistoryId INT NULL,
|
||||
CreatedBy INT NULL,
|
||||
ProcessedBy INT NULL,
|
||||
ProcessedByName NVARCHAR(100) NULL,
|
||||
ProcessedDate DATETIME NULL,
|
||||
CreatedDate DATETIME NOT NULL DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
UpdatedDate DATETIME NOT NULL DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
FOREIGN KEY (ConsumableId) REFERENCES ConsumableInventory(ConsumableId) ON DELETE CASCADE,
|
||||
FOREIGN KEY (CreatedBy) REFERENCES Users(UserId) ON DELETE SET NULL
|
||||
);
|
||||
PRINT 'Table ConsumableBorrowRequests created successfully.';
|
||||
END
|
||||
|
||||
IF COL_LENGTH('dbo.ConsumableBorrowRequests', 'RequestType') IS NULL
|
||||
BEGIN
|
||||
ALTER TABLE ConsumableBorrowRequests
|
||||
ADD RequestType NVARCHAR(20) NOT NULL CONSTRAINT DF_ConsumableBorrowRequests_RequestType DEFAULT('borrow');
|
||||
END
|
||||
|
||||
UPDATE ConsumableBorrowRequests
|
||||
SET RequestType = 'borrow'
|
||||
WHERE RequestType IS NULL OR LTRIM(RTRIM(RequestType)) = '';
|
||||
|
||||
DECLARE @ConsumableBorrowProcessedByFk NVARCHAR(128);
|
||||
SELECT TOP 1 @ConsumableBorrowProcessedByFk = fk.name
|
||||
FROM sys.foreign_keys fk
|
||||
INNER JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
|
||||
INNER JOIN sys.columns c
|
||||
ON c.object_id = fkc.parent_object_id
|
||||
AND c.column_id = fkc.parent_column_id
|
||||
WHERE fk.parent_object_id = OBJECT_ID('dbo.ConsumableBorrowRequests')
|
||||
AND c.name = 'ProcessedBy';
|
||||
|
||||
IF @ConsumableBorrowProcessedByFk IS NOT NULL
|
||||
BEGIN
|
||||
DECLARE @DropConsumableBorrowProcessedByFkSql NVARCHAR(MAX) =
|
||||
N'ALTER TABLE ConsumableBorrowRequests DROP CONSTRAINT ' + QUOTENAME(@ConsumableBorrowProcessedByFk);
|
||||
EXEC sp_executesql @DropConsumableBorrowProcessedByFkSql;
|
||||
END
|
||||
|
||||
-- ===========================================
|
||||
-- 7. CREATE ASSET DEPARTMENTS TABLE
|
||||
-- ===========================================
|
||||
@@ -441,8 +553,7 @@ BEGIN
|
||||
CreatedDate DATETIME DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
UpdatedDate DATETIME DEFAULT (DATEADD(HOUR, 7, SYSUTCDATETIME())),
|
||||
FOREIGN KEY (AssetId) REFERENCES AssetInventory(AssetId) ON DELETE CASCADE,
|
||||
FOREIGN KEY (CreatedBy) REFERENCES Users(UserId) ON DELETE SET NULL,
|
||||
FOREIGN KEY (ProcessedBy) REFERENCES Users(UserId) ON DELETE SET NULL
|
||||
FOREIGN KEY (CreatedBy) REFERENCES Users(UserId) ON DELETE SET NULL
|
||||
);
|
||||
PRINT 'Table AssetBorrowRequests created successfully.';
|
||||
END
|
||||
@@ -502,13 +613,6 @@ BEGIN
|
||||
ALTER TABLE AssetBorrowRequests ADD ProcessedDate DATETIME NULL;
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_AssetBorrowRequests_ProcessedBy')
|
||||
BEGIN
|
||||
ALTER TABLE AssetBorrowRequests
|
||||
ADD CONSTRAINT FK_AssetBorrowRequests_ProcessedBy
|
||||
FOREIGN KEY (ProcessedBy) REFERENCES Users(UserId) ON DELETE SET NULL;
|
||||
END
|
||||
|
||||
UPDATE AssetBorrowRequests
|
||||
SET RequestType = ISNULL(NULLIF(LTRIM(RTRIM(RequestType)), ''), 'borrow');
|
||||
|
||||
@@ -805,6 +909,56 @@ BEGIN
|
||||
CREATE INDEX IX_ConsumableExportHistory_ExportedDate ON ConsumableExportHistory(ExportedDate DESC);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableExportHistory_RecipientUserId')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableExportHistory_RecipientUserId ON ConsumableExportHistory(RecipientUserId);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableReturnHistory_ExportHistoryId')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableReturnHistory_ExportHistoryId ON ConsumableReturnHistory(ExportHistoryId);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableReturnHistory_ConsumableId')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableReturnHistory_ConsumableId ON ConsumableReturnHistory(ConsumableId);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableReturnHistory_ReturnedDate')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableReturnHistory_ReturnedDate ON ConsumableReturnHistory(ReturnedDate DESC);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableBorrowRequests_ConsumableId')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableBorrowRequests_ConsumableId ON ConsumableBorrowRequests(ConsumableId);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableBorrowRequests_CreatedBy')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableBorrowRequests_CreatedBy ON ConsumableBorrowRequests(CreatedBy);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableBorrowRequests_RequestStatus')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableBorrowRequests_RequestStatus ON ConsumableBorrowRequests(RequestStatus);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableBorrowRequests_CreatedDate')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableBorrowRequests_CreatedDate ON ConsumableBorrowRequests(CreatedDate DESC);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableBorrowRequests_RequestType')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableBorrowRequests_RequestType ON ConsumableBorrowRequests(RequestType);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ConsumableBorrowRequests_ExportHistoryId')
|
||||
BEGIN
|
||||
CREATE INDEX IX_ConsumableBorrowRequests_ExportHistoryId ON ConsumableBorrowRequests(ExportHistoryId);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'UX_AssetDepartments_DepartmentName')
|
||||
BEGIN
|
||||
CREATE UNIQUE INDEX UX_AssetDepartments_DepartmentName ON AssetDepartments(DepartmentName);
|
||||
|
||||
File diff suppressed because one or more lines are too long
1169
public/js/app.js
1169
public/js/app.js
File diff suppressed because it is too large
Load Diff
@@ -391,11 +391,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Export Consumable Modal -->
|
||||
<!-- Borrow / Export Consumable Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[100] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="consumableExportModal">
|
||||
<div class="modal-content w-full max-w-lg bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4">
|
||||
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between bg-slate-50">
|
||||
<h3 class="text-base font-extrabold text-slate-900">Xuất vật tư tiêu hao</h3>
|
||||
<h3 id="consumableExportModalTitle" class="text-base font-extrabold text-slate-900">Mượn / xuất vật tư tiêu hao</h3>
|
||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeConsumableExportModal()">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
@@ -412,14 +412,14 @@
|
||||
<input type="number" id="consumableExportCurrentEndingInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Xuất cho</label>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Hình thức</label>
|
||||
<select id="consumableExportTargetTypeInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" required>
|
||||
<option value="user">Người dùng</option>
|
||||
<option value="project">Dự án</option>
|
||||
<option value="user">Mượn cho người dùng</option>
|
||||
<option value="project">Xuất cho dự án</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số lượng xuất</label>
|
||||
<label id="consumableExportQuantityLabel" class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số lượng mượn</label>
|
||||
<input type="number" id="consumableExportQuantityInput" min="1" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" value="1" required>
|
||||
</div>
|
||||
<div id="consumableExportProjectField" class="hidden">
|
||||
@@ -443,13 +443,197 @@
|
||||
<input type="text" id="consumableExportRoleInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Ghi chú xuất</label>
|
||||
<label id="consumableExportNoteLabel" class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Ghi chú mượn</label>
|
||||
<textarea id="consumableExportNoteInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 h-20 resize-none" placeholder="Nhập mục đích sử dụng hoặc ghi chú bàn giao"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button type="button" class="flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg" onclick="closeConsumableExportModal()">Hủy</button>
|
||||
<button type="submit" class="flex-1 px-4 py-2 bg-primary hover:bg-primary-dim text-on-primary rounded-lg text-xs font-bold">Xác nhận xuất</button>
|
||||
<button id="consumableExportSubmitBtn" type="submit" class="flex-1 px-4 py-2 bg-primary hover:bg-primary-dim text-on-primary rounded-lg text-xs font-bold">Xác nhận mượn</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Consumable Borrow Request Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[125] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="consumableBorrowRequestModal">
|
||||
<div class="modal-content w-full max-w-lg bg-white rounded-xl shadow-2xl border border-slate-200 overflow-visible m-4">
|
||||
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between bg-slate-50">
|
||||
<h3 class="text-base font-extrabold text-slate-900">Tạo đơn mượn vật tư tiêu hao</h3>
|
||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeConsumableBorrowRequestModal()">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="consumableBorrowRequestForm" class="p-6 space-y-4 relative">
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Người tạo đơn</label>
|
||||
<input type="text" id="consumableBorrowRequesterInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Vật tư cần mượn</label>
|
||||
<div id="consumableBorrowProductPicker" class="relative z-[135]">
|
||||
<input type="hidden" id="consumableBorrowProductInput">
|
||||
<button
|
||||
type="button"
|
||||
id="consumableBorrowProductDisplayBtn"
|
||||
class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 text-left flex items-center justify-between gap-2 bg-white"
|
||||
>
|
||||
<span id="consumableBorrowProductDisplayText" class="flex-1 min-w-0 truncate text-slate-600">-- Chọn vật tư --</span>
|
||||
<span class="material-symbols-outlined text-base text-slate-400">expand_more</span>
|
||||
</button>
|
||||
<div
|
||||
id="consumableBorrowProductDropdown"
|
||||
class="hidden absolute left-0 right-0 w-full max-w-full mt-1 bg-white border border-slate-200 rounded-lg shadow-xl z-[145] overflow-hidden"
|
||||
>
|
||||
<div class="p-2 border-b border-slate-100">
|
||||
<input
|
||||
type="text"
|
||||
id="consumableBorrowProductSearchInput"
|
||||
class="w-full border border-slate-200 rounded-md text-sm py-2 px-2.5"
|
||||
placeholder="Tìm theo mã, tên hoặc model vật tư..."
|
||||
autocomplete="off"
|
||||
>
|
||||
</div>
|
||||
<div id="consumableBorrowProductList" class="overflow-auto" style="max-height: 240px; overscroll-behavior: contain;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Tồn hiện tại</label>
|
||||
<input type="number" id="consumableBorrowCurrentStockInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Đơn vị</label>
|
||||
<input type="text" id="consumableBorrowUnitInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số lượng mượn</label>
|
||||
<input type="number" id="consumableBorrowQuantityInput" min="1" value="1" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" required>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Ngày mượn</label>
|
||||
<input type="date" id="consumableBorrowDateInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" required>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Ghi chú</label>
|
||||
<textarea id="consumableBorrowNoteInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 h-20 resize-none" placeholder="Nhập mục đích sử dụng hoặc ghi chú"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-slate-500">Tồn kho chỉ được trừ sau khi Asset/Admin chấp nhận đơn.</p>
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button type="button" class="flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg" onclick="closeConsumableBorrowRequestModal()">Hủy</button>
|
||||
<button type="submit" class="flex-1 px-4 py-2 bg-primary hover:bg-primary-dim text-on-primary rounded-lg text-xs font-bold">Gửi đơn mượn</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Consumable Borrow Requests List Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[125] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="consumableBorrowRequestsModal">
|
||||
<div class="modal-content w-full max-w-7xl bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4 flex flex-col" style="max-height: calc(100vh - 2rem);">
|
||||
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between bg-slate-50">
|
||||
<div>
|
||||
<h3 id="consumableBorrowRequestsModalTitle" class="text-base font-extrabold text-slate-900">Đơn mượn vật tư của tôi</h3>
|
||||
<p id="consumableBorrowRequestsModalSubtitle" class="text-xs text-slate-500 mt-0.5">Theo dõi trạng thái các đơn đã gửi.</p>
|
||||
</div>
|
||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeConsumableBorrowRequestsModal()">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="p-6 pt-4 overflow-auto">
|
||||
<div class="rounded-xl border border-slate-200 overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse" style="min-width: 1450px;">
|
||||
<thead class="bg-slate-50 border-b border-slate-200">
|
||||
<tr>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Mã đơn</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Người tạo</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Vật tư</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Loại đơn</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500 text-right">Số lượng</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Ngày</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Trạng thái</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Ghi chú</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Người xử lý</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Lý do từ chối</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500 text-right">Hành động</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="consumableBorrowRequestsTableBody" class="divide-y divide-slate-100">
|
||||
<tr><td colspan="11" class="px-4 py-8 text-sm text-center text-slate-500">Chưa có đơn mượn/trả vật tư.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reject Consumable Borrow/Return Request Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[150] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="consumableRequestRejectModal" style="z-index: 150;">
|
||||
<div class="modal-content w-full max-w-lg bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4">
|
||||
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between bg-slate-50">
|
||||
<h3 id="consumableRequestRejectModalTitle" class="text-base font-extrabold text-slate-900">Từ chối đơn vật tư</h3>
|
||||
<button type="button" class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeConsumableRequestRejectModal()">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="consumableRequestRejectForm" class="p-6 space-y-4">
|
||||
<input type="hidden" id="consumableRequestRejectIdInput">
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Lý do từ chối</label>
|
||||
<textarea id="consumableRequestRejectReasonInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 h-24 resize-none" placeholder="Nhập lý do để người tạo đơn biết..." required></textarea>
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<button type="button" class="flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg hover:bg-slate-50" onclick="closeConsumableRequestRejectModal()">Đóng</button>
|
||||
<button type="submit" class="flex-1 px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-xs font-bold">Xác nhận từ chối</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Return Consumable Modal -->
|
||||
<div class="modal-backdrop fixed inset-0 z-[130] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="consumableReturnModal">
|
||||
<div class="modal-content w-full max-w-lg bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4">
|
||||
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between bg-slate-50">
|
||||
<h3 id="consumableReturnModalTitle" class="text-base font-extrabold text-slate-900">Hoàn trả vật tư về kho</h3>
|
||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeConsumableReturnModal()">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="consumableReturnForm" class="p-6 space-y-4">
|
||||
<input type="hidden" id="consumableReturnExportHistoryIdInput">
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Vật tư</label>
|
||||
<input type="text" id="consumableReturnConsumableInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Nơi đang nhận</label>
|
||||
<input type="text" id="consumableReturnDestinationInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số lượng chưa trả</label>
|
||||
<input type="number" id="consumableReturnRemainingInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div>
|
||||
<label id="consumableReturnQuantityLabel" class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số lượng trả kho</label>
|
||||
<input type="number" id="consumableReturnQuantityInput" min="1" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" value="1" required>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label id="consumableReturnActorLabel" class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Người nhận lại kho</label>
|
||||
<input type="text" id="consumableReturnActorInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Ghi chú trả</label>
|
||||
<textarea id="consumableReturnNoteInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 h-20 resize-none" placeholder="Nhập tình trạng hoặc ghi chú khi nhận lại"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<p id="consumableReturnHelpText" class="text-xs text-slate-500">Khi xác nhận, số lượng này sẽ được cộng lại vào tồn kho ngay.</p>
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button type="button" class="flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg" onclick="closeConsumableReturnModal()">Hủy</button>
|
||||
<button id="consumableReturnSubmitBtn" type="submit" class="flex-1 px-4 py-2 bg-primary hover:bg-primary-dim text-on-primary rounded-lg text-xs font-bold">Xác nhận trả kho</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -459,7 +643,7 @@
|
||||
<div class="modal-backdrop fixed inset-0 z-[110] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="consumableExportHistoryModal" style="z-index: 124;">
|
||||
<div class="modal-content w-full max-w-6xl bg-white rounded-xl shadow-2xl border border-slate-200 overflow-hidden m-4 flex flex-col" style="max-height: calc(100vh - 2rem);">
|
||||
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between bg-slate-50">
|
||||
<h3 class="text-base font-extrabold text-slate-900">Lịch sử xuất vật tư tiêu hao</h3>
|
||||
<h3 class="text-base font-extrabold text-slate-900">Lịch sử mượn / xuất / trả vật tư</h3>
|
||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeConsumableExportHistoryModal()">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
@@ -467,22 +651,25 @@
|
||||
<div class="p-6 pt-4 overflow-auto">
|
||||
<div class="rounded-xl border border-slate-200 overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse" style="min-width: 1100px;">
|
||||
<table class="w-full text-left border-collapse" style="min-width: 1500px;">
|
||||
<thead class="bg-slate-50 border-b border-slate-200">
|
||||
<tr>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Ngày giờ</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Vật tư</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Số lượng</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Người nhận</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Dự án nhận</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Nơi nhận</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500 text-right">Đã xuất</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500 text-right">Đã trả</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500 text-right">Còn lại</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Trạng thái</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Người xuất</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Tồn trước/sau</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500">Ghi chú</th>
|
||||
<th class="px-4 py-2.5 text-[10px] font-bold uppercase tracking-wider text-slate-500 text-right">Thao tác</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="consumableExportHistoryTableBody" class="divide-y divide-slate-100">
|
||||
<tr>
|
||||
<td colspan="8" class="px-4 py-8 text-sm text-center text-slate-500">Chưa có dữ liệu lịch sử xuất vật tư.</td>
|
||||
<td colspan="11" class="px-4 py-8 text-sm text-center text-slate-500">Chưa có dữ liệu lịch sử mượn / xuất vật tư.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -323,6 +323,6 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../js/app.js?v=20260515-5"></script>
|
||||
<script src="../js/app.js?v=20260630-1"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user