diff --git a/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml b/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml index b090376..77e7f63 100644 --- a/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml @@ -407,24 +407,24 @@ // Generate QR codes after rows are rendered const api = this.api(); api.rows().every(function () { - const data = this.data(); // Row data - const containerId = `qr${data.id}`; - + const data = this.data(); + const containerId = `qr${data.id}`; //containerid is by increments from API const container = $(`#${containerId}`); + container.empty(); container.append(`${data.item.itemId}`); + + if (container.length) { + - // console.log(container[0]); - if (container) { - // Generate QR code only if not already generated - new QRCode(container[0], { - text: data.qrString, - width: 100, - height: 100, - colorDark: "#000000", - colorLight: "#ffffff", - correctLevel: QRCode.CorrectLevel.M - }); + new QRCode(container[0], { + text: data.qrString, + width: 100, + height: 100, + colorDark: "#000000", + colorLight: "#ffffff", + correctLevel: QRCode.CorrectLevel.M, + }); } // container.on('click', function() { // window.open(data.qrString, '_blank'); diff --git a/Areas/Inventory/Views/InventoryMaster/ItemRequestMaster.cshtml b/Areas/Inventory/Views/InventoryMaster/ItemRequestMaster.cshtml index 825a62b..e9a53eb 100644 --- a/Areas/Inventory/Views/InventoryMaster/ItemRequestMaster.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/ItemRequestMaster.cshtml @@ -20,7 +20,7 @@
-

Item Request

+

Complete Request

@* *@
@@ -240,6 +240,31 @@ { "title": "Document/Picture", "data": "document", + "render": function (data, type, full, meta) { + if (!data) { + return "No Document"; + } + + // Check if the document is an image based on file extension + var isImage = /\.(jpeg|jpg|png|gif)$/i.test(data); + var isPdf = /\.pdf$/i.test(data); + + if (isImage) { + return ` + Image + `; + } + else if (isPdf) { + return ` + PDF Document +
View PDF +
`; + } else { + return `Download File`; + } + }, }, { "title": "User Remark", @@ -331,6 +356,31 @@ { "title": "Document/Picture", "data": "document", + "render": function (data, type, full, meta) { + if (!data) { + return "No Document"; + } + + // Check if the document is an image based on file extension + var isImage = /\.(jpeg|jpg|png|gif)$/i.test(data); + var isPdf = /\.pdf$/i.test(data); + + if (isImage) { + return ` + Image + `; + } + else if (isPdf) { + return ` + PDF Document +
View PDF +
`; + } else { + return `Download File`; + } + }, }, { "title": "User Remark", @@ -361,7 +411,6 @@ // data-remark="${row.remark || ''}"> // Reject // `; - // }, // "className": "align-middle", // }, diff --git a/Areas/Inventory/Views/InventoryMaster/QrMaster.cshtml b/Areas/Inventory/Views/InventoryMaster/QrMaster.cshtml index ea72ea8..3914b15 100644 --- a/Areas/Inventory/Views/InventoryMaster/QrMaster.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/QrMaster.cshtml @@ -20,16 +20,8 @@
- @* *@
- @*
-
- Loading... -
-
*@ - @*
*@ -

QR & Barcode Scanner

@@ -117,195 +109,204 @@
- +
@*Right Side*@ -
-
-
-
-

Add Item Movement

-
+
+
+
+
+

Add Item Movement

+
-
- -
- - -
- -
-
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- - @* Submit and Reset Buttons *@ -
-
- - -
-
-
- -
- -
-
-
-
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- - @* Submit and Reset Buttons *@ -
-
- - -
-
-
-
-
- -
-
-
-
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- -
- -
-
- - -
- - @* Submit and Reset Buttons *@ -
-
- - -
-
-
-
-
- - -
-
+
- - -
@@ -341,10 +342,15 @@ debounceTimeout: null, userlist: null, storelist: null, + supplierlist: null, selectedUser: "", selectedStore: "", selectedAction: "", - + assigndate: null, + selectedSupplier: "", + selectedOther: "", + remark: "", + document: null, companies: [ { companyId: 1, @@ -358,66 +364,12 @@ }, ], company: "", - // Dept: null, - // teamTypes: ["Continuous", "Manual"], - // teamType: "", - // productName: null, - // imageProduct: null, - // productCategory: null, - // serialNumber: "", - // quantity: 1, - // supplierName: null, - // purchaseDate: null, - // PO: null, - // currency: "MYR", - // DefaultPrice: 0.01, - // currencyRate: 1, - // convertPrice: 0.01, - // DONo:null, - // DODate: null, - // warranty: 0, - // EndWDate: null, - // invoiceNo: null, - // invoiceDate: null,re - // partNumber: null, - // products: [], - // depts: [], - // suppliers: [ - // { - // supplierId: 1, - // supplierName: "Pang", - // }, - // { - // supplierId: 2, - // supplierName: "Ms Kim", - // }, - // ], - // isModalOpen: false, - // selectedProduct: "", - // selectedSupplier: "", - // selectedCompany: "", - // selectedDepartment: "", - // selectedTeamType: "", - // currencies: {}, - // showItemModal: false, - // loading: false, - // thisQRInfo: { - // uniqueID: null, - // departmentName: null, - // serialNumber: null, - // endWDate: null, - // }, - // items: [], currentUser: null, currentUserCompanyDept: null, } }, mounted() { this.fetchUser(); - this.fetchItems(); - this.fetchCurrencyData(); - this.fetchCompanies(); - this.fetchProducts(); this.fetchSuppliers(); this.startScanner(); this.fetchUsers(); @@ -445,35 +397,58 @@ }, }, methods: { + handleFileUpload(event) { + const file = event.target.files[0]; + + if (file) { + const reader = new FileReader(); + reader.onload = (e) => { + this.document = e.target.result.split(',')[1]; // Get Base64 string (remove metadata) + }; + reader.readAsDataURL(file); + } else { + this.document = null; + } + }, async addItemMovement() { + if (this.showProduct.category == "Disposable") { this.serialNumber = ""; } + + const now = new Date(); const formData = { - toUser: this.selectedUser, - toStore: this.selectedStore, - Remark: this.remark, + ...(this.selectedAction === 'user' ? { toUser: this.currentUser.id, toOther: 'On Delivery', SendDate: this.assigndate, lastUser: this.selectedUser, } : {}), + ...(this.selectedAction === 'store' ? { toUser: this.currentUser.id, toOther: 'On Delivery', SendDate: this.assigndate, lastUser: this.selectedStore} : {}), + ...(this.selectedAction === 'supplier' ? { toUser: this.currentUser.id, toOther: this.selectedOther, SendDate: this.assigndate, Remark: this.remark + '. Item sent to ' + this.selectedSupplier + ' for ' + this.selectedOther,lastUser: this.currentUser.id, } : {}), + ...(this.selectedAction === 'faulty' ? { toUser: this.currentUser.id,toOther: 'Faulty', Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(), Remark: this.remark, ConsignmentNote: this.document } : {}), + + ItemId: this.thisItem.itemID, + Action: 'Stock Out', + Quantity: 1, + MovementComplete: false, + }; try { // Additional specific checks - if (this.showSerialNumber) { - this.quantity = 0; - if (this.serialNumber === null || this.serialNumber === '') { - alert('Serial Number Error', 'Serial Number must be filled when selecting Item or Part.', 'warning'); - return; - } - } - else { - this.serialNumber = null; - if (this.quantity === 0 || this.quantity === null || this.quantity === '') { - alert('quantity Error', 'Quantity is required when selecting Disposable.', 'warning'); - return; - } - } + // if (this.showSerialNumber) { + // this.quantity = 0; + // if (this.serialNumber === null || this.serialNumber === '') { + // alert('Serial Number Error', 'Serial Number must be filled when selecting Item or Part.', 'warning'); + // return; + // } + // } + // else { + // this.serialNumber = null; + // if (this.quantity === 0 || this.quantity === null || this.quantity === '') { + // alert('quantity Error', 'Quantity is required when selecting Disposable.', 'warning'); + // return; + // } + // } // Proceed to send the data to the API const response = await fetch('/InvMainAPI/AddItemMovement', { @@ -488,12 +463,12 @@ // If the form submission was successful, display a success message alert('Success!', 'Item form has been successfully submitted.', 'success'); const updatedItem = await response.json(); - this.items.push(updatedItem); - - this.fetchItem(); + // this.items.push(updatedItem); // Reset the form this.resetForm(); + // window.location.href = '/Inventory/InventoryMaster/ItemMovement'; + } else { throw new Error('Failed to submit form.'); } @@ -547,6 +522,7 @@ ); if (response.ok) { this.thisItem = await response.json(); + } else { console.error('Failed to fetch item information'); @@ -556,300 +532,6 @@ console.error('Error fetching item information:', error); } }, - async addItem() { - - if (this.showProduct.category == "Disposable") { - this.serialNumber = ""; - } - const formData = { - CompanyId: this.selectedCompany, - DepartmentId: this.selectedDepartment, - ProductId: this.selectedProduct, - SerialNumber: this.serialNumber, - Quantity: this.quantity, - Supplier: this.selectedSupplier, - PurchaseDate: this.purchaseDate, - PONo: this.PO, - Currency: this.currency, - DefaultPrice: this.DefaultPrice, - CurrencyRate: this.currencyRate, - ConvertPrice: this.convertPrice, - DODate: this.DODate, - Warranty: this.warranty, - EndWDate: this.EndWDate, - InvoiceDate: this.invoiceDate, - CreatedByUserId: this.currentUser.id, - TeamType: this.selectedTeamType, - PartNumber: this.partNumber, - }; - - try { - - // Additional specific checks - if (this.showSerialNumber) { - this.quantity = 0; - if (this.serialNumber === null || this.serialNumber === '') { - alert('Serial Number Error', 'Serial Number must be filled when selecting Item or Part.', 'warning'); - return; - } - } - else { - this.serialNumber = null; - if (this.quantity === 0 || this.quantity === null || this.quantity === '') { - alert('quantity Error', 'Quantity is required when selecting Disposable.', 'warning'); - return; - } - } - - // Proceed to send the data to the API - const response = await fetch('/InvMainAPI/AddItem', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - // 'Authorization': `Bearer ${this.token}` - }, - body: JSON.stringify(formData) - }); - if (response.ok) { - // If the form submission was successful, display a success message - alert('Success!', 'Item form has been successfully submitted.', 'success'); - const updatedItem = await response.json(); - this.items.push(updatedItem); - - this.fetchItems(); - - // Reset the form - this.resetForm(); - } else { - throw new Error('Failed to submit form.'); - } - - } catch (error) { - console.error('Error:', error); - - // Displaying error message - alert('Inventory PSTW Error', `An error occurred: ${error.message}`, 'error'); - } - - }, - - initiateTable() { - self = this; - this.itemDatatable = $('#itemDatatable').DataTable({ - "data": this.items, - "columns": [ - { - "title": "Unique Id", - "data": "uniqueID", - "createdCell": function (td, cellData, rowData, row, col) { - // Assign a unique ID to the element - $(td).attr('id', `qr${cellData}`); - }, - }, - { - "title": "Print", - "data": "uniqueID", - "render": function (data, type, full, meta) { - var printButton = ``; - return printButton; - }, - "className": "align-middle", - }, - { - "title": "Item Short Name", - "data": "productShortName", - }, - { - "title": "Serial Number", - "data": "serialNumber", - }, - { - "title": "Part Number", - "data": "partNumber", - }, - { - "title": "Category", - "data": "category", - }, - { - "title": "Quantity", - "data": "quantity", - }, - { - "title": "Supplier", - "data": "supplier", - }, - { - "title": "Purchase Date", - "data": "purchaseDate", - }, - { - "title": "Price(RM)", - "data": "convertPrice", - }, - { - "title": "Invoice Date", - "data": "invoiceDate", - }, - { - "title": "Warranty Until", - "data": "warranty", - "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) { - currentUser = data ?? null; - currentStore = full.currentStore ?? 'N/A'; - currentStation = full.currentStation ?? 'N/A'; - return `User: ${currentUser}
- Store: ${currentStore}
- Station: ${currentStation}` - } - }, - { - "title": "Delete", - "data": "itemID", - "render": function (data) { - var deleteButton = ``; - return deleteButton; - }, - "className": "align-middle", - } - ], - responsive: true, - drawCallback: function (settings) { - // Generate QR codes after rows are rendered - const api = this.api(); - api.rows().every(function () { - const data = this.data(); // Row data - const containerId = `qr${data.uniqueID}`; - const container = $(`#${containerId}`); - container.empty(); - container.append(`${data.uniqueID}`); - // console.log(container[0]); - if (container) { - // Generate QR code only if not already generated - new QRCode(container[0], { - text: data.qrString, - width: 100, - height: 100, - colorDark: "#000000", - colorLight: "#ffffff", - correctLevel: QRCode.CorrectLevel.M - }); - } - // container.on('click', function() { - // window.open(data.qrString, '_blank'); - // }); - }); - }, - }) - - // Attach click event listener to the delete buttons - $('#itemDatatable tbody').on('click', '.delete-btn', function () { - const itemId = $(this).data('id'); - self.deleteItem(itemId); - }); - - $('#itemDatatable tbody').on('click', '.print-btn', function () { - const $button = $(this); // The clicked button - const $row = $button.closest('tr'); // The parent row of the button - const itemId = $button.data('id'); // Get the item ID from the button's data attribute - - let imageSrc; - - // Check if the table is collapsed - if ($row.hasClass('child')) { - // For collapsed view: Look for the closest `.dtr-data` that contains the img - imageSrc = $row.prev('tr').find('td:nth-child(1) img').attr('src'); - } else { - // For expanded view: Find the img in the first column of the current row - imageSrc = $row.find('td:nth-child(1) img').attr('src'); - } - - if (imageSrc) { - self.printItem(itemId, imageSrc); // Call the print function with the itemId and imageSrc - } else { - console.error("Image source not found."); - } - }); - - this.loading = false; - }, - - async fetchItems() { - - try { - // const token = localStorage.getItem('token'); // Get the token from localStorage - const response = await fetch('/InvMainAPI/ItemList', { - method: 'POST', // Specify the HTTP method - headers: { - 'Content-Type': 'application/json', // Set content type - // 'Authorization': `Bearer ${token}` // Include the token in the headers - } - }); - - if (!response.ok) { - throw new Error('Failed to fetch item'); - } - this.items = await response.json(); - - if (this.itemDatatable) { - this.itemDatatable.clear().destroy(); - } - this.initiateTable(); - } - catch (error) { - console.error('Error fetching item:', error); - } - }, - - async fetchProducts() { - try { - // const token = localStorage.getItem('token'); // Get the token from localStorage - const response = await fetch('/InvMainAPI/ProductList', { - method: 'POST', // Specify the HTTP method - headers: { - 'Content-Type': 'application/json', // Set content type - // 'Authorization': `Bearer ${token}` // Include the token in the headers - } - }); - - if (!response.ok) { - throw new Error('Failed to fetch products'); - } - - this.products = await response.json(); - } - catch (error) { - console.error('Error fetching products:', error); - } - }, - - async fetchCompanies() { - try { - const response = await fetch('/AdminAPI/GetDepartmentWithCompanyList', { - method: 'POST', // Specify the HTTP method - headers: { - 'Content-Type': 'application/json' - } - }); - if (!response.ok) { - throw new Error('Failed to fetch companies'); - } - - this.companies = await response.json(); - - } catch (error) { - console.error('Error fetching products:', error); - } - }, - async fetchSuppliers() { try { const response = await fetch('/InvMainAPI/SupplierList', { @@ -861,127 +543,26 @@ if (!response.ok) { throw new Error('Failed to fetch suppliers'); } - this.suppliers = await response.json(); // Get the full response object + this.supplierlist = await response.json(); // Get the full response object } catch (error) { console.error('Error fetching suppliers:', error); } }, - async fetchCurrencyData() { - try { - // Fetch currency data from the API - const response = await fetch('https://openexchangerates.org/api/currencies.json'); // Example API - this.currencies = await response.json(); - } catch (error) { - console.error('Error fetching currency data:', error); - } - }, - convertCurrency() { - // Your currency conversion logic here - console.log('Selected currency:', this.currency); - }, resetForm() { - this.selectedUser = null; - this.selectedStore = null; - this.remark = ''; + this.selectedUser = ""; + this.selectedStore = ""; + this.remark = ""; + this.assigndate = ""; + this.selectedStore = ""; + this.selectedOther = ""; + }, // FRONT END FUNCTIONS //----------------------// - //Calculate Total Price - convertCurrency() { - const total = this.DefaultPrice * this.currencyRate; - this.convertPrice = total.toFixed(2); - this.DefaultPrice = this.DefaultPrice - // .replace(/[^0-9.]/g, '') // Remove non-numeric characters except decimal points - // .replace(/(\..*)\..*/g, '$1') // Allow only one decimal point - // .replace(/^(\d*\.\d{0,2})\d*$/, '$1'); // Limit to two decimal places - - }, - calculateWarrantyEndDate() { - // Check if DODate and warranty are valid - if (!this.DODate || isNaN(Date.parse(this.DODate))) { - this.EndWDate = null; - return; - } - - const DODates = new Date(this.DODate); - const warrantyMonth = parseInt(this.warranty); - - // Ensure warranty is a valid number - if (!isNaN(warrantyMonth)) { - DODates.setMonth(DODates.getMonth() + warrantyMonth); - this.EndWDate = DODates.toISOString().split('T')[0]; - } else { - this.EndWDate = null; - } - }, - async deleteItem(itemId) { - if (!confirm("Are you sure you want to delete this item?")) { - return; - } - try { - const response = await fetch(`/InvMainAPI/DeleteItem/${itemId}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - }); - const result = await response.json(); - - if (result.success) { - alert(result.message); - // Remove the row from DataTables - this.itemDatatable - .row($(`.delete-btn[data-id="${itemId}"]`).closest('tr')) - .remove() - .draw(); - } else { - alert(result.message); - } - } - catch (error) { - console.error("Error deleting item:", error); - alert("An error occurred while deleting the item."); - } - finally { - this.loading = false; - } - }, - async printItem(itemId, imgSrc) { - try { - this.thisQRInfo.uniqueID = itemId; - const uniqueQR = itemId; - const container = document.getElementById("QrContainer"); - - if (!container) { - console.error("Container not found."); - return; - } - - // Safely set image content - const sanitizedImgSrc = encodeURI(imgSrc); // Sanitize the URL - container.innerHTML = `QR Code`; - - // Fetch QR information - const qrInfo = this.getPrintedQR(uniqueQR); - if (!qrInfo) { - console.error("QR Info not found."); - return; - } - - this.thisQRInfo = qrInfo; - this.thisQRInfo.imgSrc = sanitizedImgSrc - this.thisQRInfo.imgContainer = container.innerHTML - $(`#QrItemModal`).modal('show'); // Show modal - } - catch (error) { - console.error("Error generating QR code:", error); - alert("An error occurred while generating the QR code."); - } - }, async fetchUser() { try { const response = await fetch(`/IdentityAPI/GetUserInformation/`, { @@ -994,6 +575,7 @@ this.currentUserCompanyDept = companyDeptData; this.selectedCompany = companyDeptData?.companyId || ""; this.selectedDepartment = companyDeptData?.departmentId || ""; + } else { console.error(`Failed to fetch user: ${response.statusText}`); @@ -1003,88 +585,27 @@ console.error('There was a problem with the fetch operation:', error); } }, - getPrintedQR(uniqueID) { - if (!this.items || !Array.isArray(this.items)) { - console.error("Items list is not available or is not an array."); - return null; - } - return this.items.find(item => item.uniqueID === uniqueID); - }, - printQRInfo() { - // Create a virtual DOM element - const virtualElement = document.createElement('div'); - virtualElement.style.width = '330px '; // Match label size for 2 inches at 203 DPI - virtualElement.style.height = '160px'; - virtualElement.style.position = 'absolute'; - virtualElement.style.left = '-9999px'; // Position offscreen to avoid rendering on the main UI - // virtualElement.style.border = '1px solid #000'; // Optional: Add a border for debugging dimensions - - // Populate the virtual DOM with content - virtualElement.innerHTML = ` -
-
-
-
-
-
${this.thisQRInfo.imgContainer}
-
${this.thisQRInfo.uniqueID}
-
-
-
-
-
-
${this.thisQRInfo.departmentName}
-
${this.thisQRInfo.productShortName}
-
${this.thisQRInfo.serialNumber??"-"}
-
${this.thisQRInfo.partNumber}
-
-
-
-
- `; - - // Append the virtual DOM to the body (temporarily) - document.body.appendChild(virtualElement); - - // Wait for the font to be loaded (important for custom fonts like OCR-A) - document.fonts.load('1em "OCR A"').then(() => { - // Use html2canvas to convert the virtual DOM to an image - html2canvas(virtualElement, { - scale: 1, // Increase scale for sharper images - }).then((canvas) => { - // Convert the canvas to an image - const imgData = canvas.toDataURL('image/png'); - // Open the image in a new tab for preview (optional) - // const newWindow = window.open(); - // newWindow.location.href = imgData; - // console.log(imgData) - // Use printJS to print the image - printJS({ - printable: imgData, - type: 'image', - css: '/../lib/bootstrap/dist/css/bootstrap.css', - style: ` - @@media print { - @@page { - margin: 5px 5px 0px 5px; - } - body { margin: 0; } - } - ` - }); - - // Remove the virtual DOM from the body after use - document.body.removeChild(virtualElement); - }).catch((error) => { - console.error("Error generating image:", error); - // Remove the virtual DOM if an error occurs - document.body.removeChild(virtualElement); + async fetchStoreId() { + try { + const response = await fetch(`/IdentityAPI/GetUserInformation/`, { + method: 'POST', }); - }).catch((error) => { - console.error("Error loading font:", error); - // Remove the virtual DOM if font loading fails - document.body.removeChild(virtualElement); - }); + if (response.ok) { + const data = await response.json(); + this.currentUser = data?.userInfo || null; + const companyDeptData = await this.currentUser.department; + this.currentUserCompanyDept = companyDeptData; + this.selectedCompany = companyDeptData?.companyId || ""; + this.selectedDepartment = companyDeptData?.departmentId || ""; + + } + else { + console.error(`Failed to fetch user: ${response.statusText}`); + } + } + catch (error) { + console.error('There was a problem with the fetch operation:', error); + } }, async fetchUsers() { try { @@ -1125,6 +646,7 @@ this.storelist = await response.json(); + } catch (error) { console.error('Error fetching item:', error); diff --git a/Controllers/API/Inventory/InvMainAPI.cs b/Controllers/API/Inventory/InvMainAPI.cs index 94e49c1..3f3517f 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; @@ -643,7 +644,6 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory [HttpPost("AddItemMovement")] public async Task AddItemMovement([FromBody] ItemMovementModel itemmovement) - //public async Task AddItemMovement() { @@ -655,6 +655,32 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory try { + + 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 diff --git a/wwwroot/Media/Inventory/itemmovement/8_9d1a573e-5956-4e78-a4c7-ee2ae4ac94508_Request.jpg b/wwwroot/Media/Inventory/itemmovement/8_9d1a573e-5956-4e78-a4c7-ee2ae4ac94508_Request.jpg new file mode 100644 index 0000000..b4c8942 Binary files /dev/null and b/wwwroot/Media/Inventory/itemmovement/8_9d1a573e-5956-4e78-a4c7-ee2ae4ac94508_Request.jpg differ diff --git a/wwwroot/Media/Inventory/request/sequence diagram.png b/wwwroot/Media/Inventory/request/sequence diagram.png new file mode 100644 index 0000000..0584ff4 Binary files /dev/null and b/wwwroot/Media/Inventory/request/sequence diagram.png differ