From 43962646bbd4d254264d69cf38d78dc0a1c8b0d5 Mon Sep 17 00:00:00 2001 From: ArifHilmi Date: Tue, 25 Feb 2025 16:24:27 +0800 Subject: [PATCH] update qr scanner --- Areas/Inventory/Models/ItemMovementModel.cs | 3 +- .../InventoryMaster/AdminDashboard.cshtml | 2 +- .../InventoryMaster/ItemRegistration.cshtml | 2 +- .../Views/ItemMovement/ItemRequest.cshtml | 11 +- .../Views/ItemMovement/QrUser.cshtml | 236 +++++++++++++++--- .../Views/ItemMovement/UserDashboard.cshtml | 2 +- Controllers/API/Inventory/InvMainAPI.cs | 102 ++++++-- Views/Shared/_Layout.cshtml | 21 +- 8 files changed, 306 insertions(+), 73 deletions(-) diff --git a/Areas/Inventory/Models/ItemMovementModel.cs b/Areas/Inventory/Models/ItemMovementModel.cs index a7caef2..dc3d6fd 100644 --- a/Areas/Inventory/Models/ItemMovementModel.cs +++ b/Areas/Inventory/Models/ItemMovementModel.cs @@ -30,8 +30,9 @@ namespace PSTW_CentralSystem.Areas.Inventory.Models public bool MovementComplete { get; set; } = false; //public virtual ItemModel? Item { get; set; } //[ForeignKey("ToStore")] - public virtual ItemModel? Item { get; set; } [ForeignKey("ItemId")] + public virtual ItemModel? Item { get; set; } + [ForeignKey("ToStore")] public virtual StoreModel? NextStore { get; set; } [ForeignKey("ToStation")] public virtual StationModel? NextStation { get; set; } diff --git a/Areas/Inventory/Views/InventoryMaster/AdminDashboard.cshtml b/Areas/Inventory/Views/InventoryMaster/AdminDashboard.cshtml index 94d3e40..f3a0b3e 100644 --- a/Areas/Inventory/Views/InventoryMaster/AdminDashboard.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/AdminDashboard.cshtml @@ -10,7 +10,7 @@

Store: {{ currentUserCompanyDept.departmentName }}

- @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml"); + @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml")

Inventory Report

diff --git a/Areas/Inventory/Views/InventoryMaster/ItemRegistration.cshtml b/Areas/Inventory/Views/InventoryMaster/ItemRegistration.cshtml index 70b03ae..de4b962 100644 --- a/Areas/Inventory/Views/InventoryMaster/ItemRegistration.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/ItemRegistration.cshtml @@ -223,7 +223,7 @@
diff --git a/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml b/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml index 710dcb0..a7f255e 100644 --- a/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml +++ b/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml @@ -240,10 +240,6 @@ try { const requiredFields = ['stationId', 'productId', 'quantity', 'productCategory']; - this.userId = this.currentUser.id; - this.status = "Requested"; - this.requestDate = new Date().toISOString(); - // Loop through required fields and check if any are null or empty for (let field of requiredFields) { if (!this[field]) { @@ -252,6 +248,13 @@ } } + this.userId = this.currentUser.id; + this.status = "Requested"; + + const now = new Date(); + this.requestDate = new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(); + + // Prepare data as JSON (No file upload) const requestData = { ProductId: this.productId, diff --git a/Areas/Inventory/Views/ItemMovement/QrUser.cshtml b/Areas/Inventory/Views/ItemMovement/QrUser.cshtml index 858c036..f22ab6c 100644 --- a/Areas/Inventory/Views/ItemMovement/QrUser.cshtml +++ b/Areas/Inventory/Views/ItemMovement/QrUser.cshtml @@ -32,10 +32,16 @@

QR & Barcode Scanner

-
+ + +

Item Receive Information :

-
+
+

Item Return Information :

+
+ +
@@ -81,7 +87,7 @@

- +
@@ -121,10 +127,51 @@
+ +
+
+
+
+ Receiver Information +
+
    + +
  • +
    + + User: + + + {{ thisItem.toUserName }} + +
    +
  • + + +
  • + + Store: + + {{ thisItem.toStoreName }} +
  • + + +
  • + + Station: + + {{ thisItem.toStationName || 'N/A' }} +
  • +
+
+
+
+
+
@@ -155,8 +202,8 @@ @* Submit and Reset Buttons *@
- - + +
@@ -165,8 +212,10 @@
+ +
@@ -201,8 +250,7 @@ @* Submit and Reset Buttons *@
- - +
@@ -213,6 +261,66 @@
+ + + + +
+
+

The item has been register as returned.

+

You need to request this item again to used it legally.

+
+
+ + +
+
+

The item is not assigned to you.

+

You need to request this item to validly use it.

+
+
+
@@ -240,7 +348,11 @@ debounceTime: 500, currentUser: null, movementId: null, - currentUserId:null, + currentUserId: null, + remark: null, + consignmentNote: null, + receiveReturn: null, + UniqueID : null, }; }, mounted() { @@ -250,18 +362,29 @@ }, methods: { async updateItemMovement() { - if (!confirm("Are you sure you already receive this item?")) { - return false; + + const requiredFields = ['selectedStation']; + + for (let field of requiredFields) { + if (!this[field]) { + alert(`Request Error: Please fill in required field ${field}.`, 'warning'); + return; + } + } + + if (this.receiveReturn == null) { + if (!confirm("Are you sure you already received this item?")) { + return false; + } } try { - // Disable button - + const now = new Date(); const formData = { Id: this.thisItem.movementId, LastStation: this.selectedStation, LatestStatus: "Delivered", - ReceiveDate: new Date().toISOString(), + ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(), MovementComplete: true }; @@ -274,35 +397,61 @@ }); if (response.ok) { - alert('Success! Item movement has been successfully submitted.'); - this.thisItem = await response.json(); - this.displayStatus = "return"; - this.resetForm(); + if (this.receiveReturn == null) { + alert('Success! Item has been successfully received.'); + this.thisItem = await response.json(); + this.displayStatus = "return"; + this.fetchItem(this.UniqueID); + this.resetForm(); + } else { + this.returnItemMovement(); + } } else { throw new Error('Failed to submit form.'); } } catch (error) { console.error('Error:', error); alert('Inventory PSTW Error: An error occurred.'); - } + } }, async returnItemMovement() { - if (!confirm("Are you sure you already receive this item?")) { + + const requiredFields = ['remark', 'consignmentNote']; + + for (let field of requiredFields) { + if (!this[field]) { + alert(`Request Error: Please fill in required field ${field}.`, 'warning'); + return; + } + } + + if (!confirm("Are you sure you want to return this item?")) { return false; } try { - // Disable button - + const now = new Date(); const formData = { - Id: this.thisItem.movementId, - LastStation: this.selectedStation, - LatestStatus: "Delivered", - ReceiveDate: new Date().toISOString(), - MovementComplete: true + ItemId: this.thisItem.itemID, + ToStation: this.thisItem.currentStationId, + ToStore: this.thisItem.currentStoreId, + ToUser: this.currentUserId, + ToOther: "Return", + SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(), + Action: "StockIn", + Quantity: this.thisItem.quantity, + Remark: this.remark, + ConsignmentNote: this.consignmentNote, + Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(), + LastUser: this.thisItem.toUser, + LastStore: this.thisItem.toStore, + LastStation: this.thisItem.toStation, + LatestStatus: null, + ReceiveDate: null, + MovementComplete: false, }; - const response = await fetch('/InvMainAPI/UpdateItemMovementUser', { + const response = await fetch('/InvMainAPI/ReturnItemMovementUser', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -311,9 +460,10 @@ }); if (response.ok) { - alert('Success! Item movement has been successfully submitted.'); + alert('Success! Item is on the delivery to return to Inventory Master.'); this.thisItem = await response.json(); - this.displayStatus = "return"; + $('#returnModal').modal('hide'); + this.displayStatus = "requestAgain"; this.resetForm(); } else { throw new Error('Failed to submit form.'); @@ -326,7 +476,7 @@ startScanner() { const config = { fps: 60, - qrbox: 200 + qrbox: 400 }; navigator.mediaDevices.getUserMedia({ video: true }) @@ -336,6 +486,7 @@ if (!this.debounceTimeout) { this.debounceTimeout = setTimeout(() => { this.qrCodeResult = decodedText; + this.UniqueID = decodedText.split('/').pop(); this.fetchItem(decodedText.split('/').pop()); this.debounceTimeout = null; }, this.debounceTime); @@ -356,14 +507,15 @@ if (response.ok) { this.thisItem = await response.json(); - if (this.thisItem.movementId != null && this.thisItem.latestStatus == null && this.thisItem.currentUserId == this.currentUserId) { + if (this.thisItem.movementId != null && this.thisItem.toOther === "On Delivery" && this.thisItem.latestStatus == null && this.thisItem.currentUserId == this.currentUserId) { this.displayStatus = "arrived"; - } else if (this.thisItem.movementId != null && this.thisItem.toOther === "Delivered" && this.thisItem.currentUserId == this.currentUserId) { + } else if (this.thisItem.movementId != null && this.thisItem.toOther === "On Delivery" && this.thisItem.latestStatus != null && this.thisItem.currentUserId == this.currentUserId) { this.displayStatus = "return"; + } else if (this.thisItem.movementId != null && this.thisItem.toOther === "Return" && this.thisItem.latestStatus == null && this.thisItem.toUser == this.currentUserId) { + this.displayStatus = "requestAgain"; } else { this.displayStatus = "differentUser"; this.thisItem = null; - this.displayStatus = null; } } else { console.error('Failed to fetch item information'); @@ -409,6 +561,7 @@ console.error('There was a problem with the fetch operation:', error); } }, + resetScanner() { this.displayStatus = null; this.qrCodeResult = null; @@ -416,9 +569,24 @@ this.startScanner(); }, + resetForm() { this.selectedStation = null; - } + }, + + async receiveReturnAPI() { + this.receiveReturn = 1; + console.log("update"); + this.updateItemMovement(); + }, + + receiveReturnMessage() { + $("#returnModal").modal("show"); + }, + + closeModal() { + $('#returnModal').modal('hide'); // Manually hide the modal + }, }, }); diff --git a/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml b/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml index f130caa..9f400f4 100644 --- a/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml +++ b/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml @@ -10,7 +10,7 @@

Store: {{ currentUserCompanyDept.departmentName }}

- @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml"); + @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml") @section Scripts { @{ diff --git a/Controllers/API/Inventory/InvMainAPI.cs b/Controllers/API/Inventory/InvMainAPI.cs index 94e49c1..4247d9f 100644 --- a/Controllers/API/Inventory/InvMainAPI.cs +++ b/Controllers/API/Inventory/InvMainAPI.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authorization; +using Azure.Core; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -328,6 +329,9 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory item.Product!.ProductShortName, item.Product!.Category, //CurrentUser = item.Movement?.FromUser?.UserName, + FromUser = item.Movement?.ToUser, + FromStore = item.Movement?.ToStore, + FromStation = item.Movement?.ToStation, CurrentUser = item.Movement?.FromUser?.UserName, CurrentStore = item.Movement?.FromStore?.StoreName, CurrentStation = item.Movement?.FromStation?.StationName, @@ -480,7 +484,13 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory .Include(i => i.Movement) .ThenInclude(m => m!.FromStation) .Include(i => i.Movement) - .ThenInclude(m => m!.FromUser).FirstOrDefaultAsync(i => i.UniqueID == id); + .ThenInclude(m => m!.FromUser) + .Include(i => i.Movement) + .ThenInclude(m => m!.NextStore) + .Include(i => i.Movement) + .ThenInclude(m => m!.NextStation) + .Include(i => i.Movement) + .ThenInclude(m => m!.NextUser).FirstOrDefaultAsync(i => i.UniqueID == id); if (item == null){ return NotFound(new { success = false, message = "Item not found" }); } @@ -514,7 +524,15 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory CurrentUser = item.Movement?.FromUser?.UserName, CurrentUserId = item.Movement?.FromUser?.Id, CurrentStore = item.Movement?.FromStore?.StoreName, + CurrentStoreId = item.Movement?.FromStore?.Id, CurrentStation = item.Movement?.FromStation?.StationName, + CurrentStationId = item.Movement?.FromStation?.StationId, + ToUser = item.Movement?.ToUser, + ToUserName = item.Movement?.NextUser?.UserName, + ToStore = item.Movement?.ToStore, + ToStoreName = item.Movement?.NextStore?.StoreName, + ToStation = item.Movement?.ToStation, + ToStationName = item.Movement?.NextStation?.StationName, item.Movement?.ToOther, item.Movement?.LatestStatus, QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}" // Generate QR String @@ -1065,6 +1083,16 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory _centralDbContext.ItemMovements.Update(updatedList); await _centralDbContext.SaveChangesAsync(); + var receiveItems = await _centralDbContext.Items.FindAsync(receiveMovement.ItemId); + + if (receiveItems != null) + { + receiveItems.ItemStatus = 3; + _centralDbContext.Items.Update(receiveItems); + + await _centralDbContext.SaveChangesAsync(); // Simpan perubahan + } + return Json(updatedList); } catch (Exception ex) @@ -1084,33 +1112,53 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory try { - var updatedList = await _centralDbContext.ItemMovements - .Where(r => r.Id == returnMovement.Id) - .FirstAsync(); - - updatedList.ItemId = updatedList.ItemId; - updatedList.ToStation = updatedList.ToStation; - updatedList.ToStore = updatedList.ToStore; - updatedList.ToUser = updatedList.ToUser; - updatedList.ToOther = updatedList.ToOther; - updatedList.sendDate = updatedList.sendDate; - updatedList.ToStation = updatedList.ToStation; - updatedList.Action = updatedList.Action; - updatedList.Quantity = updatedList.Quantity; - updatedList.Remark = updatedList.Remark; - updatedList.ConsignmentNote = updatedList.ConsignmentNote; - updatedList.Date = updatedList.Date; - updatedList.LastUser = updatedList.LastUser; - updatedList.LastStore = updatedList.ToStore; - - updatedList.LastStation = returnMovement.LastStation; - updatedList.LatestStatus = returnMovement.LatestStatus; - updatedList.receiveDate = returnMovement.receiveDate; - updatedList.MovementComplete = returnMovement.MovementComplete; - + // 1. Simpan returnMovement dalam database + _centralDbContext.ItemMovements.Add(returnMovement); await _centralDbContext.SaveChangesAsync(); - return Json(updatedList); + // 2. Cari item movement yang ada ItemId & MovementComplete = false + var updateItemIdMovement = await _centralDbContext.ItemMovements + .FirstOrDefaultAsync(m => m.ItemId == returnMovement.ItemId && m.MovementComplete == false); + + + // 3. Jika wujud, update MovementId + if (updateItemIdMovement != null) + { + var returnItems = await _centralDbContext.Items.FindAsync(updateItemIdMovement.ItemId); + + if (returnItems != null) + { + returnItems.MovementId = updateItemIdMovement.Id; + returnItems.ItemStatus = 2; + _centralDbContext.Items.Update(returnItems); + + await _centralDbContext.SaveChangesAsync(); // Simpan perubahan + } + } + + return Json(new + { + updateItemIdMovement.Id, + updateItemIdMovement.ItemId, + updateItemIdMovement.ToStation, + updateItemIdMovement.ToStore, + updateItemIdMovement.ToUser, + updateItemIdMovement.ToOther, + updateItemIdMovement.sendDate, + updateItemIdMovement.Action, + updateItemIdMovement.Quantity, + updateItemIdMovement.Remark, + updateItemIdMovement.ConsignmentNote, + updateItemIdMovement.Date, + updateItemIdMovement.LastUser, + updateItemIdMovement.LastStore, + updateItemIdMovement.LastStation, + updateItemIdMovement.LatestStatus, + updateItemIdMovement.receiveDate, + updateItemIdMovement.MovementComplete + }); + + } catch (Exception ex) { diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 6fbf781..c4acf0c 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -1,9 +1,19 @@ @* For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 *@ +@using Microsoft.AspNetCore.Identity +@inject SignInManager SignInManager +@inject UserManager UserManager +@{ + var user = await UserManager.GetUserAsync(User); + var roles = user != null ? await UserManager.GetRolesAsync(user) : new List(); + Console.WriteLine("User Roles: " + string.Join(", ", roles)); + var isNotTechnician = !roles.Any(r => r.Trim().Equals("Technician", StringComparison.OrdinalIgnoreCase)); + Console.WriteLine("Is NOT Technician: " + (isNotTechnician ? "True" : "False")); +} @@ -433,18 +443,18 @@ Inventory