mohd-faraz

_blogs

// blogs / 20260611.md

Dev Log: June 11 Wrap-up

2026-06-11
#refactoring#crm#backend#java

Overview

Today was one of those “behind the scenes” days—heavy on the plumbing and refactoring. I spent most of my time making our CRM query system less brittle and cleaning up some code duplication that had started to bother me.

What I Worked On

Smarter Query Negation and Ranges

I finally tackled a weird edge case in our filtering logic. When a user tried to negate an empty search (basically asking the system to find records where a field is not empty), the logic would sometimes fall over. I had to tweak the utility to explicitly check for that empty string negation so the database knows exactly what to look for.

I also added a little “quality of life” improvement: automatic date range parsing. Instead of requiring the frontend to send separate start and end parameters, I wrote a parser that looks for a specific pattern (like value1_value2) and converts it into a proper range expression on the fly. It makes the API a lot more flexible without adding unnecessary complexity to the requests.

Fighting the Copy-Paste Demon

I noticed that my decorators for different CRM modules were starting to look suspiciously similar. I was basically copy-pasting the same normalization and counting logic across three different files. I spent the afternoon migrating that shared logic into a centralized helper class. It’s much more maintainable now; if I need to change how we calculate a sum or a count, I only have to do it in one place.

One specific addition was using a transient key to fetch counts for the partner list. Instead of storing a hard-coded count in the database (which is a nightmare to keep in sync), the decorator now fetches it dynamically when the list is requested:

// Fetching a count via a helper and attaching it to the resource on the fly
for (BaseResource item : results) {
    long total = InternalHelper.getInstance().getCount(
        new Expression(FIELD_LINKED_ID, REL_OP.EQ, item.getId()), 
        ctx
    );
    // Set a transient value so it's sent to the UI but not saved to the DB
    item.setTransientValue("total_count", total);
}

Restoring the Decorators

I also spent some time “restoring” the core logic in our main customer decorator. Somewhere along the way, some of the process triggers got messy, so I re-synced the code and made sure the post-save logic was firing correctly. It’s a lot cleaner now, and the specialized query types like GET_SUM and GET_COUNT are finally fully supported across all the modules I touched today.

Wrapping Up

It feels good to have the query logic in a more stable place. Tomorrow I'll probably pivot back to some of the frontend components, but getting the backend “plumbing” right today was definitely the right call. It's much less of a headache to build on top of a solid foundation.