Skip to content

Mobile App Sync api update#178

Merged
LijuJacob08 merged 3 commits into
mainfrom
ft/listAllChapterAssignments-user
Jun 8, 2026
Merged

Mobile App Sync api update#178
LijuJacob08 merged 3 commits into
mainfrom
ft/listAllChapterAssignments-user

Conversation

@LijuJacob08

Copy link
Copy Markdown
Contributor

Things covered:

  • Added the updateAfter query param in bulk text(POST - Bible Text Api) for fetching data after a specific date.
  • Created a new api to fetch the chapterAssignments for all the projects that the user is part of.
  • This new API also supports optional query parameters like excludeProject ID and updateAfter.
    #issue 36

Comment thread src/domains/projects/chapter-assignments/project-chapter-assignments.route.ts Outdated
Comment thread src/domains/bibles/bible-texts/bible-texts.route.ts Outdated
Comment on lines +141 to +158
.where(
excludeProjectIds.length === 0 && updatedAfter
? and(
inArray(project_units.projectId, projectIds),
gt(chapter_assignments.updatedAt, updatedAfter)
)
: or(
inArray(
project_units.projectId,
projectIds.filter((id) => !excludeProjectIds.includes(id))
),
excludeProjectIds.length > 0 && updatedAfter
? and(
inArray(project_units.projectId, excludeProjectIds),
gt(chapter_assignments.updatedAt, updatedAfter)
)
: undefined
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complex, hard-to-reason repository logic.
The ternary where clause in getByProjects tries to handle excludeProjectIds + updatedAfter in a single expression. It produces or(x, undefined) when excludeProjectIds.length > 0 && !updatedAfter, which is brittle. Extracting explicit conditions into a builder variable or using an array filter before passing to and()/or() would be much cleaner and safer.

Comment on lines +35 to +48
export const memberChapterAssignmentResponseSchema = z.object({
chapterAssignmentId: z.number().int(),
projectId: z.number().int(),
projectUnitId: z.number().int(),
bibleId: z.number().int(),
bookId: z.number().int(),
chapterNumber: z.number().int(),
assignedUserId: z.number().int().nullable(),
peerCheckerId: z.number().int().nullable(),
status: z.string(),
submittedTime: z.string().nullable(),
createdAt: z.string().nullable(),
updatedAt: z.string().nullable(),
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date schema inconsistency
This memberChapterAssignmentResponseSchema uses z.string().nullable() for timestamps, while the adjacent chapterAssignmentProgressResponseSchema (in the same file) uses z.date().nullable(). If the JSON response actually contains ISO strings, the z.date() schemas elsewhere may fail client-side validation depending on the OpenAPI generator. Align on one representation.

This also should be consistent even if we move this logic to the user domain. DB types are consistent and the code should reflect that.

Comment on lines +49 to +52
return ok({
syncedAt: new Date().toISOString(),
data: toBulkChapterTextResponses(result.data),
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a minor deviation from the return signature that the codebase follows. While this is not a big deal, it prompts the question of whether we should consider keeping mobile-specific logic in a src/services/mobile-sync.service.ts and the data queries in their respective domains. This is not necessary for this PR but, if there are more sync endpoints that will be implemented, it is worth discussion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. For reference, we currently have two sync-oriented endpoints: one for chapter assignments and one for bulk Bible texts. While they were introduced to support the mobile sync workflow, they are not limited to mobile clients.

The intent is to use the same endpoints for both full and incremental syncs. An initial sync retrieves the complete dataset, while subsequent syncs use the updatedAfter parameter to fetch only records that have changed since the last sync.

@LijuJacob08
LijuJacob08 requested a review from kaseywright June 8, 2026 11:32
@LijuJacob08
LijuJacob08 merged commit 6c2b3ee into main Jun 8, 2026
1 check passed
@github-actions
github-actions Bot deleted the ft/listAllChapterAssignments-user branch June 8, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants