Skip to content

Data Models

Relevant source files - controllers/subscription.controller.js - middlewares/error.middleware.js - models/subscription.model.js - models/user.model.js

The Subscription Tracker API utilizes Mongoose to define structured schemas for MongoDB. The data layer is centered around two primary entities: User and Subscription. These models enforce strict validation, handle data integrity through indexes, and implement automated lifecycle logic via middleware hooks.

User Model

The User model represents an authenticated entity within the system. It stores core identity information and serves as the parent entity for all subscription data.

Schema Definition

The schema is defined in models/user.model.js3-26

Field Type Validation / Rules
name String Required, trim, 2-50 characters models/user.model.js4-10
email String Required, unique, lowercase, regex-validated email format models/user.model.js11-18
password String Required, minimum 6 characters models/user.model.js19-23
createdAt Date Automatically generated by timestamps: truemodels/user.model.js25
updatedAt Date Automatically generated by timestamps: truemodels/user.model.js25

Code Entity Association: User

The following diagram maps the logical user entity to the Mongoose implementation.

User Entity Mapping

[Flowchart Diagram]

Sources: models/user.model.js3-28


Subscription Model

The Subscription model is the core of the application, tracking financial commitments, billing cycles, and categories. It contains complex validation logic and a pre-save hook to manage dates automatically.

Schema Definition

The schema is defined in models/subscription.model.js3-68

Field Type Validation / Enum Values
name String Required, trim, 2-100 characters models/subscription.model.js4-10
price Number Required, minimum 0 models/subscription.model.js11-15
currency String INR, USD, EUR, GBP (Default: INR) models/subscription.model.js16-20
frequency String daily, weekly, monthly, yearlymodels/subscription.model.js21-24
category String basic, standard, premium, enterprisemodels/subscription.model.js25-29
status String active, inactive, canceled, pending, expiredmodels/subscription.model.js35-39
startDate Date Required, must not be in the future models/subscription.model.js40-47
renewalDate Date Must be after startDatemodels/subscription.model.js48-59
user ObjectId Ref: User, Required, Indexed models/subscription.model.js60-65

Automated Lifecycle Logic (Pre-save Hook)

The model implements a Mongoose pre('save') hook to automate date calculations and status transitions before the document is persisted to MongoDB.

  1. Renewal Date Calculation: If renewalDate is not provided, the system calculates it by adding a specific number of days to the startDate based on the frequencymodels/subscription.model.js71-81:

  2. daily: +1 day

  3. weekly: +7 days
  4. monthly: +30 days
  5. yearly: +365 days
  6. Auto-Expiration: If the renewalDate is less than or equal to the current system time, the status is automatically set to 'expired'models/subscription.model.js83

Data Flow: Subscription Creation

The following diagram illustrates how the model interacts with the controller and the database during the creation process.

Subscription Creation Flow

sequenceDiagram
    participant C as "subscription.controller.js"
    participant M as "subscription.model.js (Mongoose)"
    participant DB as "MongoDB"
    C->>M: "Subscription.create(req.body)"
    Note over M: "pre('save') hook triggered"
    M->>M: "Calculate renewalDate"
    M->>M: "Check if status == 'expired'"
    M->>DB: "Persist Document"
    DB-->>C: "Return Saved Document"

Sources: models/subscription.model.js70-84controllers/subscription.controller.js5-10


Indexing and Performance

To ensure efficient querying, especially for user-specific data and upcoming reminders, the following indexes are implemented:

  • User Foreign Key: The user field in the Subscription model is indexed to optimize Subscription.find({ user: userId }) calls models/subscription.model.js64
  • Unique Email: The email field in the User model is unique, preventing duplicate registrations and speeding up authentication lookups models/user.model.js14

Error Handling for Models

The system uses a global errorMiddleware to catch and format Mongoose-specific errors:

Sources: middlewares/error.middleware.js1-37models/subscription.model.js86-88models/user.model.js28-30