SolidX
TutorialSchool Fees Portal RevampedData Modeling

Student Model

Business Purpose: Represents a student in an institute. This model stores personal and contact information for the student and their parent/guardian, and it includes fields to facilitate a separate login portal for them.

Fields:

Field NameTypeDescription
studentNameshortTextThe full name of the student.
studentEmailAddressshortTextThe student's email address.
studentMobileNumbershortTextThe student's mobile number.
parentNameshortTextThe name of the parent or guardian.
parentMobileNumbershortTextThe parent's or guardian's mobile number.
parentEmailAddressshortTextThe parent's or guardian's email address.
studentIdshortTextThe official student ID provided by the institute.
instituterelationA many-to-one relationship to the institute model.
paymentsrelationA one-to-many relationship to the payment model.
otpshortTextOne-time password for student/parent login.
otpExpiresAtdatetimeExpiry time for the OTP.
tokenlongTextAuthentication token for the student/parent session.
studentLoginIdcomputedA unique login ID for the student, computed from their name.

Key Fields Explained

  • otp, otpExpiresAt, token: These fields are not for the admin panel. They are specifically designed to support the separate, student-facing payment portal. The workflow is:
    1. A student/parent enters their mobile number or email to log in.
    2. The system generates an otp (One-Time Password) and saves it along with an otpExpiresAt timestamp.
    3. The user enters the OTP. If valid, the system generates a long-lived token (like a JWT) that keeps them logged in on that device.
  • studentLoginId (Computed): This field is the User Key for the student. It's a unique ID automatically generated by SolidX by combining the student's name with a random alphanumeric string (e.g., john-doe-a4f81). This provides a stable, unique identifier for each student.
  • payments (Inverse Relation): This field represents the "one-to-many" side of the relationship between a Student and their Payments. You do not need to create this field yourself. When you define the many-to-one relationship from the Payment model back to the Student model, SolidX will automatically add this payments field, which holds a list of all payment records associated with the student.

To generate studentLoginId please refer use cases section of this tutorial.

Creation Steps

If you are following the manual "Guided Tour", follow these steps to create the Student model in the App Builder.

  1. Navigate to Fees Portal > App Builder > Model and click Add.
  2. Fill in the primary details for the model:
    • Singular Name: student
    • Plural Name: students
    • Display Name: Student
  3. Go to the Fields tab.
  4. Click Add Field and create each field exactly as defined in the table above.
  5. Click Save.

For the Fast Track: Model Metadata The JSON block below contains the complete metadata definition for the Student model.

This definition is structured with top-level properties for the model itself (like singularName, pluralName, tableName) and a fields array that defines every attribute you see in the table above.

You can use this metadata as part of the "Fast Track" approach by including it in the main fees-portal-metadata.json file.

{
  "singularName": "student",
  "pluralName": "students",
  "displayName": "Student",
  "description": "This table allows us to store student records institute wise",
  "dataSource": "default",
  "dataSourceType": "postgres",
  "tableName": "fees_portal_student",
  "userKeyFieldUserKey": "studentLoginId",
  "isChild": false,
  "enableAuditTracking": true,
  "enableSoftDelete": false,
  "draftPublishWorkflow": false,
  "internationalisation": false,
  "fields": [
    {
      "name": "studentName",
      "displayName": "Student Name",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": true,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "studentEmailAddress",
      "displayName": "Student Email Address",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": false,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "studentMobileNumber",
      "displayName": "Student Mobile Number",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": false,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "parentName",
      "displayName": "Parent Name",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": true,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "parentMobileNumber",
      "displayName": "Parent Mobile Number",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": true,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "parentEmailAddress",
      "displayName": "Parent Email Address",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": true,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "studentId",
      "displayName": "Student Id",
      "description": null,
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": true,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "institute",
      "displayName": "Institute",
      "description": null,
      "type": "relation",
      "ormType": "integer",
      "isSystem": false,
      "relationType": "many-to-one",
      "relationCoModelFieldName": null,
      "relationCreateInverse": false,
      "relationCoModelSingularName": "institute",
      "relationCoModelColumnName": null,
      "relationModelModuleName": "fees-portal",
      "relationCascade": "cascade",
      "required": true,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "relationJoinTableName": null,
      "isRelationManyToManyOwner": null,
      "relationFieldFixedFilter": "",
      "enableAuditTracking": true
    },
    {
      "name": "otp",
      "displayName": "Otp",
      "description": "This is used to store student otp",
      "type": "shortText",
      "ormType": "varchar",
      "isSystem": false,
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": false,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": false,
      "enableAuditTracking": true
    },
    {
      "name": "otpExpiresAt",
      "displayName": "Otp Expires At",
      "description": "This is the time when otp get expired",
      "type": "datetime",
      "ormType": "timestamp",
      "isSystem": false,
      "defaultValue": null,
      "required": false,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "enableAuditTracking": true
    },
    {
      "name": "token",
      "displayName": "Token",
      "description": null,
      "type": "longText",
      "ormType": "text",
      "isSystem": false,
      "regexPattern": "",
      "regexPatternNotMatchingErrorMsg": "",
      "defaultValue": null,
      "min": null,
      "max": null,
      "required": false,
      "unique": false,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null
    },
    {
      "name": "studentLoginId",
      "displayName": "Student Login ID",
      "description": "Student Login ID",
      "type": "computed",
      "ormType": "varchar",
      "isSystem": false,
      "computedFieldValueType": "string",
      "computedFieldTriggerConfig": [
        {
          "modelName": "student",
          "moduleName": "fees-portal",
          "operations": [
            "before-insert"
          ]
        }
      ],
      "computedFieldValueProvider": "AlphaNumExternalIdComputationProvider",
      "computedFieldValueProviderCtxt": "{\n  \"dynamicFieldPrefix\": \"studentName\",\n  \"length\": 5\n}",
      "required": true,
      "unique": true,
      "index": false,
      "private": false,
      "encrypt": false,
      "encryptionType": null,
      "decryptWhen": null,
      "columnName": null,
      "isUserKey": true
    }
  ]
}