Compare commits

..

36 Commits

Author SHA1 Message Date
rowell_m_soriano
227ebe3906 adding variables via gitea variables
All checks were successful
Build and Deploy CPRNIMS / build-and-deploy (push) Successful in 3m36s
2026-06-29 16:21:34 +08:00
rowell_m_soriano
6b28e00102 fix: explicit exit 0 after robocopy success to prevent false step failures
All checks were successful
Build and Deploy CPRNIMS / build-and-deploy (push) Successful in 2m58s
2026-06-29 15:40:02 +08:00
rowell_m_soriano
34097298e0 Update Gitea CI/CD deployment workflow
Some checks failed
Build and Deploy CPRNIMS / build-and-deploy (push) Failing after 2m32s
2026-06-29 14:29:55 +08:00
rowell_m_soriano
2aa375cf55 Update Gitea CI/CD deployment workflow
Some checks are pending
Build and Deploy CPRNIMS / build-and-deploy (push) Waiting to run
2026-06-29 14:04:46 +08:00
rowell_m_soriano
d6c2d668ee Update Gitea CI/CD deployment workflow
Some checks are pending
Build and Deploy CPRNIMS / build-and-deploy (push) Waiting to run
2026-06-29 13:51:54 +08:00
rowell_m_soriano
8fdbe48640 Remove bin/obj/.vs build artifacts from tracking, apply .gitignore
Some checks are pending
Build and Deploy CPRNIMS / build-and-deploy (push) Waiting to run
2026-06-29 07:03:51 +08:00
rowell_m_soriano
12407aeaf5 Remove bin/obj/.vs build artifacts from tracking, apply .gitignore 2026-06-25 17:26:55 +08:00
rowell_m_soriano
84ba85490c Add .gitignore, remove build artifacts from tracking 2026-06-25 17:15:47 +08:00
rowell_m_soriano
c9fc25832f Add .gitignore and remove build artifacts from tracking 2026-06-25 16:43:25 +08:00
rowell_m_soriano
3d82fb67ba CICD deploy.yml 2026-06-25 16:05:33 +08:00
rowell_m_soriano
3c0be5eae2 CRUD for RIS, MRS, Inventory reports are working properly 2026-06-25 08:57:30 +08:00
rowell_m_soriano
440cdfcdb7 Features for option to select currency for each PO during PO Creation 2026-06-24 10:16:45 +08:00
rowell_m_soriano
fa03ef5a3d Full CRUD with RIS, MRS, Inventory including reports 2026-06-18 16:51:31 +08:00
rowell_m_soriano
44862d01b5 RIS creation, approval and Cancel working well 2026-06-15 16:41:50 +08:00
rowell_m_soriano
6710f04bd7 fixing bugs in custom po for unit price consistency 2026-05-21 13:55:15 +08:00
rowell_m_soriano
f2aee9645d Enhanced Shipping instructions and Custom PO for import 2026-05-20 16:50:48 +08:00
rowell_m_soriano
5c6fc08bf3 Roll back the Shipping instruction 2026-05-12 15:48:42 +08:00
rowell_m_soriano
67a501f4fc Fixing status bug in Supplier page 2026-05-05 13:03:52 +08:00
rowell_m_soriano
b02af975ac Adding validaiton for existing suppliers to prevent from duplication 2026-04-27 09:18:38 +08:00
rowell_m_soriano
d1c9c4b52b AI Driven Searching and tagging with button and UI/UX enhancement in canvassing partial only 2026-04-22 17:21:45 +08:00
rowell_m_soriano
3825a986f6 AI-Driven Supplier Search & Tagging 2026-04-21 11:59:21 +08:00
rowell_m_soriano
ee0f853a85 Fixing Qty submission in Item Cart and adding Item no searching in item management 2026-03-17 07:11:17 +08:00
rowell_m_soriano
a188699c56 UI/UX Enhancement 2026-03-13 14:48:15 +08:00
rowell_m_soriano
d770613286 Backend pagination for Item, Pr Tracking, approved pr, Deleted PR 2026-03-12 16:03:02 +08:00
rowell_m_soriano
1b06999f15 fixing bugs on custom PO 2026-03-11 14:26:41 +08:00
rowell_m_soriano
199c1271a0 Item removal enhancement on receiving page 2026-03-05 12:16:05 +08:00
rowell_m_soriano
d23347c299 PR item addition in existing PRNo 2026-03-02 12:25:08 +08:00
rowell_m_soriano
84bcc7aaa7 Custom PO working already all features 2026-02-27 10:29:27 +08:00
rowell_m_soriano
798f8f67ea minor issue for custom PO but working already, need to change the incormterms into autocomplete 2026-02-24 17:08:04 +08:00
rowell_m_soriano
da0af6a64e Partial for custom PO 2026-02-19 17:23:28 +08:00
rowell_m_soriano
11646fec68 PR Tabbed for Approved but no PO, Deleted items are working properly 2026-02-17 17:05:52 +08:00
rowell_m_soriano
99be1e9c8b fixing approval and returning approval name 2026-02-16 16:37:20 +08:00
rowell_m_soriano
9419130ee3 approval and project code maintenance is working properly 2026-02-16 09:18:27 +08:00
rowell_m_soriano
6e0551707e push only for upload attachment and project code but not working the autocomplete yet 2026-02-13 15:56:56 +08:00
rowell_m_soriano
0612679648 Project code maintenance and pr item attachment 2026-02-12 10:41:44 +08:00
rowell_m_soriano
33b839741f Multiple pr item approval 2026-02-10 14:19:30 +08:00
392 changed files with 36536 additions and 12772 deletions

211
.gitea/workflows/deploy.yml Normal file
View File

@ -0,0 +1,211 @@
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 Normal file
View File

@ -0,0 +1,48 @@
# 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

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

View File

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

View File

@ -7,7 +7,12 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<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="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,6 +1,12 @@
using CPRNIMS.Infrastructure.Dto.Canvass; using CPRNIMS.Domain.Services;
using CPRNIMS.Domain.Services.ICanvass;
using CPRNIMS.Infrastructure.Dto.Canvass;
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Entities.Canvass; using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.ViewModel.Canvass;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -9,46 +15,47 @@ using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Canvass namespace CPRNIMS.Domain.Contracts.Canvass
{ {
public interface ICanvass public interface ICanvass : ISupplier
{ {
#region Post Put #region Post Put
Task<RFQ> PostPerSupplierToken(CanvassDto CanvassDto); Task<Result<StartCanvassResponse>> StartCanvass(CanvassVM canvass,CancellationToken ct);
Task<RFQ> PostPerSupplierToken(ForCanvassDto CanvassDto);
Task<ForCanvassFollowUp> PutSupplierCanvass(long canvassSupplierId); Task<ForCanvassFollowUp> PutSupplierCanvass(long canvassSupplierId);
Task<PRDetails> PostCanvass(CanvassDto CanvassDto); Task<SupplierResponse> PostPutSupplier(CanvassDto CanvassDto);
Task<Suppliers> PostPutSupplier(CanvassDto CanvassDto); Task<SupplierResponse> PostTaggingSupplier(CanvassDto CanvassDto);
Task<Suppliers> PostTaggingSupplier(CanvassDto CanvassDto); Task<SupplierResponse> PostApprovedSupp(CanvassDto CanvassDto);
Task<Suppliers> PostApprovedSupp(CanvassDto CanvassDto);
Task<CanvassDetail> PostSuggestedSupp(CanvassDto CanvassDto); Task<CanvassDetail> PostSuggestedSupp(CanvassDto CanvassDto);
Task<CanvassDetail> PutSuppUnitPrice(CanvassDto CanvassDto); Task<CanvassDetail> PutSuppUnitPrice(CanvassDto CanvassDto);
Task<CanvassDetail> PutSuppBidDetails(CanvassDto canvassDto); Task<CanvassDetail> PutSuppBidDetails(CanvassDto canvassDto);
Task<Suppliers> PostPutMySupplier(CanvassDto canvassDto); Task<SupplierResponse> PostPutMySupplier(CanvassDto canvassDto);
Task<Suppliers> PostPutItemTagging(CanvassDto canvassDto); Task<SupplierResponse> PostPutItemTagging(CanvassDto canvassDto);
Task<CanvassSupplier> UnlockFormLink(CanvassDto canvassDto); Task<CanvassSupplier> UnlockFormLink(CanvassDto canvassDto);
#endregion #endregion
#region Get #region Get
Task<List<PRDetails>> GetCanvassById(CanvassDto CanvassDto); Task<List<PRCanvassDetail>> GetCanvassById(CanvassDto CanvassDto);
Task<List<WOResponse>> GetCanvassWOResponse(CanvassDto CanvassDto); Task<List<WOResponse>> GetCanvassWOResponse(CanvassDto CanvassDto);
Task<List<WOResponseById>> GetWOResponseBySuppId(CanvassDto CanvassDto); Task<List<WOResponseById>> GetWOResponseBySuppId(CanvassDto CanvassDto);
Task<List<Suppliers>> GetSupplierById(CanvassDto CanvassDto); Task<List<SupplierResponseDto>> GetSupplierById(CanvassDto CanvassDto);
Task<List<RFQReference>> GetRFQ(CanvassDto CanvassDto); Task<List<RFQReference>> GetRFQ(ForCanvassDto CanvassDto);
Task<List<BiddingItem>> GetSupplierBid(CanvassDto CanvassDto); Task<List<BiddingItem>> GetSupplierBid(CanvassDto CanvassDto);
Task<List<RFQPerSupplier>> GetSupplierBidByItem(CanvassDto CanvassDto); Task<List<RFQPerSupplier>> GetSupplierBidByItem(CanvassDto CanvassDto);
Task<List<SupplierBidById>> GetSupplierBidById(CanvassDto CanvassDto); Task<List<SupplierBidById>> GetSupplierBidById(CanvassDto CanvassDto);
Task<List<PerSupplier>> GetCanvassPerSupplier(CanvassDto CanvassDto); Task<PagedResult<PerSupplier>> GetCanvassPerSupplier(CanvassDto dto);
Task<List<PRDetails>> GetCanvassPerSupplierEmail(CanvassDto CanvassDto); Task<PagedResult<ItemsForTagging>> GetItemsForTagging(CanvassDto dto);
Task<List<PRDetails>> GetCanvassPerSupplierId(CanvassDto itemCodeDto); Task<List<PRCanvassDetail>> GetCanvassPerSupplierEmail(CanvassDto CanvassDto);
Task<List<PRCanvassDetail>> GetCanvassPerSupplierId(CanvassDto itemCodeDto);
Task<List<ItemListWOEmail>> GetItemSupplierWOEmail(CanvassDto CanvassDto); Task<List<ItemListWOEmail>> GetItemSupplierWOEmail(CanvassDto CanvassDto);
Task<List<Suppliers>> GetSupplierItemWOEmail(CanvassDto CanvassDto); Task<List<SupplierResponseDto>> GetSupplierItemWOEmail(CanvassDto CanvassDto);
Task<List<PRDetails>> GetCanvassByPRNo(CanvassDto CanvassDto); Task<List<PRCanvassDetail>> GetCanvassByPRNo(CanvassDto CanvassDto);
Task<List<CanvassGroupByPRNo>> GetCanvassGroupByPRNo(CanvassDto CanvassDto); Task<List<CanvassGroupByPRNo>> GetCanvassGroupByPRNo(CanvassDto CanvassDto);
Task<List<PRDetails>> GetCanvassByItemNo(CanvassDto CanvassDto); Task<List<PRCanvassDetail>> GetCanvassByItemNo(CanvassDto CanvassDto);
Task<List<PRDetails>> GetPRItemList(CanvassDto CanvassDto); Task<List<PRCanvassDetail>> GetPRItemList(CanvassDto CanvassDto);
Task<List<PRDetails>> GetPRItem(CanvassDto CanvassDto); Task<List<PRCanvassDetail>> GetPRItem(CanvassDto CanvassDto);
Task<List<Infrastructure.Entities.Canvass.PRList>> GetPRListByPRNo(CanvassDto canvassDto); Task<List<Infrastructure.Entities.Canvass.PRList>> GetPRListByPRNo(CanvassDto canvassDto);
Task<List<ForCanvass>> GetForCanvassPerItem(CanvassDto CanvassDto); Task<List<ForCanvass>> GetForCanvassPerItem(CanvassDto CanvassDto);
Task<int> GetCanvassNo(); Task<int> GetCanvassNo();
Task<List<ForCanvassFollowUp>> GetCanvassForFollowUp(CanvassDto itemDto); Task<List<ForCanvassFollowUp>> GetCanvassForFollowUp(CanvassDto itemDto);
Task<List<Suppliers>> GetMySuppliers(CanvassDto CanvassDto); Task<List<SupplierResponseDto>> GetMySuppliers(CanvassDto CanvassDto);
Task<List<MyPRWOCanvass>> GetMyPRWOCanvass(CanvassDto itemDto); Task<List<MyPRWOCanvass>> GetMyPRWOCanvass(CanvassDto itemDto);
Task<List<AlternativeOfferDetails>> GetAlternativeOfferByPRDetailId(CanvassDto itemDto); Task<List<AlternativeOfferDetails>> GetAlternativeOfferByPRDetailId(CanvassDto itemDto);
Task<List<AllForCanvass>> GetAllForCanvass(); Task<List<AllForCanvass>> GetAllForCanvass();

View File

@ -0,0 +1,23 @@
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Purchasing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services.ICanvass
{
public interface ISupplier
{
Task<List<Suppliers>> GetSuppliers(CancellationToken ct);
Task<List<ForAISearchingTagging>> GetForAISearchingTagging(CancellationToken ct);
Task<List<ItemWithoutSupplier>> GetItemWithoutSupplier(CancellationToken ct);
Task<List<SupplierForCanvass>> GetSupplierForCanvass(int supplierId, string userName,CancellationToken ct);
Task<Result<SupplierResponse>> PostPutSupplierAsync(SupplierRequest request, CancellationToken ct);
Task<bool> SendRFQ(SupplierEmailRequest supplierEmailRequest);
Task DeleteAsync(long pRDetailsId, CancellationToken ct);
}
}

View File

@ -0,0 +1,14 @@
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<RRDetail> PostPutPayment(RRDetailsDto itemDto); Task<RRDetailDto> PostPutPayment(RRDetailsDto itemDto);
} }
} }

View File

@ -1,4 +1,6 @@
using CPRNIMS.Infrastructure.Dto.Inventory; using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Entities.Inventory; using CPRNIMS.Infrastructure.Entities.Inventory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -11,11 +13,15 @@ namespace CPRNIMS.Domain.Contracts.Inventory
public interface IInventory public interface IInventory
{ {
Task<List<Lot>> GetLotNo(InventoryDto itemDto); Task<List<Lot>> GetLotNo(InventoryDto itemDto);
Task<List<Lot>> GetLotNoById(InventoryDto itemDto);// Task<List<Lot>> GetLotNoById(InventoryDto itemDto);
Task<List<LotQtyByItem>> GetLotQtyByItem(InventoryDto itemDto); Task<List<LotQtyByItem>> GetLotQtyByItem(InventoryDto itemDto);
Task<List<Infrastructure.Entities.Inventory.Inventory>> GetInventoryByUserId(InventoryDto itemDto); Task<List<Infrastructure.Entities.Inventory.Inventory>> GetInventoryByUserId(InventoryDto itemDto);
Task<List<RequestItemDetail>> GetRequestedItemByUserId(InventoryDto itemDto); Task<List<RequestItemDetail>> GetRequestedItemByUserId(InventoryDto itemDto);
Task<List<ItemDetail>> GetInventoryById(InventoryDto itemDto); Task<List<ItemDetail>> GetInventoryById(InventoryDto itemDto);
Task<PagedResult<InventoryResponse>> GetInventory(InventoryRequest request, CancellationToken ct);
Task<List<InventoryByIdResponse>> GetInventoryById(InventoryRequest itemDto, CancellationToken ct);
Task<TransactContextDto?> GetTransactContextAsync(int inventoryId, CancellationToken ct);
Task<IReadOnlyList<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

@ -0,0 +1,17 @@
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

@ -0,0 +1,22 @@
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Entities.Inventory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Inventory
{
public interface IMRS
{
Task<MRSPagedResult> GetPagedAsync(MRSFilterDto filter, CancellationToken ct,int? departmentId = null, string? userName = "");
Task<IReadOnlyList<RISSearchResultDto>> SearchRISForReturnAsync(string? risNoQuery, int? projectCodeId, CancellationToken ct);
Task<IReadOnlyList<ProjectCodeOptionDto>> GetProjectsWithOpenRISAsync(string? nameQuery, CancellationToken ct);
Task<MRS?> GetByIdAsync(long mrsId, CancellationToken ct);
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

@ -0,0 +1,22 @@
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Entities.Inventory;
using CPRNIMS.Infrastructure.Entities.Purchasing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Contracts.Inventory
{
public interface IRIS
{
Task<RISPagedResult> GetPagedAsync(RISFilterDto filter, CancellationToken ct, int? departmentId = null, string? userName = "");
Task<RISResponse?> GetByIdAsync(long risId, CancellationToken ct);
Task<Infrastructure.Entities.Inventory.RIS> CreateAsync(CreateRISRequest dto, string createdBy, CancellationToken ct);
Task ApproveAsync(ApproveRISRequest request, string approvedBy, CancellationToken ct);
Task CancelAsync(CancelRISRequest request,string canceledBy, CancellationToken ct);
}
}

View File

@ -2,6 +2,7 @@
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Items; using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Models.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -13,19 +14,22 @@ namespace CPRNIMS.Domain.Contracts.Items
public interface IItem public interface IItem
{ {
Task<List<Departments>> GetDepartment(ItemCodeDto itemCode); Task<List<Departments>> GetDepartment(ItemCodeDto itemCode);
Task<List<ItemList>> GetItemList(ItemCodeDto itemCode); Task<PagedResult<ItemList>> GetItemList(ItemCodeDto itemCode);
Task<List<ItemCart>> GetItemCart(ItemDto itemDto); Task<List<ItemCart>> GetItemCart(ItemDto itemDto);
Task<List<Item>> GetItemDetail(ItemDto itemDto); Task<List<ItemDtos>> 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<long> GetPRNo(); Task<IReadOnlyList<ProjectCodes>> GetProjectCode();
Task<ItemCart> PostPurchRequest(ItemDto itemDto); Task<IReadOnlyList<ProjectCodes>> GetProjectCodeByTerm(string? fileName);
Task<(long, long)> GetPRNo();
Task<ResponseObject> PostPurchRequest(ItemDto itemDto);
Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto); Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto);
Task<Item> PutItemDetail(ItemDto itemDto); Task<Item> PutItemDetail(ItemDto itemDto);
Task<ItemCart> PostPutItemCart(ItemDto itemDto); Task<ItemCart> PostPutItemCart(ItemDto itemDto);
Task<ItemCart> PostPutItemPath(ItemDto itemDto); Task<ItemCart> PostPutItemPath(ItemDto itemDto);
Task PostPutAttachment(AttachmentRequest attach);
} }
} }

View File

@ -1,4 +1,5 @@
using CPRNIMS.Infrastructure.Dto.PO; using CPRNIMS.Infrastructure.Dto.Canvass.Response;
using CPRNIMS.Infrastructure.Dto.PO;
using CPRNIMS.Infrastructure.Entities.Canvass; using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.LocalDb.NonInvent; using CPRNIMS.Infrastructure.Entities.LocalDb.NonInvent;
@ -15,6 +16,8 @@ namespace CPRNIMS.Domain.Contracts.PO
public interface IPurchaseOrder public interface IPurchaseOrder
{ {
#region Get #region Get
Task<POFormData> GetPOFormDataAsync(long? poId);
Task<List<Infrastructure.Entities.PO.PO>> GetPOListByTerm(PODto itemDto);
Task<List<IncomingShipmentDto>> GetIncomingShipment(PODto itemDto); Task<List<IncomingShipmentDto>> GetIncomingShipment(PODto itemDto);
Task<List<IndexCard>> GetIndexCard(PODto poDto); Task<List<IndexCard>> GetIndexCard(PODto poDto);
Task<List<PurchaseOrder>> GetForPOApprovalByPRNo(PODto PODto); Task<List<PurchaseOrder>> GetForPOApprovalByPRNo(PODto PODto);
@ -35,11 +38,12 @@ namespace CPRNIMS.Domain.Contracts.PO
Task<List<SystemSettings>> GetLatestPO2(PODto pODto); Task<List<SystemSettings>> GetLatestPO2(PODto pODto);
Task<List<DocRequired>> GetDocRequired(PODto pODto); Task<List<DocRequired>> GetDocRequired(PODto pODto);
Task<List<OtherCharges>> GetOtherCharges(PODto itemDto); Task<List<OtherCharges>> GetOtherCharges(PODto itemDto);
Task<List<Suppliers>> GetSuppliers(PODto itemDto); Task<List<SupplierResponseDto>> GetSuppliers(PODto itemDto);
Task<List<CreatedPO>> GetCreatedPO(PODto pODto); Task<List<CreatedPO>> GetCreatedPO(PODto pODto);
Task<List<POItemDetail>> GetPOItemDetail(PODto pODto); Task<List<POItemDetail>> GetPOItemDetail(PODto pODto);
Task<List<CreatedPO>> GetMyCreatedPO(PODto pODto); Task<List<CreatedPO>> GetMyCreatedPO(PODto pODto);
Task<List<Incoterm>> GetIncoterms(PODto itemDto); Task<List<Incoterm>> GetIncoterms(PODto itemDto);
Task<List<Incoterm>> GetIncotermsByName(PODto itemDto);
Task<List<PRPOSummaryCount>> GetPRPOSummaryReport(PODto itemDto); Task<List<PRPOSummaryCount>> GetPRPOSummaryReport(PODto itemDto);
Task<List<PRPOSummaryItem>> GetPRPOSummaryItem(PODto itemDto); Task<List<PRPOSummaryItem>> GetPRPOSummaryItem(PODto itemDto);
PODto CreatePoDto(POVM PODto, byte docRequirementId, int otherChargesId, long prDetailsId PODto CreatePoDto(POVM PODto, byte docRequirementId, int otherChargesId, long prDetailsId
@ -52,6 +56,7 @@ namespace CPRNIMS.Domain.Contracts.PO
Task<PurchaseOrder> PostPutPO(PODto PODto); Task<PurchaseOrder> PostPutPO(PODto PODto);
Task<OtherCharges> PostSuppCharges(PODto poDto); Task<OtherCharges> PostSuppCharges(PODto poDto);
Task<CustomPO> PostPutCustomPO(PODto pODto); Task<CustomPO> PostPutCustomPO(PODto pODto);
Task<CustomPO> PutExistingPO(PODto pODto);
Task<DocRequired>PostSuppDocRequirements(PODto poDto); Task<DocRequired>PostSuppDocRequirements(PODto poDto);
Task<PurchaseOrder> PostPOToSupplier(PODto PODto); Task<PurchaseOrder> PostPOToSupplier(PODto PODto);
Task<Suppliers> PostApprovedSupplier(PODto PODto); Task<Suppliers> PostApprovedSupplier(PODto PODto);
@ -65,6 +70,7 @@ 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

@ -1,7 +1,10 @@
using CPRNIMS.Infrastructure.Dto.PR; using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.Infrastructure.Dto.PR.Response;
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Entities.SMTP; using CPRNIMS.Infrastructure.Entities.SMTP;
using CPRNIMS.Infrastructure.Models.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -18,22 +21,29 @@ namespace CPRNIMS.Domain.Contracts.PR
Task<List<ForReceiving>> GetForReceiving(PRDto PRDto); Task<List<ForReceiving>> GetForReceiving(PRDto PRDto);
Task<List<Dashboard>> GetDashBoard(PRDto PRDto); Task<List<Dashboard>> GetDashBoard(PRDto PRDto);
Task<List<ItemApproval>> GetMyPR(PRDto PRDto); Task<List<ItemApproval>> GetMyPR(PRDto PRDto);
Task<List<PRList>> GetAllPR(PRDto PRDto); Task<PagedResult<DetailedPRTracking>> GetDetailedPRTracking(PRDto PRDto);
Task<PagedResult<Infrastructure.Entities.Purchasing.PRList>> GetAllPR(PRDto PRDto);
Task<PagedResult<Infrastructure.Entities.Purchasing.PRList>> GetPRArchived(PRDto pRDto);
Task<List<Infrastructure.Entities.Canvass.PRList>> GetPRListByPRNo(PRDto PRDto); Task<List<Infrastructure.Entities.Canvass.PRList>> GetPRListByPRNo(PRDto PRDto);
Task<List<NotifUserKey>> GetNotifUserKey(PRDto PRDto); Task<List<NotifUserKey>> GetNotifUserKey(PRDto PRDto);
Task<List<PRDetails>> GetPRDetailByPRNo(PRDto PRDto); Task<List<PRItemList>> GetPRDetailByPRNo(PRDto PRDto);
Task<List<PRTracking>> GetPRStatusById(PRDto PRDto); Task<List<PRTracking>> GetPRStatusById(PRDto PRDto);
Task<List<RRReport>> GetDetailedPRTracking(PRDto PRDto);
Task<List<AlternativeOffer>> GetSupplierAlternativeOffer(PRDto PRDto); Task<List<AlternativeOffer>> GetSupplierAlternativeOffer(PRDto PRDto);
Task<List<AlternativeOfferDetails>> GetSupplierAlterOfferDetails(PRDto PRDto); Task<List<AlternativeOfferDetails>> GetSupplierAlterOfferDetails(PRDto PRDto);
Task<List<NotificationById>> GetNotificationById(PRDto PRDto); Task<List<NotificationById>> GetNotificationById(PRDto PRDto);
Task<List<PRDto>> GetApproverName(PRDto PRDto); Task<List<PRDto>> GetApproverName(PRDto PRDto);
Task<List<PRDto>> GetApproverNameByPRNo(PRDto PRDto);
Task<List<ProjectCodes>> GetProjectCodes(PRDto pRDto);
Task<PagedResult<DeletedPR>> GetDeletedPR(PRDto pRDto);
Task<PagedResult<ApprovedPR>> GetApprovedPR(PRDto pRDto);
Task<MessageResponse> PRItemRemoval(PRDto pRDto); Task<MessageResponse> PRItemRemoval(PRDto pRDto);
Task<PRDetails> PostPRApproveReject(PRDto PRDto); Task<PRResponse> PostPRApproveReject(PRDto PRDto);
Task<PRDetails> PostPutReceiving(PRDto PRDto); Task<PRResponse> PostPutReceiving(PRDto PRDto);
Task<PRDetails> PutPOClose(PRDto PRDto); Task<PRResponse> PutPOClose(PRDto PRDto);
Task<PRDetails> PutItemDetail(PRDto PRDto); Task<PRResponse> PutItemDetail(PRDto PRDto);
Task<PRDetails> PostPutDeniedItem(PRDto PRDto); Task<PRResponse> PostPutDeniedItem(PRDto PRDto);
Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto); Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto);
Task<ResponseObject> PostPutProjectCode(PRDto prDto);
Task<ResponseObject> PostItemInPR(PRDto dto);
} }
} }

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<RRDetail>> GetRRDetail(ItemDto itemDto); Task<List<RRDetailDto>> 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

@ -0,0 +1,16 @@
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

@ -0,0 +1,16 @@
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

@ -0,0 +1,24 @@
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CPRNIMS.Infrastructure.Entities.Canvass;
namespace CPRNIMS.Domain.Profile.Canvass
{
public class SupplierRequestProfile : AutoMapper.Profile
{
public SupplierRequestProfile()
{
CreateMap<SupplierRequest, Suppliers>();
CreateMap<Suppliers, SupplierResponse>();
CreateMap<SupplierResponse, SupplierRequest>().ReverseMap();
CreateMap<StartCanvassRequest, ForAISearchingTagging>();
CreateMap<ForAISearchingTagging, StartCanvassResponse>().ReverseMap();
}
}
}

View File

@ -57,6 +57,7 @@ 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

@ -26,44 +26,36 @@ namespace CPRNIMS.Domain.Services.Account
} }
public async Task<List<object>> GetAllUsersProfile() public async Task<List<object>> GetAllUsersProfile()
{ {
try var usersWithRolesAndAttachments = await (from user in _userManager.Users
{ join userRole in _dbContext.IdentityUserRoles on user.Id equals userRole.UserId into userRoles
var usersWithRolesAndAttachments = await (from user in _userManager.Users from ur in userRoles.DefaultIfEmpty()
join userRole in _dbContext.IdentityUserRoles on user.Id equals userRole.UserId into userRoles join role in _dbContext.Roles on ur.RoleId equals role.Id into roles
from ur in userRoles.DefaultIfEmpty() from r in roles.DefaultIfEmpty()
join role in _dbContext.Roles on ur.RoleId equals role.Id into roles join attachment in _dbContext.Attachments on user.Id equals attachment.AttachmentId into attachments
from r in roles.DefaultIfEmpty() from a in attachments.DefaultIfEmpty()
join attachment in _dbContext.Attachments on user.Id equals attachment.AttachmentId into attachments select new
from a in attachments.DefaultIfEmpty() {
select new user.Id,
{ Role = r != null ? r.Name ?? "N/A" : "N/A",
user.Id, URL = a != null ? a.URL ?? "404userImage" : "404userImage",
Role = r != null ? r.Name ?? "N/A" : "N/A", FileName = a != null ? a.FileName ?? "404userImage.jpg" : "404userImage.jpg",
URL = a != null ? a.URL ?? "N/A" : "N/A", user.Company,
FileName = a != null ? a.FileName ?? "N/A" : "N/A", user.DepartmentId,
user.Company, user.UserName,
user.DepartmentId, user.FullName,
user.UserName, user.Email,
user.FullName, user.EmailConfirmed,
user.Email, Address = user.Address ?? "N/A",
user.EmailConfirmed, PhoneNumber = user.PhoneNumber ?? "N/A",
Address = user.Address ?? "N/A", user.LockoutEnd,
PhoneNumber = user.PhoneNumber ?? "N/A", user.LockoutEnabled,
user.LockoutEnd, user.CreatedBy,
user.LockoutEnabled, user.UpdatedBy,
user.CreatedBy, user.CreatedDate,
user.UpdatedBy, user.UpdatedDate
user.CreatedDate, }).ToListAsync();
user.UpdatedDate
}).ToListAsync();
return usersWithRolesAndAttachments.Cast<object>().ToList(); return usersWithRolesAndAttachments.Cast<object>().ToList();
}
catch (Exception ex)
{
ex.ToString();
throw;
}
} }
public async Task AssignUserRole(RegisterModel registerModel) public async Task AssignUserRole(RegisterModel registerModel)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,453 @@
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
using CPRNIMS.Infrastructure.Dto.Canvass.Result;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services.Canvass
{
public class SupplierSearchService
{
private readonly HttpClient _httpClient;
private readonly IConfiguration _config;
// Common contact page suffixes to try
private static readonly string[] ContactPaths =
{ "/contact", "/contact-us", "/pages/contact-us", "/about/contact", "/about" };
/// <summary>
/// Uses Groq to fuzzy-match a new supplier against existing ones.
/// Handles rebranding, spacing in phone numbers, name variations, etc.
/// Returns the matched existing SupplierId, or null if no match.
/// </summary>
public async Task<int?> FindMatchingExistingSupplierAsync(
SupplierResponse incoming,
List<SupplierResponse> existingSuppliers)
{
if (!existingSuppliers.Any()) return null;
// ── Layer 1: Exact C# match (fast, free, no API call) ──────────────
var incomingEmail = (incoming.EmailAddress ?? "").Trim().ToLower();
var incomingPhone = NormalizePhone(incoming.ContactNo ?? "");
var incomingDomain = ExtractDomain(incoming.Website ?? "");
foreach (var s in existingSuppliers)
{
var existEmail = (s.EmailAddress ?? "").Trim().ToLower();
var existPhone = NormalizePhone(s.ContactNo ?? "");
var existDomain = ExtractDomain(s.Website ?? "");
if (!string.IsNullOrEmpty(incomingEmail) && incomingEmail == existEmail)
return s.SupplierId;
if (!string.IsNullOrEmpty(incomingPhone) && incomingPhone == existPhone)
return s.SupplierId;
if (!string.IsNullOrEmpty(incomingDomain) && incomingDomain == existDomain)
return s.SupplierId;
}
// ── Layer 2: Fuzzy C# pre-filter — narrow to top candidates ────────
var incomingName = (incoming.SupplierName ?? "").ToLower();
var candidates = existingSuppliers
.Where(s =>
{
var name = (s.SupplierName ?? "").ToLower();
// Keep if first word matches (e.g. "Linde" in "Linde PH" vs "Linde Philippines")
var incomingFirstWord = incomingName.Split(' ').FirstOrDefault() ?? "";
var existFirstWord = name.Split(' ').FirstOrDefault() ?? "";
return !string.IsNullOrEmpty(incomingFirstWord)
&& incomingFirstWord.Length > 2 // ignore short words like "co", "ph"
&& existFirstWord.StartsWith(incomingFirstWord, StringComparison.OrdinalIgnoreCase);
})
.Take(5) // max 5 candidates to Groq — well within token limit
.Select(s => new
{
s.SupplierId,
s.SupplierName,
s.EmailAddress,
s.ContactNo,
s.Website
})
.ToList();
// No fuzzy candidates found — it's a new supplier
if (!candidates.Any()) return null;
// ── Layer 3: Groq fuzzy match — only on small candidate list ────────
var incomingJson = JsonSerializer.Serialize(new
{
incoming.SupplierName,
incoming.EmailAddress,
incoming.ContactNo,
incoming.Website
});
var candidatesJson = JsonSerializer.Serialize(candidates);
var prompt =
"TASK: Determine if the INCOMING supplier already exists in the CANDIDATES list.\n\n" +
"MATCHING RULES (any one is enough):\n" +
"1. Same email address (case-insensitive).\n" +
"2. Same phone number after stripping spaces, dashes, country codes.\n" +
"3. Same company despite rebranding, abbreviation, or spacing differences.\n" +
"4. Same website domain (ignore www, http/https).\n\n" +
"If matched: respond ONLY { \"matched\": true, \"supplierId\": <number> }\n" +
"If not matched: respond ONLY { \"matched\": false, \"supplierId\": null }\n" +
"No explanation. No markdown. JSON only.\n\n" +
$"INCOMING:\n{incomingJson}\n\n" +
$"CANDIDATES:\n{candidatesJson}";
var payload = new
{
model = _config["Groq:Model"] ?? "llama-3.1-8b-instant",
stream = false,
max_tokens = 50,
temperature = 0,
messages = new[]
{
new { role = "system", content = "You are a supplier deduplication engine. Return ONLY valid JSON. No markdown. No explanation." },
new { role = "user", content = prompt }
}
};
var request = new HttpRequestMessage(HttpMethod.Post, _config["Groq:ApiUrl"]);
request.Headers.Add("Authorization", $"Bearer {_config["Groq:ApiKey"]}");
request.Content = new StringContent(
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
var groqResp = JsonSerializer.Deserialize<GroqResponse>(body,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var rawText = groqResp?.Choices?[0]?.Message?.Content ?? string.Empty;
rawText = Regex.Replace(rawText, @"```[a-z]*|```", "").Trim();
var match = JsonSerializer.Deserialize<GroqMatchResult>(rawText,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
return match?.Matched == true ? match.SupplierId : null;
}
public SupplierSearchService(HttpClient httpClient, IConfiguration config)
{
_httpClient = httpClient;
_config = config;
}
public async Task<List<SupplierResponse>> SearchAndFilterSuppliersAsync(
string itemName, string itemDescription, bool isInternational)
{
var locality = isInternational
? "all over Asia including Philippines"
: "Philippines";
// Step 1: Tavily — get supplier URLs
var (searchContent, supplierUrls) = await SearchTavilyAsync(itemName, itemDescription, locality);
// Step 2: Fetch contact pages from discovered URLs
var contactContent = await FetchContactPagesAsync(supplierUrls);
// Step 3: Combine search + contact content, send to Groq
var combined = searchContent + " CONTACT_PAGES_DATA: " + contactContent;
var suppliers = await FilterWithGroqAsync(itemName, itemDescription, combined,isInternational);
return suppliers;
}
// ── Tavily ──
private async Task<(string content, List<string> urls)> SearchTavilyAsync(
string itemName, string itemDescription,string locality)
{
try
{
var query = $"{itemName} {itemDescription} suppliers {locality} budget price contact email phone";
var payload = new
{
query,
max_results = 10,
search_depth = "advanced",
include_answer = false
};
var request = new HttpRequestMessage(HttpMethod.Post, _config["Tavily:SearchUrl"]);
request.Headers.Add("Authorization", $"Bearer {_config["Tavily:ApiKey"]}");
request.Content = new StringContent(
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<TavilySearchResult>(body,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var sb = new StringBuilder();
var urls = new List<string>();
int i = 1;
foreach (var r in result?.Results ?? new())
{
// Clean text
var clean = Regex.Replace(r.Content ?? "", @"[^\x20-\x7E]", " ");
clean = Regex.Replace(clean, @"\s{3,}", " ");
if (clean.Length > 300) clean = clean[..300];
sb.Append($"{i}. Title:{r.Title}|URL:{r.Url}|Content:{clean}|");
// Collect base domain URLs for contact page fetching
try
{
var uri = new Uri(r.Url);
var baseUrl = $"{uri.Scheme}://{uri.Host}";
if (!urls.Contains(baseUrl)) urls.Add(baseUrl);
}
catch { }
i++;
}
var fullText = sb.ToString();
if (fullText.Length > 2000) fullText = fullText[..2000];
return (fullText, urls);
}
catch (Exception ex)
{
ex.ToString();
throw;
}
}
// ── Fetch Contact Pages ───
private async Task<string> FetchContactPagesAsync(List<string> baseUrls)
{
var sb = new StringBuilder();
// Limit to top 5 domains to avoid timeout
foreach (var baseUrl in baseUrls.Take(5))
{
foreach (var path in ContactPaths)
{
try
{
var url = baseUrl + path;
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var resp = await _httpClient.GetAsync(url, cts.Token);
if (!resp.IsSuccessStatusCode) continue;
var html = await resp.Content.ReadAsStringAsync();
// Strip HTML tags
var text = Regex.Replace(html, @"<[^>]+>", " ");
text = Regex.Replace(text, @"[^\x20-\x7E]", " ");
text = Regex.Replace(text, @"\s{3,}", " ");
// Extract only lines with contact signals
var contactLines = text.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Where(w => w.Contains("@")
|| Regex.IsMatch(w, @"\+?[\d\-\(\)]{7,}")
|| w.Contains("email")
|| w.Contains("phone")
|| w.Contains("contact")
|| w.Contains("mobile")
|| w.Contains("tel"))
.Take(50);
var contactText = string.Join(" ", contactLines);
if (!string.IsNullOrWhiteSpace(contactText))
{
sb.Append($"[{baseUrl}]: {contactText} | ");
break; // Found contact page for this domain, move to next
}
}
catch { /* timeout or unreachable — skip */ }
}
}
return sb.Length > 2000 ? sb.ToString()[..2000] : sb.ToString();
}
// ── Groq ─────────────────────────────────────────────────────────────────
private async Task<List<SupplierResponse>> FilterWithGroqAsync(
string itemName, string itemDescription, string searchContent, bool isInternational)
{
try
{
var localityRule = isInternational
? "1. Include suppliers from Philippines first, then other Asian countries (e.g. China, Japan, South Korea, Taiwan, India, Singapore).\n"
: "1. STRICT: Include ONLY suppliers based in the Philippines. Exclude ANY supplier from other countries — even if they ship to Philippines. If a supplier's country is not Philippines, skip it entirely.\n";
var prompt =
$"TASK: Extract up to 10 unique suppliers that sell: [{itemName}] — {itemDescription}.\n\n" +
"RULES:\n" +
localityRule +
"2. Prefer budget-friendly suppliers with known pricing.\n" +
"3. DEDUPLICATION (strict): Each entry must have a unique company_name, contact_email, AND phone_number.\n" +
" - If two entries share the same email OR phone number, keep only the first.\n" +
" - If two inferred emails resolve to the same address, keep only one.\n" +
"4. CONTACT EXTRACTION:\n" +
" - Look in the CONTACT_PAGES_DATA section for real emails and phone numbers.\n" +
" - Use exact values found. Do not fabricate contact details.\n" +
" - If no email is found for a domain, infer: sales@domain.com or info@domain.com.\n" +
" - If no phone is found, use null — do not guess.\n" +
"5. estimated_price_usd MUST be a number (e.g. 12.50) or null. NEVER a string.\n" +
"6. Exclude any supplier with no company_name or no contact_email.\n\n" +
"OUTPUT FORMAT:\n" +
"Return ONLY a valid raw JSON array. No markdown. No explanation. No extra text.\n" +
"Each object must have exactly these fields:\n" +
" company_name (string)\n" +
" country (string)\n" +
" phone_number (string | null)\n" +
" contact_email (string | null)\n" +
" website (string | null)\n" +
" estimated_price_usd (number | null)\n" +
" item_specifications (string | null)\n\n" +
$"DATA:\n{searchContent}";
var payload = new
{
model = _config["Groq:Model"] ?? "llama-3.1-8b-instant",
stream = false,
max_tokens = 2048,
temperature = 0.1,
messages = new[]
{
new { role = "system", content = "You are a supplier data extractor. Extract real contact details from provided content. Return ONLY a valid JSON array, no markdown, no explanation." },
new { role = "user", content = prompt }
}
};
var request = new HttpRequestMessage(HttpMethod.Post, _config["Groq:ApiUrl"]);
request.Headers.Add("Authorization", $"Bearer {_config["Groq:ApiKey"]}");
request.Content = new StringContent(
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
var groqResp = JsonSerializer.Deserialize<GroqResponse>(body,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var rawText = groqResp?.Choices?[0]?.Message?.Content ?? string.Empty;
var match = Regex.Match(rawText, @"\[[\s\S]*\]");
if (!match.Success) return new List<SupplierResponse>();
// Add the converter to the shared options
var jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
Converters = { new FlexibleDecimalConverter() }
};
var groqList = JsonSerializer.Deserialize<List<GroqSupplierResult>>(match.Value, jsonOptions)
?? new List<GroqSupplierResult>();
var seenNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var seenEmails = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var seenPhones = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var suppliers = new List<SupplierResponse>();
var allowedCountries = isInternational
? new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Philippines", "China", "Japan", "South Korea", "Taiwan",
"India", "Singapore", "Malaysia", "Thailand", "Vietnam",
"Indonesia", "Hong Kong"
}
: new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Philippines"
};
foreach (var s in groqList)
{
var key = (s.CompanyName ?? "").Trim().ToLower();
var email = (s.ContactEmail ?? "").Trim().ToLower();
var phone = NormalizePhone(s.PhoneNumber ?? "");
// Skip if no company name
if (string.IsNullOrEmpty(key)) continue;
// Skip if no email
if (string.IsNullOrEmpty(email)) continue;
// ✅ Skip if company name, email, OR phone already seen
if (seenNames.Contains(key)) continue;
if (seenEmails.Contains(email)) continue;
if (!string.IsNullOrEmpty(phone) && seenPhones.Contains(phone)) continue;
seenNames.Add(key);
seenEmails.Add(email);
if (!string.IsNullOrEmpty(phone)) seenPhones.Add(phone);
suppliers.Add(new SupplierResponse
{
SupplierName = s.CompanyName,
EmailAddress = s.ContactEmail,
ContactNo = s.PhoneNumber ?? string.Empty,
Address = s.Country ?? string.Empty,
IsActive = true,
VatInc = false,
Currency = "PHP",
CurrencyId = 1,
PaymentTermsId = 1,
PaymentTerms = "30 Days",
LeadTime = "7-14 Days",
TinNo = string.Empty,
ContactPerson = string.Empty,
Website = s.Website ?? string.Empty,
});
if (suppliers.Count >= 10) break;
}
return suppliers;
}
catch (Exception ex)
{
ex.ToString();
throw;
}
}
private static string NormalizePhone(string phone)
{
if (string.IsNullOrWhiteSpace(phone)) return string.Empty;
// Strip everything except digits
var digits = Regex.Replace(phone, @"\D", "");
// Remove leading country code "1" for US/CA numbers (11 digits starting with 1)
if (digits.Length == 11 && digits.StartsWith("1"))
digits = digits[1..];
return digits;
}
private static string ExtractDomain(string url)
{
if (string.IsNullOrWhiteSpace(url)) return string.Empty;
try
{
if (!url.StartsWith("http")) url = "https://" + url;
var host = new Uri(url).Host;
return host.StartsWith("www.") ? host[4..] : host;
}
catch { return string.Empty; }
}
}
}

View File

@ -0,0 +1,49 @@
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

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services
{
public static class ContentTypeHelper
{
public static string GetContentType(string fileName)
{
var extension = Path.GetExtension(fileName).ToLowerInvariant();
return extension switch
{
".pdf" => "application/pdf",
".doc" => "application/msword",
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
".xls" => "application/vnd.ms-excel",
".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".png" => "image/png",
".jpg" or ".jpeg" => "image/jpeg",
".gif" => "image/gif",
".txt" => "text/plain",
_ => "application/octet-stream"
};
}
public static string ValidateFile(string filePath, string uploadsPath)
{
var message = "";
// Security: Prevent directory traversal attacks
var fullPath = Path.GetFullPath(filePath);
if (!fullPath.StartsWith(Path.GetFullPath(uploadsPath)))
{
message = "Invalid file path";
}
if (!System.IO.File.Exists(filePath))
{
message = "File not found";
}
return message;
}
}
}

View File

@ -40,7 +40,7 @@ namespace CPRNIMS.Domain.Services.Finance
return allItems ?? new List<ReceivingDetail>(); return allItems ?? new List<ReceivingDetail>();
} }
public async Task<RRDetail> PostPutPayment(RRDetailsDto itemDto) public async Task<RRDetailDto> 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 RRDetail(); return new RRDetailDto();
} }
} }
} }

View File

@ -1,9 +1,11 @@
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.Items; using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Entities.Finance; 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;
@ -17,69 +19,224 @@ namespace CPRNIMS.Domain.Services.Inventory
public class Inventory : IInventory public class Inventory : IInventory
{ {
private readonly NonInventoryDbContext _dbContext; private readonly NonInventoryDbContext _dbContext;
public Inventory(NonInventoryDbContext dbContext) private readonly UserManager<ApplicationUser> _userManager;
public Inventory(NonInventoryDbContext dbContext, UserManager<ApplicationUser> userManager)
{ {
_dbContext = dbContext; _dbContext = dbContext;
_userManager = userManager;
} }
public async Task<List<Infrastructure.Entities.Inventory.ItemDetail>> GetInventoryById(InventoryDto itemDto) public async Task<TransactContextDto?> GetTransactContextAsync(int inventoryId, CancellationToken ct)
{ {
try var inv = await _dbContext.Inventories
{ .Where(i => i.InventoryId == inventoryId && i.IsActive)
var allItems = await _dbContext.ItemDetails .Select(i => new
.FromSqlRaw($"EXEC GetInventoryById @UserId = '{itemDto.UserId}',@InventoryId = '{itemDto.InventoryId}'")
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Inventory.ItemDetail>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<Infrastructure.Entities.Inventory.Inventory>>
GetInventoryByUserId(InventoryDto itemDto)
{
try
{
if(itemDto.IsSorting == false)
{ {
itemDto.DateFrom=DateTime.Now; i.InventoryId,
itemDto.DateTo = DateTime.Now; i.QtyOnHand,
} i.QtyIn,
var allItems = await _dbContext.Inventories i.QtyOut,
.FromSqlRaw($"EXEC GetInventoryByUserId @UserId,@DateFrom,@DateTo,@IsSorting",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@DateFrom", itemDto.DateFrom),
new SqlParameter("@DateTo", itemDto.DateTo),
new SqlParameter("@IsSorting", itemDto.IsSorting))
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Inventory.Inventory>(); LotNo = i.Lot != null ? i.Lot.LotName : null,
}
catch (SqlException ex) Department = i.User != null && i.User.Department != null
? i.User.Department.Department
: null,
i.ItemNo,
FirstDetail = i.InventTrans
.Where(t => t.IsActive)
.SelectMany(t => t.InventTransDetails)
.Where(d => d.PRDetails != null
&& d.PRDetails.PRs != null
&& d.IsActive)
.Select(d => new
{
d.PRDetails!.ItemName,
PRNo = d.PRDetails.PRs!.PRNo
})
.FirstOrDefault()
})
.FirstOrDefaultAsync(ct);
if (inv == null) return null;
// Computed property QtyAvailableToReturn can't be used in EF Where,
// so filter after projection using a raw expression in the query.
var openRIS = await _dbContext.RIS
.Where(r => r.InventoryId == inventoryId
&& r.Status == 1)
.Select(r => new RISReferenceDto
{
RISId = r.RISId,
RISNo = r.RISNo,
QtyIssued = r.QtyIssued,
TotalReturned = r.MaterialReturns
.Where(m => m.Status != 2)
.Sum(m => (int?)m.QtyReturned) ?? 0,
DisciplineName = r.Discipline.DisciplineName,
CreatedDate = r.CreatedDate
})
// Can't use the computed property here — EF won't translate it
// so we repeat the expression inline
.Where(r => r.QtyIssued - r.TotalReturned > 0)
.OrderByDescending(r => r.CreatedDate)
.ToListAsync(ct);
var disciplines = await GetDisciplinesAsync(ct);
var projectCodes = await GetProjectCodesAsync(ct);
return new TransactContextDto
{ {
ex.ToString(); InventoryId = inv.InventoryId,
throw; ItemName = inv.FirstDetail?.ItemName ?? "—",
PRNo = inv.FirstDetail.PRNo,
ItemNo = inv.ItemNo,
LotNo = inv.LotNo,
Department = inv.Department,
QtyOnHand = inv.QtyOnHand,
QtyIn = inv.QtyIn,
QtyOut = inv.QtyOut,
ProjectCodes = projectCodes,
Disciplines = disciplines,
OpenRISList = openRIS
};
}
public async Task<IReadOnlyList<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct)
{
return await _dbContext.Disciplines
.AsNoTracking()
.OrderBy(d => d.DisciplineName)
.Select(d => new DisciplineDto
{
DisciplineId = d.DisciplineId,
DisciplineName = d.DisciplineName
})
.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)
{
var allItems = await _dbContext.ItemDetails
.FromSqlRaw($"EXEC GetInventoryById @UserId = '{itemDto.UserId}',@InventoryId = '{itemDto.InventoryId}'")
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Inventory.ItemDetail>();
}
public async Task<PagedResult<InventoryResponse>> GetInventory(InventoryRequest request, CancellationToken ct)
{
var parameters = new[]
{
new SqlParameter("@UserId", request.UserId),
new SqlParameter("@SearchPRNo", request.SearchPRNo ?? ""),
new SqlParameter("@SearchItemNo", request.SearchItemNo ?? ""),
new SqlParameter("@SearchItemName", request.SearchItemName ?? ""),
new SqlParameter("@SearchDept", request.SearchDept ?? ""),
new SqlParameter("@SearchProjectCode",request.SearchProjectCode ?? ""),
new SqlParameter("@PageNumber", request.PageNumber),
new SqlParameter("@PageSize", request.PageSize)
};
var departmentList = new List<string>();
int totalCount = 0;
var items = new List<InventoryResponse>();
await using var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync(ct);
using var cmd = conn.CreateCommand();
cmd.CommandText = @"EXEC GetInventory @UserId, @SearchPRNo, @SearchItemNo, @SearchItemName, @SearchDept,@SearchProjectCode, @PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
cmd.CommandTimeout = 60;
using var reader = await cmd.ExecuteReaderAsync(ct);
while (await reader.ReadAsync(ct))
departmentList.Add(reader.GetString(0));
await reader.NextResultAsync(ct);
if (await reader.ReadAsync(ct))
totalCount = reader.GetInt32(0);
await reader.NextResultAsync(ct);
while (await reader.ReadAsync(ct))
{
items.Add(new InventoryResponse
{
InventoryId = reader.GetInt32(reader.GetOrdinal("InventoryId")),
QtyIn = reader["QtyIn"] as decimal? ?? 0,
QtyOut = reader["QtyOut"] as decimal? ?? 0,
QtyOnHand = reader["QtyOnHand"] as decimal? ?? 0,
LotNo = reader["LotNo"]?.ToString(),
PRNo = Convert.ToInt64(reader["PRNo"]),
UserId = reader["UserId"]?.ToString(),
ItemName = reader["ItemName"]?.ToString(),
ItemNo = Convert.ToInt64(reader["ItemNo"]),
ItemDescription = reader["ItemDescription"]?.ToString(),
ItemCategoryName = reader["ItemCategoryName"]?.ToString(),
Department = reader["Department"]?.ToString(),
ProjectCode = reader["ProjectCode"]?.ToString(),
CreatedDate = reader["CreatedDate"] == DBNull.Value
? DateTime.MinValue
: Convert.ToDateTime(reader["CreatedDate"])
});
} }
await conn.CloseAsync();
return new PagedResult<InventoryResponse>
{
Data = items,
TotalCount = totalCount,
PageNumber = request.PageNumber,
PageSize = request.PageSize,
DepartmentList = departmentList
};
}
public async Task<List<InventoryByIdResponse>> GetInventoryById(InventoryRequest itemDto,CancellationToken ct)
{
var allItems = await _dbContext.InventoryByIdResponses
.FromSqlRaw($"EXEC GetInventoryById @InventoryId",
new SqlParameter("@InventoryId", itemDto.InventoryId))
.ToListAsync(ct);
return allItems ?? new List<InventoryByIdResponse>();
}
public async Task<List<Infrastructure.Entities.Inventory.Inventory>>GetInventoryByUserId(InventoryDto itemDto)
{
if (itemDto.IsSorting == false)
{
itemDto.DateFrom = DateTime.Now;
itemDto.DateTo = DateTime.Now;
}
var allItems = await _dbContext.Inventories
.FromSqlRaw($"EXEC GetInventoryByUserId @UserId,@DateFrom,@DateTo,@IsSorting",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@DateFrom", itemDto.DateFrom),
new SqlParameter("@DateTo", itemDto.DateTo),
new SqlParameter("@IsSorting", itemDto.IsSorting))
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Inventory.Inventory>();
} }
public async Task<List<Lot>> GetLotNoById(InventoryDto itemDto) public async Task<List<Lot>> GetLotNoById(InventoryDto itemDto)
{ {
try var allItems = await _dbContext.Lots
{ .FromSqlRaw($"EXEC GetLotById @UserId = '{itemDto.UserId}'")
var allItems = await _dbContext.Lots .ToListAsync();
.FromSqlRaw($"EXEC GetLotById @UserId = '{itemDto.UserId}'")
.ToListAsync();
return allItems ?? new List<Lot>(); return allItems ?? new List<Lot>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<Lot>> GetLotNo(InventoryDto itemDto) public async Task<List<Lot>> GetLotNo(InventoryDto itemDto)
@ -94,125 +251,77 @@ namespace CPRNIMS.Domain.Services.Inventory
public async Task<Lot> PostPutLotNo(InventoryDto itemDto) public async Task<Lot> PostPutLotNo(InventoryDto itemDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync("EXEC PostPutLotNo @UserId, @LotId, @LotTypeId,@LotName",
await _dbContext.Database new SqlParameter("@LotId", itemDto.LotId != null ? itemDto.LotId : 0L),
.ExecuteSqlRawAsync("EXEC PostPutLotNo @UserId, @LotId, @LotTypeId,@LotName", new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@LotId", itemDto.LotId != null ? itemDto.LotId : 0L), new SqlParameter("@LotTypeId", itemDto.LotTypeId),
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@LotName", itemDto.LotName));
new SqlParameter("@LotTypeId", itemDto.LotTypeId), return new Lot();
new SqlParameter("@LotName", itemDto.LotName));
return new Lot();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<Infrastructure.Entities.Inventory.Inventory> PostPutReqApproval(InventoryDto itemDto) public async Task<Infrastructure.Entities.Inventory.Inventory> PostPutReqApproval(InventoryDto itemDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync("EXEC PostPutReqApproval @UserId, @ItemNo, @Status, @Remarks",
await _dbContext.Database new SqlParameter("@ItemNo", itemDto.InventoryId != null ? itemDto.InventoryId : 0L),
.ExecuteSqlRawAsync("EXEC PostPutReqApproval @UserId, @ItemNo, @Status, @Remarks", new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemNo", itemDto.InventoryId != null ? itemDto.InventoryId : 0L), new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@Remarks", itemDto.Remarks ?? "N/A"));
new SqlParameter("@Status", itemDto.Status), return new Infrastructure.Entities.Inventory.Inventory();
new SqlParameter("@Remarks", itemDto.Remarks ?? "N/A"));
return new Infrastructure.Entities.Inventory.Inventory();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<ItemDetail> PostPutLotBin(InventoryDto itemDto) public async Task<ItemDetail> PostPutLotBin(InventoryDto itemDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync("EXEC PostPutLotBin @UserId, @LotId, @InventoryId",
await _dbContext.Database new SqlParameter("@InventoryId", itemDto.InventoryId),
.ExecuteSqlRawAsync("EXEC PostPutLotBin @UserId, @LotId, @InventoryId", new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@InventoryId", itemDto.InventoryId), new SqlParameter("@LotId", itemDto.LotId));
new SqlParameter("@UserId", itemDto.UserId), return new ItemDetail();
new SqlParameter("@LotId", itemDto.LotId));
return new ItemDetail();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<RequestItem> PostPutReqItems(InventoryDto itemDto) public async Task<RequestItem> PostPutReqItems(InventoryDto itemDto)
{ {
try if (itemDto.QtyReceived == null || itemDto.QtyReceived == 0)
{ {
if(itemDto.QtyReceived == null || itemDto.QtyReceived == 0) itemDto.QtyReceived = 0;
{
itemDto.QtyReceived = 0;
}
if(itemDto.LotId == null || itemDto.LotId == 0)
{
itemDto.LotId = 0;
}
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutReqItems @UserId, @RequestItemId, @ItemNo, @QtyRequest,@Status,@IsApproved,@QtyReceived,@LotId",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemNo", itemDto.ItemNo),
new SqlParameter("@RequestItemId", itemDto.RequestItemId != null ? itemDto.RequestItemId : 0L),
new SqlParameter("@QtyRequest", itemDto.QtyRequest),
new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@IsApproved", itemDto.IsApproved),
new SqlParameter("@QtyReceived", itemDto.QtyReceived),
new SqlParameter("@LotId", itemDto.LotId));
return new RequestItem();
} }
catch (SqlException ex) if (itemDto.LotId == null || itemDto.LotId == 0)
{ {
ex.ToString(); itemDto.LotId = 0;
throw;
} }
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutReqItems @UserId, @RequestItemId, @ItemNo, @QtyRequest,@Status,@IsApproved,@QtyReceived,@LotId",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemNo", itemDto.ItemNo),
new SqlParameter("@RequestItemId", itemDto.RequestItemId != null ? itemDto.RequestItemId : 0L),
new SqlParameter("@QtyRequest", itemDto.QtyRequest),
new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@IsApproved", itemDto.IsApproved),
new SqlParameter("@QtyReceived", itemDto.QtyReceived),
new SqlParameter("@LotId", itemDto.LotId));
return new RequestItem();
} }
public async Task<List<RequestItemDetail>> GetRequestedItemByUserId(InventoryDto itemDto) public async Task<List<RequestItemDetail>> GetRequestedItemByUserId(InventoryDto itemDto)
{ {
try var allItems = await _dbContext.RequestItemDetails
{
var allItems = await _dbContext.RequestItemDetails
.FromSqlRaw($"EXEC GetRequestedItemByUserId @UserId = '{itemDto.UserId}', " + .FromSqlRaw($"EXEC GetRequestedItemByUserId @UserId = '{itemDto.UserId}', " +
$"@RequestItemId = '{itemDto.RequestItemId}',@WithoutStocks = '{itemDto.WithoutStocks}'") $"@RequestItemId = '{itemDto.RequestItemId}',@WithoutStocks = '{itemDto.WithoutStocks}'")
.ToListAsync(); .ToListAsync();
return allItems ?? new List<RequestItemDetail>(); return allItems ?? new List<RequestItemDetail>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<LotQtyByItem>> GetLotQtyByItem(InventoryDto itemDto) public async Task<List<LotQtyByItem>> GetLotQtyByItem(InventoryDto itemDto)
{ {
try var allItems = await _dbContext.LotQtyByItems
{ .FromSqlRaw($"EXEC GetLotQtyByItem @UserId = '{itemDto.UserId}', " +
var allItems = await _dbContext.LotQtyByItems $"@ItemNo = '{itemDto.ItemNo}',@LotId = '{itemDto.LotId}'")
.FromSqlRaw($"EXEC GetLotQtyByItem @UserId = '{itemDto.UserId}', " + .ToListAsync();
$"@ItemNo = '{itemDto.ItemNo}',@LotId = '{itemDto.LotId}'")
.ToListAsync();
return allItems ?? new List<LotQtyByItem>(); return allItems ?? new List<LotQtyByItem>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
} }
} }

View File

@ -0,0 +1,307 @@
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

@ -0,0 +1,260 @@
using CPRNIMS.Domain.Contracts.Common;
using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Entities.Inventory;
using Microsoft.EntityFrameworkCore;
namespace CPRNIMS.Domain.Services.Inventory
{
public class MRS : IMRS
{
private readonly NonInventoryDbContext _db;
private readonly ITransactionFacade _transactionFacade;
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.");
// }
//}
var rms = await _db.MRS.FindAsync(mrsId)
?? throw new InvalidOperationException("MRS not found.");
if (rms.Status != 0)
throw new InvalidOperationException("Only Draft MRS records can be approved.");
rms.Status = 1; // Approved
rms.ApprovedBy = approvedBy;
rms.ApprovedDate = DateTime.Now;
await _db.SaveChangesAsync(ct);
}
public async Task CancelAsync(CancelMRSRequest request,string canceledBy, CancellationToken ct)
{
//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
.Include(r => r.Inventory)
.FirstOrDefaultAsync(r => r.RISId == dto.RISId, ct)
?? throw new InvalidOperationException("Referenced RIS not found.");
if (dto.QtyReturned > ris.QtyIssued)
throw new InvalidOperationException(
$"Cannot return more than issued. Issued: {ris.QtyIssued}.");
var mrsNo = await GenerateMRSNoAsync();
var mrs = new Infrastructure.Entities.Inventory.MRS
{
MRSNo = mrsNo,
RISId = dto.RISId,
InventoryId = ris.InventoryId,
ReturnedBy = dto.ReturnedBy,
QtyReturned = dto.QtyReturned,
Condition = dto.Condition,
Remarks = dto.Remarks,
Status = 1,//Matic Approve for now
CreatedBy = createdBy,
CreatedDate = DateTime.Now
};
_db.MRS.Add(mrs);
var inventory = ris.Inventory;
inventory.QtyOut = Math.Max(0m, inventory.QtyOut - dto.QtyReturned);
inventory.QtyOnHand = inventory.QtyIn - inventory.QtyOut;
var trans = await _db.InventTrans
.FirstOrDefaultAsync(t => t.InventoryId == ris.InventoryId && t.IsActive == true, ct)!;
_db.InventTransDetails.Add(new InventTransDetail
{
InventTransId = trans.InventTransId,
TransTypeId = 6,
QtyIn = dto.QtyReturned,
CreatedDate = DateTime.Now,
Remarks = $"MRS: {mrsNo} — return from MRS: {ris.RISNo}",
IsActive = true
});
return mrs;
}, ct);
}
public async Task<Infrastructure.Entities.Inventory.MRS?> GetByIdAsync(long mrsId, CancellationToken ct)
=> await _db.MRS
.Include(r => r.Inventory)
.Include(r => r.RIS)
.FirstOrDefaultAsync(r => r.RISId == mrsId, ct);
public async Task<MRSPagedResult> GetPagedAsync(MRSFilterDto 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.MRS
.Include(m => m.RIS)
.Include(m => m.Inventory)
.AsQueryable();
if (departmentId.HasValue && !seeAllDepartments)
{
q = q.Where(itd =>
itd.Inventory.User.DepartmentId == departmentId.Value);
}
if (!string.IsNullOrWhiteSpace(filter.SearchMRSNo))
q = q.Where(m => m.MRSNo.Contains(filter.SearchMRSNo));
if (filter.RISId.HasValue)
q = q.Where(m => m.RISId == filter.RISId.Value);
if (filter.Status.HasValue)
q = q.Where(m => m.Status == filter.Status.Value);
if (filter.DateFrom.HasValue)
q = q.Where(m => m.CreatedDate >= filter.DateFrom.Value);
if (filter.DateTo.HasValue)
q = q.Where(m => m.CreatedDate <= filter.DateTo.Value.AddDays(1));
var total = await q.CountAsync(ct);
var data = await q
.OrderByDescending(m => m.CreatedDate)
.Skip((filter.PageNumber - 1) * filter.PageSize)
.Take(filter.PageSize)
.Select(m => new MRSPagedDto
{
MRSId = m.MRSId,
MRSNo = m.MRSNo,
RISId = m.RISId,
RISNo = m.RIS.RISNo,
InventoryId = m.InventoryId,
ItemName = m.Inventory.InventTrans
.SelectMany(t => t.InventTransDetails)
.Select(d => d.PRDetails != null ? d.PRDetails.ItemName : "—")
.FirstOrDefault() ?? "—",
ReturnedBy = m.ReturnedBy,
QtyReturned = m.QtyReturned,
Condition = m.Condition,
Remarks = m.Remarks,
Status = m.Status,
CreatedBy = m.CreatedBy,
CreatedDate = m.CreatedDate,
ApprovedBy = m.ApprovedBy,
ApprovedDate = m.ApprovedDate
})
.ToListAsync(ct);
return new MRSPagedResult { Data = data, RecordsTotal = total };
}
private async Task<string> GenerateMRSNoAsync()
{
var year = DateTime.Now.Year;
var month = DateTime.Now.Month.ToString("D2");
var count = await _db.MRS.CountAsync(m => m.CreatedDate.Year == year) + 1;
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

@ -0,0 +1,331 @@
using CPRNIMS.Domain.Contracts.Common;
using CPRNIMS.Domain.Contracts.Inventory;
using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Entities.Inventory;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services.Inventory
{
public class RIS : IRIS
{
private readonly NonInventoryDbContext _db;
private readonly ITransactionFacade _transactionFacade;
public RIS(NonInventoryDbContext db, ITransactionFacade transactionFacade)
{
_db = db;
_transactionFacade = transactionFacade;
}
public async Task<Infrastructure.Entities.Inventory.RIS> CreateAsync(CreateRISRequest dto, string createdBy, CancellationToken ct)
{
return await _transactionFacade.ExecuteAsync(async () =>
{
var inventory = await _db.Inventories
.FirstOrDefaultAsync(i => i.InventoryId == dto.InventoryId, ct)
?? throw new InvalidOperationException("Inventory record not found.");
if (inventory.QtyOnHand < dto.QtyIssued)
throw new InvalidOperationException(
$"Insufficient stock. On hand: {inventory.QtyOnHand}, requested: {dto.QtyIssued}.");
var risNo = await GenerateRISNoAsync(ct);
var ris = new Infrastructure.Entities.Inventory.RIS
{
RISNo = risNo,
InventoryId = dto.InventoryId,
PRDetailId = dto.PRDetailId,
ProjectCodeId = dto.ProjectCodeId,
DisciplineId = dto.DisciplineId,
QtyIssued = dto.QtyIssued,
Remarks = dto.Remarks,
Status = 1,//Approved alredy 0 is Draft
CreatedBy = createdBy,
CreatedDate = DateTime.Now
};
_db.RIS.Add(ris);
var trans = await _db.InventTrans
.Where(t => t.InventoryId == dto.InventoryId && t.IsActive == true)
.FirstOrDefaultAsync(ct)
?? throw new InvalidOperationException(
"No active InventTrans found for this inventory record.");
_db.InventTransDetails.Add(new InventTransDetail
{
InventTransId = trans.InventTransId,
TransTypeId = 5,
PRDetailId = dto.PRDetailId,
QtyOut = dto.QtyIssued,
CreatedDate = DateTime.Now,
Remarks = $"RIS: {risNo}",
IsActive = true
});
inventory.QtyOut = Math.Max(0m, inventory.QtyOut) + dto.QtyIssued;
inventory.QtyOnHand = Math.Max(0m, inventory.QtyIn) - (decimal)inventory.QtyOut;
return ris;
}, 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)
?? throw new InvalidOperationException("RIS not found.");
if (ris.Status != 0)
throw new InvalidOperationException("Only Draft RIS records can be approved.");
ris.Status = 1; // Approved
ris.ApprovedBy = approvedBy;
ris.ApprovedDate = DateTime.Now;
await _db.SaveChangesAsync(ct);
}
public async Task CancelAsync(CancelRISRequest request,string canceledBy, CancellationToken ct)
{
//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 ris = await _db.RIS
.Include(r => r.Inventory)
.FirstOrDefaultAsync(r => r.RISId == request.RISId, ct)
?? throw new InvalidOperationException("RIS not found.");
if (ris.Status == 2)
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.QtyOnHand = ris.Inventory.QtyIn - ris.Inventory.QtyOut;
ris.Reason = request.Reason;
ris.Status = 2; // Cancelled
var trans = await _db.InventTrans
.Where(t => t.InventoryId == ris.InventoryId && t.IsActive == true)
.FirstOrDefaultAsync(ct)
?? throw new InvalidOperationException(
"No active InventTrans found for this inventory record.");
_db.InventTransDetails.Add(new InventTransDetail
{
InventTransId = trans.InventTransId,
TransTypeId = 5,
PRDetailId = ris.PRDetailId,
QtyIn = ris.QtyIssued,//Return the issued Qty
CreatedDate = DateTime.Now,
Remarks = request.Reason,
IsActive = true
});
}, ct);
}
private async Task<string> GenerateRISNoAsync(CancellationToken ct)
{
var year = DateTime.Now.Year;
var month = DateTime.Now.Month.ToString("D2");
var count = await _db.RIS
.CountAsync(r => r.CreatedDate.Year == year,ct) + 1;
return $"RIS-{year}{month}-{count:D4}"; // e.g. RIS-202606-0001
}
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
.Include(r => r.Discipline)
.Include(r => r.Inventory)
.Include(r => r.MaterialReturns)
.AsQueryable();
if (departmentId.HasValue && !seeAllDepartments)
{
q = q.Where(itd =>
itd.Inventory.User.DepartmentId == departmentId.Value);
}
// Status filter (default to Draft=0 if null)
if (filter.Status.HasValue)
q = q.Where(r => r.Status == filter.Status.Value);
//else
// q = q.Where(r => r.Status == 0);
// RIS No
if (!string.IsNullOrWhiteSpace(filter.SearchRISNo))
q = q.Where(r => r.RISNo.Contains(filter.SearchRISNo));
// Item Name
if (!string.IsNullOrWhiteSpace(filter.SearchItemName))
q = q.Where(r => r.Inventory.InventTrans
.SelectMany(t => t.InventTransDetails)
.Any(d => d.PRDetails != null &&
d.PRDetails.ItemName.Contains(filter.SearchItemName)));
// Issued To is Project code/name
if (!string.IsNullOrWhiteSpace(filter.SearchIssuedTo))
q = q.Where(r => r.ProjectCodes.ProjectCode.Contains(filter.SearchIssuedTo)
|| r.ProjectCodes.ProjectName.Contains(filter.SearchIssuedTo));
// Discipline
if (!string.IsNullOrWhiteSpace(filter.Discipline))
q = q.Where(r => r.Discipline.DisciplineName == filter.Discipline);
// Date range (if you ever add date filters)
if (filter.DateFrom.HasValue)
q = q.Where(r => r.CreatedDate >= filter.DateFrom.Value);
if (filter.DateTo.HasValue)
q = q.Where(r => r.CreatedDate <= filter.DateTo.Value.AddDays(1));
var total = await q.CountAsync(ct);
var data = await q
.OrderByDescending(r => r.CreatedDate)
.Skip((filter.PageNumber - 1) * filter.PageSize)
.Take(filter.PageSize)
.Select(r => new RISResponse
{
RISId = r.RISId,
RISNo = r.RISNo,
InventoryId = r.InventoryId,
ItemName = r.Inventory.InventTrans
.SelectMany(t => t.InventTransDetails)
.Select(d => d.PRDetails != null ? d.PRDetails.ItemName : "—")
.FirstOrDefault() ?? "—",
ItemNo = r.Inventory.ItemNo,
LotNo = r.Inventory.Lot != null ? r.Inventory.Lot.LotName : null,
ProjectName = r.ProjectCodes.ProjectName,
ProjectCode = r.ProjectCodes.ProjectCode,
DisciplineName = r.Discipline.DisciplineName,
DisciplineId = r.DisciplineId,
QtyIssued = r.QtyIssued,
Remarks = r.Remarks,
Status = r.Status,
CreatedBy = r.CreatedBy,
CreatedDate = r.CreatedDate,
ApprovedBy = r.ApprovedBy,
ApprovedDate = r.ApprovedDate,
MRSCount = r.MaterialReturns.Count(m => m.Status != 2),
TotalReturned = r.MaterialReturns
.Where(m => m.Status != 2)
.Sum(m => m.QtyReturned)
})
.ToListAsync(ct);
// Full department list (never filtered)
var departments = await _db.Departments
.Select(d => d.Department)
.OrderBy(d => d)
.ToListAsync(ct);
var disciplines = await GetDisciplinesAsync(ct);
return new RISPagedResult
{
Data = data,
RecordsTotal = total,
DepartmentList = departments,
DisciplineList = disciplines
};
}
public async Task<IReadOnlyList<DisciplineDto>> GetDisciplinesAsync(CancellationToken ct)
{
return await _db.Disciplines
.OrderBy(d => d.DisciplineName)
.Select(d => new DisciplineDto
{
DisciplineId = d.DisciplineId,
DisciplineName = d.DisciplineName
})
.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)
{
return await _db.RIS
.Where(r => r.RISId == risId)
.Select(r => new RISResponse
{
RISId = r.RISId,
RISNo = r.RISNo,
InventoryId = r.InventoryId,
ProjectCodeId = r.ProjectCodeId,
DisciplineName = r.Discipline.DisciplineName,
DisciplineId = r.DisciplineId,
QtyIssued = r.QtyIssued,
Remarks = r.Remarks,
Status = r.Status,
CreatedBy = r.CreatedBy,
CreatedDate = r.CreatedDate,
ApprovedBy = r.ApprovedBy,
ApprovedDate = r.ApprovedDate,
MRSCount = r.MaterialReturns.Count(m => m.Status != 2),
TotalReturned = r.MaterialReturns
.Where(m => m.Status != 2)
.Sum(m => m.QtyReturned)
})
.FirstOrDefaultAsync(ct);
}
}
}

View File

@ -1,16 +1,12 @@
using CPRNIMS.Domain.Contracts.Account; using CPRNIMS.Domain.Contracts.Items;
using CPRNIMS.Domain.Contracts.Items;
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Canvass;
using CPRNIMS.Infrastructure.Dto.Items; using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Items; using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Models.Common;
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -26,384 +22,355 @@ namespace CPRNIMS.Domain.Services.Items
} }
public async Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto) public async Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto)
{ {
try var messCodeParam = new SqlParameter("@MessCode", SqlDbType.TinyInt)
{ {
var messCodeParam = new SqlParameter("@MessCode", SqlDbType.TinyInt) Direction = ParameterDirection.Output
{ };
Direction = ParameterDirection.Output var messageParam = new SqlParameter("@Message", SqlDbType.VarChar, 500)
};
var messageParam = new SqlParameter("@Message", SqlDbType.VarChar, 500)
{
Direction = ParameterDirection.Output
};
var itemCodeParam = new SqlParameter("@ItemCode", SqlDbType.BigInt)
{
Direction = ParameterDirection.Output
};
await _dbContext.Database.ExecuteSqlRawAsync(
"EXEC PostPutItem @ItemCodeId, @ItemName, @ItemDescription, @ItemCategoryId, @Status, @UserId, " +
"@ItemCode OUTPUT, @MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@ItemCodeId", itemDto.ItemCodeId != null ? itemDto.ItemCodeId : 0L),
new SqlParameter("@ItemName", itemDto.ItemName ?? (object)DBNull.Value),
new SqlParameter("@ItemDescription", itemDto.ItemDescription ?? (object)DBNull.Value),
new SqlParameter("@ItemCategoryId", itemDto.ItemCategoryId),
new SqlParameter("@Status", itemDto.Status != null ? itemDto.Status : 4),
new SqlParameter("@UserId", itemDto.UserId ?? (object)DBNull.Value),
itemCodeParam,
messCodeParam,
messageParam
);
var messCode = (byte)messCodeParam.Value;
var message = messageParam.Value?.ToString();
var itemCode = itemCodeParam.Value != DBNull.Value ? (long?)itemCodeParam.Value : null;
return new ItemCodeDto
{
ItemCodeId = Convert.ToInt64(itemCode),
ItemName = itemDto.ItemName,
ItemDescription = itemDto.ItemDescription,
ItemCategoryId = itemDto.ItemCategoryId,
Status = itemDto.Status,
UserId = itemDto.UserId
};
}
catch (Exception ex)
{ {
// You could log ex.Message or rethrow with a custom message Direction = ParameterDirection.Output
throw new Exception("An error occurred while executing PostPutItem.", ex); };
} var itemCodeParam = new SqlParameter("@ItemCode", SqlDbType.BigInt)
{
Direction = ParameterDirection.Output
};
await _dbContext.Database.ExecuteSqlRawAsync(
"EXEC PostPutItem @ItemCodeId, @ItemName, @ItemDescription, @ItemCategoryId, @Status, @UserId, " +
"@ItemCode OUTPUT, @MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@ItemCodeId", itemDto.ItemCodeId != null ? itemDto.ItemCodeId : 0L),
new SqlParameter("@ItemName", itemDto.ItemName ?? (object)DBNull.Value),
new SqlParameter("@ItemDescription", itemDto.ItemDescription ?? (object)DBNull.Value),
new SqlParameter("@ItemCategoryId", itemDto.ItemCategoryId),
new SqlParameter("@Status", itemDto.Status != null ? itemDto.Status : 4),
new SqlParameter("@UserId", itemDto.UserId ?? (object)DBNull.Value),
itemCodeParam,
messCodeParam,
messageParam
);
var messCode = (byte)messCodeParam.Value;
var message = messageParam.Value?.ToString();
var itemCode = itemCodeParam.Value != DBNull.Value ? (long?)itemCodeParam.Value : null;
return new ItemCodeDto
{
ItemCodeId = Convert.ToInt64(itemCode),
ItemName = itemDto.ItemName,
ItemDescription = itemDto.ItemDescription,
ItemCategoryId = itemDto.ItemCategoryId,
Status = itemDto.Status,
UserId = itemDto.UserId
};
} }
public async Task<Infrastructure.Entities.Items.Item> PutItemDetail(ItemDto itemDto) public async Task<Infrastructure.Entities.Items.Item> PutItemDetail(ItemDto itemDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync($"EXEC PutItemDetail @ItemCodeId,@ItemLocalId,@ItemTypeId,@UOMId,@ItemColorId,@IsActive," +
await _dbContext.Database $"@UserId,@ItemNo,@PRTypeId,@PackagingTypeId,@Qty,@ItemAttachId,@ItemAttachPath,@IsCommon,@ItemCategoryId," +
.ExecuteSqlRawAsync($"EXEC PutItemDetail @ItemCodeId,@ItemLocalId,@ItemTypeId,@UOMId,@ItemColorId,@IsActive," + $"@RequestTypeId,@ItemName,@ItemDescription,@IsMDLD",
$"@UserId,@ItemNo,@PRTypeId,@PackagingTypeId,@Qty,@ItemAttachId,@ItemAttachPath,@IsCommon,@ItemCategoryId," + new SqlParameter("@ItemCodeId", itemDto.ItemCodeId != null ? itemDto.ItemCodeId : 0L),
$"@RequestTypeId,@ItemName,@ItemDescription,@IsMDLD", new SqlParameter("@ItemLocalId", itemDto.ItemLocalId),
new SqlParameter("@ItemCodeId", itemDto.ItemCodeId != null ? itemDto.ItemCodeId : 0L), new SqlParameter("@ItemTypeId", itemDto.ItemTypeId),
new SqlParameter("@ItemLocalId", itemDto.ItemLocalId), new SqlParameter("@UOMId", itemDto.UOMId),
new SqlParameter("@ItemTypeId", itemDto.ItemTypeId), new SqlParameter("@ItemColorId", itemDto.ItemColorId),
new SqlParameter("@UOMId", itemDto.UOMId), new SqlParameter("@IsActive", itemDto.IsActive),
new SqlParameter("@ItemColorId", itemDto.ItemColorId), new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@IsActive", itemDto.IsActive), new SqlParameter("@ItemNo", itemDto.ItemNo),
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@PRTypeId", itemDto.PRTypeId),
new SqlParameter("@ItemNo", itemDto.ItemNo), new SqlParameter("@PackagingTypeId", itemDto.PackagingTypeId),
new SqlParameter("@PRTypeId", itemDto.PRTypeId), new SqlParameter("@Qty", itemDto.Qty),
new SqlParameter("@PackagingTypeId", itemDto.PackagingTypeId), new SqlParameter("@ItemAttachId", itemDto.ItemAttachId != null ? itemDto.ItemAttachId : 0L),
new SqlParameter("@Qty", itemDto.Qty), new SqlParameter("@ItemAttachPath", itemDto.ItemAttachPath ?? "N/A"),
new SqlParameter("@ItemAttachId", itemDto.ItemAttachId != null ? itemDto.ItemAttachId : 0L), new SqlParameter("@IsCommon", itemDto.IsCommon),
new SqlParameter("@ItemAttachPath", itemDto.ItemAttachPath ?? "N/A"), new SqlParameter("@ItemCategoryId", itemDto.ItemCategoryId),
new SqlParameter("@IsCommon", itemDto.IsCommon), new SqlParameter("@RequestTypeId", itemDto.RequestTypeId),
new SqlParameter("@ItemCategoryId", itemDto.ItemCategoryId), new SqlParameter("@ItemName", itemDto.ItemName),
new SqlParameter("@RequestTypeId", itemDto.RequestTypeId), new SqlParameter("@ItemDescription", itemDto.ItemDescription),
new SqlParameter("@ItemName", itemDto.ItemName), new SqlParameter("@IsMDLD", itemDto.IsMDLD));
new SqlParameter("@ItemDescription", itemDto.ItemDescription),
new SqlParameter("@IsMDLD", itemDto.IsMDLD));
return new Infrastructure.Entities.Items.Item(); return new Infrastructure.Entities.Items.Item();
}
catch (Exception ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto)
{
try
{
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>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto)
{
try
{
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>();
}
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<Infrastructure.Entities.Items.Item>> GetItemDetail(ItemDto itemDto)
{
try
{
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>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemList>> GetItemList(ItemCodeDto itemCode)
{
try
{
var allItems = await _dbContext.ItemList
.FromSqlRaw($"EXEC GetItemList @UserId = '{itemCode.UserId}'")
.ToListAsync();
return allItems ?? new List<ItemList>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemColor>> GetItemColor(ItemDto itemDto)
{
try
{
var colors = await _dbContext.ItemColors
.Where(ic => EF.Functions.Like(ic.ItemColorName, $"%{itemDto.ItemColorName}%"))
.Take(5)
.ToListAsync();
return colors ?? new List<ItemColor>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto)
{
try
{
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>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<ItemAttachement> PostPutItemPath(ItemDto itemDto) public async Task<ItemAttachement> PostPutItemPath(ItemDto itemDto)
{ {
try var isExist = await _dbContext.ItemAttachements
{
var isExist = await _dbContext.ItemAttachements
.FirstOrDefaultAsync(ia => ia.IsActive == true .FirstOrDefaultAsync(ia => ia.IsActive == true
&& ia.ItemNo == itemDto.ItemNo); && ia.ItemNo == itemDto.ItemNo);
if(isExist != null) if (isExist != null)
{
isExist.ItemAttachPath = itemDto.ItemAttachPath;
await _dbContext.SaveChangesAsync();
return new ItemAttachement();
}
else
{
return new ItemAttachement();
}
}
catch (SqlException ex)
{ {
ex.ToString(); isExist.ItemAttachPath = itemDto.ItemAttachPath;
throw; await _dbContext.SaveChangesAsync();
return new ItemAttachement();
}
else
{
return new ItemAttachement();
} }
} }
public async Task<ItemCart> PostPutItemCart(ItemDto itemDto) public async Task<ItemCart> PostPutItemCart(ItemDto itemDto)
{ {
try await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutItemCart @ItemCartId,@ItemNo,@UserId,@UOMId,@ItemColorId,@ItemCategoryId,@PackagingTypeId,@ItemAttachId,@ItemLocalId",
new SqlParameter("@ItemCartId", itemDto.ItemCartId != null ? itemDto.ItemCartId : 0L),
new SqlParameter("@ItemNo", itemDto.ItemNo != null ? itemDto.ItemNo : 0L),
new SqlParameter("@UOMId", itemDto.UOMId),
new SqlParameter("@ItemColorId", itemDto.ItemColorId),
new SqlParameter("@ItemCategoryId", itemDto.ItemCategoryId),
new SqlParameter("@PackagingTypeId", itemDto.PackagingTypeId),
new SqlParameter("@ItemAttachId", itemDto.ItemAttachId),
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemLocalId", itemDto.ItemLocalId));
return new ItemCart();
}
public async Task<ResponseObject> PostPurchRequest(ItemDto itemDto)
{
var (messCode, message) = OutputParamMessage.CreateOutputParams();
if (itemDto.RequestTypeId == 1)//Internal
{
itemDto.Status = 2;
itemDto.IsApproved = 2;
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutReqItems @UserId, @RequestItemId, @ItemNo, @QtyRequest,@Status,@IsApproved,@QtyReceived,@LotId," +
"@MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemNo", itemDto.ItemNo),
new SqlParameter("@RequestItemId", itemDto.RequestItemId != null ? itemDto.RequestItemId : 0L),
new SqlParameter("@QtyRequest", itemDto.Qty),
new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@IsApproved", itemDto.IsApproved),
new SqlParameter("@QtyReceived", itemDto.QtyReceived),
new SqlParameter("@LotId", itemDto.LotId),
messCode,message);
}
else
{ {
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutItemCart @ItemCartId,@ItemNo,@UserId,@UOMId,@ItemColorId,@ItemCategoryId,@PackagingTypeId,@ItemAttachId,@ItemLocalId", .ExecuteSqlRawAsync("EXEC PostPurchRequest @ItemCartId, @IsActive, @UserId,@ItemCount," +
new SqlParameter("@ItemCartId", itemDto.ItemCartId != null ? itemDto.ItemCartId : 0L), "@PRNo,@DateNeeded,@Qty,@ChargeTo,@Remarks,@ProjectCodeId,@MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@ItemNo", itemDto.ItemNo != null ? itemDto.ItemNo : 0L), new SqlParameter("@ItemCartId", itemDto.ItemCartId != null ? itemDto.ItemCartId : 0L),
new SqlParameter("@UOMId", itemDto.UOMId), new SqlParameter("@IsActive", 1),
new SqlParameter("@ItemColorId", itemDto.ItemColorId), new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemCategoryId", itemDto.ItemCategoryId), new SqlParameter("@ItemCount", itemDto.ItemCount),
new SqlParameter("@PackagingTypeId", itemDto.PackagingTypeId), new SqlParameter("@PRNo", itemDto.PRNo),
new SqlParameter("@ItemAttachId", itemDto.ItemAttachId), new SqlParameter("@DateNeeded", itemDto.DateNeeded),
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@Qty", itemDto.Qty),
new SqlParameter("@ItemLocalId", itemDto.ItemLocalId)); new SqlParameter("@ChargeTo", itemDto.ChargeTo),
return new ItemCart(); new SqlParameter("@Remarks", itemDto.Remarks ?? "N/A"),
new SqlParameter("@ProjectCodeId", itemDto.ProjectCodeId),
messCode, message);
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemCart>> GetItemCart(ItemDto itemDto) return new ResponseObject() {
messCode= (byte)messCode.Value,
message= message.Value.ToString()
};
}
public async Task PostPutAttachment(AttachmentRequest attach)
{ {
try var existing = await _dbContext.PRAttachments
.FirstOrDefaultAsync(a => a.PRId == attach.PRId);
if (existing == null)
{ {
var allItems = await _dbContext.ItemCarts var attchmnt = new PRAttachments()
.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>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<ItemCart> PostPurchRequest(ItemDto itemDto)
{
try
{
if(itemDto.RequestTypeId == 1)//Internal
{ {
itemDto.Status = 2; FileName = attach.FileName,
itemDto.IsApproved = 2; OrigFileName = attach.OrigFileName,
PRId = attach.PRId
await _dbContext.Database };
.ExecuteSqlRawAsync("EXEC PostPutReqItems @UserId, @RequestItemId, @ItemNo, @QtyRequest,@Status,@IsApproved,@QtyReceived,@LotId", await _dbContext.PRAttachments.AddAsync(attchmnt);
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemNo", itemDto.ItemNo),
new SqlParameter("@RequestItemId", itemDto.RequestItemId != null ? itemDto.RequestItemId : 0L),
new SqlParameter("@QtyRequest", itemDto.Qty),
new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@IsApproved", itemDto.IsApproved),
new SqlParameter("@QtyReceived", itemDto.QtyReceived),
new SqlParameter("@LotId", itemDto.LotId));
}
else
{
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPurchRequest @ItemCartId, @IsActive, @UserId,@ItemCount,@PRNo,@DateNeeded,@Qty,@ChargeTo,@Remarks",
new SqlParameter("@ItemCartId", itemDto.ItemCartId != null ? itemDto.ItemCartId : 0L),
new SqlParameter("@IsActive", 1),
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemCount", itemDto.ItemCount),
new SqlParameter("@PRNo", itemDto.PRNo),
new SqlParameter("@DateNeeded", itemDto.DateNeeded),
new SqlParameter("@Qty", itemDto.Qty),
new SqlParameter("@ChargeTo", itemDto.ChargeTo),
new SqlParameter("@Remarks", itemDto.Remarks));
}
return new ItemCart();
} }
catch (SqlException ex) else
{ {
ex.ToString(); existing.OrigFileName = attach.OrigFileName;
throw; existing.FileName = attach.FileName;
} }
} await _dbContext.SaveChangesAsync();
public async Task<long> GetPRNo() }
{
try
{
// Query the PRs table
var latestPR = await _dbContext.PRs
.OrderByDescending(ic => ic.PRNo) // Sort by PRNo in descending order
.FirstOrDefaultAsync(); // Retrieve the first record
if (latestPR != null)
{
return latestPR.PRNo;
}
else
{
return 0; // Example: Return 0 if no records found
}
}
catch (SqlException ex)
{
// Handle the exception (log, rethrow, etc.)
ex.ToString();
throw;
}
}
Task<ItemCart> IItem.PostPutItemPath(ItemDto itemDto) Task<ItemCart> IItem.PostPutItemPath(ItemDto itemDto)
{ {
throw new NotImplementedException(); 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();
public async Task <List<Departments>> GetDepartment(ItemCodeDto itemCode) return allItems ?? new List<ItemCart>();
}
public async Task<(long, long)> GetPRNo()
{ {
try try
{ {
var departments = await _dbContext.Departments var latestPR = await _dbContext.PRs
.Where(d => d.IsActive == true) .Where(ic => ic.PRNo != null)
.ToListAsync(); .OrderByDescending(ic => ic.PRNo)
return departments; .FirstOrDefaultAsync();
if (latestPR != null)
return (latestPR.PRNo + 1, latestPR.PRId + 1);
else
return (0, 0);
} }
catch (Exception ex) catch (Exception ex)
{ {
// Log the exception or handle it as needed
throw; throw;
} }
}
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<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)
{
return await _dbContext.Departments
.Where(d => d.IsActive == true)
.ToListAsync();
} }
public async Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto) public async Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto)
{ {
try var allItems = await _dbContext.NotifUserKeys
{ .FromSqlRaw($"EXEC GetNotifUserKey @UserId,@Status,@PRDetailsId,@PRNo",
var allItems = await _dbContext.NotifUserKeys new SqlParameter("@UserId", itemDto.UserId),
.FromSqlRaw($"EXEC GetNotifUserKey @UserId,@Status,@PRDetailsId,@PRNo", new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@PRDetailsId", itemDto.PRDetailsId),
new SqlParameter("@Status", itemDto.Status), new SqlParameter("@PRNo", itemDto.PRNo))
new SqlParameter("@PRDetailsId", itemDto.PRDetailsId), .ToListAsync();
new SqlParameter("@PRNo", itemDto.PRNo))
.ToListAsync();
return allItems ?? new List<NotifUserKey>(); return allItems ?? new List<NotifUserKey>();
} }
catch (SqlException ex) public async Task<IReadOnlyList<ProjectCodes>> GetProjectCode()
{ {
ex.ToString(); return await _dbContext.ProjectCodes
throw; .AsNoTracking()
} .ToListAsync();
}
public async Task<IReadOnlyList<ProjectCodes>> GetProjectCodeByTerm(string? term)
{
return await _dbContext.ProjectCodes
.AsNoTracking()
.Where(p => p.StatusName != "Completed" && p.IsActive
&& EF.Functions.Like(p.ProjectCode, $"%{term}%"))
.ToListAsync();
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,21 @@
using CPRNIMS.Domain.Contracts.PR; using CPRNIMS.Domain.Contracts.PR;
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Dto.PR; using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.Infrastructure.Dto.PR.Response;
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Entities.SMTP; using CPRNIMS.Infrastructure.Entities.SMTP;
using CPRNIMS.Infrastructure.Models.Common;
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using static CPRNIMS.Domain.Services.OutputParamMessage; using Newtonsoft.Json.Linq;
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.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json.Linq; using static CPRNIMS.Domain.Services.OutputParamMessage;
namespace CPRNIMS.Domain.Services.PR namespace CPRNIMS.Domain.Services.PR
{ {
@ -25,15 +27,392 @@ namespace CPRNIMS.Domain.Services.PR
_dbContext = dbContext; _dbContext = dbContext;
} }
#region Get #region Get
public async Task<List<PRList>> GetAllPR(PRDto PRDto) public async Task<List<NotificationById>> GetNotificationById(PRDto PRDto)
{ {
var allItems = await _dbContext.PRLists var allItems = await _dbContext.NotificationByIds
.FromSqlRaw($"EXEC GetAllPR @UserId,@IsArchived", .FromSqlRaw("EXEC GetNotificationById @UserId,@PRDetailsId,@AppsModuleId",
new SqlParameter("@UserId", PRDto.UserId), new SqlParameter("@UserId", PRDto.UserId),
new SqlParameter("@IsArchived", PRDto.IsArchived)) new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
new SqlParameter("@AppsModuleId", PRDto.AppsModuleId))
.ToListAsync(); .ToListAsync();
return allItems ?? new List<PRList>(); return allItems ?? new List<NotificationById>();
}
public async Task<List<ProjectCodes>> GetProjectCodes(PRDto pRDto)
{
return await _dbContext.ProjectCodes.ToListAsync();
}
public async Task<PagedResult<DeletedPR>> GetDeletedPR(PRDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@IsArchived", dto.IsArchived),
new SqlParameter("@SearchPRNo", dto.SearchPRNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchDept", dto.SearchDept ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
int totalCount = 0;
var items = new List<DeletedPR>();
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"EXEC GetDeletedPR @UserId,
@SearchPRNo, @SearchItemName, @SearchDept,
@PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
using var reader = await cmd.ExecuteReaderAsync();
// First result set = total count
if (await reader.ReadAsync())
totalCount = reader.GetInt32(0);
// Second result set = paged rows
await reader.NextResultAsync();
while (await reader.ReadAsync())
{
items.Add(new DeletedPR
{
PRId = reader["PRId"] as long? ?? 0,
PRNo = reader["PRNo"] as long? ?? 0,
PRDetailsId = reader["PRDetailsId"] as long? ?? 0,
ItemNo = reader["ItemNo"] as long? ?? 0,
ItemName = reader["ItemName"]?.ToString(),
Department = reader["Department"]?.ToString(),
Remarks = reader["Remarks"]?.ToString(),
DateNeeded = reader["DateNeeded"] as DateTime? ?? DateTime.UtcNow,
CreatedDate = reader["CreatedDate"] as DateTime? ?? DateTime.UtcNow,
AttestedDate = reader["AttestedDate"]?.ToString(),
ApprovedDate = reader["ApprovedDate"]?.ToString(),
ApprovedBy = reader["ApprovedBy"]?.ToString(),
AttestedBy = reader["AttestedBy"]?.ToString(),
CreatedBy = reader["CreatedBy"]?.ToString(),
Qty = Convert.ToDecimal(reader["Qty"])
});
}
await conn.CloseAsync();
return new PagedResult<DeletedPR>
{
Data = items,
TotalCount = totalCount,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize
};
}
public async Task<PagedResult<DetailedPRTracking>> GetDetailedPRTracking(PRDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@SearchPRNo", dto.SearchPRNo ?? ""),
new SqlParameter("@SearchItemNo", dto.SearchItemNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchDept", dto.SearchDept ?? ""),
new SqlParameter("@SearchStatusName", dto.SearchStatusName ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
var statusList = new List<string>();
int totalCount = 0;
var items = new List<DetailedPRTracking>();
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"EXEC GetDetailedPRTracking @UserId,
@SearchPRNo, @SearchItemNo, @SearchItemName, @SearchDept, @SearchStatusName,
@PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
cmd.CommandTimeout = 60;
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
statusList.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 DetailedPRTracking
{
PRNo = Convert.ToInt64(reader["PRNo"]),
PRDetailsId = Convert.ToInt64(reader["PRDetailsId"]),
PRBy = reader["PRBy"]?.ToString(),
PRTypeName = reader["PRTypeName"]?.ToString(),
PRDate = reader["PRDate"] as DateTime? ?? DateTime.UtcNow,
AttestedBy = reader["AttestedBy"]?.ToString(),
ApprovedBy = reader["ApprovedBy"]?.ToString(),
CanvassDate = reader["CanvassDate"]?.ToString(),
CanvassBy = reader["CanvassBy"]?.ToString(),
CanvassNo = reader["CanvassNo"]?.ToString(),
PONo = reader["PONo"]?.ToString(),
POBy = reader["POBy"]?.ToString(),
POQty = Convert.ToDecimal(reader["POQty"]),
PODate = reader["PODate"]?.ToString(),
RRDate = reader["RRDate"]?.ToString(),
ReceivedDate = reader["ReceivedDate"]?.ToString(),
ReceivedBy = reader["ReceivedBy"]?.ToString(),
AcknowledgeBy = reader["AcknowledgeBy"]?.ToString(),
AcknowledgeDate = reader["AcknowledgeDate"]?.ToString(),
Specification = reader["Specification"]?.ToString(),
RRNo = Convert.ToInt64(reader["RRNo"]),
Department = reader["Department"]?.ToString(),
ItemCategoryName = reader["ItemCategoryName"]?.ToString(),
ItemName = reader["ItemName"]?.ToString(),
ItemDescription = reader["ItemDescription"]?.ToString(),
Status = Convert.ToInt16(reader["Status"]),
StatusName = reader["StatusName"]?.ToString(),
NewPRNo = reader["NewPRNo"]?.ToString(),
DateNeeded = reader["DateNeeded"] as DateTime? ?? DateTime.UtcNow,
ItemNo = Convert.ToInt64(reader["ItemNo"]),
Qty = Convert.ToDecimal(reader["Qty"]),
QuantityReceived = Convert.ToDecimal(reader["QuantityReceived"]),
UOMName = reader["UOMName"]?.ToString(),
ItemAttachPath = reader["ItemAttachPath"]?.ToString(),
Remarks = reader["Remarks"]?.ToString(),
});
}
await conn.CloseAsync();
return new PagedResult<DetailedPRTracking>
{
Data = items,
TotalCount = totalCount,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize,
StatusList = statusList
};
}
public async Task<PagedResult<ApprovedPR>> GetApprovedPR(PRDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@SearchPRNo", dto.SearchPRNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchDept", dto.SearchDept ?? ""),
new SqlParameter("@SearchStatusName", dto.SearchStatusName ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
var statusList = new List<string>();
int totalCount = 0;
var items = new List<ApprovedPR>();
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"EXEC GetApprovedPR @UserId,
@SearchPRNo, @SearchItemName, @SearchDept, @SearchStatusName,
@PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
cmd.CommandTimeout = 60;
using var reader = await cmd.ExecuteReaderAsync();
// Result set 1 — distinct status list
while (await reader.ReadAsync())
statusList.Add(reader.GetString(0));
// Result set 2 — total count
await reader.NextResultAsync();
if (await reader.ReadAsync())
totalCount = reader.GetInt32(0);
// Result set 3 — paged rows
await reader.NextResultAsync();
while (await reader.ReadAsync())
{
items.Add(new ApprovedPR
{
PRId = reader["PRId"] as long? ?? 0,
PRNo = reader["PRNo"] as long? ?? 0,
PRDetailsId = reader["PRDetailsId"] as long? ?? 0,
ItemNo = reader["ItemNo"] as long? ?? 0,
ItemName = reader["ItemName"]?.ToString(),
Department = reader["Department"]?.ToString(),
StatusName = reader["StatusName"]?.ToString(),
DateNeeded = reader["DateNeeded"] as DateTime? ?? DateTime.UtcNow,
CreatedDate = reader["CreatedDate"] as DateTime? ?? DateTime.UtcNow,
AttestedDate = reader["AttestedDate"]?.ToString(),
ApprovedDate = reader["ApprovedDate"]?.ToString(),
Qty = Convert.ToDecimal(reader["Qty"]),
ApprovedBy = reader["ApprovedBy"]?.ToString(),
AttestedBy = reader["AttestedBy"]?.ToString(),
CreatedBy = reader["CreatedBy"]?.ToString(),
RemainingDays = reader["RemainingDays"] as int? ?? 0,
});
}
await conn.CloseAsync();
return new PagedResult<ApprovedPR>
{
Data = items,
TotalCount = totalCount,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize,
StatusList = statusList
};
}
public async Task<PagedResult<Infrastructure.Entities.Purchasing.PRList>> GetAllPR(PRDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@SearchPRNo", dto.SearchPRNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchDept", dto.SearchDept ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
int totalCount = 0;
var items = new List<Infrastructure.Entities.Purchasing.PRList>();
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"EXEC GetAllPR @UserId,
@SearchPRNo, @SearchItemName, @SearchDept,
@PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
using var reader = await cmd.ExecuteReaderAsync();
if (await reader.ReadAsync())
totalCount = reader.GetInt32(0);
await reader.NextResultAsync();
while (await reader.ReadAsync())
{
items.Add(new Infrastructure.Entities.Purchasing.PRList
{
PRId = reader["PRId"] as long? ?? 0,
PRNo = reader["PRNo"] as long? ?? 0,
NewPRNo = reader["NewPRNo"]?.ToString(),
AggreItemName = reader["AggreItemName"]?.ToString(),
CreatedDate = reader["CreatedDate"] as DateTime? ?? DateTime.UtcNow,
DateNeeded = reader["DateNeeded"] as DateTime? ?? DateTime.UtcNow,
CreatedBy = reader["CreatedBy"]?.ToString(),
Department = reader["Department"]?.ToString(),
ApprovedBy = reader["ApprovedBy"]?.ToString(),
AttestedBy = reader["AttestedBy"]?.ToString(),
Remarks = reader["Remarks"]?.ToString(),
Status = reader["Status"] as short? ?? 0,
});
}
await conn.CloseAsync();
return new PagedResult<Infrastructure.Entities.Purchasing.PRList>
{
Data = items,
TotalCount = totalCount,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize
};
}
public async Task<PagedResult<Infrastructure.Entities.Purchasing.PRList>> GetPRArchived(PRDto dto)
{
var parameters = new[]
{
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@SearchPRNo", dto.SearchPRNo ?? ""),
new SqlParameter("@SearchItemName", dto.SearchItemName ?? ""),
new SqlParameter("@SearchDept", dto.SearchDept ?? ""),
new SqlParameter("@PageNumber", dto.PageNumber),
new SqlParameter("@PageSize", dto.PageSize)
};
int totalCount = 0;
var items = new List<Infrastructure.Entities.Purchasing.PRList>();
var conn = _dbContext.Database.GetDbConnection();
await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"EXEC GetPRArchived @UserId,
@SearchPRNo, @SearchItemName, @SearchDept,
@PageNumber, @PageSize";
foreach (var p in parameters) cmd.Parameters.Add(p);
using var reader = await cmd.ExecuteReaderAsync();
if (await reader.ReadAsync())
totalCount = reader.GetInt32(0);
await reader.NextResultAsync();
while (await reader.ReadAsync())
{
items.Add(new Infrastructure.Entities.Purchasing.PRList
{
PRId = reader["PRId"] as long? ?? 0,
PRNo = reader["PRNo"] as long? ?? 0,
NewPRNo = reader["NewPRNo"]?.ToString(),
AggreItemName = reader["AggreItemName"]?.ToString(),
CreatedDate = reader["NewPRNo"] as DateTime? ?? DateTime.UtcNow,
DateNeeded = reader["DateNeeded"] as DateTime? ?? DateTime.UtcNow,
CreatedBy = reader["CreatedBy"]?.ToString(),
Department = reader["Department"]?.ToString(),
ApprovedBy = reader["ApprovedBy"]?.ToString(),
AttestedBy = reader["AttestedBy"]?.ToString(),
Remarks = reader["Remarks"]?.ToString(),
Status = reader["Status"] as short? ?? 0,
});
}
await conn.CloseAsync();
return new PagedResult<Infrastructure.Entities.Purchasing.PRList>
{
Data = items,
TotalCount = totalCount,
PageNumber = dto.PageNumber,
PageSize = dto.PageSize
};
}
public async Task<List<PRDto>> GetApproverNameByPRNo(PRDto PRDto)
{
var result = await _dbContext.Approved
.Where(a => a.PRNo == PRDto.PRNo && (a.ApproverId == 1 || a.ApproverId == 2))
.GroupBy(a => a.PRNo)
.Select(g => new PRDto
{
AttestedBy = g.Where(x => x.ApproverId == 1 && x.ApprovedBy != null)
.Select(x => x.ApprovedBy)
.FirstOrDefault(),
ApprovedBy = g.Where(x => x.ApproverId == 2 && x.ApprovedBy != null)
.Select(x => x.ApprovedBy)
.FirstOrDefault()
})
.ToListAsync();
if (result.Any() && (result[0].AttestedBy != null || result[0].ApprovedBy != null))
{
return result;
}
return new List<PRDto>();
} }
public async Task<List<PRDto>> GetApproverName(PRDto PRDto) public async Task<List<PRDto>> GetApproverName(PRDto PRDto)
{ {
@ -109,15 +488,15 @@ namespace CPRNIMS.Domain.Services.PR
return allItems ?? new List<NotifUserKey>(); return allItems ?? new List<NotifUserKey>();
} }
public async Task<List<PRDetails>> GetPRDetailByPRNo(PRDto PRDto) public async Task<List<PRItemList>> GetPRDetailByPRNo(PRDto PRDto)
{ {
var allItems = await _dbContext.PRDetails var allItems = await _dbContext.PRItemLists
.FromSqlRaw($"EXEC GetPRDetailByPRNo @UserId, @PRNo", .FromSqlRaw($"EXEC GetPRDetailByPRNo @UserId, @PRNo",
new SqlParameter("@UserId", PRDto.UserId), new SqlParameter("@UserId", PRDto.UserId),
new SqlParameter("@PRNo", PRDto.PRNo)) new SqlParameter("@PRNo", PRDto.PRNo))
.ToListAsync(); .ToListAsync();
return allItems ?? new List<PRDetails>(); return allItems ?? new List<PRItemList>();
} }
public async Task<List<PRTracking>> GetPRStatusById(PRDto PRDto) public async Task<List<PRTracking>> GetPRStatusById(PRDto PRDto)
{ {
@ -150,14 +529,6 @@ namespace CPRNIMS.Domain.Services.PR
return new List<Infrastructure.Entities.Canvass.PRList>(); return new List<Infrastructure.Entities.Canvass.PRList>();
} }
public async Task<List<RRReport>> GetDetailedPRTracking(PRDto PRDto)
{
var allItems = await _dbContext.DetailedPRTrackings
.FromSqlRaw("EXEC GetDetailedPRTracking @UserId",
new SqlParameter("@UserId", PRDto.UserId)).ToListAsync();
return allItems ?? new List<RRReport>();
}
public async Task<List<AlternativeOffer>> GetSupplierAlternativeOffer(PRDto PRDto) public async Task<List<AlternativeOffer>> GetSupplierAlternativeOffer(PRDto PRDto)
{ {
var rfq = await _dbContext.AlternativeOffers var rfq = await _dbContext.AlternativeOffers
@ -175,94 +546,62 @@ namespace CPRNIMS.Domain.Services.PR
} }
#endregion #endregion
#region Post Put #region Post Put
public async Task<PRDetails> PostPRApproveReject(PRDto PRDto) public async Task<PRResponse> PostPRApproveReject(PRDto PRDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync("EXEC PostPRApproveReject @UserId, @ItemNo, @Status, @PRDetailsId, @Remarks",
await _dbContext.Database new SqlParameter("@ItemNo", PRDto.ItemNo != null ? PRDto.ItemNo : 0L),
.ExecuteSqlRawAsync("EXEC PostPRApproveReject @UserId, @ItemNo, @Status, @PRDetailsId, @Remarks", new SqlParameter("@UserId", PRDto.UserId),
new SqlParameter("@ItemNo", PRDto.ItemNo != null ? PRDto.ItemNo : 0L), new SqlParameter("@Status", PRDto.Status),
new SqlParameter("@UserId", PRDto.UserId), new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
new SqlParameter("@Status", PRDto.Status), new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId), return new PRResponse();
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
return new PRDetails();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<PRDetails> PutItemDetail(PRDto PRDto) public async Task<PRResponse> PutItemDetail(PRDto PRDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync($"EXEC PutPRItemDetail @UserId, @ItemLocalId, @UOMId, @ItemColorId," +
await _dbContext.Database $"@Qty,@ItemCategoryId,@PRDetailsId,@Remarks,@ItemName,@ItemDescription",
.ExecuteSqlRawAsync($"EXEC PutPRItemDetail @UserId, @ItemLocalId, @UOMId, @ItemColorId," + new SqlParameter("@PRDetailsId", PRDto.PRDetailsId != null ? PRDto.PRDetailsId : 0L),
$"@Qty,@ItemCategoryId,@PRDetailsId,@Remarks,@ItemName,@ItemDescription", new SqlParameter("@ItemLocalId", PRDto.ItemLocalId),
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId != null ? PRDto.PRDetailsId : 0L), new SqlParameter("@UOMId", PRDto.UOMId),
new SqlParameter("@ItemLocalId", PRDto.ItemLocalId), new SqlParameter("@ItemColorId", PRDto.ItemColorId),
new SqlParameter("@UOMId", PRDto.UOMId), new SqlParameter("@UserId", PRDto.UserId),
new SqlParameter("@ItemColorId", PRDto.ItemColorId), new SqlParameter("@Qty", PRDto.Qty),
new SqlParameter("@UserId", PRDto.UserId), new SqlParameter("@ItemCategoryId", PRDto.ItemCategoryId),
new SqlParameter("@Qty", PRDto.Qty), new SqlParameter("@Remarks", PRDto.Remarks),
new SqlParameter("@ItemCategoryId", PRDto.ItemCategoryId), new SqlParameter("@ItemName", PRDto.ItemName),
new SqlParameter("@Remarks", PRDto.Remarks), new SqlParameter("@ItemDescription", PRDto.ItemDescription));
new SqlParameter("@ItemName", PRDto.ItemName), return new PRResponse();
new SqlParameter("@ItemDescription", PRDto.ItemDescription));
return new PRDetails();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<PRDetails> PostPutDeniedItem(PRDto PRDto) public async Task<PRResponse> PostPutDeniedItem(PRDto PRDto)
{ {
try await _dbContext.Database
{
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutDeniedItem @UserId,@PRDetailsId,@Remarks", .ExecuteSqlRawAsync("EXEC PostPutDeniedItem @UserId,@PRDetailsId,@Remarks",
new SqlParameter("@UserId", PRDto.UserId), new SqlParameter("@UserId", PRDto.UserId),
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId), new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A")); new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
return new PRDetails(); return new PRResponse();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<PRDetails> PostPutReceiving(PRDto PRDto) public async Task<PRResponse> PostPutReceiving(PRDto PRDto)
{ {
try await _dbContext.Database
{ .ExecuteSqlRawAsync($"EXEC PostPutReceiving @UserId, @PONo, @POTypeId, @EmailAddress, @DRNo, @DocTypeId, @QuantityReceived,@RRNo,@PRDetailsId,@Remarks,@ReceivedDate,@IsCompleted",
await _dbContext.Database new SqlParameter("@UserId", PRDto.UserId),
.ExecuteSqlRawAsync($"EXEC PostPutReceiving @UserId, @PONo, @POTypeId, @EmailAddress, @DRNo, @DocTypeId, @QuantityReceived,@RRNo,@PRDetailsId,@Remarks,@ReceivedDate,@IsCompleted", new SqlParameter("@PONo", PRDto.PONo),
new SqlParameter("@UserId", PRDto.UserId), new SqlParameter("@POTypeId", PRDto.POTypeId),
new SqlParameter("@PONo", PRDto.PONo), new SqlParameter("@EmailAddress", PRDto.EmailAddress),
new SqlParameter("@POTypeId", PRDto.POTypeId), new SqlParameter("@DRNo", PRDto.DRNo),
new SqlParameter("@EmailAddress", PRDto.EmailAddress), new SqlParameter("@DocTypeId", PRDto.DocTypeId),
new SqlParameter("@DRNo", PRDto.DRNo), new SqlParameter("@QuantityReceived", PRDto.QuantityReceived),
new SqlParameter("@DocTypeId", PRDto.DocTypeId), new SqlParameter("@RRNo", PRDto.RRNo),
new SqlParameter("@QuantityReceived", PRDto.QuantityReceived), new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
new SqlParameter("@RRNo", PRDto.RRNo), new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"),
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId), new SqlParameter("@ReceivedDate", PRDto.ReceivedDate),
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"), new SqlParameter("@IsCompleted", PRDto.IsCompleted));
new SqlParameter("@ReceivedDate", PRDto.ReceivedDate), return new PRResponse();
new SqlParameter("@IsCompleted", PRDto.IsCompleted));
return new PRDetails();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<PRDetails> PutPOClose(PRDto PRDto) public async Task<PRResponse> PutPOClose(PRDto PRDto)
{ {
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PutPOClose @UserId, @PONo, @POTypeId, @EmailAddress,@PRDetailsId,@DocTypeId,@PRNo,@Remarks", .ExecuteSqlRawAsync("EXEC PutPOClose @UserId, @PONo, @POTypeId, @EmailAddress,@PRDetailsId,@DocTypeId,@PRNo,@Remarks",
@ -274,7 +613,7 @@ namespace CPRNIMS.Domain.Services.PR
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId), new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
new SqlParameter("@PRNo", PRDto.PRNo), new SqlParameter("@PRNo", PRDto.PRNo),
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A")); new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
return new PRDetails(); return new PRResponse();
} }
public async Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto) public async Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto)
{ {
@ -285,19 +624,26 @@ namespace CPRNIMS.Domain.Services.PR
new SqlParameter("@CanvassDetailId", pRDto.CanvassDetailId)); new SqlParameter("@CanvassDetailId", pRDto.CanvassDetailId));
return new AlternativeOfferDetails(); return new AlternativeOfferDetails();
} }
private async Task<bool> IsUsingAsync(int projectCodeId)
public async Task<List<NotificationById>> GetNotificationById(PRDto PRDto)
{ {
var allItems = await _dbContext.NotificationByIds return await (from pr in _dbContext.PRs
.FromSqlRaw("EXEC GetNotificationById @UserId,@PRDetailsId,@AppsModuleId", join pod in _dbContext.PODetails on pr.PRNo equals pod.PRNo
new SqlParameter("@UserId", PRDto.UserId), where pr.ProjectCodeId == projectCodeId
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId), && !pod.IsRemoved
new SqlParameter("@AppsModuleId", PRDto.AppsModuleId)) && pr.IsActive
.ToListAsync(); select pr).AnyAsync();
return allItems ?? new List<NotificationById>();
} }
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();
@ -318,6 +664,84 @@ namespace CPRNIMS.Domain.Services.PR
}; };
return response; return response;
} }
public async Task<ResponseObject> PostPutProjectCode(PRDto prDto)
{
if (prDto == null) throw new ArgumentNullException(nameof(prDto));
var existing = await _dbContext.ProjectCodes
.FirstOrDefaultAsync(p => p.ProjectCodeId == prDto.ProjectCodeId);
if (existing == null)
{
var project = new ProjectCodes
{
ProjectCode = prDto.ProjectCode,
ProjectName = prDto.ProjectName,
DeliveryAddress = prDto.DeliveryAddress,
MaxDays = prDto.MaxDays,
StatusName = prDto.StatusName,
IsActive = prDto.IsActive
};
await _dbContext.ProjectCodes.AddAsync(project);
}
else
{
if (await IsUsingAsync(prDto.ProjectCodeId) && await ProjectStatusChanges(prDto.ProjectCodeId,prDto.StatusName) == false)
{
return new ResponseObject()
{
message = "Cannot update this project code because it is already being used in a Purchase Order (PO).",
messCode = 0,
success = false,
};
}
if (await IsUsingAsync(prDto.ProjectCodeId))
{
existing.StatusName = prDto.StatusName;
}
else
{
existing.ProjectCode = prDto.ProjectCode;
existing.ProjectName = prDto.ProjectName;
existing.DeliveryAddress = prDto.DeliveryAddress;
existing.MaxDays = prDto.MaxDays;
existing.StatusName = prDto.StatusName;
existing.IsActive = prDto.IsActive;
}
}
await _dbContext.SaveChangesAsync();
return new ResponseObject()
{
message = "Project code detail successfully updated",
messCode = 1,
success = true
};
}
public async Task<ResponseObject> PostItemInPR(PRDto dto)
{
var (messCode, message) = CreateOutputParams();
await _dbContext.Database.ExecuteSqlRawAsync(
"EXEC PostItemInPR @UserId,@ItemNo,@Qty,@PRNo,@MessCode OUTPUT,@Message OUTPUT",
new SqlParameter("@UserId", dto.UserId),
new SqlParameter("@ItemNo", dto.ItemNo),
new SqlParameter("@Qty", dto.Qty),
new SqlParameter("@PRNo", dto.PRNo),
messCode,
message
);
var response = new ResponseObject
{
message = message.Value?.ToString(),
messCode = Convert.ToByte(messCode.Value)
};
return response;
}
#endregion #endregion
} }
} }

View File

@ -23,113 +23,65 @@ namespace CPRNIMS.Domain.Services.Receiving
#region Get #region Get
public async Task<List<Infrastructure.Entities.Receiving.RRReport>> GetRRReport(ItemDto itemDto) public async Task<List<Infrastructure.Entities.Receiving.RRReport>> GetRRReport(ItemDto itemDto)
{ {
try if (!itemDto.IsSorting)
{ {
if (!itemDto.IsSorting) itemDto.DateFrom = DateTime.Today;
{ itemDto.DateTo = DateTime.Today.AddDays(1).AddSeconds(-1);
itemDto.DateFrom = DateTime.Today;
itemDto.DateTo = DateTime.Today.AddDays(1).AddSeconds(-1);
}
var allItems = await _dbContext.RRReports
.FromSqlRaw($"EXEC GetRRReport @DateFrom,@DateTo,@IsSorting",
new SqlParameter("@DateFrom", itemDto.DateFrom),
new SqlParameter("@DateTo", itemDto.DateTo),
new SqlParameter("@IsSorting", itemDto.IsSorting))
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Receiving.RRReport>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
} }
var allItems = await _dbContext.RRReports
.FromSqlRaw($"EXEC GetRRReport @DateFrom,@DateTo,@IsSorting",
new SqlParameter("@DateFrom", itemDto.DateFrom),
new SqlParameter("@DateTo", itemDto.DateTo),
new SqlParameter("@IsSorting", itemDto.IsSorting))
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.Receiving.RRReport>();
} }
public async Task<List<ForReceiving>> GetForReceiving(ItemDto itemDto) public async Task<List<ForReceiving>> GetForReceiving(ItemDto itemDto)
{ {
try var allItems = await _dbContext.ForReceivings
{ .FromSqlRaw($"EXEC GetForReceiving @UserId,@IsDenied",
var allItems = await _dbContext.ForReceivings new SqlParameter("@UserId", itemDto.UserId),
.FromSqlRaw($"EXEC GetForReceiving @UserId,@IsDenied", new SqlParameter("@IsDenied", itemDto.IsDenied))
new SqlParameter("@UserId", itemDto.UserId), .ToListAsync();
new SqlParameter("@IsDenied", itemDto.IsDenied))
.ToListAsync();
return allItems ?? new List<ForReceiving>(); return allItems ?? new List<ForReceiving>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<RR>> GetRR(ItemDto itemDto) public async Task<List<RR>> GetRR(ItemDto itemDto)
{ {
try var allItems = await _dbContext.RRs
{
var allItems = await _dbContext.RRs
.FromSqlRaw($"EXEC GetRR @UserId", .FromSqlRaw($"EXEC GetRR @UserId",
new SqlParameter("@UserId", itemDto.UserId)) new SqlParameter("@UserId", itemDto.UserId))
.ToListAsync(); .ToListAsync();
return allItems ?? new List<RR>(); return allItems ?? new List<RR>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<RRSeries>> GetLatestRRNo(ItemDto itemDto) public async Task<List<RRSeries>> GetLatestRRNo(ItemDto itemDto)
{ {
try return await _dbContext.RRSeries.FromSqlRaw("EXEC GetLatestRRNo @UserId",
{ new SqlParameter("@UserId", itemDto.UserId)).ToListAsync();
return await _dbContext.RRSeries.FromSqlRaw("EXEC GetLatestRRNo @UserId",
new SqlParameter("@UserId",itemDto.UserId)).ToListAsync();
}
catch (Exception)
{
throw;
}
} }
public async Task<List<ReceivingDetail>> GetRRDetailByPO(ItemDto itemDto) public async Task<List<ReceivingDetail>> GetRRDetailByPO(ItemDto itemDto)
{ {
try var allItems = await _dbContext.ReceivingDetails
{ .FromSqlRaw($"EXEC GetRRDetailByPO @PONo,@POTypeId,@UserId",
var allItems = await _dbContext.ReceivingDetails new SqlParameter("@PONo", itemDto.PONo),
.FromSqlRaw($"EXEC GetRRDetailByPO @PONo,@POTypeId,@UserId", new SqlParameter("@POTypeId", itemDto.POTypeId),
new SqlParameter("@PONo", itemDto.PONo), new SqlParameter("@UserId", itemDto.UserId))
new SqlParameter("@POTypeId", itemDto.POTypeId), .ToListAsync();
new SqlParameter("@UserId", itemDto.UserId))
.ToListAsync();
return allItems ?? new List<ReceivingDetail>(); return allItems ?? new List<ReceivingDetail>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<RRDetail>> GetRRDetail(ItemDto itemDto) public async Task<List<RRDetailDto>> GetRRDetail(ItemDto itemDto)
{ {
try var allItems = await _dbContext.RRDetailss
{ .FromSqlRaw("EXEC GetRRDetail @RRNo,@UserId",
var allItems = await _dbContext.RRDetailss
.FromSqlRaw($"EXEC GetRRDetail @RRNo,@UserId",
new SqlParameter("@RRNo", itemDto.RRNo), new SqlParameter("@RRNo", itemDto.RRNo),
new SqlParameter("@UserId", itemDto.UserId)) new SqlParameter("@UserId", itemDto.UserId))
.ToListAsync(); .ToListAsync();
return allItems ?? new List<RRDetail>(); return allItems ?? new List<RRDetailDto>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
#endregion #endregion
#region Post Put #region Post Put

View File

@ -0,0 +1,80 @@
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

@ -0,0 +1,109 @@
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

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services
{
public class Result<T>
{
public bool IsSuccess { get; set; }
public string? Error { get; set; }
public T? Value { get; set; }
private Result(bool isSuccess, T? value, string? error)
{
IsSuccess = isSuccess;
Error = error;
Value = value;
}
public static Result<T> Success(T value)
=> new Result<T>(true, value, null);
public static Result<T> Failure(string? error)
=> new Result<T>(false, default, error);
}
}

View File

@ -1,4 +1,5 @@
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.ViewModel.Canvass; using CPRNIMS.Infrastructure.ViewModel.Canvass;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
using System; using System;
@ -11,10 +12,10 @@ namespace CPRNIMS.Domain.UIContracts.Canvass
{ {
public interface ICanvass public interface ICanvass
{ {
#region
Task<List<CanvassVM>> GetSupplierBid(User user, CanvassVM viewModel); Task<List<CanvassVM>> GetSupplierBid(User user, CanvassVM viewModel);
Task<List<CanvassVM>> GetSupplierBidByItem(User user, CanvassVM viewModel); Task<List<CanvassVM>> GetSupplierBidByItem(User user, CanvassVM viewModel);
Task<List<CanvassVM>> GetSupplierBidById(User user, CanvassVM viewModel); Task<List<CanvassVM>> GetSupplierBidById(User user, CanvassVM viewModel);
Task<List<CanvassVM>> GetCanvassPerSupplier(User user, CanvassVM viewModel);
Task<List<CanvassVM>> GetCanvassPerSupplierEmail(User user, CanvassVM viewModel); Task<List<CanvassVM>> GetCanvassPerSupplierEmail(User user, CanvassVM viewModel);
Task<List<CanvassVM>> GetItemSupplierWOEmail(User user, CanvassVM viewModel); Task<List<CanvassVM>> GetItemSupplierWOEmail(User user, CanvassVM viewModel);
Task<List<CanvassVM>> GetSupplierItemWOEmail(User user, CanvassVM viewModel); Task<List<CanvassVM>> GetSupplierItemWOEmail(User user, CanvassVM viewModel);
@ -32,6 +33,13 @@ namespace CPRNIMS.Domain.UIContracts.Canvass
Task<List<CanvassVM>?> GetCanvassPerSupplierId(User user, CanvassVM viewModel); Task<List<CanvassVM>?> GetCanvassPerSupplierId(User user, CanvassVM viewModel);
Task<List<CanvassVM>?> GetCanvassGroupByPRNo(User user, CanvassVM viewModel); Task<List<CanvassVM>?> GetCanvassGroupByPRNo(User user, CanvassVM viewModel);
Task<List<CanvassVM>?> GetAlternativeOfferByPRDetailId(User user, CanvassVM viewModels); Task<List<CanvassVM>?> GetAlternativeOfferByPRDetailId(User user, CanvassVM viewModels);
Task<PagedResult<CanvassVM>> GetCanvassPerSupplier(User user, CanvassVM viewModel);
Task<PagedResult<CanvassVM>> GetItemsForTagging(User user, CanvassVM dto);
#endregion
#region Post Put
Task<CanvassVM> PostSupplierForCanvass(User user, CanvassVM viewModel);
Task<CanvassVM> PostCanvass(User user, CanvassVM viewModel); Task<CanvassVM> PostCanvass(User user, CanvassVM viewModel);
Task<CanvassVM> PostPutSupplier(User user, CanvassVM viewModel); Task<CanvassVM> PostPutSupplier(User user, CanvassVM viewModel);
Task<CanvassVM> PostTaggingSupplier(User user, CanvassVM viewModel); Task<CanvassVM> PostTaggingSupplier(User user, CanvassVM viewModel);
@ -42,5 +50,7 @@ namespace CPRNIMS.Domain.UIContracts.Canvass
Task<CanvassVM> PostPutMySupplier(User user, CanvassVM viewModel); Task<CanvassVM> PostPutMySupplier(User user, CanvassVM viewModel);
Task<CanvassVM> PostPutItemTagging(User user, CanvassVM viewModel); Task<CanvassVM> PostPutItemTagging(User user, CanvassVM viewModel);
Task<CanvassVM> UnlockFormLink(User user, CanvassVM viewModel); Task<CanvassVM> UnlockFormLink(User user, CanvassVM viewModel);
Task<CanvassVM> StartCanvass(User user, CanvassVM viewModel);
#endregion
} }
} }

View File

@ -1,4 +1,6 @@
using CPRNIMS.Infrastructure.Dto.Inventory; using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.ViewModel.Inventory; using CPRNIMS.Infrastructure.ViewModel.Inventory;
using System; using System;
@ -11,12 +13,15 @@ namespace CPRNIMS.Domain.UIContracts.Inventory
{ {
public interface IInventory public interface IInventory
{ {
Task<TransactContextDto?> GetTransactContextAsync(int inventoryId);
Task<List<InventoryVM>> GetInventoryByUserId(User user, InventoryVM viewModel); Task<List<InventoryVM>> GetInventoryByUserId(User user, InventoryVM viewModel);
Task<List<InventoryVM>> GetRequestedItemByUserId(User user, InventoryVM viewModel); Task<List<InventoryVM>> GetRequestedItemByUserId(User user, InventoryVM viewModel);
Task<List<InventoryVM>> GetInventoryById(User user, InventoryVM viewModel); Task<List<InventoryVM>> GetInventoryById(User user, InventoryVM viewModel);
Task<List<InventoryVM>> GetLotNo(User user, InventoryVM viewModel); Task<List<InventoryVM>> GetLotNo(User user, InventoryVM viewModel);
Task<List<InventoryVM>> GetLotQtyByItem(User user, InventoryVM viewModel); Task<List<InventoryVM>> GetLotQtyByItem(User user, InventoryVM viewModel);
Task<List<InventoryVM>> GetLotNoById(User user, InventoryVM viewModel); Task<List<InventoryVM>> GetLotNoById(User user, InventoryVM viewModel);
Task<PagedResult<InventoryResponse>> GetInventory(User user, InventoryRequest request);
Task<InventoryVM> PostPutLotNo(User user, InventoryVM viewModel); Task<InventoryVM> PostPutLotNo(User user, InventoryVM viewModel);
Task<InventoryVM> PostPutLotBin(User user, InventoryVM viewModel); Task<InventoryVM> PostPutLotBin(User user, InventoryVM viewModel);
Task<InventoryVM> PostPutReqApproval(User user, InventoryVM viewModel); Task<InventoryVM> PostPutReqApproval(User user, InventoryVM viewModel);

View File

@ -0,0 +1,18 @@
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

@ -0,0 +1,22 @@
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

@ -0,0 +1,20 @@
using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.ViewModel.Inventory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.Inventory
{
public interface IRIS
{
Task<ApiResponse<object>> ApproveRIS(ApproveRISRequest request, CancellationToken ct);
Task<ApiResponse<object>> CancelRIS(CancelRISRequest request, CancellationToken ct);
Task<ApiResponse<object>> CreateRIS(CreateRISRequest request, CancellationToken ct);
Task<RISPagedResponse> GetRISPaged(RISPagedRequest request, CancellationToken ct);
}
}

View File

@ -13,7 +13,8 @@ namespace CPRNIMS.Domain.UIContracts.Items
{ {
public interface IItem public interface IItem
{ {
Task<List<ItemVM>> GetItemList(User user, ItemVM viewModel); Task<PagedResult<ItemVM>> GetItemList(
User user, ItemVM viewModel);
Task<List<ItemVM>> GetItemDetail(User user, ItemVM viewModel); Task<List<ItemVM>> GetItemDetail(User user, ItemVM viewModel);
Task<List<ItemVM>> GetItemCateg(User user, ItemVM viewModel); Task<List<ItemVM>> GetItemCateg(User user, ItemVM viewModel);
Task<List<ItemVM>> GetItemLocalization(User userd, ItemVM viewModel); Task<List<ItemVM>> GetItemLocalization(User userd, ItemVM viewModel);
@ -21,6 +22,7 @@ namespace CPRNIMS.Domain.UIContracts.Items
Task<List<ItemVM>> GetItemUOM(User user, ItemVM viewModel); Task<List<ItemVM>> GetItemUOM(User user, ItemVM viewModel);
Task<List<ItemVM>> GetDepartment(User user, ItemVM viewModel); Task<List<ItemVM>> GetDepartment(User user, ItemVM viewModel);
Task<List<ItemVM>> GetItemCart(User user, ItemVM viewModel); Task<List<ItemVM>> GetItemCart(User user, ItemVM viewModel);
Task<List<ItemVM>?> GetProjectCodeByTerm(User user, ItemVM viewModels);
Task<ItemVM> PostPurchRequest(User user, ItemVM viewModel); Task<ItemVM> PostPurchRequest(User user, ItemVM viewModel);
Task<ItemVM> PostPutItem(User user, ItemVM viewModel); Task<ItemVM> PostPutItem(User user, ItemVM viewModel);
Task<ItemVM> PutItemDetail(User user, ItemVM viewModel); Task<ItemVM> PutItemDetail(User user, ItemVM viewModel);

View File

@ -0,0 +1,14 @@
using CPRNIMS.Infrastructure.Entities.PO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.PO
{
public interface ICustomPOService
{
Task<POFormData> GetPOFormDataAsync(long? poId = null);
}
}

View File

@ -8,9 +8,10 @@ using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.PO 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);
@ -40,6 +41,8 @@ namespace CPRNIMS.Domain.UIContracts.PO
Task<List<POVM>?> GetIndexCard(User user, POVM viewModel); Task<List<POVM>?> GetIndexCard(User user, POVM viewModel);
Task<List<POVM>?> GetPortOfDischarge(User user, POVM viewModels); Task<List<POVM>?> GetPortOfDischarge(User user, POVM viewModels);
Task<List<POVM>?> GetIncomingShipment(User user, POVM viewModels); Task<List<POVM>?> GetIncomingShipment(User user, POVM viewModels);
Task<List<POVM>?> GetPOListByTerm(User user, POVM viewModels);
Task<List<POVM>?> GetIncotermsByName(User user, POVM viewModels);
#endregion #endregion
#region Post Put #region Post Put
Task<POVM> PostApprovedSupplier(User user, POVM viewModel); Task<POVM> PostApprovedSupplier(User user, POVM viewModel);

View File

@ -1,6 +1,5 @@
using CPRNIMS.Infrastructure.Dto.Items; using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.ViewModel.Items;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,21 +11,28 @@ namespace CPRNIMS.Domain.UIContracts.PR
{ {
public interface IPRequest public interface IPRequest
{ {
#region Get
Task<PagedResult<PRVM>> GetAllPR(User user, PRVM viewModel);
Task<PagedResult<PRVM>> GetDetailedPRTracking(User user, PRVM viewModel);
Task<PagedResult<PRVM>> GetPRArchived(User user, PRVM viewModel);
Task<PagedResult<PRVM>> GetApprovedPR(User user, PRVM viewModels);
Task<PagedResult<PRVM>> GetDeletedPR(User user, PRVM viewModels);
Task<List<PRVM>?> GetApproverName(User user, PRVM viewModels); Task<List<PRVM>?> GetApproverName(User user, PRVM viewModels);
Task<List<PRVM>?> GetApproverNameByPRNo(User user, PRVM viewModels);
Task<List<PRVM>> GetForReceiving(User user, PRVM viewModel); Task<List<PRVM>> GetForReceiving(User user, PRVM viewModel);
Task<List<PRVM>> GetItemDetailForReceiving(User user, PRVM viewModel); Task<List<PRVM>> GetItemDetailForReceiving(User user, PRVM viewModel);
Task<List<PRVM>> GetDashBoard(User user, PRVM viewModel); Task<List<PRVM>> GetDashBoard(User user, PRVM viewModel);
Task<List<PRVM>> GetPRByRRId(User user, PRVM viewModel); Task<List<PRVM>> GetPRByRRId(User user, PRVM viewModel);
Task<List<PRVM>> GetRRDetailByPO(User user, PRVM viewModel); Task<List<PRVM>> GetRRDetailByPO(User user, PRVM viewModel);
Task<List<PRVM>> GetPRStatusById(User user, PRVM viewModel); Task<List<PRVM>> GetPRStatusById(User user, PRVM viewModel);
Task<List<PRVM>> GetAllPR(User user, PRVM viewModel);
Task<List<PRVM>> GetPRArchived(User user, PRVM viewModel);
Task<List<PRVM>> GetMyPR(User user, PRVM viewModel); Task<List<PRVM>> GetMyPR(User user, PRVM viewModel);
Task<List<PRVM>> GetPRDetailByPRNo(User user, PRVM viewModel); Task<List<PRVM>> GetPRDetailByPRNo(User user, PRVM viewModel);
Task<List<PRVM>?> GetPRListByPRNo(User user, PRVM viewModels); Task<List<PRVM>?> GetPRListByPRNo(User user, PRVM viewModels);
Task<List<PRVM>?> GetDetailedPRTracking(User user, PRVM viewModel);
Task<List<PRVM>?> GetSupplierAlternativeOffer(User user, PRVM viewModel); Task<List<PRVM>?> GetSupplierAlternativeOffer(User user, PRVM viewModel);
Task<List<PRVM>?> GetSupplierAlterOfferDetails(User user, PRVM viewModel); Task<List<PRVM>?> GetSupplierAlterOfferDetails(User user, PRVM viewModel);
Task<List<PRVM>?> GetProjectCodes(User user, PRVM viewModels);
#endregion
#region Post Put
Task<PRVM> PostPRApproveReject(User user, PRVM viewModel); Task<PRVM> PostPRApproveReject(User user, PRVM viewModel);
Task<PRVM> PostPutItemReceiving(User user, PRVM viewModel); Task<PRVM> PostPutItemReceiving(User user, PRVM viewModel);
Task<PRVM> PutItemDetail(User user, PRVM viewModel); Task<PRVM> PutItemDetail(User user, PRVM viewModel);
@ -36,5 +42,10 @@ namespace CPRNIMS.Domain.UIContracts.PR
Task<PRVM> PutAlternativeOffer(User user, PRVM viewModel); Task<PRVM> PutAlternativeOffer(User user, PRVM viewModel);
Task<PRVM> PutSupplierAlterOffer(User user, PRVM viewModel); Task<PRVM> PutSupplierAlterOffer(User user, PRVM viewModel);
Task<PRVM> PRItemRemoval(User user, PRVM viewModel); Task<PRVM> PRItemRemoval(User user, PRVM viewModel);
Task<PRVM> ApprovedSelectedPRItem(User user, PRVM viewModel);
Task<PRVM> PostPutProjectCode(User user, PRVM viewModel);
Task<PRVM> PostPutAttachment(User user, PRVM prVM);
Task<PRVM> PostItemInPR(User user, PRVM viewModel);
#endregion
} }
} }

View File

@ -1,5 +1,6 @@
using CPRNIMS.Domain.UIContracts.Canvass; using CPRNIMS.Domain.UIContracts.Canvass;
using CPRNIMS.Domain.UIContracts.Common; using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.Models.Common; using CPRNIMS.Infrastructure.Models.Common;
@ -123,6 +124,54 @@ namespace CPRNIMS.Domain.UIServices.Canvass
throw; throw;
} }
} }
public async Task<PagedResult<CanvassVM>> SendGetPageListApiRequest
(User user, CanvassVM viewModel, string apiEndpoint)
{
var token = await _tokenHelper.GetValidTokenAsync();
try
{
if (string.IsNullOrEmpty(token))
{
return null;
}
viewModel.UserId = user.UserId;
var jsonContent = JsonSerializer.Serialize(viewModel);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
using (var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token))
{
HttpResponseMessage response;
response = await httpClient.PostAsync(apiEndpoint, content);
var jsonResponse = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
viewModel.messCode = 1;
var result = JsonSerializer.Deserialize<PagedResult<CanvassVM>>(jsonResponse, options);
return result;
}
else
{
var result = JsonSerializer.Deserialize<PagedResult<CanvassVM>>(jsonResponse);
viewModel.messCode = 0;
viewModel.errMessage = "Bad request";
return result;
}
}
}
catch (Exception ex)
{
throw;
}
}
#endregion #endregion
#region Get #region Get
@ -135,12 +184,7 @@ namespace CPRNIMS.Domain.UIServices.Canvass
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:GetSupplierBidByItem"]); _configuration["LLI:NonInvent:CanvassMgmt:GetSupplierBidByItem"]);
} }
public async Task<List<CanvassVM>> GetCanvassPerSupplier(User user, CanvassVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:GetCanvassPerSupplier"]);
}
public async Task<List<CanvassVM>> GetCanvassPerSupplierEmail(User user, CanvassVM viewModel) public async Task<List<CanvassVM>> GetCanvassPerSupplierEmail(User user, CanvassVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
@ -236,6 +280,16 @@ namespace CPRNIMS.Domain.UIServices.Canvass
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:GetAlternativeOfferByPRDetailId"]); _configuration["LLI:NonInvent:CanvassMgmt:GetAlternativeOfferByPRDetailId"]);
} }
public async Task<PagedResult<CanvassVM>> GetCanvassPerSupplier(User user, CanvassVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:GetCanvassPerSupplier"]);
}
public async Task<PagedResult<CanvassVM>> GetItemsForTagging(User user, CanvassVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:GetItemsForTagging"]);
}
#endregion #endregion
#region Post Put #region Post Put
public async Task<CanvassVM> PostCanvass(User user, CanvassVM viewModel) public async Task<CanvassVM> PostCanvass(User user, CanvassVM viewModel)
@ -288,6 +342,19 @@ namespace CPRNIMS.Domain.UIServices.Canvass
return await SendPostApiRequest(user, viewModel, return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:UnlockFormLink"]); _configuration["LLI:NonInvent:CanvassMgmt:UnlockFormLink"]);
} }
public async Task<CanvassVM> StartCanvass(User user, CanvassVM viewModel)
{
return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:StartCanvass"]);
}
public async Task<CanvassVM> PostSupplierForCanvass(User user, CanvassVM viewModel)
{
return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:CanvassMgmt:PostSupplierForCanvass"]);
}
#endregion #endregion
} }
} }

View File

@ -1,9 +1,11 @@
using CPRNIMS.Domain.UIContracts.Common; using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Domain.UIContracts.Inventory; using CPRNIMS.Domain.UIContracts.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.Models.Common; using CPRNIMS.Infrastructure.Models.Common;
using CPRNIMS.Infrastructure.ViewModel.Finance;
using CPRNIMS.Infrastructure.ViewModel.Inventory; using CPRNIMS.Infrastructure.ViewModel.Inventory;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System; using System;
@ -123,6 +125,73 @@ namespace CPRNIMS.Domain.UIServices.Inventory
throw; throw;
} }
} }
public async Task<TransactContextDto?> GetTransactContextAsync(int inventoryId)
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
return null;
var apiEndpoint =
_configuration["LLI:NonInvent:InventoryMgmt:GetTransactContext"] ?? "api/InventoryMgmt/GetTransactContext";
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
var response = await httpClient.GetAsync( $"{apiEndpoint}?inventoryId={inventoryId}");
if (!response.IsSuccessStatusCode)
return null;
var jsonResponse = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<TransactContextDto>(jsonResponse,
new JsonSerializerOptions{PropertyNameCaseInsensitive = true});
}
public async Task<Infrastructure.Dto.Inventory.PagedResult<InventoryResponse>> SendGetPageListApiRequest
(User user, InventoryRequest request, string apiEndpoint)
{
var token = await _tokenHelper.GetValidTokenAsync();
try
{
if (string.IsNullOrEmpty(token))
{
return null;
}
request.UserId = user.UserId;
var jsonContent = JsonSerializer.Serialize(request);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
using (var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token))
{
HttpResponseMessage response;
response = await httpClient.PostAsync(apiEndpoint, content);
var jsonResponse = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var result = JsonSerializer.Deserialize<PagedResult<InventoryResponse>>(jsonResponse, options);
return result ?? new PagedResult<InventoryResponse>();
}
else
{
return new PagedResult<InventoryResponse>
{
IsSuccess = false,
ErrorMessage = $"API returned {response.StatusCode}"
};
}
}
}
catch (Exception ex)
{
throw;
}
}
#endregion #endregion
#region Get #region Get
public async Task<List<InventoryVM>> GetInventoryById(User user, InventoryVM viewModel) public async Task<List<InventoryVM>> GetInventoryById(User user, InventoryVM viewModel)
@ -141,7 +210,11 @@ namespace CPRNIMS.Domain.UIServices.Inventory
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:InventoryMgmt:GetLotNoById"]); _configuration["LLI:NonInvent:InventoryMgmt:GetLotNoById"]);
} }
public async Task<Infrastructure.Dto.Inventory.PagedResult<InventoryResponse>> GetInventory(User user, InventoryRequest reqquest)
{
return await SendGetPageListApiRequest(user, reqquest,
_configuration["LLI:NonInvent:InventoryMgmt:GetInventory"]);
}
public async Task<List<InventoryVM>> GetInventoryByUserId(User user, InventoryVM viewModel) public async Task<List<InventoryVM>> GetInventoryByUserId(User user, InventoryVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
@ -153,7 +226,11 @@ namespace CPRNIMS.Domain.UIServices.Inventory
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:InventoryMgmt:GetRequestedItemByUserId"]); _configuration["LLI:NonInvent:InventoryMgmt:GetRequestedItemByUserId"]);
} }
public async Task<List<InventoryVM>> GetLotQtyByItem(User user, InventoryVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:InventoryMgmt:GetLotQtyByItem"]);
}
#endregion #endregion
#region Post Put #region Post Put
public async Task<InventoryVM> PostPutReqApproval(User user, InventoryVM viewModel) public async Task<InventoryVM> PostPutReqApproval(User user, InventoryVM viewModel)
@ -177,12 +254,6 @@ namespace CPRNIMS.Domain.UIServices.Inventory
return await SendPostApiRequest(user, viewModel, return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:InventoryMgmt:PostPutReqItems"]); _configuration["LLI:NonInvent:InventoryMgmt:PostPutReqItems"]);
} }
public async Task<List<InventoryVM>> GetLotQtyByItem(User user, InventoryVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:InventoryMgmt:GetLotQtyByItem"]);
}
#endregion #endregion
} }
} }

View File

@ -0,0 +1,126 @@
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

@ -0,0 +1,197 @@
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

@ -0,0 +1,157 @@
using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Domain.UIContracts.Inventory;
using CPRNIMS.Infrastructure.Dto.Common;
using CPRNIMS.Infrastructure.Dto.Inventory.Request;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Dto.PR.Response;
using CPRNIMS.Infrastructure.Helper;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIServices.Inventory
{
public class RIS : IRIS
{
private readonly IConfiguration _configuration;
private readonly TokenHelper _tokenHelper;
private readonly IApiConfigurationService _apiConfigurationService;
public RIS(IConfiguration configuration, TokenHelper tokenHelper,
IApiConfigurationService apiConfigurationService)
{
_configuration = configuration;
_tokenHelper = tokenHelper;
_apiConfigurationService = apiConfigurationService;
}
#region Get
public async Task<RISPagedResponse> GetRISPaged(RISPagedRequest 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:GetRIS"]
?? throw new InvalidOperationException("GetRIS endpoint is not configured.");
// ── Build query string — GET request, no body ──
var qs = new StringBuilder(baseEndpoint).Append('?');
qs.Append($"pageNumber={request.PageNumber}");
qs.Append($"&pageSize={request.PageSize}");
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.SearchIssuedTo))
qs.Append($"&searchIssuedTo={Uri.EscapeDataString(request.SearchIssuedTo)}");
if (!string.IsNullOrWhiteSpace(request.Discipline))
qs.Append($"&discipline={Uri.EscapeDataString(request.Discipline)}");
if (request.Status.HasValue)
qs.Append($"&status={request.Status.Value}");
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
// ── GET, no content body ──
var response = await httpClient.GetAsync(qs.ToString(), ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
{
Console.WriteLine($"[GetRISPaged] Error {(int)response.StatusCode}: {json}");
return new RISPagedResponse { Data = [], RecordsTotal = 0 };
}
var result = JsonSerializer.Deserialize<RISPagedResponse>(json, _jsonOptions);
return result ?? new RISPagedResponse();
}
#endregion
#region Post Put
public async Task<ApiResponse<object>> ApproveRIS(ApproveRISRequest 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:ApproveRIS"]
?? throw new InvalidOperationException("ApproveRIS endpoint is not configured.");
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(JsonSerializer.Serialize(request),Encoding.UTF8,"application/json");
var response = await httpClient.PutAsync(endpoint, content, 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)
result.success = false;
return result;
}
public async Task<ApiResponse<object>> CancelRIS(CancelRISRequest 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:CancelRIS"]
?? throw new InvalidOperationException("CancelRIS endpoint is not configured.");
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync(endpoint, content, 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)
result.success = false;
return result;
}
public async Task<ApiResponse<object>> CreateRIS(CreateRISRequest 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:CreateRIS"] ??
throw new InvalidOperationException("CreateRIS endpoint is not configured.");
using var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token);
using var content = new StringContent(JsonSerializer.Serialize(request),Encoding.UTF8,"application/json");
var response = await httpClient.PostAsync(endpoint, content,ct);
var json = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse<object>>(json, _jsonOptions)
?? new ApiResponse<object> { success = false, message = $"HTTP {(int)response.StatusCode}" };
if (!response.IsSuccessStatusCode)
result.success = false;
return result;
}
private static readonly JsonSerializerOptions _jsonOptions = new()
{
PropertyNameCaseInsensitive = true
};
#endregion
}
}

View File

@ -1,5 +1,6 @@
using CPRNIMS.Domain.UIContracts.Common; using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Domain.UIContracts.Items; using CPRNIMS.Domain.UIContracts.Items;
using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.Models.Common; using CPRNIMS.Infrastructure.Models.Common;
@ -31,7 +32,61 @@ namespace CPRNIMS.Domain.UIServices.Items
_apiConfigurationService = apiConfigurationService; _apiConfigurationService = apiConfigurationService;
} }
#region SendRequest service #region SendRequest service
public async Task<PagedResult<ItemVM>> GetItemList(
Infrastructure.Models.Account.User user, ItemVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:ItemMgmt:GetItemList"]);
}
public async Task<PagedResult<ItemVM>> SendGetPageListApiRequest
(Infrastructure.Models.Account.User user,ItemVM viewModel,string apiEndpoint)
{
var token = await _tokenHelper.GetValidTokenAsync();
try
{
if (string.IsNullOrEmpty(token))
{
// Handle token retrieval failure
return null;
}
viewModel.UserId = user.UserId;
var jsonContent = JsonSerializer.Serialize(viewModel);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
using (var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token))
{
HttpResponseMessage response;
response = await httpClient.PostAsync(apiEndpoint, content);
var jsonResponse = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
viewModel.messCode = 1;
var myArtWork = JsonSerializer.Deserialize<PagedResult<ItemVM>>(jsonResponse, options);
return myArtWork;
}
else
{
var myArtWork = JsonSerializer.Deserialize<PagedResult<ItemVM>>(jsonResponse);
viewModel.messCode = 0;
viewModel.message = "Bad request";
return myArtWork;
}
}
}
catch (Exception ex)
{
throw;
}
}
public async Task<ItemVM> SendPostApiRequest(Infrastructure.Models.Account.User user, public async Task<ItemVM> SendPostApiRequest(Infrastructure.Models.Account.User user,
ItemVM viewModel, string apiEndpoint) ItemVM viewModel, string apiEndpoint)
{ {
@ -129,6 +184,11 @@ namespace CPRNIMS.Domain.UIServices.Items
} }
#endregion #endregion
#region Get Method #region Get Method
public async Task<List<ItemVM>> GetProjectCodeByTerm(Infrastructure.Models.Account.User user, ItemVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:ItemMgmt:GetProjectCodeByTerm"]);
}
public async Task<List<ItemVM>> GetItemDetail(Infrastructure.Models.Account.User user, public async Task<List<ItemVM>> GetItemDetail(Infrastructure.Models.Account.User user,
ItemVM viewModel) ItemVM viewModel)
{ {
@ -141,13 +201,13 @@ namespace CPRNIMS.Domain.UIServices.Items
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:ItemMgmt:GetItemCart"]); _configuration["LLI:NonInvent:ItemMgmt:GetItemCart"]);
} }
public async Task<List<ItemVM>> GetItemList(Infrastructure.Models.Account.User user, /* public async Task<List<ItemVM>> GetItemList(Infrastructure.Models.Account.User user,
ItemVM viewModel) ItemVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:ItemMgmt:GetItemList"]); _configuration["LLI:NonInvent:ItemMgmt:GetItemList"]);
} }
*/
public async Task<List<ItemVM>> GetItemCateg(Infrastructure.Models.Account.User user, ItemVM viewModel) public async Task<List<ItemVM>> GetItemCateg(Infrastructure.Models.Account.User user, ItemVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,

View File

@ -0,0 +1,76 @@
using CPRNIMS.Domain.UIContracts.PO;
using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Helper;
using Google.Apis.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIServices.PO
{
public class CustomPOService : ICustomPOService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly TokenHelper _tokenHelper;
private readonly IConfiguration _configuration;
private readonly ILogger<CustomPOService> _logger;
public CustomPOService(
IHttpClientFactory httpClientFactory,
TokenHelper tokenHelper,
IConfiguration configuration,
ILogger<CustomPOService> logger)
{
_httpClientFactory = httpClientFactory;
_tokenHelper = tokenHelper;
_configuration = configuration;
_logger = logger;
}
public async Task<POFormData> GetPOFormDataAsync(long? poId = null)
{
try
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new UnauthorizedAccessException("No valid token available.");
var httpClient = _httpClientFactory.CreateClient("AuthApi");
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
var url = _configuration["LLI:NonInvent:POMgmt:GetPOFormData"];
if (poId.HasValue)
url += $"?poId={poId}";
var response = await httpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
_logger.LogError("GetPOFormData failed: {StatusCode}", response.StatusCode);
return new POFormData();
}
var json = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<POFormData>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
return result ?? new POFormData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in GetPOFormDataAsync");
return new POFormData();
}
}
}
}

View File

@ -126,6 +126,17 @@ namespace CPRNIMS.Domain.UIServices.PO
#endregion #endregion
#region Get #region Get
public async Task<List<POVM>?> GetIncotermsByName(User user, POVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:POMgmt:GetIncotermsByName"]);
}
public async Task<List<POVM>?> GetPOListByTerm(User user, POVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:POMgmt:GetPOListByTerm"]);
}
public async Task<List<POVM>?> GetIncomingShipment(User user, POVM viewModel) public async Task<List<POVM>?> GetIncomingShipment(User user, POVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
@ -273,6 +284,11 @@ 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

@ -1,5 +1,6 @@
using CPRNIMS.Domain.UIContracts.Common; using CPRNIMS.Domain.UIContracts.Common;
using CPRNIMS.Domain.UIContracts.PR; using CPRNIMS.Domain.UIContracts.PR;
using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Account; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.Models.Common; using CPRNIMS.Infrastructure.Models.Common;
@ -7,7 +8,6 @@ using CPRNIMS.Infrastructure.ViewModel.PR;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIServices.PR namespace CPRNIMS.Domain.UIServices.PR
{ {
@ -116,15 +116,95 @@ namespace CPRNIMS.Domain.UIServices.PR
} }
#endregion #endregion
#region Get #region Get
public async Task<List<PRVM>?> GetProjectCodes(User user, PRVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetProjectCodes"]);
}
public async Task<List<PRVM>?> GetApproverName(User user, PRVM viewModel) public async Task<List<PRVM>?> GetApproverName(User user, PRVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetApproverName"]); _configuration["LLI:NonInvent:PRMgmt:GetApproverName"]);
} }
public async Task<List<PRVM>> GetAllPR(User user, PRVM viewModel) public async Task<List<PRVM>?> GetApproverNameByPRNo(User user, PRVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetAllPR"]); _configuration["LLI:NonInvent:PRMgmt:GetApproverNameByPRNo"]);
}
public async Task<PagedResult<PRVM>> GetAllPR(
User user, PRVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetAllPR"]);
}
public async Task<PagedResult<PRVM>> GetPRArchived(
User user, PRVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetPRArchived"]);
}
public async Task<PagedResult<PRVM>> GetDeletedPR(User user, PRVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetDeletedPR"]);
}
public async Task<PagedResult<PRVM>> GetApprovedPR(User user, PRVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetApprovedPR"]);
}
public async Task<PagedResult<PRVM>> GetDetailedPRTracking(User user, PRVM viewModel)
{
return await SendGetPageListApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetDetailedPRTracking"]);
}
public async Task<PagedResult<PRVM>> SendGetPageListApiRequest
(User user, PRVM viewModel, string apiEndpoint)
{
var token = await _tokenHelper.GetValidTokenAsync();
try
{
if (string.IsNullOrEmpty(token))
{
return null;
}
viewModel.UserId = user.UserId;
var jsonContent = JsonSerializer.Serialize(viewModel);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
using (var httpClient = _apiConfigurationService.CreateHttpClientWithDefaultHeaders(token))
{
HttpResponseMessage response;
response = await httpClient.PostAsync(apiEndpoint, content);
var jsonResponse = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
viewModel.messCode = 1;
var myArtWork = JsonSerializer.Deserialize<PagedResult<PRVM>>(jsonResponse, options);
return myArtWork;
}
else
{
var myArtWork = JsonSerializer.Deserialize<PagedResult<PRVM>>(jsonResponse);
viewModel.messCode = 0;
viewModel.message = "Bad request";
return myArtWork;
}
}
}
catch (Exception ex)
{
throw;
}
} }
public async Task<List<PRVM>> GetMyPR(User user, PRVM viewModel) public async Task<List<PRVM>> GetMyPR(User user, PRVM viewModel)
{ {
@ -166,21 +246,11 @@ namespace CPRNIMS.Domain.UIServices.PR
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetDashBoard"]); _configuration["LLI:NonInvent:PRMgmt:GetDashBoard"]);
} }
public async Task<List<PRVM>> GetPRArchived(User user, PRVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetPRArchived"]);
}
public async Task<List<PRVM>?> GetPRListByPRNo(User user, PRVM viewModel) public async Task<List<PRVM>?> GetPRListByPRNo(User user, PRVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetPRListByPRNo"]); _configuration["LLI:NonInvent:PRMgmt:GetPRListByPRNo"]);
} }
public async Task<List<PRVM>?> GetDetailedPRTracking(User user, PRVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetDetailedPRTracking"]);
}
public async Task<List<PRVM>?> GetSupplierAlternativeOffer(User user, PRVM viewModel) public async Task<List<PRVM>?> GetSupplierAlternativeOffer(User user, PRVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
@ -248,6 +318,29 @@ namespace CPRNIMS.Domain.UIServices.PR
return await SendPostApiRequest(user, viewModel, return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:PRItemRemoval"]); _configuration["LLI:NonInvent:PRMgmt:PRItemRemoval"]);
} }
public async Task<PRVM> ApprovedSelectedPRItem(User user, PRVM viewModel)
{
return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:ApprovedSelectedPRItem"]);
}
public async Task<PRVM> PostPutProjectCode(User user, PRVM viewModel)
{
return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:PostPutProjectCode"]);
}
public async Task<PRVM> PostPutAttachment(User user, PRVM prVM)
{
return await SendPostApiRequest(user, prVM,
_configuration["LLI:NonInvent:PRMgmt:PostPutAttachment"]);
}
public async Task<PRVM> PostItemInPR(User user, PRVM prVM)
{
return await SendPostApiRequest(user, prVM,
_configuration["LLI:NonInvent:PRMgmt:PostItemInPR"]);
}
#endregion #endregion
} }
} }

View File

@ -23,4 +23,8 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Dto\PR\Request\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,6 @@
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Dto.Canvass.Response;
using CPRNIMS.Infrastructure.Dto.Inventory.Response;
using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Canvass; using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.Finance; using CPRNIMS.Infrastructure.Entities.Finance;
@ -21,9 +23,7 @@ namespace CPRNIMS.Infrastructure.Database
public class NonInventoryDbContext : IdentityDbContext<ApplicationUser> public class NonInventoryDbContext : IdentityDbContext<ApplicationUser>
{ {
public NonInventoryDbContext(DbContextOptions<NonInventoryDbContext> options) : base(options) { } public NonInventoryDbContext(DbContextOptions<NonInventoryDbContext> options) : base(options) { }
public virtual DbSet<ItemCode> ItemCodes { get; set; } #region Common
public virtual DbSet<ItemList> ItemList { get; set; }
public virtual DbSet<Item> Items { get; set; }
public DbSet<Departments> Departments { get; set; } public DbSet<Departments> Departments { get; set; }
public DbSet<IdentityRole> IdentityRoles { get; set; } public DbSet<IdentityRole> IdentityRoles { get; set; }
public DbSet<AuthorizeRoles> AuthorizeRoles { get; set; } public DbSet<AuthorizeRoles> AuthorizeRoles { get; set; }
@ -31,35 +31,57 @@ namespace CPRNIMS.Infrastructure.Database
public DbSet<IdentityUserRole<string>> IdentityUserRoles { get; set; } public DbSet<IdentityUserRole<string>> IdentityUserRoles { get; set; }
public DbSet<ForgotPassword> ForgotPasswords { get; set; } public DbSet<ForgotPassword> ForgotPasswords { get; set; }
public virtual DbSet<Otps> Otps { get; set; } public virtual DbSet<Otps> Otps { get; set; }
public virtual DbSet<ErrorMessage> ErrorMessages { get; set; }
public virtual DbSet<ControllerAccess> ControllerAccess { get; set; }
public virtual DbSet<SMTPCredential> SMTPCredentials { get; set; }
#endregion
#region Item
public virtual DbSet<ItemCode> ItemCodes { get; set; }
public virtual DbSet<ItemList> ItemList { 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; }
public virtual DbSet<ItemAttachement> ItemAttachements { get; set; } public virtual DbSet<ItemAttachement> ItemAttachements { get; set; }
public virtual DbSet<ErrorMessage> ErrorMessages { get; set; }
public virtual DbSet<ControllerAccess> ControllerAccess { get; set; }
public virtual DbSet<ItemCategory> ItemCategories { get; set; } public virtual DbSet<ItemCategory> ItemCategories { get; set; }
public virtual DbSet<UnitOfMessure> UnitOfMessures { get; set; } public virtual DbSet<UnitOfMessure> UnitOfMessures { get; set; }
public virtual DbSet<ItemColor> ItemColors { get; set; } public virtual DbSet<ItemColor> ItemColors { get; set; }
public virtual DbSet<ItemLocalization> ItemLocalizations { get; set; } public virtual DbSet<ItemLocalization> ItemLocalizations { get; set; }
public virtual DbSet<ItemCart> ItemCarts { get; set; } public virtual DbSet<ItemCart> ItemCarts { get; set; }
public virtual DbSet<ItemApproval> ItemApprovals { get; set; }
public virtual DbSet<Entities.Inventory.ItemDetail> ItemDetails { get; set; }
#endregion
#region PR
public virtual DbSet<PR> PRs { get; set; } public virtual DbSet<PR> PRs { get; set; }
public virtual DbSet<Approved> Approved { get; set; } public virtual DbSet<Approved> Approved { get; set; }
public virtual DbSet<SMTPCredential> SMTPCredentials { get; set; } public virtual DbSet<ApprovedPR> ApprovedPrs { get; set; }
public virtual DbSet<DeletedPR> DeletedPRs { get; set; }
public virtual DbSet<PRDetails> PRDetails { get; set; } public virtual DbSet<PRDetails> PRDetails { get; set; }
public virtual DbSet<PRItemList> PRItemLists { get; set; }
public DbSet<PRAttachments> PRAttachments { get; set; }
public DbSet<ProjectCodes> ProjectCodes { get; set; }
public virtual DbSet<Entities.Purchasing.PRList> PRLists { get; set; }
public virtual DbSet<Entities.Canvass.PRList> PRItemList { get; set; }
public virtual DbSet<PRWOCanvass> PRWOCanvasses { get; set; }
public virtual DbSet<Entities.PO.ItemDetail> PRItemDetails { get; set; }
public virtual DbSet<DetailedPRTracking> DetailedPRTrackings { get; set; }
public virtual DbSet<PRTracking> PRTrackings { get; set; }
public virtual DbSet<Dashboard> Dashboards { get; set; }
#endregion
#region Canvassing
public virtual DbSet<NotificationById> NotificationByIds { get; set; } public virtual DbSet<NotificationById> NotificationByIds { get; set; }
public virtual DbSet<AlternativeOffer> AlternativeOffers { get; set; } public virtual DbSet<AlternativeOffer> AlternativeOffers { get; set; }
public virtual DbSet<AlternativeOfferDetails> AlternativeOfferDetails { get; set; } public virtual DbSet<AlternativeOfferDetails> AlternativeOfferDetails { get; set; }
public virtual DbSet<MyPRWOCanvass> MyPRWOCanvass { get; set; } public virtual DbSet<MyPRWOCanvass> MyPRWOCanvass { get; set; }
public virtual DbSet<Entities.Purchasing.PRList> PRLists { get; set; }
public virtual DbSet<Entities.Canvass.PRList> PRItemList { get; set; }
public virtual DbSet<ItemApproval> ItemApprovals { get; set; }
public virtual DbSet<ForReceiving> ForReceivings { get; set; }
public virtual DbSet<Infrastructure.Entities.Receiving.RRReport> RRReports { get; set; }
public virtual DbSet<ReceivingDetail> ReceivingDetails { get; set; }
public virtual DbSet<RRDetail> RRDetails { get; set; }
public virtual DbSet<ForRR> ForRRs { get; set; }
public virtual DbSet<RR> RRs { get; set; }
public virtual DbSet<Canvass> Canvasses { get; set; } public virtual DbSet<Canvass> Canvasses { get; set; }
public DbSet<SupplierForCanvass> SupplierForCanvass { get; set; }
public DbSet<SupplierResponseDto> SupplierResponses { get; set; }
public DbSet<SupplierItems> SupplierItems { get; set; }
public DbSet<ItemsForTagging> ItemsForTaggings { get; set; }
public virtual DbSet<ForCanvassFollowUp> ForCanvassFollowUps { get; set; } public virtual DbSet<ForCanvassFollowUp> ForCanvassFollowUps { get; set; }
public virtual DbSet<WOResponse> WOResponses { get; set; } public virtual DbSet<WOResponse> WOResponses { get; set; }
public virtual DbSet<WOResponseById> WOResponseByIds { get; set; } public virtual DbSet<WOResponseById> WOResponseByIds { get; set; }
@ -73,16 +95,23 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<CanvassSupplier> CanvassSuppliers { get; set; } public virtual DbSet<CanvassSupplier> CanvassSuppliers { get; set; }
public virtual DbSet<RFQReference> RFQReferences { get; set; } public virtual DbSet<RFQReference> RFQReferences { get; set; }
public virtual DbSet<CanvassDetail> CanvassDetails { get; set; } public virtual DbSet<CanvassDetail> CanvassDetails { get; set; }
public virtual DbSet<PRCanvassDetail> PRCanvassDetails { get; set; }
public DbSet<ForAISearchingTagging> ForAISearchingTaggings { get; set; }
public virtual DbSet<CanvassGroupByPRNo> CanvassGroupByPRNos { get; set; } public virtual DbSet<CanvassGroupByPRNo> CanvassGroupByPRNos { get; set; }
public virtual DbSet<ForCanvass> ForCanvasses { get; set; } public virtual DbSet<ForCanvass> ForCanvasses { get; set; }
#endregion
#region PO
public virtual DbSet<ForPO> ForPOs { get; set; } public virtual DbSet<ForPO> ForPOs { get; set; }
public virtual DbSet<CreatedPO> CreatedPOs { get; set; } public virtual DbSet<CreatedPO> CreatedPOs { get; set; }
public virtual DbSet<CustomPO> CustomPOs { get; set; } public virtual DbSet<CustomPO> CustomPOs { get; set; }
public virtual DbSet<IndexCard> IndexCards { get; set; } public virtual DbSet<IndexCard> IndexCards { get; set; }
public virtual DbSet<ForPOApproval> ForPOApprovals { get; set; } public virtual DbSet<ForPOApproval> ForPOApprovals { get; set; }
public virtual DbSet<ApprovedPO> ApprovedPOs { get; set; } public virtual DbSet<ApprovedPO> ApprovedPOs { get; set; }
public virtual DbSet<PurchaseOrder> PurchaseOrders { get; set; } public virtual DbSet<PurchaseOrder> PurchaseOrders { get; set; }
public virtual DbSet<ForPayment> ForPayments { get; set; }
public virtual DbSet<PO> POs { get; set; } public virtual DbSet<PO> POs { get; set; }
public DbSet<PODetails> PODetails { get; set; }
public virtual DbSet<PRPOSummaryCount> PRPOSummaryCounts { get; set; } public virtual DbSet<PRPOSummaryCount> PRPOSummaryCounts { get; set; }
public virtual DbSet<PRPOSummaryItem> PRPOSummaryItems { get; set; } public virtual DbSet<PRPOSummaryItem> PRPOSummaryItems { get; set; }
public virtual DbSet<POItemDetail> POItemDetails { get; set; } public virtual DbSet<POItemDetail> POItemDetails { get; set; }
@ -90,32 +119,49 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<PortOfDischarges> PortOfDischarges { get; set; } public virtual DbSet<PortOfDischarges> PortOfDischarges { get; set; }
public virtual DbSet<DocRequired> DocRequireds { get; set; } public virtual DbSet<DocRequired> DocRequireds { get; set; }
public virtual DbSet<BiddingApproval> BiddingApprovals { get; set; } public virtual DbSet<BiddingApproval> BiddingApprovals { get; set; }
public virtual DbSet<Entities.Receiving.RRDetail> RRDetailss { get; set; }
public virtual DbSet<RRSeries> RRSeries { get; set; }
public virtual DbSet<PRWOCanvass> PRWOCanvasses { get; set; }
public virtual DbSet<ForPayment> ForPayments { get; set; }
public virtual DbSet<Inventory> Inventories { get; set; }
public virtual DbSet<Entities.Inventory.ItemDetail> ItemDetails { get; set; }
public virtual DbSet<Entities.PO.ItemDetail> PRItemDetails { get; set; }
public virtual DbSet<Lot> Lots { get; set; }
public virtual DbSet<LotQtyByItem> LotQtyByItems { get; set; }
public virtual DbSet<RequestItem> RequestItems { get; set; }
public virtual DbSet<RequestItemDetail> RequestItemDetails { get; set; }
public virtual DbSet<NotifUserKey> NotifUserKeys { get; set; } public virtual DbSet<NotifUserKey> NotifUserKeys { get; set; }
public virtual DbSet<ItemListForPO> ItemListForPOs { get; set; } public virtual DbSet<ItemListForPO> ItemListForPOs { get; set; }
public virtual DbSet<CreatedPOPerSupId> CreatedPOPerSupIds { get; set; } public virtual DbSet<CreatedPOPerSupId> CreatedPOPerSupIds { get; set; }
public virtual DbSet<PRTracking> PRTrackings { get; set; } public DbSet<IncomingShipment> IncomingShipments { get; set; }
public virtual DbSet<Dashboard> Dashboards { get; set; } public virtual DbSet<IncomingShipmentDto> IncomingShipmentDtos { get; set; }
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 virtual DbSet<RRReport> DetailedPRTrackings { get; set; } public DbSet<Currencies> Currencies { get; set; }
public DbSet<IncomingShipment> IncomingShipments { get; set; } #endregion
public virtual DbSet<IncomingShipmentDto> IncomingShipmentDtos { get; set; }
#region Inventory
public virtual DbSet<Inventory> Inventories { get; set; }
public virtual DbSet<Lot> Lots { get; set; }
public virtual DbSet<LotType> LotTypes { get; set; }
public virtual DbSet<LotQtyByItem> LotQtyByItems { get; set; }
public virtual DbSet<RequestItem> RequestItems { get; set; }
public virtual DbSet<RequestItemDetail> RequestItemDetails { get; set; }
public virtual DbSet<RIS> RIS { get; set; }
public virtual DbSet<MRS> MRS { get; set; }
public virtual DbSet<Discipline> Disciplines { get; set; }
public virtual DbSet<InventTrans> InventTrans { get; set; }
public virtual DbSet<InventTransDetail> InventTransDetails { get; set; }
public DbSet<InventoryByIdResponse> InventoryByIdResponses { get; set; }
#endregion
#region RR
public virtual DbSet<ForReceiving> ForReceivings { get; set; }
public virtual DbSet<Infrastructure.Entities.Receiving.RRReport> RRReports { get; set; }
public virtual DbSet<ReceivingDetail> ReceivingDetails { get; set; }
public virtual DbSet<RRDetailDto> RRDetailDtos { get; set; }
public virtual DbSet<ForRR> ForRRs { get; set; }
public virtual DbSet<RR> RRs { get; set; }
public virtual DbSet<Entities.Receiving.RRDetailDto> RRDetailss { get; set; }
public virtual DbSet<Entities.Receiving.RRDetails> RRDetails { get; set; }
public virtual DbSet<RRSeries> RRSeries { get; set; }
#endregion
#region Automation Part #region Automation Part
public virtual DbSet<AllForCanvass> AllForCanvasses { get; set; } public virtual DbSet<AllForCanvass> AllForCanvasses { get; set; }
public DbSet<ItemWithoutSupplier> ItemWithoutSuppliers { get; set; }
public DbSet<ErrorLog> ErrorLogs { get; set; }
#endregion #endregion
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@ -128,7 +174,7 @@ namespace CPRNIMS.Infrastructure.Database
.Property(e => e.CanvassSupplierId) .Property(e => e.CanvassSupplierId)
.ValueGeneratedNever(); .ValueGeneratedNever();
modelBuilder.Entity<RRReport>(b => modelBuilder.Entity<DetailedPRTracking>(b =>
{ {
b.ToTable("DetailsedPRTracking"); b.ToTable("DetailsedPRTracking");
b.HasNoKey(); b.HasNoKey();
@ -143,6 +189,11 @@ namespace CPRNIMS.Infrastructure.Database
b.ToTable("PRPOSummaryItem"); b.ToTable("PRPOSummaryItem");
b.HasNoKey(); b.HasNoKey();
}); });
modelBuilder.Entity<RR>(b =>
{
b.ToTable("RR");
b.HasNoKey();
});
modelBuilder.Entity<ApplicationUser>(b => modelBuilder.Entity<ApplicationUser>(b =>
{ {
b.ToTable("Users"); b.ToTable("Users");
@ -150,7 +201,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); // Allow null if there is no attachment .IsRequired(false);
}); });
modelBuilder.Entity<Attachment>(b => modelBuilder.Entity<Attachment>(b =>
{ {
@ -158,7 +209,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); // Allow null if there is no extension .IsRequired(false);
}); });
modelBuilder.Entity<ApplicationUser>(b => modelBuilder.Entity<ApplicationUser>(b =>
{ {
@ -216,6 +267,74 @@ namespace CPRNIMS.Infrastructure.Database
{ {
b.ToTable("UserRoles"); b.ToTable("UserRoles");
}); });
modelBuilder.Entity<Inventory>()
.HasOne(i => i.Lot)
.WithMany()
.HasForeignKey(i => i.LotId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Inventory>()
.HasOne(i => i.Item)
.WithMany()
.HasForeignKey(i => i.ItemNo)
.OnDelete(DeleteBehavior.Restrict);
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);
modelBuilder.Entity<InventTransDetail>(e =>
{
e.HasOne(i => i.PRDetails)
.WithMany()
.HasForeignKey(t => t.PRDetailId)
.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 =>
{
e.HasOne(i => i.PRs)
.WithMany()
.HasForeignKey(t => t.PRId)
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<RIS>(e => {
e.HasOne(r => r.Inventory)
.WithMany()
.HasForeignKey(r => r.InventoryId)
.OnDelete(DeleteBehavior.Restrict);
e.HasOne(r => r.Discipline)
.WithMany()
.HasForeignKey(r => r.DisciplineId);
e.HasOne(r => r.ProjectCodes)
.WithMany()
.HasForeignKey(r => r.ProjectCodeId);
});
modelBuilder.Entity<MRS>(e => {
e.HasOne(m => m.RIS)
.WithMany(r => r.MaterialReturns)
.HasForeignKey(m => m.RISId)
.OnDelete(DeleteBehavior.Restrict);
});
} }
} }
} }

View File

@ -3,6 +3,7 @@ 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;
@ -20,6 +21,7 @@ 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,5 +13,6 @@ 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

@ -1,4 +1,5 @@
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Dto.Canvass.Request;
using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.ViewModel.Items; using CPRNIMS.Infrastructure.ViewModel.Items;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -9,7 +10,7 @@ using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass namespace CPRNIMS.Infrastructure.Dto.Canvass
{ {
public class CanvassDto : CommonProperties public class CanvassDto : CanvassRequestSearch
{ {
public byte PaymentTermsId { get; set; } = 0; public byte PaymentTermsId { get; set; } = 0;
public bool IsArchived { get; set; } = false; public bool IsArchived { get; set; } = false;
@ -56,7 +57,7 @@ namespace CPRNIMS.Infrastructure.Dto.Canvass
public long CanvassDetailId { get; set; } public long CanvassDetailId { get; set; }
public long CanvassId { get; set; } public long CanvassId { get; set; }
public decimal QtyRequest { get; set; } public decimal QtyRequest { get; set; }
//public byte IsApproved { get; set; } public bool IsInternational { get; set; }
public long RRDetailId { get; set; } public long RRDetailId { get; set; }
public long PRDetailId { get; set; } public long PRDetailId { get; set; }
public decimal Quantity { get; set; } public decimal Quantity { get; set; }
@ -74,6 +75,7 @@ namespace CPRNIMS.Infrastructure.Dto.Canvass
public bool IsDenied { get; set; } = false; public bool IsDenied { get; set; } = false;
public string? FullName { get; set; } public string? FullName { get; set; }
public string? Specification { get; set; } public string? Specification { get; set; }
public byte CurrencyId { get; set; } = 1; public byte CurrencyId { get; set; } = 1;
public bool VatInc { get; set; }=false; public bool VatInc { get; set; }=false;
public string? TinNo { get; set; } public string? TinNo { get; set; }

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass
{
public class CanvassItemDto
{
public long PRDetailsId { get; set; }
public long PRNo { get; set; }
public long ItemNo { get; set; }
public string ItemDescription { get; set; } = string.Empty;
public string ItemName { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass
{
public class ForCanvassDto
{
public short Status {get;set;}
public string UserId { get; set; } = string.Empty;
public int SupplierId { get; set; }
public long PRNo { get; set; }
public long ItemNo { get; set; }
public int CanvassNo { get; set; }
public long PRDetailsId { get; set; }
public string FullName { get; set; } = string.Empty;
public string? Remarks { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CPRNIMS.Infrastructure.Dto.Common;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
{
public class CanvassRequestSearch : PagedRequest
{
public string SearchPRNo { get; set; } = string.Empty;
public string SearchItemName { get; set; } = string.Empty;
public string SearchItemNo { get; set; } = string.Empty;
public string SearchCreatedBy { get; set; } = string.Empty;
public string SearchSupplier { get; set; } = string.Empty;
public string SearchDepartment { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
{
public class ForCanvassRequest
{
public string UserId { get; set; } = string.Empty;
public int SupplierId { get; set; }
public long PRNo { get; set; }
public long ItemNo { get; set; }
public int CanvassNo { get; set; }
public long PRDetailsId { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
{
public class SearchSupplierRequest
{
public long PRDetailsId { get; set; }
public long PRNo { get; set; }
public long ItemNo { get; set; }
public string ItemName { get; set; } = string.Empty;
public string ItemDescription { get; set; } = string.Empty;
public string FullName { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,18 @@
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.Canvass.Request
{
public class StartCanvassRequest
{
[JsonPropertyName("isInternational")]
public bool IsInternational { get; set; }
[JsonPropertyName("items")]
public List<CanvassItemDto> Items { get; set; } = new();
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
{
public class SupplierEmailRequest
{
public string Subject { get; set; } = string.Empty;
public string SenderEmail { get; set; } = string.Empty;
public string Recipient { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public int OutGoingPort { get; set; } = 587;
public string Password { get; set; } = string.Empty;
public string Token { get; set; } = string.Empty;
public string Server { get; set; } = string.Empty;
public string CC { get; set; } = string.Empty;
public bool IsCanvass { get; set; }
public string Purchaser { get; set; }=string.Empty;
public string UserName { get; set; } = string.Empty;
public string FormLink { get; set; } = string.Empty;
public string EmailAddress { get; set; } = string.Empty;
public string SupplierName { get; set; } = string.Empty;
public bool IsSuccess { get; set; }
public string AttachPath { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
{
public class SupplierRequest
{
public string SupplierName { get; set; } = string.Empty;
public string EmailAddress { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
public string ContactNo { get; set; } = string.Empty;
public string ContactPerson { get; set; } = string.Empty;
public string LeadTime { get; set; } = string.Empty;
public bool IsVatable { get; set; } = false;
public byte PaymentTermsId { get; set; } = 1;
public byte CurrencyId { get; set; } = 1;
public string TinNo { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public long ItemNo { get; set; } = 0;
public string Website { get; set; } = string.Empty;
public int SupplierId { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Response
{
public class SearchSupplierResponse
{
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Response
{
public class StartCanvassResponse
{
public Guid Id { get; set; }
public bool IsInternational { get; set; }
public string UserId { get; set; } = string.Empty;
public List<CanvassItemDto> Items { get; set; } = new();
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Response
{
public class SupplierResponse
{
public int SupplierId { get; set; }
public string SupplierName { get; set; } = string.Empty;
public string? EmailAddress { get; set; }
public bool IsActive { get; set; }
public string? ContactNo { get; set; }
public string? ContactPerson { get; set; }
public string? LeadTime { get; set; }
public bool? IsVatable { get; set; }
public byte? PaymentTermsId { get; set; }
public byte? CurrencyId { get; set; }
public string? TinNo { get; set; }
public string? Address { get; set; }
public string? Website { get; set; }
public bool VatInc { get; set; }
public string Currency { get; set; }=string.Empty;
public string PaymentTerms { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Response
{
public class SupplierResponseDto
{
[Key]
public int SupplierId { get; set; }
public string? SupplierName { get; set; }
public string? EmailAddress { get; set; }
public string? ContactNo { get; set; }
public string? ContactPerson { get; set; }
public string? LeadTime { get; set; }
public bool VatInc { get; set; }
public string? Currency { get; set; }
public string? PaymentTerms { get; set; }
public byte PaymentTermsId { get; set; }
public byte CurrencyId { get; set; }
public string? TinNo { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Canvass.Result
{
public class GroqSupplierResult
{
[JsonPropertyName("company_name")]
public string CompanyName { get; set; } = string.Empty;
[JsonPropertyName("country")]
public string? Country { get; set; }
[JsonPropertyName("phone_number")]
public string? PhoneNumber { get; set; }
[JsonPropertyName("contact_email")]
public string? ContactEmail { get; set; }
[JsonPropertyName("website")]
public string? Website { get; set; }
[JsonPropertyName("source")]
public string? Source { get; set; }
[JsonConverter(typeof(FlexibleDecimalConverter))]
public decimal? EstimatedPriceUsd { get; set; }
[JsonPropertyName("item_specifications")]
public JsonElement? ItemSpecifications { get; set; }
}
public class FlexibleDecimalConverter : JsonConverter<decimal?>
{
public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.Number:
return reader.TryGetDecimal(out var num) ? num : null;
case JsonTokenType.String:
var str = reader.GetString()?.Trim();
if (string.IsNullOrWhiteSpace(str)) return null;
// Strip currency symbols and commas e.g. "$1,200.00" → 1200.00
str = Regex.Replace(str, @"[^\d.]", "");
return decimal.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out var parsed)
? parsed
: null; // "contact for pricing", "varies", etc. → null
case JsonTokenType.Null:
default:
return null;
}
}
public override void Write(Utf8JsonWriter writer, decimal? value, JsonSerializerOptions options)
{
if (value.HasValue) writer.WriteNumberValue(value.Value);
else writer.WriteNullValue();
}
}
public class TavilySearchResult
{
public List<TavilyResult> Results { get; set; } = new();
}
public class TavilyResult
{
public string Title { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public double Score { get; set; }
}
public class GroqMatchResult
{
public bool Matched { get; set; }
public int? SupplierId { get; set; }
}
public class GroqResponse
{
public List<GroqChoice> Choices { get; set; } = new();
}
public class GroqChoice
{
public GroqMessage Message { get; set; } = new();
}
public class GroqMessage
{
public string Content { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Common
{
public class ApiResponse<T>
{
public bool success { get; set; }
public string? message { get; set; }
public T? data { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Common
{
public class PagedRequest
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Common
{
public class PagedResult<T>
{
public List<T> Data { get; set; } = new List<T>();
public int TotalCount { get; set; }
public int PageNumber { get; set; }
public int PageSize { get; set; }
public List<string> ClientList { get; set; } = new List<string>();
public List<string> SupplierList { get; set; } = new List<string>();
public List<string> CategoryList { get; set; } = new List<string>();
public List<string> DepartmentList { get; set; } = new List<string>();
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class DisciplineDto
{
public byte DisciplineId { get; set; }
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

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class MRSFilterDto
{
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 12;
public string? SearchMRSNo { get; set; }
public long? RISId { get; set; }
public short? Status { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
}
}

View File

@ -0,0 +1,30 @@
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

@ -0,0 +1,20 @@
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

@ -0,0 +1,17 @@
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
{
public class MRSPagedResult
{
public IEnumerable<MRSPagedDto> Data { get; set; } = [];
public int RecordsTotal { get; set; }
public List<string> DepartmentList { get; set; } = new List<string>();
public List<string> DisciplineList { get; set; } = new List<string>();
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class PagedResult<T>
{
public List<T> Data { get; set; } = new List<T>();
public int TotalCount { get; set; }
public int PageNumber { get; set; }
public int PageSize { get; set; }
public List<string> DepartmentList { get; set; } = new List<string>();
public List<string> CategoryList { get; set; } = new List<string>();
public bool IsSuccess { get; set; } = true;
public string? ErrorMessage { get; set; }
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class RISFilterDto
{
public string? SearchRISNo { get; set; }
public string? SearchItemName { get; set; }
public string? SearchIssuedTo { get; set; }
public string? Discipline { get; set; }
public short? Status { get; set; }
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 12;
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
}
}

View File

@ -0,0 +1,17 @@
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
{
public class RISPagedResult
{
public IEnumerable<RISResponse> Data { get; set; } = [];
public int RecordsTotal { get; set; }
public IEnumerable<string> DepartmentList { get; set; } = [];
public IEnumerable<DisciplineDto> DisciplineList { get; set; } = [];
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory
{
public class RISReferenceDto
{
public long RISId { get; set; }
public string RISNo { get; set; } = string.Empty;
public decimal QtyIssued { get; set; }
public decimal TotalReturned { get; set; }
public decimal QtyAvailableToReturn => QtyIssued - TotalReturned;
public string DisciplineName { get; set; } = string.Empty;
public DateTime CreatedDate { get; set; }
}
}

View File

@ -0,0 +1,26 @@
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

@ -0,0 +1,50 @@
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

@ -0,0 +1,160 @@
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

@ -0,0 +1,14 @@
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

@ -0,0 +1,13 @@
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

@ -0,0 +1,13 @@
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

@ -0,0 +1,10 @@
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

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

View File

@ -0,0 +1,14 @@
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

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

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{
public class CreateMRSRequest
{
public long RISId { get; set; }
public decimal QtyReturned { get; set; }
public string ReturnedBy { get; set; } = string.Empty;
public string? Condition { get; set; }
public string? Remarks { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Inventory.Request
{
public class CreateRISRequest
{
public int InventoryId { get; set; }
public long PRDetailId { get; set; }
public int ProjectCodeId { get; set; }
public byte DisciplineId { get; set; }
public decimal QtyIssued { get; set; }
public string? Remarks { get; set; }
}
}

View File

@ -0,0 +1,18 @@
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; }
}
}

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