update item Movement user
This commit is contained in:
parent
ea4666690e
commit
2cdf176620
@ -15,6 +15,10 @@ namespace PSTW_CentralSystem.Areas.Inventory.Controllers
|
|||||||
{
|
{
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
public ActionResult ItemMovementUser()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
public ActionResult QrUser()
|
public ActionResult QrUser()
|
||||||
{
|
{
|
||||||
return View();
|
return View();
|
||||||
|
|||||||
261
Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml
Normal file
261
Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Item Movement";
|
||||||
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||||
|
}
|
||||||
|
<style>
|
||||||
|
@@font-face {
|
||||||
|
font-family: 'OCR-A';
|
||||||
|
src: url('../assets/fonts/ocraext.ttf');
|
||||||
|
}
|
||||||
|
|
||||||
|
.QrPrintFont {
|
||||||
|
font-family: 'OCR-A', monospace;
|
||||||
|
}
|
||||||
|
.table td img {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml");
|
||||||
|
|
||||||
|
<div id="ItemMovement" class="row">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<h2 for="sortSelect" class="col-sm-1 col-form-h2">Sort by:</h2>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<select id="sortSelect" class="form-control" v-model="sortBy" v-on:change="handleSorting">
|
||||||
|
<option value="all">All</option>
|
||||||
|
<option value="item">Item</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="sortBy === 'all'">
|
||||||
|
<div class="row card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>Pending Item Movement</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementNotCompleteDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>Complete Item Movement</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementCompleteDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="sortBy === 'item'">
|
||||||
|
<div v-for="(movements, itemId) in groupedByItem" :key="itemId" class="row card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>Item ID: {{ itemId }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-bordered table-hover table-striped no-wrap item-table" :id="'itemTable_' + itemId" style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section Scripts {
|
||||||
|
@{
|
||||||
|
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
||||||
|
}
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
app.mount('#ItemMovement');
|
||||||
|
});
|
||||||
|
const app = Vue.createApp({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
itemMovements: [],
|
||||||
|
itemMovementCompleteDatatable : null,
|
||||||
|
itemMovementNotCompleteDatatable : null,
|
||||||
|
itemDatatables: {}, // Store tables by ItemId
|
||||||
|
sortBy: 'all', // Sorting option
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
groupedByItem() {
|
||||||
|
return this.itemMovements.reduce((acc, movement) => {
|
||||||
|
if (!acc[movement.itemId]) {
|
||||||
|
acc[movement.itemId] = [];
|
||||||
|
}
|
||||||
|
acc[movement.itemId].push(movement);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchItemMovement();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async fetchItemMovement() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/InvMainAPI/ItemMovementUser', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Failed to fetch item movement');
|
||||||
|
}
|
||||||
|
this.itemMovements = await response.json();
|
||||||
|
|
||||||
|
if (this.itemMovementNotCompleteDatatable) {
|
||||||
|
this.itemMovementNotCompleteDatatable.clear().destroy();
|
||||||
|
}
|
||||||
|
if (this.itemMovementCompleteDatatable) {
|
||||||
|
this.itemMovementCompleteDatatable.clear().destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.renderTables();
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('Error fetching item:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderTables() {
|
||||||
|
if (this.sortBy === 'all') {
|
||||||
|
this.initAllTables();
|
||||||
|
} else {
|
||||||
|
console.log(this.sortBy);
|
||||||
|
this.initItemTables();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initAllTables() {
|
||||||
|
if (this.itemMovementNotCompleteDatatable) {
|
||||||
|
this.itemMovementNotCompleteDatatable.clear().destroy();
|
||||||
|
}
|
||||||
|
if (this.itemMovementCompleteDatatable) {
|
||||||
|
this.itemMovementCompleteDatatable.clear().destroy();
|
||||||
|
}
|
||||||
|
self = this;
|
||||||
|
this.itemMovementNotCompleteDatatable = $('#itemMovementNotCompleteDatatable').DataTable({
|
||||||
|
"data": this.itemMovements.filter(movement => movement.movementComplete == 0),
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"title": "Unique Id",
|
||||||
|
"data": "id",
|
||||||
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
|
// Assign a unique ID to the <td> element
|
||||||
|
$(td).attr('id', `qr${cellData}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ title: "From User", data: "toUserName" },
|
||||||
|
{ title: "Last User", data: "lastUserName" },
|
||||||
|
{ title: "From Station", data: "toStationName" },
|
||||||
|
{ title: "From Store", data: "toStoreName" },
|
||||||
|
{ title: "Action", data: "action" },
|
||||||
|
{ title: "Start Status", data: "toOther" },
|
||||||
|
{ title: "Quantity", data: "quantity" },
|
||||||
|
{ title: "Send Date", data: "sendDate" },
|
||||||
|
{ title: "Note", data: "consignmentNote" },
|
||||||
|
{ title: "Remark", data: "remark" },
|
||||||
|
],
|
||||||
|
responsive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.itemMovementCompleteDatatable = $('#itemMovementCompleteDatatable').DataTable({
|
||||||
|
"data": this.itemMovements.filter(movement => movement.movementComplete == 1),
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"title": "Unique Id",
|
||||||
|
"data": "id",
|
||||||
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
|
// Assign a unique ID to the <td> element
|
||||||
|
$(td).attr('id', `qr${cellData}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ "title": "From User", "data": "toUserName" },
|
||||||
|
{ "title": "Last User", "data": "lastUserName" },
|
||||||
|
{ "title": "From Station", "data": "toStationName" },
|
||||||
|
{ "title": "Last Station", "data": "lastStationName" },
|
||||||
|
{ "title": "From Store", "data": "toStoreName" },
|
||||||
|
{ "title": "Last Store", "data": "lastStoreName" },
|
||||||
|
{ "title": "Action", "data": "action" },
|
||||||
|
{ "title": "Start Status", "data": "toOther" },
|
||||||
|
{ "title": "Latest Status", "data": "latestStatus" },
|
||||||
|
{ "title": "Qty", "data": "quantity" },
|
||||||
|
{ "title": "Send Date", "data": "sendDate" },
|
||||||
|
{ "title": "Receive Date", "data": "receiveDate" },
|
||||||
|
{ "title": "Note", "data": "consignmentNote" },
|
||||||
|
{ "title": "Remark", "data": "remark" },
|
||||||
|
],
|
||||||
|
responsive: true,
|
||||||
|
});
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
initItemTables() {
|
||||||
|
if (this.itemMovementNotCompleteDatatable) {
|
||||||
|
this.itemMovementNotCompleteDatatable.clear().destroy();
|
||||||
|
}
|
||||||
|
if (this.itemMovementCompleteDatatable) {
|
||||||
|
this.itemMovementCompleteDatatable.clear().destroy();
|
||||||
|
}
|
||||||
|
Object.values(this.itemDatatables).forEach(table => table.destroy());
|
||||||
|
this.itemDatatables = {};
|
||||||
|
|
||||||
|
Object.entries(this.groupedByItem).forEach(([itemId, movements]) => {
|
||||||
|
const tableId = `#itemTable_${itemId}`;
|
||||||
|
|
||||||
|
this.itemDatatables[itemId] = $(tableId).DataTable({
|
||||||
|
data: movements,
|
||||||
|
columns: this.getColumns(),
|
||||||
|
responsive: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getColumns() {
|
||||||
|
return [
|
||||||
|
{ title: "Unique Id", data: "id" },
|
||||||
|
{ title: "From User", data: "toUserName" },
|
||||||
|
{ title: "Last User", data: "lastUserName" },
|
||||||
|
{ title: "From Station", data: "toStationName" },
|
||||||
|
{ title: "From Store", data: "toStoreName" },
|
||||||
|
{ title: "Action", data: "action" },
|
||||||
|
{ title: "Start Status", data: "toOther" },
|
||||||
|
{ title: "Quantity", data: "quantity" },
|
||||||
|
{ title: "Send Date", data: "sendDate" },
|
||||||
|
{ title: "Note", data: "consignmentNote" },
|
||||||
|
{ title: "Remark", data: "remark" },
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
resetForm() {
|
||||||
|
this.itemMovement = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSorting() {
|
||||||
|
// Destroy existing DataTables before switching views
|
||||||
|
if (this.itemMovementNotCompleteDatatable) {
|
||||||
|
this.itemMovementNotCompleteDatatable.clear().destroy();
|
||||||
|
this.itemMovementNotCompleteDatatable = null;
|
||||||
|
}
|
||||||
|
if (this.itemMovementCompleteDatatable) {
|
||||||
|
this.itemMovementCompleteDatatable.clear().destroy();
|
||||||
|
this.itemMovementCompleteDatatable = null;
|
||||||
|
}
|
||||||
|
Object.values(this.itemDatatables).forEach(table => table.destroy());
|
||||||
|
this.itemDatatables = {};
|
||||||
|
|
||||||
|
// Delay rendering to ensure Vue updates the DOM
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.renderTables();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
}
|
||||||
@ -25,4 +25,17 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-6 col-md-6 col-lg-3">
|
||||||
|
<div class="card card-hover">
|
||||||
|
<a asp-area="Inventory" asp-controller="ItemMovement" asp-action="ItemMovementUser">
|
||||||
|
<div class="box bg-warning text-center">
|
||||||
|
<h1 class="font-light text-white">
|
||||||
|
<i class="mdi mdi-factory"></i>
|
||||||
|
</h1>
|
||||||
|
<h6 class="text-white">Item Movement</h6>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -777,6 +777,65 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
|
|
||||||
#endregion ItemMovement
|
#endregion ItemMovement
|
||||||
|
|
||||||
|
#region ItemMovementUser
|
||||||
|
|
||||||
|
[HttpPost("ItemMovementUser")]
|
||||||
|
public async Task<IActionResult> ItemMovementUser()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound("Item movement record not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemMovementUser = await _centralDbContext.ItemMovements
|
||||||
|
.Include(i => i.FromStore)
|
||||||
|
.Include(i => i.FromStation)
|
||||||
|
.Include(i => i.FromUser)
|
||||||
|
.Include(i => i.NextStore)
|
||||||
|
.Include(i => i.NextStation)
|
||||||
|
.Include(i => i.NextUser)
|
||||||
|
.Where(i => i.ToUser == user.Id || i.LastUser == user.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Json(itemMovementUser.Select(i => new
|
||||||
|
{
|
||||||
|
i.Id,
|
||||||
|
i.ItemId,
|
||||||
|
i.ToStation,
|
||||||
|
i.ToStore,
|
||||||
|
i.ToUser,
|
||||||
|
LastUserName = i.FromUser?.FullName,
|
||||||
|
LastStoreName = i.FromStore?.StoreName,
|
||||||
|
LastStationName = i.FromStation?.StationName,
|
||||||
|
ToUserName = i.NextUser?.FullName,
|
||||||
|
ToStoreName = i.NextStore?.StoreName,
|
||||||
|
ToStationName = i.NextStation?.StationName,
|
||||||
|
i.ToOther,
|
||||||
|
i.sendDate,
|
||||||
|
i.Action,
|
||||||
|
i.Quantity,
|
||||||
|
i.Remark,
|
||||||
|
i.ConsignmentNote,
|
||||||
|
i.Date,
|
||||||
|
i.LastUser,
|
||||||
|
i.LastStore,
|
||||||
|
i.LastStation,
|
||||||
|
i.LatestStatus,
|
||||||
|
i.receiveDate,
|
||||||
|
i.MovementComplete
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region ItemRequestUser
|
#region ItemRequestUser
|
||||||
[HttpPost("AddRequest")]
|
[HttpPost("AddRequest")]
|
||||||
public async Task<IActionResult> AddRequest([FromBody] RequestModel request)
|
public async Task<IActionResult> AddRequest([FromBody] RequestModel request)
|
||||||
|
|||||||
@ -9,9 +9,10 @@
|
|||||||
var user = await UserManager.GetUserAsync(User);
|
var user = await UserManager.GetUserAsync(User);
|
||||||
var roles = user != null ? await UserManager.GetRolesAsync(user) : new List<string>();
|
var roles = user != null ? await UserManager.GetRolesAsync(user) : new List<string>();
|
||||||
|
|
||||||
Console.WriteLine("User Roles: " + string.Join(", ", roles));
|
Console.WriteLine("User Roles: " + string.Join(", ", roles)); var restrictedRoles = new List<string> { "SuperAdmin", "SystemAdmin", "Inventory Master" };
|
||||||
var isNotTechnician = !roles.Any(r => r.Trim().Equals("Technician", StringComparison.OrdinalIgnoreCase));
|
var isAdmin = roles.Any(r => restrictedRoles.Contains(r.Trim(), StringComparer.OrdinalIgnoreCase));
|
||||||
Console.WriteLine("Is NOT Technician: " + (isNotTechnician ? "True" : "False"));
|
|
||||||
|
Console.WriteLine("Is NOT Admin: " + (isAdmin ? "True" : "False"));
|
||||||
|
|
||||||
}
|
}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -443,13 +444,17 @@
|
|||||||
<i class="mdi mdi-receipt"></i><span class="hide-menu">Inventory </span>
|
<i class="mdi mdi-receipt"></i><span class="hide-menu">Inventory </span>
|
||||||
</a>
|
</a>
|
||||||
<ul aria-expanded="false" class="collapse first-level">
|
<ul aria-expanded="false" class="collapse first-level">
|
||||||
<li class="sidebar-item" v-if="@isNotTechnician">
|
@if (isAdmin)
|
||||||
|
{
|
||||||
|
<li class="sidebar-item">
|
||||||
<a class="sidebar-link waves-effect waves-dark sidebar-link"
|
<a class="sidebar-link waves-effect waves-dark sidebar-link"
|
||||||
asp-area="Inventory" asp-controller="InventoryMaster" asp-action="AdminDashboard"
|
asp-area="Inventory" asp-controller="InventoryMaster" asp-action="AdminDashboard"
|
||||||
aria-expanded="false">
|
aria-expanded="false">
|
||||||
<i class="mdi mdi-view-dashboard"></i><span class="hide-menu">Admin Dashboard</span>
|
<i class="mdi mdi-view-dashboard"></i><span class="hide-menu">Admin Dashboard</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
|
|
||||||
<li class="sidebar-item">
|
<li class="sidebar-item">
|
||||||
<a class="sidebar-link waves-effect waves-dark sidebar-link"
|
<a class="sidebar-link waves-effect waves-dark sidebar-link"
|
||||||
asp-area="Inventory" asp-controller="ItemMovement" asp-action="UserDashboard"
|
asp-area="Inventory" asp-controller="ItemMovement" asp-action="UserDashboard"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user