update Inv

This commit is contained in:
Naz 2025-07-24 16:58:02 +08:00
parent 5298db78cb
commit 01ba9a6629
5 changed files with 166 additions and 154 deletions

View File

@ -36,9 +36,6 @@ namespace PSTW_CentralSystem.Areas.Inventory.Models
public string PartNumber { get; set; } = string.Empty; public string PartNumber { get; set; } = string.Empty;
public int CreatedByUserId { get; set; } public int CreatedByUserId { get; set; }
[ForeignKey("CreatedByUserId")] [ForeignKey("CreatedByUserId")]
public DateTime CreateDate { get; set; } = DateTime.Now;
public virtual UserModel? CreatedBy { get; set; } public virtual UserModel? CreatedBy { get; set; }
[ForeignKey("CompanyId")] [ForeignKey("CompanyId")]
public virtual CompanyModel? Company { get; set; } public virtual CompanyModel? Company { get; set; }

View File

@ -580,137 +580,140 @@
}, },
initiateTable() { initiateTable() {
self = this; self = this;
this.itemDatatable = $('#itemDatatable').DataTable({ this.itemDatatable = $('#itemDatatable').DataTable({
"data": this.items, "data": this.items,
"columns": [ "columns": [
{ {
"title": "Unique Id", "title": "Unique Id",
"data": "uniqueID", "data": "uniqueID",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
// Assign a unique ID to the <td> element // Assign a unique ID to the <td> element
$(td).attr('id', `qr${cellData}`); $(td).attr('id', `qr${cellData}`);
}, },
}, },
{ {
"title": "Print", "title": "Print",
"data": "uniqueID", "data": "uniqueID",
"render": function (data, type, full, meta) { "render": function (data, type, full, meta) {
var printButton = `<button type="button" class="btn btn-success print-btn" data-id="${data}">Print</button>`; var printButton = `<button type="button" class="btn btn-success print-btn" data-id="${data}">Print</button>`;
return printButton; return printButton;
}, },
"className": "align-middle", "className": "align-middle",
}, },
{ {
"title": "Item Short Name", "title": "Item Short Name",
"data": "productShortName", "data": "productShortName",
}, },
{ {
"title": "Serial Number", "title": "Serial Number",
"data": "serialNumber", "data": "serialNumber",
}, },
{ {
"title": "Part Number", "title": "Part Number",
"data": "partNumber", "data": "partNumber",
}, },
{ {
"title": "Category", "title": "Category",
"data": "category", "data": "category",
}, },
{ {
"title": "Quantity", "title": "Quantity",
"data": "quantity", "data": "quantity",
}, },
{ {
"title": "Supplier", "title": "Supplier",
"data": "supplier", "data": "supplier",
}, },
{ {
"title": "Purchase Date", "title": "Purchase Date",
"data": "purchaseDate", "data": "purchaseDate",
}, },
{ {
"title": "Price(RM)", "title": "Price(RM)",
"data": (row) => parseFloat(row.convertPrice).toFixed(2), "data": (row) => parseFloat(row.convertPrice).toFixed(2),
}, },
{ // --- REMOVE ---
"title": "Register Date", // {
"data": "createDate", // "title": "Register Date",
}, // "data": "createDate", // This is the problematic line
{ // },
"title": "Warranty Until", // --------------
"data": "warranty", {
"render": function (data, type, full, meta) { "title": "Warranty Until",
if (data > 0) { return full.endWDate } "data": "warranty",
else { return data } "render": function (data, type, full, meta) {
} if (data > 0) { return full.endWDate }
}, else { return data }
{ }
"title": "Location", },
"data": "currentUser", {
"render": function (data, type, full, meta) { "title": "Location",
currentUser = data ?? null; "data": "currentUser",
currentStore = full.currentStore ?? 'N/A'; "render": function (data, type, full, meta) {
currentStation = full.currentStation ?? 'N/A'; currentUser = data ?? null;
return `User: ${currentUser}<br> currentStore = full.currentStore ?? 'N/A';
Store: ${currentStore}<br> currentStation = full.currentStation ?? 'N/A';
Station: ${currentStation}` return `User: ${currentUser}<br>
} Store: ${currentStore}<br>
}, Station: ${currentStation}`
{ }
"title": "Edit", },
"data": "itemID", {
"render": function (data) { "title": "Edit",
var editButton = `<button type="button" class="btn btn-success edit-btn" data-id="${data}">Edit</button>`; "data": "itemID",
return editButton; "render": function (data) {
}, var editButton = `<button type="button" class="btn btn-success edit-btn" data-id="${data}">Edit</button>`;
"className": "align-middle", return editButton;
}, },
{ "className": "align-middle",
"title": "Delete", },
"data": "itemID", {
"render": function (data) { "title": "Delete",
var deleteButton = `<button type="button" class="btn btn-danger delete-btn" data-id="${data}">Delete</button>`; "data": "itemID",
return deleteButton; "render": function (data) {
}, var deleteButton = `<button type="button" class="btn btn-danger delete-btn" data-id="${data}">Delete</button>`;
"className": "align-middle", return deleteButton;
} },
], "className": "align-middle",
responsive: true,
drawCallback: function (settings) {
setTimeout(() => {
const api = this.api();
api.rows().every(function () {
const data = this.data();
const containerId = `qr${data.uniqueID}`;
const container = document.getElementById(containerId);
if (!container) {
return;
} }
],
responsive: true,
drawCallback: function (settings) {
setTimeout(() => {
const api = this.api();
api.rows().every(function () {
const data = this.data();
const containerId = `qr${data.uniqueID}`;
const container = document.getElementById(containerId);
container.innerHTML = ""; if (!container) {
container.append(data.uniqueID); return;
}
// Ensure qrString is valid before generating QR code container.innerHTML = "";
if (!data.qrString) { container.append(data.uniqueID);
return;
} // Ensure qrString is valid before generating QR code
if (!data.qrString) {
return;
}
// Generate QR Code
new QRCode(container, {
text: data.qrString,
width: 100,
height: 100,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M
});
});
}, 100); // Small delay to ensure elements exist
}
})
// Generate QR Code
new QRCode(container, {
text: data.qrString,
width: 100,
height: 100,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M
});
});
}, 100); // Small delay to ensure elements exist
}
})
// Attach click event listener to the edit buttons // Attach click event listener to the edit buttons
$('#itemDatatable tbody').off('click', '.edit-btn').on('click', '.edit-btn', function () { $('#itemDatatable tbody').off('click', '.edit-btn').on('click', '.edit-btn', function () {

View File

@ -182,7 +182,7 @@
<!-- Send Date --> <!-- Send Date -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;"> <div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4> <h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span> <span class="fixed-value text-truncate">{{ formatDate(movement.sendDate) }}</span>
</div> </div>
<!-- Receive Date --> <!-- Receive Date -->
@ -277,7 +277,7 @@
<!-- Send Date --> <!-- Send Date -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;"> <div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4> <h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span> <span class="fixed-value text-truncate">{{ formatDate(movement.sendDate) }}</span>
</div> </div>
<!-- Receive Date --> <!-- Receive Date -->
@ -398,7 +398,7 @@
<!-- Send Date --> <!-- Send Date -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;"> <div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4> <h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span> <span class="fixed-value text-truncate">{{ formatDate(movement.sendDate) }}</span>
</div> </div>
<!-- Receive Date --> <!-- Receive Date -->
@ -490,7 +490,7 @@
<!-- Send Date --> <!-- Send Date -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;"> <div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4> <h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span> <span class="fixed-value text-truncate">{{ formatDate(movement.sendDate) }}</span>
</div> </div>
<!-- Receive Date --> <!-- Receive Date -->
@ -830,6 +830,17 @@
]); ]);
}, },
methods: { methods: {
formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
paginatedItemsStation(item) { paginatedItemsStation(item) {
const start = (this.currentPageStation - 1) * this.itemsPerPageStation; const start = (this.currentPageStation - 1) * this.itemsPerPageStation;
const end = start + this.itemsPerPageStation; const end = start + this.itemsPerPageStation;
@ -1024,7 +1035,7 @@
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } }, { title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
{ title: "Product Code", data: "uniqueID" }, { title: "Product Code", data: "uniqueID" },
{ title: "Action", data: "action" }, { title: "Action", data: "action" },
{ title: "Send Date", data: "sendDate" }, { title: "Send Date", data: "sendDate", render: this.formatDate.bind(this) },
{ title: "Start Status", data: "toOther" }, { title: "Start Status", data: "toOther" },
{ title: "From User", data: "toUserName" }, { title: "From User", data: "toUserName" },
{ title: "Last User", data: "lastUserName" }, { title: "Last User", data: "lastUserName" },
@ -1044,7 +1055,7 @@
{ title: "Unique Id", data: "id" }, { title: "Unique Id", data: "id" },
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } }, { title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
{ title: "Product Code", data: "uniqueID" }, { title: "Product Code", data: "uniqueID" },
{ title: "Send Date", data: "sendDate" }, { title: "Send Date", data: "sendDate", render: this.formatDate.bind(this) },
{ title: "Receive Date", data: "receiveDate" }, { title: "Receive Date", data: "receiveDate" },
{ title: "Action", data: "action" }, { title: "Action", data: "action" },
{ title: "Start Status", data: "toOther" }, { title: "Start Status", data: "toOther" },
@ -1069,7 +1080,7 @@
{ title: "Unique Id", data: "id" }, { title: "Unique Id", data: "id" },
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; }}, { title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; }},
{ title: "Product Code", data: "uniqueID" }, { title: "Product Code", data: "uniqueID" },
{ title: "Assign Date", data: "sendDate" }, { title: "Assign Date", data: "sendDate", render: this.formatDate.bind(this) },
{ title: "Action", data: "action" }, { title: "Action", data: "action" },
{ title: "Station User PIC", data: "toUserName" }, { title: "Station User PIC", data: "toUserName" },
{ title: "From Station", data: "toStationName" }, { title: "From Station", data: "toStationName" },

View File

@ -468,6 +468,17 @@
function renderDeleteButton(data) { function renderDeleteButton(data) {
return `<button type="button" class="btn btn-danger delete-btn" data-id="${data}">Delete</button>`; return `<button type="button" class="btn btn-danger delete-btn" data-id="${data}">Delete</button>`;
} }
function formatDateTime(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
this.pendingRequestDatatable = $('#requestDatatable').DataTable({ this.pendingRequestDatatable = $('#requestDatatable').DataTable({
"data": this.request.filter(req => req.status === "Requested"), "data": this.request.filter(req => req.status === "Requested"),
@ -479,7 +490,7 @@
{ "title": "Document / Picture", "data": "document", "render": (data, type, full) => renderDocument(data) }, { "title": "Document / Picture", "data": "document", "render": (data, type, full) => renderDocument(data) },
{ "title": "Remark", "data": "remarkUser" }, { "title": "Remark", "data": "remarkUser" },
{ "title": "Station Deploy", "data": "stationName", "render": (data) => data || "Self Assign" }, { "title": "Station Deploy", "data": "stationName", "render": (data) => data || "Self Assign" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": (data) => formatDateTime(data) }, // Apply formatting here
{ "title": "Status", "data": "status" }, { "title": "Status", "data": "status" },
{ "title": "Delete", "data": "requestID", "render": renderDeleteButton, "className": "align-middle" } { "title": "Delete", "data": "requestID", "render": renderDeleteButton, "className": "align-middle" }
], ],
@ -498,8 +509,8 @@
{ "title": "Document / Picture", "data": "document", "render": (data, type, full) => renderDocument(data) }, { "title": "Document / Picture", "data": "document", "render": (data, type, full) => renderDocument(data) },
{ "title": "Remark", "data": "remarkUser" }, { "title": "Remark", "data": "remarkUser" },
{ "title": "Remark (Master)", "data": "remarkMasterInv" }, { "title": "Remark (Master)", "data": "remarkMasterInv" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": (data) => formatDateTime(data) }, // Apply formatting here
{ "title": "Approval Date", "data": "approvalDate" } { "title": "Approval Date", "data": "approvalDate", "render": (data) => formatDateTime(data) } // Apply formatting here
], ],
responsive: true, responsive: true,
}); });

View File

@ -379,7 +379,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
var userRole = await _userManager.GetRolesAsync(user); var userRole = await _userManager.GetRolesAsync(user);
var isAdmin = userRole.Contains("SystemAdmin") || userRole.Contains("SuperAdmin") || userRole.Contains("Finance"); var isAdmin = userRole.Contains("SystemAdmin") || userRole.Contains("SuperAdmin") || userRole.Contains("Finance");
List<ItemModel> itemList = new List<ItemModel>(); List<ItemModel> itemList = new List<ItemModel>();
List<ItemMovementModel> createDate = new List<ItemMovementModel>();
// Get the item list // Get the item list
if (isAdmin) if (isAdmin)
{ {
@ -418,15 +418,10 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
// Get the departments list (DepartmentId references Departments) // Get the departments list (DepartmentId references Departments)
var departments = await _centralDbContext.Departments.ToListAsync(); var departments = await _centralDbContext.Departments.ToListAsync();
var createDates = await _centralDbContext.ItemMovements.Where(r => r.Action == "Register").ToListAsync();
// Buat dictionary agar lebih cepat dicari berdasarkan ItemID
var createDateDict = await _centralDbContext.ItemMovements.Where(r => r.Action == "Register").GroupBy(r => r.ItemId).ToDictionaryAsync(g => g.Key, g => g.Min(m => m.Date));
// Now join items with users and departments manually // Now join items with users and departments manually
var itemListWithDetails = itemList.Select(item => new var itemListWithDetails = itemList.Select(item => new
{ {
createDate = createDateDict.ContainsKey(item.ItemID) ? createDateDict[item.ItemID].ToString("dd/MM/yyyy HH:mm:ss") : null, // createDate = createDateDict.ContainsKey(item.ItemID) ? createDateDict[item.ItemID].ToString("dd/MM/yyyy HH:mm:ss") : null,
item.ItemID, item.ItemID,
item.UniqueID, item.UniqueID,
item.CompanyId, item.CompanyId,
@ -450,7 +445,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
EndWDate = item.EndWDate.ToString("dd/MM/yyyy"), EndWDate = item.EndWDate.ToString("dd/MM/yyyy"),
InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"), InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"),
item.Department?.DepartmentName, item.Department?.DepartmentName,
RegisterDate = createDate, //RegisterDate = createDate,
CreatedBy =item.CreatedBy!.UserName, CreatedBy =item.CreatedBy!.UserName,
item.Product!.ProductName, item.Product!.ProductName,
item.Product!.ProductShortName, item.Product!.ProductShortName,
@ -497,9 +492,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
try try
{ {
var product = await _centralDbContext.Products.FirstOrDefaultAsync(p => p.ProductId == item.ProductId) ?? throw new Exception("Product not found"); var product = await _centralDbContext.Products.FirstOrDefaultAsync(p => p.ProductId == item.ProductId) ?? throw new Exception("Product not found");
var inventoryMaster = await _centralDbContext.InventoryMasters var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == item.CreatedByUserId) ?? new InventoryMasterModel { UserId = item.CreatedByUserId };
.Include("User")
.FirstOrDefaultAsync(i => i.UserId == item.CreatedByUserId) ?? new InventoryMasterModel { UserId = item.CreatedByUserId };
if (product.Category == "Disposable") if (product.Category == "Disposable")
{ {
@ -516,8 +509,6 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
item.Quantity = 1; // Force quantity to 1 for Assets/Parts if it's not already item.Quantity = 1; // Force quantity to 1 for Assets/Parts if it's not already
} }
item.CreateDate = DateTime.Now;
_centralDbContext.Items.Add(item); _centralDbContext.Items.Add(item);
_centralDbContext.Products.Update(product); // Update the product quantity _centralDbContext.Products.Update(product); // Update the product quantity
@ -584,7 +575,6 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
savedItem.EndWDate, savedItem.EndWDate,
savedItem.InvoiceDate, savedItem.InvoiceDate,
savedItem.PartNumber, savedItem.PartNumber,
CreateDate = savedItem.CreateDate.ToString("dd/MM/yyyy HH:mm:ss")
}; };
return Json(updatedItem); return Json(updatedItem);
} }