Update Inventory

This commit is contained in:
Naz 2025-07-16 09:22:06 +08:00
parent 5e5d7280f4
commit d671db342a
13 changed files with 569 additions and 207 deletions

View File

@ -158,7 +158,7 @@
<div class="row card"> <div class="row card">
<div class="card-header"> <div class="card-header">
<h2>Complete Item Movessment</h2> <h2>Complete Item Movement</h2>
</div> </div>
<div class="card-header"> <div class="card-header">
<h4>All Item Movement</h4> <h4>All Item Movement</h4>
@ -884,7 +884,7 @@
return this.groupedByStation; return this.groupedByStation;
} }
let searchQueryStation = this.toLowerCase(); let searchQueryStation = String(this.searchQueryStation).toLowerCase();
let grouped = this.groupedByStation; let grouped = this.groupedByStation;
let filtered = {}; let filtered = {};

View File

@ -626,6 +626,25 @@
initiateTable() { initiateTable() {
self = this; self = this;
function formatDateTime(dateString) {
if (!dateString) {
return ""; // Return empty string if date is null or undefined
}
const date = new Date(dateString);
// Add 8 hours for GMT+8, as DateTime.UtcNow is used on the backend.
// If the backend stores dates in a specific timezone and you want to display them
// in the client's local timezone, you might need a different approach or
// ensure the backend sends timezone information.
// For now, assuming backend's UtcNow and client display in GMT+8.
date.setHours(date.getHours()); // Adjust for local time if needed.
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}`;
}
function renderActionButtons(data, type, row) { function renderActionButtons(data, type, row) {
var actiontButtons = `<div class="row" style="padding: 5px;"> <button type="button" class="btn btn-success approve-btn" data-id="${data}">Approve</button></div> <div class="row" style="padding: 5px;"><button type="button" class="btn btn-danger reject-btn" data-id="${data}">Reject</button></div>`; var actiontButtons = `<div class="row" style="padding: 5px;"> <button type="button" class="btn btn-success approve-btn" data-id="${data}">Approve</button></div> <div class="row" style="padding: 5px;"><button type="button" class="btn btn-danger reject-btn" data-id="${data}">Reject</button></div>`;
return actiontButtons; return actiontButtons;
@ -671,8 +690,8 @@
{ "title": "Document/Picture", "data": "document", "render": renderDocument }, { "title": "Document/Picture", "data": "document", "render": renderDocument },
{ "title": "User Remark", "data": "remarkUser" }, { "title": "User Remark", "data": "remarkUser" },
{ "title": "Status", "data": "status" }, { "title": "Status", "data": "status" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": formatDateTime }, // Apply formatDateTime
{ "title": "Approval Date", "data": "approvalDate" } { "title": "Approval Date", "data": "approvalDate", "render": formatDateTime } // Apply formatDateTime
], ],
responsive: true, responsive: true,
drawCallback: function (settings) { } drawCallback: function (settings) { }
@ -691,8 +710,8 @@
{ "title": "User Remark", "data": "remarkUser" }, { "title": "User Remark", "data": "remarkUser" },
{ "title": "InvMaster Remark", "data": "remarkMasterInv" }, { "title": "InvMaster Remark", "data": "remarkMasterInv" },
{ "title": "Status", "data": "status" }, { "title": "Status", "data": "status" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": formatDateTime }, // Apply formatDateTime
{ "title": "Approval Date", "data": "approvalDate" } { "title": "Approval Date", "data": "approvalDate", "render": formatDateTime } // Apply formatDateTime
], ],
responsive: true responsive: true
}); });
@ -708,8 +727,8 @@
{ "title": "Document/Picture", "data": "document", "render": renderDocument }, { "title": "Document/Picture", "data": "document", "render": renderDocument },
{ "title": "Remark", "data": "remarkUser" }, { "title": "Remark", "data": "remarkUser" },
{ "title": "Status", "data": "status" }, { "title": "Status", "data": "status" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": formatDateTime }, // Apply formatDateTime
{ "title": "Approval Date", "data": "approvalDate" }, { "title": "Approval Date", "data": "approvalDate", "render": formatDateTime }, // Apply formatDateTime
{ {
"title": "Delete", "data": "requestID", "title": "Delete", "data": "requestID",
"render": function (data) { "render": function (data) {
@ -736,8 +755,8 @@
{ "title": "Document/Picture", "data": "document", "render": renderDocument }, { "title": "Document/Picture", "data": "document", "render": renderDocument },
{ "title": "User Remark", "data": "remarkUser" }, { "title": "User Remark", "data": "remarkUser" },
{ "title": "Status", "data": "status" }, { "title": "Status", "data": "status" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": formatDateTime }, // Apply formatDateTime
{ "title": "Approval Date", "data": "approvalDate" } { "title": "Approval Date", "data": "approvalDate", "render": formatDateTime } // Apply formatDateTime
], ],
responsive: true responsive: true
}); });
@ -754,8 +773,8 @@
{ "title": "Document/Picture", "data": "document", "render": renderDocument }, { "title": "Document/Picture", "data": "document", "render": renderDocument },
{ "title": "User Remark", "data": "remarkUser" }, { "title": "User Remark", "data": "remarkUser" },
{ "title": "Status", "data": "status" }, { "title": "Status", "data": "status" },
{ "title": "Request Date", "data": "requestDate" }, { "title": "Request Date", "data": "requestDate", "render": formatDateTime }, // Apply formatDateTime
{ "title": "Approval Date", "data": "approvalDate" } { "title": "Approval Date", "data": "approvalDate", "render": formatDateTime } // Apply formatDateTime
], ],
responsive: true responsive: true
}); });

View File

@ -34,6 +34,30 @@
<input type="text" class="form-control" id="manufacturerName" v-model="newManufacturer.manufacturerName" required> <input type="text" class="form-control" id="manufacturerName" v-model="newManufacturer.manufacturerName" required>
</div> </div>
</div> </div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary closeModal" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="editManufacturerModal" tabindex="-1" role="dialog" aria-labelledby="editManufacturerModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit Manufacturer</h5>
<button type="button" class="closeModal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form v-on:submit.prevent="updateManufacturer">
<div class="modal-body">
<div class="form-group">
<label for="editManufacturerName">Manufacturer Name:</label>
<input type="text" class="form-control" id="editManufacturerName" v-model="editManufacturer.manufacturerName" required>
</div>
</div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary closeModal" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary closeModal" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button> <button type="submit" class="btn btn-primary">Save changes</button>
@ -42,6 +66,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@section Scripts { @section Scripts {
@{ @{
@ -57,6 +82,11 @@
manufacturerName: null, manufacturerName: null,
}, },
loading: true, loading: true,
editManufacturer: {
manufacturerId: null,
manufacturerName: null,
},
} }
}, },
@ -88,27 +118,54 @@
}, },
async initiateTable() { async initiateTable() {
// Clear any existing DataTable instance before re-initializing
if (this.manufacturerDatatable) {
this.manufacturerDatatable.destroy();
}
this.manufacturerDatatable = $('#manufacturerTable').DataTable({ this.manufacturerDatatable = $('#manufacturerTable').DataTable({
"data": this.manufacturer, "data": this.manufacturer,
"columns": [ "columns": [
{ "title": "Manufacturer Name", {
"title": "Manufacturer Name",
"data": "manufacturerName", "data": "manufacturerName",
}, },
{ "title": "Delete", {
"data": "manufacturerName", "title": "Edit",
"render": function (data, type, full, meta) { "data": "manufacturerId", // Use manufacturerId for the data attribute
var deleteButton = `<button type="button" class="btn btn-danger delete-btn" data-id="${full.manufacturerId}">Delete</button>`; "render": (data, type, row) => { // Use arrow function to preserve 'this' context
// 'this' inside this arrow function will refer to the Vue instance
var editButton = `<button type="button" class="btn btn-success edit-btn" data-id="${data}">Edit</button>`;
return editButton;
},
},
{
"title": "Delete",
"data": "manufacturerId", // Use manufacturerId for the data attribute
"render": (data, type, row) => { // Use arrow function to preserve 'this' context
var deleteButton = `<button type="button" class="btn btn-danger delete-btn" data-id="${data}">Delete</button>`;
return deleteButton; return deleteButton;
}, },
"width": '10%', "width": '10%',
}, },
], ],
}) });
self = this;
// Use a variable to store the Vue instance for consistent access
const vueInstance = this;
// Attach click event listener to the edit buttons
$('#manufacturerTable tbody').off('click', '.edit-btn').on('click', '.edit-btn', function () {
const manufacturerId = $(this).data('id');
// Call the method on the stored Vue instance
vueInstance.openEditManufacturerModal(manufacturerId);
$('#editManufacturerModal').modal('show'); // Ensure the modal is shown here
});
// Attach click event listener to the delete buttons // Attach click event listener to the delete buttons
$('#manufacturerTable tbody').on('click', '.delete-btn', function () { $('#manufacturerTable tbody').off('click', '.delete-btn').on('click', '.delete-btn', function () {
const manufacturerId = $(this).data('id'); // Get the manufacturer ID from the button const manufacturerId = $(this).data('id');
self.deleteManufacturer(manufacturerId); // Call the Vue method vueInstance.deleteManufacturer(manufacturerId);
}); });
this.loading = false; this.loading = false;
@ -153,6 +210,43 @@
this.newManufacturer.manufacturerName = null; this.newManufacturer.manufacturerName = null;
}); });
}, },
openEditManufacturerModal(manufacturerId) {
const selected = this.manufacturer.find(m => m.manufacturerId === manufacturerId);
if (!selected) {
alert('Manufacturer not found');
return;
}
this.editManufacturer.manufacturerId = selected.manufacturerId;
this.editManufacturer.manufacturerName = selected.manufacturerName;
$('#editManufacturerModal').modal('show');
},
async updateManufacturer() {
try {
const response = await fetch('/InvMainAPI/EditManufacturer', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.editManufacturer)
});
const data = await response.json();
if (data && data.success) {
alert('Manufacturer updated successfully');
this.fetchManufactures(); // Refresh list
$('#editManufacturerModal').modal('hide');
} else {
alert(data.message || 'Failed to update manufacturer');
}
} catch (error) {
console.error('Error updating manufacturer:', error);
alert('Error occurred while updating');
}
},
async deleteManufacturer(manufacturerId) { async deleteManufacturer(manufacturerId) {
if (!confirm("Are you sure you want to delete this manufacturer?")) { if (!confirm("Are you sure you want to delete this manufacturer?")) {
return; return;
@ -201,6 +295,14 @@
// Show the modal with the ID 'addManufacturerModal'. // Show the modal with the ID 'addManufacturerModal'.
$('#addManufacturerModal').modal('hide'); $('#addManufacturerModal').modal('hide');
}); });
$('#editManufacturerBtn').on('click', function () {
// Show the modal with the ID 'editManufacturerModal'.
$('#editManufacturerModal').modal('show');
});
$('.closeModal').on('click', function () {
// Show the modal with the ID 'editManufacturerModal'.
$('#editManufacturerModal').modal('hide');
});
}); });
</script> </script>
} }

View File

@ -145,20 +145,18 @@
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab"> <div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
<div style="text-align: center; margin: 20px 0; padding: 20px;"> <div style="text-align: center; margin: 20px 0; padding: 20px;">
<div v-if="itemlateststatus == 'On Delivery' && this.thisItem.toUser == this.currentUser.id"> <div v-if="itemlateststatus == 'On Delivery' && this.thisItem.toUser == this.currentUser.id && !isCancelled">
<h2 class="register-heading">Item is on Delivery</h2> <h2 class="register-heading">Item is on Delivery</h2>
<div class="col-sm-3"></div> <div class="col-sm-3"></div>
<div class="col-sm-6 offset-sm-3"> <div class="col-sm-6 offset-sm-3">
<form v-on:submit.prevent="receiveItemMovement" data-aos="fade-right"> <form v-on:submit.prevent="receiveItemMovement" data-aos="fade-right">
<div class="row register-form"> <div class="row register-form">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">Remark:</label> <label class="col-sm-4 col-form-label">Remark:</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" id="remark" name="remark" v-model="remark" class="form-control" required /> <input type="text" id="remark" name="remark" v-model="remark" class="form-control" required />
</div> </div>
</div> </div>
<div style="display: flex; justify-content: center; margin-top: 20px;"> <div style="display: flex; justify-content: center; margin-top: 20px;">
<button type="submit" class="btn btn-primary" style="width: 200px; padding: 10px; font-size: 16px;"> <button type="submit" class="btn btn-primary" style="width: 200px; padding: 10px; font-size: 16px;">
Cancel Item Movement Cancel Item Movement
@ -257,17 +255,13 @@
</div> </div>
</div> </div>
<div v-if="itemlateststatus == 'Ready To Deploy' && this.itemassignedtouser"> <div v-if="isCancelled || (itemlateststatus == 'Ready To Deploy' && this.itemassignedtouser)">
<h2 class="register-heading">Add Item Movement</h2> <h2 class="register-heading">Add Item Movement</h2>
<div class="col-sm-3"></div> <div class="col-sm-3"></div>
<div class="col-sm-6 offset-sm-3"> <div class="col-sm-6 offset-sm-3">
<div class="dropdown"> <div class="dropdown">
<select class="btn btn-primary dropdown-toggle col-md-10 " v-model="selectedAction" required> <select class="btn btn-primary dropdown-toggle col-md-10 " v-model="selectedAction" required>
<option class="btn-light" value="" disabled selected>Select Action</option> <option class="btn-light" value="" disabled selected>Select Action</option>
@* <option class="btn-light" value="user" v-if="itemlateststatus == 'Ready To Deploy'">Assign to User</option> *@
@* <option class="btn-light" value="store" v-if="itemlateststatus == 'Ready To Deploy'">Assign to Store</option> *@
@* <option class="btn-light" value="supplier" v-if="itemlateststatus != 'Delivered'">Assign to Supplier</option> *@
@* <option class="btn-light" value="faulty" v-if="itemlateststatus != 'Delivered'">Faulty</option> *@
<option class="btn-light" value="user">Assign to User</option> <option class="btn-light" value="user">Assign to User</option>
<option class="btn-light" value="station">Assign to Station</option> <option class="btn-light" value="station">Assign to Station</option>
<option class="btn-light" value="store">Assign to Store</option> <option class="btn-light" value="store">Assign to Store</option>
@ -277,7 +271,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label"></label> <label class="col-sm-3 col-form-label"></label>
@ -620,6 +613,7 @@
currentUser: null, currentUser: null,
currentUserCompanyDept: null, currentUserCompanyDept: null,
itemlateststatus: "", itemlateststatus: "",
isCancelled: false,
//QR VARIABLE //QR VARIABLE
qrCodeResult: null, qrCodeResult: null,
@ -662,9 +656,21 @@
}, },
computed: { computed: {
selectedStationPicName() { selectedStationPicName() {
const selectedStationObj = this.stationlist.find(station => station.stationId === this.selectedStation); const selectedStationObj = this.stationlist.find(
return selectedStationObj ? selectedStationObj.stationPic.fullName : ""; station => station.stationId === this.selectedStation
);
if (
selectedStationObj &&
selectedStationObj.stationPic &&
selectedStationObj.stationPic.fullName
) {
return selectedStationObj.stationPic.fullName;
}
return "";
}, },
filteredDepartments() { filteredDepartments() {
if (!this.selectedCompany) { if (!this.selectedCompany) {
return []; // No company selected, return empty list return []; // No company selected, return empty list
@ -804,6 +810,7 @@
}, },
resetScanner() { resetScanner() {
this.thisItem = null; this.thisItem = null;
this.isCancelled = false; // Add this
this.resetForm(); this.resetForm();
}, },
handleFileUpload(event) { handleFileUpload(event) {
@ -876,7 +883,6 @@
}, },
async receiveItemMovement() { async receiveItemMovement() {
if (this.showProduct.category == "Disposable") { if (this.showProduct.category == "Disposable") {
this.serialNumber = ""; this.serialNumber = "";
} }
@ -888,77 +894,55 @@
} }
const now = new Date(); const now = new Date();
console.log('currentuser'+this.currentUser.id);
console.log('lastuser'+this.thisItem.lastuser);
const formData = {
Id: this.thisItem.movementId,
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
Remark: this.thisItem.toOther === "On Delivery" && this.thisItem.toUser == this.currentUser.id ? this.thisItem.remark + ". Inventory Master cancelled delivery with remark: " + this.remark : this.thisItem.remark,
LastUser: this.thisItem.lastuser == null ? this.currentUser.id : this.thisItem.lastuser,
LatestStatus: this.thisItem.toOther === "Return" ? "Faulty" : (this.thisItem.toOther === "Calibration" || this.thisItem.toOther === "Repair" || this.thisItem.toOther === "On Delivery" ) ? "Ready To Deploy" : (this.itemlateststatus == 'On Delivery' && this.thisItem.lastStore == this.currentUser.store ? "Delivered" : "")
};
try { try {
// First, update the current movement to mark it as complete
// Proceed to send the data to the API const updateResponse = await fetch('/InvMainAPI/UpdateItemMovementMaster', {
const response = await fetch('/InvMainAPI/UpdateItemMovementMaster', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
// 'Authorization': `Bearer ${this.token}`
}, },
body: JSON.stringify(formData) body: JSON.stringify({
Id: this.thisItem.movementId,
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
Remark: this.thisItem.toOther === "On Delivery" && this.thisItem.toUser == this.currentUser.id ?
this.thisItem.remark + ". Inventory Master cancelled delivery with remark: " + this.remark :
this.thisItem.remark,
LastUser: this.thisItem.lastuser == null ? this.currentUser.id : this.thisItem.lastuser,
LatestStatus: "Ready To Deploy", // Set status to Ready To Deploy
MovementComplete: true
})
}); });
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);
// console.log(updatedItem);
// Reset the form if (!updateResponse.ok) {
this.resetForm(); throw new Error('Failed to update current movement');
window.location.href = '/Inventory/InventoryMaster/ItemMovement';
} else {
throw new Error('Failed to submit form.');
} }
// Set cancelled flag and reset form
this.isCancelled = true;
this.resetForm();
// Show the movement form by setting selectedAction
this.selectedAction = "user"; // Default to assign to user
} catch (error) { } catch (error) {
console.error('Error:', error); console.error('Error:', error);
// Displaying error message
alert('Inventory PSTW Error', `An error occurred: ${error.message}`, 'error'); alert('Inventory PSTW Error', `An error occurred: ${error.message}`, 'error');
} }
}, },
async fetchItem(itemid) { async fetchItem(itemid) {
try { try {
const response = await fetch('/InvMainAPI/GetItem/' + itemid, { const response = await fetch('/InvMainAPI/GetItem/' + itemid, {
method: 'POST',} method: 'POST',
); });
if (response.ok) { if (response.ok) {
// this.thisItem = await response.json();
this.thisItem = await response.json(); this.thisItem = await response.json();
console.log('last store'+this.thisItem.lastStore);
this.itemlateststatus = this.thisItem.latestStatus ? this.thisItem.latestStatus : this.thisItem.toOther; this.itemlateststatus = this.thisItem.latestStatus ? this.thisItem.latestStatus : this.thisItem.toOther;
this.itemassignedtouser = (this.thisItem.toUser === this.currentUser.id || this.thisItem.lastUser === this.currentUser.id ) && this.thisItem.lastStore === this.currentUser.store ? true : false; this.itemassignedtouser = (this.thisItem.toUser === this.currentUser.id || this.thisItem.lastUser === this.currentUser.id) && this.thisItem.lastStore === this.currentUser.store;
// console.log(this.thisItem);
// console.log(this.itemassignedtouser);
console.log(this.thisItem.lastStore);
console.log( this.thisItem.lastStore == this.currentUser.store? true : false);
console.log(this.thisItem.toUser == this.currentUser.id? true : false);
console.log( this.thisItem.lastUser == this.currentUser.id ? true : false);
console.log(((this.thisItem.toUser == this.currentUser.id) || ( this.thisItem.lastUser == this.currentUser.id)) ? true : false);
console.log('currentuser store'+this.currentUser.store);
// Reset cancellation flag when scanning
this.isCancelled = false;
} else { } else {
console.error('Failed to fetch item information'); console.error('Failed to fetch item information');
this.responseMessage = await response.text(); this.responseMessage = await response.text();

View File

@ -5,6 +5,7 @@
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml") @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml")
<div id="registerSupplier"> <div id="registerSupplier">
<div class="row" v-if="addSection == true">
<form v-on:submit.prevent="addSupplier" data-aos="fade-right" id="registerSupplierForm" v-if="registerSupplierForm"> <form v-on:submit.prevent="addSupplier" data-aos="fade-right" id="registerSupplierForm" v-if="registerSupplierForm">
<div class="container register" data-aos="fade-right"> <div class="container register" data-aos="fade-right">
<div class="row"> <div class="row">
@ -72,9 +73,98 @@
</div> </div>
</div> </div>
</form> </form>
<div class="row">
<button class="btn btn-danger col-md-3 m-1"
v-on:click="resetForm(); registerSupplierForm = false; addSection = false;">
<i class="fa fa-minus"></i>&nbsp;Hide Add Supplier Section
</button>
</div>
</div>
<div class="row" v-if="editSection == true">
<form v-on:submit.prevent="submitEditSupplier" data-aos="fade-right">
<div class="container register" data-aos="fade-right">
<div class="row">
@*Right Side*@
<div class="col-md-9" data-aos="fade-right">
<div class="tab-content" id="myTabContent" data-aos="fade-right">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab" data-aos="fade-right">
<h3 class="register-heading">EDIT SUPPLIER</h3>
<div class="row register-form">
<div class="col-md-61">
@* Supplier Name *@
<div class="form-group row">
<label for="supplierCompName" class="col-sm-3">Supplier Company Name:</label>
<div class="col-sm-9">
<input type="text" id="supplierCompName" name="supplierCompName" class="form-control" required v-model="supplierCompName">
</div>
</div>
@* Supplier Gender *@
<div class="form-group row">
<label class="col-sm-3">Supplier Address:</label>
<div class="col-sm-9">
<div class="dropdown">
<textarea type="text" id="supplierAddress" name="supplierAddress" class="form-control" required v-model="supplierAddress"></textarea>
</div>
</div>
</div>
@* Supplier PIC *@
<div class="form-group row">
<label class="col-sm-3">Supplier PIC:</label>
<div class="col-sm-9">
<input type="email" id="supplierPIC" name="supplierPIC" class="form-control" v-model="supplierPIC">
</div>
</div>
@* Supplier Email *@
<div class="form-group row">
<label class="col-sm-3">Supplier Email:</label>
<div class="col-sm-9">
<input type="email" id="supplierEmail" name="supplierEmail" class="form-control" v-model="supplierEmail">
</div>
</div>
@* Supplier Number Phone *@
<div class="form-group row">
<label class="col-sm-3">Supplier Phone Number:</label>
<div class="col-sm-9">
<input type="tel" id="supplierPhoneNo" name="supplierPhoneNo" class="form-control" v-model="supplierPhoneNo">
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-9 offset-sm-3">
<button type="button" v-on:click="resetForm" class="btn btn-secondary m-1">Reset</button>
<button type="submit" class="btn btn-primary m-1">Submit</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<div class="row">
<button class="btn btn-danger col-md-3 m-1" v-on:click="hideEditSection">
<i class="fa fa-minus"></i>&nbsp;Hide Edit Supplier Section
</button>
</div>
</div>
<div class="row card"> <div class="row card">
<div class="card-header"> <div class="card-header">
<button id="addSupplierBtn" :class="['btn', 'col-md-3', 'col-lg-3', 'm-1', 'col-12', registerSupplierForm ? 'btn-danger' : 'btn-success']" v-on:click="registerSupplierForm = !registerSupplierForm"><i :class="['fa', registerSupplierForm ? 'fa-minus' : 'fa-plus']"></i>&nbsp;{{registerSupplierForm ? 'Hide Add Supplier' : 'Show Add Supplier'}}</button> <div class="row">
<button id="addSupplierBtn"
class="btn btn-success col-md-3 m-1"
v-show="addSection == false"
v-on:click="resetForm(); registerSupplierForm = true; addSection = true; editSection = false;">
<i class="fa fa-plus"></i>&nbsp;Show Add Supplier Section
</button>
</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<table class="table table-bordered table-hover table-striped no-wrap" id="supplierDatatable" style="width:100%;border-style: solid; border-width: 1px"></table> <table class="table table-bordered table-hover table-striped no-wrap" id="supplierDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
@ -110,7 +200,10 @@
suppliers: null, suppliers: null,
supplierDatatable: null, supplierDatatable: null,
gender: ["Male", "Female", "Helicopter"], gender: ["Male", "Female", "Helicopter"],
registerSupplierForm: false registerSupplierForm: false,
editSection: false,
supplierId: null,
addSection: false,
} }
}, },
mounted(){ mounted(){
@ -151,11 +244,12 @@
$('#loadingModal').modal('show'); $('#loadingModal').modal('show');
// Create the payload // Create the payload
const formData = { const formData = {
supplierId: this.supplierId,
supplierCompName: this.supplierCompName, supplierCompName: this.supplierCompName,
supplierAddress: this.supplierAddress,
supplierPIC: this.supplierPIC,
supplierEmail: this.supplierEmail, supplierEmail: this.supplierEmail,
supplierPhoneNo: this.supplierPhoneNo, supplierPIC: this.supplierPIC,
supplierAddress: this.supplierAddress,
supplierPhoneNo: this.supplierPhoneNo
}; };
try { try {
@ -165,7 +259,7 @@
// Loop through required fields and check if any are null or empty // Loop through required fields and check if any are null or empty
for (let field of requiredFields) { for (let field of requiredFields) {
if (this[field] === null || this[field] === '') { if (this[field] === null || this[field] === '') {
alert('Product Error', `Please fill in required fields: ${field}.`, 'warning'); alert('Supplier Error', `Please fill in required fields: ${field}.`, 'warning');
return; // Exit early if validation fails return; // Exit early if validation fails
} }
} }
@ -193,7 +287,7 @@
} }
catch (error) { catch (error) {
console.error('Error:', error); console.error('Error:', error);
alert('Product Error', `An error occurred: ${error.message}`, 'error'); alert('Supplier Error', `An error occurred: ${error.message}`, 'error');
} }
finally { finally {
await new Promise(resolve => { await new Promise(resolve => {
@ -234,6 +328,14 @@
"title": "Supplier Phone No", "title": "Supplier Phone No",
"data": "supplierPhoneNo", "data": "supplierPhoneNo",
}, },
{
"title": "Edit",
"data": "supplierId",
"render": function (data) {
var editButton = `<button type="button" class="btn btn-success edit-btn" data-id="${data}">Edit</button>`;
return editButton;
},
},
{ {
"title": "Delete", "title": "Delete",
"data": "supplierId", "data": "supplierId",
@ -247,6 +349,12 @@
}) })
// Attach click event listener to the edit buttons
$('#supplierDatatable tbody').off('click', '.edit-btn').on('click', '.edit-btn', function () {
const supplierId = $(this).data('id');
self.editSupplier(supplierId);
});
// Attach click event listener to the delete buttons // Attach click event listener to the delete buttons
$('#supplierDatatable tbody').on('click', '.delete-btn', function () { $('#supplierDatatable tbody').on('click', '.delete-btn', function () {
const supplierId = $(this).data('id'); const supplierId = $(this).data('id');
@ -255,6 +363,75 @@
this.loading = false; this.loading = false;
}, },
async editSupplier(supplierId) {
const supplier = this.suppliers.find(s => s.supplierId === supplierId);
if (!supplier) {
alert('Error', 'Supplier not found!', 'warning');
return;
}
// Populate form fields
this.supplierId = supplierId;
this.supplierCompName = supplier.supplierCompName;
this.supplierEmail = supplier.supplierEmail;
this.supplierAddress = supplier.supplierAddress;
this.supplierPhoneNo = supplier.supplierPhoneNo;
this.supplierPIC = supplier.supplierPIC;
// Show the edit form and hide the add form
this.addSection = false;
this.editSection = true;
},
async submitEditSupplier() {
const formData = {
supplierId: this.supplierId,
SupplierCompName: this.supplierCompName,
supplierEmail: this.supplierEmail,
SupplierPIC: this.supplierPIC,
SupplierAddress: this.supplierAddress,
SupplierPhoneNo: this.supplierPhoneNo
};
try {
// List of required fields
const requiredFields = ['supplierCompName', 'supplierAddress', 'supplierPIC', 'supplierEmail', 'supplierPhoneNo'];
// Loop through required fields and check if any are null or empty
for (let field of requiredFields) {
if (this[field] === null || this[field] === '') {
alert('Supplier Error', `Please fill in required fields: ${field}.`, 'warning');
return; // Exit early if validation fails
}
}
// Edit supplier detail
const response = await fetch('/InvMainAPI/EditSupplier', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
if (!response.ok) {
const errorData = await response.json();
console.error('Error response:', errorData);
this.errorMessage = 'Error: ' + (errorData.message || 'Unknown error');
return;
}
// Refresh station list and reset form
alert('Success!', 'Supplier form has been successfully submitted.', 'success');
this.fetchSuppliers();
this.resetForm();
this.editSection = false;
} catch (error) {
console.error('Error editing Supplier:', error);
this.errorMessage = 'Error: ' + error.message;
}
},
async deleteSupplier(supplierId) { async deleteSupplier(supplierId) {
if (!confirm("Are you sure you want to delete this supplier?")) { if (!confirm("Are you sure you want to delete this supplier?")) {
return; return;
@ -280,6 +457,17 @@
console.error('Error deleting supplier:', error); console.error('Error deleting supplier:', error);
this.errorMessage = 'Error: ' + error.message; this.errorMessage = 'Error: ' + error.message;
} }
},
hideEditSection() {
this.resetForm();
this.editSection = false;
this.addSection = false;
},
toggleAddSupplier() {
this.resetForm();
this.editSection = false;
this.addSection = !this.addSection;
this.registerSupplierForm = this.addSection;
} }
} }
}); });

View File

@ -138,7 +138,7 @@
<!-- Button + Input dalam satu box --> <!-- Button + Input dalam satu box -->
<div class="dropdown-toggle-box" v-on:click="dropdownOpen = !dropdownOpen"> <div class="dropdown-toggle-box" v-on:click="dropdownOpen = !dropdownOpen">
<input type="text" class="form-control" v-model="searchQuery" <input type="text" class="form-control" v-model="searchQuery"
placeholder="Search product..." v-on:focus="dropdownOpen = true" v-on:click.stop /> placeholder="Search product..." v-on:focus="dropdownOpen = true" v-on:click.stop required/>
<button type="button" class="btn btn-primary dropdown-btn" v-on:click.stop="dropdownOpen = !dropdownOpen"> <button type="button" class="btn btn-primary dropdown-btn" v-on:click.stop="dropdownOpen = !dropdownOpen">
</button> </button>
@ -233,7 +233,7 @@
<div class="form-group row d-flex align-items-center"> <div class="form-group row d-flex align-items-center">
<label class="col-sm-2 col-form-label">Remark:</label> <label class="col-sm-2 col-form-label">Remark:</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" class="form-control col-md-10" v-model="remark" /> <input type="text" class="form-control col-md-10" v-model="remark" required/>
</div> </div>
</div> </div>
@ -259,6 +259,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</form> </form>
</div> </div>
</div> </div>
@ -373,14 +374,14 @@
// Loop through required fields and check if any are null or empty // Loop through required fields and check if any are null or empty
for (let field of requiredFields) { for (let field of requiredFields) {
if (!this[field]) { if (!this[field]) {
alert('Request Error', `Please fill in required fields: ${field}.`, 'warning'); alert(`Please fill in required fields: ${field}.`, 'warning');
return; return;
} }
} }
if (this.assign === "Station"){ if (this.assign === "Station"){
if (this.stationId == null) { if (this.stationId == null) {
alert('Request Error', `Please fill in required fields : Station.`, 'warning'); alert( `Please fill in required fields : Station.`, 'warning');
return; return;
} }
} }
@ -511,8 +512,7 @@
}); });
this.loading = false; this.loading = false;
} },
async fetchRequest() { async fetchRequest() {
try try

View File

@ -111,6 +111,41 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
} }
} }
[HttpPost("EditManufacturer")]
public async Task<IActionResult> EditManufacturer([FromBody] ManufacturerModel updatedManufacturer)
{
if (updatedManufacturer == null || updatedManufacturer.ManufacturerId == 0)
{
return BadRequest(new { success = false, message = "Invalid manufacturer data." });
}
try
{
// Find the existing manufacturer
var manufacturer = await _centralDbContext.Manufacturers
.FirstOrDefaultAsync(m => m.ManufacturerId == updatedManufacturer.ManufacturerId);
if (manufacturer == null)
{
return NotFound(new { success = false, message = "Manufacturer not found." });
}
// Update fields
manufacturer.ManufacturerName = updatedManufacturer.ManufacturerName;
// Save changes
await _centralDbContext.SaveChangesAsync();
return Ok(new { success = true, message = "Manufacturer updated successfully." });
}
catch (Exception ex)
{
// Optional: Log the error
return StatusCode(500, new { success = false, message = "Internal server error: " + ex.Message });
}
}
[HttpDelete("DeleteManufacturer/{id}")] [HttpDelete("DeleteManufacturer/{id}")]
public async Task<IActionResult> DeleteManufacturer(int id) public async Task<IActionResult> DeleteManufacturer(int id)
{ {
@ -274,6 +309,40 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
} }
} }
[HttpPost("EditSupplier")]
public async Task<IActionResult> EditSupplier([FromBody] SupplierModel editedSupplier)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var supplier = await _centralDbContext.Suppliers.FindAsync(editedSupplier.SupplierId);
if (supplier == null)
{
return NotFound("Supplier is null");
}
try
{
supplier.SupplierCompName = editedSupplier.SupplierCompName;
supplier.SupplierAddress = editedSupplier.SupplierAddress;
supplier.SupplierPIC = editedSupplier.SupplierPIC;
supplier.SupplierEmail = editedSupplier.SupplierEmail;
supplier.SupplierPhoneNo = editedSupplier.SupplierPhoneNo;
_centralDbContext.Suppliers.Update(supplier);
await _centralDbContext.SaveChangesAsync();
return Json(supplier);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpDelete("DeleteSupplier/{id}")] [HttpDelete("DeleteSupplier/{id}")]
public async Task<IActionResult> DeleteSupplier(int id) public async Task<IActionResult> DeleteSupplier(int id)
{ {
@ -1263,7 +1332,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
Request.status = "Approved"; Request.status = "Approved";
Request.remarkMasterInv = request.remarkMasterInv; Request.remarkMasterInv = request.remarkMasterInv;
Request.approvalDate = DateTime.UtcNow; Request.approvalDate = DateTime.Now;
_centralDbContext.SaveChanges(); _centralDbContext.SaveChanges();
return Ok(new { success = true, message = "Request Approved Successfully", data = Request }); return Ok(new { success = true, message = "Request Approved Successfully", data = Request });
@ -1282,7 +1351,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
Request.status = "Rejected"; Request.status = "Rejected";
Request.remarkMasterInv = request.remarkMasterInv; Request.remarkMasterInv = request.remarkMasterInv;
Request.approvalDate = DateTime.UtcNow; Request.approvalDate = DateTime.Now;
_centralDbContext.SaveChanges(); _centralDbContext.SaveChanges();
return Ok(new { success = true, message="Request Rejected Successfully", data=Request }); return Ok(new { success = true, message="Request Rejected Successfully", data=Request });

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB