SuiteCRM V8 Filter Bug?

Hi Guys,

I’m new to SuiteCRM and I’m working with the V8 API. When I’m running the GET Accounts (/api/V8/module/Account). I wanted to filter based on a custom field so I added a custom field called erp_id (erp_id_c).

When I run a GET request against /api/V8/module/Account?filter[erp_id_c][EQ]=17111 it returns “Filter field erp_id_c in Account module not found”.

I looked into this and found the problem inside of Api/V8/JsonApi/Repository/Filter.php. Here is the original code (starting at line 47 in version 7.10.10-0):

foreach ($params as $field => $expr) {
    if (!property_exists($bean, $field)) {
        throw new \InvalidArgumentException(sprintf(
            'Filter field %s in %s module is not found',
            $field,
            $bean->getObjectName()
        ));
    }
    if (!is_array($expr)) {
        throw new \InvalidArgumentException(sprintf('Filter field %s must be an array', $field));
    }
    foreach ($expr as $op => $value) {
        $this->checkOperator($op);
        $where[] = sprintf(
            '%s.%s %s %s',
            $bean->getTableName(),
            $field,
            constant(sprintf('%s::OP_%s', self::class, strtoupper($op))),
            $this->db->quoted($value)
        );
    }
}

The problem appears to be that it’s hard coded to check the bean for the field. It does not fall back to custom fields, and custom fields are not added to the root bean object. Since custom fields are available in the bean, and the query already has the _cstm table it was any fix. I changed the code to the following (again, starting at line 47):

foreach ($params as $field => $expr) {
    
    if ( property_exists($bean, $field) ) {
        $tableName = $bean->getTableName(); 
    } else if ( $bean->custom_fields->fieldExists($field) ) {
        $tableName = $bean->getTableName() . "_cstm";
    } else {
        throw new \InvalidArgumentException(sprintf(
            'Filter field %s in %s module is not found',
            $field,
            $bean->getObjectName()
        ));
    }

    if (!is_array($expr)) {
        throw new \InvalidArgumentException(sprintf('Filter field %s must be an array', $field));
    }
    
    foreach ($expr as $op => $value) {
        $this->checkOperator($op);
        $where[] = sprintf(
            '%s.%s %s %s',
            $tableName,
            $field,
            constant(sprintf('%s::OP_%s', self::class, strtoupper($op))),
            $this->db->quoted($value)
        );
    }
}

This is a fairly simple change, I just move the table name into a local variable. The check to see if it exists on the bean also assigns the local variable. If it doesn’t exist on the bean it checks the custom fields and if that exists it adds _cstm to the table name.

My questions are these:

  • Am I doing something wrong? Is there actually a way to filter on custom fields through the version 8 API without customization?
  • If this is a limitation of SuiteCRM, is this the correct way to fix the problem? Should I be checking fields in another way or will this cause problems with some modules?
  • Finally, if it is a limitation and I’m not doing anything wrong. How can I submit this to try and get this into the next release? Would I post this as an issue along with the resolution on the github repository?

I did end up posting an issue on the github repository.
https://github.com/salesagility/SuiteCRM/issues/6455

3 Likes