Update
This commit is contained in:
parent
815769fab7
commit
0636109ac9
@ -1044,44 +1044,43 @@
|
||||
this.loading = true;
|
||||
await this.fetchUser();
|
||||
try {
|
||||
// const token = localStorage.getItem('token'); // Get the token from localStorage
|
||||
const response = await fetch('/InvMainAPI/ItemMovementList', {
|
||||
method: 'POST', // Specify the HTTP method
|
||||
headers: {
|
||||
'Content-Type': 'application/json', // Set content type
|
||||
// 'Authorization': `Bearer ${token}` // Include the token in the headers
|
||||
}
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch item');
|
||||
}
|
||||
if (!response.ok) throw new Error('Failed to fetch item');
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if(this.currentRole == "Super Admin"){
|
||||
this.items = await response.json();
|
||||
this.initAllTables();
|
||||
|
||||
this.items = data;
|
||||
} else {
|
||||
const data = await response.json();
|
||||
|
||||
const myStationIds = this.stations
|
||||
.filter(s => s.stationPicID === this.currentUser.id)
|
||||
.map(s => s.stationId);
|
||||
|
||||
this.items = data.filter(item =>
|
||||
item.lastUser === this.currentUser.id ||
|
||||
item.toUser === this.currentUser.id ||
|
||||
item.lastStore === this.currentUser.store ||
|
||||
item.toStore === this.currentUser.store
|
||||
item.lastUser === this.currentUser.id ||
|
||||
item.toUser === this.currentUser.id ||
|
||||
(item.lastStation && myStationIds.includes(item.lastStation)) ||
|
||||
(item.toStation && myStationIds.includes(item.toStation)) ||
|
||||
item.lastStore === this.currentUser.store ||
|
||||
item.toStore === this.currentUser.store
|
||||
);
|
||||
|
||||
this.initAllTables();
|
||||
|
||||
}
|
||||
|
||||
this.initAllTables();
|
||||
|
||||
if (this.itemDatatable) {
|
||||
this.itemDatatable.clear().destroy();
|
||||
}
|
||||
this.initiateTable();
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error fetching item:', error);
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
},
|
||||
async fetchUser() {
|
||||
@ -1164,10 +1163,10 @@
|
||||
{ title: "Action", data: "action" },
|
||||
{ title: "Send Date", data: "sendDate" , render: this.formatDate.bind(this)},
|
||||
{ title: "From User", data: "lastUserName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "From Station", data: "lastStationName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "From Store", data: "lastStoreName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "Last Store", data: "toStoreName" },
|
||||
{ title: "Start Status", data: "toOther" },
|
||||
{ title: "Product Category", data: "productCategory" },
|
||||
@ -1189,10 +1188,10 @@
|
||||
{ title: "Receive Date", data: "receiveDate", render: this.formatDate.bind(this) },
|
||||
{ title: "Action", data: "action" },
|
||||
{ title: "From User", data: "lastUserName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "From Station", data: "lastStationName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "From Store", data: "lastStoreName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "Last Store", data: "toStoreName" },
|
||||
{ title: "Start Status", data: "toOther" },
|
||||
{ title: "Latest Status", data: "latestStatus" },
|
||||
@ -1205,12 +1204,16 @@
|
||||
});
|
||||
|
||||
this.assignStationDatatable = $("#assignStationDatatable").DataTable({
|
||||
data: this.items.filter((m) => m.action === "Assign" ),
|
||||
data: this.items.filter((m) =>
|
||||
m.action === "Assign" ||
|
||||
m.action === "Change" ||
|
||||
m.toStation !== null
|
||||
),
|
||||
columns: [
|
||||
{ title: "Unique Id", data: "id" },
|
||||
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
|
||||
{ title: "Product Code", data: "uniqueID" },
|
||||
{ title: "Assign Date", data: "sendDate", render: this.formatDate.bind(this) },
|
||||
{ title: "Assign Date", data: "sendDate", render: this.formatDate.bind(this) },
|
||||
{ title: "Action", data: "action" },
|
||||
{ title: "Station User PIC", data: "lastUserName" },
|
||||
{ title: "From Station", data: "lastStationName" },
|
||||
|
||||
@ -337,7 +337,7 @@
|
||||
<div class="form-group row d-flex align-items-center">
|
||||
<label class="col-sm-2 col-form-label">Quantity:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" v-model="quantity" required />
|
||||
<input type="number" class="form-control" v-model="quantity" min="1" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -426,11 +426,11 @@
|
||||
// Show the modal
|
||||
$('.modal').modal('hide');
|
||||
});
|
||||
$('.submit-button').on('click', function () {
|
||||
// Show the modal
|
||||
$('#rejectModal').modal('hide');
|
||||
$('#approveModal').modal('hide');
|
||||
});
|
||||
// $('.submit-button').on('click', function () {
|
||||
// Show the modal
|
||||
// $('#rejectModal').modal('hide');
|
||||
// $('#approveModal').modal('hide');
|
||||
// });
|
||||
});
|
||||
const app = Vue.createApp({
|
||||
data() {
|
||||
@ -536,7 +536,7 @@
|
||||
// Prepare data as JSON (No file upload)
|
||||
const requestDatas = {
|
||||
ProductId: this.productId,
|
||||
StationId: this.stationId,
|
||||
// StationId: this.stationId,
|
||||
UserId: this.userId,
|
||||
ProductCategory: this.productCategory,
|
||||
RequestQuantity: this.quantity,
|
||||
@ -720,8 +720,8 @@
|
||||
"columns": [
|
||||
{ "title": "Request ID", "data": "requestID" },
|
||||
{ "title": "Product", "data": "productName", "render": renderDocument },
|
||||
{ "title": "From Store", "data": "fromStoreItem" },
|
||||
{ "title": "Assign Store", "data": "assignStoreItem" },
|
||||
{ "title": "From Store", "data": "fromStoreName" },
|
||||
{ "title": "Assign Store", "data": "assignStoreName" },
|
||||
{ "title": "Product Category", "data": "productCategory" },
|
||||
{ "title": "Request Quantity", "data": "requestQuantity" },
|
||||
{ "title": "Document/Picture", "data": "document", "render": renderDocument },
|
||||
@ -748,8 +748,8 @@
|
||||
{ "title": "Action", "data": "requestID", "render": renderActionButtons, "className": "align-middle" },
|
||||
{ "title": "Product", "data": "productName", "render": renderDocument },
|
||||
{ "title": "Requested by User", "data": "userName" },
|
||||
{ "title": "From Store", "data": "fromStoreItem" },
|
||||
{ "title": "Assign Store", "data": "assignStoreItem" },
|
||||
{ "title": "From Store", "data": "fromStoreName" },
|
||||
{ "title": "Assign Store", "data": "assignStoreName" },
|
||||
{ "title": "Product Category", "data": "productCategory" },
|
||||
{ "title": "Request Quantity", "data": "requestQuantity" },
|
||||
{ "title": "Document/Picture", "data": "document", "render": renderDocument },
|
||||
@ -766,8 +766,8 @@
|
||||
{ "title": "Request ID", "data": "requestID" },
|
||||
{ "title": "Product", "data": "productName", "render": renderDocument },
|
||||
{ "title": "Requested by User", "data": "userName" },
|
||||
{ "title": "From Store", "data": "fromStoreItem" },
|
||||
{ "title": "Assign Store", "data": "assignStoreItem" },
|
||||
{ "title": "From Store", "data": "fromStoreName" },
|
||||
{ "title": "Assign Store", "data": "assignStoreName" },
|
||||
{ "title": "Product Category", "data": "productCategory" },
|
||||
{ "title": "Request Quantity", "data": "requestQuantity" },
|
||||
{ "title": "Document/Picture", "data": "document", "render": renderDocument },
|
||||
@ -976,107 +976,79 @@
|
||||
}
|
||||
},
|
||||
async approveRequest() {
|
||||
// if (!confirm("Are you sure you want to approve this request?")) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!this.approveremark || this.approveremark.trim() === "") {
|
||||
alert("Please enter a remark before approving this request.");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
RemarkMasterInv: this.rejectremark,
|
||||
RemarkMasterInv: this.approveremark,
|
||||
};
|
||||
|
||||
};
|
||||
let requestID = this.currentrequestID;
|
||||
this.loading = true;
|
||||
|
||||
let requestID = this.currentrequestID;
|
||||
try {
|
||||
const response = await fetch(`/InvMainAPI/ApproveRequest/${requestID}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(formData)
|
||||
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
alert(result.message);
|
||||
|
||||
//static update
|
||||
const row = $(`.approve-btn[data-id="${requestID}"]`).closest('tr');
|
||||
let rowData = this.requestDatatable.row(row).data();
|
||||
|
||||
// Update the status and remark
|
||||
rowData.status = "Approved";
|
||||
|
||||
// Remove row from requestDatatable
|
||||
this.requestDatatable.row(row).remove().draw();
|
||||
|
||||
// Add updated row to settledrequestDatatable
|
||||
this.settledrequestDatatable.row.add(rowData).draw();
|
||||
|
||||
|
||||
this.approveremark = "";
|
||||
this.fetchRequest();
|
||||
} else {
|
||||
alert(result.message);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error("Error approving request:", error);
|
||||
// alert("An error occurred while approving the request.");
|
||||
}
|
||||
finally {
|
||||
this.loading = false;
|
||||
$('#approveModal').modal('hide');
|
||||
}
|
||||
},
|
||||
|
||||
async rejectRequest() {
|
||||
if (!this.rejectremark || this.rejectremark.trim() === "") {
|
||||
alert("Please enter a remark before rejecting this request.");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
RemarkMasterInv: this.rejectremark,
|
||||
|
||||
};
|
||||
const formData = {
|
||||
RemarkMasterInv: this.rejectremark,
|
||||
};
|
||||
|
||||
let requestID = this.currentrequestID;
|
||||
let requestID = this.currentrequestID;
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
|
||||
const response = await fetch(`/InvMainAPI/RejectRequest/${requestID}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
// 'Authorization': `Bearer ${this.token}`
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(formData)
|
||||
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// If the form submission was successful, display a success message
|
||||
// alert('Success!', 'Request has been Rejected.', 'success');
|
||||
|
||||
const row = $(`.approve-btn[data-id="${requestID}"]`).closest('tr');
|
||||
let rowData = this.requestDatatable.row(row).data();
|
||||
|
||||
// Update the status and remark
|
||||
rowData.status = "Rejected";
|
||||
rowData.remarkMasterInv = this.rejectremark;
|
||||
|
||||
// Remove row from requestDatatable
|
||||
this.requestDatatable.row(row).remove().draw();
|
||||
|
||||
// Add updated row to settledrequestDatatable
|
||||
this.settledrequestDatatable.row.add(rowData).draw();
|
||||
|
||||
|
||||
alert('Request has been Rejected.');
|
||||
this.rejectremark = "";
|
||||
this.fetchRequest();
|
||||
} 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');
|
||||
}
|
||||
finally {
|
||||
this.loading = false;
|
||||
$('#rejectModal').modal('hide');
|
||||
}
|
||||
},
|
||||
async rejectRequestModal(requestID, remark) {
|
||||
|
||||
@ -280,8 +280,10 @@
|
||||
<button type="button" v-on:click="ReturnMessage" class="btn btn-warning m-2" style="width: 200px; padding: 10px;">
|
||||
<i class="fas fa-undo me-2"></i>Return Item
|
||||
</button>
|
||||
|
||||
<button type="button" v-on:click="StationMessage" class="btn btn-primary m-2" style="width: 200px; padding: 10px;">
|
||||
<i class="fas fa-broadcast-tower me-2"></i>Deploy To Station
|
||||
<i class="fas fa-broadcast-tower me-2"></i>
|
||||
{{ (thisItem?.currentStationId || thisItem?.toStationId) ? "Change Station" : "Deploy To Station" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -353,11 +355,24 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">To User:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="dropdown">
|
||||
<select class="btn btn-primary dropdown-toggle col-md-10" v-model="selectedUser" required style="width: 100%;">
|
||||
<option class="btn-light" value="" disabled selected>Select User</option>
|
||||
<option class="btn-light" v-for="(user, index) in userlist" :key="index" :value="user.id">{{user.fullName}}</option>
|
||||
</select>
|
||||
<div class="custom-searchable-dropdown" style="position: relative;" @@click.stop>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" v-model="userSearchQuery"
|
||||
placeholder="Search and Select User..."
|
||||
@@focus ="userDropdownOpen = true" />
|
||||
<button type="button" class="btn btn-primary" @@click ="userDropdownOpen = !userDropdownOpen">
|
||||
{{ userDropdownOpen ? '▲' : '▼' }}
|
||||
</button>
|
||||
</div>
|
||||
<ul class="list-group shadow-sm" v-if="userDropdownOpen" style="position: absolute; z-index: 1000; width: 100%; max-height: 200px; overflow-y: auto;">
|
||||
<li class="list-group-item text-muted" v-if="searchedUserList.length === 0">No users found</li>
|
||||
<li class="list-group-item list-group-item-action"
|
||||
v-for="(user, index) in searchedUserList" :key="index"
|
||||
@@click ="selectUser(user.id, user.fullName)"
|
||||
style="cursor: pointer;">
|
||||
{{ user.fullName }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -411,12 +426,24 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">To Station:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="dropdown">
|
||||
<select class="btn btn-primary dropdown-toggle col-md-10" v-model="selectedStation" required style="width: 100%;">
|
||||
<option class="btn-light" value="" disabled selected>Select Station</option>
|
||||
<option class="btn-light" v-for="(station, index) in stationlist" :key="index" :value="station.stationId">{{station.stationName}}</option>
|
||||
</select>
|
||||
|
||||
<div class="custom-searchable-dropdown" style="position: relative;" @@click.stop>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" v-model="stationSearchQuery"
|
||||
placeholder="Search and Select Station..."
|
||||
@@focus ="stationDropdownOpen = true" />
|
||||
<button type="button" class="btn btn-primary" @@click ="stationDropdownOpen = !stationDropdownOpen">
|
||||
{{ stationDropdownOpen ? '▲' : '▼' }}
|
||||
</button>
|
||||
</div>
|
||||
<ul class="list-group shadow-sm" v-if="stationDropdownOpen" style="position: absolute; z-index: 1000; width: 100%; max-height: 200px; overflow-y: auto;">
|
||||
<li class="list-group-item text-muted" v-if="searchedStationListForDropdown.length === 0">No stations found</li>
|
||||
<li class="list-group-item list-group-item-action"
|
||||
v-for="(station, index) in searchedStationListForDropdown" :key="index"
|
||||
@@click ="selectStation(station.stationId, station.stationName)"
|
||||
style="cursor: pointer;">
|
||||
{{ station.stationName }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -538,11 +565,24 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">To Supplier:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="dropdown">
|
||||
<select class="btn btn-primary dropdown-toggle col-md-10" v-model="selectedSupplier" required style="width: 100%;">
|
||||
<option class="btn-light" value="" disabled selected>Select Supplier</option>
|
||||
<option class="btn-light" v-for="(supplier, index) in supplierlist" :key="index" :value="supplier.supplierCompName">{{supplier.supplierCompName}}</option>
|
||||
</select>
|
||||
<div class="custom-searchable-dropdown" style="position: relative;" @@click.stop>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" v-model="supplierSearchQuery"
|
||||
placeholder="Search and Select Supplier..."
|
||||
@@focus ="supplierDropdownOpen = true" />
|
||||
<button type="button" class="btn btn-primary" @@click ="supplierDropdownOpen = !supplierDropdownOpen">
|
||||
{{ supplierDropdownOpen ? '▲' : '▼' }}
|
||||
</button>
|
||||
</div>
|
||||
<ul class="list-group shadow-sm" v-if="supplierDropdownOpen" style="position: absolute; z-index: 1000; width: 100%; max-height: 200px; overflow-y: auto;">
|
||||
<li class="list-group-item text-muted" v-if="searchedSupplierList.length === 0">No suppliers found</li>
|
||||
<li class="list-group-item list-group-item-action"
|
||||
v-for="(supplier, index) in searchedSupplierList" :key="index"
|
||||
@@click ="selectSupplier(supplier.supplierCompName)"
|
||||
style="cursor: pointer;">
|
||||
{{ supplier.supplierCompName }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -664,7 +704,7 @@
|
||||
<div class="form-group row mb-3">
|
||||
<label class="col-sm-4 col-form-label">Remark:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" v-model="remark" required />
|
||||
<input type="text" class="form-control" v-model="remark"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-3">
|
||||
@ -683,43 +723,51 @@
|
||||
</div>
|
||||
|
||||
@* Model Deploy to Station *@
|
||||
<div class="modal fade" id="stationMessageModal" tabindex="-1" role="dialog">
|
||||
<div class="modal fade" id="stationMessageModal" tabindex="-1" role="dialog" aria-labelledby="stationModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Deploy to Station</h5>
|
||||
<button type="button" class="close closeModal" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
<h5 class="modal-title" id="stationModalLabel">
|
||||
{{ (thisItem?.currentStationId || thisItem?.toStationId) ? "Change Station" : "Deploy to Station" }}
|
||||
</h5>
|
||||
<button type="button" class="close closeModal" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form v-on:submit.prevent="confirmDeployStation">
|
||||
|
||||
<div class="form-group row mb-3">
|
||||
<label class="col-sm-4 col-form-label">Select Station:</label>
|
||||
<label class="col-sm-4 col-form-label">Deploy Station : </label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-select" v-model="selectedStation" required>
|
||||
<option value="" disabled>-- Select Station --</option>
|
||||
<option v-for="station in filteredStationList" :key="station.stationId" :value="station.stationId">
|
||||
<select class="btn btn-primary dropdown-toggle col-md-10" v-model="selectedStation" required>
|
||||
<option class="btn-light" value="" disabled selected>-- Select Station --</option>
|
||||
<option v-if="filteredStationList.length === 0" class="btn-light" disabled>No Station Assigned to You</option>
|
||||
<option class="btn-light" v-for="station in filteredStationList" :key="station.stationId" :value="station.stationId">
|
||||
{{ station.stationName }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row mb-3">
|
||||
<label class="col-sm-4 col-form-label">Remark:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" v-model="remark" placeholder="Optional" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row mb-3">
|
||||
<label class="col-sm-4 col-form-label">Consignment Note:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="file" class="form-control-file" v-on:change="handleFileUpload" accept="image/*, application/pdf" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-success">Confirm Deployment</button>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ (thisItem?.currentStationId || thisItem?.toStationId) ? "Confirm Change" : "Confirm Deployment" }}
|
||||
</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -794,7 +842,16 @@
|
||||
videoInputDevices: [],
|
||||
selectedCameraId: null,
|
||||
scanStartTime: null,
|
||||
scanTime: null
|
||||
scanTime: null,
|
||||
|
||||
supplierDropdownOpen: false,
|
||||
supplierSearchQuery: "",
|
||||
|
||||
userDropdownOpen: false,
|
||||
userSearchQuery: "",
|
||||
|
||||
stationDropdownOpen: false,
|
||||
stationSearchQuery: "",
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -875,6 +932,22 @@
|
||||
station.stationPicID == this.currentUser.id
|
||||
);
|
||||
},
|
||||
|
||||
searchedUserList() {
|
||||
if (!this.userlist) return [];
|
||||
if (!this.userSearchQuery) return this.userlist;
|
||||
return this.userlist.filter(u => u.fullName.toLowerCase().includes(this.userSearchQuery.toLowerCase()));
|
||||
},
|
||||
searchedSupplierList() {
|
||||
if (!this.supplierlist) return [];
|
||||
if (!this.supplierSearchQuery) return this.supplierlist;
|
||||
return this.supplierlist.filter(s => s.supplierCompName.toLowerCase().includes(this.supplierSearchQuery.toLowerCase()));
|
||||
},
|
||||
searchedStationListForDropdown() {
|
||||
if (!this.stationlist) return [];
|
||||
if (!this.stationSearchQuery) return this.stationlist;
|
||||
return this.stationlist.filter(s => s.stationName.toLowerCase().includes(this.stationSearchQuery.toLowerCase()));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// Split Url dapatkan unique ID Je
|
||||
@ -904,6 +977,27 @@
|
||||
this.error = message;
|
||||
},
|
||||
|
||||
selectUser(userId, userName) {
|
||||
this.selectedUser = userId;
|
||||
this.userSearchQuery = userName;
|
||||
this.userDropdownOpen = false;
|
||||
},
|
||||
selectSupplier(supplierName) {
|
||||
this.selectedSupplier = supplierName;
|
||||
this.supplierSearchQuery = supplierName;
|
||||
this.supplierDropdownOpen = false;
|
||||
},
|
||||
selectStation(stationId, stationName) {
|
||||
this.selectedStation = stationId;
|
||||
this.stationSearchQuery = stationName;
|
||||
this.stationDropdownOpen = false;
|
||||
},
|
||||
closeAllDropdowns() {
|
||||
this.userDropdownOpen = false;
|
||||
this.supplierDropdownOpen = false;
|
||||
this.stationDropdownOpen = false;
|
||||
},
|
||||
|
||||
//Setting Camera
|
||||
async onCameraReady(videoElement) {
|
||||
|
||||
@ -1189,8 +1283,8 @@
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
this.resetForm();
|
||||
window.location.href = '/Inventory/InventoryMaster/ItemMovement';
|
||||
this.resetScanner();
|
||||
// window.location.href = '/Inventory/InventoryMaster/ItemMovement';
|
||||
} else {
|
||||
throw new Error('Failed to submit form.');
|
||||
}
|
||||
@ -1276,7 +1370,9 @@
|
||||
this.cancelRemark = "";
|
||||
this.quantity = 1; // Reset quantity when the form is reset
|
||||
this.maxQuantity = null; // Clear maxQuantity on form reset
|
||||
|
||||
this.userSearchQuery = "";
|
||||
this.supplierSearchQuery = "";
|
||||
this.stationSearchQuery = "";
|
||||
|
||||
},
|
||||
|
||||
@ -1585,7 +1681,7 @@
|
||||
alert('Success! Item has been deployed to the station.');
|
||||
$('#stationMessageModal').modal('hide');
|
||||
this.resetScanner();
|
||||
window.location.href = '/Inventory/InventoryMaster/ItemMovement';
|
||||
// window.location.href = '/Inventory/InventoryMaster/ItemMovement';
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
throw new Error(errorText || 'Failed to deploy station.');
|
||||
|
||||
@ -963,6 +963,70 @@
|
||||
}
|
||||
},
|
||||
|
||||
// initAllTables() {
|
||||
// if (this.itemMovementNotCompleteDatatable) {
|
||||
// this.itemMovementNotCompleteDatatable.destroy();
|
||||
// }
|
||||
// if (this.itemMovementCompleteDatatable) {
|
||||
// this.itemMovementCompleteDatatable.destroy();
|
||||
// }
|
||||
// if (this.assignStationDatatable) {
|
||||
// this.assignStationDatatable.destroy();
|
||||
// }
|
||||
|
||||
// Get latest movement per uniqueID after filtering
|
||||
// function getLatestMovements(data) {
|
||||
// let latestMovements = {};
|
||||
// data.forEach(movement => {
|
||||
// let id = movement.uniqueID;
|
||||
// if (!latestMovements[id] || latestMovements[id].id < movement.id) {
|
||||
// latestMovements[id] = movement;
|
||||
// }
|
||||
// });
|
||||
// return Object.values(latestMovements);
|
||||
// }
|
||||
|
||||
// Filter movements based on conditions
|
||||
// function filterMovements(movements) {
|
||||
// let stopIndex = movements.findIndex(m =>
|
||||
// m.toOther === 'Return' && m.movementComplete == 1
|
||||
// );
|
||||
|
||||
// let nextIndex = movements.findIndex(m =>
|
||||
// m.latestStatus === 'Ready To Deploy' && m.movementComplete == 1
|
||||
// );
|
||||
|
||||
// if (stopIndex !== -1) {
|
||||
// movements = movements.slice(0, stopIndex);
|
||||
// }
|
||||
|
||||
// if (nextIndex !== -1) {
|
||||
// movements = movements.slice(0, nextIndex);
|
||||
// }
|
||||
|
||||
// return movements;
|
||||
// }
|
||||
|
||||
// let latestMovements = getLatestMovements(this.itemMovements);
|
||||
|
||||
// let notCompleteData = [];
|
||||
// let completeData = [];
|
||||
// let completeStationData = [];
|
||||
|
||||
// latestMovements.forEach(movement => {
|
||||
// let filteredMovements = filterMovements([movement]);
|
||||
|
||||
// if (filteredMovements.length > 0) {
|
||||
// if (movement.movementComplete == 0) {
|
||||
// notCompleteData.push(movement);
|
||||
// } else if (movement.movementComplete == 1 && movement.action !== "Assign") {
|
||||
// completeData.push(movement);
|
||||
// } else {
|
||||
// completeStationData.push(movement);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
initAllTables() {
|
||||
if (this.itemMovementNotCompleteDatatable) {
|
||||
this.itemMovementNotCompleteDatatable.destroy();
|
||||
@ -974,55 +1038,39 @@
|
||||
this.assignStationDatatable.destroy();
|
||||
}
|
||||
|
||||
// Get latest movement per uniqueID after filtering
|
||||
function getLatestMovements(data) {
|
||||
let latestMovements = {};
|
||||
data.forEach(movement => {
|
||||
let id = movement.uniqueID;
|
||||
if (!latestMovements[id] || latestMovements[id].id < movement.id) {
|
||||
latestMovements[id] = movement;
|
||||
}
|
||||
});
|
||||
return Object.values(latestMovements);
|
||||
}
|
||||
|
||||
// Filter movements based on conditions
|
||||
function filterMovements(movements) {
|
||||
let stopIndex = movements.findIndex(m =>
|
||||
m.toOther === 'Return' && m.movementComplete == 1
|
||||
);
|
||||
|
||||
let nextIndex = movements.findIndex(m =>
|
||||
m.latestStatus === 'Ready To Deploy' && m.movementComplete == 1
|
||||
);
|
||||
|
||||
if (stopIndex !== -1) {
|
||||
movements = movements.slice(0, stopIndex);
|
||||
}
|
||||
|
||||
if (nextIndex !== -1) {
|
||||
movements = movements.slice(0, nextIndex);
|
||||
}
|
||||
|
||||
return movements;
|
||||
}
|
||||
|
||||
let latestMovements = getLatestMovements(this.itemMovements);
|
||||
|
||||
let notCompleteData = [];
|
||||
let completeData = [];
|
||||
let completeStationData = [];
|
||||
|
||||
latestMovements.forEach(movement => {
|
||||
let filteredMovements = filterMovements([movement]);
|
||||
|
||||
let latestMovementsMap = {};
|
||||
|
||||
if (filteredMovements.length > 0) {
|
||||
this.itemMovements.forEach(movement => {
|
||||
let id = movement.uniqueID;
|
||||
|
||||
|
||||
if (!latestMovementsMap[id] || latestMovementsMap[id].id < movement.id) {
|
||||
latestMovementsMap[id] = movement;
|
||||
}
|
||||
|
||||
// Push ALL station history to the Assign Station table!
|
||||
if (movement.movementComplete == 1 && (movement.action === "Assign" || movement.action === "Change" || movement.toStation !== null)) {
|
||||
completeStationData.push(movement);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let latestMovements = Object.values(latestMovementsMap);
|
||||
|
||||
latestMovements.forEach(movement => {
|
||||
let isReturned = movement.toOther === 'Return' && movement.movementComplete == 1;
|
||||
let isReady = movement.latestStatus === 'Ready To Deploy' && movement.movementComplete == 1;
|
||||
|
||||
if (!isReturned && !isReady) {
|
||||
if (movement.movementComplete == 0) {
|
||||
notCompleteData.push(movement);
|
||||
} else if (movement.movementComplete == 1 && movement.action !== "Assign") {
|
||||
completeData.push(movement);
|
||||
} else {
|
||||
completeStationData.push(movement);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1038,10 +1086,10 @@
|
||||
{ title: "Send Date", data: "sendDate", render: this.formatDate.bind(this) },
|
||||
{ title: "Start Status", data: "toOther" },
|
||||
{ title: "From User", data: "lastUserName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "From Station", data: "lastStationName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "From Store", data: "lastStoreName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "Last Store", data: "toStoreName" },
|
||||
{ title: "Quantity", data: "quantity" },
|
||||
{ title: "Note", data: "consignmentNote", render: renderFile },
|
||||
@ -1063,10 +1111,10 @@
|
||||
{ title: "Start Status", data: "toOther" },
|
||||
{ title: "Latest Status", data: "latestStatus" },
|
||||
{ title: "From User", data: "lastUserName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "From Station", data: "lastStationName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "From Store", data: "lastStoreName" },
|
||||
{ title: "Last User", data: "toUserName" },
|
||||
{ title: "Last Station", data: "toStationName" },
|
||||
{ title: "Last Store", data: "toStoreName" },
|
||||
{ title: "Qty", data: "quantity" },
|
||||
{ title: "Note", data: "consignmentNote", render: renderFile },
|
||||
|
||||
@ -196,7 +196,7 @@
|
||||
<div class="form-group row d-flex align-items-center">
|
||||
<label class="col-sm-2 col-form-label">Quantity:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" v-model="quantity" required />
|
||||
<input type="number" class="form-control" v-model="quantity" min="1" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -114,7 +114,9 @@
|
||||
<div class="col-12 mb-3">
|
||||
<p class="h5 fw-bold">
|
||||
<i class="fas fa-user-tie me-2 text-secondary"></i>PIC:
|
||||
<span class="text-muted">{{ thisItem.currentUserFullName || thisItem.currentUser || 'N/A' }}</span>
|
||||
<span class="text-muted">
|
||||
{{ currentUser?.fullName || 'N/A' }}
|
||||
</span>
|
||||
@* <span class="text-muted">{{thisItem.currentUserFullName}}</span> *@
|
||||
</p>
|
||||
</div>
|
||||
@ -123,7 +125,7 @@
|
||||
<div class="col-12 mb-3">
|
||||
<p class="h5 fw-bold">
|
||||
<i class="fas fa-user-tie me-2 text-secondary"></i>Station:
|
||||
<span class="text-muted">{{thisItem.currentStation || 'No Station Deploy (Self Assign)' }}</span>
|
||||
<span class="text-muted">{{ thisItem.toStationName || 'No Station Deploy (Self Assign)' }}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -135,14 +137,25 @@
|
||||
<i class="fas fa-info-circle me-2"></i>Receiver Information
|
||||
</h5>
|
||||
<ul class="list-group list-group-flush">
|
||||
<!-- User -->
|
||||
<li class="list-group-item">
|
||||
|
||||
<li class="list-group-item" v-if="thisItem.toUser || thisItem.toUserFullName">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<span class="fw-bold">
|
||||
<i class="fas fa-user me-2 text-secondary"></i>User:
|
||||
</span>
|
||||
<span class="text-muted text-end" style="max-width: 70%; word-wrap: break-word;">
|
||||
{{ thisItem.currentUserFullName || thisItem.currentUser || 'N/A' }}
|
||||
{{ thisItem.toUserFullName || thisItem.toUserName || 'N/A' }}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="list-group-item" v-if="thisItem.toStationId || thisItem.toStation">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<span class="fw-bold">
|
||||
<i class="fas fa-charging-station me-2 text-secondary"></i>Station:
|
||||
</span>
|
||||
<span class="text-muted text-end">
|
||||
{{ thisItem.toStationName || thisItem.toStation || 'N/A' }}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
@ -159,13 +172,24 @@
|
||||
<i class="fas fa-info-circle me-2"></i>Sender Information
|
||||
</h5>
|
||||
<ul class="list-group list-group-flush">
|
||||
<!-- User -->
|
||||
<li class="list-group-item">
|
||||
|
||||
<li class="list-group-item" v-if="thisItem.lastStation">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<span class="fw-bold">
|
||||
<i class="fas fa-charging-station me-2 text-secondary"></i>Station:
|
||||
</span>
|
||||
<span class="text-muted text-end">
|
||||
{{ thisItem.currentStation || 'N/A' }}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="list-group-item" v-else-if="thisItem.lastUser">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<span class="fw-bold">
|
||||
<i class="fas fa-user me-2 text-secondary"></i>User:
|
||||
</span>
|
||||
<span class="text-muted text-end" style="max-width: 70%; word-wrap: break-word;">
|
||||
<span class="text-muted text-end">
|
||||
{{ thisItem.currentUserFullName || thisItem.currentUser || 'N/A' }}
|
||||
</span>
|
||||
</div>
|
||||
@ -480,7 +504,7 @@
|
||||
|
||||
ToOther: "Delivered",
|
||||
Action: "Assign",
|
||||
Quantity: this.thisItem.quantity || 1,
|
||||
Quantity: this.thisItem.movementQuantity || 1,
|
||||
Remark: this.remark,
|
||||
ConsignmentNote: this.consignmentNote,
|
||||
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||
|
||||
@ -50,7 +50,7 @@ namespace PSTW_CentralSystem.Controllers.API
|
||||
.Select(u => new
|
||||
{
|
||||
id = u.Id,
|
||||
email = u.NormalizedEmail,
|
||||
fullName = u.FullName,
|
||||
company = u.Department!.Company!.CompanyName,
|
||||
department = u.Department,
|
||||
role = userRole,
|
||||
|
||||
@ -970,6 +970,9 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
||||
ToStoreName = item.Movement?.NextStore?.StoreName,
|
||||
LastStation = item.Movement?.LastStation,
|
||||
ToStationName = item.Movement?.NextStation?.StationName,
|
||||
|
||||
ToUserFullName = item.Movement?.NextUser?.FullName,
|
||||
|
||||
item.Movement?.ToOther,
|
||||
item.Movement?.LatestStatus,
|
||||
item.Movement?.ToUser,
|
||||
@ -1330,6 +1333,12 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
||||
return NotFound("Item movement record not found.");
|
||||
}
|
||||
|
||||
// Fetch the StationIds where the user is the PIC
|
||||
var userStationIds = await _centralDbContext.Stations
|
||||
.Where(s => s.StationPicID == user.Id)
|
||||
.Select(s => s.StationId)
|
||||
.ToListAsync();
|
||||
|
||||
var itemMovementUser = await _centralDbContext.ItemMovements
|
||||
.Include(i => i.Item)
|
||||
.ThenInclude(i => i.Product)
|
||||
@ -1339,45 +1348,47 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
||||
.Include(i => i.NextStore)
|
||||
.Include(i => i.NextStation)
|
||||
.Include(i => i.NextUser)
|
||||
.Where(i => i.LastUser == user.Id || i.ToUser == user.Id)
|
||||
.Where(i => i.LastUser == user.Id ||
|
||||
i.ToUser == user.Id ||
|
||||
(i.LastStation != null && userStationIds.Contains(i.LastStation.Value)) ||
|
||||
(i.ToStation != null && userStationIds.Contains(i.ToStation.Value)))
|
||||
.ToListAsync();
|
||||
|
||||
return Json(itemMovementUser.Select(i => new
|
||||
{
|
||||
i.Id,
|
||||
i.ItemId,
|
||||
i.LastStation,
|
||||
i.LastStore,
|
||||
i.LastUser,
|
||||
UniqueID = i.Item?.UniqueID,
|
||||
ProductName = i.Item?.Product?.ProductName,
|
||||
ProductImage = i.Item?.Product?.ImageProduct,
|
||||
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.ToUser,
|
||||
i.ToStore,
|
||||
i.ToStation,
|
||||
i.LatestStatus,
|
||||
i.receiveDate,
|
||||
i.MovementComplete
|
||||
}));
|
||||
{
|
||||
i.Id,
|
||||
i.ItemId,
|
||||
i.LastStation,
|
||||
i.LastStore,
|
||||
i.LastUser,
|
||||
UniqueID = i.Item?.UniqueID,
|
||||
ProductName = i.Item?.Product?.ProductName,
|
||||
ProductImage = i.Item?.Product?.ImageProduct,
|
||||
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.ToUser,
|
||||
i.ToStore,
|
||||
i.ToStation,
|
||||
i.LatestStatus,
|
||||
i.receiveDate,
|
||||
i.MovementComplete
|
||||
}));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -1622,12 +1633,20 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
||||
|
||||
var masterDeptId = masterUser.departmentId;
|
||||
|
||||
var myStoreIds = await _centralDbContext.InventoryMasters
|
||||
.Where(im => im.UserId == currentUserId)
|
||||
.Select(im => im.StoreId)
|
||||
.ToListAsync();
|
||||
|
||||
// 4. Fetch requests where the Requester belongs to the same department
|
||||
var itemRequestList = await _centralDbContext.Requests
|
||||
.Include(i => i.Product)
|
||||
.Include(i => i.User)
|
||||
.Include(i => i.Station)
|
||||
.Where(i => i.User.departmentId == masterDeptId)
|
||||
.Include(i => i.Store)
|
||||
.Include(i => i.Stores)
|
||||
.Where(i => i.User.departmentId == masterDeptId ||
|
||||
(i.fromStoreItem.HasValue && myStoreIds.Contains(i.fromStoreItem.Value)))
|
||||
.ToListAsync();
|
||||
|
||||
return Json(itemRequestList.Select(i => new
|
||||
@ -1649,7 +1668,9 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
||||
i.remarkMasterInv,
|
||||
i.remarkUser,
|
||||
i.assignStoreItem,
|
||||
i.fromStoreItem
|
||||
i.fromStoreItem,
|
||||
fromStoreName = i.Store?.StoreName ?? "N/A",
|
||||
assignStoreName = i.Stores?.StoreName ?? "N/A",
|
||||
}));
|
||||
}
|
||||
|
||||
@ -2113,6 +2134,18 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
||||
stationMovement.ConsignmentNote = "/" + relativePath;
|
||||
}
|
||||
|
||||
// Close the previous active movement record
|
||||
var currentItem = await _centralDbContext.Items.FindAsync(stationMovement.ItemId);
|
||||
if (currentItem != null && currentItem.MovementId.HasValue)
|
||||
{
|
||||
var previousMovement = await _centralDbContext.ItemMovements.FindAsync(currentItem.MovementId.Value);
|
||||
if (previousMovement != null)
|
||||
{
|
||||
previousMovement.MovementComplete = true; // Close the old history
|
||||
_centralDbContext.ItemMovements.Update(previousMovement);
|
||||
}
|
||||
}
|
||||
|
||||
_centralDbContext.ItemMovements.Add(stationMovement);
|
||||
await _centralDbContext.SaveChangesAsync();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user