using Azure.Core; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Mono.TextTemplating; using Newtonsoft.Json; using PSTW_CentralSystem.Areas.Inventory.Models; using PSTW_CentralSystem.DBContext; using PSTW_CentralSystem.Models; using System.ComponentModel.Design; using System.Data; using System.Diagnostics; using System.Reflection; using static System.Collections.Specialized.BitVector32; namespace PSTW_CentralSystem.Controllers.API.Inventory { [ApiController] [Route("[controller]")] public class InvMainAPI : Controller { private readonly ILogger _logger; private readonly CentralSystemContext _centralDbContext; private readonly UserManager _userManager; public InvMainAPI(ILogger logger, CentralSystemContext centralDbContext, UserManager userManager) { _logger = logger; _centralDbContext = centralDbContext; _userManager = userManager; } public class DepartmentCompany { public int DepartmentId { get; set; } public string? DepartmentName { get; set; } public int CompanyId { get; set; } public string? CompanyName { get; set; } public string? DepartmentCode { get; set; } } public async Task> GetDepartmentWithCompanyList() { var departmentList = await _centralDbContext.Departments.ToListAsync(); var companyList = await _centralDbContext.Companies.ToListAsync(); // Create a new list to store departments with their company name var departmentWithCompanyList = departmentList.Select(department => new DepartmentCompany { DepartmentId = department.DepartmentId, DepartmentName = department.DepartmentName, CompanyId = department.CompanyId, CompanyName = companyList.FirstOrDefault(company => company.CompanyId == department.CompanyId)?.CompanyName }).ToList(); // Return the constructed list as JSON return departmentWithCompanyList; } public async Task GetDepartmentWithCompany(int companyId, int departmentId) { var departmentList = await _centralDbContext.Departments.FirstOrDefaultAsync(d => d.DepartmentId == departmentId ); var companyList = await _centralDbContext.Companies.FirstOrDefaultAsync(c => c.CompanyId == companyId); // Create a new list to store departments with their company name var departmentWithCompany = new DepartmentCompany { DepartmentId = departmentList!.DepartmentId, DepartmentName = departmentList.DepartmentName, CompanyId = departmentList.CompanyId, CompanyName = companyList?.CompanyName, DepartmentCode = departmentList.DepartmentCode, }; // Return the constructed list as JSON return departmentWithCompany; } #region Manufacturer [HttpPost("ManufacturerList")] public async Task ManufacturerList() { var manifacturerList = await _centralDbContext.Manufacturers.ToListAsync(); return Json(manifacturerList); } [HttpPost("AddManufacturer")] public async Task AddManufacturer([FromBody] ManufacturerModel manufacturer) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { _centralDbContext.Manufacturers.Add(new ManufacturerModel { ManufacturerName = manufacturer.ManufacturerName, }); await _centralDbContext.SaveChangesAsync(); var updatedList = await _centralDbContext.Manufacturers.ToListAsync(); return Json(updatedList); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpDelete("DeleteManufacturer/{id}")] public async Task DeleteManufacturer(int id) { var manufacturer = await _centralDbContext.Manufacturers.FindAsync(id); if (manufacturer == null) { return NotFound(new { success = false, message = "Manufacturer not found" }); } _centralDbContext.Manufacturers.Remove(manufacturer); await _centralDbContext.SaveChangesAsync(); return Ok(new { success = true, message = "Manufacturer deleted successfully" }); } #endregion Manufacturer #region Product [HttpPost("ProductList")] public async Task ProductList() { var productList = await _centralDbContext.Products.Include("Manufacturer").ToListAsync(); return Json(productList); } [HttpPost("ProductListWithItem")] public async Task ProductListWithItem() { var productList = await _centralDbContext.Products .Include(p => p.Items) // Include related items .Include(p => p.Manufacturer) // Include related manufacturer .ToListAsync(); return Json(productList); } [HttpPost("AddProduct")] public async Task AddProduct([FromBody] ProductModel product) { if (!ModelState.IsValid) { return BadRequest(ModelState); } if (product == null) { return NotFound("Product is null"); } try { product.QuantityProduct = 0; var productImage = product.ImageProduct; // Save image to wwwroot/media/inventory/images | Images name is product.ModelNo | product.ImageProduct is in base64 string if (!string.IsNullOrEmpty(product.ImageProduct)) { var bytes = Convert.FromBase64String(product.ImageProduct); var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/images", product.ModelNo + ".jpg"); await System.IO.File.WriteAllBytesAsync(filePath, bytes); product.ImageProduct = "/media/inventory/images/" + product.ModelNo + ".jpg"; } _centralDbContext.Products.Add(product); await _centralDbContext.SaveChangesAsync(); var updatedList = await _centralDbContext.Products.Include("Manufacturer").Where(x => x.ManufacturerId == x.ManufacturerId).ToListAsync(); return Json(updatedList); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpDelete("DeleteProduct/{id}")] public async Task DeleteProduct(int id) { var Product = await _centralDbContext.Products.FindAsync(id); if (Product == null) { return NotFound(new { success = false, message = "Product not found" }); } _centralDbContext.Products.Remove(Product); await _centralDbContext.SaveChangesAsync(); return Ok(new { success = true, message = "Product deleted successfully" }); } #endregion Product #region Supplier [HttpPost("SupplierList")] public async Task SupplierList() { var supplierList = await _centralDbContext.Suppliers.ToListAsync(); return Json(supplierList); } [HttpPost("AddSupplier")] public async Task AddSupplier([FromBody] SupplierModel supplier) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { _centralDbContext.Suppliers.Add(supplier); await _centralDbContext.SaveChangesAsync(); var updatedList = await _centralDbContext.Suppliers.ToListAsync(); return Json(updatedList); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpDelete("DeleteSupplier/{id}")] public async Task DeleteSupplier(int id) { var supplier = await _centralDbContext.Suppliers.FindAsync(id); if (supplier == null) { return NotFound(new { success = false, message = "Supplier not found" }); } _centralDbContext.Suppliers.Remove(supplier); await _centralDbContext.SaveChangesAsync(); return Ok(new { success = true, message = "Supplier deleted successfully" }); } #endregion Supplier #region Item [HttpPost("ItemList")] public async Task ItemList() { try { var user = await _userManager.GetUserAsync(User); if (user == null) { return BadRequest("User not found"); } else { user.departmentId = user.departmentId != null ? user.departmentId : 0; } var userRole = await _userManager.GetRolesAsync(user); var isAdmin = userRole.Contains("SystemAdmin") || userRole.Contains("SuperAdmin") || userRole.Contains("Finance"); List itemList = new List(); // Get the item list if (isAdmin) { itemList = await _centralDbContext.Items .AsNoTracking() .Include("CreatedBy") .Include("Department") .Include("Product") .Include(i => i.Movement) .ThenInclude(m => m!.FromStore) .Include(i => i.Movement) .ThenInclude(m => m!.FromStation) .Include(i => i.Movement) .ThenInclude(m => m!.FromUser) .ToListAsync(); } else { itemList = await _centralDbContext.Items .AsNoTracking() .Include("CreatedBy") .Include("Department") .Include("Product") .Include(i => i.Movement) .ThenInclude(m => m!.FromStore) .Include(i => i.Movement) .ThenInclude(m => m!.FromStation) .Include(i => i.Movement) .ThenInclude(m => m!.FromUser) .Where(i => i.DepartmentId == user.departmentId) .ToListAsync(); } // Get the departments list (DepartmentId references Departments) var departments = await _centralDbContext.Departments.ToListAsync(); // Now join items with users and departments manually var itemListWithDetails = itemList.Select(item => new { item.ItemID, item.UniqueID, item.CompanyId, item.DepartmentId, item.ProductId, item.SerialNumber, item.Quantity, item.Supplier, PurchaseDate = item.PurchaseDate.ToString("dd/MM/yyyy"), item.PONo, item.Currency, item.DefaultPrice, item.CurrencyRate, item.ConvertPrice, item.DODate, item.Warranty, item.PartNumber, EndWDate = item.EndWDate.ToString("dd/MM/yyyy"), InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"), item.Department?.DepartmentName, CreatedBy=item.CreatedBy!.UserName, item.Product!.ProductName, 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, QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}" // Generate QR String }).ToList(); return Json(itemListWithDetails); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpPost("GenerateItemQr/{id}")] public IActionResult GenerateItemQr(string id) { // Retrieve the request's host and scheme var request = HttpContext.Request; string domain = $"{request.Scheme}://{request.Host.Value}"; // Append the QR path and item ID string QRString = $"{domain}/Inventory/ItemInformation/{id}"; return Json(QRString); } [HttpPost("AddItem")] public async Task AddItem([FromBody] ItemModel item) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { var product = await _centralDbContext.Products.FirstOrDefaultAsync(p => p.ProductId == item.ProductId) ?? throw new Exception("Product not found"); var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == item.CreatedByUserId) ?? new InventoryMasterModel{ UserId = item.CreatedByUserId }; var addToProduct = item.Quantity; product.QuantityProduct += addToProduct; if (product.Category == "Disposable") { item.SerialNumber = null; } _centralDbContext.Items.Add(item); _centralDbContext.Products.Update(product); await _centralDbContext.SaveChangesAsync(); // This generates the auto-incremented ItemID ItemMovementModel itemMovement = new ItemMovementModel { ItemId = item.ItemID, ToUser = inventoryMaster.UserId, ToStore = inventoryMaster.StoreId, LastStore = inventoryMaster.StoreId, LastUser = inventoryMaster.UserId, LatestStatus = "Ready To Deploy", Quantity = item.Quantity, Action= "Register", Date = DateTime.Now, MovementComplete = true, }; _centralDbContext.ItemMovements.Add(itemMovement); await _centralDbContext.SaveChangesAsync(); // Fetch the generated ItemID var savedItem = await _centralDbContext.Items.FirstOrDefaultAsync(i => i.ItemID == item.ItemID); // Fetch the generated itemMovement var savedMovement = await _centralDbContext.ItemMovements.FirstOrDefaultAsync(i => i.Id == itemMovement.Id); if (savedItem != null) { var companyDepartment = await GetDepartmentWithCompany(item.CompanyId, item.DepartmentId); var itemProduct = _centralDbContext.Products.Where(p => p.ProductId == item.ProductId).FirstOrDefault(); string? companyInitial = companyDepartment!.CompanyName?.ToString().Substring(0, 1).ToUpper(); string? departmentInitial = companyDepartment!.DepartmentName?.ToString().Substring(0, 1).ToUpper(); string? deptCode = companyDepartment!.DepartmentCode?.ToString(); char? initialCategory = itemProduct!.Category.ToString().Substring(0, 1).ToUpper().FirstOrDefault(); string? productId = itemProduct!.ProductId.ToString("D3"); string? itemId = item.ItemID.ToString("D5"); var uniqueId = $"{deptCode}{initialCategory}{productId}{itemId}".ToUpper(); savedItem.UniqueID = uniqueId; savedItem.MovementId = savedMovement?.Id; _centralDbContext.Items.Update(savedItem); await _centralDbContext.SaveChangesAsync(); } var updatedItem = new { savedItem!.ItemID, savedItem.UniqueID, savedItem.CompanyId, savedItem.DepartmentId, savedItem.ProductId, savedItem.SerialNumber, savedItem.Quantity, savedItem.Supplier, savedItem.PurchaseDate, savedItem.PONo, savedItem.Currency, savedItem.DefaultPrice, savedItem.CurrencyRate, savedItem.ConvertPrice, savedItem.DODate, savedItem.Warranty, savedItem.EndWDate, savedItem.InvoiceDate, savedItem.PartNumber, }; return Json(updatedItem); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpDelete("DeleteItem/{id}")] public async Task DeleteItem(int id) { var item = await _centralDbContext.Items.FindAsync(id); if (item == null) { return NotFound(new { success = false, message = "Item not found" }); } _centralDbContext.Items.Remove(item); await _centralDbContext.SaveChangesAsync(); return Ok(new { success = true, message = "Item deleted successfully" }); } [HttpPost("GetItem/{id}")] // Endpoint to retrieve an item by its ID public async Task GetItem(string id) { var item = await _centralDbContext.Items .Include("CreatedBy") .Include("Department") .Include("Product") .Include("Movement") .Include(i => i.Movement) .ThenInclude(m => m!.FromStore) .Include(i => i.Movement) .ThenInclude(m => m!.FromStation) .Include(i => i.Movement) .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" }); } var singleItem = new { item.Movement?.Id, item.ItemID, item.MovementId, item.UniqueID, item.CompanyId, item.DepartmentId, item.ProductId, item.SerialNumber, item.Quantity, item.Supplier, PurchaseDate = item.PurchaseDate.ToString("dd/MM/yyyy"), item.PONo, item.Currency, item.DefaultPrice, item.CurrencyRate, item.ConvertPrice, item.DODate, item.Warranty, item.PartNumber, EndWDate = item.EndWDate.ToString("dd/MM/yyyy"), InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"), item.Department?.DepartmentName, item.CreatedBy!.UserName, item.Product!.ProductName, item.Product!.ProductShortName, item.Product!.ImageProduct, CurrentUser = item.Movement?.FromUser?.UserName, CurrentUserFullName = item.Movement?.FromUser?.FullName, 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, item.Movement?.LastUser, item.Movement?.MovementComplete, remark = item.Movement?.Remark, QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}" // Generate QR String }; return Json(singleItem); } #endregion Item #region ItemMovement [HttpPost("ItemMovementList")] public async Task ItemMovementList() { //var itemMovementList = await _centralDbContext.ItemMovements.Include(i => i.NextUser).Include(i => i.Item).ThenInclude(i => i.Product).ToListAsync(); var itemMovementList = await _centralDbContext.ItemMovements .Include(i => i.Item) .ThenInclude(i => i.Product) .Include(i => i.FromStore) .Include(i => i.FromStation) .Include(i => i.FromUser) .Include(i => i.NextStore) .Include(i => i.NextStation) .Include(i => i.NextUser) .Include(i => i.NextUser) .ToListAsync(); //var itemList = await _centralDbContext.Items.ToListAsync(); int itemrow = 0; var itemMovementListWithQR = itemMovementList.Select(item => new { id = itemrow++, item, // Includes all properties of the original item QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.ItemId}", // Generate QR String ProductName = item.Item?.Product?.ProductName, toUserName = item.NextUser?.FullName, lastUserName = item.FromUser?.FullName }).ToList(); //Console.WriteLine(Json(itemMovementList)); //return Json(itemMovementList); //return Json(itemMovementListWithQR); return Json(itemMovementList.Select(i => new { i.Id, i.ItemId, i.ToStation, i.ToStore, i.ToUser, UniqueID = i.Item?.UniqueID, ProductName = i.Item?.Product?.ProductName, ProductCategory = i.Item?.Product?.Category, LastUserName = i.FromUser?.FullName, LastStoreName = i.FromStore?.StoreName, LastStationName = i.FromStation?.StationName, ToUserName = i.NextUser?.FullName, ToStoreName = i.NextStore?.StoreName, ToStationName = i.NextStation?.StationName, i.ToOther, i.sendDate, i.Action, i.Quantity, i.Remark, i.ConsignmentNote, i.Date, i.LastUser, i.LastStore, i.LastStation, i.LatestStatus, i.receiveDate, i.MovementComplete })); //return Json(itemMovementList.Select(item => new //{ // id = itemrow++, // item, // QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.ItemId}", // Generate QR String // ProductName = item.Item?.Product?.ProductName, // toUserName = item.NextUser?.FullName, // lastUserName = item.FromUser?.FullName //})); } [HttpPost("AddItemMovement")] public async Task AddItemMovement([FromBody] ItemMovementModel itemmovement) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { //if (itemmovement.ToUser == null) //{ // throw new Exception("itemmovement.ToUser is null"); //} //var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == itemmovement.ToUser) ?? new InventoryMasterModel { UserId = itemmovement.ToUser }; var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == itemmovement.ToUser); if (inventoryMaster != null) { itemmovement.ToStore = inventoryMaster.StoreId; } if (!string.IsNullOrEmpty(itemmovement.ConsignmentNote)) { var bytes = Convert.FromBase64String(itemmovement.ConsignmentNote); string filePath = ""; string uniqueName = $"{itemmovement.ItemId}_{Guid.NewGuid()}"; if (IsImage(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", uniqueName + itemmovement.ItemId + "_Request.jpg"); itemmovement.ConsignmentNote = "/media/inventory/itemmovement/" + uniqueName + itemmovement.ItemId + "_Request.jpg"; } else if (IsPdf(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", uniqueName + itemmovement.ItemId + "_Request.pdf"); itemmovement.ConsignmentNote = "/media/inventory/itemmovement/" + uniqueName + itemmovement.ItemId + "_Request.pdf"; } else { return BadRequest("Unsupported file format."); } await System.IO.File.WriteAllBytesAsync(filePath, bytes); } _centralDbContext.ItemMovements.Add(itemmovement); await _centralDbContext.SaveChangesAsync(); // This generates the auto-incremented ItemID var updateItem = await _centralDbContext.Items.FindAsync(itemmovement.ItemId); //only access after it have its own itemmovent if (updateItem != null) { if (itemmovement.ToOther == "On Delivery") { updateItem.ItemStatus = 2; } else if (itemmovement.ToOther == "Repair" || itemmovement.ToOther == "Calibration") { updateItem.ItemStatus = 4; } else if (itemmovement.ToOther == "Faulty") { updateItem.ItemStatus = 8; } //Console.WriteLine("updateItem.MovementId" + updateItem.MovementId); //Console.WriteLine("itemmovement.Id" + itemmovement.Id); updateItem.MovementId = itemmovement.Id; _centralDbContext.Items.Update(updateItem); await _centralDbContext.SaveChangesAsync(); // save changes for table item - movementid } return Json(new { itemmovement.Id, itemmovement.ItemId, itemmovement.ToStation, itemmovement.ToStore, itemmovement.ToUser, itemmovement.ToOther, itemmovement.sendDate, itemmovement.Action, itemmovement.Quantity, itemmovement.Remark, itemmovement.ConsignmentNote, itemmovement.Date, itemmovement.LastUser, itemmovement.LastStore, itemmovement.LastStation, itemmovement.LatestStatus, itemmovement.receiveDate, itemmovement.MovementComplete }); //return Json(itemmovement); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpPost("UpdateItemMovementMaster")] public async Task UpdateItemMovementMaster([FromBody] ItemMovementModel receiveMovement) { try { var updatedList = await _centralDbContext.ItemMovements.FindAsync(receiveMovement.Id); if (updatedList == null) { return NotFound("Item movement record not found."); } updatedList.LatestStatus = receiveMovement.LatestStatus; updatedList.receiveDate = receiveMovement.receiveDate; updatedList.Remark = receiveMovement.Remark; updatedList.MovementComplete = true; _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) { return BadRequest(ex.Message); } } #endregion ItemMovement #region ItemMovementUser [HttpPost("ItemMovementUser")] public async Task ItemMovementUser() { try { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound("Item movement record not found."); } var itemMovementUser = await _centralDbContext.ItemMovements .Include(i => i.Item) .ThenInclude(i => i.Product) .Include(i => i.FromStore) .Include(i => i.FromStation) .Include(i => i.FromUser) .Include(i => i.NextStore) .Include(i => i.NextStation) .Include(i => i.NextUser) .Where(i => i.ToUser == user.Id || i.LastUser == user.Id) .ToListAsync(); return Json(itemMovementUser.Select(i => new { i.Id, i.ItemId, i.ToStation, i.ToStore, i.ToUser, UniqueID = i.Item?.UniqueID, ProductName = i.Item?.Product?.ProductName, LastUserName = i.FromUser?.FullName, LastStoreName = i.FromStore?.StoreName, LastStationName = i.FromStation?.StationName, ToUserName = i.NextUser?.FullName, ToStoreName = i.NextStore?.StoreName, ToStationName = i.NextStation?.StationName, i.ToOther, i.sendDate, i.Action, i.Quantity, i.Remark, i.ConsignmentNote, i.Date, i.LastUser, i.LastStore, i.LastStation, i.LatestStatus, i.receiveDate, i.MovementComplete })); } catch (Exception ex) { return BadRequest(ex.Message); } } #endregion #region ItemRequestUser [HttpPost("AddRequest")] public async Task AddRequest([FromBody] RequestModel request) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { if (!string.IsNullOrEmpty(request.Document)) { var findUniqueCode = _centralDbContext.Products.FirstOrDefault(r => r.ProductId == request.ProductId); var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == request.UserId); var bytes = Convert.FromBase64String(request.Document); string filePath = ""; var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray()); if (IsImage(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.jpg"); request.Document = "/media/inventory/request/" + findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.jpg"; } else if (IsPdf(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "_Request.pdf"); request.Document = "/media/inventory/request/" + findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.pdf"; } else { return BadRequest("Unsupported file format."); } await System.IO.File.WriteAllBytesAsync(filePath, bytes); } _centralDbContext.Requests.Add(request); await _centralDbContext.SaveChangesAsync(); var updatedList = await _centralDbContext.Requests .Where(r => r.UserId == request.UserId) .ToListAsync(); return Json(updatedList); } catch (Exception ex) { return BadRequest(ex.Message); } } private bool IsImage(byte[] bytes) { // JPEG file signature: FF D8 FF if (bytes.Length > 2 && bytes[0] == 0xFF && bytes[1] == 0xD8 && bytes[2] == 0xFF) return true; // PNG file signature: 89 50 4E 47 0D 0A 1A 0A if (bytes.Length > 7 && bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4E && bytes[3] == 0x47) return true; // GIF file signature: GIF87a or GIF89a if (bytes.Length > 5 && bytes[0] == 0x47 && bytes[1] == 0x49 && bytes[2] == 0x46) return true; return false; } private bool IsPdf(byte[] bytes) { // PDF file signature: 25 50 44 46 (ASCII for "%PDF") return bytes.Length > 3 && bytes[0] == 0x25 && bytes[1] == 0x50 && bytes[2] == 0x44 && bytes[3] == 0x46; } [HttpGet("ItemRequestListEachUser/{userId}")] public async Task ItemRequestListEachUser(int userId) { var requests = await _centralDbContext.Requests .Include(i => i.Product).Include(i => i.Station).Where(r => r.UserId == userId).ToListAsync(); return Json(requests.Select(i => new { i.requestId, i.ProductId, productName = i.Product?.ProductName, i.UserId, i.status, i.StationId, stationName = i.Station?.StationName, i.RequestQuantity, i.requestDate, i.ProductCategory, i.Document, i.approvalDate, i.remarkMasterInv, i.remarkUser, })); } [HttpDelete("DeleteRequest/{requestId}")] public async Task DeleteRequest(int requestId) { var request = await _centralDbContext.Requests.FindAsync(requestId); if (request == null) { return NotFound(new { success = false, message = "Request not found" }); } _centralDbContext.Requests.Remove(request); await _centralDbContext.SaveChangesAsync(); return Ok(new { success = true, message = "Request deleted successfully" }); } #endregion #region ItemRequestAdmin [HttpGet("ItemRequestList")] public async Task ItemRequestList() { var itemRequestList = await _centralDbContext.Requests.Include(i => i.Product).Include(i => i.User).ToListAsync(); return Json(itemRequestList.Select(i => new { i.requestId, productName = i.Product?.ProductName, i.ProductId, userName = i.User?.FullName, i.status, i.StationId, i.RequestQuantity, i.requestDate, i.ProductCategory, i.Document, i.approvalDate, i.remarkMasterInv, i.remarkUser, })); } [HttpPost("ApproveRequest/{id}")] public async Task ApproveRequest(int id, [FromBody] RequestModel request) { var Request = await _centralDbContext.Requests.FindAsync(id); if (Request == null) { return NotFound(new { success = false, message = "Request not found" }); } Request.status = "Approved"; Request.remarkMasterInv = request.remarkMasterInv; Request.approvalDate = DateTime.UtcNow; _centralDbContext.SaveChanges(); return Ok(new { success = true, message = "Request Approved Successfully", data = Request }); } [HttpPost("RejectRequest/{id}")] public async Task RejectRequest(int id, [FromBody] RequestModel request) { var Request = await _centralDbContext.Requests.FindAsync(id); if (Request == null) { return NotFound(new { success = false, message = "Request not found" }); } Request.status = "Rejected"; Request.remarkMasterInv = request.remarkMasterInv; Request.approvalDate = DateTime.UtcNow; _centralDbContext.SaveChanges(); return Ok(new { success = true, message="Request Rejected Successfully", data=Request }); } #endregion ItemRequestAdmin #region ItemReport [HttpPost("GetInventoryReport/{deptId}")] public async Task GetInventoryReport(int deptId) { try{ var user = await _userManager.GetUserAsync(User); var userRole = await _userManager.GetRolesAsync(user ?? new UserModel()); List items = new List(); if (userRole.Contains("SuperAdmin") && userRole.Contains("SystemAdmin")) { items = await _centralDbContext.Items .Include("CreatedBy") .Include("Department") .Include("Product") .ToListAsync(); } else { items = await _centralDbContext.Items .Include("CreatedBy") .Include("Department") .Include("Product") .Where(i => i.DepartmentId == deptId) .ToListAsync(); } var itemListWithDetails = items.Where(i => i.Quantity > 0).Select(item => new { item.ItemID, item.UniqueID, item.CompanyId, item.DepartmentId, item.ProductId, item.SerialNumber, item.Quantity, item.Supplier, PurchaseDate = item.PurchaseDate.ToString("dd/MM/yyyy"), item.PONo, item.Currency, item.DefaultPrice, item.CurrencyRate, item.ConvertPrice, item.DODate, item.Warranty, EndWDate = item.EndWDate.ToString("dd/MM/yyyy"), InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"), item.Department?.DepartmentName, CreatedBy = item.CreatedBy!.UserName, item.Product!.ProductName, item.Product!.ProductShortName, item.Product!.Category, //CurrentUser = item.Movement?.FromUser?.UserName, CurrentUser = item.Movement?.FromUser?.UserName, CurrentStore = item.Movement?.FromStore?.StoreName, CurrentStation = item.Movement?.FromStation?.StationName, QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}" // Generate QR String }).ToList(); int itemCountRegistered = items.Count; int itemCountStillInStock = items.Where(i => i.Quantity > 0).Count(); var itemsMovementsThisMonth = _centralDbContext.ItemMovements .Where(i => i.Date.Month == DateTime.Now.Month); int itemCountRegisteredThisMonth = itemsMovementsThisMonth.Count(i => i.Action == "Register"); int itemCountStockOutThisMonth = itemsMovementsThisMonth.Count(i => i.Action == "Stock Out"); var lastMonth = DateTime.Now.AddMonths(-1).Month; var itemsMovementsLastMonth = _centralDbContext.ItemMovements .Where(i => i.Date.Month == lastMonth); int itemCountRegisteredLastMonth = itemsMovementsLastMonth.Count(i => i.Action == "Register"); int itemCountStockOutLastMonth = itemsMovementsLastMonth.Count(i => i.Action == "Stock Out"); var report = new { itemListWithDetails, itemCountRegistered, itemCountStillInStock, itemCountRegisteredThisMonth, itemCountStockOutThisMonth, itemCountRegisteredLastMonth, itemCountStockOutLastMonth }; return Json(report); } catch (Exception ex) { return BadRequest(ex.Message); } } #endregion #region Station [HttpPost("StationList")] public async Task StationList() { var stationList = await _centralDbContext.Stations.Include(i => i.StationPic).ToListAsync(); return Json(stationList); } [HttpPost("AddStation")] public async Task AddStation([FromBody] StationModel station) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { _centralDbContext.Stations.Add(station); await _centralDbContext.SaveChangesAsync(); var updatedList = await _centralDbContext.Stations.ToListAsync(); return Json(updatedList); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpDelete("DeleteStation/{id}")] public async Task DeleteStation(int id) { var station = await _centralDbContext.Stations.FindAsync(id); if (station == null) { return NotFound(new { success = false, message = "Station not found" }); } _centralDbContext.Stations.Remove(station); await _centralDbContext.SaveChangesAsync(); return Ok(new { success = true, message = "Station deleted successfully" }); } #endregion Station #region Store [HttpPost("StoreList")] public async Task StoreList() { var storeList = await _centralDbContext.Stores.ToListAsync(); return Json(storeList); } [HttpPost("StoreSpecificMaster/{storeId}")] public async Task StoreSpecificMaster(int storeId) { var storeList = await _centralDbContext.InventoryMasters.Where(i => i.StoreId == storeId).FirstOrDefaultAsync(); return Json(storeList); } #endregion Store #region AllUser [HttpPost("UserList")] public async Task UserList() { var userList = await _centralDbContext.Users.ToListAsync(); return Json(userList); } #endregion AllUser #region ScannerUser [HttpPost("UpdateItemMovementUser")] public async Task UpdateItemMovementUser([FromBody] ItemMovementModel receiveMovement) { try { var updatedList = await _centralDbContext.ItemMovements.FindAsync(receiveMovement.Id); if (updatedList == null) { return NotFound("Item movement record not found."); } updatedList.LatestStatus = receiveMovement.LatestStatus; updatedList.receiveDate = receiveMovement.receiveDate; updatedList.MovementComplete = receiveMovement.MovementComplete; _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(); return Json(updatedList); } catch (Exception ex) { return BadRequest(ex.Message); } } [HttpPost("ReturnItemMovementUser")] public async Task ReturnItemMovementUser([FromBody] ItemMovementModel returnMovement) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { if (!string.IsNullOrEmpty(returnMovement.ConsignmentNote)) { var bytes = Convert.FromBase64String(returnMovement.ConsignmentNote); string filePath = ""; string uniqueName = $"{returnMovement.Id}_{Guid.NewGuid()}"; if (IsImage(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", uniqueName + returnMovement.ItemId + "_Request.jpg"); returnMovement.ConsignmentNote = "/media/inventory/request/" + uniqueName + returnMovement.ItemId + "_Request.jpg"; } else if (IsPdf(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", uniqueName + returnMovement.ItemId + "_Request.pdf"); returnMovement.ConsignmentNote = "/media/inventory/request/" + uniqueName + returnMovement.ItemId + "_Request.pdf"; } else { return BadRequest("Unsupported file format."); } await System.IO.File.WriteAllBytesAsync(filePath, bytes); } // 1. Simpan returnMovement dalam database _centralDbContext.ItemMovements.Add(returnMovement); await _centralDbContext.SaveChangesAsync(); // 2. Cari item movement yang ada ItemId & MovementComplete = false var updateItemIdMovement = await _centralDbContext.ItemMovements .FirstOrDefaultAsync(m => m.Id == returnMovement.Id && 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); } } //4. Update Assign Row (Untuk ToStore = Ada value , kepada , ToStore = null) var updateToStoreAssignStation = await _centralDbContext.ItemMovements.Where(i => i.Action == "Assign").ToListAsync(); foreach (var item in updateToStoreAssignStation) { item.ToStore = null; // Set ToStore to null for each matching row _centralDbContext.ItemMovements.Update(item); } 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) { return BadRequest(ex.Message); } } [HttpPost("StationItemMovementUser")] public async Task StationItemMovementUser([FromBody] ItemMovementModel stationMovement) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { if (!string.IsNullOrEmpty(stationMovement.ConsignmentNote)) { var bytes = Convert.FromBase64String(stationMovement.ConsignmentNote); string filePath = ""; string uniqueName = $"{stationMovement.Id}_{Guid.NewGuid()}"; if (IsImage(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", uniqueName + stationMovement.ItemId + "_Request.jpg"); stationMovement.ConsignmentNote = "/media/inventory/request/" + uniqueName + stationMovement.ItemId + "_Request.jpg"; } else if (IsPdf(bytes)) { filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", uniqueName + stationMovement.ItemId + "_Request.pdf"); stationMovement.ConsignmentNote = "/media/inventory/request/" + uniqueName + stationMovement.ItemId + "_Request.pdf"; } else { return BadRequest("Unsupported file format."); } await System.IO.File.WriteAllBytesAsync(filePath, bytes); } // 1. Simpan returnMovement dalam database _centralDbContext.ItemMovements.Add(stationMovement); await _centralDbContext.SaveChangesAsync(); // 2. Cari item movement yang ada ItemId & MovementComplete = false var updateItemIdMovement = await _centralDbContext.ItemMovements.Include(i => i.Item) .FirstOrDefaultAsync(m => m.Id == stationMovement.Id); // 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 = 3; _centralDbContext.Items.Update(returnItems); // Simpan perubahan await _centralDbContext.SaveChangesAsync(); } } return Json(new { updateItemIdMovement.Id, updateItemIdMovement.ItemId, updateItemIdMovement.Item?.UniqueID, 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) { return BadRequest(ex.Message); } } #endregion } }