GetUserDocumentsQuery
Overview
The GetUserDocumentsQuery retrieves a list of all documents associated with a SelfService user. This query is optimized for performance by returning only document metadata without the actual file content, making it ideal for displaying document lists in the UI.
Handler File: CB.Administration.Api/Commands/BPM/SelfService/DocumentManagementCommand.cs
Use Cases
- Display list of uploaded documents in user profile UI
- Show document checklist with completion status
- Audit trail of all documents submitted by user
- Quick overview of available documentation
- Document management dashboard
Performance Optimization
🚀 Fast Query: This query excludes the documentData field, making responses 500x smaller and faster than including full document content.
Example:
- 50 documents with data: ~25MB response, 5-10 seconds
- 50 documents without data: ~50KB response, 100-200ms ⚡
Request Parameters
Required Parameters
| Parameter | Type | Description |
|---|---|---|
selfServiceUserId | long | The ID of the user to retrieve documents for |
Request Example
{
"cmd": "GetUserDocumentsQuery",
"data": {
"selfServiceUserId": 250
}
}
Response Format
Success Response
{
"statusCode": "00",
"statusMessage": "SUCCESS",
"data": [
{
"documentId": "b2c3d4e5-f6g7-8901-bcde-f12345678901",
"documentName": "Passport.pdf",
"documentType": 2,
"documentTypeName": "INTERNATIONAL_PASSPORT",
"description": "International passport - bio page",
"documentNumber": "A12345678",
"documentExpiry": "2030-12-31T00:00:00Z",
"documentIssueDate": "2020-06-15T00:00:00Z",
"documentIssuer": "Immigration Service",
"createdDate": "2026-01-12T11:30:00Z",
"createdBy": {
"userId": 250,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com"
}
},
{
"documentId": "c3d4e5f6-g7h8-9012-cdef-g23456789012",
"documentName": "Utility Bill - January 2026.pdf",
"documentType": 4,
"documentTypeName": "UTILITY_BILL",
"description": "Electricity bill for address verification",
"documentNumber": null,
"documentExpiry": null,
"documentIssueDate": "2026-01-01T00:00:00Z",
"documentIssuer": "Power Company",
"createdDate": "2026-01-12T12:45:00Z",
"createdBy": {
"userId": 250,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com"
}
}
]
}
Empty Result Response
{
"statusCode": "00",
"statusMessage": "SUCCESS",
"data": []
}
Error Response
{
"statusCode": "01",
"statusMessage": "User with ID 999 not found",
"data": null
}
Response Fields
| Field | Type | Description |
|---|---|---|
documentId | string (GUID) | Unique identifier for the document |
documentName | string | File name |
documentType | int | Document type enum value |
documentTypeName | string | Human-readable type name |
description | string | Document description |
documentNumber | string | Official document number |
documentExpiry | DateTime | Expiration date (if applicable) |
documentIssueDate | DateTime | Issue date |
documentIssuer | string | Issuing organization |
createdDate | DateTime | Upload timestamp |
createdBy | object | User who uploaded the document |
⚠️ Note: The documentData field is NOT included in this response for performance reasons.
JavaScript Usage Example
// Fetch and display user document list
const loadUserDocuments = async (userId) => {
try {
const result = await api.query({
cmd: "GetUserDocumentsQuery",
data: JSON.stringify({ selfServiceUserId: userId })
});
if (result.statusCode === "00") {
const documents = result.data;
console.log(`Found ${documents.length} documents for user`);
// Display in UI
displayUserDocuments(documents);
return documents;
} else {
console.error("Error:", result.statusMessage);
return [];
}
} catch (error) {
console.error("Failed to load documents:", error);
return [];
}
};
// Display documents in table
const displayUserDocuments = (documents) => {
const tbody = document.querySelector('#userDocumentTable tbody');
tbody.innerHTML = '';
documents.forEach(doc => {
const row = tbody.insertRow();
row.innerHTML = `
<td>${doc.documentName}</td>
<td>${doc.documentTypeName}</td>
<td>${doc.documentNumber || 'N/A'}</td>
<td>${new Date(doc.createdDate).toLocaleDateString()}</td>
<td>
<button onclick="downloadUserDocument(${doc.createdBy.userId}, '${doc.documentId}')">
Download
</button>
</td>
`;
});
};
// Download specific document (use GetUserDocumentByIdQuery)
const downloadUserDocument = async (userId, documentId) => {
// See get-user-document-by-id.md for download implementation
console.log("Downloading document:", documentId);
};
Complete UI Component Example
class UserDocumentViewer {
constructor(userId, containerId) {
this.userId = userId;
this.container = document.getElementById(containerId);
this.documents = [];
}
async load() {
const result = await api.query({
cmd: "GetUserDocumentsQuery",
data: JSON.stringify({ selfServiceUserId: this.userId })
});
if (result.statusCode === "00") {
this.documents = result.data;
this.render();
}
}
render() {
const html = `
<div class="document-list">
<h3>User Documents (${this.documents.length})</h3>
<table class="table">
<thead>
<tr>
<th>Document Name</th>
<th>Type</th>
<th>Upload Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
${this.documents.map(doc => this.renderRow(doc)).join('')}
</tbody>
</table>
</div>
`;
this.container.innerHTML = html;
}
renderRow(doc) {
const uploadDate = new Date(doc.createdDate).toLocaleDateString();
return `
<tr>
<td>
<i class="file-icon"></i> ${doc.documentName}
</td>
<td>
<span class="badge">${doc.documentTypeName}</span>
</td>
<td>${uploadDate}</td>
<td>
<button class="btn-download"
onclick="userViewer.download('${doc.documentId}')">
Download
</button>
</td>
</tr>
`;
}
async download(documentId) {
// Use GetUserDocumentByIdQuery to download
const result = await api.query({
cmd: "GetUserDocumentByIdQuery",
data: JSON.stringify({
selfServiceUserId: this.userId,
documentId: documentId
})
});
if (result.statusCode === "00") {
const doc = result.data;
const blob = this.base64ToBlob(doc.documentData);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = doc.documentName;
a.click();
URL.revokeObjectURL(url);
}
}
base64ToBlob(base64) {
const byteCharacters = atob(base64);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
return new Blob([byteArray]);
}
}
// Usage
const userViewer = new UserDocumentViewer(250, 'userDocumentContainer');
userViewer.load();
Document Type Reference
| Value | Name | Common Use |
|---|---|---|
| 1 | NATIONAL_ID | Primary identification |
| 2 | INTERNATIONAL_PASSPORT | International ID |
| 3 | DRIVERS_LICENCE | Alternate ID |
| 4 | UTILITY_BILL | Address verification |
| 5 | BANK_STATEMENT | Financial verification |
| 6 | COMPANY_REGISTRATION | Business verification |
| 7 | TAX_CLEARANCE | Tax compliance |
Error Codes
| Status Code | Description |
|---|---|
| 00 | Success - documents retrieved |
| 01 | User not found |
| 99 | General error (see statusMessage) |
Related Commands
- CreateUserDocumentCommand - Upload new document
- GetUserDocumentByIdQuery - Download specific document
- GetLoanQuoteDocumentsQuery - List documents for loan quotes
Performance Tips
✅ DO: Use this query for displaying document lists
✅ DO: Cache the list and refresh only when needed
✅ DO: Use pagination if dealing with 100+ documents
❌ DON'T: Use this for downloading documents (use GetUserDocumentByIdQuery)
❌ DON'T: Poll this endpoint repeatedly (use webhooks/SignalR for updates)
Database Query
-- Simplified version of what the handler executes
SELECT
d.DocumentId,
d.DocumentName,
d.DocumentType,
d.Description,
d.DocumentNumber,
d.DocumentExpiry,
d.DocumentIssueDate,
d.DocumentIssuer,
d.CreatedDate,
-- DocumentData is NOT selected (performance!)
u.Id AS UserId,
ud.FirstName,
ud.LastName,
ud.Email
FROM [BPMSelfServiceDocument].[dbo].[SelfServiceDocumentAssociation] da
INNER JOIN [BPMSelfServiceDocument].[dbo].[SelfServiceDocument] d
ON da.SelfServiceDocumentId = d.Id
LEFT JOIN [Administration].[dbo].[SelfServiceUser] u
ON d.CreatedByUserId = u.Id
LEFT JOIN [Administration].[dbo].[UserDetail] ud
ON u.UserDetailId = ud.Id
WHERE da.AssociatedUserId = @selfServiceUserId
ORDER BY d.CreatedDate DESC
Testing Checklist
- Retrieve documents for user with 0 documents
- Retrieve documents for user with 1 document
- Retrieve documents for user with 10+ documents
- Verify documentData field is NOT in response
- Test with invalid selfServiceUserId
- Verify response time (less than 200ms for 50 docs)
- Check creator information is included
- Verify all metadata fields are populated