fix model validate
This commit is contained in:
@@ -4426,6 +4426,10 @@ app.post('/api/assets', requireAssetOrAdmin, async (req, res) => {
|
|||||||
return res.status(400).json({ success: false, message: 'Asset name is required' });
|
return res.status(400).json({ success: false, message: 'Asset name is required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!payload.model) {
|
||||||
|
return res.status(400).json({ success: false, message: 'Model is required' });
|
||||||
|
}
|
||||||
|
|
||||||
if (!payload.assetCode) {
|
if (!payload.assetCode) {
|
||||||
payload.assetCode = await generateUniqueManualAssetCode(payload);
|
payload.assetCode = await generateUniqueManualAssetCode(payload);
|
||||||
}
|
}
|
||||||
@@ -4490,6 +4494,10 @@ app.put('/api/assets/:id', requireAssetOrAdmin, async (req, res) => {
|
|||||||
return res.status(400).json({ success: false, message: 'Asset code and asset name are required' });
|
return res.status(400).json({ success: false, message: 'Asset code and asset name are required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!payload.model) {
|
||||||
|
return res.status(400).json({ success: false, message: 'Model is required' });
|
||||||
|
}
|
||||||
|
|
||||||
await ensureDepartmentExists(payload.department);
|
await ensureDepartmentExists(payload.department);
|
||||||
|
|
||||||
await pool.request()
|
await pool.request()
|
||||||
@@ -4608,6 +4616,8 @@ app.post('/api/assets/import', requireAssetOrAdmin, upload.single('file'), async
|
|||||||
const normalizedRows = incomingRows
|
const normalizedRows = incomingRows
|
||||||
.map((row, rowIndex) => {
|
.map((row, rowIndex) => {
|
||||||
const normalized = normalizeAssetPayload(row);
|
const normalized = normalizeAssetPayload(row);
|
||||||
|
const rowSourceStt = parseAssetImportSttNumber(row?.sourceStt);
|
||||||
|
normalized.__importRowLabel = rowSourceStt !== null ? `STT ${rowSourceStt}` : `dong ${rowIndex + 1}`;
|
||||||
const hasOriginalAssetCode = String(normalized.assetCode || '').trim() !== '';
|
const hasOriginalAssetCode = String(normalized.assetCode || '').trim() !== '';
|
||||||
if (!hasOriginalAssetCode && normalized.assetName) {
|
if (!hasOriginalAssetCode && normalized.assetName) {
|
||||||
normalized.assetCode = generateImportAssetCodeFromRow(normalized, rowIndex + 1);
|
normalized.assetCode = generateImportAssetCodeFromRow(normalized, rowIndex + 1);
|
||||||
@@ -4619,7 +4629,20 @@ app.post('/api/assets/import', requireAssetOrAdmin, upload.single('file'), async
|
|||||||
.filter(row => isMeaningfulImportedAssetRow(row));
|
.filter(row => isMeaningfulImportedAssetRow(row));
|
||||||
|
|
||||||
if (!normalizedRows.length) {
|
if (!normalizedRows.length) {
|
||||||
return res.status(400).json({ success: false, message: 'No valid rows found. Asset name or model is required.' });
|
return res.status(400).json({ success: false, message: 'No valid rows found. MODEL is required.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const missingModelRows = normalizedRows
|
||||||
|
.filter(row => !String(row.model || '').trim())
|
||||||
|
.map(row => row.__importRowLabel)
|
||||||
|
.filter(Boolean);
|
||||||
|
if (missingModelRows.length) {
|
||||||
|
const limitedRows = missingModelRows.slice(0, 20);
|
||||||
|
const suffix = missingModelRows.length > limitedRows.length ? ', ...' : '';
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: `Cot MODEL la bat buoc. Thieu du lieu tai: ${limitedRows.join(', ')}${suffix}`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const transaction = new sql.Transaction(pool);
|
const transaction = new sql.Transaction(pool);
|
||||||
|
|||||||
@@ -4418,6 +4418,7 @@ class AccountManager {
|
|||||||
|
|
||||||
bindInput('assetCodeInput', 'assetCodeError');
|
bindInput('assetCodeInput', 'assetCodeError');
|
||||||
bindInput('assetNameInput', 'assetNameError');
|
bindInput('assetNameInput', 'assetNameError');
|
||||||
|
bindInput('assetModelInput', 'assetModelError');
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAssetFieldValidation(inputId, errorId) {
|
clearAssetFieldValidation(inputId, errorId) {
|
||||||
@@ -4438,6 +4439,7 @@ class AccountManager {
|
|||||||
clearAssetFormValidation() {
|
clearAssetFormValidation() {
|
||||||
this.clearAssetFieldValidation('assetCodeInput', 'assetCodeError');
|
this.clearAssetFieldValidation('assetCodeInput', 'assetCodeError');
|
||||||
this.clearAssetFieldValidation('assetNameInput', 'assetNameError');
|
this.clearAssetFieldValidation('assetNameInput', 'assetNameError');
|
||||||
|
this.clearAssetFieldValidation('assetModelInput', 'assetModelError');
|
||||||
}
|
}
|
||||||
|
|
||||||
setAssetFieldValidationError(inputId, errorId, message) {
|
setAssetFieldValidationError(inputId, errorId, message) {
|
||||||
@@ -4828,6 +4830,13 @@ class AccountManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!payload.model) {
|
||||||
|
this.setAssetFieldValidationError('assetModelInput', 'assetModelError', 'Vui lòng nhập model.');
|
||||||
|
this.notifyWarning('Vui lòng nhập đầy đủ các trường bắt buộc.');
|
||||||
|
document.getElementById('assetModelInput')?.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isEdit && !payload.assetCode) {
|
if (isEdit && !payload.assetCode) {
|
||||||
this.setAssetFieldValidationError('assetCodeInput', 'assetCodeError', 'Mã tài sản là bắt buộc khi cập nhật.');
|
this.setAssetFieldValidationError('assetCodeInput', 'assetCodeError', 'Mã tài sản là bắt buộc khi cập nhật.');
|
||||||
this.notifyWarning('Vui lòng nhập đầy đủ các trường bắt buộc.');
|
this.notifyWarning('Vui lòng nhập đầy đủ các trường bắt buộc.');
|
||||||
|
|||||||
@@ -225,8 +225,9 @@
|
|||||||
<input type="text" id="assetStatusInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly value="Trong kho">
|
<input type="text" id="assetStatusInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3 bg-slate-50" readonly value="Trong kho">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Model</label>
|
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Model <span class="text-red-600">*</span></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">
|
<input type="text" id="assetModelInput" class="w-full border border-slate-200 rounded-lg text-sm py-2.5 px-3" required placeholder="Latitude 5440">
|
||||||
|
<p id="assetModelError" class="mt-1 text-xs font-semibold text-red-600 hidden"></p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số serial</label>
|
<label class="text-[10px] font-bold uppercase text-slate-500 tracking-widest block mb-1">Số serial</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user