This commit is contained in:
MOHD ARIFF 2026-03-12 14:03:59 +08:00
parent 8890cba87e
commit 45afdec610
3 changed files with 216 additions and 82 deletions

View File

@ -66,7 +66,6 @@
<div class="card-header">
<h3 class="card-title">Report Inquiry</h3>
</div>
</div>
<div class="card-body">
<div v-if="reportData">
<div class="row justify-content-center">
@ -86,13 +85,6 @@
<div class=""><button class="btn btn-danger" v-on:click="selectedMonth = null">Clear</button></div>
</div>
</div>
<div class="col-3">
<div class="row col-10">
<h4>Position Filter</h4>
<multiselect v-model="selectedPosition" :options="positionList" :multiple="false" placeholder="Search Position" track-by="positionId" label="positionName"></multiselect>
<div class=""><button class="btn btn-danger" v-on:click="selectedPosition = []">Clear</button></div>
</div>
</div>
<div class="col-12">
<button class="btn btn-primary" v-on:click="generateReport">Generate Report</button>
</div>
@ -104,9 +96,15 @@
<li class="nav-item">
<button :class="['nav-link', {active: activeTab === 'userTab'}]" v-on:click="activeTab = 'userTab'">User</button>
</li>
<li class="nav-item">
<button :class="['nav-link', {active: activeTab === 'stationTab'}]" v-on:click="activeTab = 'stationTab'">Station</button>
</li>
<li class="nav-item">
<button :class="['nav-link', {active: activeTab === 'storeTab'}]" v-on:click="activeTab = 'storeTab'">Store</button>
</li>
<li class="nav-item">
<button :class="['nav-link', {active: activeTab === 'allStoreTab'}]" v-on:click="activeTab = 'allStoreTab'">All Item</button>
</li>
</ul>
<hr />
<div class="card-body">
@ -118,7 +116,15 @@
<multiselect v-model="selectedUser" :options="formResponse.userItemBalance" :multiple="false" placeholder="Select User" track-by="userId" label="userFullName"></multiselect>
</div>
<div class="col-9">
<table id="userItemsTable" class="display table table-bordered"></table>
<table id="userItemsTable" class="display table table-bordered table-hover"></table>
</div>
</div>
<div v-if="formResponse" v-show="activeTab === 'stationTab'">
<div class="col-3">
<h4>Store</h4>
</div>
<div class="col-9">
<table id="stationItemsTable" class="display table table-bordered table-hover"></table>
</div>
</div>
<div v-if="formResponse" v-show="activeTab === 'storeTab'">
@ -126,7 +132,16 @@
<h4>Store</h4>
</div>
<div class="col-9">
<table id="itemsTable" class="display table table-bordered"></table>
<table id="storeItemsTable" class="display table table-bordered table-hover"></table>
</div>
</div>
<div v-if="formResponse" v-show="activeTab === 'allStoreTab'">
<div class="col-3">
<h4>Store</h4>
</div>
<div class="col-9">
<table id="storeAllItemsTable" class="display table table-bordered table-hover"></table>
</div>
</div>
</div>
</div>
@ -173,13 +188,14 @@
selectedSingleDepartment: [],
selectedItem: [],
selectedCategory: [],
selectedPosition: [],
usersInfo: [],
submitBody: null,
formResponse: null,
selectedUser: [],
userItemsTable: null,
itemsTable: null,
stationItemsTable: null,
storeItemsTable: null,
storeAllItemsTable: null,
activeTab: "userTab"
}
},
@ -202,6 +218,7 @@
}
// if (newVal && newVal.items) {
const tableData = newVal?.items ? newVal.items : [];
var app = this;
this.$nextTick(() => {
this.userItemsTable = $('#userItemsTable').DataTable({
data: tableData ,
@ -223,13 +240,18 @@
</tr>`
);
},
"createdRow": function (row, data, dataIndex) {
$(row).on('click', function () {
app.fetchItemMovement(data.uniqueID);
});
}
});
});
}
},
methods: {
async generateReport(){
if(this.selectedMonth == null || this.selectedSingleDepartment.length == 0 || this.selectedPosition.length == 0)
if(this.selectedMonth == null || this.selectedSingleDepartment.length == 0)
{
var msg = [];
if(this.selectedMonth == null)
@ -240,10 +262,6 @@
{
msg.push("Department");
}
if(this.selectedPosition.length == 0)
{
msg.push("Position");
}
alert(msg.length > 1 ? msg.join(" & ") + " cannot be empty" : msg[0] + " cannot be empty");
}
else{
@ -251,9 +269,6 @@
formDate: new Date(this.selectedMonth.year, this.selectedMonth.month + 1, 0, 23, 59, 59).toISOString().slice(0, 19),
// selectedCategory: this.selectedCategory,
deptId: this.selectedSingleDepartment.departmentCode,
toUser: this.selectedPosition.positionId == 1 ? 1 : 0,
toStation: this.selectedPosition.positionId == 2 ? 1 : 0,
toStore: this.selectedPosition.positionId == 3 ? 1 : 0,
}
this.fetchCurrentReport();
}
@ -276,11 +291,14 @@
this.userItemsTable = null;
this.selectedUser = null;
}
if (this.itemsTable) {
this.itemsTable.clear().destroy();
this.itemsTable = null;
if (this.stationItemsTable) {
this.stationItemsTable.clear().destroy();
this.stationItemsTable = null;
}
if (this.storeItemsTable) {
this.storeItemsTable.clear().destroy();
this.storeItemsTable = null;
}
console.log(data);
}
else {
console.error(`Failed to fetch user: ${response.statusText}`);
@ -397,10 +415,54 @@
}
},
initTable() {
this.userItemsTable = $('#userItemsTable').DataTable();
this.$nextTick(() => {
this.itemsTable = $('#itemsTable').DataTable({
data: this.formResponse.allProductInStore ,
this.userItemsTable = $('#userItemsTable').DataTable();
const stationTableData = this.formResponse.stationItemBalance ? this.formResponse.stationItemBalance : [];
this.stationItemsTable = $('#stationItemsTable').DataTable({
data: stationTableData.items,
columns: [
{ data: 'itemName', title: 'Item Name' },
{ data: 'uniqueID', title: 'Unique ID' },
{ data: 'quantity', title: 'Quantity' },
{ data: 'itemPrice', title: 'Item Price' },
],
destroy: true,
drawCallback: function () {
const total = stationTableData.totalItemPrice;
$(this.api().table().node()).find('tbody tr.total-row').remove();
$(this.api().table().node()).find('tbody').append(
`<tr class="total-row">
<td colspan="3"><strong>Total</strong></td>
<td class="text-end"><strong>${total}</strong></td>
</tr>`
);
},
});
const storeTableData = this.formResponse.storeItemBalance ? this.formResponse.storeItemBalance : [];
this.storeItemsTable = $('#storeItemsTable').DataTable({
data: storeTableData.items,
columns: [
{ data: 'itemName', title: 'Item Name' },
{ data: 'uniqueID', title: 'Unique ID' },
{ data: 'quantity', title: 'Quantity' },
{ data: 'itemPrice', title: 'Item Price' },
],
destroy: true,
drawCallback: function () {
const total = storeTableData.totalItemPrice;
$(this.api().table().node()).find('tbody tr.total-row').remove();
$(this.api().table().node()).find('tbody').append(
`<tr class="total-row">
<td colspan="3"><strong>Total</strong></td>
<td class="text-end"><strong>${total}</strong></td>
</tr>`
);
},
});
const storeAllTableData = this.formResponse.allProductInStore ? this.formResponse.allProductInStore : [];
this.storeAllItemsTable = $('#storeAllItemsTable').DataTable({
data: storeAllTableData ,
columns: [
{ data: 'productName', title: 'Item Name' },
{ data: 'quantity', title: 'Quantity' },
@ -411,6 +473,27 @@
});
});
},
async fetchItemMovement(data){
try {
const response = await fetch(`/ReportingAPI/GetItemMovement/`, {
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
method: 'POST',
});
if (response.ok) {
const data = await response.json();
this.itemMovement = data;
}
else {
console.error(`Failed to fetch item movement: ${response.statusText}`);
}
}
catch (error) {
console.error('There was a problem with the fetch operation:', error);
}
}
// selectedUserFunc() {
// if (this.userItemsTable) {
// this.userItemsTable.destroy();

View File

@ -1920,8 +1920,10 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
[HttpPost("UserList")]
public async Task<IActionResult> UserList()
{
var userList = await _centralDbContext.Users.Include(i => i.Department).ToListAsync();
//get current user
var thisUser = await _userManager.GetUserAsync(User);
var thisUserDept = thisUser!.departmentId;
var userList = await _centralDbContext.Users.Include(i => i.Department).Where(i => i.departmentId == thisUserDept).ToListAsync();
return Json(userList.Select(i => new
{
i.Id,

View File

@ -38,9 +38,6 @@ namespace PSTW_CentralSystem.Controllers.API
{
public string? FormDate { get; set; }
public string? DeptId { get; set; }
public int ToUser { get; set; }
public int ToStation { get; set; }
public int ToStore { get; set; }
}
#region ItemReport
@ -142,9 +139,6 @@ namespace PSTW_CentralSystem.Controllers.API
{
string FormDate = reportQuery.FormDate!;
string DeptId = reportQuery.DeptId!;
int ToUser = reportQuery.ToUser;
int ToStation = reportQuery.ToStation;
int ToStore = reportQuery.ToStore;
var currentProductBalance = new List<ProductReport>();
var result = await _centralDbContext.Products
.Include(p => p.Items)
@ -226,9 +220,9 @@ namespace PSTW_CentralSystem.Controllers.API
.Where(s => s.Department!.DepartmentCode == DeptId)
.ToListAsync();
var departmentStores = await _centralDbContext.Stores
var departmentStores = await _centralDbContext.Departments
.Include(s => s.Company)
.Where(s => s.Department!.DepartmentCode == DeptId)
.Where(s => s.DepartmentCode == DeptId)
.ToListAsync();
var latestItemMovements = await _centralDbContext.ItemMovements
@ -237,6 +231,7 @@ namespace PSTW_CentralSystem.Controllers.API
.Include(m => m.NextUser)
.Include(m => m.NextStation)
.Include(m => m.NextStore)
.Where(m => m.MovementComplete == true)
.GroupBy(m => m.ItemId)
.Select(g => g
.Where(m => m.Date <= parsedDate)
@ -269,7 +264,7 @@ namespace PSTW_CentralSystem.Controllers.API
UniqueID = m.Item.UniqueID,
})
.ToList(),
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToUser == u.Id).Sum(m => m!.Item!.ConvertPrice * m.Quantity),
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToUser == u.Id).Select(m => m!.Item!.ConvertPrice).Sum(),
})
.Where(u => u.Items.Count > 0).ToList();
@ -292,15 +287,39 @@ namespace PSTW_CentralSystem.Controllers.API
UniqueID = m.Item.UniqueID,
})
.ToList(),
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToStation == u.StationId).Sum(m => m!.Item!.ConvertPrice * m.Quantity),
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToStation == u.StationId).Select(m => m!.Item!.ConvertPrice).Sum(),
})
.Where(u => u.Items.Count > 0).ToList();
.Where(u => u.Items.Count > 0).FirstOrDefault();
var storeItemMovements = departmentStores
.Select(u => new
{
Department = u.DepartmentName,
Items = latestStationItemMovements
.Where(m => m != null && m.ToStore > 0 && m.NextStore!.StoreName.Contains(u.DepartmentName))
.Select(m => new
{
ItemId = m!.ItemId,
ItemName = m.Item!.Product!.ProductName,
Quantity = m.Quantity,
ItemPrice = m.Item!.ConvertPrice,
PO = m.Item!.PONo,
DO = m.Item!.DONo,
SerialNumber = m.Item.SerialNumber,
UniqueID = m.Item.UniqueID,
})
.ToList(),
TotalItemPrice = latestStationItemMovements.Where(m => m != null && m.ToStore > 0 && m.NextStore!.StoreName.Contains(u.DepartmentName)).Select(m => m!.Item!.ConvertPrice).Sum(),
})
.Where(u => u.Items.Count > 0).FirstOrDefault();
var report = new
{
allProductInStore = currentProductBalance,
userItemBalance = usersItemMovements,
stationItemBalance = stationItemMovements,
storeItemBalance = storeItemMovements,
};
return Json(report);
@ -311,7 +330,37 @@ namespace PSTW_CentralSystem.Controllers.API
}
}
#endregion
#region Item Movement report
[HttpPost("GetItemMovement")]
public async Task<IActionResult> GetItemMovement([FromBody] String data)
{
try
{
if (string.IsNullOrEmpty(data))
{
return BadRequest("Invalid Unique ID");
}
var itemMovement = await _centralDbContext.ItemMovements
.Include(im => im.Item)
.Where(im => im.Item!.UniqueID == data)
.OrderByDescending(im => im.Id)
.Select(im => new
{
From = im.LastUser != null ? im.FromUser!.FullName : im.LastStation != null ? im.FromStation!.StationName : im.LastStore != null ? im.FromStore!.StoreName : null,
To = im.ToUser != null ? im.NextUser!.FullName : im.ToStation != null ? im.NextStation!.StationName : im.ToStore != null ? im.NextStore!.StoreName : null,
Date = im.Date,
MovementStatus = im.MovementComplete
})
.ToListAsync();
return Json(itemMovement);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
#endregion
#region Report Inventory ii
[HttpPost("GetInventoryReport")]
public async Task<IActionResult> GetInventoryReport([FromBody] ReportFilterDTO filter)