Compare commits
3 Commits
6dfac52c27
...
978411c9ec
| Author | SHA1 | Date | |
|---|---|---|---|
| 978411c9ec | |||
| 61c4415ff7 | |||
| 1408294922 |
34
.env
Normal file
34
.env
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# AccManager Backend Configuration
|
||||||
|
|
||||||
|
# Application
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
|
# Host port exposed by docker compose
|
||||||
|
APP_PORT=3000
|
||||||
|
|
||||||
|
# Image used for server pull deployment
|
||||||
|
DOCKER_IMAGE=toiiiiday/accmanager:1.0.3
|
||||||
|
|
||||||
|
# Container app port
|
||||||
|
PORT=3000
|
||||||
|
|
||||||
|
# SQL Server Configuration
|
||||||
|
DB_SERVER=172.20.235.176
|
||||||
|
DB_USER=sa
|
||||||
|
DB_PASSWORD=robotics@2022
|
||||||
|
DB_NAME=AccManager
|
||||||
|
DB_ENCRYPT=false
|
||||||
|
DB_TRUST_CERTIFICATE=true
|
||||||
|
DB_CONNECT_TIMEOUT=30000
|
||||||
|
|
||||||
|
# Security
|
||||||
|
BCRYPT_ROUNDS=12
|
||||||
|
|
||||||
|
# Email Verification (SMTP)
|
||||||
|
APP_BASE_URL=https://accrobot.pnkr.asia/
|
||||||
|
SMTP_HOST=smtp.gmail.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_SECURE=false
|
||||||
|
SMTP_USER=robotics.gitlab.2fa@gmail.com
|
||||||
|
SMTP_PASS=jaljalhreomqruqo
|
||||||
|
SMTP_FROM=robotics.gitlab.2fa@gmail.com
|
||||||
1143
backend/server.js
1143
backend/server.js
File diff suppressed because it is too large
Load Diff
@@ -89,18 +89,21 @@ BEGIN
|
|||||||
AssetId INT PRIMARY KEY IDENTITY(1,1),
|
AssetId INT PRIMARY KEY IDENTITY(1,1),
|
||||||
AssetCode NVARCHAR(100) NOT NULL UNIQUE,
|
AssetCode NVARCHAR(100) NOT NULL UNIQUE,
|
||||||
AssetName NVARCHAR(255) NOT NULL,
|
AssetName NVARCHAR(255) NOT NULL,
|
||||||
Category NVARCHAR(100),
|
|
||||||
Brand NVARCHAR(100),
|
|
||||||
Model NVARCHAR(255),
|
Model NVARCHAR(255),
|
||||||
SerialNumber NVARCHAR(100),
|
SerialNumber NVARCHAR(100),
|
||||||
Quantity INT NOT NULL DEFAULT 1,
|
Quantity INT NOT NULL DEFAULT 0,
|
||||||
|
ImportInPeriod INT NOT NULL DEFAULT 0,
|
||||||
|
ExportInPeriod INT NOT NULL DEFAULT 0,
|
||||||
|
EndingBalance INT NOT NULL DEFAULT 0,
|
||||||
Unit NVARCHAR(50),
|
Unit NVARCHAR(50),
|
||||||
Department NVARCHAR(100),
|
Department NVARCHAR(100),
|
||||||
|
Project NVARCHAR(150),
|
||||||
Location NVARCHAR(150),
|
Location NVARCHAR(150),
|
||||||
Custodian NVARCHAR(100),
|
Custodian NVARCHAR(100),
|
||||||
|
Borrower NVARCHAR(255),
|
||||||
|
ExportedBy NVARCHAR(100),
|
||||||
PurchaseDate DATE NULL,
|
PurchaseDate DATE NULL,
|
||||||
PurchasePrice DECIMAL(18,2) NULL,
|
PurchasePrice DECIMAL(18,2) NULL,
|
||||||
WarrantyUntil DATE NULL,
|
|
||||||
Status NVARCHAR(30) NOT NULL DEFAULT 'in_use',
|
Status NVARCHAR(30) NOT NULL DEFAULT 'in_use',
|
||||||
Notes NVARCHAR(MAX),
|
Notes NVARCHAR(MAX),
|
||||||
CreatedBy INT NULL,
|
CreatedBy INT NULL,
|
||||||
@@ -111,6 +114,16 @@ BEGIN
|
|||||||
PRINT 'Table AssetInventory created successfully.';
|
PRINT 'Table AssetInventory created successfully.';
|
||||||
END
|
END
|
||||||
|
|
||||||
|
IF COL_LENGTH('dbo.AssetInventory', 'Borrower') IS NULL
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE AssetInventory ADD Borrower NVARCHAR(255) NULL;
|
||||||
|
END
|
||||||
|
|
||||||
|
IF COL_LENGTH('dbo.AssetInventory', 'ExportedBy') IS NULL
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE AssetInventory ADD ExportedBy NVARCHAR(100) NULL;
|
||||||
|
END
|
||||||
|
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
-- 5. CREATE AUDIT LOG TABLE
|
-- 5. CREATE AUDIT LOG TABLE
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
@@ -132,6 +145,7 @@ END
|
|||||||
|
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
-- 6. CREATE INDEXES
|
-- 6. CREATE INDEXES
|
||||||
|
-- 6. CREATE INDEXES
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_Users_Username')
|
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_Users_Username')
|
||||||
BEGIN
|
BEGIN
|
||||||
@@ -158,10 +172,21 @@ BEGIN
|
|||||||
CREATE INDEX IX_AssetInventory_Status ON AssetInventory(Status);
|
CREATE INDEX IX_AssetInventory_Status ON AssetInventory(Status);
|
||||||
END
|
END
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_AssetInventory_AssetCode')
|
||||||
|
BEGIN
|
||||||
|
CREATE INDEX IX_AssetInventory_AssetCode ON AssetInventory(AssetCode);
|
||||||
|
END
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_AssetInventory_Status')
|
||||||
|
BEGIN
|
||||||
|
CREATE INDEX IX_AssetInventory_Status ON AssetInventory(Status);
|
||||||
|
END
|
||||||
|
|
||||||
PRINT 'Indexes created successfully.';
|
PRINT 'Indexes created successfully.';
|
||||||
|
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
-- 7. INSERT INITIAL DATA
|
-- 7. INSERT INITIAL DATA
|
||||||
|
-- 7. INSERT INITIAL DATA
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
|
|
||||||
-- Check if admin user exists
|
-- Check if admin user exists
|
||||||
@@ -186,6 +211,7 @@ END
|
|||||||
|
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
-- 8. DISPLAY DATABASE INFORMATION
|
-- 8. DISPLAY DATABASE INFORMATION
|
||||||
|
-- 8. DISPLAY DATABASE INFORMATION
|
||||||
-- ===========================================
|
-- ===========================================
|
||||||
PRINT '';
|
PRINT '';
|
||||||
PRINT '========================================';
|
PRINT '========================================';
|
||||||
|
|||||||
1098
public/js/app.js
1098
public/js/app.js
File diff suppressed because it is too large
Load Diff
@@ -197,126 +197,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Add/Edit Asset Modal -->
|
|
||||||
<div class="modal-backdrop fixed inset-0 z-[100] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="assetModal">
|
|
||||||
<div class="modal-content w-full max-w-2xl 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">Biểu mẫu tài sản</h3>
|
|
||||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeAssetModal()">
|
|
||||||
<span class="material-symbols-outlined">close</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<form id="assetForm" class="p-6 space-y-4 overflow-y-auto">
|
|
||||||
<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">Mã tài sản</label>
|
|
||||||
<input type="text" id="assetCodeInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" required placeholder="TS-001">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Tên tài sản</label>
|
|
||||||
<input type="text" id="assetNameInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" required placeholder="Laptop Dell Latitude 5440">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Danh mục</label>
|
|
||||||
<input type="text" id="assetCategoryInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="Thiết bị CNTT">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Trạng thái</label>
|
|
||||||
<select id="assetStatusInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3">
|
|
||||||
<option value="in_use">Đang sử dụng</option>
|
|
||||||
<option value="in_stock">Trong kho</option>
|
|
||||||
<option value="maintenance">Bảo trì</option>
|
|
||||||
<option value="disposed">Thanh lý</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Hãng</label>
|
|
||||||
<input type="text" id="assetBrandInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="Dell">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Model</label>
|
|
||||||
<input type="text" id="assetModelInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="Latitude 5440">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số serial</label>
|
|
||||||
<input type="text" id="assetSerialInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="SN123...">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số lượng</label>
|
|
||||||
<input type="number" id="assetQuantityInput" min="1" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" value="1">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Đơn vị</label>
|
|
||||||
<input type="text" id="assetUnitInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="cái">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Phòng ban</label>
|
|
||||||
<input type="text" id="assetDepartmentInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="Kỹ thuật">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Vị trí</label>
|
|
||||||
<input type="text" id="assetLocationInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="Kho A">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Người phụ trách</label>
|
|
||||||
<input type="text" id="assetCustodianInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="Nguyễn Văn A">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Ngày mua</label>
|
|
||||||
<input type="date" id="assetPurchaseDateInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Giá mua</label>
|
|
||||||
<input type="number" id="assetPriceInput" min="0" step="0.01" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" placeholder="0">
|
|
||||||
</div>
|
|
||||||
<div class="md:col-span-2">
|
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Hạn bảo hành</label>
|
|
||||||
<input type="date" id="assetWarrantyUntilInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3">
|
|
||||||
</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="assetNotesInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 h-20 resize-none" placeholder="Thông tin bổ sung"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-3 pt-2 sticky bottom-0 bg-white pb-1">
|
|
||||||
<button type="button" class="flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg" onclick="closeAssetModal()">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">Lưu tài sản</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- View Asset Modal -->
|
|
||||||
<div class="modal-backdrop fixed inset-0 z-[100] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="viewAssetModal">
|
|
||||||
<div class="modal-content w-full max-w-2xl 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">Chi tiết tài sản</h3>
|
|
||||||
<button class="p-1.5 rounded-lg hover:bg-slate-200 text-slate-400 transition-colors" onclick="closeViewAssetModal()">
|
|
||||||
<span class="material-symbols-outlined">close</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="assetDetailsContent" class="p-6 grid grid-cols-1 md:grid-cols-2 gap-3 text-sm text-slate-700 overflow-y-auto"></div>
|
|
||||||
<div class="p-6 pt-3 flex gap-3 border-t border-slate-100 bg-white">
|
|
||||||
<button type="button" class="flex-1 px-4 py-2 text-xs font-bold text-slate-600 border border-slate-200 rounded-lg" onclick="closeViewAssetModal()">Đóng</button>
|
|
||||||
<button type="button" class="flex-1 px-4 py-2 bg-primary hover:bg-primary-dim text-on-primary rounded-lg text-xs font-bold edit-asset-from-view">Sửa</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Delete Asset Modal -->
|
|
||||||
<div class="modal-backdrop fixed inset-0 z-[100] flex items-center justify-center bg-black/40 backdrop-blur-sm" id="deleteAssetModal">
|
|
||||||
<div class="modal-content w-full max-w-md 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 bg-red-50 flex items-center gap-3">
|
|
||||||
<span class="material-symbols-outlined text-red-600 text-2xl">warning</span>
|
|
||||||
<h3 class="text-base font-extrabold text-red-700">Xóa tài sản</h3>
|
|
||||||
</div>
|
|
||||||
<div class="p-6">
|
|
||||||
<p class="text-sm text-slate-600 mb-6">Bạn có chắc muốn xóa tài sản <strong id="deleteAssetName">-</strong>? Hành động này không thể hoàn tác.</p>
|
|
||||||
<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" onclick="closeDeleteAssetModal()">Hủy</button>
|
|
||||||
<button type="button" class="flex-1 px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-xs font-bold confirm-delete-asset">Xóa</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user