Need to reload server to update sequelize relationship scope

Feature(s) impacted

One-to-many relation with scope.

Observed behavior

Context :

There is 2 tables → companies and prices
Companies can have 1:n prices

I split this relation on 3 relations depending of the start_date and end_date to have :

  • Archive prices
  • Current prices
  • Futur prices

To do that I used sequelize scopes :

Companies.hasMany(models.prices, {
      foreignKey: "company_id",
      as: "CurrentPrices",
      scope: {
        [Op.and]: [
          {
            startDate: {
              [Op.lte]: new Date(),
            },
          },
          {
            endDate: { [Op.or]: [null, { [Op.gte]: Date.now() }] },
          },
        ],
      },
    });
    Companies.hasMany(models.prices, {
      foreignKey: "company_id",
      as: "FuturPrices",
      scope: {
        startDate: {
          [Op.gt]: new Date(),
        },
      },
    });
    Companies.hasMany(models.prices, {
      foreignKey: "company_id",
      as: "ArchivePrices",
      scope: {
        endDate: {
          [Op.lt]: new Date(),
        },
      },
    });

Current prices are displayed into the futur prices section until I reload forest server.

Expected behavior

To have prices into the right scope.

Context

  • Project name: Julaya
  • Team name: admin
  • Environment name: production
  • Agent type & version: “forest-express-sequelize”: “^8.0.5”,

Hello,
What do you mean about “are displayed into the future prices section” ? You have some “current price” records inside the “future prices” section ?

Hello @Alban_Bertolin, exactly!

I have prices who match current prices conditions but displayed into futur prices segment. When I restart forest server everything become fine.

Sorry, difficult to explain -_-

Hello,
Can I see your prices model please ? :pray:

1 Like

Hello @Alban_Bertolini,

Here companies / prices models (full code), let me know if you need something else.

Companies model :

const { Op } = require("sequelize");

// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  // This section contains the fields of your model, mapped to your table's columns.
  // Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
  const Companies = sequelize.define(
    "companies",
    {
      customId: {
        type: DataTypes.INTEGER,
      },
      supportCustomId: {
        type: DataTypes.INTEGER,
      },
      name: {
        type: DataTypes.STRING,
      },
      slug: {
        type: DataTypes.STRING,
      },
      description: {
        type: DataTypes.STRING,
      },
      address: {
        type: DataTypes.JSONB,
      },
      createdAt: {
        type: DataTypes.DATE,
      },
      updatedAt: {
        type: DataTypes.DATE,
      },
      doubleValidation: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },
      options: {
        type: DataTypes.JSONB,
      },
      prefix: {
        type: DataTypes.STRING,
      },
      isActive: {
        type: DataTypes.BOOLEAN,
        defaultValue: true,
      },
    },
    {
      tableName: "companies",
      underscored: true,
      schema: process.env.DATABASE_SCHEMA,
    }
  );

  let date = new Date();

  // This section contains the relationships for this model. See: https://docs.forestadmin.com/documentation/v/v6/reference-guide/relationships#adding-relationships.
  Companies.associate = (models) => {
    Companies.hasMany(models.accounts, {
      foreignKey: "company_id",
    });

    Companies.hasMany(models.prices, {
      foreignKey: "company_id",
      as: "CurrentPrices",
      scope: {
        [Op.and]: [
          {
            startDate: {
              [Op.lte]: new Date(),
            },
          },
          {
            endDate: { [Op.or]: [null, { [Op.gte]: Date.now() }] },
          },
        ],
      },
    });
    Companies.hasMany(models.prices, {
      foreignKey: "company_id",
      as: "FuturPrices",
      scope: {
        startDate: {
          [Op.gt]: new Date(),
        },
      },
    });
    Companies.hasMany(models.prices, {
      foreignKey: "company_id",
      as: "ArchivePrices",
      scope: {
        endDate: {
          [Op.lt]: new Date(),
        },
      },
    });
  };

  return Companies;
};

Prices model :

// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models
module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  // This section contains the fields of your model, mapped to your table's columns.
  // Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model
  const Prices = sequelize.define(
    "prices",
    {
      serviceId: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      companyId: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      startDate: {
        type: DataTypes.DATE,
        allowNull: false,
      },
      endDate: {
        type: DataTypes.DATE,
        allowNull: true,
      },
      fees: {
        type: DataTypes.DOUBLE,
      },
      fixFees: {
        type: DataTypes.INTEGER,
      },
      extraFees: {
        type: DataTypes.DOUBLE,
        allowNull: true,
        defaultValue: 0,
      },
    },
    {
      tableName: "prices",
      underscored: true,
      schema: process.env.DATABASE_SCHEMA,
    }
  );

  // This section contains the relationships for this model. See: https://docs.forestadmin.com/documentation/v/v6/reference-guide/relationships#adding-relationships.
  Prices.associate = (models) => {
    Prices.belongsTo(models.services, {
      foreignKey: {
        field: "service_id",
      },
      as: "service",
    });
    Prices.belongsTo(models.companies, {
      foreignKey: {
        field: "company_id",
      },
      as: "company",
    });
  };

  return Prices;
};

Your problem is linked to your scope. When you restart your server the given “new Date()” is evaluated and freeze because it is passed as argument. To evaluate “new Date” every time you should use the
function syntaxe endDate() : { return .... } or by using sequelize.fn('NOW') :slight_smile:
Tell me if it works :slight_smile:

1 Like

Can I close the thread if the the solution works ?

1 Like

Hello @Alban_Bertolini ! Your solution works well, thanks a lot :rocket: