feat(backend): modularize services and clean deps (#813 #814 #815 #821) - #1
Open
marvel6828 wants to merge 1 commit into
Open
feat(backend): modularize services and clean deps (#813 #814 #815 #821)#1marvel6828 wants to merge 1 commit into
marvel6828 wants to merge 1 commit into
Conversation
…inTease#814 BrainTease#815 BrainTease#821) BrainTease#821 — Analytics ingestion pipeline modularized into discrete stages - Add pipeline/ folder under src/analytics/ with four stages: DataCollectionStage (I/O), AggregationStage (computation), PersistenceStage (upsert), CacheStage (invalidation) - Add AnalyticsPipeline orchestrator that sequences the stages - Refactor AnalyticsService.aggregateCourse to delegate to the pipeline - Update AnalyticsModule to register all pipeline providers - Add analytics.pipeline.spec.ts unit tests (stage isolation + orchestrator) BrainTease#815 — Royalty-distribution calculation extracted into a service - Add RoyaltyCalculationService with RoyaltyInput/RoyaltyResult interfaces - Expose calculate(), calculateBatch(), getCoursePrice(), getPlatformFeePercent() — pure computation, no I/O - Refactor PayoutsService.calculatePayouts to delegate to the new service - Update PayoutsModule to register RoyaltyCalculationService - Add royalty-calculation.service.spec.ts unit tests BrainTease#814 — Remove unused npm dependencies - Remove apollo-server-express (zero imports; GraphQL runs via @nestjs/graphql) - Remove graphql-query-complexity (zero imports) - Confirmed all other suspect deps (class-sanitizer, otplib, qrcode, xml2js, adm-zip, passport-google-oauth20, cache-manager-redis-store, graphql-depth-limit, @elastic/elasticsearch) are actively used BrainTease#813 — Dispute-resolution service refactored (reduced cyclomatic complexity) - Extract DisputeResolutionService with isTerminal() guard helper - AdminService now owns only user management; delegates dispute methods - Update AdminModule to register DisputeResolutionService - Add dispute-resolution.service.spec.ts unit tests (7 cases)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
closes BrainTease#821
closes BrainTease#813
closes BrainTease#814
closes BrainTease#815
Resolves four backend technical-debt issues in a single cohesive PR.
BrainTease#821 — Analytics ingestion pipeline modularized
Problem:
AnalyticsService.aggregateCoursewas a monolith mixing database I/O, metric calculation, persistence, and cache invalidation in one method.Solution: Introduced four discrete pipeline stages under
src/analytics/pipeline/:DataCollectionStageAggregationStagePersistenceStageCacheStageAnalyticsPipelineorchestrates the stages in order.AnalyticsService.aggregateCoursenow delegates entirely topipeline.run(courseId).Tests:
analytics.pipeline.spec.ts— stage isolation + orchestrator orderingBrainTease#815 — Royalty-distribution calculation extracted into a service
Problem: Revenue/royalty math was inlined inside
PayoutsService.calculatePayouts, mixing business logic with persistence.Solution: Created
RoyaltyCalculationServicewith:calculate(input)— single-course royalty (completions × price − platform fee)calculateBatch(inputs)— filters zero-completion courses, mapscalculategetCoursePrice(courseId)/getPlatformFeePercent()— config accessorsPayoutsServicenow delegates all math to this service.Tests:
royalty-calculation.service.spec.ts— covers all public methodsBrainTease#814 — Remove unused npm dependencies
Analysis method: Static import scan across all
src/**/*.tsfiles.Removed:
apollo-server-express— zero imports; GraphQL runs through@nestjs/graphql/@nestjs/apollographql-query-complexity— zero importsRetained (confirmed in use):
class-sanitizer,otplib,qrcode,xml2js,adm-zip,passport-google-oauth20,cache-manager-redis-store,graphql-depth-limit,@elastic/elasticsearchBrainTease#813 — Dispute-resolution service refactored
Problem:
AdminServicemixed user management with dispute lifecycle logic, increasing cyclomatic complexity through nested guards and status checks.Solution: Extracted
DisputeResolutionServicewith:createDispute,listDisputes,getDisputeOrThrow,resolveDisputeisTerminal(status)helper replacing repeated inline status comparisonsAdminServicenow owns only user management and thin delegatorsTests:
dispute-resolution.service.spec.ts— 7 cases covering happy paths and all guard branchesTesting
All new code is covered by unit tests that run without a database or real cache:
Checklist