- Implemented a unified `getAndSet` method in RedisService to handle caching for single, list, and paginated responses. - Removed redundant cache checks and writes in various services, simplifying the code and improving readability. - Updated GoodsService, StockKeepingUnitsService, PartnerActivatedLicensesService, and others to utilize the new caching mechanism. - Adjusted Prisma connection limit for better resource management.
11 KiB
GapCode Agent Instructions
AGENTS.md
Operational guide for AI/coding agents working in consumer_api.
⚡ RTK LOW-TOKEN EXECUTION POLICY (MANDATORY)
This repository uses RTK (Rust Token Killer).
All shell interactions MUST prefer RTK wrappers to reduce token usage.
If an RTK equivalent exists, never use the raw command.
This repository can be large; uncontrolled shell output will quickly exhaust model context.
✅ COMMAND REWRITE RULES (STRICT)
Always rewrite commands using RTK:
git status → rtk git status git diff → rtk git diff git log → rtk git log ls → rtk ls tree → rtk ls cat → rtk read grep → rtk grep rg → rtk grep find → rtk find
Never run:
- raw git commands for inspection
- raw cat
- raw grep
- raw ls
- raw tree
📂 CODE NAVIGATION WORKFLOW (MANDATORY)
When working in this repository follow this order:
1️⃣ Discover structure
rtk ls
2️⃣ Search before opening files
rtk grep <symbol | class | function | DTO | service>
3️⃣ Read only the necessary files
rtk read
4️⃣ For large files (>300 lines)
rtk read -l aggressive
5️⃣ For quick understanding
rtk smart
Never open many files blindly.
Never read entire modules without searching first.
🧠 DIFF INSPECTION RULES
For reviewing repository changes:
Use:
rtk git diff
For large diffs:
rtk git diff -l aggressive
Never run raw git diff.
📁 FORBIDDEN PATHS
Never inspect or read these directories unless explicitly required:
node_modules/ dist/ build/ coverage/ .prisma/ prisma/migrations/
These folders produce extremely large outputs and waste tokens.
📄 FILE READING POLICY
Preferred:
rtk read file.ts
Large file:
rtk read file.ts -l aggressive
Quick overview:
rtk smart file.ts
Never use cat for source code inspection.
🔎 SEARCH POLICY
Always search before opening files.
Use:
rtk grep
Avoid raw recursive searches.
🎯 TOKEN SAFETY RULES
- Never scan the entire repository.
- Never dump full logs.
- Never output entire large files.
- Prefer targeted inspection.
Token preservation is mandatory for this project.
Scope
- Applies to the whole repository.
- Stack: NestJS + Prisma + TypeScript.
Primary Goals
- Deliver minimal, safe, and focused changes.
- Preserve existing API behavior unless explicitly requested.
- Keep Prisma schema/data operations forward-safe.
Project Conventions
- Keep module layering consistent:
controller -> service -> prisma/shared service. - Reuse shared services for cross-module business logic (for example, sales invoice create flow).
- Keep DTO validation at API boundaries; avoid unchecked
anyin new code. - Keep response shaping aligned with existing
ResponseMapperusage. - Prefer explicit Prisma
select/includeto control payload shape.
Sales Invoice / TSP Rules
originalSend,correctionSend, andrevokeflows should be consistent and auditable.- For correction/revoke creation, prepare data from the related invoice when required.
- Persist attempt records with clear status transitions (
QUEUED-> final status). - Store request/response payloads for traceability.
- Avoid changing fiscal/tax status semantics without explicit approval.
Prisma and Migration Safety
- Treat committed migrations as immutable history.
- Prefer forward migrations; avoid destructive resets unless explicitly requested.
- For data-affecting changes:
- use transactions,
- verify expected row scope,
- keep logic idempotent where possible.
Editing Principles
- Do not modify unrelated files.
- Do not revert user changes unless asked.
- Keep functions cohesive; extract shared logic when duplication appears.
- Remove debug leftovers (
console.log, dead code) before finishing unless explicitly needed.
Validation Checklist (before handoff)
- Read target module/service/DTO end-to-end before edits.
- Apply minimal patch with consistent naming.
- Run typecheck:
pnpm -s tsc --noEmit. - If behavior changed, run targeted checks/tests where possible.
- Summarize changed files and behavior impact clearly.
Useful Commands
- Typecheck:
pnpm -s tsc --noEmit - Migration status:
pnpm prisma migrate status - Create migration:
pnpm prisma migrate dev --name <name> - Deploy migrations:
pnpm prisma migrate deploy
Communication Style
- Be concise and implementation-focused.
- Call out assumptions/risk before risky steps.
- Provide practical next actions after task completion.
Do / Don't (Repo-Specific)
Do
- Do derive correction/revoke invoice creation data from
relatedInvoicewhen the flow requires historical consistency. - Do keep TSP attempt lifecycle explicit (
QUEUED, then update with provider result and timestamps). - Do use shared invoice-creation service instead of duplicating create logic across modules.
- Do normalize numeric DB values (
Decimal) withNumber(...)before DTO/payload composition. - Do keep Prisma queries tight with
select/includeonly for fields you actually use.
Don't
- Don't pass undefined/out-of-scope variables in TSP flows (common regressions:
invoice_id,attemptId,pos_idmismatches). - Don't leave placeholder query blocks (for example empty
select: {}) in production code. - Don't mix method semantics (
sendvsoriginalSend) across services without verifying signatures. - Don't leave debug logs (
console.log) in critical invoice/tax paths unless explicitly requested. - Don't change invoice type semantics (
ORIGINAL,CORRECTION,REVOKE) implicitly.
Common Pitfalls To Recheck
- Incorrect relation field names (
tax_idon wrong model, missing relation selects). - Building payloads from the wrong invoice (must match the expected new/ref invoice in each flow).
- Creating attempts without persisting request payload and final response payload.
- Mismatch between DTO shapes and shared service input contracts.
Thread Notes (May 2026)
- Shared sale-invoice creation was introduced and must be injected/exported correctly in consuming modules (example failure:
UnknownDependenciesExceptionforSharedSaleInvoiceCreateService). - In
SalesInvoiceTspService.revoke, prepare all creation/update data fromrelatedInvoice(no externaldataToUpdateargument expected). - Prisma client is generated to
src/generated/prismavia:provider = "prisma-client"output = "../../src/generated/prisma"moduleFormat = "cjs"
- Docker/runtime must include generated Prisma artifacts and
@prisma/clientruntime; missing@prisma/client/runtime/clientindicates build/copy/install mismatch. - Seeder commands that use
tsxrequire dev dependencies/runtime tools; if running in slim production container, use a dedicated seed target/container or run seed from build/dev image. pnpminvocation in containers should use executable form (pnpm ...), notnode /app/pnpm.- Added SQL/Prisma error normalization utility:
src/common/utils/prisma-error.util.ts; prefer mapping duplicate/constraint DB errors to domain-friendly messages. - Partner-module list endpoints were standardized toward
ResponseMapper.paginatewhere pagination response contract is expected. - For heavy license provisioning (100+), request path should not synchronously insert all licenses; queue/background + batching is required.
Migration Drift Playbook (Prisma/MySQL)
- If Prisma reports
modified after applied, never edit an already-applied migration in-place for shared environments; create a new forward migration instead. - If migration history and DB drift mismatch:
- Verify local migration folders are complete and ordered.
- Check
_prisma_migrationsfor missing/applied names. - Use
prisma migrate resolveonly to reconcile history state, then apply a forward fix migration.
- Duplicate FK error seen in this repo:
sales_invoices_ref_id_fkey(MySQL 1826). Recheck migration SQL for repeatedADD CONSTRAINTstatements before rerun. - Drift that repeatedly showed in this project: missing FK/unique on
sale_invoice_tsp_attempts.invoice_id. Validate both schema and migration SQL produce the same final state. prisma migrate statusmay show up-to-date whilemigrate devstill detects drift (shadow DB/application history issue); treatmigrate devoutput as source of truth for fixing local history.
Redis Cache Conventions (May 2026)
- Use
RedisKeyMakerinsrc/common/utils/redis-key-maker.util.tsfor all cache keys and wildcard patterns; do not inline key strings in services. - Keep invalidation domain-based (for example
src/modules/admin/guilds/cache/*,src/modules/admin/partners/cache/*,src/modules/pos/cache/*) and avoid duplicating delete logic across modules. - For list APIs that are expensive or frequently read, prefer read-through cache with TTL and invalidation on every related write path.
- For entity endpoints, use list + detail split:
- list key(s): invalidated broadly on writes,
- detail key(s): invalidated per entity id.
- Partner domain rules:
- Shared partner cache namespace is
partners:*(not admin-prefixed) because writes occur in bothadmin/partnersandpartnersmodules. - Use shared invalidation service
src/modules/partners/cache/partners-cache-invalidation.service.tsfrom both admin and partner write paths. - Invalidate
partners:listandpartners:{id}:detailon partner create/update/delete and license-affecting writes. - Invalidate partner license caches (activated-licenses list, charge-transactions list/detail) via the shared invalidation service.
- Shared partner cache namespace is
- POS goods rules:
- Cache key shape is BA + guild scoped (
pos:ba:{businessActivityId}:guild:{guildId}:goods:list) because results combine guild-default and BA-owned goods. - Invalidate POS goods cache by guild when admin guild goods/category/sku changes.
- Invalidate POS goods cache by business activity when consumer BA goods create/update/delete.
- Cache key shape is BA + guild scoped (
- Consumer/Partner hierarchy rules:
- Consumer profile cache key:
consumers:{consumerId}:info. - Partner-consumer profile cache key:
partners:{partnerId}:consumers:{consumerId}:info. - On partner-consumer single read, write both keys when practical to share warm cache across modules.
- On consumer info update or partner-consumer update, invalidate both consumer and partner-consumer profile keys.
- For business activities, invalidate both list and detail layers; child updates may invalidate parent single cache when parent aggregates depend on child state.
- Consumer profile cache key:
- Wildcard invalidation implementation:
- Use
RedisService.deleteByPattern/RedisService.deleteByPatternsfor all pattern deletes. - Do not implement ad-hoc scan/delete loops inside domain services.
- Pattern deletion uses
SCAN+ pipelinedDEL; multi-pattern deletes run in parallel.
- Use