diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml
new file mode 100644
index 0000000..50c56c7
--- /dev/null
+++ b/.forgejo/workflows/build.yml
@@ -0,0 +1,49 @@
+name: Build
+
+# on:
+# push:
+# tags:
+# - "v[0-9]+.[0-9]+.[0-9]+"
+# - "v[0-9]+.[0-9]+.[0-9]+*"
+# workflow_dispatch:
+
+env:
+ REGISTRY: ${{ vars.CONTAINER_REGISTRY }}
+ REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }}
+ REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
+ CONTAINER_IMAGE_NAME: ${{ vars.CONTAINER_REGISTRY }}/${{ vars.CONTAINER_IMAGE_OWNER }}/${{ vars.CONTAINER_IMAGE_NAME }}
+ IMAGE_VERSION: build
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+ with:
+ config-inline: |
+ [registry."${{ env.REGISTRY }}"]
+ ca=["/etc/ssl/certs/ca-certificates.crt"]
+ - name: Tag Version
+ run: |
+ if [[ "${{ github.event_name }}" == "push" ]]; then
+ echo "IMAGE_VERSION=${{ github.ref_name }}" | sed 's/v//g' >> $GITHUB_ENV
+ else
+ echo "IMAGE_VERSION=${{ env.IMAGE_VERSION }}-${{ github.run_number }}" >> $GITHUB_ENV
+ fi
+ - name: Login in to registry
+ uses: docker/login-action@v2
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ env.REGISTRY_USERNAME }}
+ password: ${{ env.REGISTRY_PASSWORD }}
+ - name: Build and push docker image
+ uses: docker/build-push-action@v3
+ with:
+ platforms: linux/amd64
+ context: .
+ file: Dockerfile
+ tags: ${{ env.CONTAINER_IMAGE_NAME }}:latest,${{ env.CONTAINER_IMAGE_NAME }}:${{ env.IMAGE_VERSION }}
+ push: true
diff --git a/.forgejo/workflows/ci-cd.yml b/.forgejo/workflows/ci-cd.yml
new file mode 100644
index 0000000..2b0e136
--- /dev/null
+++ b/.forgejo/workflows/ci-cd.yml
@@ -0,0 +1,82 @@
+name: Build & Deploy on Dev
+
+on:
+ push:
+ tags:
+ - "v[0-9]+.[0-9]+.[0-9]+"
+ workflow_dispatch:
+
+env:
+ REGISTRY: ${{ vars.CONTAINER_REGISTRY }}
+ REGISTRY_USERNAME: ${{ vars.CONTAINER_REGISTRY_USERNAME }}
+ REGISTRY_PASSWORD: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
+ CONTAINER_IMAGE_NAME: ${{ vars.CONTAINER_REGISTRY }}/${{ vars.CONTAINER_IMAGE_OWNER }}/${{ vars.CONTAINER_IMAGE_NAME }}
+ IMAGE_VERSION: latest
+ DISCORD_WEBHOOK: ${{ vars.DISCORD_WEBHOOK }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+ with:
+ config-inline: |
+ [registry."${{ env.REGISTRY }}"]
+ ca=["/etc/ssl/certs/ca-certificates.crt"]
+ - name: Tag Version
+ run: |
+ if [ "${{ github.ref_type }}" == "tag" ]; then
+ echo "IMAGE_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV
+ else
+ echo "IMAGE_VERSION=latest" >> $GITHUB_ENV
+ fi
+ - name: Login in to registry
+ uses: docker/login-action@v2
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ env.REGISTRY_USERNAME }}
+ password: ${{ env.REGISTRY_PASSWORD }}
+ - name: Build and push docker image
+ uses: docker/build-push-action@v3
+ with:
+ platforms: linux/amd64
+ context: .
+ file: Dockerfile
+ tags: ${{ env.CONTAINER_IMAGE_NAME }}:latest,${{ env.CONTAINER_IMAGE_NAME }}:${{ env.IMAGE_VERSION }}
+ push: true
+ - name: Remote Deploy
+ uses: appleboy/ssh-action@v1.2.1
+ with:
+ host: ${{ vars.SSH_DEPLOY_HOST }}
+ port: ${{ vars.SSH_DEPLOY_PORT }}
+ username: ${{ secrets.SSH_DEPLOY_USER }}
+ password: ${{ secrets.SSH_DEPLOY_PASSWORD }}
+ script: |
+ cd ~/repo
+ ./replace-env.sh API_RECRUIT "${{ env.IMAGE_VERSION }}"
+ ./deploy.sh hrms-api-recruit
+
+ - name: Discord Notification
+ if: always()
+ run: |
+ STATUS="${{ job.status == 'success' && '✅ Success' || '❌ Failed' }}"
+ COLOR="${{ job.status == 'success' && '3066993' || '15158332' }}"
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
+ curl -H "Content-Type: application/json" \
+ -X POST \
+ -d "{
+ \"embeds\": [{
+ \"title\": \"$STATUS\",
+ \"description\": \"**Build & Deploy**\\n- Image: \`${{ env.CONTAINER_IMAGE_NAME }}\`\\n- Version: \`${{ env.IMAGE_VERSION }}\`\\n- By: \`${{ github.actor }}\`\",
+ \"color\": $COLOR,
+ \"footer\": {
+ \"text\": \"Release Notification\",
+ \"icon_url\": \"https://example.com/success-icon.png\"
+ },
+ \"timestamp\": \"$TIMESTAMP\"
+ }]
+ }" \
+ ${{ env.DISCORD_WEBHOOK }}
diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml
new file mode 100644
index 0000000..5861922
--- /dev/null
+++ b/.forgejo/workflows/deploy.yml
@@ -0,0 +1,29 @@
+name: Build
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: "Version to deploy"
+ type: string
+ required: false
+ default: "latest"
+
+env:
+ IMAGE_VERSION: build
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Remote Deploy
+ uses: appleboy/ssh-action@v1.2.1
+ with:
+ host: ${{ vars.SSH_DEPLOY_HOST }}
+ port: ${{ vars.SSH_DEPLOY_PORT }}
+ username: ${{ secrets.SSH_DEPLOY_USER }}
+ password: ${{ secrets.SSH_DEPLOY_PASSWORD }}
+ script: |
+ cd ~/repo
+ ./replace-env.sh API_RECRUIT "${{ inputs.version }}"
+ ./deploy.sh hrms-api-recruit
diff --git a/.idea/.idea.BMA.EHR.Recruit.Service/.idea/.gitignore b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/.gitignore
new file mode 100644
index 0000000..889a0d6
--- /dev/null
+++ b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/contentModel.xml
+/projectSettingsUpdater.xml
+/modules.xml
+/.idea.BMA.EHR.Recruit.Service.iml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.BMA.EHR.Recruit.Service/.idea/.name b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/.name
new file mode 100644
index 0000000..aaf1117
--- /dev/null
+++ b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/.name
@@ -0,0 +1 @@
+BMA.EHR.Recruit.Service
\ No newline at end of file
diff --git a/.idea/.idea.BMA.EHR.Recruit.Service/.idea/encodings.xml b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.BMA.EHR.Recruit.Service/.idea/indexLayout.xml b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.BMA.EHR.Recruit.Service/.idea/vcs.xml b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/.idea.BMA.EHR.Recruit.Service/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Controllers/RecruitController.cs b/Controllers/RecruitController.cs
index 3561b97..39fd3c9 100644
--- a/Controllers/RecruitController.cs
+++ b/Controllers/RecruitController.cs
@@ -752,6 +752,8 @@ namespace BMA.EHR.Recruit.Service.Controllers
var cols = workSheet.GetHeaderColumns();
int row = 2;
+ int batchCount = 0;
+ const int batchSize = 500;
while (row <= totalRows)
{
@@ -860,13 +862,23 @@ namespace BMA.EHR.Recruit.Service.Controllers
//imported.Recruits.Add(r);
row++;
+ batchCount++;
+
+ // Batch save to prevent OutOfMemoryException on large imports
+ if (batchCount >= batchSize)
+ {
+ _context.SaveChanges();
+ _context.ChangeTracker.Clear();
+ // Re-attach the import entity after clearing the tracker
+ _context.RecruitImports.Attach(imported);
+ batchCount = 0;
+ }
}
}
}
- // finally save to database
-
+ // Save remaining records in the last batch
_context.SaveChanges();
return Success();
@@ -1371,6 +1383,8 @@ namespace BMA.EHR.Recruit.Service.Controllers
var cols = workSheet.GetHeaderColumns();
int row = 8;
+ int batchCount = 0;
+ const int batchSize = 500;
var endRow = workSheet.Dimension.End.Row; // แถวสุดท้ายที่มีข้อมูล
while (row <= endRow)
{
@@ -1461,14 +1475,31 @@ namespace BMA.EHR.Recruit.Service.Controllers
}
row++;
+ batchCount++;
+
+ // Batch save to prevent OutOfMemoryException on large imports
+ if (batchCount >= batchSize)
+ {
+ rec_import.ScoreImport = imported;
+ await _context.SaveChangesAsync();
+ _context.ChangeTracker.Clear();
+ // Re-attach entities after clearing the tracker
+ _context.Attach(rec_import);
+ _context.Attach(imported);
+ imported.Scores.Clear();
+ batchCount = 0;
+ }
} // end of sheet loop
} // end of all file loop
}
- // finally save to database
- rec_import.ScoreImport = imported;
- await _context.SaveChangesAsync();
+ // Save remaining records in the last batch
+ if (imported.Scores.Count > 0)
+ {
+ rec_import.ScoreImport = imported;
+ await _context.SaveChangesAsync();
+ }
return Success();
diff --git a/obj/BMA.EHR.Recruit.Service.csproj.nuget.dgspec.json b/obj/BMA.EHR.Recruit.Service.csproj.nuget.dgspec.json
index c30443d..ea2eb46 100644
--- a/obj/BMA.EHR.Recruit.Service.csproj.nuget.dgspec.json
+++ b/obj/BMA.EHR.Recruit.Service.csproj.nuget.dgspec.json
@@ -39,7 +39,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
- "SdkAnalysisLevel": "9.0.300"
+ "SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net7.0": {
@@ -203,7 +203,7 @@
"privateAssets": "all"
}
},
- "runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/9.0.305/RuntimeIdentifierGraph.json"
+ "runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/10.0.203/RuntimeIdentifierGraph.json"
}
}
}
diff --git a/obj/BMA.EHR.Recruit.Service.csproj.nuget.g.props b/obj/BMA.EHR.Recruit.Service.csproj.nuget.g.props
index 5868417..8714023 100644
--- a/obj/BMA.EHR.Recruit.Service.csproj.nuget.g.props
+++ b/obj/BMA.EHR.Recruit.Service.csproj.nuget.g.props
@@ -7,7 +7,7 @@
/Users/suphonchaip/.nuget/packages/
/Users/suphonchaip/.nuget/packages/
PackageReference
- 6.14.0
+ 7.0.0
diff --git a/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs b/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs
index a9058da..4257f4b 100644
--- a/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs
+++ b/obj/Debug/net7.0/.NETCoreApp,Version=v7.0.AssemblyAttributes.cs
@@ -1,4 +1,4 @@
-//
-using System;
-using System.Reflection;
-[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")]
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")]
diff --git a/obj/Debug/net7.0/BMA.EHR.Recruit.Service.AssemblyInfo.cs b/obj/Debug/net7.0/BMA.EHR.Recruit.Service.AssemblyInfo.cs
deleted file mode 100644
index b0967b3..0000000
--- a/obj/Debug/net7.0/BMA.EHR.Recruit.Service.AssemblyInfo.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-using System;
-using System.Reflection;
-
-[assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute("d45c95ce-6b9d-4aa7-aaaf-62fe8b792934")]
-[assembly: System.Reflection.AssemblyCompanyAttribute("BMA.EHR.Recruit.Service")]
-[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
-[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e1d869c9329ffd1d9e4fdb73f077eee60b67e09c")]
-[assembly: System.Reflection.AssemblyProductAttribute("BMA.EHR.Recruit.Service")]
-[assembly: System.Reflection.AssemblyTitleAttribute("BMA.EHR.Recruit.Service")]
-[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
-
-// Generated by the MSBuild WriteCodeFragment class.
-
diff --git a/obj/Debug/net7.0/BMA.EHR.Recruit.Service.AssemblyInfoInputs.cache b/obj/Debug/net7.0/BMA.EHR.Recruit.Service.AssemblyInfoInputs.cache
deleted file mode 100644
index 0aa2ab4..0000000
--- a/obj/Debug/net7.0/BMA.EHR.Recruit.Service.AssemblyInfoInputs.cache
+++ /dev/null
@@ -1 +0,0 @@
-115668deb371dd5b1a7e9691f5117e5e4acdd7bef73f049871879b64ab58463e
diff --git a/obj/project.assets.json b/obj/project.assets.json
index e6f4b38..46e800f 100644
--- a/obj/project.assets.json
+++ b/obj/project.assets.json
@@ -13782,7 +13782,7 @@
"auditLevel": "low",
"auditMode": "direct"
},
- "SdkAnalysisLevel": "9.0.300"
+ "SdkAnalysisLevel": "10.0.200"
},
"frameworks": {
"net7.0": {
@@ -13946,7 +13946,7 @@
"privateAssets": "all"
}
},
- "runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/9.0.305/RuntimeIdentifierGraph.json"
+ "runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/10.0.203/RuntimeIdentifierGraph.json"
}
}
}
diff --git a/obj/project.nuget.cache b/obj/project.nuget.cache
index 876e06c..4bae79d 100644
--- a/obj/project.nuget.cache
+++ b/obj/project.nuget.cache
@@ -1,6 +1,6 @@
{
"version": 2,
- "dgSpecHash": "z4TN+iW9Ey8=",
+ "dgSpecHash": "6/jNsBvJ3SY=",
"success": true,
"projectFilePath": "/Users/suphonchaip/Develop/hrms/hrms-api-recruit/BMA.EHR.Recruit.Service.csproj",
"expectedPackageFiles": [