Update Last/To
This commit is contained in:
parent
2735cfdf99
commit
c48f61f40e
@ -1166,7 +1166,9 @@
|
|||||||
{ title: "From User", data: "lastUserName" },
|
{ title: "From User", data: "lastUserName" },
|
||||||
{ title: "Last User", data: "toUserName" },
|
{ title: "Last User", data: "toUserName" },
|
||||||
{ title: "From Station", data: "lastStationName" },
|
{ title: "From Station", data: "lastStationName" },
|
||||||
|
{ title: "Last Station", data: "toStationName" },
|
||||||
{ title: "From Store", data: "lastStoreName" },
|
{ title: "From Store", data: "lastStoreName" },
|
||||||
|
{ title: "Last Store", data: "toStoreName" },
|
||||||
{ title: "Start Status", data: "toOther" },
|
{ title: "Start Status", data: "toOther" },
|
||||||
{ title: "Product Category", data: "productCategory" },
|
{ title: "Product Category", data: "productCategory" },
|
||||||
{ title: "Qty", data: "quantity" },
|
{ title: "Qty", data: "quantity" },
|
||||||
|
|||||||
@ -97,6 +97,37 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card shadow-sm border-0">
|
<div class="card shadow-sm border-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<h5 class="card-title mb-4 text-primary">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>Current Information
|
||||||
|
</h5>
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<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' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
<span class="fw-bold">
|
||||||
|
<i class="mdi mdi-factory me-2 text-secondary"></i>Store:
|
||||||
|
</span>
|
||||||
|
<span class="text-muted">{{ thisItem.currentStore || 'N/A' }}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
<span class="fw-bold">
|
||||||
|
<i class="fas fa-map-marker-alt me-2 text-secondary"></i>Station:
|
||||||
|
</span>
|
||||||
|
<span class="text-muted">{{ thisItem.currentStation || 'N/A' }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@* <div class="card-body">
|
||||||
<h5 class="card-title mb-4 text-primary">
|
<h5 class="card-title mb-4 text-primary">
|
||||||
<i class="fas fa-info-circle me-2"></i>Current Information
|
<i class="fas fa-info-circle me-2"></i>Current Information
|
||||||
</h5>
|
</h5>
|
||||||
@ -126,7 +157,7 @@
|
|||||||
<span class="text-muted">{{ thisItem.lastStationName || 'N/A' }}</span>
|
<span class="text-muted">{{ thisItem.lastStationName || 'N/A' }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div> *@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -165,7 +196,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="itemlateststatus == 'On Delivery' && this.thisItem.lastUser == this.currentUser.id">
|
<div v-if="itemlateststatus == 'On Delivery' && (this.thisItem.lastUser == this.currentUser.id || this.thisItem.lastStore == this.currentUser.store)">
|
||||||
<h3 class="register-heading">Cancel Item Movement</h3>
|
<h3 class="register-heading">Cancel Item Movement</h3>
|
||||||
<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">
|
||||||
@ -194,7 +225,23 @@
|
|||||||
|
|
||||||
<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;">
|
||||||
Receive Item
|
Receive Item for Store
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="itemlateststatus == 'On Delivery' && isStationPIC">
|
||||||
|
<h2 class="register-heading">Receive Item</h2>
|
||||||
|
<div class="col-sm-3"></div>
|
||||||
|
<div class="col-sm-6 offset-sm-3">
|
||||||
|
<form v-on:submit.prevent="receiveItemMovement" data-aos="fade-right">
|
||||||
|
<div class="row register-form">
|
||||||
|
<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;">
|
||||||
|
Receive for Station
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -227,7 +274,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@* Inv Master Return Item & Deploy to Station*@
|
@* Inv Master Return Item & Deploy to Station*@
|
||||||
<div v-if="itemlateststatus == 'Delivered' && thisItem.toUser == currentUser.id">
|
<div v-if="itemlateststatus == 'Delivered' && (this.thisItem.toUser == this.currentUser.id || this.thisItem.toStore == this.currentUser.store || this.isStationPIC )">
|
||||||
<h2 class="text-center register-heading">Item Actions</h2>
|
<h2 class="text-center register-heading">Item Actions</h2>
|
||||||
<div class="col-sm-12 d-flex justify-content-center mt-3">
|
<div class="col-sm-12 d-flex justify-content-center mt-3">
|
||||||
<button type="button" v-on:click="ReturnMessage" class="btn btn-warning m-2" style="width: 200px; padding: 10px;">
|
<button type="button" v-on:click="ReturnMessage" class="btn btn-warning m-2" style="width: 200px; padding: 10px;">
|
||||||
@ -817,6 +864,17 @@
|
|||||||
return isPIC;
|
return isPIC;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
isStationPIC() {
|
||||||
|
if (!this.thisItem || !this.stationlist || !this.currentUser) return false;
|
||||||
|
|
||||||
|
// Now this.thisItem.toStation will have the ID from the backend
|
||||||
|
const targetStationId = this.thisItem.toStation;
|
||||||
|
|
||||||
|
return this.stationlist.some(station =>
|
||||||
|
station.stationId == targetStationId &&
|
||||||
|
station.stationPicID == this.currentUser.id
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// Split Url dapatkan unique ID Je
|
// Split Url dapatkan unique ID Je
|
||||||
@ -973,20 +1031,57 @@
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
const formData = {
|
const formData = {
|
||||||
|
|
||||||
...(this.selectedAction === 'user' ? { lastStore: this.currentUser.store, lastUser: this.currentUser.id, toOther: 'On Delivery', SendDate: this.assigndate, toUser: this.selectedUser, MovementComplete: false, Remark: this.remark, ConsignmentNote: this.document} : {}),
|
...(this.selectedAction === 'user' ? {
|
||||||
|
lastStore: null,
|
||||||
|
lastUser: this.currentUser.id,
|
||||||
|
toOther: 'On Delivery',
|
||||||
|
SendDate: this.assigndate,
|
||||||
|
toUser: this.selectedUser,
|
||||||
|
MovementComplete: false,
|
||||||
|
Remark: this.remark,
|
||||||
|
ConsignmentNote: this.document} : {}),
|
||||||
|
|
||||||
...(this.selectedAction === 'station' ? {
|
...(this.selectedAction === 'station' ? {
|
||||||
lastStore: this.currentUser.store,
|
lastStore: this.currentUser.store,
|
||||||
lastUser: this.currentUser.id,
|
lastUser: this.currentUser.id,
|
||||||
toOther: 'On Delivery',
|
toOther: 'On Delivery',
|
||||||
SendDate: this.assigndate,
|
SendDate: this.assigndate,
|
||||||
toStation: this.selectedStation,
|
toStation: this.selectedStation,
|
||||||
toUser: this.selectedStationPIC,
|
|
||||||
MovementComplete: false,
|
MovementComplete: false,
|
||||||
Remark: this.remark,
|
Remark: this.remark,
|
||||||
ConsignmentNote: this.document} : {}),
|
ConsignmentNote: this.document} : {}),
|
||||||
...(this.selectedAction === 'store' ? { lastStore: this.currentUser.store, lastUser: this.currentUser.id, toOther: 'On Delivery', SendDate: this.assigndate, toStore: this.selectedStore, MovementComplete: false, Remark: this.remark, ConsignmentNote: this.document} : {}),
|
|
||||||
...(this.selectedAction === 'supplier' ? { lastStore: this.currentUser.store, lastUser: this.currentUser.id, toOther: this.selectedOther, SendDate: this.assigndate, Remark: this.remark + '. Item sent to ' + this.selectedSupplier + ' for ' + this.selectedOther, ConsignmentNote: this.document, toUser: this.currentUser.id, toStore: this.currentUser.store, MovementComplete: false, } : {}),
|
...(this.selectedAction === 'store' ? {
|
||||||
...(this.selectedAction === 'faulty' ? { lastStore: this.currentUser.store, lastUser: this.currentUser.id,toOther: 'Faulty', SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(), ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(), Remark: this.remark, ConsignmentNote: this.document, MovementComplete: true, } : {}),
|
lastStore: this.currentUser.store,
|
||||||
|
lastUser: null,
|
||||||
|
toOther: 'On Delivery',
|
||||||
|
SendDate: this.assigndate,
|
||||||
|
toStore: this.selectedStore,
|
||||||
|
MovementComplete: false,
|
||||||
|
Remark: this.remark,
|
||||||
|
ConsignmentNote: this.document} : {}),
|
||||||
|
|
||||||
|
...(this.selectedAction === 'supplier' ? {
|
||||||
|
lastStore: this.currentUser.store,
|
||||||
|
lastUser: this.currentUser.id,
|
||||||
|
toOther: this.selectedOther,
|
||||||
|
SendDate: this.assigndate,
|
||||||
|
Remark: this.remark + '. Item sent to ' + this.selectedSupplier + ' for ' + this.selectedOther,
|
||||||
|
ConsignmentNote: this.document,
|
||||||
|
toUser: this.currentUser.id,
|
||||||
|
toStore: this.currentUser.store,
|
||||||
|
MovementComplete: false, } : {}),
|
||||||
|
|
||||||
|
...(this.selectedAction === 'faulty' ? {
|
||||||
|
lastStore: this.currentUser.store,
|
||||||
|
lastUser: this.currentUser.id,
|
||||||
|
toOther: 'Faulty',
|
||||||
|
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
|
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
|
Remark: this.remark,
|
||||||
|
ConsignmentNote: this.document,
|
||||||
|
MovementComplete: true, } : {}),
|
||||||
|
|
||||||
ItemId: this.thisItem.itemID,
|
ItemId: this.thisItem.itemID,
|
||||||
Action: 'Stock Out',
|
Action: 'Stock Out',
|
||||||
@ -1036,7 +1131,7 @@
|
|||||||
|
|
||||||
// If it's On Delivery and the current user/store is the target toUser/toStore, set to Delivered
|
// If it's On Delivery and the current user/store is the target toUser/toStore, set to Delivered
|
||||||
if (this.thisItem.toOther === "On Delivery" &&
|
if (this.thisItem.toOther === "On Delivery" &&
|
||||||
(this.thisItem.toUser == this.currentUser.id || this.thisItem.toStore == this.currentUser.store))
|
(this.thisItem.toUser == this.currentUser.id || this.thisItem.toStore == this.currentUser.store || this.isStationPIC))
|
||||||
{
|
{
|
||||||
statusToSave = "Delivered";
|
statusToSave = "Delivered";
|
||||||
}
|
}
|
||||||
@ -1050,15 +1145,42 @@
|
|||||||
statusToSave = "Ready To Deploy";
|
statusToSave = "Ready To Deploy";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let receiveToUser = null;
|
||||||
|
let receiveToStore = null;
|
||||||
|
let receiveToStation = null;
|
||||||
|
|
||||||
|
if (this.thisItem.toStation) {
|
||||||
|
// Only keep Station. Clear User and Store as requested.
|
||||||
|
receiveToUser = null;
|
||||||
|
receiveToStore = null;
|
||||||
|
receiveToStation = this.thisItem.toStation;
|
||||||
|
}
|
||||||
|
else if (this.thisItem.toStore) {
|
||||||
|
receiveToUser = null;
|
||||||
|
receiveToStore = this.currentUser.store;
|
||||||
|
}
|
||||||
|
else if (this.thisItem.toUser) {
|
||||||
|
receiveToUser = this.currentUser.id;
|
||||||
|
receiveToStore = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. BINA PAKEJ DATA (Lengkap dengan Last & To)
|
||||||
const formData = {
|
const formData = {
|
||||||
Id: this.thisItem.movementId,
|
Id: this.thisItem.movementId,
|
||||||
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
Remark: this.thisItem.remark,
|
Remark: this.thisItem.remark,
|
||||||
ToUser: this.thisItem.touser == null ? this.currentUser.id : this.thisItem.touser,
|
LatestStatus: statusToSave,
|
||||||
ToStore: this.currentUser.store,
|
|
||||||
LatestStatus: statusToSave // Uses the prioritized status from above
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Data Penerima (Update kepada siapa yang klik receive sekarang)
|
||||||
|
ToUser: receiveToUser,
|
||||||
|
ToStore: receiveToStore,
|
||||||
|
ToStation: receiveToStation,
|
||||||
|
|
||||||
|
// Data Penghantar (Kekalkan maklumat asal sebagai rujukan sejarah)
|
||||||
|
LastUser: this.thisItem.lastUser,
|
||||||
|
LastStore: this.thisItem.lastStore,
|
||||||
|
LastStation: this.thisItem.lastStation
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/InvMainAPI/UpdateItemMovementMaster', {
|
const response = await fetch('/InvMainAPI/UpdateItemMovementMaster', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -1100,10 +1222,15 @@
|
|||||||
this.selectedDepartment != null &&
|
this.selectedDepartment != null &&
|
||||||
this.selectedDepartment !== ""
|
this.selectedDepartment !== ""
|
||||||
);
|
);
|
||||||
// Debugging logs to help you verify in the browser console
|
|
||||||
|
// Debugging logs
|
||||||
console.log('Item Store ID:', this.thisItem.lastStore);
|
console.log('Item Store ID:', this.thisItem.lastStore);
|
||||||
console.log('User Master Store ID:', this.currentUser.store);
|
console.log('User Master Store ID:', this.currentUser.store);
|
||||||
console.log('Is User Authorized Master for this item?', this.itemassignedtouser);
|
console.log('Is User Authorized Master for this item?', this.itemassignedtouser);
|
||||||
|
console.log("Scanned Item Data:", this.thisItem);
|
||||||
|
console.log("Target Station ID:", this.thisItem.toStation);
|
||||||
|
console.log("Current User ID:", this.currentUser.id);
|
||||||
|
console.log("Full Station List:", this.stationlist);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// If the response is not OK (e.g., 404 Not Found)
|
// If the response is not OK (e.g., 404 Not Found)
|
||||||
@ -1194,10 +1321,13 @@
|
|||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
Id: this.thisItem.movementId,
|
Id: this.thisItem.movementId,
|
||||||
|
ToUser: originalMovementDetails.toUser,
|
||||||
|
ToStore: originalMovementDetails.toStore,
|
||||||
|
ToStation: originalMovementDetails.toStation,
|
||||||
MovementComplete: true,
|
MovementComplete: true,
|
||||||
LatestStatus: 'Cancelled',
|
LatestStatus: 'Cancelled',
|
||||||
// Append the cancellation remark to the current remark
|
// Append the cancellation remark to the current remark
|
||||||
Remark: `${currentRemark.trim()}${currentRemark.trim() ? ' / ' : ''}Movement cancelled: ${this.cancelRemark}`
|
Remark: `Current: ${currentRemark.trim()}${currentRemark.trim() ? ' / ' : ''}Movement cancelled: ${this.cancelRemark}`
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1342,36 +1472,27 @@
|
|||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const formData = {
|
const formData = {
|
||||||
// ItemId: this.thisItem.itemID,
|
|
||||||
// LastStore: this.thisItem.lastStore,
|
|
||||||
// LastUser: this.thisItem.lastUser, This will be handled by the API logic
|
|
||||||
// ToOther: "Return",
|
|
||||||
// SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
|
||||||
// Action: "StockIn",
|
|
||||||
// Quantity: this.thisItem.quantity || 1,
|
|
||||||
// Remark: this.remark + " (Returned)",
|
|
||||||
// ConsignmentNote: this.document, The base64 string from handleFileUpload
|
|
||||||
// Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
|
||||||
// ToUser: this.currentUser.id,
|
|
||||||
// ToStore: this.thisItem.lastStore,
|
|
||||||
// LatestStatus: null,
|
|
||||||
// MovementComplete: false
|
|
||||||
|
|
||||||
ItemId: this.thisItem.itemID,
|
ItemId: this.thisItem.itemID,
|
||||||
LastStation: this.thisItem.currentStationId,
|
|
||||||
LastStore: this.thisItem.currentStoreId,
|
// ORIGIN: Where is it right now?
|
||||||
LastUser: this.currentUser.id,
|
LastUser: this.thisItem.toUser,
|
||||||
|
LastStore: this.thisItem.toStore,
|
||||||
|
LastStation: this.thisItem.toStation,
|
||||||
|
|
||||||
|
// DESTINATION: Set to null here. The C# backend will query the DB
|
||||||
|
// and fill these in automatically based on history!
|
||||||
|
ToUser: null,
|
||||||
|
ToStore: null,
|
||||||
|
ToStation: null,
|
||||||
|
|
||||||
ToOther: "Return",
|
ToOther: "Return",
|
||||||
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
Action: "StockIn",
|
Action: "StockIn",
|
||||||
// Quantity: this.thisItem.quantity,
|
|
||||||
Quantity: this.thisItem.movementQuantity || 1,
|
Quantity: this.thisItem.movementQuantity || 1,
|
||||||
Remark: this.remark,
|
Remark: this.remark,
|
||||||
ConsignmentNote: this.consignmentNote,
|
ConsignmentNote: this.document,
|
||||||
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
ToUser: this.thisItem.lastUser,
|
|
||||||
ToStore: this.thisItem.lastStore,
|
|
||||||
// ToStation: this.thisItem.lastStation,
|
|
||||||
LatestStatus: null,
|
LatestStatus: null,
|
||||||
ReceiveDate: null,
|
ReceiveDate: null,
|
||||||
MovementComplete: false,
|
MovementComplete: false,
|
||||||
@ -1387,7 +1508,7 @@
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
alert('Success! Item is now on delivery to be returned.');
|
alert('Success! Item is now on delivery to be returned.');
|
||||||
$('#returnMessageModal').modal('hide');
|
$('#returnMessageModal').modal('hide');
|
||||||
this.resetScanner(); // Reset view back to scanner
|
this.resetScanner();
|
||||||
window.location.href = '/Inventory/InventoryMaster/ItemMovement';
|
window.location.href = '/Inventory/InventoryMaster/ItemMovement';
|
||||||
} else {
|
} else {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
@ -1404,35 +1525,56 @@
|
|||||||
$("#stationMessageModal").modal("show");
|
$("#stationMessageModal").modal("show");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
async confirmDeployStation() {
|
async confirmDeployStation() {
|
||||||
if (!this.selectedStation) {
|
if (!this.selectedStation) {
|
||||||
alert("Please select a station.");
|
alert("Please select a station.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
|
// 1. LOGIC: Dynamically Identify the Origin (Where is the item right now?)
|
||||||
|
let originUser = null;
|
||||||
|
let originStore = null;
|
||||||
|
let originStation = null;
|
||||||
|
|
||||||
|
if (this.thisItem.toStation || this.thisItem.currentStationId) {
|
||||||
|
originStation = this.thisItem.toStation || this.thisItem.currentStationId;
|
||||||
|
} else if (this.thisItem.toStore) {
|
||||||
|
originStore = this.thisItem.toStore;
|
||||||
|
} else if (this.thisItem.toUser) {
|
||||||
|
originUser = this.thisItem.toUser;
|
||||||
|
} else {
|
||||||
|
originUser = this.currentUserId; // Fallback
|
||||||
|
}
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
ItemId: this.thisItem.itemID,
|
ItemId: this.thisItem.itemID,
|
||||||
LastStation: this.thisItem.lastStation || this.thisItem.currentStationId || null,
|
|
||||||
LastStore: this.currentUser.store,
|
// ORIGINS: Shift the current location to the "Last" fields
|
||||||
LastUser: this.currentUser.id,
|
LastStation: originStation,
|
||||||
|
LastStore: originStore,
|
||||||
|
LastUser: originUser,
|
||||||
|
|
||||||
|
// DESTINATIONS: To the newly selected station (User and Store must be null)
|
||||||
|
ToStation: this.selectedStation,
|
||||||
|
ToUser: null,
|
||||||
|
ToStore: null,
|
||||||
|
|
||||||
ToOther: "Delivered",
|
ToOther: "Delivered",
|
||||||
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
|
||||||
Action: "Assign",
|
Action: "Assign",
|
||||||
Quantity: this.thisItem.quantity || 1,
|
Quantity: this.thisItem.movementQuantity || 1,
|
||||||
Remark: this.remark || "Deployed to station",
|
Remark: this.remark ? (this.remark + ' / Deployed to station') : 'Deployed to station',
|
||||||
ConsignmentNote: this.document, // Base64 from file upload
|
ConsignmentNote: this.document, // Ensure this matches how your file is stored in Vue data
|
||||||
|
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
ToUser: this.currentUser.id,
|
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
ToStore: this.currentUser.store,
|
|
||||||
ToStation: this.selectedStation, // The new station ID selected in modal
|
|
||||||
LatestStatus: "Delivered",
|
LatestStatus: "Delivered",
|
||||||
receiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
|
||||||
MovementComplete: true
|
MovementComplete: true
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('/InvMainAPI/StationItemMovementUser', {
|
const response = await fetch('/InvMainAPI/StationItemMovementUser', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
|||||||
@ -1040,7 +1040,9 @@
|
|||||||
{ title: "From User", data: "lastUserName" },
|
{ title: "From User", data: "lastUserName" },
|
||||||
{ title: "Last User", data: "toUserName" },
|
{ title: "Last User", data: "toUserName" },
|
||||||
{ title: "From Station", data: "lastStationName" },
|
{ title: "From Station", data: "lastStationName" },
|
||||||
|
{ title: "Last Station", data: "toStationName" },
|
||||||
{ title: "From Store", data: "lastStoreName" },
|
{ title: "From Store", data: "lastStoreName" },
|
||||||
|
{ title: "Last Store", data: "toStoreName" },
|
||||||
{ title: "Quantity", data: "quantity" },
|
{ title: "Quantity", data: "quantity" },
|
||||||
{ title: "Note", data: "consignmentNote", render: renderFile },
|
{ title: "Note", data: "consignmentNote", render: renderFile },
|
||||||
{ title: "Remark", data: "remark" },
|
{ title: "Remark", data: "remark" },
|
||||||
|
|||||||
@ -114,7 +114,8 @@
|
|||||||
<div class="col-12 mb-3">
|
<div class="col-12 mb-3">
|
||||||
<p class="h5 fw-bold">
|
<p class="h5 fw-bold">
|
||||||
<i class="fas fa-user-tie me-2 text-secondary"></i>PIC:
|
<i class="fas fa-user-tie me-2 text-secondary"></i>PIC:
|
||||||
<span class="text-muted">{{thisItem.currentUserFullName}}</span>
|
<span class="text-muted">{{ thisItem.currentUserFullName || thisItem.currentUser || 'N/A' }}</span>
|
||||||
|
@* <span class="text-muted">{{thisItem.currentUserFullName}}</span> *@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -141,7 +142,7 @@
|
|||||||
<i class="fas fa-user me-2 text-secondary"></i>User:
|
<i class="fas fa-user me-2 text-secondary"></i>User:
|
||||||
</span>
|
</span>
|
||||||
<span class="text-muted text-end" style="max-width: 70%; word-wrap: break-word;">
|
<span class="text-muted text-end" style="max-width: 70%; word-wrap: break-word;">
|
||||||
{{ thisItem.currentUser }}
|
{{ thisItem.currentUserFullName || thisItem.currentUser || 'N/A' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -165,7 +166,7 @@
|
|||||||
<i class="fas fa-user me-2 text-secondary"></i>User:
|
<i class="fas fa-user me-2 text-secondary"></i>User:
|
||||||
</span>
|
</span>
|
||||||
<span class="text-muted text-end" style="max-width: 70%; word-wrap: break-word;">
|
<span class="text-muted text-end" style="max-width: 70%; word-wrap: break-word;">
|
||||||
{{ thisItem.currentUser }}
|
{{ thisItem.currentUserFullName || thisItem.currentUser || 'N/A' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -448,21 +449,42 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
|
// 1. LOGIC: Identify the Origin (Last location)
|
||||||
|
let originUser = null;
|
||||||
|
let originStore = null;
|
||||||
|
let originStation = null;
|
||||||
|
|
||||||
|
if (this.thisItem.toStation || this.thisItem.currentStationId) {
|
||||||
|
originStation = this.thisItem.toStation || this.thisItem.currentStationId;
|
||||||
|
} else if (this.thisItem.toStore) {
|
||||||
|
originStore = this.thisItem.toStore;
|
||||||
|
} else if (this.thisItem.toUser) {
|
||||||
|
originUser = this.thisItem.toUser;
|
||||||
|
} else {
|
||||||
|
originUser = this.currentUserId; // Fallback to current user if not found
|
||||||
|
}
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
ItemId: this.thisItem.itemID,
|
ItemId: this.thisItem.itemID,
|
||||||
LastStation: this.thisItem.currentStationId,
|
|
||||||
LastStore: this.thisItem.lastStore,
|
// ORIGINS: Based on the logic above
|
||||||
LastUser: this.currentUserId,
|
LastStation: originStation,
|
||||||
|
LastStore: originStore,
|
||||||
|
LastUser: originUser,
|
||||||
|
|
||||||
|
// DESTINATIONS: Explicitly set to only the Station
|
||||||
|
ToStation: this.selectedStation,
|
||||||
|
ToUser: null,
|
||||||
|
ToStore: null,
|
||||||
|
|
||||||
ToOther: "Delivered",
|
ToOther: "Delivered",
|
||||||
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
|
||||||
Action: "Assign",
|
Action: "Assign",
|
||||||
Quantity: this.thisItem.quantity,
|
Quantity: this.thisItem.quantity || 1,
|
||||||
Remark: this.remark,
|
Remark: this.remark,
|
||||||
ConsignmentNote: this.consignmentNote,
|
ConsignmentNote: this.consignmentNote,
|
||||||
|
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
ToUser: this.currentUserId,
|
|
||||||
ToStore: this.thisItem.lastStore,
|
|
||||||
ToStation: this.selectedStation,
|
|
||||||
LatestStatus: "Delivered",
|
LatestStatus: "Delivered",
|
||||||
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
MovementComplete: true,
|
MovementComplete: true,
|
||||||
@ -482,6 +504,7 @@
|
|||||||
alert('Success! Item assign to the Station.');
|
alert('Success! Item assign to the Station.');
|
||||||
$('#stationMessage').modal('hide');
|
$('#stationMessage').modal('hide');
|
||||||
this.displayStatus = "return";
|
this.displayStatus = "return";
|
||||||
|
this.resetForm();
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Failed to submit form.');
|
throw new Error('Failed to submit form.');
|
||||||
}
|
}
|
||||||
@ -501,12 +524,42 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
|
let receiveToUser = null;
|
||||||
|
let receiveToStore = null;
|
||||||
|
let receiveToStation = null;
|
||||||
|
|
||||||
|
if (this.thisItem.toStation) {
|
||||||
|
// Only keep Station. Clear User and Store as requested.
|
||||||
|
receiveToUser = null;
|
||||||
|
receiveToStore = null;
|
||||||
|
receiveToStation = this.thisItem.toStation;
|
||||||
|
}
|
||||||
|
else if (this.thisItem.toStore) {
|
||||||
|
receiveToUser = null;
|
||||||
|
receiveToStore = this.currentUser.store;
|
||||||
|
}
|
||||||
|
else if (this.thisItem.toUser) {
|
||||||
|
receiveToUser = this.currentUser.id;
|
||||||
|
receiveToStore = null;
|
||||||
|
}
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
Id: this.thisItem.id,
|
Id: this.thisItem.id,
|
||||||
ToStore: this.thisItem.lastStore,
|
// ToStore: this.thisItem.lastStore,
|
||||||
LatestStatus: "Delivered",
|
LatestStatus: "Delivered",
|
||||||
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
ReceiveDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
MovementComplete: true,
|
MovementComplete: true,
|
||||||
|
|
||||||
|
// Data Penerima (Update kepada siapa yang klik receive sekarang)
|
||||||
|
ToUser: receiveToUser,
|
||||||
|
ToStore: receiveToStore,
|
||||||
|
ToStation: receiveToStation,
|
||||||
|
|
||||||
|
// Data Penghantar (Kekalkan maklumat asal sebagai rujukan sejarah)
|
||||||
|
LastUser: this.thisItem.lastUser,
|
||||||
|
LastStore: this.thisItem.lastStore,
|
||||||
|
LastStation: this.thisItem.lastStation
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch('/InvMainAPI/UpdateItemMovementUser', {
|
const response = await fetch('/InvMainAPI/UpdateItemMovementUser', {
|
||||||
@ -537,29 +590,47 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
async returnItemMovement() {
|
async returnItemMovement() {
|
||||||
|
|
||||||
if (!confirm("Are you sure you want to return this item?")) {
|
if (!confirm("Are you sure you want to return this item?")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 1. LOGIC: Identify the Origin (Last location)
|
||||||
|
let returnLastUser = null;
|
||||||
|
let returnLastStore = null;
|
||||||
|
let returnLastStation = null;
|
||||||
|
|
||||||
|
if (this.thisItem.toStation || this.thisItem.currentStationId) {
|
||||||
|
returnLastStation = this.thisItem.toStation || this.thisItem.currentStationId;
|
||||||
|
} else if (this.thisItem.toStore) {
|
||||||
|
returnLastStore = this.thisItem.toStore;
|
||||||
|
} else if (this.thisItem.toUser) {
|
||||||
|
returnLastUser = this.thisItem.toUser;
|
||||||
|
} else {
|
||||||
|
returnLastUser = this.currentUserId; // Fallback to current user if not found
|
||||||
|
}
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const formData = {
|
const formData = {
|
||||||
ItemId: this.thisItem.itemID,
|
ItemId: this.thisItem.itemID,
|
||||||
LastStation: this.thisItem.currentStationId,
|
|
||||||
LastStore: this.thisItem.currentStoreId,
|
// ORIGINS: Where the item is currently sitting
|
||||||
LastUser: this.currentUserId,
|
LastUser: returnLastUser,
|
||||||
|
LastStore: returnLastStore,
|
||||||
|
LastStation: returnLastStation,
|
||||||
|
|
||||||
|
// DESTINATIONS: Set to null (the C# API logic overrides this)
|
||||||
|
ToUser: null,
|
||||||
|
ToStore: null,
|
||||||
|
ToStation: null,
|
||||||
|
|
||||||
ToOther: "Return",
|
ToOther: "Return",
|
||||||
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
|
||||||
Action: "StockIn",
|
Action: "StockIn",
|
||||||
// Quantity: this.thisItem.quantity,
|
|
||||||
Quantity: this.thisItem.movementQuantity || 1,
|
Quantity: this.thisItem.movementQuantity || 1,
|
||||||
Remark: this.remark,
|
Remark: this.remark,
|
||||||
ConsignmentNote: this.consignmentNote,
|
ConsignmentNote: this.consignmentNote,
|
||||||
|
SendDate: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
Date: new Date(now.getTime() + 8 * 60 * 60 * 1000).toISOString(),
|
||||||
ToUser: this.InventoryMasterId,
|
|
||||||
ToStore: this.thisItem.lastStore,
|
|
||||||
ToStation: this.thisItem.lastStation,
|
|
||||||
LatestStatus: null,
|
LatestStatus: null,
|
||||||
ReceiveDate: null,
|
ReceiveDate: null,
|
||||||
MovementComplete: false,
|
MovementComplete: false,
|
||||||
@ -598,22 +669,27 @@
|
|||||||
this.thisItem = await response.json();
|
this.thisItem = await response.json();
|
||||||
// this.fetchStore(this.thisItem.lastStore);
|
// this.fetchStore(this.thisItem.lastStore);
|
||||||
|
|
||||||
console.log("Current Station ID:", this.thisItem.currentStationId);
|
// Check if the current user is the PIC of the destination station
|
||||||
console.log("To Station ID:", this.thisItem.toStationId);
|
const isPicOfTargetStation = this.stationList.some(
|
||||||
|
station => station.stationId == this.thisItem.toStationId
|
||||||
|
);
|
||||||
|
|
||||||
// 1. ARRIVED/RECEIVE LOGIC: Check if YOU are the "ToUser"
|
console.log("Is PIC of Target Station:", isPicOfTargetStation);
|
||||||
|
|
||||||
|
// 1. ARRIVED/RECEIVE LOGIC
|
||||||
|
// Allow access if the user is the 'ToUser' OR the 'Station PIC'
|
||||||
if (this.thisItem.movementId != null &&
|
if (this.thisItem.movementId != null &&
|
||||||
this.thisItem.toOther === "On Delivery" &&
|
this.thisItem.toOther === "On Delivery" &&
|
||||||
this.thisItem.latestStatus == null &&
|
this.thisItem.latestStatus == null &&
|
||||||
this.thisItem.toUser == this.currentUserId && // Check ToUser, not LastUser/CurrentUserId
|
(this.thisItem.toUser == this.currentUserId || isPicOfTargetStation) &&
|
||||||
this.thisItem.movementComplete == 0) {
|
this.thisItem.movementComplete == 0) {
|
||||||
|
|
||||||
this.displayStatus = "arrived";
|
this.displayStatus = "arrived";
|
||||||
|
|
||||||
// 2. RETURN/OWNED LOGIC: Check if YOU currently hold the item
|
// 2. RETURN/OWNED LOGIC
|
||||||
} else if (this.thisItem.movementId != null &&
|
} else if (this.thisItem.movementId != null &&
|
||||||
this.thisItem.latestStatus != null &&
|
this.thisItem.latestStatus != null &&
|
||||||
this.thisItem.toUser == this.currentUserId &&
|
(this.thisItem.toUser == this.currentUserId || isPicOfTargetStation) &&
|
||||||
this.thisItem.latestStatus != "Ready To Deploy") {
|
this.thisItem.latestStatus != "Ready To Deploy") {
|
||||||
|
|
||||||
this.displayStatus = "return";
|
this.displayStatus = "return";
|
||||||
@ -627,7 +703,6 @@
|
|||||||
this.displayStatus = "requestAgain";
|
this.displayStatus = "requestAgain";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// FALLBACK: If none of the above matches, it means someone else is the ToUser
|
|
||||||
this.displayStatus = "differentUser";
|
this.displayStatus = "differentUser";
|
||||||
this.thisItem = null;
|
this.thisItem = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -962,6 +962,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
|
|
||||||
CurrentStationId = item.Movement?.ToStation ?? item.Movement?.LastStation,
|
CurrentStationId = item.Movement?.ToStation ?? item.Movement?.LastStation,
|
||||||
ToStationId = item.Movement?.ToStation,
|
ToStationId = item.Movement?.ToStation,
|
||||||
|
toStation = item.Movement?.ToStation,
|
||||||
|
|
||||||
LastUser = item.Movement?.LastUser,
|
LastUser = item.Movement?.LastUser,
|
||||||
ToUserName = item.Movement?.NextUser?.UserName,
|
ToUserName = item.Movement?.NextUser?.UserName,
|
||||||
@ -1060,14 +1061,38 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
itemmovement.sendDate = DateTime.Now; // This ensures hours/minutes/seconds are captured
|
//itemmovement.sendDate = DateTime.Now; // This ensures hours/minutes/seconds are captured
|
||||||
itemmovement.Date = DateTime.Now; // Set the general record date as well
|
//itemmovement.Date = DateTime.Now; // Set the general record date as well
|
||||||
|
|
||||||
var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == itemmovement.LastUser);
|
//var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == itemmovement.LastUser);
|
||||||
|
//if (inventoryMaster != null)
|
||||||
|
//{
|
||||||
|
// itemmovement.LastStore = inventoryMaster.StoreId;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// 1. FIX DATE OVERRULE:
|
||||||
|
// Use the date from the frontend (assigndate) if it exists.
|
||||||
|
// Only set to DateTime.Now if the frontend sent null/empty.
|
||||||
|
if (itemmovement.sendDate == default || itemmovement.sendDate == null)
|
||||||
|
{
|
||||||
|
itemmovement.sendDate = DateTime.Now;
|
||||||
|
}
|
||||||
|
itemmovement.Date = DateTime.Now; // Log the entry creation time
|
||||||
|
|
||||||
|
// 2. FIX STORE/USER OVERRULE:
|
||||||
|
// Only auto-fill LastStore if:
|
||||||
|
// - The frontend didn't send one (null)
|
||||||
|
// - We have a LastUser to look up
|
||||||
|
// - AND it is NOT a "user" assignment (because for 'user', we want it to stay NULL)
|
||||||
|
if (itemmovement.LastStore == null && itemmovement.LastUser != null && itemmovement.ToUser == null)
|
||||||
|
{
|
||||||
|
var inventoryMaster = await _centralDbContext.InventoryMasters
|
||||||
|
.FirstOrDefaultAsync(i => i.UserId == itemmovement.LastUser);
|
||||||
if (inventoryMaster != null)
|
if (inventoryMaster != null)
|
||||||
{
|
{
|
||||||
itemmovement.LastStore = inventoryMaster.StoreId;
|
itemmovement.LastStore = inventoryMaster.StoreId;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(itemmovement.ConsignmentNote))
|
if (!string.IsNullOrEmpty(itemmovement.ConsignmentNote))
|
||||||
@ -1184,8 +1209,11 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
return NotFound("Item movement record not found.");
|
return NotFound("Item movement record not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedList.ToUser = receiveMovement.ToUser;
|
updatedList.ToUser = receiveMovement.ToUser ?? updatedList.ToUser;
|
||||||
updatedList.ToStore = receiveMovement.ToStore;
|
updatedList.ToStore = receiveMovement.ToStore ?? updatedList.ToStore;
|
||||||
|
updatedList.ToStation = receiveMovement.ToStation ?? updatedList.ToStation;
|
||||||
|
//updatedList.ToUser = receiveMovement.ToUser;
|
||||||
|
//updatedList.ToStore = receiveMovement.ToStore;
|
||||||
updatedList.LatestStatus = receiveMovement.LatestStatus;
|
updatedList.LatestStatus = receiveMovement.LatestStatus;
|
||||||
updatedList.receiveDate = receiveMovement.receiveDate;
|
updatedList.receiveDate = receiveMovement.receiveDate;
|
||||||
updatedList.Remark = receiveMovement.Remark;
|
updatedList.Remark = receiveMovement.Remark;
|
||||||
@ -1934,10 +1962,45 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// --- CORE FIX: ISOLATE THE CURRENT LIFECYCLE ---
|
||||||
|
// 1. Find the last time the item cycle was "reset" (Returned or newly Registered)
|
||||||
|
var lastResetMovement = await _centralDbContext.ItemMovements
|
||||||
|
.Where(m => m.ItemId == returnMovement.ItemId && (m.Action == "StockIn" || m.Action == "Register"))
|
||||||
|
.OrderByDescending(m => m.Id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
// Get the ID where the current cycle started (if 0, it means it has never been returned/registered)
|
||||||
|
int currentCycleStartId = lastResetMovement != null ? lastResetMovement.Id : 0;
|
||||||
|
|
||||||
|
// 2. Find the VERY FIRST movement AFTER the cycle started.
|
||||||
|
// This bypasses the middleman (User/Store who gave it to the station) and
|
||||||
|
// accurately grabs the Inventory Master who originally assigned it at the beginning of the chain.
|
||||||
|
var originalMasterMovement = await _centralDbContext.ItemMovements
|
||||||
|
.Where(m => m.ItemId == returnMovement.ItemId
|
||||||
|
&& m.Id > currentCycleStartId
|
||||||
|
&& (m.LastUser != null || m.LastStore != null))
|
||||||
|
.OrderBy(m => m.Id) // <-- Get the FIRST movement of the current chain
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (originalMasterMovement != null)
|
||||||
|
{
|
||||||
|
// Set the destination back to the original Inventory Master
|
||||||
|
returnMovement.ToUser = originalMasterMovement.LastUser;
|
||||||
|
returnMovement.ToStore = originalMasterMovement.LastStore;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback just in case history isn't found
|
||||||
|
returnMovement.ToUser = null;
|
||||||
|
returnMovement.ToStore = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(returnMovement.ConsignmentNote))
|
if (!string.IsNullOrEmpty(returnMovement.ConsignmentNote))
|
||||||
{
|
{
|
||||||
var findUniqueCode = _centralDbContext.Items.Include(i => i.Product).FirstOrDefault(r => r.ItemID == returnMovement.ItemId);
|
var findUniqueCode = _centralDbContext.Items.Include(i => i.Product).FirstOrDefault(r => r.ItemID == returnMovement.ItemId);
|
||||||
var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == returnMovement.LastUser);
|
|
||||||
|
// Fetch the user data for the file name based on the destination we just assigned
|
||||||
|
var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == returnMovement.ToUser);
|
||||||
|
|
||||||
var bytes = Convert.FromBase64String(returnMovement.ConsignmentNote);
|
var bytes = Convert.FromBase64String(returnMovement.ConsignmentNote);
|
||||||
|
|
||||||
@ -2026,27 +2089,28 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == stationMovement.LastUser);
|
var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == stationMovement.LastUser);
|
||||||
|
|
||||||
var bytes = Convert.FromBase64String(stationMovement.ConsignmentNote);
|
var bytes = Convert.FromBase64String(stationMovement.ConsignmentNote);
|
||||||
string filePath = "";
|
|
||||||
|
|
||||||
var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray());
|
var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray());
|
||||||
|
|
||||||
|
// FIX: Safely handle null users and clean invalid file characters (just like your Return API)
|
||||||
|
string safeUserName = string.Join("_", (findUniqueUser?.FullName ?? "Station").Split(Path.GetInvalidFileNameChars()));
|
||||||
|
string safeModelNo = string.Join("_", (findUniqueCode?.Product?.ModelNo ?? "NA").Split(Path.GetInvalidFileNameChars()));
|
||||||
|
|
||||||
if (IsImage(bytes))
|
string extension = IsPdf(bytes) ? ".pdf" : ".jpg";
|
||||||
|
if (!IsImage(bytes) && !IsPdf(bytes)) return BadRequest("Unsupported file format.");
|
||||||
|
|
||||||
|
string relativePath = $"media/inventory/itemmovement/{safeUserName}_{safeModelNo}_{uniqueAbjad}_Station{extension}";
|
||||||
|
string folderPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "media", "inventory", "itemmovement");
|
||||||
|
string filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", relativePath);
|
||||||
|
|
||||||
|
if (!Directory.Exists(folderPath))
|
||||||
{
|
{
|
||||||
filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Station.jpg");
|
Directory.CreateDirectory(folderPath);
|
||||||
stationMovement.ConsignmentNote = "/media/inventory/itemmovement/" + findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Station.jpg";
|
|
||||||
}
|
|
||||||
else if (IsPdf(bytes))
|
|
||||||
{
|
|
||||||
filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "Return.pdf");
|
|
||||||
stationMovement.ConsignmentNote = "/media/inventory/itemmovement/" + findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Station.pdf";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return BadRequest("Unsupported file format.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await System.IO.File.WriteAllBytesAsync(filePath, bytes);
|
await System.IO.File.WriteAllBytesAsync(filePath, bytes);
|
||||||
|
|
||||||
|
// Save the safe relative path to the database
|
||||||
|
stationMovement.ConsignmentNote = "/" + relativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
_centralDbContext.ItemMovements.Add(stationMovement);
|
_centralDbContext.ItemMovements.Add(stationMovement);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user