Feature(s) impacted
Smart fields no longer computed after editing
Observed behavior
I have this collection :
// 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 Contracts = sequelize.define('contracts', {
displayName: {
type: DataTypes.STRING,
defaultValue: "",
allowNull: false,
},
amount: {
type: DataTypes.BIGINT,
defaultValue: 0,
allowNull: false,
},
createdAt: {
type: DataTypes.DATE,
},
updatedAt: {
type: DataTypes.DATE,
},
parcelSergicId: {
type: DataTypes.INTEGER,
},
sergicUpdateTime: {
type: DataTypes.DATE,
},
customerReferenceNumber: {
type: DataTypes.STRING,
},
customerKey: {
type: DataTypes.STRING,
},
invitedCount: {
type: DataTypes.INTEGER,
defaultValue: 0,
allowNull: false,
},
reminderGroup: {
type: DataTypes.INTEGER,
defaultValue: 8,
},
reportAccountEntryAmount: {
type: DataTypes.BIGINT,
defaultValue: 0,
},
reportAccountEntryOperationDate: {
type: DataTypes.DATE,
},
deletedAt: {
type: DataTypes.DATE,
},
coownerAmount: {
type: DataTypes.BIGINT,
defaultValue: Sequelize.literal('0.0'),
},
pendingAmount: {
type: DataTypes.INTEGER,
defaultValue: 0,
allowNull: false,
},
dueDate: {
type: DataTypes.DATE,
},
occupant: {
type: DataTypes.BOOLEAN,
},
startDate: {
type: DataTypes.DATEONLY,
},
endDate: {
type: DataTypes.DATEONLY,
},
lastReminderGroupUpdate: {
type: DataTypes.DATEONLY,
},
}, {
tableName: 'contracts',
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.
Contracts.associate = (models) => {
Contracts.belongsTo(models.identities, {
foreignKey: {
name: 'identityIdKey',
field: 'identity_id',
},
as: 'identity',
});
Contracts.belongsTo(models.places, {
foreignKey: {
name: 'placeIdKey',
field: 'place_id',
},
as: 'place',
});
Contracts.belongsTo(models.integrations, {
foreignKey: {
name: 'placeIdKey',
field: 'place_id',
},
as: 'integration',
});
Contracts.belongsToMany(models.parcels, {
through: 'parcelContracts',
foreignKey: 'contract_id',
otherKey: 'parcel_id',
as: 'parcelsThroughParcelContracts',
});
// decomposition de la relation ci-dessus en 2
Contracts.hasMany(models.parcelContracts, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'contractParcel',
});
Contracts.hasMany(models.managementFees, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'managementFees',
});
Contracts.hasMany(models.contractDocuments, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'contractDocuments',
});
Contracts.hasMany(models.accountEntries, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'accountEntries',
});
Contracts.hasMany(models.alerts, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'alerts',
});
Contracts.hasMany(models.publicWorkDetails, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'publicWorkDetails',
});
Contracts.hasMany(models.convocationSettings, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'convocationSettings',
});
Contracts.hasMany(models.preEtatDateRequests, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'preEtatDateRequests',
});
Contracts.hasMany(models.contractRepartitionKeys, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'contractRepartitionKeys',
});
Contracts.hasMany(models.waterReadings, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'waterReadings',
});
// relation creee manuellement pour les mandataires de compte client
Contracts.hasMany(models.roles, {
foreignKey: {
name: 'contractIdKey',
field: 'resource_id',
},
as: 'roles',
});
Contracts.hasOne(models.moneyOrders, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'moneyOrder',
});
Contracts.hasOne(models.contractAddresses, {
foreignKey: {
name: 'contractIdKey',
field: 'contract_id',
},
as: 'contractAddress',
});
};
return Contracts;
};
with a bunch of smart fields :
const { collection } = require('forest-express-sequelize');
const models = require('../models');
const { Sequelize } = require('sequelize');
const Op = require('sequelize').Op;
const axios = require('axios').default;
const API_URL = process.env.API_URL;
// This file allows you to add to your Forest UI:
// - Smart actions: https://docs.forestadmin.com/documentation/reference-guide/actions/create-and-manage-smart-actions
// - Smart fields: https://docs.forestadmin.com/documentation/reference-guide/fields/create-and-manage-smart-fields
// - Smart relationships: https://docs.forestadmin.com/documentation/reference-guide/relationships/create-a-smart-relationship
// - Smart segments: https://docs.forestadmin.com/documentation/reference-guide/segments/smart-segments
collection('contracts', {
actions: [],
fields: [{
field: 'reference immeuble',
type: 'String',
get: contract => models.places.findByPk(contract.placeIdKey)
.then(place => place ? place.sergicIdFull : ''),
search: (query, search) => {
const searchCondition = {
[Op.or]: [
{ '$place.sergic_id_full$': { [Op.iLike]: `%${search}%` } }
],
};
query.where[Op.and][0][Op.or].push(searchCondition);
if (!query.include.find((include) => include.as === 'place')) {
query.include.push({
model: models.places,
as: 'place',
});
}
return query;
}
}, {
field: 'nom complet',
type: 'String',
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity ? `${identity.lastName ? identity.lastName.toUpperCase() : ''} ${identity.firstName ? identity.firstName : ''}` : ''),
search: (query, search) => {
const split = search.split(' ');
const searchCondition = {
[Op.or]: [
{ '$identity.last_name$': { [Op.iLike]: `%${split[0]}%` } },
{ '$identity.last_name$': { [Op.iLike]: `%${split[1]}%` } },
{ '$identity.first_name$': { [Op.iLike]: `%${split[0]}%` } },
{ '$identity.first_name$': { [Op.iLike]: `%${split[1]}%` } },
],
};
query.where[Op.and][0][Op.or].push(searchCondition);
if (!query.include.find((include) => include.as === 'identity')) {
query.include.push({
model: models.identities,
as: 'identity',
});
}
return query;
}
}, {
field: 'ID client',
type: 'String',
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity && identity.sergicId ? identity.sergicId : '')
}, {
field: 'civilite',
type: 'Enum',
enums: [
'Madame et Monsieur',
'Madame ou Monsieur',
'Madame',
'Mesdames',
'Madame, Mademoiselle ou Monsieur',
'Monsieur',
'Messieurs',
'Mademoiselle',
'Succession',
'Indivision',
'Société civile immobilière',
'Compagnie',
'Société',
'Groupe',
'Administrations',
'Société civile promotion immobilière',
'Société civile construction vente',
'Maître',
'Maîtres',
'Cabinet',
'Docteur',
'Notaire',
'Etablissements',
'Entreprise unipersonnelle à responsabilité limitée',
'Groupement d\'intéret économique',
'Société anonyme',
'Société à responsabilité limitée',
'Société anonyme simplifiée',
'Société civile',
'Société civile de moyens',
'Société d\'économie mixte',
'Société en nom collectif',
'Société privée européenne',
'Entreprise individuelle à responsabilité limitée',
'Syndicat',
'Association syndicale libre',
'Association',
'Banque',
'Club',
],
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity && identity.title ? identity.title : '')
}, {
field: 'nom',
type: 'String',
get: contract => {
console.log(contract);
return models.identities.findByPk(contract.identityIdKey)
.then(identity => identity && identity.lastName ? identity.lastName.toUpperCase() : '');
}
}, {
field: 'prenom',
type: 'String',
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity ? identity.firstName : '')
}, {
field: 'Invite a la connexion',
type: 'Boolean',
}, {
field: 'telephone',
type: 'String',
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity && identity.phoneNumber ? identity.phoneNumber : ''),
search: (query, search) => {
const searchCondition = {
[Op.or]: [
{ '$identity.phone_number$': { [Op.iLike]: `%${search}%` } }
],
};
query.where[Op.and][0][Op.or].push(searchCondition);
if (!query.include.find((include) => include.as === 'identity')) {
query.include.push({
model: models.identities,
as: 'identity',
});
}
return query;
}
}, {
field: 'telephone domicile',
type: 'String',
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity && identity.homePhone ? identity.homePhone : '')
}, {
field: 'email',
type: 'String',
get: contract => models.identities.findByPk(contract.identityIdKey)
.then(identity => identity && identity.email ? identity.email : ''),
search: (query, search) => {
const searchCondition = {
[Op.or]: [
{ '$identity.email$': { [Op.iLike]: `%${search}%` } }
],
};
query.where[Op.and][0][Op.or].push(searchCondition);
if (!query.include.find((include) => include.as === 'identity')) {
query.include.push({
model: models.identities,
as: 'identity',
});
}
return query;
}
}, {
field: 'lots',
type: 'String',
get: contract => models.contracts.findAll({
where: { id: contract.id },
include: [{
model: models.parcels,
as: 'parcelsThroughParcelContracts'
}]
}).then(results => {
if (results[0].parcelsThroughParcelContracts) {
return results[0].parcelsThroughParcelContracts.map(lot =>
lot.displayName + (lot.doorNumber ? ' ' + lot.doorNumber : '')).join(', ');
}
})
}, {
field: 'Date derniere connexion ',
type: 'Date',
get: contract => models.identities.findOne({
where: { id: contract.identityIdKey },
include: [{
model: models.users,
as: 'user'
}],
}).then(identity => identity && identity.user ? identity.user.lastConnectionSyndicone : null)
}, {
field: 'Mandataire',
type: 'String',
get: contract => models.roles.findAll({
where: {
name: 'representative',
resource_type: 'Contract',
resource_id: contract.id,
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles',
required: true,
}]
}).then(roles => {
if (roles[0]) {
const identity = roles[0].identitiesThroughIdentitiesRoles[0];
return `${identity.title} ${identity.lastName.toUpperCase()} ${identity.firstName ? identity.firstName : ''}`;
}
})
}, {
field: 'Telephone mandataire',
type: 'String',
get: contract => models.roles.findAll({
where: {
name: 'representative',
resource_type: 'Contract',
resource_id: contract.id,
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles',
required: true,
}]
}).then(roles => {
if (roles[0]) {
const identity = roles[0].identitiesThroughIdentitiesRoles[0];
return `${identity.phoneNumber}`;
}
})
}, {
field: 'Email mandataire',
type: 'String',
get: contract => models.roles.findAll({
where: {
name: 'representative',
resource_type: 'Contract',
resource_id: contract.id,
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles',
required: true,
}]
}).then(roles => {
if (roles[0]) {
const identity = roles[0].identitiesThroughIdentitiesRoles[0];
return `${identity.email}`;
}
})
}, {
field: 'Adresse mandataire',
type: 'String',
get: contract => models.roles.findAll({
where: {
name: 'representative',
resource_type: 'Contract',
resource_id: contract.id,
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles',
required: true,
include: [{
model: models.addresses,
as: 'addresses',
required: true,
where: { addressable_type: 'Identity' }
}]
}]
}).then(roles => {
if (roles[0]) {
const address = roles[0].identitiesThroughIdentitiesRoles[0].addresses[0];
return `${address.streetNumber} ${address.street} ${address.complementary ? address.complementary : ''} ${address.zipCode} ${address.city.toUpperCase()} ${address.country}`;
}
})
}, {
field: 'Adresse postale',
type: 'String',
get: contract => models.addresses.findOne({
where: {
addressable_id: contract.identityIdKey,
addressable_type: 'Identity'
}
}).then(address => address && address.street ? `${address.streetNumber} ${address.street} ${address.complementary ? address.complementary : ''} ${address.zipCode} ${address.city.toUpperCase()} ${address.country ? address.country.toUpperCase() : ''}` : '')
}, {
field: 'nature juridique',
type: 'Enum',
enums: ['natural_person', 'legal_entity'],
get: contract => models.roles.findAll({
where: {
name: 'representative',
resource_type: 'Contract',
resource_id: contract.id,
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles',
required: true,
}]
}).then(roles => roles[0] && roles[0].identitiesThroughIdentitiesRoles[0] ? roles[0].identitiesThroughIdentitiesRoles[0].legalKind : null)
}, {
field: 'comptes',
type: ['String'],
reference: 'contracts.id'
}, {
field: 'appels de charges dematerialisees',
type: 'Boolean',
get: contract => models.convocationSettings.findOne({
where: { contract_id: contract.id },
order: [['created_at', 'DESC']],
}).then(convocationSetting => convocationSetting ? convocationSetting.acceptDematerializedMail : null)
}, {
field: 'convocation ag',
type: 'Enum',
enums: ['dematerialized_only', 'paper_except_annexes', 'paper_only'],
get: contract => models.convocationSettings.findOne({
where: { contract_id: contract.id },
order: [['created_at', 'DESC']],
}).then(convocationSetting => convocationSetting && convocationSetting.auxilliaryDocumentsShipment ? convocationSetting.auxilliaryDocumentsShipment : null)
}, {
field: 'statut du mandat Yousign',
type: 'Enum',
enums: ['unsigned', 'waiting', 'init', 'signed_complete'],
get: contract => models.convocationSettings.findOne({
where: { contract_id: contract.id },
order: [['created_at', 'DESC']],
}).then(convocationSetting => convocationSetting && convocationSetting.state ? convocationSetting.state : null)
}, {
field: 'derniere modification',
type: 'Date',
get: contract => models.convocationSettings.findOne({
where: { contract_id: contract.id },
order: [['created_at', 'DESC']],
}).then(convocationSetting => convocationSetting ? convocationSetting.updatedAt : null)
}, {
field: 'Envoi de la convoc AG au mandataire',
type: 'Boolean',
get: contract => models.convocationSettings.findOne({
where: { contract_id: contract.id },
order: [['created_at', 'DESC']],
}).then(convocationSetting => convocationSetting ? convocationSetting.sendConvocationToRepresentative : null)
}, {
field: 'Envoi des charges au mandataire',
type: 'Boolean',
get: contract => models.convocationSettings.findOne({
where: { contract_id: contract.id },
order: [['created_at', 'DESC']],
}).then(convocationSetting => convocationSetting ? convocationSetting.sendExpenseReportToRepresentative : null)
}, {
field: 'Mode de paiement',
type: 'Enum',
enums: ['auto_usual', 'auto', 'manual'],
get: contract => models.moneyOrders.findOne({
where: { contract_id: contract.id }
}).then(moneyOrder => moneyOrder ? moneyOrder.paymentType : null)
}, {
field: 'Mandat de prelevement recu',
type: 'Boolean',
get: contract => models.moneyOrders.findOne({
where: { contract_id: contract.id }
}).then(moneyOrder => moneyOrder ? moneyOrder.yousignState : null)
}, {
field: 'role',
type: 'String',
get: contract => axios.get(`${API_URL}/forest_admin/places/${contract.placeIdKey}/top_place_role/${contract.identityIdKey}`, {
headers: {
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
'X-CURRENT-USER-EMAIL': process.env.SERVICE_EMAIL
},
}).then(res => res.data.display_place_role)
}, {
field: 'solde',
type: 'Number',
get: contract => axios.get(`${API_URL}/forest_admin/places/${contract.placeIdKey}/sage_contract_balance`, {
headers: {
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
'X-CURRENT-USER-EMAIL': process.env.SERVICE_EMAIL
},
params: {
contract_id: contract.id
}
}).then(res => res.data.solde_actuel
).catch(() => null)
}, {
field: 'ecritures-comptables',
type: ['String'],
reference: 'contract-accounting-entries.id'
}, {
field: 'emails',
type: ['String'],
reference: 'contractEmails.id'
}, {
field: 'tickets',
type: ['String'],
reference: 'contractTickets.id'
}, {
field: 'niveau de relance',
type: 'String',
get: contract => models.alerts.findOne({
where: {
contract_id: contract.id,
treated: false
},
order: [['created_at', 'DESC']],
}).then(alert => alert ? alert.reminderLevel : '')
}, {
field: 'date de derniere relance',
type: 'Dateonly',
get: contract => models.alerts.findOne({
where: {
contract_id: contract.id,
treated: false
},
order: [['created_at', 'DESC']],
}).then(alert => alert ? alert.reminderDate : null)
}, {
field: 'alerte traitee',
type: 'Boolean',
get: contract => models.alerts.findOne({
where: {
contract_id: contract.id,
treated: false
},
order: [['created_at', 'DESC']],
}).then(alert => alert ? alert.treated : '')
}, {
field: 'commentaire',
type: 'String',
get: contract => models.alerts.findOne({
where: {
contract_id: contract.id,
treated: false
},
order: [['created_at', 'DESC']],
}).then(alert => alert ? alert.comment : '')
}, {
field: 'gestionnaire',
type: 'String',
get: contract => models.roles.findOne({
where: {
name: 'coowner_manager',
resource_type: 'Place',
resource_id: contract.placeIdKey
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles'
}]
}).then(role => `${role ? role.identitiesThroughIdentitiesRoles[0].firstName : ''} ${role ? role.identitiesThroughIdentitiesRoles[0].lastName.toUpperCase() : ''}`),
search: async (query, search) => {
const { QueryTypes, Op } = models.objectMapping;
const split = search.split(' ');
// NOTICE: complexe raw query to gather all ids from the places collection that match your business needs
const contractsIds = await models.connections.default.query(`
SELECT contracts.id FROM contracts
INNER JOIN places ON places.id = contracts.place_id
INNER JOIN roles ON places.id = roles.resource_id
INNER JOIN identities_roles ON identities_roles.role_id = roles.id
INNER JOIN identities ON identities.id = identities_roles.identity_id
WHERE roles.name = 'coowner_manager'
AND roles.resource_type = 'Place'
AND (identities.first_name ILIKE '%${split[0]}%'
OR identities.last_name ILIKE '%${split[0]}%'
OR identities.last_name ILIKE '%${split[1]}%'
OR identities.last_name ILIKE '%${split[1]}%')`,
{ type: QueryTypes.SELECT });
// NOTICE: fill the where condition with a simple `id in (ArrayOfIds)` to match ids returned by the complexe query making the polymorphic joins
const searchCondition = { id: { [Op.in]: contractsIds.map(a => a.id) } };
query.where[Op.and][0][Op.or].push(searchCondition);
}
}, {
field: 'assistant copro',
type: 'String',
get: contract => models.roles.findOne({
where: {
name: 'coowner_assistant',
resource_type: 'Place',
resource_id: contract.placeIdKey
},
include: [{
model: models.identities,
as: 'identitiesThroughIdentitiesRoles'
}]
}).then(role => `${role ? role.identitiesThroughIdentitiesRoles[0].firstName : ''} ${role ? role.identitiesThroughIdentitiesRoles[0].lastName.toUpperCase() : ''}`),
search: async (query, search) => {
const { QueryTypes, Op } = models.objectMapping;
const split = search.split(' ');
// NOTICE: complexe raw query to gather all ids from the places collection that match your business needs
const contractsIds = await models.connections.default.query(`
SELECT contracts.id FROM contracts
INNER JOIN places ON places.id = contracts.place_id
INNER JOIN roles ON places.id = roles.resource_id
INNER JOIN identities_roles ON identities_roles.role_id = roles.id
INNER JOIN identities ON identities.id = identities_roles.identity_id
WHERE roles.name = 'coowner_assistant'
AND roles.resource_type = 'Place'
AND (identities.first_name ILIKE '%${split[0]}%'
OR identities.last_name ILIKE '%${split[0]}%'
OR identities.last_name ILIKE '%${split[1]}%'
OR identities.last_name ILIKE '%${split[1]}%')`,
{ type: QueryTypes.SELECT });
// NOTICE: fill the where condition with a simple `id in (ArrayOfIds)` to match ids returned by the complexe query making the polymorphic joins
const searchCondition = { id: { [Op.in]: contractsIds.map(a => a.id) } };
query.where[Op.and][0][Op.or].push(searchCondition);
}
}, {
field: 'cgu acceptees',
type: 'String',
get: contract => models.identities.findOne({
where: { id: contract.identityIdKey },
include: [{
model: models.users,
as: 'user'
}]
}).then(identity => identity && identity.user && identity.user.termVersionSyndicone ? identity.user.termVersionSyndicone : '')
}],
segments: [],
});
I edit a record as so :
router.put('/contracts/:id', permissionMiddlewareCreator.update(), (request, response, next) => {
// Learn what this route does here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/routes/default-routes#update-a-record
const recordSerializer = new RecordSerializer({ name: 'contracts' });
const contract_id = parseInt(request.params.id, 10);
const data = request.body.data.attributes;
let body = { contract: {} };
if (data.occupant != null || typeof data.occupant !== 'undefined') { body.contract.occupant = data.occupant; }
if (data.reminderGroup) { body.contract.reminder_group = data.reminderGroup; }
axios.put(`${API_URL}/forest_admin/contracts/${contract_id}`, body, {
headers: {
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
'X-CURRENT-USER-EMAIL': request.user.email
}
}).then(async res => {
console.log(res.data);
console.log(await recordSerializer.serialize(res.data));
response.send(await recordSerializer.serialize(res.data));
}).catch(err => {
response.status(400).send(err.response.data.error.message);
});
});
The strangest thing happens :
Here is some data returned by the API :
{
id: 812,
reminder_group: 2,
place_id: 185,
customer_reference_number: '9213853',
last_reminder_group_update: '2022-01-05',
display_name: '9213853 ()',
amount: 0,
created_at: '2022-01-03T18:03:51.552+01:00',
updated_at: '2022-01-05T16:29:33.064+01:00',
parcel_sergic_id: null,
sergic_update_time: null,
customer_key: null,
invited_count: 0,
report_account_entry_amount: 0,
report_account_entry_operation_date: null,
deleted_at: null,
identity_id: 870,
coowner_amount: 0,
pending_amount: 0,
due_date: null,
occupant: null,
start_date: null,
end_date: null,
integration_completed: null
}
and once this record is serialized, it looks as so:
{
data: {
type: 'contracts',
id: '812',
attributes: {
'reference immeuble': '',
'nom complet': '',
'ID client': '',
civilite: '',
nom: '',
prenom: '',
telephone: '',
'telephone domicile': '',
email: '',
lots: '',
Mandataire: undefined,
'Telephone mandataire': undefined,
'Email mandataire': undefined,
'Adresse mandataire': undefined,
'nature juridique': null,
'appels de charges dematerialisees': false,
'convocation ag': 'paper_only',
'statut du mandat Yousign': 'unsigned',
'derniere modification': 2022-01-03T16:03:51.605Z,
'Envoi de la convoc AG au mandataire': false,
'Envoi des charges au mandataire': false,
'Mode de paiement': null,
'Mandat de prelevement recu': null,
solde: null,
'niveau de relance': '',
'date de derniere relance': null,
'alerte traitee': '',
commentaire: '',
id: 812,
amount: 0,
occupant: null
},
relationships: {
comptes: [Object],
'ecritures-comptables': [Object],
emails: [Object],
tickets: [Object],
parcelsThroughParcelContracts: [Object],
contractParcel: [Object],
managementFees: [Object],
contractDocuments: [Object],
accountEntries: [Object],
alerts: [Object],
publicWorkDetails: [Object],
convocationSettings: [Object],
preEtatDateRequests: [Object],
contractRepartitionKeys: [Object],
waterReadings: [Object],
roles: [Object]
}
}
}
As you can see, the fields ‘nom’, ‘prenom’, ‘telephone’… aren’t part of the record but smart fields.
These smart fields are not re-computed and disappear from the screen after Edit.
Before:
After:
I have to manually refresh my page to have my smart fields re-computed.
Expected behavior
My smart fields should still be visible after Edit
Context
Please provide in this mandatory section, the relevant information about your configuration:
- Project name: Sergic
- Team name: Gestion
- Environment name: Dev
- Agent type & version:
“forest-express”: “^7.9.4”,
“forest-express-sequelize”: “^7.12.3”, - Recent changes made on your end if any: none