Skip to main content

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

ParameterTypeDescription
selfServiceUserIdlongThe 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

FieldTypeDescription
documentIdstring (GUID)Unique identifier for the document
documentNamestringFile name
documentTypeintDocument type enum value
documentTypeNamestringHuman-readable type name
descriptionstringDocument description
documentNumberstringOfficial document number
documentExpiryDateTimeExpiration date (if applicable)
documentIssueDateDateTimeIssue date
documentIssuerstringIssuing organization
createdDateDateTimeUpload timestamp
createdByobjectUser 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

ValueNameCommon Use
1NATIONAL_IDPrimary identification
2INTERNATIONAL_PASSPORTInternational ID
3DRIVERS_LICENCEAlternate ID
4UTILITY_BILLAddress verification
5BANK_STATEMENTFinancial verification
6COMPANY_REGISTRATIONBusiness verification
7TAX_CLEARANCETax compliance

Error Codes

Status CodeDescription
00Success - documents retrieved
01User not found
99General error (see statusMessage)

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