Subversion Repositories SmartDukaan

Rev

Show changed files | Directory listing | RSS feed

Filtering Options

Rev Age Author Path Log message Diff
37565 5 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/ IMEI activation: 20s tick lanes for oppo/realme/vivo, idle once the day clears

Replaces the two once-a-day passes with chunk-per-tick lanes. Each tick takes one
chunk and returns; when a brand's pool comes back empty its turn is skipped, and
when everything is clear the ticks do nothing and stay silent until midnight.

- browser lane (StandAlone): one chunk of 25 for one brand every 20s, oppo and
realme by turns. Still exactly one ChromeDriver alive at a time.
- vivo lane: its own tick, chunk of 250. It must not share the browser lane --
0.24s an imei against oppo's 10.2s means it would need ~70 hours behind them
for work it does alone in 39 minutes.

The snapshot is gone; the pool query is the cursor. That is what makes a restart
cost one chunk instead of the day: the 12:03 restart on 09-Sep forfeited ~4,000
lookups and the whole afternoon, and last_finish had read -1 for three days.

The snapshot existed to stop the re-ask loop (realme, 29-Aug: 4,524 requests
against 1,004 distinct imeis). That is now closed at the source instead -- oppo,
realme and motorola stamp every imei they asked about, not just the ones that
produced a map entry, so a failed lookup rests until tomorrow rather than coming
back on the next tick. Motorola is fixed pre-emptively; nothing schedules it yet.

Also:
- secondary and tertiary are merged by turns rather than concatenated. Safe while
a pass walked to the end; without that guarantee oppo's 163 tertiary serials sat
behind 3,819 secondary ones and would only be reached on a day that cleared.
- vivo abandons a tick rather than the chunk when the captcha solver returns no
code -- one probe per 20s while it is down instead of 250, and no rows rested
over a transient outage.
- the funnel gauges move from a pass to a day. due is measured on the first tick
after midnight, the rest accumulate, and last_finish_epoch becomes a real
completion clock. Truncation is detected at the midnight rollover, which is the
case that never reaches an end-of-run at all.

This does not create capacity. At the 21s/imei measured on 09-Sep the pool still
needs ~35 hours and will not clear; it now rolls over visibly instead of silently.
The lever for that is DAYS=1.
 
37564 5 m amit /trunk/profitmandi-fofo/src/main/ Creation screens request only live listings from the item typeahead

/item takes an activeOnly flag (default false, preserving current behaviour)
and passes it to getAllPartnerItemStringDescription. getItemAheadOptions takes
an optional 4th argument, so existing 3-argument callers are unaffected.

Sent true from the two creation entry points:
- warehouse purchase (PO) invoice line picker
- the new-price-drop modal (#typeaheaditem)

Left false where the screen works on records that already exist and may since
have been delisted: the price-drop pause/manage picker (#typeaheaditem1),
catalog-item, combo and prebooking.

jsVersion 419 -> 420 to cache-bust common.js / warehouse-purchase.js (419 was
already taken by another change).
 
37563 13 m amit /trunk/profitmandi-dao/src/main/ Filter delisted SKUs out of creation pickers; add rolling 24m delist migration

Creation screens could offer items whose catalog.tag_listing.active = 0:
- Item.selectAllModels (scheme/offer model dropdown) joined tag_listing with
no active predicate. Adding tl.active = true also gives the model-level
rollup, since callers dedupe to catalogItemId: a model whose colours are
all inactive now yields no rows, one keeping a listed colour stays.
- The shared partner item picker had no active filter at all. Added a second
basis via getAllPartnerItemStringDescription(anyColor, activeOnly);
activeOnly participates in the fofoItems cache key so the two bases cannot
serve each other's cached results. Default stays false for screens that
inspect or edit existing records.
- New TagListing.selectActiveItemIds named query backs the filter.

Also adds the rolling 24-month delist migration: zero stock both sides, no
outstanding vendor PO (status IN (1,2), external supplier, unfulfilled > 0 --
INIT is excluded as it is a drawer of stale drafts), and re-categorises
fully-dark mobile models to OTHER. Idempotent, audited, rollback documented.
 
37562 2 h 15 m amit /trunk/profitmandi-dao/src/main/resources/sql/ Add SQL to delist pre-2025 Samsung listings with no stock

Marks 738 catalog.tag_listing rows (tag_id 4) inactive with eol_date
2026-09-08. These are Samsung listings published before 2025-01-01 holding
no stock in any SmartDukaan warehouse and none at any active partner store.

Id list is frozen from the prod evaluation rather than re-derived, so the
same listings are delisted in every environment; stock tables in a copy
drift from prod. Script is idempotent and carries guards, verification and
a rollback block.

Applied to prod hadb1 and the local dev copy.
 
37561 8 h 55 m ranu /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/ ticket download option given and some enhancement on notification panel  
37560 9 h 10 m ranu /trunk/profitmandi-fofo/src/main/ ticket download option given and some enhancement on notification panel  
37559 9 h 24 m ranu /trunk/profitmandi-fofo/src/main/ ticket download option given and some enhancement on notification panel  
37558 9 h 49 m ranu /trunk/ system generated leak bgc l2 can assign to l1 without any geo location  
37557 11 h 15 m ranu /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ system generated leak bgc l2 can assign to l1 without any geo location  
37556 12 h 14 m ranu /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/ loi process added, revival and code changes process  
37555 12 h 23 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/ web offer sync: one value per SKU per payment mode

The circular says two things about the same phone. Motorola Sep'26 page 9 names
'G37 Power' generically at Rs.1,000 CC Full Swipe (row 12) and 'G37 Power (8+128)'
at Rs.2,000 (row 13), so G37 Power 8+128 carried both badges and a partner could
quote either.

Precedence, per (catalog_id, txn_mode):
1. a specifically named VARIANT beats a generic MODEL - the named line is the OEM
being precise about that SKU
2. at the same level, the higher value wins
3. tie-break on lowest offer id, so the outcome is deterministic

The generic line still covers every variant nobody named: G37 Power 4+64 keeps its
Rs.1,000 Full Swipe while 8+128 takes Rs.2,000. Verified on the live data - 1026311
now resolves to exactly CC_EMI 2500 and CC_FULL_SWIPE 2000, down from four competing
values.

An offer keeps a SKU if it wins on at least one of its own modes, since one badge
carries every mode of its offer. Scheme-only offers are never filtered - no value to
compare.

Deliberately NOT reusing v_offer_applicable, which encodes the same VARIANT-beats-
MODEL rule but has no document or status filter: once August is re-ingested its rows
enter that view and an EXPIRED August variant would silently suppress a live
September model. Scoping to one document avoids that; the view is left alone for
other consumers.

Measured on Sep'26: 557 product links -> 458, 191 badges -> 166.
 
37554 13 h 31 m amit /trunk/profitmandi-fofo/src/ web offer: put the brand back in the title

SEPTEMBER 2026 MOTOROLA Rs.1,000 cashback on Credit Card Full Swipe
SEPTEMBER 2026 MOTOROLA No Cost EMI on 3, 6 months

Month and brand now both match the convention of the 3,850 hand-written rows, which
is how the admin listing is scanned. What stays gone is the redundant
'Cashback Offer-' label: the value already states what the offer is, and calling a
scheme-only row a cashback offer is what produced the live 'Cashback Offer- NA'
badges on 81 SKUs.

Brand comes from the division's catalog brand, falling back to its display name, so
a division with no catalog.brand row (Google) still reads sensibly rather than
emitting an empty gap.
 
37553 13 h 54 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/ web offer sync: all_banks is TINYINT(1), so never cast it to Number

ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number, thrown from
selectPublishableOffers on every ingest since 2026-09-08. Confirmed against the live
driver: SELECT all_banks returns java.lang.Boolean.

MySQL Connector/J maps TINYINT(1) to Boolean while Hibernate may hand back a Number,
so the value must be read through isTrue() - the same shape as ScopeConfig.isTrue and
OfferScopeRepositoryImpl.isTrue, both of which exist for exactly this reason and both
of which I had in front of me when writing the cast.

The failure was silent by design: CircularIngestRunner swallows sync exceptions so a
web-offer problem can never fail a good ingest. The circular kept publishing, the
document's processed_at kept moving, and the only symptom was that web_offer.synced_at
stopped advancing - which is what should have been checked before reporting the sync
as working on 8 September.
 
37552 14 h 22 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ lead/knowlarity: stop a null lookup key from matching every row

selectByEquals maps a null VALUE to NO PREDICATE AT ALL rather than to "= null",
because GenericRepositoryImpl.prepareEqualPredicate skips null entries. So a null
lookup key does not miss -- it selects the whole table and dies on
NonUniqueResultException. Two live call paths were doing exactly that.

RecordingService.updateAgentCallLog read caller_id, which knowlarity has never sent
on push-call-log: a sample of 50 live webhooks contained it zero times. Every call
therefore ran selectByCallerId(null) -> "select every sip_master row" -> throw, and
the whole feed was discarded. 17 of those 50 were Connected calls with a real agent.
Resolve the agent from agent_number instead, which is the field that actually
identifies them and holds the sip_url; it arrives bare, sip:-prefixed, or as the
literals "False"/"None" when nobody picked up. caller_id is still honoured first in
case they ever start sending it. A payload naming no agent is INFO, and an agent
missing from sip_master is WARN (an ops fix, and per-agent, so an ERROR would
fingerprint into one GlitchTip issue per agent).

AuthRepositoryImpl.putEmailOrMobile had the same hole via Long.parseLong(null)
falling into the catch and putting a null email. selectByEmailOrMobile(null)
degenerated to "select all 405 users", and authenticate(null, hash) degenerated to
"does ANY user have this password hash", which would answer true. Both fail closed
today only as an accident of how many rows the table holds, so the guard goes on the
one path they share.

Fixes GlitchTip #58/#1324/#1335 (fofo, 281 events) and #10 (web).
 
37551 14 h 23 m amit /trunk/profitmandi-fofo/src/ web offer: keep the month in the title

SEPTEMBER 2026 Up to Rs.4,000 cashback
SEPTEMBER 2026 Rs.1,500 cashback on Credit Card EMI
SEPTEMBER 2026 No Cost EMI on 3, 6 months

Matches the convention of the 3,850 hand-written rows and is how the admin listing is
scanned. The brand stays out - the product card already shows it, so that was the
redundant half, and dropping it is what makes room for the value to lead.

The month comes from the OFFER's own start date, not the circular's period: offers
run past a month end - four Aug'26 Apple offers ran to 26 September - and labelling
one of those AUGUST on a badge read in September would be wrong.
 
37550 14 h 28 m amit /trunk/profitmandi-fofo/src/ web offer: partner-facing titles, and stop calling a scheme offer a cashback offer

web_offer.title is partner-facing - StoreController and DealsController map it into
the product's offer list - so it now leads with the value rather than a filing label:

Up to Rs.4,000 cashback
Rs.1,500 cashback on Credit Card EMI
10% cashback up to Rs.7,500 on Credit Card EMI
No Cost EMI on 3, 6 months

Month and brand are gone: the card already shows the product, and the offer carries
its own dates. The full breakdown sits in detailedText below it.

This fixes a live defect. 16 published offers have no cashback at all, and the old
template rendered them 'SEPTEMBER 2026 XIAOMI Cashback Offer- NA' with detail 'NA',
on 81 SKUs. They are EMI-scheme offers and now say so.

Scheme inference at ingest: Motorola states the scheme in the DESCRIPTION rather than
the tenure cell - '[3&6 M]' plus 'Only NCEMI', where every other OEM writes
'6(NCE),9,12(LCE)'. TenureParser is right to return NONE for such a cell; the scheme
is simply not in it. Recovered in CircularIngestService where both columns are in
hand, and deliberately narrow: only when EVERY tenure came back without a scheme AND
the description names exactly one. On Sep'26 that is 10 offers, all Motorola; the
other 23 scheme-less rows are cashback offers whose descriptions are amounts, and
inventing a scheme for those would misstate the terms.

This distinction is money: four of the Motorola rows are LOW cost EMI, and calling
them no-cost would promise a partner something the bank will not honour.

'No cashback.' is dropped everywhere - the absence of an amount says it, and beside a
Cashback Instant Benefit scheme it flatly contradicted the name.

Tests 8 -> 12.
 
37549 14 h 29 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/ web offer sync: read tenures for scheme-only offers

selectTenures, keyed by offer id like the benefit and bank reads.

Needed because an offer with no cashback is still a real offer - a no-cost or
low-cost EMI scheme - and its tenures are the only thing it has to say. Without them
those rows can only be described as 'NA'.
 
37548 15 h 4 m ranu /trunk/ v2 version some fixes  
37547 15 h 7 m ranu /trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/controller/ v2 switch version fixes on server side  
37546 1 d 7 h amit /trunk/profitmandi-fofo/src/ web offer sync: compose detailed text from the parsed offer

detailedText is now built from benefit_timing + offer_benefit + offer_bank instead
of copying the circular's line:

Instant cashback. Rs.4,000 on Credit Card EMI; Rs.3,000 on Credit Card Full
Swipe. Banks: Axis Bank, ICICI Bank, State Bank of India (credit cards)

Every payment mode is always named, even when the circular's prose is terse
('10% CC EMI'), and the amounts come from offer_benefit - the authoritative
per-mode source. CC/DC cannot leak here at all, because the mode codes expand
natively rather than being patched by find-and-replace.

Three cases that would otherwise read badly:
- 21 offers carry NO benefit (circular cell 'NA', timing NONE). They are tenure-only
offers, so they read 'No-cost EMI. No cashback.' rather than showing a blank badge.
- The bank columns often list a bank under both card types while only one carries a
benefit. Card types shown are restricted to those actually paid on, or the text
would imply a debit offer that does not exist.
- benefit_timing UPI and NONE are not timings. Nothing is asserted rather than
inventing one.

smallText keeps the circular's short line - that column is only VARCHAR(256) and the
composed detail runs past it. One flowing paragraph, no line breaks, since the badge
may not render them.

Tests 8 -> 14.
 

Show All