Smart action: cannot read value of null in console

Hi Forest,

I have a broken smart action in prod. Half of the fields are unreachable…

In console, I get this error:

However, I don’t have any errors on server side. I can see that the request to load the form seems all right:

and also have this request in 404 (I always see this kind of .../values 404 on all smart actions):

To try to debug, I have duplicated the exact same data that is loaded by the smart action in dev env. Everything works nice.

Context:
“meta”: {
“liana”: “forest-express-mongoose”,
“liana_version”: “7.8.2”,
“stack”: {
“database_type”: “MongoDB”,
“engine”: “nodejs”,
“engine_version”: “12.22.1”,
“orm_version”: “5.9.4”
}
}

Any ideas?

Best

Hello,

It seems that your server is not knowing the route POST /forest/actions/rembourser-une-echeance-en-cb, as it returns a 404. Can you share with me the declaration of this route (without the inner code)?

Regarding the 404, it seems that it is normal with your current version of forest-express-mongoose, and that’s not the reason of the error you are getting.

I’m investigating on the error

Can you paste the content of the response to hooks/load?

No I can’t @GuillaumeGautreau , I did not create this route, thus it’s not a root that I handle

I mean, in your browser, you have access to the network tab. Here you can see all requests that are sent by the browser.

I need to have the content of the response to the request POST /forest/actions/rembourser-une-echeance-en-cb/hooks/load. It seems that the error is caused by incoherent data sent by this endpoint.

1 Like

ok sorry , I misunderstood :slight_smile:

Indeed, there is a null value returned in the fields array:

I checked and all my current fields are present. So the third field at null is anormal.

Is there any problem with the forestadmin-schema.json in prod ?

here are my field definitions:

fields: [
    {
      field: 'Echéance à rembourser',
      type: 'Enum',
      description: "Si aucune échéance n'a été payée, la liste est vide.",
      enums: [],
      isRequired: true
    },
    {
      field: "Montant déjà remboursé sur l'échéance",
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      type: 'Number',
      isReadOnly: true
    },
    ,
    {
      field: "Montant restant sur l'échéance",
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      type: 'Number',
      isReadOnly: true
    },
    {
      field: "Article d'un participant",
      description: "UNIQUEMENT si le remboursement concerne l'article d'un participant en particuliers. Sinon, laisser vide",
      type: 'Enum',
      enums: []
    },
    {
      field: 'Remettre en vente ?',
      description: "Action appliquée à tous les articles ou UNIQUEMENT à l'article du participant sélectionné.",
      type: 'Enum',
      enums: ['NON', 'OUI'],
      isRequired: true
    },
    {
      field: "Quantité  de l'article à remettre en vente",
      description:
        "Indiquer une quantité UNIQUEMENT si l'article d'un participant est sélectionné. Si aucun article n'est sélectionné et que vous remmettez les quantités en vente, toutes les quantités commandées seront remise en vente.",
      type: 'Number'
    },
    {
      field: 'Montant du remboursement',
      description:
        "/!/ Si vous avez sélectionné l'article d'un participant, le montant du remboursement ne doit s'appliquer qu'à cet article /!/",
      type: 'Number',
      isRequired: true
    },
    {
      field: "Montant des frais déjà remboursés sur l'échéance",
      type: 'Number',
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      isReadOnly: true
    },
    {
      field: "Montant des frais restant sur l'échéance",
      type: 'Number',
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      isReadOnly: true
    },
    {
      field: 'Montant des frais à rembourser',
      description: 'Uniquement sur la première échéance. Laissez vide si vous ne voulez pas rembourser de frais.',
      type: 'Number'
    }
  ],

Hello again :wave:

Could you also share the load hook code?

Thanks in advance

yes:


function onLoadSetSchedulesEnum(fields: IForestSmartActionFields, payment: IPayment) {
  fields['Echéance à rembourser'].enums = getScheduleEnumValues(payment, [EPaymentStatus.COMPLETED], [EPaymentMethod.CARD])
}

async function onLoadSetParticipantEnum(fields: IForestSmartActionFields, payment: IPayment) {
  const order = payment.orderId as IOrder
  const collect: ICollect = await GetOneCollect.init({ _id: order.collect })
  
  if (collect.type !== ECollectType.REGATTA) {
    const orderDetails: IRegistrationOrderDetails = await GetRegistrationOrderDetails.init(order._id)

    fields["Article d'un participant"].enums = orderDetails.orderItemsByParticipant.flatMap(participant => {
      return participant.orderItems.flatMap(({ productName, orderItemIds, variants }) => {
        if (variants && variants.length > 0) {
          return variants.map(
            ({ weekDay, startTime, endTime, orderItemId }) =>
              `${participant.participantFullname} - ${productName} - créneau du ${EWeekDayLabel[weekDay]} ${startTime} à  ${endTime} - ${orderItemId}`
          )
        }
        return `${participant.participantFullname} - ${productName} - ${orderItemIds[0]}`
      })
    })
  }
}

export const refundPaymentScheduleAction = {
  name: 'Rembourser une échéance en CB',
  type: 'single',
  fields: [
    {
      field: 'Echéance à rembourser',
      type: 'Enum',
      description: "Si aucune échéance n'a été payée, la liste est vide.",
      enums: [],
      isRequired: true
    },
    {
      field: "Montant déjà remboursé sur l'échéance",
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      type: 'Number',
      isReadOnly: true
    },
    ,
    {
      field: "Montant restant sur l'échéance",
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      type: 'Number',
      isReadOnly: true
    },
    {
      field: "Article d'un participant",
      description: "UNIQUEMENT si le remboursement concerne l'article d'un participant en particuliers. Sinon, laisser vide",
      type: 'Enum',
      enums: []
    },
    {
      field: 'Remettre en vente ?',
      description: "Action appliquée à tous les articles ou UNIQUEMENT à l'article du participant sélectionné.",
      type: 'Enum',
      enums: ['NON', 'OUI'],
      isRequired: true
    },
    {
      field: "Quantité  de l'article à remettre en vente",
      description:
        "Indiquer une quantité UNIQUEMENT si l'article d'un participant est sélectionné. Si aucun article n'est sélectionné et que vous remmettez les quantités en vente, toutes les quantités commandées seront remise en vente.",
      type: 'Number'
    },
    {
      field: 'Montant du remboursement',
      description:
        "/!/ Si vous avez sélectionné l'article d'un participant, le montant du remboursement ne doit s'appliquer qu'à cet article /!/",
      type: 'Number',
      isRequired: true
    },
    {
      field: "Montant des frais déjà remboursés sur l'échéance",
      type: 'Number',
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      isReadOnly: true
    },
    {
      field: "Montant des frais restant sur l'échéance",
      type: 'Number',
      description: 'Ce champs est à titre informatif. Il ne sera jamais pris en compte.',
      isReadOnly: true
    },
    {
      field: 'Montant des frais à rembourser',
      description: 'Uniquement sur la première échéance. Laissez vide si vous ne voulez pas rembourser de frais.',
      type: 'Number'
    }
  ],
  hooks: {
    load: async ({ fields, record }: ISmartActionParams) => {
      onLoadSetSchedulesEnum(fields, record)
      await onLoadSetParticipantEnum(fields, record)
      return fields
    },
    change: {
      ['Echéance à rembourser']: ({ fields, record }: ISmartActionParams) => {
        onChangeSetRefundedAmountValue(fields, record)
        onChangeSetRefundableAmountValue(fields, record)
        onChangeSetAmountToRefundValue(fields)
        onChangeSetFeesAmountToRefundValue(fields)
        onChangeSetRefundedFeesValue(fields, record)
        onChangeSetRefundableFeesValue(fields, record)
        return fields
      },
      ["Article d'un participant"]: ({ fields, record }: ISmartActionParams) => {
        onChangeSetParticipantArticleOrderQuantityValue(fields, record)
        return fields
      },
      ['Remettre en vente ?']: ({ fields, record }: ISmartActionParams) => {
        onChangeSetParticipantArticleOrderQuantityValue(fields, record)
        return fields
      }
    }
  }
}

Isn’t this the issue? I’m pretty sure it would push a null value in your load hook.

Let me know :smiley:

OMG :face_with_hand_over_mouth:

How my linter could not see that …

However, strangely, I don’t have any null value in the fields array in dev env with the exact same code

Indeed, this looks weird. However, I’m having the same error you have with a double ,, so the error definitely comes from here (Even in plain javascript)

Maybe this comes from a different configuration of your ts compiler? I doubt it, but that’s my best guess.

don’t think so. The TS compiler is the same in prod than in dev.

Then, I have no idea why you have a different behavior between your dev and your production :frowning:

Both of your dev & production environment seems to share the exact same configuration on our end.

Looking at our code, I can’t see any reason for the hooks to behave differently between a production environment & a development one. They both share the exact some code, so the issue does not seems to be related to our hook code (Maybe I’m wrong though).

Let me know if it fixes your production issue :raised_hands:

@jeffladiray it did work! nice! sorry for the typo…

I have another issue for you :wink:

I have some fields in readOnly. They do appear in readOnly when I open the form.

… however they are not anymore in readOnly once their value is changed by the change hook:

I would like them to stay in readOnly after their value changes.

Do you want me to open a new issue ?

Can you create another topic for this specific subject?