Compare commits

..

No commits in common. "main" and "Maintenance/May2026" have entirely different histories.

170 changed files with 6346 additions and 10747 deletions

View File

@ -1,211 +0,0 @@
name: Build and Deploy CPRNIMS
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: windows
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Clean previous publish output
shell: pwsh
run: |
Remove-Item -Recurse -Force "C:\ci-output\webapi" -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force "C:\ci-output\webapps" -ErrorAction SilentlyContinue
- name: Publish WebApi
shell: pwsh
run: dotnet publish .\CPRNIMS.WebApi\CPRNIMS.WebApi.csproj -c Release -o C:\ci-output\webapi
- name: Publish WebApps
shell: pwsh
run: dotnet publish .\CPRNIMS.WebApps\CPRNIMS.WebApps.csproj -c Release -o C:\ci-output\webapps
# ---- Generate production config from Gitea Actions secrets (never committed to git) ----
- name: Write production appsettings - WebApi
shell: pwsh
env:
TAVILY_KEY: ${{ secrets.LLI_NON_INVENTORY_PROD_TAVILY_API_KEY }}
GROQ_KEY: ${{ secrets.LLI_NON_INVENTORY_PROD_GROQ_API_KEY }}
JWT_SECRET: ${{ secrets.LLI_NON_INVENTORY_PROD_JWT_SECRET }}
DB_CONN: ${{ secrets.LLI_NON_INVENTORY_PROD_DB_CONNECTION }}
LOCALPURCH_CONN: ${{ secrets.LLI_NON_INVENTORY_PROD_DB_LOCALPURCH_CONNECTION }}
run: |
$config = @{
Tavily = @{
ApiKey = $env:TAVILY_KEY
SearchUrl = "https://api.tavily.com/search"
}
Groq = @{
ApiKey = $env:GROQ_KEY
ApiUrl = "https://api.groq.com/openai/v1/chat/completions"
Model = "llama-3.1-8b-instant"
}
JWT = @{
ValidAudience = "https://lloydwebapi.lloydlab.com:2021"
ValidIssuer = "https://lloydwebapi.lloydlab.com:2021"
Secret = $env:JWT_SECRET
}
WebEndPoint = @{
ForgotPassword = "https://llipurchasingnoninventory.com:8080/"
SupplierForm = "https://llipurchasingnoninventory.com:8083/"
}
ConnectionStrings = @{
DefaultConnection = $env:DB_CONN
LocalPurchConn = $env:LOCALPURCH_CONN
}
}
$json = $config | ConvertTo-Json -Depth 5
$json | Out-File -FilePath "C:\ci-output\webapi\appsettings.Production.json" -Encoding utf8
Write-Host "Wrote appsettings.Production.json to webapi output (values masked in this log automatically)"
exit 0
# ---- Generate production config for WebApps (uses Variables, not Secrets, since BaseUrl isn't sensitive) ----
- name: Write production appsettings - WebApps
shell: pwsh
env:
API_BASE_URL: ${{ vars.LLI_NON_INVENTORY_PROD_API_BASE_URL }}
run: |
$config = @{
CommonEndpoints = @{
ApiDefaultHeaders = @{
BaseUrl = $env:API_BASE_URL
ESignaturePath = "https://llipurchasingnoninventory.com:8080/Content/Images/Signatures/"
ItemImages = "https://llipurchasingnoninventory.com:8080/content/images/"
ContentTypeMedia = "application/json"
Authorization = "token"
ErrorMessage = "api/ErrorLogs/ErrorMessage/"
}
}
}
$json = $config | ConvertTo-Json -Depth 5
$json | Out-File -FilePath "C:\ci-output\webapps\appsettings.Production.json" -Encoding utf8
Write-Host "Wrote appsettings.Production.json to webapps output"
exit 0
# ---- Backup current live deployment before touching anything ----
- name: Backup current live files
shell: pwsh
run: |
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
New-Item -ItemType Directory -Force -Path "C:\backups\$stamp" | Out-Null
# Mirror current live folders into the backup location (only if they exist / aren't empty)
if (Test-Path "C:\inetpub\cprnims-api") {
robocopy "C:\inetpub\cprnims-api" "C:\backups\$stamp\webapi" /MIR /R:2 /W:3 | Out-Null
}
if (Test-Path "C:\inetpub\cprnims-web") {
robocopy "C:\inetpub\cprnims-web" "C:\backups\$stamp\webapps" /MIR /R:2 /W:3 | Out-Null
}
# Record this backup's timestamp so later steps know where it lives
$stamp | Out-File -FilePath "C:\backups\latest.txt" -Encoding ascii -NoNewline
# Keep only the last 5 backups to avoid filling the disk
$all = Get-ChildItem "C:\backups" -Directory | Sort-Object Name -Descending
if ($all.Count -gt 5) {
$all | Select-Object -Skip 5 | Remove-Item -Recurse -Force
}
Write-Host "Backed up current deployment to C:\backups\$stamp"
exit 0
- name: Stop app pools
shell: pwsh
run: |
Import-Module WebAdministration
Stop-WebAppPool -Name "CPRNIMS-Api" -ErrorAction SilentlyContinue
Stop-WebAppPool -Name "CPRNIMS-Web" -ErrorAction SilentlyContinue
Start-Sleep -Seconds 3
- name: Deploy WebApi files
id: deploy_api
shell: pwsh
run: |
robocopy "C:\ci-output\webapi" "C:\inetpub\cprnims-api" /MIR /R:3 /W:5
$rc = $LASTEXITCODE
Write-Host "ROBOCOPY EXIT CODE: $rc"
if ($rc -ge 8) {
throw "robocopy failed for WebApi with exit code $rc"
}
exit 0
- name: Deploy WebApps files
id: deploy_web
shell: pwsh
run: |
robocopy "C:\ci-output\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5
$rc = $LASTEXITCODE
Write-Host "ROBOCOPY EXIT CODE: $rc"
if ($rc -ge 8) {
throw "robocopy failed for WebApps with exit code $rc"
}
exit 0
- name: Start app pools
shell: pwsh
run: |
Import-Module WebAdministration
Start-WebAppPool -Name "CPRNIMS-Api"
Start-WebAppPool -Name "CPRNIMS-Web"
- name: Verify app pools are running
shell: pwsh
run: |
Start-Sleep -Seconds 3
Import-Module WebAdministration
$api = Get-WebAppPoolState -Name "CPRNIMS-Api"
$web = Get-WebAppPoolState -Name "CPRNIMS-Web"
Write-Host "CPRNIMS-Api: $($api.Value)"
Write-Host "CPRNIMS-Web: $($web.Value)"
if ($api.Value -ne "Started" -or $web.Value -ne "Started") {
throw "One or more app pools failed to start"
}
# ---- Rollback path: only runs if any prior step in this job failed ----
- name: ROLLBACK - restore previous backup
if: failure()
shell: pwsh
run: |
$stamp = Get-Content "C:\backups\latest.txt" -Raw
$backupPath = "C:\backups\$stamp"
Write-Host "Deployment failed - rolling back to backup: $backupPath"
Import-Module WebAdministration
Stop-WebAppPool -Name "CPRNIMS-Api" -ErrorAction SilentlyContinue
Stop-WebAppPool -Name "CPRNIMS-Web" -ErrorAction SilentlyContinue
Start-Sleep -Seconds 3
if (Test-Path "$backupPath\webapi") {
robocopy "$backupPath\webapi" "C:\inetpub\cprnims-api" /MIR /R:3 /W:5 | Out-Null
}
if (Test-Path "$backupPath\webapps") {
robocopy "$backupPath\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 | Out-Null
}
Start-WebAppPool -Name "CPRNIMS-Api"
Start-WebAppPool -Name "CPRNIMS-Web"
Write-Host "Rollback complete. Restored from $backupPath"
exit 0
- name: ROLLBACK - verify pools after restore
if: failure()
shell: pwsh
run: |
Start-Sleep -Seconds 3
Import-Module WebAdministration
$api = Get-WebAppPoolState -Name "CPRNIMS-Api"
$web = Get-WebAppPoolState -Name "CPRNIMS-Web"
Write-Host "After rollback - CPRNIMS-Api: $($api.Value)"
Write-Host "After rollback - CPRNIMS-Web: $($web.Value)"
if ($api.Value -ne "Started" -or $web.Value -ne "Started") {
Write-Host "WARNING: app pools still not running after rollback. Manual intervention needed."
}

48
.gitignore vendored
View File

@ -1,48 +0,0 @@
# Build output
[Bb]in/
[Oo]bj/
[Dd]ebug/
[Rr]elease/
x64/
x86/
build/
bld/
# Visual Studio
.vs/
*.user
*.suo
*.userosscache
*.sln.docstates
*.userprefs
# Publish output
publish/
*.publishsettings
PublishScripts/
# NuGet
*.nupkg
*.snupkg
packages/
!packages/build/
project.lock.json
project.fragment.lock.json
artifacts/
# Rider / VS Code (if anyone uses them)
.idea/
.vscode/
# Build results / logs
*.binlog
*.log
msbuild.log
msbuild.err
# Environment-specific config with secrets
appsettings.*.json
!appsettings.json
*.dev.json
secrets.json
*.pfx

Binary file not shown.

View File

@ -0,0 +1,12 @@
{
"Version": 1,
"WorkspaceRootPath": "D:\\sourcecode\\NonInventPurchasing\\",
"Documents": [],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": []
}
]
}

View File

@ -0,0 +1,6 @@
{
"ExpandedNodes": [
""
],
"PreviewInSolutionExplorer": false
}

View File

@ -10,9 +10,6 @@
<PackageReference Include="AutoMapper" Version="16.1.1" /> <PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="CaptchaGen.NetCore" Version="1.1.2" /> <PackageReference Include="CaptchaGen.NetCore" Version="1.1.2" />
<PackageReference Include="Dapper" Version="2.1.66" /> <PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="FastReport.OpenSource" Version="2026.2.3" />
<PackageReference Include="FastReport.OpenSource.Export.PdfSimple" Version="2026.2.3" />
<PackageReference Include="FastReport.OpenSource.Web" Version="2026.2.3" />
<PackageReference Include="Google.Apis.Drive.v3" Version="1.67.0.3373" /> <PackageReference Include="Google.Apis.Drive.v3" Version="1.67.0.3373" />
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.4" /> <PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.0" />

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Common
{
public interface ITransactionFacade
{
Task<T> ExecuteAsync<T>(Func<Task<T>> operation,CancellationToken ct);
Task ExecuteAsync(Func<Task> operation,CancellationToken ct);
}
}

View File

@ -13,6 +13,6 @@ namespace CPRNIMS.Domain.Contracts.Finance
{ {
Task<List<ForPayment>> GetAllClosedPO(RRDetailsDto itemDto); Task<List<ForPayment>> GetAllClosedPO(RRDetailsDto itemDto);
Task<List<ReceivingDetail>> GetRRDetailByPO(RRDetailsDto itemDto); Task<List<ReceivingDetail>> GetRRDetailByPO(RRDetailsDto itemDto);
Task<RRDetailDto> PostPutPayment(RRDetailsDto itemDto); Task<RRDetail> PostPutPayment(RRDetailsDto itemDto);
} }
} }

View File

@ -21,7 +21,7 @@ namespace CPRNIMS.Domain.Contracts.Inventory
Task<PagedResult<InventoryResponse>> GetInventory(InventoryRequest request, CancellationToken ct); Task<PagedResult<InventoryResponse>> GetInventory(InventoryRequest request, CancellationToken ct);
Task<List<InventoryByIdResponse>> GetInventoryById(InventoryRequest itemDto, CancellationToken ct); Task<List<InventoryByIdResponse>> GetInventoryById(InventoryRequest itemDto, CancellationToken ct);
Task<TransactContextDto?> GetTransactContextAsync(int inventoryId, CancellationToken ct); Task<TransactContextDto?> GetTransactContextAsync(int inventoryId, CancellationToken ct);
Task<IReadOnlyList<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct); Task<IEnumerable<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct);
Task<Infrastructure.Entities.Inventory.Inventory> PostPutReqApproval(InventoryDto itemDto); Task<Infrastructure.Entities.Inventory.Inventory> PostPutReqApproval(InventoryDto itemDto);
Task<RequestItem> PostPutReqItems(InventoryDto itemDto); Task<RequestItem> PostPutReqItems(InventoryDto itemDto);
Task<Lot> PostPutLotNo(InventoryDto itemDto); Task<Lot> PostPutLotNo(InventoryDto itemDto);

View File

@ -1,17 +0,0 @@
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Inventory
{
public interface IInventoryReports
{
Task<RISReportDto> GetRISReportAsync(InventoryReportsRequest request, string userName, int? departmentId, CancellationToken ct);
Task<MRSReportDto> GetMRSReportAsync(InventoryReportsRequest request, string userName, int? departmentId, CancellationToken ct);
Task<InventoryReportDto> GetInventoryReportAsync(InventoryReportsRequest request,string userName, int? departmentId, CancellationToken ct);
}
}

View File

@ -11,12 +11,9 @@ namespace CPRNIMS.Domain.Contracts.Inventory
{ {
public interface IMRS public interface IMRS
{ {
Task<MRSPagedResult> GetPagedAsync(MRSFilterDto filter, CancellationToken ct,int? departmentId = null, string? userName = ""); Task<MRSPagedResult> GetPagedAsync(MRSFilterDto filter);
Task<IReadOnlyList<RISSearchResultDto>> SearchRISForReturnAsync(string? risNoQuery, int? projectCodeId, CancellationToken ct); Task<MRS?> GetByIdAsync(long mrsId);
Task<IReadOnlyList<ProjectCodeOptionDto>> GetProjectsWithOpenRISAsync(string? nameQuery, CancellationToken ct); Task<MRS> CreateAsync(CreateMRSRequest dto, string createdBy);
Task<MRS?> GetByIdAsync(long mrsId, CancellationToken ct); Task ApproveAsync(long mrsId, string approvedBy);
Task<MRS> CreateAsync(CreateMRSRequest dto, string createdBy, CancellationToken ct);
Task ApproveAsync(long mrsId, string approvedBy, CancellationToken ct);
Task CancelAsync(CancelMRSRequest request, string canceledBy, CancellationToken ct);
} }
} }

View File

@ -13,10 +13,10 @@ namespace CPRNIMS.Domain.Contracts.Inventory
{ {
public interface IRIS public interface IRIS
{ {
Task<RISPagedResult> GetPagedAsync(RISFilterDto filter, CancellationToken ct, int? departmentId = null, string? userName = ""); Task<RISPagedResult> GetPagedAsync(RISFilterDto filter, CancellationToken ct);
Task<RISResponse?> GetByIdAsync(long risId, CancellationToken ct); Task<RISResponse?> GetByIdAsync(long risId, CancellationToken ct);
Task<Infrastructure.Entities.Inventory.RIS> CreateAsync(CreateRISRequest dto, string createdBy, CancellationToken ct); Task<Infrastructure.Entities.Inventory.RIS> CreateAsync(CreateRISRequest dto, string createdBy, CancellationToken ct);
Task ApproveAsync(ApproveRISRequest request, string approvedBy, CancellationToken ct); Task ApproveAsync(ApproveRISRequest request, string approvedBy, CancellationToken ct);
Task CancelAsync(CancelRISRequest request,string canceledBy, CancellationToken ct); Task CancelAsync(CancelRISRequest request, CancellationToken ct);
} }
} }

View File

@ -16,14 +16,14 @@ namespace CPRNIMS.Domain.Contracts.Items
Task<List<Departments>> GetDepartment(ItemCodeDto itemCode); Task<List<Departments>> GetDepartment(ItemCodeDto itemCode);
Task<PagedResult<ItemList>> GetItemList(ItemCodeDto itemCode); Task<PagedResult<ItemList>> GetItemList(ItemCodeDto itemCode);
Task<List<ItemCart>> GetItemCart(ItemDto itemDto); Task<List<ItemCart>> GetItemCart(ItemDto itemDto);
Task<List<ItemDtos>> GetItemDetail(ItemDto itemDto); Task<List<Item>> GetItemDetail(ItemDto itemDto);
Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto); Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto);
Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto); Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto);
Task<List<ItemColor>> GetItemColor(ItemDto itemDto); Task<List<ItemColor>> GetItemColor(ItemDto itemDto);
Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto); Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto);
Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto); Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto);
Task<IReadOnlyList<ProjectCodes>> GetProjectCode(); Task<List<ProjectCodes>> GetProjectCode();
Task<IReadOnlyList<ProjectCodes>> GetProjectCodeByTerm(string? fileName); Task<List<ProjectCodes>> GetProjectCodeByTerm(string? fileName);
Task<(long, long)> GetPRNo(); Task<(long, long)> GetPRNo();
Task<ResponseObject> PostPurchRequest(ItemDto itemDto); Task<ResponseObject> PostPurchRequest(ItemDto itemDto);
Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto); Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto);

View File

@ -70,7 +70,6 @@ namespace CPRNIMS.Domain.Contracts.PO
Task<Incoterm> PostPutIncoterms(PODto pODto); Task<Incoterm> PostPutIncoterms(PODto pODto);
Task<bool> DeleteIncShip(PODto poDto); Task<bool> DeleteIncShip(PODto poDto);
Task<bool> PostIncShipFollowUp(PODto pODto); Task<bool> PostIncShipFollowUp(PODto pODto);
Task<IReadOnlyList<Currencies>> GetCurrencies(string currencyName, CancellationToken ct);
#endregion #endregion
} }
} }

View File

@ -12,7 +12,7 @@ namespace CPRNIMS.Domain.Contracts.Receiving
public interface IReceiving public interface IReceiving
{ {
Task<List<ReceivingDetail>> GetRRDetailByPO(ItemDto itemDto); Task<List<ReceivingDetail>> GetRRDetailByPO(ItemDto itemDto);
Task<List<RRDetailDto>> GetRRDetail(ItemDto itemDto); Task<List<RRDetail>> GetRRDetail(ItemDto itemDto);
Task<List<ForReceiving>> GetForReceiving(ItemDto itemDto); Task<List<ForReceiving>> GetForReceiving(ItemDto itemDto);
Task<List<RR>> GetRR(ItemDto itemDto); Task<List<RR>> GetRR(ItemDto itemDto);
Task<List<RRSeries>> GetLatestRRNo(ItemDto itemDto); Task<List<RRSeries>> GetLatestRRNo(ItemDto itemDto);

View File

@ -1,16 +0,0 @@
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using FastReport;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Reports
{
public interface IReportBuilder
{
Task<Report> RISBuildAsync(DateTime dateFrom, DateTime dateTo, string templatePath, CancellationToken ct);
Task<Report> MRSBuildAsync(DateTime dateFrom, DateTime dateTo, string templatePath, CancellationToken ct);
}
}

View File

@ -1,16 +0,0 @@
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Reports
{
public interface IReportDataService
{
List<RISRowDto> GetMain(DateTime dateFrom, DateTime dateTo);
List<DisciplineAggDto> GetDisciplines(DateTime dateFrom, DateTime dateTo);
List<TopRecipientDto> GetRecipients(DateTime dateFrom, DateTime dateTo);
}
}

View File

@ -57,7 +57,6 @@ namespace CPRNIMS.Domain.Services.Account
new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim("FullName", user.FullName ?? ""), new Claim("FullName", user.FullName ?? ""),
new Claim("Company", user.Company ?? ""), new Claim("Company", user.Company ?? ""),
new Claim("DepartmentId", Convert.ToString(user.DepartmentId)),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
}; };

View File

@ -1,49 +0,0 @@
using CPRNIMS.Domain.Contracts.Common;
using CPRNIMS.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace CPRNIMS.Domain.Services.Common
{
public class TransactionFacade : ITransactionFacade
{
private readonly NonInventoryDbContext _db;
public TransactionFacade(NonInventoryDbContext db)
=> _db = db ?? throw new ArgumentNullException(nameof(db));
public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(operation);
var strategy = _db.Database.CreateExecutionStrategy();
return await strategy.ExecuteAsync(async () =>
{
await using var tx = await _db.Database.BeginTransactionAsync(ct);
try
{
var result = await operation();
await _db.SaveChangesAsync(ct);
await tx.CommitAsync(ct);
return result;
}
catch
{
await tx.RollbackAsync(ct);
throw;
}
});
}
public async Task ExecuteAsync(Func<Task> operation, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(operation);
await ExecuteAsync<bool>(async () =>
{
await operation();
return true;
}, ct);
}
}
}

View File

@ -40,7 +40,7 @@ namespace CPRNIMS.Domain.Services.Finance
return allItems ?? new List<ReceivingDetail>(); return allItems ?? new List<ReceivingDetail>();
} }
public async Task<RRDetailDto> PostPutPayment(RRDetailsDto itemDto) public async Task<RRDetail> PostPutPayment(RRDetailsDto itemDto)
{ {
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutPayment @UserId, @PONo, @POTypeId, @PRDetailsId", .ExecuteSqlRawAsync("EXEC PostPutPayment @UserId, @PONo, @POTypeId, @PRDetailsId",
@ -48,7 +48,7 @@ namespace CPRNIMS.Domain.Services.Finance
new SqlParameter("@PONo", itemDto.PONo), new SqlParameter("@PONo", itemDto.PONo),
new SqlParameter("@POTypeId", itemDto.POTypeId), new SqlParameter("@POTypeId", itemDto.POTypeId),
new SqlParameter("@PRDetailsId", itemDto.PRDetailsId)); new SqlParameter("@PRDetailsId", itemDto.PRDetailsId));
return new RRDetailDto(); return new RRDetail();
} }
} }
} }

View File

@ -3,9 +3,7 @@ using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory; using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response; using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Inventory; using CPRNIMS.Infrastructure.Entities.Inventory;
using Microsoft.AspNetCore.Identity;
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System; using System;
@ -19,11 +17,9 @@ namespace CPRNIMS.Domain.Services.Inventory
public class Inventory : IInventory public class Inventory : IInventory
{ {
private readonly NonInventoryDbContext _dbContext; private readonly NonInventoryDbContext _dbContext;
private readonly UserManager<ApplicationUser> _userManager; public Inventory(NonInventoryDbContext dbContext)
public Inventory(NonInventoryDbContext dbContext, UserManager<ApplicationUser> userManager)
{ {
_dbContext = dbContext; _dbContext = dbContext;
_userManager = userManager;
} }
public async Task<TransactContextDto?> GetTransactContextAsync(int inventoryId, CancellationToken ct) public async Task<TransactContextDto?> GetTransactContextAsync(int inventoryId, CancellationToken ct)
{ {
@ -83,7 +79,7 @@ namespace CPRNIMS.Domain.Services.Inventory
.ToListAsync(ct); .ToListAsync(ct);
var disciplines = await GetDisciplinesAsync(ct); var disciplines = await GetDisciplinesAsync(ct);
var projectCodes = await GetProjectCodesAsync(ct);
return new TransactContextDto return new TransactContextDto
{ {
InventoryId = inv.InventoryId, InventoryId = inv.InventoryId,
@ -95,15 +91,13 @@ namespace CPRNIMS.Domain.Services.Inventory
QtyOnHand = inv.QtyOnHand, QtyOnHand = inv.QtyOnHand,
QtyIn = inv.QtyIn, QtyIn = inv.QtyIn,
QtyOut = inv.QtyOut, QtyOut = inv.QtyOut,
ProjectCodes = projectCodes,
Disciplines = disciplines, Disciplines = disciplines,
OpenRISList = openRIS OpenRISList = openRIS
}; };
} }
public async Task<IReadOnlyList<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct) public async Task<IEnumerable<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct)
{ {
return await _dbContext.Disciplines return await _dbContext.Disciplines
.AsNoTracking()
.OrderBy(d => d.DisciplineName) .OrderBy(d => d.DisciplineName)
.Select(d => new DisciplineDto .Select(d => new DisciplineDto
{ {
@ -112,19 +106,6 @@ namespace CPRNIMS.Domain.Services.Inventory
}) })
.ToListAsync(ct); .ToListAsync(ct);
} }
public async Task<IReadOnlyList<ProjectCodeDto>> GetProjectCodesAsync(CancellationToken ct)
{
return await _dbContext.ProjectCodes
.Where(p => p.StatusName != "Completed" && p.IsActive)
.OrderBy(d => d.ProjectName)
.Select(d => new ProjectCodeDto
{
ProjectCodeId = d.ProjectCodeId,
ProjectCode = d.ProjectCode ?? "N/A",
ProjectName = d.ProjectName ?? "N/A"
})
.ToListAsync(ct);
}
public async Task<List<ItemDetail>> GetInventoryById(InventoryDto itemDto) public async Task<List<ItemDetail>> GetInventoryById(InventoryDto itemDto)
{ {
var allItems = await _dbContext.ItemDetails var allItems = await _dbContext.ItemDetails

View File

@ -1,307 +0,0 @@
using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Drawing.Printing;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CPRNIMS.Domain.Services.Inventory
{
public class InventoryReports : IInventoryReports
{
private readonly NonInventoryDbContext _db;
public InventoryReports(NonInventoryDbContext db) => _db = db;
public async Task<RISReportDto> GetRISReportAsync(InventoryReportsRequest request, string userName, int? departmentId, CancellationToken ct)
{
var endDate = request.DateTo.Date.AddDays(1);
var allowedAllDeptUsers = new[] { "LSKRISUR24", "LSCYNDIZ25", "LSJONTAN25", "LHRIOCAS24" };
bool seeAllDepartments = !string.IsNullOrWhiteSpace(userName)
&& allowedAllDeptUsers.Contains(userName, StringComparer.OrdinalIgnoreCase);
var dateToInclusive = request.DateTo.AddDays(1);
var query = _db.RIS
.Include(r => r.Discipline)
.Include(r => r.Inventory)
.Include(r => r.MaterialReturns)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.Where(r => r.CreatedDate >= request.DateFrom && r.CreatedDate < dateToInclusive);
if (departmentId.HasValue && !seeAllDepartments)
{
query = query.Where(m =>
m.Inventory.User != null &&
m.Inventory.User.DepartmentId == departmentId.Value);
}
var rows = await query
.OrderByDescending(r => r.CreatedDate)
.Select(r => new RISReportRow
{
RISNo = r.RISNo,
CreatedDate = r.CreatedDate,
ItemName = r.PRDetail != null ? r.PRDetail.ItemName : "—",
ItemNo = r.Inventory.ItemNo,
DisciplineName = r.Discipline.DisciplineName,
ProjectName = r.ProjectCodes.ProjectName,
QtyIssued = r.QtyIssued,
TotalReturned = r.MaterialReturns
.Where(m => m.Status != 2)
.Sum(m => (int?)m.QtyReturned) ?? 0,
Status = r.Status,
StatusLabel = r.Status == 0 ? "Draft"
: r.Status == 1 ? "Approved"
: "Cancelled"
})
.ToListAsync(ct);
foreach (var row in rows)
row.NetIssued = row.QtyIssued - row.TotalReturned;
var summary = new RISReportSummary
{
TotalRIS = rows.Count,
TotalApproved = rows.Count(r => r.Status == 1),
TotalPending = rows.Count(r => r.Status == 0),
TotalCancelled = rows.Count(r => r.Status == 2),
TotalQtyIssued = rows.Sum(r => r.QtyIssued),
TotalQtyReturned = rows.Sum(r => r.TotalReturned),
TotalNetIssued = rows.Sum(r => r.NetIssued),
ApprovalRatePct = rows.Count > 0
? Math.Round(rows.Count(r => r.Status == 1) * 100m / rows.Count, 1)
: 0
};
var byDiscipline = rows
.GroupBy(r => r.DisciplineName)
.Select(g => new DisciplineCount { DisciplineName = g.Key, Count = g.Count() })
.OrderByDescending(d => d.Count)
.ToList();
var topRecipients = rows
.GroupBy(r => r.ProjectName)
.Select(g => new TopRecipient
{
IssuedTo = g.Key,
SlipCount = g.Count(),
TotalQty = g.Sum(r => r.QtyIssued)
})
.OrderByDescending(t => t.TotalQty)
.Take(5)
.ToList();
return new RISReportDto
{
ReportNo = $"RPT-RIS-{DateTime.Now:yyyyMM}-{Random.Shared.Next(1, 999):D3}",
DateFrom = request.DateFrom,
DateTo = request.DateTo,
Summary = summary,
Rows = rows,
ByDiscipline = byDiscipline,
TopRecipients = topRecipients
};
}
public async Task<MRSReportDto> GetMRSReportAsync(InventoryReportsRequest request, string userName, int? departmentId, CancellationToken ct)
{
var endDate = request.DateTo.Date.AddDays(1);
var allowedAllDeptUsers = new[] { "LSKRISUR24", "LSCYNDIZ25", "LSJONTAN25", "LHRIOCAS24" };
bool seeAllDepartments = !string.IsNullOrWhiteSpace(userName)
&& allowedAllDeptUsers.Contains(userName, StringComparer.OrdinalIgnoreCase);
var query = _db.MRS
.Include(m => m.RIS)
.Include(m => m.Inventory)
.ThenInclude(i => i.User)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.Where(m => m.CreatedDate >= request.DateFrom &&
m.CreatedDate < endDate);
if (departmentId.HasValue && !seeAllDepartments)
{
query = query.Where(m =>
m.Inventory.User != null &&
m.Inventory.User.DepartmentId == departmentId.Value);
}
var rows = await query
.OrderByDescending(m => m.CreatedDate)
.Select(m => new MRSReportRow
{
MRSNo = m.MRSNo,
CreatedDate = m.CreatedDate,
RISNo = m.RIS.RISNo,
ItemName = m.RIS.PRDetail != null ? m.RIS.PRDetail.ItemName : "—",
ReturnedBy = m.ReturnedBy,
QtyReturned = m.QtyReturned,
Condition = m.Condition ?? "Good",
Status = m.Status,
StatusLabel = m.Status == 0 ? "Draft"
: m.Status == 1 ? "Approved"
: "Cancelled"
})
.ToListAsync(ct);
// Total RIS qty issued in the same period (for the comparison panel)
var totalRISQty = await _db.RIS
.Where(r => r.CreatedDate >= request.DateFrom && r.CreatedDate < endDate
&& r.Status != 2)
.SumAsync(r => (int?)r.QtyIssued, ct) ?? 0;
var totalReturned = rows.Where(r => r.Status != 2).Sum(r => r.QtyReturned);
var goodCount = rows.Count(r => r.Condition == "Good");
var summary = new MRSReportSummary
{
TotalMRS = rows.Count,
TotalQtyReturned = totalReturned,
TotalQtyIssuedRIS = totalRISQty,
NetQtyConsumed = totalRISQty - totalReturned,
ReturnRatePct = totalRISQty > 0
? Math.Round(totalReturned * 100m / totalRISQty, 1)
: 0,
GoodConditionPct = rows.Count > 0
? Math.Round(goodCount * 100m / rows.Count, 1)
: 0
};
var byCondition = rows
.Where(r => r.Status != 2)
.GroupBy(r => r.Condition)
.Select(g => new ConditionTotal { Condition = g.Key, TotalQty = g.Sum(r => r.QtyReturned) })
.OrderByDescending(c => c.TotalQty)
.ToList();
return new MRSReportDto
{
ReportNo = $"RPT-MRS-{DateTime.Now:yyyyMM}-{Random.Shared.Next(1, 999):D3}",
DateFrom = request.DateFrom,
DateTo = request.DateTo,
Summary = summary,
Rows = rows,
ByCondition = byCondition
};
}
public async Task<InventoryReportDto> GetInventoryReportAsync(InventoryReportsRequest request, string userName, int? departmentId, CancellationToken ct)
{
var allowedAllDeptUsers = new[] { "LSKRISUR24", "LSCYNDIZ25", "LSJONTAN25", "LHRIOCAS24" };
bool seeAllDepartments = !string.IsNullOrWhiteSpace(userName)
&& allowedAllDeptUsers.Contains(userName, StringComparer.OrdinalIgnoreCase);
var endDate = request.DateTo.Date.AddDays(1);
var dto = new InventoryReportDto
{
ReportNo = $"RPT-INV-{DateTime.Now:yyyyMM}-{Random.Shared.Next(1, 999):D3}",
AsOf = endDate,
Rows = new List<InventoryReportRow>(),
ByCategory = new List<CategoryStockLevel>(),
Alerts = new List<InventoryAlert>(),
Summary = new InventoryReportSummary(),
Departments = new List<string>(),
Page = request.Page,
PageSize = request.PageSize
};
var conn = _db.Database.GetDbConnection();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "dbo.GetInventoryReport";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@DateFrom", (object?)request.DateFrom ?? DBNull.Value));
cmd.Parameters.Add(new SqlParameter("@DateTo", (object?)request.DateTo ?? DBNull.Value));
cmd.Parameters.Add(new SqlParameter("@Department", (object?)request.Department ?? DBNull.Value));
cmd.Parameters.Add(new SqlParameter("@DepartmentId", (object?)departmentId ?? DBNull.Value));
cmd.Parameters.Add(new SqlParameter("@SeeAllDepartments", seeAllDepartments ? 1 : 0));
cmd.Parameters.Add(new SqlParameter("@Page", request.Page));
cmd.Parameters.Add(new SqlParameter("@PageSize", request.PageSize));
cmd.Parameters.Add(new SqlParameter("@Paginate", request.Paginate ? 1 : 0));
bool openedHere = conn.State != System.Data.ConnectionState.Open;
if (openedHere) await conn.OpenAsync(ct);
try
{
await using var reader = await cmd.ExecuteReaderAsync(ct);
// 0: departments
while (await reader.ReadAsync(ct))
dto.Departments.Add(reader.GetString(reader.GetOrdinal("Department")));
// 1: detail rows
if (await reader.NextResultAsync(ct))
{
while (await reader.ReadAsync(ct))
{
dto.Rows.Add(new InventoryReportRow
{
ItemName = reader.GetString(reader.GetOrdinal("ItemName")),
ItemNo = reader.GetInt64(reader.GetOrdinal("ItemNo")),
ItemCategoryName = reader.GetString(reader.GetOrdinal("ItemCategoryName")),
LotNo = reader.IsDBNull(reader.GetOrdinal("LotNo")) ? null : reader.GetString(reader.GetOrdinal("LotNo")),
Department = reader.IsDBNull(reader.GetOrdinal("Department")) ? null : reader.GetString(reader.GetOrdinal("Department")),
CurrencyCode = reader.IsDBNull(reader.GetOrdinal("CurrencyCode")) ? null : reader.GetString(reader.GetOrdinal("CurrencyCode")),
QtyIn = reader.GetDecimal(reader.GetOrdinal("QtyIn")),
QtyOut = reader.GetDecimal(reader.GetOrdinal("QtyOut")),
QtyOnHand = reader.GetDecimal(reader.GetOrdinal("QtyOnHand")),
UnitPrice = reader.GetDecimal(reader.GetOrdinal("UnitPrice")),
StockPct = reader.GetInt32(reader.GetOrdinal("StockPct"))
});
}
}
// 2: summary
if (await reader.NextResultAsync(ct) && await reader.ReadAsync(ct))
{
dto.Summary = new InventoryReportSummary
{
TotalSKUs = reader.GetInt32(reader.GetOrdinal("TotalSKUs")),
TotalOnHand = reader.GetDecimal(reader.GetOrdinal("TotalOnHand")),
TotalQtyIn = reader.GetDecimal(reader.GetOrdinal("TotalQtyIn")),
TotalQtyOut = reader.GetDecimal(reader.GetOrdinal("TotalQtyOut")),
TotalValue = reader.GetDecimal(reader.GetOrdinal("TotalValue")),
LowStockCount = reader.GetInt32(reader.GetOrdinal("LowStockCount")),
OutOfStockCount = reader.GetInt32(reader.GetOrdinal("OutOfStockCount"))
};
}
// 3: by category
if (await reader.NextResultAsync(ct))
while (await reader.ReadAsync(ct))
dto.ByCategory.Add(new CategoryStockLevel
{
CategoryName = reader.GetString(reader.GetOrdinal("CategoryName")),
AvgStockPct = reader.GetInt32(reader.GetOrdinal("AvgStockPct"))
});
// 4: alerts
if (await reader.NextResultAsync(ct))
while (await reader.ReadAsync(ct))
dto.Alerts.Add(new InventoryAlert
{
ItemName = reader.GetString(reader.GetOrdinal("ItemName")),
QtyOnHand = reader.GetDecimal(reader.GetOrdinal("QtyOnHand")),
Severity = reader.GetString(reader.GetOrdinal("Severity"))
});
// 5: total row count
if (await reader.NextResultAsync(ct) && await reader.ReadAsync(ct))
dto.TotalRows = reader.GetInt32(reader.GetOrdinal("TotalRows"));
}
finally
{
if (conn.State == System.Data.ConnectionState.Open)
await conn.CloseAsync();
}
return dto;
}
}
}

View File

@ -1,35 +1,25 @@
using CPRNIMS.Domain.Contracts.Common; using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory; using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Entities.Inventory; using CPRNIMS.Infrastructure.Entities.Inventory;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services.Inventory namespace CPRNIMS.Domain.Services.Inventory
{ {
public class MRS : IMRS public class MRS : IMRS
{ {
private readonly NonInventoryDbContext _db; private readonly NonInventoryDbContext _db;
private readonly ITransactionFacade _transactionFacade; public MRS(NonInventoryDbContext db) => _db = db;
public MRS(NonInventoryDbContext db, ITransactionFacade transactionFacade)
{
_db = db;
_transactionFacade = transactionFacade;
}
public async Task ApproveAsync(long mrsId, string approvedBy, CancellationToken ct)
{
//var user = await _userManager.FindByNameAsync(approvedBy);
//if (user != null)
//{
// bool isApprover2 = await _userManager.IsInRoleAsync(user, "APPROVER2");
// if (!isApprover2)
// {
// throw new Exception("You have no permission to approve this item.");
// }
//}
public async Task ApproveAsync(long mrsId, string approvedBy)
{
var rms = await _db.MRS.FindAsync(mrsId) var rms = await _db.MRS.FindAsync(mrsId)
?? throw new InvalidOperationException("MRS not found."); ?? throw new InvalidOperationException("MRS not found.");
@ -40,49 +30,14 @@ namespace CPRNIMS.Domain.Services.Inventory
rms.ApprovedBy = approvedBy; rms.ApprovedBy = approvedBy;
rms.ApprovedDate = DateTime.Now; rms.ApprovedDate = DateTime.Now;
await _db.SaveChangesAsync(ct); await _db.SaveChangesAsync();
} }
public async Task CancelAsync(CancelMRSRequest request,string canceledBy, CancellationToken ct) public async Task<Infrastructure.Entities.Inventory.MRS> CreateAsync(CreateMRSRequest dto, string createdBy)
{
//var user = await _userManager.FindByNameAsync(canceledBy);
//if (user != null)
//{
// bool isApprover2 = await _userManager.IsInRoleAsync(user, "APPROVER2");
// if (!isApprover2)
// {
// throw new Exception("You have no permission to cancel this item.");
// }
//}
await _transactionFacade.ExecuteAsync(async () =>
{
var mrs = await _db.MRS
.Include(m => m.Inventory)
.FirstOrDefaultAsync(m => m.MRSId == request.MRSId)
?? throw new InvalidOperationException("MRS not found.");
if (mrs.Status == 2)
throw new InvalidOperationException("MRS is already cancelled.");
// Reverse the return: deduct qty back out
mrs.Inventory.QtyOut = Math.Max(0m, mrs.Inventory.QtyOut) + mrs.QtyReturned;
mrs.Inventory.QtyOnHand = mrs.Inventory.QtyIn - mrs.Inventory.QtyOut;
mrs.Reason = request.Reason;
mrs.Status = 2;
mrs.CanceledDate = DateTime.Now;
mrs.CanceledBy = canceledBy;
}, ct);
}
public async Task<Infrastructure.Entities.Inventory.MRS> CreateAsync(CreateMRSRequest dto, string createdBy, CancellationToken ct)
{
return await _transactionFacade.ExecuteAsync(async () =>
{ {
var ris = await _db.RIS var ris = await _db.RIS
.Include(r => r.Inventory) .Include(r => r.Inventory)
.FirstOrDefaultAsync(r => r.RISId == dto.RISId, ct) .FirstOrDefaultAsync(r => r.RISId == dto.RISId)
?? throw new InvalidOperationException("Referenced RIS not found."); ?? throw new InvalidOperationException("Referenced RIS not found.");
if (dto.QtyReturned > ris.QtyIssued) if (dto.QtyReturned > ris.QtyIssued)
@ -100,7 +55,7 @@ namespace CPRNIMS.Domain.Services.Inventory
QtyReturned = dto.QtyReturned, QtyReturned = dto.QtyReturned,
Condition = dto.Condition, Condition = dto.Condition,
Remarks = dto.Remarks, Remarks = dto.Remarks,
Status = 1,//Matic Approve for now Status = 0,
CreatedBy = createdBy, CreatedBy = createdBy,
CreatedDate = DateTime.Now CreatedDate = DateTime.Now
}; };
@ -112,7 +67,7 @@ namespace CPRNIMS.Domain.Services.Inventory
inventory.QtyOnHand = inventory.QtyIn - inventory.QtyOut; inventory.QtyOnHand = inventory.QtyIn - inventory.QtyOut;
var trans = await _db.InventTrans var trans = await _db.InventTrans
.FirstOrDefaultAsync(t => t.InventoryId == ris.InventoryId && t.IsActive == true, ct)!; .FirstOrDefaultAsync(t => t.InventoryId == ris.InventoryId && t.IsActive == true)!;
_db.InventTransDetails.Add(new InventTransDetail _db.InventTransDetails.Add(new InventTransDetail
{ {
@ -124,35 +79,24 @@ namespace CPRNIMS.Domain.Services.Inventory
IsActive = true IsActive = true
}); });
await _db.SaveChangesAsync();
return mrs; return mrs;
}, ct);
} }
public async Task<Infrastructure.Entities.Inventory.MRS?> GetByIdAsync(long mrsId, CancellationToken ct) public async Task<Infrastructure.Entities.Inventory.MRS?> GetByIdAsync(long mrsId)
=> await _db.MRS => await _db.MRS
.Include(r => r.Inventory) .Include(r => r.Inventory)
.Include(r => r.RIS) .Include(r => r.RIS)
.FirstOrDefaultAsync(r => r.RISId == mrsId, ct); .FirstOrDefaultAsync(r => r.RISId == mrsId);
public async Task<MRSPagedResult> GetPagedAsync(MRSFilterDto filter, CancellationToken ct, public async Task<MRSPagedResult> GetPagedAsync(MRSFilterDto filter)
int? departmentId = null, string? userName = "")
{ {
var allowedAllDeptUsers = new[] { "LSKRISUR24", "LSCYNDIZ25", "LSJONTAN25", "LHRIOCAS24" };
bool seeAllDepartments = !string.IsNullOrWhiteSpace(userName)
&& allowedAllDeptUsers.Contains(userName, StringComparer.OrdinalIgnoreCase);
var q = _db.MRS var q = _db.MRS
.Include(m => m.RIS) .Include(m => m.RIS)
.Include(m => m.Inventory) .Include(m => m.Inventory)
.AsQueryable(); .AsQueryable();
if (departmentId.HasValue && !seeAllDepartments)
{
q = q.Where(itd =>
itd.Inventory.User.DepartmentId == departmentId.Value);
}
if (!string.IsNullOrWhiteSpace(filter.SearchMRSNo)) if (!string.IsNullOrWhiteSpace(filter.SearchMRSNo))
q = q.Where(m => m.MRSNo.Contains(filter.SearchMRSNo)); q = q.Where(m => m.MRSNo.Contains(filter.SearchMRSNo));
@ -168,13 +112,13 @@ namespace CPRNIMS.Domain.Services.Inventory
if (filter.DateTo.HasValue) if (filter.DateTo.HasValue)
q = q.Where(m => m.CreatedDate <= filter.DateTo.Value.AddDays(1)); q = q.Where(m => m.CreatedDate <= filter.DateTo.Value.AddDays(1));
var total = await q.CountAsync(ct); var total = await q.CountAsync();
var data = await q var data = await q
.OrderByDescending(m => m.CreatedDate) .OrderByDescending(m => m.CreatedDate)
.Skip((filter.PageNumber - 1) * filter.PageSize) .Skip((filter.Page - 1) * filter.PageSize)
.Take(filter.PageSize) .Take(filter.PageSize)
.Select(m => new MRSPagedDto .Select(m => new MRSResponse
{ {
MRSId = m.MRSId, MRSId = m.MRSId,
MRSNo = m.MRSNo, MRSNo = m.MRSNo,
@ -195,10 +139,11 @@ namespace CPRNIMS.Domain.Services.Inventory
ApprovedBy = m.ApprovedBy, ApprovedBy = m.ApprovedBy,
ApprovedDate = m.ApprovedDate ApprovedDate = m.ApprovedDate
}) })
.ToListAsync(ct); .ToListAsync();
return new MRSPagedResult { Data = data, RecordsTotal = total }; return new MRSPagedResult { Data = data, RecordsTotal = total };
} }
private async Task<string> GenerateMRSNoAsync() private async Task<string> GenerateMRSNoAsync()
{ {
var year = DateTime.Now.Year; var year = DateTime.Now.Year;
@ -206,55 +151,5 @@ namespace CPRNIMS.Domain.Services.Inventory
var count = await _db.MRS.CountAsync(m => m.CreatedDate.Year == year) + 1; var count = await _db.MRS.CountAsync(m => m.CreatedDate.Year == year) + 1;
return $"MRS-{year}{month}-{count:D4}"; return $"MRS-{year}{month}-{count:D4}";
} }
public async Task<IReadOnlyList<RISSearchResultDto>> SearchRISForReturnAsync(string? risNoQuery, int? projectCodeId, CancellationToken ct)
{
var query = _db.RIS
.Where(r => r.Status == 1);
if (projectCodeId.HasValue)
query = query.Where(r => r.ProjectCodeId == projectCodeId.Value);
if (!string.IsNullOrWhiteSpace(risNoQuery))
query = query.Where(r => r.RISNo.Contains(risNoQuery));
return await query
.Select(r => new RISSearchResultDto
{
RISId = r.RISId,
RISNo = r.RISNo,
ProjectCodeId = r.ProjectCodeId,
ProjectCode = r.ProjectCodes.ProjectCode ?? "N/A",
ProjectName = r.ProjectCodes.ProjectName ?? "N/A",
DisciplineName = r.Discipline.DisciplineName,
QtyAvailableToReturn = r.QtyIssued - r.MaterialReturns.Sum(m => m.QtyReturned)
})
.Where(r => r.QtyAvailableToReturn > 0)
.OrderByDescending(r => r.RISId)
.Take(20)
.ToListAsync(ct);
}
public async Task<IReadOnlyList<ProjectCodeOptionDto>> GetProjectsWithOpenRISAsync(string? nameQuery, CancellationToken ct)
{
var query = _db.RIS
.Where(r => r.Status == 1 && r.QtyIssued > r.MaterialReturns.Sum(m => m.QtyReturned));
if (!string.IsNullOrWhiteSpace(nameQuery))
query = query.Where(r =>
r.ProjectCodes.ProjectName.Contains(nameQuery) ||
r.ProjectCodes.ProjectCode.Contains(nameQuery));
return await query
.Select(r => new ProjectCodeOptionDto
{
ProjectCodeId = r.ProjectCodeId,
ProjectCode = r.ProjectCodes.ProjectCode ?? "N/A",
ProjectName = r.ProjectCodes.ProjectName ?? "N/A"
})
.Distinct()
.OrderBy(p => p.ProjectName)
.Take(20)
.ToListAsync(ct);
}
} }
} }

View File

@ -1,5 +1,5 @@
using CPRNIMS.Domain.Contracts.Common; using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Domain.Contracts.Inventory; using CPRNIMS.Domain.UIServices.Inventory;
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory; using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
@ -17,15 +17,17 @@ namespace CPRNIMS.Domain.Services.Inventory
public class RIS : IRIS public class RIS : IRIS
{ {
private readonly NonInventoryDbContext _db; private readonly NonInventoryDbContext _db;
private readonly ITransactionFacade _transactionFacade;
public RIS(NonInventoryDbContext db, ITransactionFacade transactionFacade) public RIS(NonInventoryDbContext db) => _db = db;
{
_db = db;
_transactionFacade = transactionFacade;
}
public async Task<Infrastructure.Entities.Inventory.RIS> CreateAsync(CreateRISRequest dto, string createdBy, CancellationToken ct) public async Task<Infrastructure.Entities.Inventory.RIS> CreateAsync(CreateRISRequest dto, string createdBy, CancellationToken ct)
{ {
return await _transactionFacade.ExecuteAsync(async () => var strategy = _db.Database.CreateExecutionStrategy();
return await strategy.ExecuteAsync(async () =>
{
await using var tx = await _db.Database.BeginTransactionAsync(ct);
try
{ {
var inventory = await _db.Inventories var inventory = await _db.Inventories
.FirstOrDefaultAsync(i => i.InventoryId == dto.InventoryId, ct) .FirstOrDefaultAsync(i => i.InventoryId == dto.InventoryId, ct)
@ -42,15 +44,16 @@ namespace CPRNIMS.Domain.Services.Inventory
RISNo = risNo, RISNo = risNo,
InventoryId = dto.InventoryId, InventoryId = dto.InventoryId,
PRDetailId = dto.PRDetailId, PRDetailId = dto.PRDetailId,
ProjectCodeId = dto.ProjectCodeId, IssuedTo = dto.IssuedTo,
DisciplineId = dto.DisciplineId, DisciplineId = dto.DisciplineId,
QtyIssued = dto.QtyIssued, QtyIssued = dto.QtyIssued,
Remarks = dto.Remarks, Remarks = dto.Remarks,
Status = 1,//Approved alredy 0 is Draft Status = 0,
CreatedBy = createdBy, CreatedBy = createdBy,
CreatedDate = DateTime.Now CreatedDate = DateTime.Now
}; };
_db.RIS.Add(ris); _db.RIS.Add(ris);
await _db.SaveChangesAsync(ct);
var trans = await _db.InventTrans var trans = await _db.InventTrans
.Where(t => t.InventoryId == dto.InventoryId && t.IsActive == true) .Where(t => t.InventoryId == dto.InventoryId && t.IsActive == true)
@ -72,23 +75,21 @@ namespace CPRNIMS.Domain.Services.Inventory
inventory.QtyOut = Math.Max(0m, inventory.QtyOut) + dto.QtyIssued; inventory.QtyOut = Math.Max(0m, inventory.QtyOut) + dto.QtyIssued;
inventory.QtyOnHand = Math.Max(0m, inventory.QtyIn) - (decimal)inventory.QtyOut; inventory.QtyOnHand = Math.Max(0m, inventory.QtyIn) - (decimal)inventory.QtyOut;
await _db.SaveChangesAsync(ct);
await tx.CommitAsync(ct);
return ris; return ris;
}, ct); }
catch
{
await tx.RollbackAsync(ct);
throw;
}
});
} }
public async Task ApproveAsync(ApproveRISRequest request, string approvedBy, CancellationToken ct) public async Task ApproveAsync(ApproveRISRequest request, string approvedBy, CancellationToken ct)
{ {
//var user = await _userManager.FindByNameAsync(approvedBy);
//if (user != null)
//{
// bool isApprover2 = await _userManager.IsInRoleAsync(user, "APPROVER2");
// if (!isApprover2)
// {
// throw new Exception("You have no permission to approved this item.");
// }
//}
var ris = await _db.RIS.FindAsync(request.RISId, ct) var ris = await _db.RIS.FindAsync(request.RISId, ct)
?? throw new InvalidOperationException("RIS not found."); ?? throw new InvalidOperationException("RIS not found.");
@ -102,20 +103,14 @@ namespace CPRNIMS.Domain.Services.Inventory
await _db.SaveChangesAsync(ct); await _db.SaveChangesAsync(ct);
} }
public async Task CancelAsync(CancelRISRequest request,string canceledBy, CancellationToken ct) public async Task CancelAsync(CancelRISRequest request, CancellationToken ct)
{ {
//var user = await _userManager.FindByNameAsync(canceledBy); var strategy = _db.Database.CreateExecutionStrategy();
//if (user != null)
//{
// bool isApprover2 = await _userManager.IsInRoleAsync(user, "APPROVER2");
// if (!isApprover2) await strategy.ExecuteAsync(async () =>
// { {
// throw new Exception("You have no permission to cancel this item."); await using var tx = await _db.Database.BeginTransactionAsync(ct);
// } try
//}
await _transactionFacade.ExecuteAsync(async () =>
{ {
var ris = await _db.RIS var ris = await _db.RIS
.Include(r => r.Inventory) .Include(r => r.Inventory)
@ -125,23 +120,6 @@ namespace CPRNIMS.Domain.Services.Inventory
if (ris.Status == 2) if (ris.Status == 2)
throw new InvalidOperationException("RIS is already cancelled."); throw new InvalidOperationException("RIS is already cancelled.");
//Check if already approved the related RIS No to MRS must cannot be cancel
var mrs = await _db.MRS.FirstOrDefaultAsync(m => m.RISId == request.RISId, ct);
if (mrs != null)
{
if (mrs.Status == 1)
{
throw new InvalidOperationException(
$"MRS #{mrs.MRSNo} has already been approved in relation to RIS #{ris.RISNo}.");
}
mrs.Status = 2;
mrs.CanceledDate = DateTime.Now;
mrs.CanceledBy = canceledBy;
mrs.Reason = "Canceled in RIS already";
}
ris.Inventory.QtyOut = Math.Max(0m, ris.Inventory.QtyOut - ris.QtyIssued); ris.Inventory.QtyOut = Math.Max(0m, ris.Inventory.QtyOut - ris.QtyIssued);
ris.Inventory.QtyOnHand = ris.Inventory.QtyIn - ris.Inventory.QtyOut; ris.Inventory.QtyOnHand = ris.Inventory.QtyIn - ris.Inventory.QtyOut;
ris.Reason = request.Reason; ris.Reason = request.Reason;
@ -163,7 +141,31 @@ namespace CPRNIMS.Domain.Services.Inventory
Remarks = request.Reason, Remarks = request.Reason,
IsActive = true IsActive = true
}); });
}, ct);
//var inventory = await _db.Inventories
// .FirstOrDefaultAsync(i => i.InventoryId == ris.InventoryId, ct)
// ?? throw new InvalidOperationException("Inventory record not found.");
//if (inventory.QtyOnHand < ris.QtyIssued)
// throw new InvalidOperationException(
// $"Insufficient stock. On hand: {inventory.QtyOnHand}, requested: {ris.QtyIssued}.");
////restore the QtyOnHand using ris.QtyIssued
//inventory.QtyOnHand = Math.Max(0m, inventory.QtyOnHand) + ris.QtyIssued;
////reduce the QtyOut using ris.QtyIssued as we cancel the return isuance slip
//inventory.QtyOut = Math.Max(0m, inventory.QtyOut) - ris.QtyIssued;
await _db.SaveChangesAsync(ct);
await tx.CommitAsync(ct);
return ris;
}
catch
{
await tx.RollbackAsync(ct);
throw;
}
});
} }
private async Task<string> GenerateRISNoAsync(CancellationToken ct) private async Task<string> GenerateRISNoAsync(CancellationToken ct)
@ -175,30 +177,19 @@ namespace CPRNIMS.Domain.Services.Inventory
return $"RIS-{year}{month}-{count:D4}"; // e.g. RIS-202606-0001 return $"RIS-{year}{month}-{count:D4}"; // e.g. RIS-202606-0001
} }
public async Task<RISPagedResult> GetPagedAsync(RISFilterDto filter, CancellationToken ct, public async Task<RISPagedResult> GetPagedAsync(RISFilterDto filter, CancellationToken ct)
int? departmentId = null, string? userName = "")
{ {
var allowedAllDeptUsers = new[] { "LSKRISUR24", "LSCYNDIZ25", "LSJONTAN25", "LHRIOCAS24" };
bool seeAllDepartments = !string.IsNullOrWhiteSpace(userName)
&& allowedAllDeptUsers.Contains(userName, StringComparer.OrdinalIgnoreCase);
var q = _db.RIS var q = _db.RIS
.Include(r => r.Discipline) .Include(r => r.Discipline)
.Include(r => r.Inventory) .Include(r => r.Inventory)
.Include(r => r.MaterialReturns) .Include(r => r.MaterialReturns)
.AsQueryable(); .AsQueryable();
if (departmentId.HasValue && !seeAllDepartments)
{
q = q.Where(itd =>
itd.Inventory.User.DepartmentId == departmentId.Value);
}
// Status filter (default to Draft=0 if null) // Status filter (default to Draft=0 if null)
if (filter.Status.HasValue) if (filter.Status.HasValue)
q = q.Where(r => r.Status == filter.Status.Value); q = q.Where(r => r.Status == filter.Status.Value);
//else else
// q = q.Where(r => r.Status == 0); q = q.Where(r => r.Status == 0);
// RIS No // RIS No
if (!string.IsNullOrWhiteSpace(filter.SearchRISNo)) if (!string.IsNullOrWhiteSpace(filter.SearchRISNo))
@ -211,10 +202,9 @@ namespace CPRNIMS.Domain.Services.Inventory
.Any(d => d.PRDetails != null && .Any(d => d.PRDetails != null &&
d.PRDetails.ItemName.Contains(filter.SearchItemName))); d.PRDetails.ItemName.Contains(filter.SearchItemName)));
// Issued To is Project code/name // Issued To
if (!string.IsNullOrWhiteSpace(filter.SearchIssuedTo)) if (!string.IsNullOrWhiteSpace(filter.SearchIssuedTo))
q = q.Where(r => r.ProjectCodes.ProjectCode.Contains(filter.SearchIssuedTo) q = q.Where(r => r.IssuedTo.Contains(filter.SearchIssuedTo));
|| r.ProjectCodes.ProjectName.Contains(filter.SearchIssuedTo));
// Discipline // Discipline
if (!string.IsNullOrWhiteSpace(filter.Discipline)) if (!string.IsNullOrWhiteSpace(filter.Discipline))
@ -243,8 +233,7 @@ namespace CPRNIMS.Domain.Services.Inventory
.FirstOrDefault() ?? "—", .FirstOrDefault() ?? "—",
ItemNo = r.Inventory.ItemNo, ItemNo = r.Inventory.ItemNo,
LotNo = r.Inventory.Lot != null ? r.Inventory.Lot.LotName : null, LotNo = r.Inventory.Lot != null ? r.Inventory.Lot.LotName : null,
ProjectName = r.ProjectCodes.ProjectName, IssuedTo = r.IssuedTo,
ProjectCode = r.ProjectCodes.ProjectCode,
DisciplineName = r.Discipline.DisciplineName, DisciplineName = r.Discipline.DisciplineName,
DisciplineId = r.DisciplineId, DisciplineId = r.DisciplineId,
QtyIssued = r.QtyIssued, QtyIssued = r.QtyIssued,
@ -277,7 +266,7 @@ namespace CPRNIMS.Domain.Services.Inventory
DisciplineList = disciplines DisciplineList = disciplines
}; };
} }
public async Task<IReadOnlyList<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct) public async Task<IEnumerable<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct)
{ {
return await _db.Disciplines return await _db.Disciplines
.OrderBy(d => d.DisciplineName) .OrderBy(d => d.DisciplineName)
@ -288,19 +277,6 @@ namespace CPRNIMS.Domain.Services.Inventory
}) })
.ToListAsync(ct); .ToListAsync(ct);
} }
public async Task<IReadOnlyList<ProjectCodeDto>> GetProjectCodesAsync(CancellationToken ct)
{
return await _db.ProjectCodes
.Where(p=>p.StatusName !="Completed")
.OrderBy(d => d.ProjectName)
.Select(d => new ProjectCodeDto
{
ProjectCodeId= d.ProjectCodeId,
ProjectCode = d.ProjectCode ?? "N/A",
ProjectName = d.ProjectName ?? "N/A"
})
.ToListAsync(ct);
}
public async Task<RISResponse?> GetByIdAsync(long risId, CancellationToken ct) public async Task<RISResponse?> GetByIdAsync(long risId, CancellationToken ct)
{ {
return await _db.RIS return await _db.RIS
@ -310,7 +286,7 @@ namespace CPRNIMS.Domain.Services.Inventory
RISId = r.RISId, RISId = r.RISId,
RISNo = r.RISNo, RISNo = r.RISNo,
InventoryId = r.InventoryId, InventoryId = r.InventoryId,
ProjectCodeId = r.ProjectCodeId, IssuedTo = r.IssuedTo,
DisciplineName = r.Discipline.DisciplineName, DisciplineName = r.Discipline.DisciplineName,
DisciplineId = r.DisciplineId, DisciplineId = r.DisciplineId,
QtyIssued = r.QtyIssued, QtyIssued = r.QtyIssued,

View File

@ -63,6 +63,7 @@ namespace CPRNIMS.Domain.Services.Items
UserId = itemDto.UserId UserId = itemDto.UserId
}; };
} }
public async Task<Infrastructure.Entities.Items.Item> PutItemDetail(ItemDto itemDto) public async Task<Infrastructure.Entities.Items.Item> PutItemDetail(ItemDto itemDto)
{ {
await _dbContext.Database await _dbContext.Database
@ -91,6 +92,126 @@ namespace CPRNIMS.Domain.Services.Items
return new Infrastructure.Entities.Items.Item(); return new Infrastructure.Entities.Items.Item();
} }
public async Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto)
{
var localizations = await _dbContext.ItemLocalizations
.Where(ic => ic.IsActive == true &&
EF.Functions.Like(ic.ItemLocalName, $"%{itemDto.ItemLocalName}%"))
.Take(15)
.ToListAsync();
return localizations ?? new List<ItemLocalization>();
}
public async Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto)
{
if (itemDto.ItemCategoryId == 0 || itemDto.ItemCategoryId == null)
{
var categories = await _dbContext.ItemCategories
.Where(ic => ic.IsActive == true)
.ToListAsync();
return categories ?? new List<ItemCategory>();
}
else
{
var categories = await _dbContext.ItemCategories
.Where(ic => ic.IsActive == true && ic.ItemCategoryId == itemDto.ItemCategoryId)
.ToListAsync();
return categories ?? new List<ItemCategory>();
}
}
public async Task<List<Infrastructure.Entities.Items.Item>> GetItemDetail(ItemDto itemDto)
{
var allItems = await _dbContext.Items
.FromSqlRaw($"EXEC GetItemDetail @ItemCodeId,@UserId",
new SqlParameter("@ItemCodeId", itemDto.ItemCodeId),
new SqlParameter("@UserId", itemDto.UserId))
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Items.Item>();
}
public async Task<PagedResult<ItemList>> GetItemList(ItemCodeDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@SearchItemNo", dto.SearchItemNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchCategory", dto.SearchCategory ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
int totalCount = 0;
var items = new List<ItemList>();
var categoryList = new List<string>();
// Use ADO.NET to read two result sets
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = "EXEC GetItemList @UserId, @SearchItemNo,@SearchItemName,@SearchCategory, @PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
cmd.CommandTimeout = 60;
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
categoryList.Add(reader.GetString(0));
await reader.NextResultAsync();
if (await reader.ReadAsync())
totalCount = reader.GetInt32(0);
await reader.NextResultAsync();
while (await reader.ReadAsync())
{
items.Add(new ItemList
{
ItemCodeId = Convert.ToInt64(reader["ItemCodeId"]),
ItemNo = Convert.ToInt64(reader["ItemNo"]),
ItemName = reader["ItemName"]?.ToString(),
ItemDescription = reader["ItemDescription"]?.ToString(),
ItemCategoryName = reader["ItemCategoryName"]?.ToString(),
CartItemCount = Convert.ToInt32(reader["CartItemCount"])
});
}
await conn.CloseAsync();
return new PagedResult<ItemList>
{
Data = items,
TotalCount = totalCount,
CategoryList= categoryList,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize
};
}
public async Task<List<ItemColor>> GetItemColor(ItemDto itemDto)
{
var colors = await _dbContext.ItemColors
.Where(ic => EF.Functions.Like(ic.ItemColorName, $"%{itemDto.ItemColorName}%"))
.Take(5)
.ToListAsync();
return colors ?? new List<ItemColor>();
}
public async Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto)
{
var uoms = await _dbContext.UnitOfMessures
.Where(ic => ic.IsActive == true &&
EF.Functions.Like(ic.UOMName, $"%{itemDto.UOMName}%"))
.Take(150)
.ToListAsync();
return uoms ?? new List<UnitOfMessure>();
}
public async Task<ItemAttachement> PostPutItemPath(ItemDto itemDto) public async Task<ItemAttachement> PostPutItemPath(ItemDto itemDto)
{ {
var isExist = await _dbContext.ItemAttachements var isExist = await _dbContext.ItemAttachements
@ -122,6 +243,19 @@ namespace CPRNIMS.Domain.Services.Items
new SqlParameter("@ItemLocalId", itemDto.ItemLocalId)); new SqlParameter("@ItemLocalId", itemDto.ItemLocalId));
return new ItemCart(); return new ItemCart();
} }
public async Task<List<ItemCart>> GetItemCart(ItemDto itemDto)
{
var allItems = await _dbContext.ItemCarts
.FromSqlRaw($"EXEC GetItemCart @UserId,@RequestTypeId,@IsCount",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@RequestTypeId", itemDto.RequestTypeId),
new SqlParameter("@IsCount", itemDto.IsCount))
.ToListAsync();
return allItems ?? new List<ItemCart>();
}
public async Task<ResponseObject> PostPurchRequest(ItemDto itemDto) public async Task<ResponseObject> PostPurchRequest(ItemDto itemDto)
{ {
var (messCode, message) = OutputParamMessage.CreateOutputParams(); var (messCode, message) = OutputParamMessage.CreateOutputParams();
@ -188,22 +322,7 @@ namespace CPRNIMS.Domain.Services.Items
} }
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync();
} }
Task<ItemCart> IItem.PostPutItemPath(ItemDto itemDto) public async Task<(long,long)> GetPRNo()
{
throw new NotImplementedException();
}
public async Task<List<ItemCart>> GetItemCart(ItemDto itemDto)
{
var allItems = await _dbContext.ItemCarts
.FromSqlRaw($"EXEC GetItemCart @UserId,@RequestTypeId,@IsCount",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@RequestTypeId", itemDto.RequestTypeId),
new SqlParameter("@IsCount", itemDto.IsCount))
.ToListAsync();
return allItems ?? new List<ItemCart>();
}
public async Task<(long, long)> GetPRNo()
{ {
try try
{ {
@ -213,9 +332,9 @@ namespace CPRNIMS.Domain.Services.Items
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
if (latestPR != null) if (latestPR != null)
return (latestPR.PRNo + 1, latestPR.PRId + 1); return (latestPR.PRNo + 1,latestPR.PRId + 1);
else else
return (0, 0); return (0,0);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -224,122 +343,11 @@ namespace CPRNIMS.Domain.Services.Items
} }
} }
public async Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto) Task<ItemCart> IItem.PostPutItemPath(ItemDto itemDto)
{ {
var localizations = await _dbContext.ItemLocalizations throw new NotImplementedException();
.Where(ic => ic.IsActive == true &&
EF.Functions.Like(ic.ItemLocalName, $"%{itemDto.ItemLocalName}%"))
.Take(15)
.ToListAsync();
return localizations ?? new List<ItemLocalization>();
} }
public async Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto)
{
if (itemDto.ItemCategoryId == 0 || itemDto.ItemCategoryId == null)
{
var categories = await _dbContext.ItemCategories
.Where(ic => ic.IsActive == true)
.ToListAsync();
return categories ?? new List<ItemCategory>();
}
else
{
var categories = await _dbContext.ItemCategories
.Where(ic => ic.IsActive == true && ic.ItemCategoryId == itemDto.ItemCategoryId)
.ToListAsync();
return categories ?? new List<ItemCategory>();
}
}
public async Task<List<ItemDtos>> GetItemDetail(ItemDto itemDto)
{
var allItems = await _dbContext.ItemDtos
.FromSqlRaw($"EXEC GetItemDetail @ItemCodeId,@UserId",
new SqlParameter("@ItemCodeId", itemDto.ItemCodeId),
new SqlParameter("@UserId", itemDto.UserId))
.ToListAsync();
return allItems ?? new List<ItemDtos>();
}
public async Task<PagedResult<ItemList>> GetItemList(ItemCodeDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@SearchItemNo", dto.SearchItemNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchCategory", dto.SearchCategory ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
int totalCount = 0;
var items = new List<ItemList>();
var categoryList = new List<string>();
// Use ADO.NET to read two result sets
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = "EXEC GetItemList @UserId, @SearchItemNo,@SearchItemName,@SearchCategory, @PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
cmd.CommandTimeout = 60;
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
categoryList.Add(reader.GetString(0));
await reader.NextResultAsync();
if (await reader.ReadAsync())
totalCount = reader.GetInt32(0);
await reader.NextResultAsync();
while (await reader.ReadAsync())
{
items.Add(new ItemList
{
ItemCodeId = Convert.ToInt64(reader["ItemCodeId"]),
ItemNo = Convert.ToInt64(reader["ItemNo"]),
ItemName = reader["ItemName"]?.ToString(),
ItemDescription = reader["ItemDescription"]?.ToString(),
ItemCategoryName = reader["ItemCategoryName"]?.ToString(),
CartItemCount = Convert.ToInt32(reader["CartItemCount"])
});
}
await conn.CloseAsync();
return new PagedResult<ItemList>
{
Data = items,
TotalCount = totalCount,
CategoryList = categoryList,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize
};
}
public async Task<List<ItemColor>> GetItemColor(ItemDto itemDto)
{
var colors = await _dbContext.ItemColors
.Where(ic => EF.Functions.Like(ic.ItemColorName, $"%{itemDto.ItemColorName}%"))
.Take(5)
.ToListAsync();
return colors ?? new List<ItemColor>();
}
public async Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto)
{
var uoms = await _dbContext.UnitOfMessures
.Where(ic => ic.IsActive == true &&
EF.Functions.Like(ic.UOMName, $"%{itemDto.UOMName}%"))
.Take(150)
.ToListAsync();
return uoms ?? new List<UnitOfMessure>();
}
public async Task <List<Departments>> GetDepartment(ItemCodeDto itemCode) public async Task <List<Departments>> GetDepartment(ItemCodeDto itemCode)
{ {
return await _dbContext.Departments return await _dbContext.Departments
@ -358,18 +366,18 @@ namespace CPRNIMS.Domain.Services.Items
return allItems ?? new List<NotifUserKey>(); return allItems ?? new List<NotifUserKey>();
} }
public async Task<IReadOnlyList<ProjectCodes>> GetProjectCode()
public async Task<List<ProjectCodes>> GetProjectCode()
{ {
return await _dbContext.ProjectCodes return await _dbContext.ProjectCodes
.AsNoTracking() .AsNoTracking()
.ToListAsync(); .ToListAsync();
} }
public async Task<IReadOnlyList<ProjectCodes>> GetProjectCodeByTerm(string? term) public async Task<List<ProjectCodes>> GetProjectCodeByTerm(string? term)
{ {
return await _dbContext.ProjectCodes return await _dbContext.ProjectCodes
.AsNoTracking() .AsNoTracking()
.Where(p => p.StatusName != "Completed" && p.IsActive .Where(p => EF.Functions.Like(p.ProjectCode, $"%{term}%"))
&& EF.Functions.Like(p.ProjectCode, $"%{term}%"))
.ToListAsync(); .ToListAsync();
} }
} }

View File

@ -30,14 +30,6 @@ namespace CPRNIMS.Domain.Services.PO
_smptHelper = smptHelper; _smptHelper = smptHelper;
} }
#region Get #region Get
public async Task<IReadOnlyList<Currencies>> GetCurrencies(string currencyName, CancellationToken ct)
{
return await _dbContext.Currencies.AsNoTracking()
.Where(c => c.IsActive==true &&
(string.IsNullOrEmpty(currencyName) || c.CurrencyName.Contains(currencyName)))
.ToListAsync(ct);
}
public async Task<POFormData> GetPOFormDataAsync(long? poId) public async Task<POFormData> GetPOFormDataAsync(long? poId)
{ {
// Reuse the connection from your existing DbContext // Reuse the connection from your existing DbContext
@ -501,7 +493,7 @@ namespace CPRNIMS.Domain.Services.PO
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutCustomPO @UserId,@POTypeId,@PONumber,@PRDetailsId,@Specification,@PRNo,@PORemarks,@IncoTermsId," + .ExecuteSqlRawAsync("EXEC PostPutCustomPO @UserId,@POTypeId,@PONumber,@PRDetailsId,@Specification,@PRNo,@PORemarks,@IncoTermsId," +
$"@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@SupplierId,@DeliveryDate,@Discount,@Amount," + $"@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@SupplierId,@DeliveryDate,@Discount,@Amount," +
$"@UnitPrice,@Quantity,@DeliverTo,@CountryOrigin,@CurrencyId, @MessCode OUTPUT, @Message OUTPUT", $"@UnitPrice,@Quantity,@DeliverTo,@CountryOrigin, @MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@UserId", pODto.UserId), new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@POTypeId", pODto.POTypeId), new SqlParameter("@POTypeId", pODto.POTypeId),
new SqlParameter("@PONumber", formattedPONumber), new SqlParameter("@PONumber", formattedPONumber),
@ -524,7 +516,6 @@ namespace CPRNIMS.Domain.Services.PO
new SqlParameter("@Quantity", pODto.Quantity), new SqlParameter("@Quantity", pODto.Quantity),
new SqlParameter("@DeliverTo", pODto.DeliverTo), new SqlParameter("@DeliverTo", pODto.DeliverTo),
new SqlParameter("@CountryOrigin", pODto.CountryOrigin ?? "N/A"), new SqlParameter("@CountryOrigin", pODto.CountryOrigin ?? "N/A"),
new SqlParameter("@CurrencyId", pODto.CurrencyId),
messCode, messCode,
message); message);
@ -553,7 +544,7 @@ namespace CPRNIMS.Domain.Services.PO
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PutExistingPO @UserId,@POTypeId,@PONumber,@PRDetailsId,@Specification,@PRNo,@PORemarks,@IncoTermsId," + .ExecuteSqlRawAsync("EXEC PutExistingPO @UserId,@POTypeId,@PONumber,@PRDetailsId,@Specification,@PRNo,@PORemarks,@IncoTermsId," +
$"@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@SupplierId,@DeliveryDate,@Discount,@Amount," + $"@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@SupplierId,@DeliveryDate,@Discount,@Amount," +
$"@UnitPrice,@Quantity,@DeliverTo,@IsRemoved,@CountryOrigin,@CurrencyId, @MessCode OUTPUT, @Message OUTPUT", $"@UnitPrice,@Quantity,@DeliverTo,@IsRemoved,@CountryOrigin, @MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@UserId", pODto.UserId), new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@POTypeId", pODto.POTypeId), new SqlParameter("@POTypeId", pODto.POTypeId),
new SqlParameter("@PONumber", pODto.PONo), new SqlParameter("@PONumber", pODto.PONo),
@ -577,7 +568,6 @@ namespace CPRNIMS.Domain.Services.PO
new SqlParameter("@DeliverTo", pODto.DeliverTo), new SqlParameter("@DeliverTo", pODto.DeliverTo),
new SqlParameter("@IsRemoved", isRemoved), new SqlParameter("@IsRemoved", isRemoved),
new SqlParameter("@CountryOrigin", pODto.CountryOrigin ?? "N/A"), new SqlParameter("@CountryOrigin", pODto.CountryOrigin ?? "N/A"),
new SqlParameter("@CurrencyId", pODto.CurrencyId),
messCode, messCode,
message); message);
@ -645,8 +635,7 @@ namespace CPRNIMS.Domain.Services.PO
DeliverTo = PODto.DeliverTo ?? "N/A", DeliverTo = PODto.DeliverTo ?? "N/A",
Specification = specification, Specification = specification,
IsUpdate = PODto.IsUpdate, IsUpdate = PODto.IsUpdate,
CountryOrigin=PODto.CountryOrigin, CountryOrigin=PODto.CountryOrigin
CurrencyId=PODto.CurrencyId
}; };
} }
public async Task<DocRequired> PostSuppDocRequirements(PODto poDto) public async Task<DocRequired> PostSuppDocRequirements(PODto poDto)

View File

@ -633,17 +633,6 @@ namespace CPRNIMS.Domain.Services.PR
&& pr.IsActive && pr.IsActive
select pr).AnyAsync(); select pr).AnyAsync();
} }
private async Task<bool> ProjectStatusChanges(int projectCodeId,string? status)
{
var project = await _dbContext.ProjectCodes.FirstOrDefaultAsync(pc=>pc.ProjectCodeId==projectCodeId);
if (project == null)
return false;
if (project.StatusName == status)
return false;
else
return true;
}
public async Task<MessageResponse> PRItemRemoval(PRDto prDto) public async Task<MessageResponse> PRItemRemoval(PRDto prDto)
{ {
var (messCode, message) = CreateOutputParams(); var (messCode, message) = CreateOutputParams();
@ -664,6 +653,7 @@ namespace CPRNIMS.Domain.Services.PR
}; };
return response; return response;
} }
public async Task<ResponseObject> PostPutProjectCode(PRDto prDto) public async Task<ResponseObject> PostPutProjectCode(PRDto prDto)
{ {
if (prDto == null) throw new ArgumentNullException(nameof(prDto)); if (prDto == null) throw new ArgumentNullException(nameof(prDto));
@ -679,14 +669,13 @@ namespace CPRNIMS.Domain.Services.PR
ProjectName = prDto.ProjectName, ProjectName = prDto.ProjectName,
DeliveryAddress = prDto.DeliveryAddress, DeliveryAddress = prDto.DeliveryAddress,
MaxDays = prDto.MaxDays, MaxDays = prDto.MaxDays,
StatusName = prDto.StatusName,
IsActive = prDto.IsActive IsActive = prDto.IsActive
}; };
await _dbContext.ProjectCodes.AddAsync(project); await _dbContext.ProjectCodes.AddAsync(project);
} }
else else
{ {
if (await IsUsingAsync(prDto.ProjectCodeId) && await ProjectStatusChanges(prDto.ProjectCodeId,prDto.StatusName) == false) if (await IsUsingAsync(prDto.ProjectCodeId))
{ {
return new ResponseObject() return new ResponseObject()
{ {
@ -695,17 +684,12 @@ namespace CPRNIMS.Domain.Services.PR
success = false, success = false,
}; };
} }
if (await IsUsingAsync(prDto.ProjectCodeId))
{
existing.StatusName = prDto.StatusName;
}
else else
{ {
existing.ProjectCode = prDto.ProjectCode; existing.ProjectCode = prDto.ProjectCode;
existing.ProjectName = prDto.ProjectName; existing.ProjectName = prDto.ProjectName;
existing.DeliveryAddress = prDto.DeliveryAddress; existing.DeliveryAddress = prDto.DeliveryAddress;
existing.MaxDays = prDto.MaxDays; existing.MaxDays = prDto.MaxDays;
existing.StatusName = prDto.StatusName;
existing.IsActive = prDto.IsActive; existing.IsActive = prDto.IsActive;
} }
} }

View File

@ -73,7 +73,7 @@ namespace CPRNIMS.Domain.Services.Receiving
return allItems ?? new List<ReceivingDetail>(); return allItems ?? new List<ReceivingDetail>();
} }
public async Task<List<RRDetailDto>> GetRRDetail(ItemDto itemDto) public async Task<List<RRDetail>> GetRRDetail(ItemDto itemDto)
{ {
var allItems = await _dbContext.RRDetailss var allItems = await _dbContext.RRDetailss
.FromSqlRaw("EXEC GetRRDetail @RRNo,@UserId", .FromSqlRaw("EXEC GetRRDetail @RRNo,@UserId",
@ -81,7 +81,7 @@ namespace CPRNIMS.Domain.Services.Receiving
new SqlParameter("@UserId", itemDto.UserId)) new SqlParameter("@UserId", itemDto.UserId))
.ToListAsync(); .ToListAsync();
return allItems ?? new List<RRDetailDto>(); return allItems ?? new List<RRDetail>();
} }
#endregion #endregion
#region Post Put #region Post Put

View File

@ -1,80 +0,0 @@
using CPRNIMS.Domain.Contracts.Reports;
using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using CPRNIMS.Infrastructure.Helper;
using FastReport;
using Microsoft.Extensions.Configuration;
using System.Data;
using System.Net.Http.Json;
using System.Text.Json;
namespace CPRNIMS.Infrastructure.Reports
{
public class ReportBuilder : IReportBuilder
{
private readonly IConfiguration _configuration;
private readonly TokenHelper _tokenHelper;
private readonly IApiConfigurationService _apiConfigurationService;
public ReportBuilder(IConfiguration configuration, TokenHelper tokenHelper,
IApiConfigurationService apiConfigurationService)
{
_configuration = configuration;
_tokenHelper = tokenHelper;
_apiConfigurationService = apiConfigurationService;
}
private static readonly JsonSerializerOptions _jsonOptions = new()
{
PropertyNameCaseInsensitive = true
};
public Task<Report> MRSBuildAsync(DateTime dateFrom, DateTime dateTo, string templatePath, CancellationToken ct)
{
throw new NotImplementedException();
}
public async Task<Report> RISBuildAsync(
DateTime dateFrom, DateTime dateTo, string templatePath, CancellationToken ct = default)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var endpoint = _configuration["LLI:NonInvent:InventoryMgmt:RISReportData"]
?? throw new InvalidOperationException("RISReportData endpoint is not configured.");
// Append the date range as query string
var url = $"{endpoint}?dateFrom={dateFrom:yyyy-MM-dd}&dateTo={dateTo:yyyy-MM-dd}";
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await httpClient.GetAsync(url, ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
throw new InvalidOperationException(
$"Failed to fetch RIS report data. HTTP {(int)response.StatusCode}: {json}");
var dto = JsonSerializer.Deserialize<RISReportDataDto>(json, _jsonOptions)
?? new RISReportDataDto();
var report = new Report();
report.Load(templatePath);
// RegisterData accepts IEnumerable<object> — names must match the .frx datasources.
report.RegisterData(dto.Rows ?? new(), "TRIS");
report.RegisterData(dto.Disciplines ?? new(), "TDisciplineAgg");
report.RegisterData(dto.Recipients ?? new(), "TTopRecipients");
/* report.GetDataSource("Table").Enabled = true;
report.GetDataSource("Table1").Enabled = true;
report.GetDataSource("Table3").Enabled = true;*/
report.GetDataSource("TRIS").Enabled = true;
report.GetDataSource("TDisciplineAgg").Enabled = true;
report.GetDataSource("TTopRecipients").Enabled = true;
report.SetParameterValue("DateFrom", dateFrom);
report.SetParameterValue("DateTo", dateTo);
return report;
}
}
}

View File

@ -1,109 +0,0 @@
using CPRNIMS.Domain.Contracts.Reports;
using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using Dapper;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
namespace CPRNIMS.Infrastructure.Reports
{
public class ReportDataService : IReportDataService
{
private readonly NonInventoryDbContext _context;
public ReportDataService(NonInventoryDbContext context) => _context = context;
private const string MainSql = """
SELECT
R.RISNo,
PR.PRNo,
R.QtyIssued,
R.IssuedTo,
CASE R.Status
WHEN 0 THEN 'Draft'
WHEN 1 THEN 'Approved'
WHEN 2 THEN 'Cancelled'
ELSE 'Unknown'
END AS StatusLabel,
CreatedBy.CreatedBy,
ApprovedBy.ApprovedBy,
R.ApprovedDate,
R.CreatedDate,
D.DisciplineName,
PRD.ItemName,
PRD.ItemNo,
IV.QtyIn,
IV.QtyOut,
IV.QtyOnHand,
DEP.Department AS DepartmentName,
ISNULL(MRS_AGG.TotalReturned, 0) AS TotalReturned,
ISNULL(MRS_AGG.MRSCount, 0) AS MRSCount,
R.QtyIssued - ISNULL(MRS_AGG.TotalReturned, 0) AS NetIssued
FROM dbo.RIS R
INNER JOIN dbo.Disciplines D ON R.DisciplineId = D.DisciplineId
INNER JOIN dbo.Inventory IV ON R.InventoryId = IV.InventoryId AND IV.IsActive = 1
LEFT JOIN dbo.Lot L ON IV.LotId = L.LotId
OUTER APPLY (SELECT U.FullName ApprovedBy FROM dbo.Users U WHERE R.ApprovedBy = U.UserName) ApprovedBy
OUTER APPLY (SELECT U2.FullName CreatedBy FROM dbo.Users U2 WHERE R.CreatedBy = U2.UserName) CreatedBy
INNER JOIN Users U ON IV.UserId = U.Id
LEFT JOIN dbo.Departments DEP ON U.DepartmentId = DEP.DepartmentId
LEFT JOIN dbo.PRDetails PRD ON R.PRDetailId = PRD.PRDetailsId AND PRD.IsActive = 1
LEFT JOIN dbo.PR PR ON PRD.PRId = PR.PRId AND PR.IsActive = 1
LEFT JOIN (
SELECT
RISId,
COUNT(*) AS MRSCount,
SUM(QtyReturned) AS TotalReturned
FROM dbo.MRS
WHERE Status != 2
GROUP BY RISId
) MRS_AGG ON R.RISId = MRS_AGG.RISId
WHERE R.Status != 2
AND R.CreatedDate >= @DateFrom
AND R.CreatedDate < DATEADD(DAY, 1, @DateTo)
ORDER BY R.CreatedDate DESC, R.RISNo ASC;
""";
private const string DisciplineSql = """
SELECT
D.DisciplineName,
COUNT(*) AS SlipCount
FROM dbo.RIS R
INNER JOIN dbo.Disciplines D ON R.DisciplineId = D.DisciplineId
WHERE R.Status != 2
AND R.CreatedDate >= @DateFrom
AND R.CreatedDate < DATEADD(DAY, 1, @DateTo)
GROUP BY D.DisciplineName
ORDER BY SlipCount DESC;
""";
private const string RecipientsSql = """
SELECT TOP 5
R.IssuedTo AS Name,
COUNT(*) AS SlipCount,
SUM(IV.QtyOut) AS QtyOut
FROM dbo.RIS R
INNER JOIN dbo.Inventory IV ON R.InventoryId = IV.InventoryId AND IV.IsActive = 1
WHERE R.Status != 2
AND R.CreatedDate >= @DateFrom
AND R.CreatedDate < DATEADD(DAY, 1, @DateTo)
GROUP BY R.IssuedTo
ORDER BY COUNT(*) DESC;
""";
public List<RISRowDto> GetMain(DateTime dateFrom, DateTime dateTo) =>
Query<RISRowDto>(MainSql, dateFrom, dateTo);
public List<DisciplineAggDto> GetDisciplines(DateTime dateFrom, DateTime dateTo) =>
Query<DisciplineAggDto>(DisciplineSql, dateFrom, dateTo);
public List<TopRecipientDto> GetRecipients(DateTime dateFrom, DateTime dateTo) =>
Query<TopRecipientDto>(RecipientsSql, dateFrom, dateTo);
private List<T> Query<T>(string sql, DateTime from, DateTime to)
{
using var conn = new SqlConnection(_context.Database.GetConnectionString());
return conn.Query<T>(sql, new { DateFrom = from, DateTo = to }).ToList();
}
}
}

View File

@ -1,18 +0,0 @@
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.Inventory
{
public interface IInventoryReports
{
Task<RISReportDto> GetRISReportAsync(InventoryReportsRequest request, CancellationToken ct);
Task<MRSReportDto> GetMRSReportAsync(InventoryReportsRequest request, CancellationToken ct);
Task<InventoryReportDto> GetInventoryReportAsync(InventoryReportsRequest request, CancellationToken ct);
}
}

View File

@ -1,22 +0,0 @@
using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.Inventory
{
public interface IMRS
{
Task<MRSPagedResponse> GetMRSPaged(MRSPagedRequest request, CancellationToken ct);
Task<ApiResponse<object>> CreateMRS(CreateMRSRequest request, CancellationToken ct);
Task<ApiResponse<object>> ApproveMRS(ApproveMRSRequest request, CancellationToken ct);
Task<ApiResponse<object>> CancelMRS(CancelMRSRequest request, CancellationToken ct);
Task<ApiResponse<List<SearchRISProjectCodeResponse>>> SearchRIS(SearchRISProjectCodeRequest request, CancellationToken ct);
Task<ApiResponse<List<ProjectCodeOptionResponse>>> SearchProjects(SearchRISProjectCodeRequest request, CancellationToken ct);
}
}

View File

@ -1,5 +1,4 @@
using CPRNIMS.Infrastructure.Dto.Common; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response; using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.ViewModel.Inventory; using CPRNIMS.Infrastructure.ViewModel.Inventory;
using System; using System;
@ -12,9 +11,10 @@ namespace CPRNIMS.Domain.UIContracts.Inventory
{ {
public interface IRIS public interface IRIS
{ {
Task<ApiResponse<object>> ApproveRIS(ApproveRISRequest request, CancellationToken ct); Task<bool> ApproveRIS(ApproveRISRequest request, CancellationToken ct);
Task<ApiResponse<object>> CancelRIS(CancelRISRequest request, CancellationToken ct); Task<bool> CancelRIS(CancelRISRequest request, CancellationToken ct);
Task<ApiResponse<object>> CreateRIS(CreateRISRequest request, CancellationToken ct); Task<RISResponse> CreateRIS(CreateRISRequest request, CancellationToken ct);
Task<RISPagedResponse> GetRISById(int risId, CancellationToken ct);
Task<RISPagedResponse> GetRISPaged(RISPagedRequest request, CancellationToken ct); Task<RISPagedResponse> GetRISPaged(RISPagedRequest request, CancellationToken ct);
} }
} }

View File

@ -11,7 +11,6 @@ namespace CPRNIMS.Domain.UIContracts.PO
public interface IPurchaseOrder public interface IPurchaseOrder
{ {
#region Get #region Get
Task<List<POVM>> GetCurrencies(User user, POVM viewModels);
Task<List<POVM>> GetSupplierBidById(User user, POVM viewModel); Task<List<POVM>> GetSupplierBidById(User user, POVM viewModel);
Task<List<POVM>> GetSupplierBidByItem(User user, POVM viewModel); Task<List<POVM>> GetSupplierBidByItem(User user, POVM viewModel);
Task<List<POVM>> GetSupplierBid(User user, POVM viewModel); Task<List<POVM>> GetSupplierBid(User user, POVM viewModel);

View File

@ -1,126 +0,0 @@
using Azure.Core;
using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Domain.UIContracts.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using CPRNIMS.Infrastructure.Dto.Inventory.Reports.Response;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Helper;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using System.Text;
using System.Text.Json;
namespace CPRNIMS.Domain.UIServices.Inventory
{
public class InventoryReports : IInventoryReports
{
private readonly IConfiguration _configuration;
private readonly TokenHelper _tokenHelper;
private readonly IApiConfigurationService _apiConfigurationService;
public InventoryReports(IConfiguration configuration, TokenHelper tokenHelper, IApiConfigurationService apiConfigurationService)
{
_configuration = configuration;
_tokenHelper = tokenHelper;
_apiConfigurationService = apiConfigurationService;
}
private static readonly JsonSerializerOptions _jsonOpts = new()
{
PropertyNameCaseInsensitive = true
};
public async Task<InventoryReportDto> GetInventoryReportAsync(InventoryReportsRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var baseEndpoint = _configuration["LLI:NonInvent:InventoryMgmt:GetInventoryReport"]
?? throw new InvalidOperationException("GetInventoryReport endpoint is not configured.");
var qs = new Dictionary<string, string?>
{
["dateFrom"] = request.DateFrom.ToString("yyyy-MM-dd"),
["dateTo"] = request.DateTo.ToString("yyyy-MM-dd"),
["department"] = request.Department,
["page"] = request.Page.ToString(),
["pageSize"] = request.PageSize.ToString(),
["paginate"] = request.Paginate.ToString().ToLowerInvariant()
};
var url = QueryHelpers.AddQueryString(baseEndpoint, qs);
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await httpClient.GetAsync(url, ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
return new InventoryReportDto();
var result = JsonSerializer.Deserialize<InventoryReportDto>(json, _jsonOpts);
return result ?? new InventoryReportDto();
}
public async Task<MRSReportDto> GetMRSReportAsync(InventoryReportsRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var baseEndpoint = _configuration["LLI:NonInvent:InventoryMgmt:GetMRSReport"]
?? throw new InvalidOperationException("GetMRS endpoint is not configured.");
var qs = new Dictionary<string, string?>
{
["dateFrom"] = request.DateFrom.ToString("yyyy-MM-dd"),
["dateTo"] = request.DateTo.ToString("yyyy-MM-dd"),
["department"] = request.Department,
["page"] = request.Page.ToString(),
["pageSize"] = request.PageSize.ToString(),
["paginate"] = request.Paginate.ToString().ToLowerInvariant()
};
var url = QueryHelpers.AddQueryString(baseEndpoint, qs);
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await httpClient.GetAsync(url, ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
return new MRSReportDto { };
var result = JsonSerializer.Deserialize<MRSReportDto>(json, _jsonOpts);
return result ?? new MRSReportDto();
}
public async Task<RISReportDto> GetRISReportAsync(InventoryReportsRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var baseEndpoint = _configuration["LLI:NonInvent:InventoryMgmt:GetRISReport"]
?? throw new InvalidOperationException("GetMRS endpoint is not configured.");
var qs = new Dictionary<string, string?>
{
["dateFrom"] = request.DateFrom.ToString("yyyy-MM-dd"),
["dateTo"] = request.DateTo.ToString("yyyy-MM-dd"),
["department"] = request.Department,
["page"] = request.Page.ToString(),
["pageSize"] = request.PageSize.ToString(),
["paginate"] = request.Paginate.ToString().ToLowerInvariant()
};
var url = QueryHelpers.AddQueryString(baseEndpoint, qs);
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await httpClient.GetAsync(url, ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
return new RISReportDto {};
var result = JsonSerializer.Deserialize<RISReportDto>(json, _jsonOpts);
return result ?? new RISReportDto();
}
}
}

View File

@ -1,197 +0,0 @@
using Azure.Core;
using CPRNIMS.Domain.Services;
using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Domain.UIContracts.Inventory;
using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Helper;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIServices.Inventory
{
public class MRS : IMRS
{
private readonly IConfiguration _configuration;
private readonly TokenHelper _tokenHelper;
private readonly IApiConfigurationService _apiConfigurationService;
public MRS(IConfiguration configuration, TokenHelper tokenHelper,IApiConfigurationService apiConfigurationService)
{
_configuration = configuration;
_tokenHelper = tokenHelper;
_apiConfigurationService = apiConfigurationService;
}
private static readonly JsonSerializerOptions _mrsJsonOpts = new()
{
PropertyNameCaseInsensitive = true
};
public async Task<MRSPagedResponse> GetMRSPaged(MRSPagedRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var baseEndpoint = _configuration["LLI:NonInvent:InventoryMgmt:GetMRS"]
?? throw new InvalidOperationException("GetMRS endpoint is not configured.");
var qs = new StringBuilder(baseEndpoint).Append('?');
qs.Append($"pageNumber={request.PageNumber}&pageSize={request.PageSize}");
if (!string.IsNullOrWhiteSpace(request.SearchMRSNo))
qs.Append($"&searchMRSNo={Uri.EscapeDataString(request.SearchMRSNo)}");
if (!string.IsNullOrWhiteSpace(request.SearchRISNo))
qs.Append($"&searchRISNo={Uri.EscapeDataString(request.SearchRISNo)}");
if (!string.IsNullOrWhiteSpace(request.SearchItemName))
qs.Append($"&searchItemName={Uri.EscapeDataString(request.SearchItemName)}");
if (!string.IsNullOrWhiteSpace(request.SearchReturnedBy))
qs.Append($"&searchReturnedBy={Uri.EscapeDataString(request.SearchReturnedBy)}");
if (request.Status.HasValue)
qs.Append($"&status={request.Status.Value}");
if (!string.IsNullOrWhiteSpace(request.Condition))
qs.Append($"&condition={Uri.EscapeDataString(request.Condition)}");
using var http = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await http.GetAsync(qs.ToString(), ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
return new MRSPagedResponse { Data = [], RecordsTotal = 0 };
var result = JsonSerializer.Deserialize<MRSPagedResponse>(json, _mrsJsonOpts);
return result ?? new MRSPagedResponse();
}
public async Task<ApiResponse<object>> CreateMRS(CreateMRSRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var endpoint = _configuration["LLI:NonInvent:InventoryMgmt:CreateMRS"]
?? throw new InvalidOperationException("CreateMRS endpoint is not configured.");
using var http = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
var response = await http.PostAsync(endpoint, content, ct);
var json = await response.Content.ReadAsStringAsync(ct);
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _mrsJsonOpts)
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" };
if (!response.IsSuccessStatusCode)
result.success = false;
return result;
}
public async Task<ApiResponse<object>> ApproveMRS(ApproveMRSRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var endpoint = _configuration["LLI:NonInvent:InventoryMgmt:ApproveMRS"]
?? throw new InvalidOperationException("ApproveMRS endpoint is not configured.");
using var http = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(
JsonSerializer.Serialize(request),
Encoding.UTF8, "application/json");
var response = await http.PostAsync(endpoint, content, ct);
var json = await response.Content.ReadAsStringAsync(ct);
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _mrsJsonOpts)
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" };
if (!response.IsSuccessStatusCode)
result.success = false;
return result;
}
public async Task<ApiResponse<object>> CancelMRS(CancelMRSRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var endpoint = _configuration["LLI:NonInvent:InventoryMgmt:CancelMRS"]
?? throw new InvalidOperationException("CancelMRS endpoint is not configured.");
using var http = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(
JsonSerializer.Serialize(request),
Encoding.UTF8, "application/json");
var response = await http.PostAsync(endpoint, content, ct);
var json = await response.Content.ReadAsStringAsync(ct);
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _mrsJsonOpts)
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" };
if (!response.IsSuccessStatusCode)
result.success = false;
return result;
}
public async Task<ApiResponse<List<SearchRISProjectCodeResponse>>> SearchRIS(SearchRISProjectCodeRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has been expired.");
var baseEndpoint = _configuration["LLI:NonInvent:InventoryMgmt:SearchRIS"]
?? throw new InvalidOperationException("GetMRS endpoint is not configured.");
var qs = new StringBuilder(baseEndpoint).Append('?');
if (!string.IsNullOrWhiteSpace(request.SearchRISNo))
qs.Append($"&searchRISNo={Uri.EscapeDataString(request.SearchRISNo)}");
if (!string.IsNullOrWhiteSpace(request.SearchRISNo))
qs.Append($"&projectCodeId= {request.SearchProjectCodeId}");
using var http = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await http.GetAsync(qs.ToString(), ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
return new ApiResponse<List<SearchRISProjectCodeResponse>>{ };
var result = JsonSerializer.Deserialize<ApiResponse<List<SearchRISProjectCodeResponse>>>(json, _mrsJsonOpts);
return result ?? new ApiResponse<List<SearchRISProjectCodeResponse>>();
}
public async Task<ApiResponse<List<ProjectCodeOptionResponse>>> SearchProjects(SearchRISProjectCodeRequest request, CancellationToken ct)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Token has expired.");
var baseEndpoint = _configuration["LLI:NonInvent:InventoryMgmt:SearchProjects"]
?? throw new InvalidOperationException("SearchProjects endpoint is not configured.");
var qs = new StringBuilder(baseEndpoint);
if (!string.IsNullOrWhiteSpace(request.SearchProjectCode))
qs.Append('?').Append("searchProjectCode=").Append(Uri.EscapeDataString(request.SearchProjectCode));
using var http = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await http.GetAsync(qs.ToString(), ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
return new ApiResponse<List<ProjectCodeOptionResponse>>();
var result = JsonSerializer.Deserialize<ApiResponse<List<ProjectCodeOptionResponse>>>(json, _mrsJsonOpts);
return result ?? new ApiResponse<List<ProjectCodeOptionResponse>>();
}
}
}

View File

@ -3,7 +3,6 @@ using CPRNIMS.Domain.UIContracts.Inventory;
using CPRNIMS.Infrastructure.Dto.Common; using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Dto.Inventory.Request; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response; using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Dto.PR.Response;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System; using System;
@ -30,6 +29,8 @@ namespace CPRNIMS.Domain.UIServices.Inventory
} }
#region Get #region Get
public async Task<RISPagedResponse> GetRISPaged(RISPagedRequest request, CancellationToken ct) public async Task<RISPagedResponse> GetRISPaged(RISPagedRequest request, CancellationToken ct)
{
try
{ {
var token = await _tokenHelper.GetValidTokenAsync(); var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
@ -73,9 +74,16 @@ namespace CPRNIMS.Domain.UIServices.Inventory
var result = JsonSerializer.Deserialize<RISPagedResponse>(json, _jsonOptions); var result = JsonSerializer.Deserialize<RISPagedResponse>(json, _jsonOptions);
return result ?? new RISPagedResponse(); return result ?? new RISPagedResponse();
} }
catch (Exception ex)
{
ex.ToString();
throw;
}
}
#endregion #endregion
#region Post Put #region Post Put
public async Task<ApiResponse<object>> ApproveRIS(ApproveRISRequest request, CancellationToken ct) public async Task<bool> ApproveRIS(ApproveRISRequest request, CancellationToken ct)
{ {
var token = await _tokenHelper.GetValidTokenAsync(); var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
@ -89,16 +97,15 @@ namespace CPRNIMS.Domain.UIServices.Inventory
var response = await httpClient.PutAsync(endpoint, content, ct); var response = await httpClient.PutAsync(endpoint, content, ct);
var json = await response.Content.ReadAsStringAsync(ct); var json = await response.Content.ReadAsStringAsync(ct);
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _jsonOptions)
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" };
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
result.success = false; {
return false;
return result; }
return true;
} }
public async Task<ApiResponse<object>> CancelRIS(CancelRISRequest request, CancellationToken ct) public async Task<bool> CancelRIS(CancelRISRequest request, CancellationToken ct)
{ {
var token = await _tokenHelper.GetValidTokenAsync(); var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
@ -108,21 +115,19 @@ namespace CPRNIMS.Domain.UIServices.Inventory
?? throw new InvalidOperationException("CancelRIS endpoint is not configured."); ?? throw new InvalidOperationException("CancelRIS endpoint is not configured.");
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token); using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); using var content = new StringContent(
JsonSerializer.Serialize(request),Encoding.UTF8,"application/json");
var response = await httpClient.PutAsync(endpoint, content, ct); var response = await httpClient.PutAsync(endpoint, content, ct);
var json = await response.Content.ReadAsStringAsync(ct); var json = await response.Content.ReadAsStringAsync(ct);
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _jsonOptions)
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" };
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
result.success = false; {
return false;
return result;
} }
return true;
public async Task<ApiResponse<object>> CreateRIS(CreateRISRequest request, CancellationToken ct) }
public async Task<RISResponse> CreateRIS(CreateRISRequest request, CancellationToken ct)
{ {
var token = await _tokenHelper.GetValidTokenAsync(); var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
@ -133,19 +138,27 @@ namespace CPRNIMS.Domain.UIServices.Inventory
throw new InvalidOperationException("CreateRIS endpoint is not configured."); throw new InvalidOperationException("CreateRIS endpoint is not configured.");
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token); using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(JsonSerializer.Serialize(request),Encoding.UTF8,"application/json"); using var content = new StringContent(
JsonSerializer.Serialize(request),
Encoding.UTF8,
"application/json");
var response = await httpClient.PostAsync(endpoint, content,ct); var response = await httpClient.PostAsync(endpoint, content,ct);
if (!response.IsSuccessStatusCode)
{
return new RISResponse();
}
var json = await response.Content.ReadAsStringAsync(); var json = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _jsonOptions) var result = JsonSerializer.Deserialize<ApiResponse<RISResponse>>(json, _jsonOptions);
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" }; return result?.data ?? new RISResponse();
}
if (!response.IsSuccessStatusCode) public Task<RISPagedResponse> GetRISById(int risId, CancellationToken ct)
result.success = false; {
throw new NotImplementedException();
return result;
} }
private static readonly JsonSerializerOptions _jsonOptions = new() private static readonly JsonSerializerOptions _jsonOptions = new()

View File

@ -284,11 +284,6 @@ namespace CPRNIMS.Domain.UIServices.PO
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:POMgmt:GetPortOfDischarge"]); _configuration["LLI:NonInvent:POMgmt:GetPortOfDischarge"]);
} }
public async Task<List<POVM>> GetCurrencies(User user, POVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:POMgmt:GetCurrencies"]);
}
#endregion #endregion
#region Post Put #region Post Put
public async Task<POVM> PostApprovedSupplier(User user, POVM viewModel) public async Task<POVM> PostApprovedSupplier(User user, POVM viewModel)

View File

@ -40,7 +40,6 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<ItemCode> ItemCodes { get; set; } public virtual DbSet<ItemCode> ItemCodes { get; set; }
public virtual DbSet<ItemList> ItemList { get; set; } public virtual DbSet<ItemList> ItemList { get; set; }
public virtual DbSet<Item> Items { get; set; } public virtual DbSet<Item> Items { get; set; }
public DbSet<ItemDtos> ItemDtos { get; set; }
public DbSet<Attachment> Attachments { get; set; } public DbSet<Attachment> Attachments { get; set; }
public virtual DbSet<AttachmentExtension> AttachmentExtensions { get; set; } public virtual DbSet<AttachmentExtension> AttachmentExtensions { get; set; }
public virtual DbSet<AttachmentFileType> AttachmentFileTypes { get; set; } public virtual DbSet<AttachmentFileType> AttachmentFileTypes { get; set; }
@ -128,7 +127,6 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<PaymentTerm> PaymentTerms { get; set; } public virtual DbSet<PaymentTerm> PaymentTerms { get; set; }
public virtual DbSet<Incoterm> Incoterms { get; set; } public virtual DbSet<Incoterm> Incoterms { get; set; }
public virtual DbSet<CentralPONo> CentralPONos { get; set; } public virtual DbSet<CentralPONo> CentralPONos { get; set; }
public DbSet<Currencies> Currencies { get; set; }
#endregion #endregion
#region Inventory #region Inventory
@ -150,11 +148,10 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<ForReceiving> ForReceivings { get; set; } public virtual DbSet<ForReceiving> ForReceivings { get; set; }
public virtual DbSet<Infrastructure.Entities.Receiving.RRReport> RRReports { get; set; } public virtual DbSet<Infrastructure.Entities.Receiving.RRReport> RRReports { get; set; }
public virtual DbSet<ReceivingDetail> ReceivingDetails { get; set; } public virtual DbSet<ReceivingDetail> ReceivingDetails { get; set; }
public virtual DbSet<RRDetailDto> RRDetailDtos { get; set; } public virtual DbSet<RRDetail> RRDetails { get; set; }
public virtual DbSet<ForRR> ForRRs { get; set; } public virtual DbSet<ForRR> ForRRs { get; set; }
public virtual DbSet<RR> RRs { get; set; } public virtual DbSet<RR> RRs { get; set; }
public virtual DbSet<Entities.Receiving.RRDetailDto> RRDetailss { get; set; } public virtual DbSet<Entities.Receiving.RRDetail> RRDetailss { get; set; }
public virtual DbSet<Entities.Receiving.RRDetails> RRDetails { get; set; }
public virtual DbSet<RRSeries> RRSeries { get; set; } public virtual DbSet<RRSeries> RRSeries { get; set; }
#endregion #endregion
@ -201,7 +198,7 @@ namespace CPRNIMS.Infrastructure.Database
b.HasOne(u => u.Attachment) b.HasOne(u => u.Attachment)
.WithOne(a => a.ApplicationUser) .WithOne(a => a.ApplicationUser)
.HasForeignKey<Attachment>(a => a.AttachmentId) .HasForeignKey<Attachment>(a => a.AttachmentId)
.IsRequired(false); .IsRequired(false); // Allow null if there is no attachment
}); });
modelBuilder.Entity<Attachment>(b => modelBuilder.Entity<Attachment>(b =>
{ {
@ -209,7 +206,7 @@ namespace CPRNIMS.Infrastructure.Database
b.HasOne(a => a.AttachmentExtention) b.HasOne(a => a.AttachmentExtention)
.WithOne() .WithOne()
.HasForeignKey<Attachment>(a => a.ExtensionId) .HasForeignKey<Attachment>(a => a.ExtensionId)
.IsRequired(false); .IsRequired(false); // Allow null if there is no extension
}); });
modelBuilder.Entity<ApplicationUser>(b => modelBuilder.Entity<ApplicationUser>(b =>
{ {
@ -273,23 +270,13 @@ namespace CPRNIMS.Infrastructure.Database
.HasForeignKey(i => i.LotId) .HasForeignKey(i => i.LotId)
.OnDelete(DeleteBehavior.Restrict); .OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Inventory>() modelBuilder.Entity<InventTrans>(e =>
.HasOne(i => i.Item) {
.WithMany() e.HasMany(r => r.InventTransDetails)
.HasForeignKey(i => i.ItemNo) .WithOne()
.OnDelete(DeleteBehavior.Restrict); .HasForeignKey(t => t.InventTransId)
modelBuilder.Entity<Item>()
.HasOne(i => i.ItemCode)
.WithMany()
.HasForeignKey(i => i.ItemCodeId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<ItemCode>()
.HasOne(i => i.ItemCategory)
.WithMany()
.HasForeignKey(i => i.ItemCategoryId)
.OnDelete(DeleteBehavior.Restrict); .OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<InventTransDetail>(e => modelBuilder.Entity<InventTransDetail>(e =>
{ {
@ -297,15 +284,7 @@ namespace CPRNIMS.Infrastructure.Database
.WithMany() .WithMany()
.HasForeignKey(t => t.PRDetailId) .HasForeignKey(t => t.PRDetailId)
.OnDelete(DeleteBehavior.Restrict); .OnDelete(DeleteBehavior.Restrict);
e.HasOne(r => r.RRDetails)
.WithMany()
.HasForeignKey(r => r.RRDetailId)
.IsRequired(false)
.HasForeignKey(r => r.RRDetailId)
.OnDelete(DeleteBehavior.Restrict);
}); });
modelBuilder.Entity<PRDetails>(e => modelBuilder.Entity<PRDetails>(e =>
{ {
e.HasOne(i => i.PRs) e.HasOne(i => i.PRs)
@ -323,10 +302,6 @@ namespace CPRNIMS.Infrastructure.Database
e.HasOne(r => r.Discipline) e.HasOne(r => r.Discipline)
.WithMany() .WithMany()
.HasForeignKey(r => r.DisciplineId); .HasForeignKey(r => r.DisciplineId);
e.HasOne(r => r.ProjectCodes)
.WithMany()
.HasForeignKey(r => r.ProjectCodeId);
}); });
modelBuilder.Entity<MRS>(e => { modelBuilder.Entity<MRS>(e => {

View File

@ -3,7 +3,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Security.Claims;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -21,7 +20,6 @@ namespace CPRNIMS.Infrastructure.Dto.Account
public string URLAttachment { get; set; } = string.Empty; public string URLAttachment { get; set; } = string.Empty;
public string? token { get; set; } public string? token { get; set; }
public string? company { get; set; } public string? company { get; set; }
public int? departmentId { get; set; }
public string? refreshToken { get; set; } public string? refreshToken { get; set; }
public DateTime expiresAt { get; set; } public DateTime expiresAt { get; set; }
public int expiresInSeconds { get; set; } public int expiresInSeconds { get; set; }

View File

@ -13,6 +13,5 @@ namespace CPRNIMS.Infrastructure.Dto.Account
public string FullName { get; init; } = default!; public string FullName { get; init; } = default!;
public string Company { get; init; } = default!; public string Company { get; init; } = default!;
public IReadOnlyList<string> Roles { get; init; } = []; public IReadOnlyList<string> Roles { get; init; } = [];
public int? DepartmentId { get; set; }
} }
} }

View File

@ -11,10 +11,4 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory
public byte DisciplineId { get; set; } public byte DisciplineId { get; set; }
public string DisciplineName { get; set; } = string.Empty; public string DisciplineName { get; set; } = string.Empty;
} }
public class ProjectCodeDto
{
public string ProjectCode { get; set; } = string.Empty;
public string ProjectName { get; set; } = string.Empty;
public int ProjectCodeId { get; set; }
}
} }

View File

@ -8,7 +8,7 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory
{ {
public class MRSFilterDto public class MRSFilterDto
{ {
public int PageNumber { get; set; } = 1; public int Page { get; set; } = 1;
public int PageSize { get; set; } = 12; public int PageSize { get; set; } = 12;
public string? SearchMRSNo { get; set; } public string? SearchMRSNo { get; set; }
public long? RISId { get; set; } public long? RISId { get; set; }

View File

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class MRSPagedDto
{
public long MRSId { get; set; }
public string MRSNo { get; set; } = string.Empty;
public long RISId { get; set; }
public string? RISNo { get; set; }
public string? ItemName { get; set; }
public string? ReturnedBy { get; set; }
public decimal QtyReturned { get; set; }
public string? Condition { get; set; }
public string? Remarks { get; set; }
public short Status { get; set; }
public string? StatusLabel { get; set; }
public string? CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string? ApprovedBy { get; set; }
public DateTime? ApprovedDate { get; set; }
public int InventoryId { get; set; }
public List<MRSPagedDto> Data { get; set; } = [];
}
}

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class MRSPagedRequest
{
public string? SearchMRSNo { get; set; }
public string? SearchRISNo { get; set; }
public string? SearchItemName { get; set; }
public string? SearchReturnedBy { get; set; }
public short? Status { get; set; }
public string? Condition { get; set; }
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 12;
}
}

View File

@ -9,7 +9,7 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory
{ {
public class MRSPagedResult public class MRSPagedResult
{ {
public IEnumerable<MRSPagedDto> Data { get; set; } = []; public IEnumerable<MRSResponse> Data { get; set; } = [];
public int RecordsTotal { get; set; } public int RecordsTotal { get; set; }
public List<string> DepartmentList { get; set; } = new List<string>(); public List<string> DepartmentList { get; set; } = new List<string>();
public List<string> DisciplineList { get; set; } = new List<string>(); public List<string> DisciplineList { get; set; } = new List<string>();

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class RISSearchResultDto
{
public long RISId { get; set; }
public string RISNo { get; set; } = string.Empty;
public int ProjectCodeId { get; set; }
public string ProjectCode { get; set; } = string.Empty;
public string ProjectName { get; set; } = string.Empty;
public string DisciplineName { get; set; } = string.Empty;
public decimal QtyAvailableToReturn { get; set; }
}
public class ProjectCodeOptionDto
{
public int ProjectCodeId { get; set; }
public string ProjectCode { get; set; } = string.Empty;
public string ProjectName { get; set; } = string.Empty;
}
}

View File

@ -1,50 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Reports
{
public class RISReportDataDto
{
public List<RISRowDto> Rows { get; set; } = new();
public List<DisciplineAggDto> Disciplines { get; set; } = new();
public List<TopRecipientDto> Recipients { get; set; } = new();
}
public class RISRowDto
{
public string? RISNo { get; set; }
public long? PRNo { get; set; }
public decimal QtyIssued { get; set; }
public string? IssuedTo { get; set; }
public string? StatusLabel { get; set; }
public string? CreatedBy { get; set; }
public string? ApprovedBy { get; set; }
public DateTime? ApprovedDate { get; set; }
public DateTime? CreatedDate { get; set; }
public string? DisciplineName { get; set; }
public string? ItemName { get; set; }
public long? ItemNo { get; set; }
public decimal QtyIn { get; set; }
public decimal QtyOut { get; set; }
public decimal QtyOnHand { get; set; }
public string? DepartmentName { get; set; }
public decimal TotalReturned { get; set; }
public int MRSCount { get; set; }
public decimal NetIssued { get; set; }
}
public class DisciplineAggDto
{
public string? DisciplineName { get; set; }
public int SlipCount { get; set; }
}
public class TopRecipientDto
{
public string? Name { get; set; }
public int SlipCount { get; set; }
public decimal QtyOut { get; set; }
}
}

View File

@ -1,160 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Reports
{
public class RISReportDto
{
public string CompanyName { get; set; } = "Lloyd Laboratories Incorporated";
public string PreparedBy { get; set; } = "Finance Department";
public string ReportNo { get; set; } = string.Empty;
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public RISReportSummary Summary { get; set; } = new();
public List<RISReportRow> Rows { get; set; } = [];
public List<DisciplineCount> ByDiscipline { get; set; } = [];
public List<TopRecipient> TopRecipients { get; set; } = [];
}
public class RISReportSummary
{
public int TotalRIS { get; set; }
public int TotalApproved { get; set; }
public int TotalPending { get; set; }
public int TotalCancelled { get; set; }
public decimal TotalQtyIssued { get; set; }
public decimal TotalQtyReturned { get; set; }
public decimal TotalNetIssued { get; set; }
public decimal ApprovalRatePct { get; set; }
}
public class RISReportRow
{
public string RISNo { get; set; } = string.Empty;
public DateTime CreatedDate { get; set; }
public string ItemName { get; set; } = string.Empty;
public long ItemNo { get; set; }
public string DisciplineName { get; set; } = string.Empty;
public string ProjectName { get; set; } = string.Empty;
public decimal QtyIssued { get; set; }
public decimal TotalReturned { get; set; }
public decimal NetIssued { get; set; }
public short Status { get; set; }
public string StatusLabel { get; set; } = string.Empty;
}
public class DisciplineCount
{
public string DisciplineName { get; set; } = string.Empty;
public int Count { get; set; }
}
public class TopRecipient
{
public string IssuedTo { get; set; } = string.Empty;
public int SlipCount { get; set; }
public decimal TotalQty { get; set; }
}
public class MRSReportDto
{
public string CompanyName { get; set; } = "Lloyd Laboratories Incorporated";
public string PreparedBy { get; set; } = "Finance Department";
public string ReportNo { get; set; } = string.Empty;
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public MRSReportSummary Summary { get; set; } = new();
public List<MRSReportRow> Rows { get; set; } = [];
public List<ConditionTotal> ByCondition { get; set; } = [];
}
public class MRSReportSummary
{
public int TotalMRS { get; set; }
public decimal TotalQtyReturned { get; set; }
public decimal TotalQtyIssuedRIS { get; set; }
public decimal NetQtyConsumed { get; set; }
public decimal ReturnRatePct { get; set; }
public decimal GoodConditionPct { get; set; }
}
public class MRSReportRow
{
public string MRSNo { get; set; } = string.Empty;
public DateTime CreatedDate { get; set; }
public string RISNo { get; set; } = string.Empty;
public string ItemName { get; set; } = string.Empty;
public string ReturnedBy { get; set; } = string.Empty;
public decimal QtyReturned { get; set; }
public string Condition { get; set; } = string.Empty;
public short Status { get; set; }
public string StatusLabel { get; set; } = string.Empty;
}
public class ConditionTotal
{
public string Condition { get; set; } = string.Empty;
public decimal TotalQty { get; set; }
}
public class InventoryReportDto
{
public string CompanyName { get; set; } = "Lloyd Laboratories Incorporated";
public string PreparedBy { get; set; } = "Finance Department";
public string ReportNo { get; set; } = string.Empty;
public DateTime AsOf { get; set; }
public List<string> Departments { get; set; } = new();
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalRows { get; set; }
public int TotalPages => PageSize > 0 ? (int)Math.Ceiling(TotalRows / (double)PageSize) : 0;
public InventoryReportSummary Summary { get; set; } = new();
public List<InventoryReportRow> Rows { get; set; } = [];
public List<CategoryStockLevel> ByCategory { get; set; } = [];
public List<InventoryAlert> Alerts { get; set; } = [];
}
public class InventoryReportSummary
{
public int TotalSKUs { get; set; }
public decimal TotalOnHand { get; set; }
public decimal TotalQtyIn { get; set; }
public decimal TotalQtyOut { get; set; }
public decimal TotalValue { get; set; }
public int LowStockCount { get; set; }
public int OutOfStockCount { get; set; }
}
public class InventoryReportRow
{
public string ItemName { get; set; } = string.Empty;
public long ItemNo { get; set; }
public string ItemCategoryName { get; set; } = string.Empty;
public string? LotNo { get; set; }
public decimal QtyIn { get; set; }
public decimal QtyOut { get; set; }
public decimal QtyOnHand { get; set; }
public decimal UnitPrice { get; set; }
public int StockPct { get; set; }
public string? Department { get; set; }
public string? CurrencyCode { get; set; }
}
public class CategoryStockLevel
{
public string CategoryName { get; set; } = string.Empty;
public int AvgStockPct { get; set; }
}
public class InventoryAlert
{
public string ItemName { get; set; } = string.Empty;
public decimal QtyOnHand { get; set; }
public string Severity { get; set; } = string.Empty; // "Critical" | "Low"
}
}

View File

@ -1,14 +0,0 @@
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Reports.Response
{
public class InventoryData
{
public List<InventoryReportDto> Data { get; set; } = [];
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Reports.Response
{
public class MRSData
{
public List<MRSReportDto> Data { get; set; } = [];
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Reports.Response
{
public class RISData
{
public List<RISReportDto> Data { get; set; } = [];
}
}

View File

@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{
public class ApproveMRSRequest { public long MRSId { get; set; } }
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{
public class CancelMRSRequest
{
public long MRSId { get; set; }
public string Reason { get; set; } = string.Empty;
}
}

View File

@ -10,7 +10,7 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{ {
public int InventoryId { get; set; } public int InventoryId { get; set; }
public long PRDetailId { get; set; } public long PRDetailId { get; set; }
public int ProjectCodeId { get; set; } public string IssuedTo { get; set; } = string.Empty;
public byte DisciplineId { get; set; } public byte DisciplineId { get; set; }
public decimal QtyIssued { get; set; } public decimal QtyIssued { get; set; }
public string? Remarks { get; set; } public string? Remarks { get; set; }

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{
public class InventoryReportsRequest
{
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public string? Department { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public bool Paginate { get; set; }
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{
public class SearchRISProjectCodeRequest
{
public int? SearchProjectCodeId { get; set; }
public string? SearchRISNo { get; set; }
public string? SearchProjectCode { get; set; }
}
}

View File

@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
{
public class MRSPagedResponse
{
public List<MRSListItem> Data { get; set; } = [];
public int RecordsTotal { get; set; }
}
public class MRSListItem
{
public long MRSId { get; set; }
public string MRSNo { get; set; } = string.Empty;
public long RISId { get; set; }
public string? RISNo { get; set; }
public string? ItemName { get; set; }
public string? ReturnedBy { get; set; }
public decimal QtyReturned { get; set; }
public string? Condition { get; set; }
public string? Remarks { get; set; }
public short Status { get; set; }
public string? StatusLabel { get; set; }
public string? CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string? ApprovedBy { get; set; }
public DateTime? ApprovedDate { get; set; }
public int InventoryId { get; set; }
}
}

View File

@ -1,17 +1,28 @@
using CPRNIMS.Infrastructure.Models.Inventory; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Response namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
{ {
public class MRSResponse public class MRSResponse
{ {
[JsonPropertyName("success")] public bool Success { get; set; } public long MRSId { get; set; }
[JsonPropertyName("message")] public string? Message { get; set; } public string MRSNo { get; set; } = string.Empty;
[JsonPropertyName("data")] public MRSData? Data { get; set; } public long RISId { get; set; }
public string RISNo { get; set; } = string.Empty;
public int InventoryId { get; set; }
public string ItemName { get; set; } = string.Empty;
public string ReturnedBy { get; set; } = string.Empty;
public decimal QtyReturned { get; set; }
public string? Condition { get; set; }
public string? Remarks { get; set; }
public short Status { get; set; }
public string StatusLabel => Status switch { 0 => "Draft", 1 => "Approved", 2 => "Cancelled", _ => "Unknown" };
public string CreatedBy { get; set; } = string.Empty;
public DateTime CreatedDate { get; set; }
public string? ApprovedBy { get; set; }
public DateTime? ApprovedDate { get; set; }
} }
} }

View File

@ -27,9 +27,7 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
public long ItemNo { get; set; } public long ItemNo { get; set; }
public string? ProjectCode { get; set; } public string? IssuedTo { get; set; }
public string? ProjectName { get; set; }
public string? DisciplineName { get; set; } public string? DisciplineName { get; set; }

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
{
public class RISProjectCodeResponse
{
public string ProjectCode { get; set; }=string.Empty;
public string ProjectName { get; set; } = string.Empty;
}
}

View File

@ -14,7 +14,7 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
public string ItemName { get; set; } = string.Empty; public string ItemName { get; set; } = string.Empty;
public long ItemNo { get; set; } public long ItemNo { get; set; }
public string? LotNo { get; set; } public string? LotNo { get; set; }
public int ProjectCodeId { get; set; } public string IssuedTo { get; set; } = string.Empty;
public string DisciplineName { get; set; } = string.Empty; public string DisciplineName { get; set; } = string.Empty;
public string? Message { get; set; } public string? Message { get; set; }
public byte DisciplineId { get; set; } public byte DisciplineId { get; set; }
@ -28,7 +28,5 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
public DateTime? ApprovedDate { get; set; } public DateTime? ApprovedDate { get; set; }
public decimal MRSCount { get; set; } public decimal MRSCount { get; set; }
public decimal TotalReturned { get; set; } public decimal TotalReturned { get; set; }
public string? ProjectName { get; set; }
public string? ProjectCode { get; set; }
} }
} }

View File

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Response
{
public class SearchApiResponse<T>
{
public bool Success { get; set; }
public List<T> data { get; set; } = new List<T>();
}
public class SearchRISProjectCodeResponse
{
public long RISId { get; set; }
public string RISNo { get; set; } = string.Empty;
public int ProjectCodeId { get; set; }
public string ProjectCode { get; set; } = string.Empty;
public string ProjectName { get; set; } = string.Empty;
public string DisciplineName { get; set; } = string.Empty;
public decimal QtyAvailableToReturn { get; set; }
}
public class ProjectCodeOptionResponse
{
public int ProjectCodeId { get; set; }
public string ProjectCode { get; set; } = string.Empty;
public string ProjectName { get; set; } = string.Empty;
}
}

View File

@ -17,7 +17,6 @@ namespace CPRNIMS.Infrastructure.Dto.Inventory
public decimal QtyOnHand { get; set; } public decimal QtyOnHand { get; set; }
public decimal QtyIn { get; set; } public decimal QtyIn { get; set; }
public decimal QtyOut { get; set; } public decimal QtyOut { get; set; }
public IEnumerable<ProjectCodeDto> ProjectCodes { get; set; } = [];
public IEnumerable<DisciplineDto> Disciplines { get; set; } = []; public IEnumerable<DisciplineDto> Disciplines { get; set; } = [];
public IEnumerable<RISReferenceDto> OpenRISList { get; set; } = []; public IEnumerable<RISReferenceDto> OpenRISList { get; set; } = [];
} }

View File

@ -23,7 +23,7 @@ namespace CPRNIMS.Infrastructure.Dto.PO
public string? SupplierName { get; set; } public string? SupplierName { get; set; }
public string? Manufacturer { get; set; } public string? Manufacturer { get; set; }
public int ItemCount { get; set; } public int ItemCount { get; set; }
public byte CurrencyId { get; set; } public short CurrencyId { get; set; }
public string? Department { get; set; } public string? Department { get; set; }
public string? ItemCategoryName { get; set; } public string? ItemCategoryName { get; set; }
public DateTime CommitmentDate { get; set; } public DateTime CommitmentDate { get; set; }

View File

@ -23,7 +23,6 @@ namespace CPRNIMS.Infrastructure.Entities.Account
public DateTime UpdatedDate { get; set; } public DateTime UpdatedDate { get; set; }
public string? ProfilePicture { get; set; } public string? ProfilePicture { get; set; }
public string? Address { get; set; } public string? Address { get; set; }
public bool? IsActive { get; set; }
public Attachment? Attachment { get; set; } public Attachment? Attachment { get; set; }
} }
} }

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Finance namespace CPRNIMS.Infrastructure.Entities.Finance
{ {
public class RRDetailDto : CommonProperties public class RRDetail : CommonProperties
{ {
[Key] [Key]
public long RRDetailId { get; set; } public long RRDetailId { get; set; }

View File

@ -17,7 +17,6 @@ namespace CPRNIMS.Infrastructure.Entities.Inventory
public long RRNo { get; set; } public long RRNo { get; set; }
public string CreatedBy { get; set; }=string.Empty; public string CreatedBy { get; set; }=string.Empty;
public bool IsActive { get; set; } public bool IsActive { get; set; }
public Inventory? Inventory { get; set; }
public ICollection<InventTransDetail> InventTransDetails { get; set; } = []; public ICollection<InventTransDetail> InventTransDetails { get; set; } = [];
} }
} }

View File

@ -1,6 +1,4 @@
using CPRNIMS.Infrastructure.Entities.Items; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Entities.Receiving;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@ -18,15 +16,13 @@ namespace CPRNIMS.Infrastructure.Entities.Inventory
public long InventTransDetailId { get; set; } public long InventTransDetailId { get; set; }
public int InventTransId { get; set; } public int InventTransId { get; set; }
public byte TransTypeId { get; set; } public byte TransTypeId { get; set; }
public long RRDetailId { get; set; }
public decimal QtyIn { get; set; } public decimal QtyIn { get; set; }
public decimal QtyOut { get; set; } public decimal QtyOut { get; set; }
public DateTime CreatedDate { get; set; } public DateTime CreatedDate { get; set; }
public string? Remarks { get; set; } public string? Remarks { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public long PRDetailId { get; set; } public long PRDetailId { get; set; }
public long? RRDetailId { get; set; }
public PRDetails? PRDetails { get; set; } public PRDetails? PRDetails { get; set; }
public RRDetails? RRDetails { get; set; }
public InventTrans? InventTrans { get; set; }
} }
} }

View File

@ -1,5 +1,4 @@
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Items;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@ -25,6 +24,5 @@ namespace CPRNIMS.Infrastructure.Entities.Inventory
public Lot? Lot { get; set; } public Lot? Lot { get; set; }
public ICollection<InventTrans> InventTrans { get; set; } = []; public ICollection<InventTrans> InventTrans { get; set; } = [];
public ApplicationUser? User { get; set; } public ApplicationUser? User { get; set; }
public Item? Item { get; set; }
} }
} }

View File

@ -42,4 +42,5 @@ namespace CPRNIMS.Infrastructure.Entities.Inventory
public RIS RIS { get; set; } = null!; public RIS RIS { get; set; } = null!;
public Inventory Inventory { get; set; } = null!; public Inventory Inventory { get; set; } = null!;
} }
} }

View File

@ -20,6 +20,10 @@ namespace CPRNIMS.Infrastructure.Entities.Inventory
public int InventoryId { get; set; } public int InventoryId { get; set; }
public long PRDetailId { get; set; } public long PRDetailId { get; set; }
[Required, MaxLength(450)]
public string IssuedTo { get; set; } = string.Empty;
public byte DisciplineId { get; set; } public byte DisciplineId { get; set; }
public decimal QtyIssued { get; set; } public decimal QtyIssued { get; set; }
@ -36,8 +40,6 @@ namespace CPRNIMS.Infrastructure.Entities.Inventory
public string? CanceledBy { get; set; } public string? CanceledBy { get; set; }
public DateTime? CanceledDate { get; set; } public DateTime? CanceledDate { get; set; }
public string? Reason { get; set; } public string? Reason { get; set; }
public int ProjectCodeId { get; set; }
public ProjectCodes ProjectCodes { get; set; } = null!;
public Inventory Inventory { get; set; } = null!; public Inventory Inventory { get; set; } = null!;
public PRDetails PRDetail { get; set; } = null!; public PRDetails PRDetail { get; set; } = null!;
public Discipline Discipline { get; set; } = null!; public Discipline Discipline { get; set; } = null!;

View File

@ -1,7 +1,13 @@
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CPRNIMS.Infrastructure.Entities.Items namespace CPRNIMS.Infrastructure.Entities.Items
{ {
@ -36,6 +42,5 @@ namespace CPRNIMS.Infrastructure.Entities.Items
public string? ItemAttachPath { get; set; } public string? ItemAttachPath { get; set; }
public bool IsMDLD { get; set; } public bool IsMDLD { get; set; }
public bool CheckBox { get; set; } public bool CheckBox { get; set; }
public ItemCode? ItemCode { get; set; }
} }
} }

View File

@ -23,7 +23,5 @@ namespace CPRNIMS.Infrastructure.Entities.Items
public byte RequestTypeId { get; set; } public byte RequestTypeId { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public int CartItemCount { get; set; } public int CartItemCount { get; set; }
public short ItemCategoryId { get; set; }
public ItemCategory? ItemCategory { get; set; }
} }
} }

View File

@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Items
{
public class ItemDtos
{
[Key]
public long ItemNo { get; set; }
public long ItemCodeId { get; set; }
public string? Department { get; set; }
public string? ItemCategoryName { get; set; }
public string? UserId { get; set; }
public string? ItemName { get; set; }
public string? ItemDescription { get; set; }
public string? StatusName { get; set; }
public bool IsActive { get; set; }
public bool IsCommon { get; set; }
public byte RequestTypeId { get; set; }
public string? ItemLocalName { get; set; }
public string? ItemTypeName { get; set; }
public string? PRTypeName { get; set; }
public decimal Qty { get; set; }
public int ItemColorId { get; set; }
public short ItemLocalId { get; set; }
public int UOMId { get; set; }
public short ItemCategoryId { get; set; }
public string? PackagingTypeName { get; set; }
public short ItemClassId { get; set; }
public string? UOMName { get; set; }
public string? ItemColorName { get; set; }
public long ItemAttachId { get; set; }
public string? ItemAttachPath { get; set; }
public bool IsMDLD { get; set; }
public bool CheckBox { get; set; }
}
}

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.PO
{
[Table("Currencies")]
public class Currencies
{
[Key]
public byte CurrencyId { get; set; }
public string CurrencyName { get; set; }=string.Empty;
public decimal VatRate { get; set; }
public decimal CER { get; set; }
public string? AmountWords { get; set; }
public bool? IsActive { get; set; }
}
}

View File

@ -34,7 +34,6 @@ namespace CPRNIMS.Infrastructure.Entities.PO
public byte PODId { get; set; } public byte PODId { get; set; }
public byte POTypeId { get; set; } public byte POTypeId { get; set; }
public byte IncoTermsId { get; set; } public byte IncoTermsId { get; set; }
public byte CurrencyId { get; set; }
public string? IncotermsName { get; set; } public string? IncotermsName { get; set; }
public string? CountryOrigin { get; set; } public string? CountryOrigin { get; set; }
} }

View File

@ -6,7 +6,7 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CPRNIMS.Infrastructure.Entities.Purchasing namespace CPRNIMS.Infrastructure.Entities.Purchasing
{ {

View File

@ -1,5 +1,4 @@
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.ViewModel.Items; using CPRNIMS.Infrastructure.ViewModel.Items;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -25,6 +24,5 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
public decimal Qty { get; set; } public decimal Qty { get; set; }
public bool IsSearched { get; set; } public bool IsSearched { get; set; }
public PR? PRs { get; set; } public PR? PRs { get; set; }
public ItemCategory? ItemCategory { get; set; }
} }
} }

View File

@ -17,7 +17,6 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
public string? ProjectName { get; set; } public string? ProjectName { get; set; }
public int MaxDays { get; set; } public int MaxDays { get; set; }
public string? DeliveryAddress { get; set; } public string? DeliveryAddress { get; set; }
public string? StatusName { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
} }
} }

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Receiving namespace CPRNIMS.Infrastructure.Entities.Receiving
{ {
public class RRDetailDto public class RRDetail
{ {
[Key] [Key]
public long PRDetailsId { get; set; } public long PRDetailsId { get; set; }

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Receiving
{
[Table("RRDetails")]
public class RRDetails
{
[Key]
public long RRDetailId { get; set; }
public long PRDetailId { get; set; }
public long RRId { get; set; }
public long PODetailId { get; set; }
public decimal Quantity { get; set; }
public decimal QuantityReceived { get; set; }
public decimal QtyRemaining { get; set; }
public decimal UnitPrice { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -23,6 +23,5 @@ namespace CPRNIMS.Infrastructure.Models.Account
public string? Token { get; set; } public string? Token { get; set; }
public string? Company { get; set; } public string? Company { get; set; }
public string? MyAccess { get; set; } public string? MyAccess { get; set; }
public int DepartmentId { get; set; }
} }
} }

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Models.Inventory
{
public class MRSData
{
[JsonPropertyName("mrsId")] public long MRSId { get; set; }
[JsonPropertyName("mrsNo")] public string? MRSNo { get; set; }
[JsonPropertyName("risId")] public long RISId { get; set; }
[JsonPropertyName("inventoryId")] public int InventoryId { get; set; }
[JsonPropertyName("returnedBy")] public string? ReturnedBy { get; set; }
[JsonPropertyName("qtyReturned")] public decimal QtyReturned { get; set; }
[JsonPropertyName("condition")] public string? Condition { get; set; }
[JsonPropertyName("remarks")] public string? Remarks { get; set; }
[JsonPropertyName("status")] public short Status { get; set; }
[JsonPropertyName("createdBy")] public string? CreatedBy { get; set; }
[JsonPropertyName("createdDate")] public DateTime CreatedDate { get; set; }
[JsonPropertyName("approvedBy")] public string? ApprovedBy { get; set; }
[JsonPropertyName("approvedDate")] public DateTime? ApprovedDate { get; set; }
}
}

View File

@ -24,7 +24,7 @@ namespace CPRNIMS.Infrastructure.ViewModel.PO
public string? ContactPerson { get; set; } public string? ContactPerson { get; set; }
public string? Manufacturer { get; set; } public string? Manufacturer { get; set; }
public int ItemCount { get; set; } public int ItemCount { get; set; }
public byte CurrencyId { get; set; } public short CurrencyId { get; set; }
public string? Department { get; set; } public string? Department { get; set; }
public string? ItemCategoryName { get; set; } public string? ItemCategoryName { get; set; }
public DateTime CommitmentDate { get; set; } public DateTime CommitmentDate { get; set; }

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
<NameOfLastUsedPublishProfile>D:\sourcecode\NonInventPurchasing\CPRNIMS.WebApi\Properties\PublishProfiles\FolderProfile1.pubxml</NameOfLastUsedPublishProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -1,18 +1,15 @@
using CPRNIMS.Domain.Contracts.Account; using CPRNIMS.Domain.Contracts.Account;
using CPRNIMS.Domain.Contracts.Canvass; using CPRNIMS.Domain.Contracts.Canvass;
using CPRNIMS.Domain.Contracts.Common;
using CPRNIMS.Domain.Contracts.Finance; using CPRNIMS.Domain.Contracts.Finance;
using CPRNIMS.Domain.Contracts.Inventory; using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Domain.Contracts.Items; using CPRNIMS.Domain.Contracts.Items;
using CPRNIMS.Domain.Contracts.PO; using CPRNIMS.Domain.Contracts.PO;
using CPRNIMS.Domain.Contracts.PR; using CPRNIMS.Domain.Contracts.PR;
using CPRNIMS.Domain.Contracts.Receiving; using CPRNIMS.Domain.Contracts.Receiving;
using CPRNIMS.Domain.Contracts.Reports;
using CPRNIMS.Domain.Contracts.SMTP; using CPRNIMS.Domain.Contracts.SMTP;
using CPRNIMS.Domain.Services; using CPRNIMS.Domain.Services;
using CPRNIMS.Domain.Services.Account; using CPRNIMS.Domain.Services.Account;
using CPRNIMS.Domain.Services.Canvass; using CPRNIMS.Domain.Services.Canvass;
using CPRNIMS.Domain.Services.Common;
using CPRNIMS.Domain.Services.Finance; using CPRNIMS.Domain.Services.Finance;
using CPRNIMS.Domain.Services.Inventory; using CPRNIMS.Domain.Services.Inventory;
using CPRNIMS.Domain.Services.PO; using CPRNIMS.Domain.Services.PO;
@ -21,7 +18,6 @@ using CPRNIMS.Domain.Services.SMTP;
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Reports;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -93,6 +89,7 @@ namespace CPRNIMS.WebApi.Common
sql.EnableRetryOnFailure(5, TimeSpan.FromHours(2), null); sql.EnableRetryOnFailure(5, TimeSpan.FromHours(2), null);
sql.CommandTimeout(20); sql.CommandTimeout(20);
})); }));
services.AddDbContext<PurchLocalDbContext>(options => services.AddDbContext<PurchLocalDbContext>(options =>
options.UseSqlServer(localConn, sql => options.UseSqlServer(localConn, sql =>
{ {
@ -150,7 +147,6 @@ namespace CPRNIMS.WebApi.Common
{ {
services.AddMemoryCache(); services.AddMemoryCache();
services.AddScoped<IRoleAuthorizationCache, RoleAuthorizationCache>(); services.AddScoped<IRoleAuthorizationCache, RoleAuthorizationCache>();
services.AddScoped<ITransactionFacade, TransactionFacade>();
services.AddScoped<IDepartment, Department>(); services.AddScoped<IDepartment, Department>();
services.AddScoped<IAttachment, Domain.Services.Account.Attachment>(); services.AddScoped<IAttachment, Domain.Services.Account.Attachment>();
services.AddScoped<IItem, Domain.Services.Items.Item>(); services.AddScoped<IItem, Domain.Services.Items.Item>();
@ -158,8 +154,7 @@ namespace CPRNIMS.WebApi.Common
services.AddScoped<ICanvass, Canvass>(); services.AddScoped<ICanvass, Canvass>();
services.AddScoped<IRIS, RIS>(); services.AddScoped<IRIS, RIS>();
services.AddScoped<IMRS, MRS>(); services.AddScoped<IMRS, MRS>();
services.AddScoped<IReportDataService, ReportDataService>();
services.AddScoped<IInventoryReports, InventoryReports>();
#region Automation using LLM #region Automation using LLM
services.AddHttpClient<SupplierSearchService>(); services.AddHttpClient<SupplierSearchService>();
#endregion #endregion

View File

@ -67,7 +67,6 @@ namespace CPRNIMS.WebApi.Controllers.Account
userId = user.Id, userId = user.Id,
userName = user.UserName, userName = user.UserName,
fullName = user.FullName, fullName = user.FullName,
departmentId = user.DepartmentId,
email = user.Email, email = user.Email,
phoneNumber = user.PhoneNumber, phoneNumber = user.PhoneNumber,
company = user.Company, company = user.Company,

View File

@ -2,6 +2,7 @@
using CPRNIMS.Domain.Services; using CPRNIMS.Domain.Services;
using CPRNIMS.Infrastructure.Dto.Inventory; using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.WebApi.Controllers.Base; using CPRNIMS.WebApi.Controllers.Base;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;

View File

@ -1,68 +0,0 @@
using Azure.Core;
using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Domain.Contracts.Reports;
using CPRNIMS.Infrastructure.Dto.Inventory.Reports;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.WebApi.Security;
using Microsoft.AspNetCore.Mvc;
namespace CPRNIMS.WebApi.Controllers.Inventory
{
[Route("api/[controller]")]
[ApiController]
public class InventoryReportsController : ControllerBase
{
private readonly IReportDataService _data;
private readonly IInventoryReports _reports;
public InventoryReportsController(IReportDataService data, IInventoryReports reports)
{
_data = data;
_reports = reports;
}
[HttpGet("GetRISReport")]
public async Task<IActionResult> GetRISReport([FromQuery] InventoryReportsRequest request, CancellationToken ct)
{
var currentUser = User.ToUserClaims();
if (currentUser == null)
return BadRequest();
var data = await _reports.GetRISReportAsync(request, currentUser.UserName,currentUser.DepartmentId, ct);
return Ok(data);
}
[HttpGet("GetMRSReport")]
public async Task<IActionResult> GetMRSReport([FromQuery] InventoryReportsRequest request, CancellationToken ct)
{
var currentUser = User.ToUserClaims();
if (currentUser == null)
return BadRequest();
var data = await _reports.GetMRSReportAsync(request, currentUser.UserName, currentUser.DepartmentId, ct);
return Ok(data);
}
[HttpGet("GetInventoryReport")]
public async Task<IActionResult> GetInventoryReport([FromQuery] InventoryReportsRequest request, CancellationToken ct)
{
var currentUser = User.ToUserClaims();
if (currentUser == null)
return BadRequest();
var data = await _reports.GetInventoryReportAsync(request, currentUser.UserName, currentUser.DepartmentId, ct);
return Ok(data);
}
[HttpGet("GetRISData")]
public IActionResult GetData([FromQuery] DateTime dateFrom, [FromQuery] DateTime dateTo,CancellationToken ct)
{
var result = new RISReportDataDto
{
Rows = _data.GetMain(dateFrom, dateTo),
Disciplines = _data.GetDisciplines(dateFrom, dateTo),
Recipients = _data.GetRecipients(dateFrom, dateTo)
};
return Ok(result);
}
}
}

View File

@ -1,76 +1,12 @@
using CPRNIMS.Domain.Contracts.Inventory; using Microsoft.AspNetCore.Mvc;
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.WebApi.Security;
using Microsoft.AspNetCore.Mvc;
namespace CPRNIMS.WebApi.Controllers.Inventory namespace CPRNIMS.WebApi.Controllers.Inventory
{ {
[Route("api/[controller]")] public class MRSMgmtController : Controller
[ApiController]
public partial class MRSMgmtController : ControllerBase
{ {
private readonly IMRS _mrs; public IActionResult Index()
public MRSMgmtController(IMRS mrs) => _mrs = mrs;
[HttpGet]
public async Task<IActionResult> GetMRS([FromQuery] MRSFilterDto filter, CancellationToken ct)
{ {
var currentUser = User.ToUserClaims(); return View();
if (currentUser == null)
return BadRequest();
var result = await _mrs.GetPagedAsync(filter, ct, currentUser.DepartmentId, currentUser.UserName);
return Ok(result);
}
[HttpGet("SearchRIS")]
public async Task<IActionResult> SearchRIS([FromQuery] string? searchRISNo, int? projectCodeId, CancellationToken ct)
{
var results = await _mrs.SearchRISForReturnAsync(searchRISNo, projectCodeId, ct);
return Ok(new { success = true, data = results });
}
[HttpGet("SearchProjects")]
public async Task<IActionResult> SearchProjects([FromQuery] string? searchProjectCode, CancellationToken ct)
{
var results = await _mrs.GetProjectsWithOpenRISAsync(searchProjectCode, ct);
return Ok(new { success = true, data = results });
}
[HttpPost]
public async Task<IActionResult> CreateMRS([FromBody] CreateMRSRequest request, CancellationToken ct)
{
var currentUser = User.ToUserClaims();
if (currentUser == null)
return BadRequest();
var result = await _mrs.CreateAsync(request, currentUser.UserName, ct);
return Ok(new { success = true, message = $"MRS# {result.MRSNo} created successfully." });
}
[HttpPost("Approve")]
public async Task<IActionResult> ApproveMRS([FromBody] ApproveMRSRequest request, CancellationToken ct)
{
var currentUser = User.ToUserClaims();
if (currentUser == null)
return BadRequest();
await _mrs.ApproveAsync(request.MRSId, currentUser.UserName, ct);
return Ok(new { success = true, message = "MRS approved successfully." });
}
[HttpPost("Cancel")]
public async Task<IActionResult> CancelMRS([FromBody] CancelMRSRequest request, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(request.Reason))
return BadRequest(new { success = false, message = "A reason for cancellation is required." });
var currentUser = User.ToUserClaims();
if (currentUser == null)
return BadRequest();
await _mrs.CancelAsync(request, currentUser.UserName, ct);
return Ok(new {success = true,message = "MRS cancelled and inventory adjusted."});
} }
} }
} }

View File

@ -4,6 +4,7 @@ using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.WebApi.Security; using CPRNIMS.WebApi.Security;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace CPRNIMS.WebApi.Controllers.Inventory namespace CPRNIMS.WebApi.Controllers.Inventory
{ {
@ -19,11 +20,7 @@ namespace CPRNIMS.WebApi.Controllers.Inventory
[HttpGet("GetRIS")] [HttpGet("GetRIS")]
public async Task<IActionResult> GetRIS([FromQuery] RISFilterDto filter, CancellationToken ct) public async Task<IActionResult> GetRIS([FromQuery] RISFilterDto filter, CancellationToken ct)
{ {
var currentUser = User.ToUserClaims(); var result = await _risRepo.GetPagedAsync(filter,ct);
if (currentUser == null)
return BadRequest();
var result = await _risRepo.GetPagedAsync(filter,ct, currentUser.DepartmentId, currentUser.UserName);
return Ok(result); return Ok(result);
} }
@ -51,7 +48,12 @@ namespace CPRNIMS.WebApi.Controllers.Inventory
}); });
var ris = await _risRepo.CreateAsync(request, currentUser.UserName,ct); var ris = await _risRepo.CreateAsync(request, currentUser.UserName,ct);
return Ok(new { success = true, message = $"RIS# {ris.RISNo} created successfully." }); return Ok(new
{
success = true,
message = $"RIS {ris.RISNo} created successfully.",
data= ris
});
} }
[HttpPut("ApproveRIS")] [HttpPut("ApproveRIS")]
@ -67,11 +69,7 @@ namespace CPRNIMS.WebApi.Controllers.Inventory
[HttpPut("CancelRIS")] [HttpPut("CancelRIS")]
public async Task<IActionResult> CancelRIS([FromBody] CancelRISRequest request, CancellationToken ct) public async Task<IActionResult> CancelRIS([FromBody] CancelRISRequest request, CancellationToken ct)
{ {
var currentUser = User.ToUserClaims(); await _risRepo.CancelAsync(request, ct);
if (currentUser == null)
return BadRequest();
await _risRepo.CancelAsync(request, currentUser.UserName, ct);
return Ok(new { success = true, message = "RIS cancelled and inventory restored." }); return Ok(new { success = true, message = "RIS cancelled and inventory restored." });
} }
} }

View File

@ -284,12 +284,6 @@ namespace CPRNIMS.WebApi.Controllers.PO
} }
#endregion #endregion
#region Get #region Get
[HttpPost("GetCurrencies")]
public async Task<IActionResult> GetCurrencies(Currencies request, CancellationToken ct)
{
var data = await _purchaseOrder.GetCurrencies(request.CurrencyName,ct);
return Ok(data);
}
[HttpGet("GetPOFormData")] [HttpGet("GetPOFormData")]
public async Task<IActionResult> GetPOFormData(int? poId = null) public async Task<IActionResult> GetPOFormData(int? poId = null)
{ {

View File

@ -5,7 +5,6 @@ using CPRNIMS.WebApi.Common;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddApplicationServices(builder); builder.Services.AddApplicationServices(builder);
builder.Services.AddFastReport();
builder.Services.AddAutoMapper(cfg => { }, typeof(SupplierRequestProfile)); builder.Services.AddAutoMapper(cfg => { }, typeof(SupplierRequestProfile));
@ -17,22 +16,20 @@ if (app.Environment.IsDevelopment())
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(c => app.UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint("./v2/swagger.json", "LLOYD API V2"); c.SwaggerEndpoint("./v2/swagger.json", "LLOYD API V2"); //originally "./swagger/v1/swagger.json"
}); });
} }
app.UseMiddleware<GlobalExceptionMiddleware>(); app.UseMiddleware<GlobalExceptionMiddleware>();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(c => app.UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint("./v2/swagger.json", "LLOYD API V2"); c.SwaggerEndpoint("./v2/swagger.json", "LLOYD API V2"); //originally "./swagger/v1/swagger.json"
}); });
app.UseCors("AllowAnyOrigin"); app.UseCors("AllowAnyOrigin");
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseFastReport();
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<_PublishTargetUrl>D:\sourcecode\CPRNIMS\CPRNIMS.WebApi\bin\Release\net8.0\publish\</_PublishTargetUrl>
<History>True|2025-12-17T23:10:35.4921808Z||;True|2025-12-16T14:53:58.3743182+08:00||;True|2025-12-16T14:53:53.8528078+08:00||;True|2025-11-27T09:07:09.5404338+08:00||;True|2025-11-27T09:07:02.8345022+08:00||;True|2025-11-26T16:01:43.2068083+08:00||;True|2025-11-26T13:18:23.6103149+08:00||;True|2025-11-26T13:06:57.8584612+08:00||;True|2025-11-05T07:21:05.3959433+08:00||;True|2025-10-24T13:44:41.2876894+08:00||;True|2025-10-24T09:10:03.6232364+08:00||;True|2025-10-24T09:09:56.5522930+08:00||;True|2025-09-16T09:32:01.0906622+08:00||;True|2025-09-12T08:54:29.9542476+08:00||;True|2025-09-11T12:06:12.9357427+08:00||;True|2025-09-09T15:12:53.5036032+08:00||;True|2025-09-08T16:13:57.6489788+08:00||;True|2025-09-08T15:49:13.2220596+08:00||;True|2025-09-08T15:49:09.1175544+08:00||;True|2025-09-08T14:16:49.9685540+08:00||;True|2025-09-04T17:16:30.6365380+08:00||;True|2025-09-04T16:11:55.1923650+08:00||;True|2025-09-04T15:59:54.3131225+08:00||;True|2025-09-04T13:04:52.2805520+08:00||;True|2025-09-04T13:04:43.9603490+08:00||;True|2025-09-03T17:16:57.9153347+08:00||;True|2025-09-03T16:05:34.6735848+08:00||;True|2025-09-02T16:31:41.1104433+08:00||;True|2025-09-02T16:31:28.9543370+08:00||;True|2025-09-02T11:02:07.6244438+08:00||;True|2025-09-01T07:06:55.2325589+08:00||;True|2025-08-28T07:46:30.3699102+08:00||;True|2025-08-28T07:04:09.9075273+08:00||;True|2025-08-26T09:48:46.3663800+08:00||;True|2025-08-21T07:20:24.1925540+08:00||;True|2025-08-20T07:13:03.4186833+08:00||;True|2025-08-19T10:43:26.3618437+08:00||;True|2025-08-14T17:07:08.7644641+08:00||;True|2025-08-14T11:52:57.3626470+08:00||;True|2025-08-13T10:04:24.2646290+08:00||;True|2025-08-13T09:52:02.8860494+08:00||;True|2025-08-12T13:30:44.9278812+08:00||;True|2025-08-12T07:14:01.7635891+08:00||;True|2025-08-12T07:13:37.8273450+08:00||;True|2025-08-08T11:00:25.8006408+08:00||;True|2025-08-08T08:33:19.7826504+08:00||;True|2025-08-08T08:33:17.0210998+08:00||;True|2025-08-05T09:52:56.3618071+08:00||;True|2025-07-31T15:04:11.5021618+08:00||;True|2025-07-21T17:16:42.5825002+08:00||;True|2025-07-21T17:16:31.3000014+08:00||;True|2025-06-20T10:19:19.8573068+08:00||;True|2025-05-28T08:14:52.0497965+08:00||;True|2025-05-28T08:14:32.1379767+08:00||;True|2025-05-15T16:20:18.0632480+08:00||;True|2025-05-15T16:19:48.4614805+08:00||;True|2025-05-15T10:52:08.4012348+08:00||;True|2025-05-15T10:52:01.9277880+08:00||;True|2025-05-13T09:35:30.2002459+08:00||;True|2025-04-22T09:44:31.3997970+08:00||;True|2025-04-22T09:44:25.6317531+08:00||;True|2025-04-14T08:03:15.9455375+08:00||;True|2025-04-11T09:30:57.1064901+08:00||;True|2025-04-09T13:43:42.7362198+08:00||;True|2025-04-09T13:43:39.6044873+08:00||;True|2025-04-09T13:36:06.1196237+08:00||;True|2025-04-09T13:35:58.4320424+08:00||;True|2025-04-04T09:43:18.5933871+08:00||;True|2025-04-04T09:42:34.9498924+08:00||;True|2025-04-03T07:02:46.7077629+08:00||;True|2025-04-03T06:58:02.0551766+08:00||;True|2025-03-21T09:52:18.3925005+08:00||;True|2025-03-20T14:39:10.7153863+08:00||;True|2025-03-20T14:38:01.6285942+08:00||;True|2025-03-20T14:37:56.4692955+08:00||;True|2025-03-20T12:17:55.1302908+08:00||;True|2025-03-18T17:04:40.7861848+08:00||;True|2025-03-18T17:04:37.3907842+08:00||;True|2025-03-14T15:52:44.9073796+08:00||;True|2025-03-07T14:12:45.0977693+08:00||;True|2025-03-07T14:12:42.5277665+08:00||;True|2025-02-27T09:40:55.2110821+08:00||;True|2025-02-26T10:06:26.6616955+08:00||;True|2025-02-25T13:52:14.0774519+08:00||;True|2025-02-25T12:12:58.5452123+08:00||;True|2025-02-21T14:21:27.8721893+08:00||;True|2025-02-21T14:21:17.5025040+08:00||;True|2025-02-18T13:28:26.1030353+08:00||;True|2025-02-14T09:30:08.9595204+08:00||;True|2025-02-13T08:42:38.0359073+08:00||;True|2025-02-03T17:18:34.9028789+08:00||;True|2025-01-27T14:37:48.6993964+08:00||;True|2025-01-21T09:04:15.0865384+08:00||;True|2025-01-16T07:41:47.1616176+08:00||;False|2025-01-16T07:40:14.1951891+08:00||;True|2025-01-16T07:03:41.6806457+08:00||;True|2025-01-16T07:03:31.4460188+08:00||;True|2025-01-15T10:23:23.7811134+08:00||;False|2025-01-15T10:22:54.8331554+08:00||;True|2025-01-15T10:02:24.4815760+08:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net8.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net8.0</TargetFramework>
<ProjectGuid>8ab7b541-48dc-4dbf-84e0-05b161c32965</ProjectGuid>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

View File

@ -16,7 +16,6 @@ namespace CPRNIMS.WebApi.Security
UserName = user.FindFirstValue(ClaimTypes.Name) ?? "", UserName = user.FindFirstValue(ClaimTypes.Name) ?? "",
FullName = user.FindFirstValue("FullName") ?? "", FullName = user.FindFirstValue("FullName") ?? "",
Company = user.FindFirstValue("Company") ?? "", Company = user.FindFirstValue("Company") ?? "",
DepartmentId = Convert.ToInt32(user.FindFirstValue("DepartmentId")),
Roles = user.FindAll(ClaimTypes.Role) Roles = user.FindAll(ClaimTypes.Role)
.Select(r => r.Value) .Select(r => r.Value)
.ToList() .ToList()

View File

@ -1,13 +1,13 @@
USE [CPRNIMS] USE [CPRNIMS]
GO GO
/****** Object: StoredProcedure [dbo].[GetInventory] Script Date: 6/18/2026 3:09:49 PM ******/ /****** Object: StoredProcedure [dbo].[GetInventory] Script Date: 6/11/2026 9:29:29 AM ******/
SET ANSI_NULLS ON SET ANSI_NULLS ON
GO GO
SET QUOTED_IDENTIFIER ON SET QUOTED_IDENTIFIER ON
GO GO
ALTER PROCEDURE [dbo].[GetInventory] ALTER PROCEDURE [dbo].[GetInventory]
( (
@UserId VARCHAR(450)='16b37c00-131f-4205-b8f6-ad4d0f9f3a32', @UserId VARCHAR(450)='89da2977-c70f-4df9-94d4-9a610aa999ea',
@SearchPRNo VARCHAR(50) = '', @SearchPRNo VARCHAR(50) = '',
@SearchItemNo VARCHAR(50) = '', @SearchItemNo VARCHAR(50) = '',
@SearchItemName VARCHAR(100) = '', @SearchItemName VARCHAR(100) = '',
@ -20,18 +20,6 @@ AS
BEGIN BEGIN
SET NOCOUNT ON; SET NOCOUNT ON;
DECLARE @Offset INT = (@PageNumber - 1) * @PageSize; DECLARE @Offset INT = (@PageNumber - 1) * @PageSize;
DECLARE @HasFullAccess BIT = 0;
DECLARE @UserDepartmentId INT,@UserName VARCHAR(50);
SELECT @UserDepartmentId = DepartmentId,@UserName=UserName
FROM dbo.Users
WHERE Id = @UserId;
IF @UserName IN ('LSKRISUR24','LSCYNDIZ25','LSJONTAN25','LHRIOCAS24')
SET @HasFullAccess = 1;
IF @UserDepartmentId = 6
SET @HasFullAccess = 1;
-- ── 1. Full department list — unaffected by any filter ────────────── -- ── 1. Full department list — unaffected by any filter ──────────────
SELECT DISTINCT D.Department SELECT DISTINCT D.Department
@ -61,26 +49,38 @@ BEGIN
, ICAT.ItemCategoryName , ICAT.ItemCategoryName
, RRD.RemainingQty , RRD.RemainingQty
, ITD.CreatedDate , ITD.CreatedDate
,COALESCE(PC.ProjectCode,'N/A') ProjectCode ,COALESCE(PCD.ProjectCode,'N/A') ProjectCode
INTO #Inventory INTO #Inventory
FROM dbo.Inventory IV FROM dbo.Inventory IV
INNER JOIN dbo.InventTrans IT ON IV.InventoryId = IT.InventoryId INNER JOIN dbo.InventTrans IT
INNER JOIN dbo.InventTransDetail ITD ON IT.InventTransId = ITD.InventTransId ON IV.InventoryId = IT.InventoryId
INNER JOIN dbo.PRDetails PRD ON ITD.PRDetailId = PRD.PRDetailsId AND PRD.IsActive = 1 INNER JOIN dbo.InventTransDetail ITD
INNER JOIN dbo.PR ON PR.PRId=PRD.PRId AND PR.IsActive = 1 ON IT.InventTransId = ITD.InventTransId
INNER JOIN dbo.RRDetails RRD ON PRD.PRDetailsId = RRD.PRDetailId AND RRD.IsActive = 1 INNER JOIN dbo.PRDetails PRD
INNER JOIN dbo.ItemCategories ICAT ON PRD.ItemCategoryId = ICAT.ItemCategoryId ON ITD.PRDetailId = PRD.PRDetailsId
LEFT JOIN dbo.Lot L ON IV.LotId = L.LotId AND PRD.IsActive = 1
LEFT JOIN dbo.LotType LT ON L.LotTypeId = LT.LotTypeId INNER JOIN dbo.RRDetails RRD
LEFT JOIN dbo.ProjectCodes PC ON PR.ProjectCodeId = PC.ProjectCodeId ON PRD.PRDetailsId = RRD.PRDetailId
INNER JOIN dbo.Users U ON IV.UserId = U.Id AND RRD.IsActive = 1
INNER JOIN dbo.Departments D ON U.DepartmentId = D.DepartmentId INNER JOIN dbo.ItemCategories ICAT
WHERE ITD.TransTypeId = 2 AND IV.IsActive = 1 AND ITD.IsActive = 1 ON PRD.ItemCategoryId = ICAT.ItemCategoryId
AND ( INNER JOIN dbo.Lot L
@HasFullAccess = 1 ON IV.LotId = L.LotId
OR D.DepartmentId = @UserDepartmentId INNER JOIN dbo.LotType LT
) ON L.LotTypeId = LT.LotTypeId
AND (@SearchPRNo = '' OR PR.PRNo = @SearchPRNo) INNER JOIN dbo.PR PR
ON PR.UserId = IV.UserId
AND PR.IsActive = 1
INNER JOIN dbo.ProjectCodes PC
ON PR.ProjectCodeId = PC.ProjectCodeId
INNER JOIN dbo.Users U
ON IV.UserId = U.Id
INNER JOIN dbo.Departments D
ON U.DepartmentId = D.DepartmentId
INNER JOIN dbo.ProjectCodes PCD
ON PR.ProjectCodeId = PCD.ProjectCodeId
WHERE ITD.TransTypeId=2 AND IV.IsActive=1 AND ITD.IsActive=1 AND
(@SearchPRNo = '' OR PR.PRNo = @SearchPRNo)
AND (@SearchItemNo = '' OR PRD.ItemNo = @SearchItemNo) AND (@SearchItemNo = '' OR PRD.ItemNo = @SearchItemNo)
AND (@SearchItemName = '' OR PRD.ItemName LIKE '%' + @SearchItemName + '%') AND (@SearchItemName = '' OR PRD.ItemName LIKE '%' + @SearchItemName + '%')
AND (@SearchDept = '' OR D.Department LIKE '%' + @SearchDept + '%') AND (@SearchDept = '' OR D.Department LIKE '%' + @SearchDept + '%')
@ -100,7 +100,7 @@ BEGIN
, ICAT.ItemCategoryName , ICAT.ItemCategoryName
, RRD.RemainingQty , RRD.RemainingQty
, ITD.CreatedDate , ITD.CreatedDate
,PC.ProjectCode; ,PCD.ProjectCode;
-- ── 3. Total count of filtered results ────────────────────────────── -- ── 3. Total count of filtered results ──────────────────────────────
SELECT COUNT(*) AS TotalCount SELECT COUNT(*) AS TotalCount

View File

@ -16,7 +16,7 @@ CREATE TABLE [dbo].[RIS] (
[RISNo] VARCHAR(50) NOT NULL, -- generated slip number [RISNo] VARCHAR(50) NOT NULL, -- generated slip number
[InventoryId] INT NOT NULL, [InventoryId] INT NOT NULL,
[PRDetailId] BIGINT NOT NULL, [PRDetailId] BIGINT NOT NULL,
[ProjectCodeId] INT NOT NULL, -- UserId receiving items [IssuedTo] VARCHAR(450) NOT NULL, -- UserId receiving items
[DisciplineId] TINYINT NOT NULL, -- Trade/Matrix/Structural/Architectural [DisciplineId] TINYINT NOT NULL, -- Trade/Matrix/Structural/Architectural
[QtyIssued] DECIMAL(14,2) NOT NULL, [QtyIssued] DECIMAL(14,2) NOT NULL,
[Remarks] VARCHAR(500) NULL, [Remarks] VARCHAR(500) NULL,
@ -30,8 +30,7 @@ CREATE TABLE [dbo].[RIS] (
Reason VARCHAR(150) NULL, Reason VARCHAR(150) NULL,
FOREIGN KEY ([InventoryId]) REFERENCES [Inventory]([InventoryId]), FOREIGN KEY ([InventoryId]) REFERENCES [Inventory]([InventoryId]),
FOREIGN KEY ([PRDetailId]) REFERENCES [PRDetails]([PRDetailsId]), FOREIGN KEY ([PRDetailId]) REFERENCES [PRDetails]([PRDetailsId]),
FOREIGN KEY ([DisciplineId]) REFERENCES [Disciplines]([DisciplineId]), FOREIGN KEY ([DisciplineId]) REFERENCES [Disciplines]([DisciplineId])
FOREIGN KEY ([ProjectCodeId]) REFERENCES ProjectCodes([ProjectCodeId])
); );
-- ── MRS: Material Return Slip ───────────────────────────────────── -- ── MRS: Material Return Slip ─────────────────────────────────────

View File

@ -0,0 +1,56 @@
{
"JWT": {
"ValidAudience": "https://lloydwebapi.lloydlab.com:2021",
"ValidIssuer": "https://lloydwebapi.lloydlab.com:2021",
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xasd707"
},
"Tavily": {
"ApiKey": "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",
"SearchUrl": "https://api.tavily.com/search"
},
"Groq": {
"ApiKey": "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",
"ApiUrl": "https://api.groq.com/openai/v1/chat/completions",
"Model": "llama-3.1-8b-instant"
},
"WebEndPoint": {
"ForgotPassword": "https://llipurchasingnoninventory.com:8080/",
"SupplierForm": "https://llipurchasingnoninventory.com:8083/"
},
"ConnectionStrings": {
"DefaultConnection": "Server=212.47.72.54;Database=CPRNIMS;User Id=LRMS26;Password=P@ssw0rd26;Encrypt=False;",
"LocalPurchConn": "Server=DESKTOP-RQGHQQN;Database=PurchasingSystem;User Id=LRMS25;Password=P@ssw0rd26;Encrypt=False;"
},
"SMTP": {
"DisplayName": "no-reply-cwms@lloydlab.com",
"ToReceiver": "NA",
"OutgoingPort": "587",
"IncomingPort": "110",
"SenderEmail": "lli.mis2025@gmail.com",
"Password": "vcwq nesk rsqb zxbf",
"Server": "smtp.gmail.com",
"SenderName": "CWMS",
"UserName": "lli.mis2025@gmail.com",
"CC": "rmsoriano@lloydlab.com;",
"PurchasingCC": ";rmsoriano@lloydlab.com;iigajasan@lloydlab.com;laoreo@lloydlab.com;avaustria@lloydlab.com;hdbautista@lloydlab.com;pur_canvasser2@lloydlab.com;pur_canvasser4@lloydlab.com;purchasing@lloydlab.com;jmmaulawin@lloydlab.com"
},
"Canvass": {
"CC": "iigajasan@lloydlab.com;rmsoriano@lloydlab.com;laoreo@lloydlab.com;avaustria@lloydlab.com;hdbautista@lloydlab.com;pur_canvasser2@lloydlab.com;pur_canvasser4@lloydlab.com;purchasing@lloydlab.com;jmmaulawin@lloydlab.com",
"EmailSettings": {
"ExcludedEmails": [
"jmcariaga@lloydlab.com",
"projctrl@lloydlab.com",
"test@test.com",
"admin@internal.com"
]
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

Some files were not shown because too many files have changed in this diff Show More