Backend Test Report: Projects API
Test Date: December 13, 2025 Environment: Development (localhost:5000) Tenant: thaiscada
At a Glance
| Metric | Value |
|---|---|
| Total Tests | 38 |
| Passed | 38 |
| Failed | 0 |
| Skipped | 0 |
| Pass Rate | 100% |
Two bugs were discovered during initial testing and have been fixed:
- RemoveProjectEndpoint - Simplified request to use
Guid Idinstead of fullProjectDto - CreateTaskEndpoint - Added role-based authorization for task types
Results Summary
| Section | Endpoint | Tests | Status |
|---|---|---|---|
| 1. PreCreate | GET /api/projects/preCreate | 4 | Pass |
| 2. Create | GET /api/projects/create | 4 | Pass |
| 3. Get | GET /api/projects/get/{id} | 7 | Pass |
| 4. Save | POST /api/projects/save | 9 | Pass |
| 5. Remove | POST /api/projects/remove | 4 | Pass |
| 6. Search | POST /api/projects/search | 3 | Pass |
| 7. SearchByPrNo | POST /api/projects/searchByPrNo | 3 | Pass |
| 8. Workflow | POST /api/tasks/createTask | 4 | Pass |
What We Tested
This report covers the Projects API - the system that handles:
- PreCreate - Validates staff configuration before project creation
- Create - Initializes new project with defaults and lookup data
- Get - Retrieves project by ID with related entities
- Save - Creates/updates project (PR No. must be unique)
- Remove - Deletes project (FK protected)
- Search - Lists projects (keyword NOT used - returns all)
- SearchByPrNo - Searches by PR number with IsInUse and LinkedTaskRefId
Authorization Matrix
| Endpoint | Policy | Admin | Work Owner | Purchasing | Contractor |
|---|---|---|---|---|---|
| PreCreate | project-mgmt | 200 | 200 | 200 | 403 |
| Create | project-mgmt | 200 | 200 | 200 | 403 |
| Get | project-mgmt | 200 | 200 | 200 | 403 |
| Save | project-mgmt | 200 | 200 | 200 | 403 |
| Remove | project-mgmt | 200 | 200 | 200 | 403 |
| Search | project-mgmt | 200 | 200 | 200 | 403 |
| SearchByPrNo | project-mgmt | 200 | 200 | 200 | 403 |
- All endpoints require
project-mgmtrole - Work Owner, Admin, and Purchasing have
project-mgmtpermission - Contractor role does NOT have project management permission (403)
Detailed Results
1. PreCreate - Validate Staff Config (4 tests)
Endpoint: GET /api/projects/preCreate
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 1.1 | Valid request (Work Owner) | 200 | 200 | Pass |
| 1.3 | Missing authorization | 401 | 401 | Pass |
| 1.4 | Invalid token | 401 | 401 | Pass |
| 1.5 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
Returns ResultMessage with validation result for staff configuration (contractors, users by role).
2. Create - Initialize New Project (4 tests)
Endpoint: GET /api/projects/create
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 2.1 | Valid request (Work Owner) | 200 | 200 | Pass |
| 2.4 | Missing authorization | 401 | 401 | Pass |
| 2.5 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
| 2.6 | Purchasing user | 200 | 200 | Pass |
Returns project template with:
- Default values (status, dates)
- Lookup data (users by role, contractors, workspace areas)
- Document templates for selection
3. Get - Retrieve Project (7 tests)
Endpoint: GET /api/projects/get/{id}
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 3.1 | Valid get (Work Owner) | 200 | 200 | Pass |
| 3.2 | Get with includeEmptyOption=true | 200 | 200 | Pass |
| 3.3 | Get non-existent project | 400 | 400 | Pass |
| 3.4 | Missing authorization | 401 | 401 | Pass |
| 3.5 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
| 3.6 | Purchasing user | 200 | 200 | Pass |
| 3.7 | Admin user | 200 | 200 | Pass |
Test 3.3 returns 400 Bad Request with message "The project with the specified ID was not found" instead of 404.
4. Save - Create/Update Project (9 tests)
Endpoint: POST /api/projects/save
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 4.1 | Create new project (Work Owner) | 200 | 200 | Pass |
| 4.2 | Update existing project | 200 | 200 | Pass |
| 4.3 | Save with Thai content | 200 | 200 | Pass |
| 4.4 | Save with empty name (defaults to DRAFT) | 200 | 200 | Pass |
| 4.5 | Duplicate PurchaseRequisitionNo | 400 | 400 | Pass |
| 4.6 | Save with all user references | 200 | 200 | Pass |
| 4.7 | Missing authorization | 401 | 401 | Pass |
| 4.8 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
| 4.9 | Purchasing user | 200 | 200 | Pass |
Duplicate PR Number validation works correctly. Returns Thai error message: "PR No. นี้ถูกใช้งานแล้วในโครงการอื่น"
Save endpoint requires employerId to be provided. Without it, the endpoint returns 500 Internal Server Error.
5. Remove - Delete Project (4 tests)
Endpoint: POST /api/projects/remove
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 5.1 | Valid remove (Work Owner) | 200 | 200 | Pass |
| 5.3 | Missing authorization | 401 | 401 | Pass |
| 5.4 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
| 5.5 | Purchasing user | 200 | 200 | Pass |
The endpoint was simplified to accept Guid Id instead of full ProjectDto, eliminating the null reference issue during entity mapping.
6. Search - List Projects (3 tests)
Endpoint: POST /api/projects/search
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 6.1 | Valid search (Work Owner) | 200 | 200 | Pass |
| 6.2 | Search with keyword | 200 | 200 | Pass |
| 6.4 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
The keyword parameter is defined but not used in the backend implementation. Search always returns ALL projects regardless of keyword value.
7. SearchByPrNo - PR Number Search (3 tests)
Endpoint: POST /api/projects/searchByPrNo
Policy: project-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 7.1 | Valid search with PR number | 200 | 200 | Pass |
| 7.5 | Missing authorization | 401 | 401 | Pass |
| 7.6 | Contractor user (no project-mgmt) | 403 | 403 | Pass |
SearchByPrNo response includes additional fields:
isInUse- Whether project is linked to a tasklinkedTaskRefId- Reference ID of linked task (if any)
8. Workflow Integration (4 tests)
Endpoint: POST /api/tasks/createTask
Policy: realm-basic (with task-type-specific authorization)
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 8.1 | Create ProjectRegistration task (Work Owner) | 200 | 200 | Pass |
| 8.6 | Contractor cannot create ProjectRegistration task | 403 | 403 | Pass |
| 9.3 | Get task with project relationship | 200 | 200 | Pass |
| 9.5 | Missing auth on createTask | 401 | 401 | Pass |
Role-based authorization was added to CreateTaskAsync():
- ProjectRegistration (taskTypeId=1): Requires
project-mgmtrole - ContractorRegistration (taskTypeId=2): Requires
contractor-mgmtrole - WorkPermitRequest (taskTypeId=3): All authenticated users (workflow not yet implemented)
ProjectRegistration task automatically creates a project entity with:
workOwnerUserIdset to current user- Project linked via
projectIdin task info
Test Data Created
| Variable | Value | Description |
|---|---|---|
testProjectId | 019b180e-1efb-7214-be74-94f2e80605b2 | Project created via Save API |
testPrNumber | PR-HTTP-TEST-002 | Purchase Requisition Number |
workflowTaskId | 019b1818-6e0a-7b05-abc6-ba9d1d2d501c | Task created via workflow |
Resolved Issues
1. Remove Endpoint 500 Error (FIXED)
Location: RemoveProjectEndpoint.cs
Fix: Simplified request from RemoveProjectRequest(ProjectDto Project) to RemoveProjectRequest(Guid Id), eliminating the null reference during entity mapping.
2. CreateTask Authorization Missing (FIXED)
Location: TaskService.CreateTaskAsync()
Fix: Added role-based authorization check based on task type:
- ProjectRegistration → requires
project-mgmtrole - ContractorRegistration → requires
contractor-mgmtrole - WorkPermitRequest → all authenticated users
Outstanding Items
Search Keyword Not Implemented
Severity: Low
Location: SearchProjectsEndpoint
The keyword parameter in search is not used - all projects are returned regardless of the keyword value. Consider implementing keyword filtering or removing the parameter from the API contract.
Conclusion
All 38 test cases passed (100% pass rate). The Projects API correctly implements:
- Role-based access control (
project-mgmtpolicy) - PR Number uniqueness validation with Thai error messages
- SearchByPrNo with IsInUse and LinkedTaskRefId fields
- Proper 401/403 responses for authentication/authorization failures
- Workflow integration via TaskInfo linkage
- Task-type-specific authorization for workflow tasks
Bugs Fixed During Testing:
RemoveProjectEndpoint- Simplified to useGuid Idinstead of fullProjectDtoCreateTaskEndpoint- Added task-type authorization inTaskService