# Query Classes

Database query encapsulation layer. Each query class wraps Eloquent calls for a specific model or domain area, providing reusable query methods used by controllers and services. Use these instead of writing queries directly in controllers.

## Files

| Query Class | Description |
|-------------|-------------|
| `AdminQuery` | Retrieves non-deleted admin records by primary key |
| `ArticleQuery` | Fetches and updates individual article records |
| `ChapterQuery` | Queries chapter lists with day relationships for a given program |
| `CouponQuery` | Validates, checks eligibility, and applies discount coupons |
| `CurrencyQuery` | Looks up currencies by ID, code, symbol, country, or active status |
| `FailedUserPaymentQuery` | Retrieves failed payment records by primary key |
| `LanguageQuery` | Finds active, non-deleted languages by language code |
| `LogQuery` | Inserts new log records into the logs table |
| `LoginQuery` | Manages OTP-based login: generate, create, expire, and retrieve OTPs |
| `OnBoardingQuery` | Retrieves the start URL for a language-specific onboarding flow |
| `PartnerEventQuery` | Creates partner event tracking records |
| `PartnerQuery` | Finds B2B partner records by ID or name |
| `PersonalityTypeQuery` | Finds personality type records by primary key |
| `ProductCodeQuery` | Looks up product/pricing codes by program, discount, platform, and country |
| `ProgramQuery` | Retrieves program records and fetches voucher-eligible programs |
| `RazorpayListenerQuery` | Creates Razorpay webhook records and looks up subscriptions by order ID |
| `StripeListenerQuery` | Creates Stripe webhook listener records |
| `SubModuleQuery` | Queries submodules within chapters; evaluates JSON-based alternate content |
| `SubScreenQuery` | Finds non-deleted sub-screens by program and screen identifier |
| `TransactEmailQuery` | Creates, finds, and updates transactional email records by hashed email |
| `UserActivityQuery` | Gets and updates user activity from program-specific dynamic tables |
| `UserAngelQuery` | CRUD for user-angel (accountability partner) relationships |
| `UserAppActivityQuery` | Tracks app engagement: activity records and article view tracking |
| `UserChapterQuery` | Manages per-user chapter progress, submodule position, and ratings |
| `UserConfigQuery` | CRUD for user configuration records (onboarding status, preferences) |
| `UserDataQuery` | CRUD for user data with joined profile/config queries |
| `UserDayQuery` | Creates user-day records in program-specific dynamic tables |
| `UserEmailQuery` | Manages user email preferences and unsubscribe tracking |
| `UserInfoQuery` | Manages user info (email, mobile, tokens) and verifies access tokens |
| `UserProfileQuery` | Creates/updates user profiles and retrieves display names |
| `UserProgramQuery` | Manages user-program enrollment: subscription status, creation, updates |
| `UserQuery` | Core user CRUD: find by ID/email/encrypted ID, create with auto-encrypted IDs |
| `UserRazorPaymentQuery` | CRUD for Razorpay payment records by user and order ID |
| `UserSSOQuery` | Creates SSO token records for users |
| `UserSourceQuery` | Creates user source/attribution tracking records |
| `UserSubHistoryQuery` | Manages subscription history: expire active subscriptions, create records |
| `UserSubmoduleFeedbackQuery` | Manages per-user submodule feedback in program-specific dynamic tables |
| `UserSubscriptionQuery` | Creates new user subscription records |
| `VoucherQuery` | Checks voucher existence/validity, retrieves with type/profile details |
| `WebLoginDiscountQuery` | Finds web login discount configs by link source and program |

## Method Naming Conventions

| Prefix | Purpose | Examples |
|--------|---------|---------|
| `get*` | Retrieve one or more records | `getUser()`, `getActive()`, `getActiveOTP()` |
| `getBy*` | Find by a specific field | `getByEmail()`, `getByCode()`, `getByName()` |
| `create*` | Insert a new record | `create()`, `createUser()`, `createUserProfile()` |
| `update*` | Modify existing records | `update()`, `updateSubModuleID()`, `updateByUserId()` |
| `check*` | Boolean existence/validation | `checkCoupon()`, `checkEmailExist()` |
| `find*` | Find single record by key | `find()`, `findById()`, `findByName()` |
| `expire*` | Soft-expire records | `expirePreviousOTP()`, `expireActiveSubscriptions()` |
| `userHas*` | Boolean user-scoped existence | `userHasVoucher()`, `userHasVoucherWithEmail()` |

## Conventions

- **Dynamic tables**: Several query classes use `setTable($programId)` or `forProgram($programId)` for program-specific tables (UserActivity, UserChapter, UserDay, UserSubmoduleFeedback, SubModule, Chapter)
- **Soft deletes**: Filtered manually via `bDeleted = 0` rather than Laravel's SoftDeletes trait
- **Column selection**: Parameterized with `$columns = ['*']` defaults
- **Error returns**: Structured arrays with translated messages (e.g., CouponQuery's `fail()` helper)
