Subversion Repositories SmartDukaan

Rev

Show changed files | Directory listing | RSS feed

Filtering Options

Rev Age Author Path Log message Diff
36406 38 m amit /trunk/profitmandi-dao/src/main/resources/sql/ Add scheme_item windowing migration script.

Migrates fofo.scheme_item from composite (scheme_id, catalog_id) PK to
surrogate id BIGINT, adds audit columns, swaps the old uniqueness to
the 4-column window key, adds a date-driven lookup index, and installs
BEFORE INSERT/UPDATE triggers that enforce start<=end, containment in
parent scheme window, and non-overlap within (catalog_id, scheme_id).

Step 4b drops the legacy UNIQUE scheme_catalog (scheme_id, catalog_id);
without this the windowing feature is functionally blocked.

Applied on hadb1 in this revision.
 
36405 39 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ Fix duplicate SchemeInOut on concurrent GRN: SELECT FOR UPDATE on inventory_item before createSchemeInOut to serialise concurrent GRN calls per IMEI  
36403 3 h 23 m amit /trunk/profitmandi-dao/src/main/ Add catalog.catalog_monitor_type table, entity, and repository for per-catalog focused/normal monitor type tagging  
36399 3 h 28 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ Replace mailSender (SendGrid) with gmailRelaySender - SendGrid API key expired/revoked  
36397 3 h 42 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ Scheme item windowing: add startDate/endDate per scheme_item.

Each fofo.scheme_item row now carries an optional [start_date, end_date]
window so the same (scheme_id, catalog_id) pair can be applicable for
different date ranges. Backward compatible: NULL window = always active.

- SchemeItem entity: composite (schemeId, catalogId) PK -> surrogate
long id (IDENTITY), unique (catalog_id, scheme_id, start_date, end_date),
audit cols (updatedBy, updatedOn).
- Scheme + TagListing named queries: gated by
'(si.start_date is null or :onDate between si.start_date and si.end_date)'.
- SchemeItemRepository: + selectById, selectBySchemeId,
existsOverlapping (half-open, with self-exclude), selectItemsOutsideWindow.
- SchemeService: + updateSchemeItemWindow / addSchemeItemWithDates /
clampSchemeItems with containment + overlap validation; drop dead
getTotalMargin.
- SchemeServiceImpl.processSchemeOut: pin scheme resolution to each
IMEI's GRN billing date (Purchase -> Order.billingTimestamp via
PurchaseService.getBillingDateOfPurchase) instead of fofoOrder
createTimestamp, aligning OUT with the existing IN behaviour.
 
36395 3 h 45 m ranu /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/model/ login talktime hours cap on 100%  
36387 2 d 23 h ranu /trunk/ code commit for reports section v2  
36383 3 d 0 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/exception/ Add DbErrorTranslator: translates Spring DataIntegrityViolationException (truncation / duplicate key / FK violation) into ProfitMandiBusinessException with prettified field label.  
36376 3 d 1 h aman /trunk/ Feat:Cart Api Implementation  
36375 3 d 2 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/transaction/ Added Rising Star/NEW  
36374 3 d 2 h ranu /trunk/ schemes and offer for v2 version  
36372 3 d 5 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ Wallet: SELECT FOR UPDATE on user_wallet mutations to close lost-update hole

addAmountToWallet/consumeAmountFromWallet(x2)/rollbackAmountFromWallet all
follow a read-modify-write pattern on user_wallet with no pessimistic lock
and no @Version, so two concurrent tx for the same partner both read the
same pre-snapshot amount, compute their own deltas, and commit - the second
UPDATE silently overwrites the first's credit/debit. user_wallet_history
still gets both rows, so balance drifts vs sum(history) with no exception.

Replaces the misnamed (and body-broken) selectByIdForUpdate - whose
implementation was a plain selectById, not a lock - with a new
selectByRetailerIdForUpdate that issues SELECT ... FOR UPDATE via
LockModeType.PESSIMISTIC_WRITE, mirroring the idiom already used in
GenericRepositoryImpl.selectByIdForUpdate and OrderRepositoryImpl.
Preserves the create-on-missing behavior of selectByRetailerId so
first-time partners keep working.

Switches the four read-modify-write call sites in WalletServiceImpl from
selectByRetailerId to the new locking variant. Read-only callers
(getUserWalletByUserId, getUserWalletHistoryByUserId, etc.) keep using
the non-locking selectByRetailerId - MVCC snapshot reads stay non-blocking
for display/statement endpoints.

Also drops the stale commented-out selectByIdForUpdate line in
rollbackAmountFromWallet and removes the broken method from the
UserWalletRepository interface / impl - it had zero live callers.

Blast radius: every write call to these three wallet methods now holds
an X-lock on the target user_wallet row for the rest of the outer tx.
Concurrent write tx for the same partner will briefly serialize at the
SELECT FOR UPDATE - correct serialization instead of silent drift.
Read-only traffic is unaffected (MVCC).
 
36371 3 d 6 h amit /trunk/ HDFC webhook: INSERT IGNORE on hdfc_payment to fix concurrent-duplicate 500 storm

Replaces persist() with a native INSERT IGNORE so concurrent same-UTR webhook
retries serialize on the unique-index check, and the loser gets a 0-row no-op
(warning, not exception). Outer @Transactional session stays clean, Spring
commits normally, HDFC sees 200 on both the winner (Success) and the loser
(Duplicate) - retry amplification ends.

Flow:
persist(hdfcPayment) -> insertIgnore(hdfcPayment) + selectByUtrNo(utr)
- inserted == 1: proceed with wallet / sidbi side-effects using fetched id
- inserted == 0: respond Duplicate, skip side-effects (owned by winning tx)
- defensive: log warn if insertIgnore returned 0 but selectByUtrNo finds
no row (could mean IGNORE swallowed a non-duplicate issue like truncation)

Also drops HdfcProcessingHelper (r36366) which used REQUIRES_NEW for the same
goal; that approach required a second JDBC connection and is no longer needed
with SQL-level idempotency.

Does NOT touch the wallet-side lost-update hole (user_wallet read-modify-write
without FOR UPDATE). That is a separate commit.
 
36366 4 d 1 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/transaction/ Add HdfcProcessingHelper: per-payment REQUIRES_NEW wrapper for HDFC credit writes

Isolates the hdfc_payment insert + wallet-credit / sidbi-sanction writes in
their own transaction so concurrent duplicate webhooks (HDFC retry, manual
entry, reconciliation) can't poison the caller's session. On the deadlock/
duplicate-key path (DataIntegrityViolationException), logs once at INFO and
returns silently — the row's side-effects are owned by whichever path
inserted it first; re-applying would double-credit.

Mirrors the OfferProcessingHelper pattern (also REQUIRES_NEW per item),
keeping the controller's outer transaction clean and making this method
safe to invoke from a batch loop later without refactor.
 
36364 4 d 3 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/fofo/ Fix /activateFinanceServices returning empty row for retailers without partner_onboarding_panel

Change selectFinanceServicesByFofoId named query to LEFT JOIN PartnerOnBoardingPanel.
Previously an inner join filtered out 32 fofo_stores (16 internal + 16 external)
lacking an onboarding panel row, so the /activateFinanceServices response rendered
empty for them (e.g. codeInt=1359 / UPGBN1359) even though the partner_service
save itself worked.
 
36362 4 d 22 h amit /trunk/profitmandi-dao/src/main/ Make fofo_order creation idempotent on (fofo_id, invoice_number)

Fixes insert-intention gap-lock deadlocks on idx_invoice_number observed in
SHOW ENGINE INNODB STATUS at 2026-04-22 13:01:54 — two concurrent requests
inserting the same invoice_number for the same customer (client retry /
upstream webhook retry pattern).

- OrderServiceImpl.createAndGetFofoOrder: select-then-insert idempotency.
Fast path returns existing row if already created; slow-race path catches
DataIntegrityViolationException and re-selects the winner's row.
- add_uk_fofo_order_fofo_invoice.sql: adds UNIQUE KEY (fofo_id, invoice_number)
so the loser of a concurrent-insert race gets a clean DIVE instead of a
silent duplicate row (pre-check showed zero existing dup groups, safe).

findExistingFofoOrder wraps the repo call to swallow the repo's declared
ProfitMandiBusinessException — the impl actually returns null on not-found
(constructs an exception but never throws), so the swallow matches reality.
 
36359 4 d 23 h ranu /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/ rbm rating dashboard view commited  
36357 5 d 0 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/ Fix background-thread 'no session' error in DB guard. CronBatchRepository.selectRunningForOffer uses getCurrentSession() which needs an open tx; when OfferBatchService.processOfferWithBatch is called from the async worker thread (no outer tx), the guard query crashed with 'Could not obtain transaction-synchronized Session'. Offer 8819 submit succeeded but the background run died at the guard — before createBatch, so no cron_batch / cron_batch_item rows. Added CronBatchService.findRunningForOffer wrapping the repo call in @Transactional(readOnly=true); orchestrator calls the service method instead of repo directly. Matches the pattern used by loadOfferRequest / createBatch / calculate*Payouts — every caller opens its own tx.  
36356 5 d 1 h ranu /trunk/ rbm rating dashboard view commited  
36355 5 d 1 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/offers/ Skip already-paid partners before creating cron_batch_item rows. Adds hasRemainingSellinPayout / hasRemainingOfferPayout predicates on OfferProcessingHelper that mirror the amount calc in processPartner*Payout. Orchestrator filters partnerPayouts through these before createBatch — partners whose serials are fully paid (amount=0 after subtracting serialNumberPaid) are excluded entirely. Reruns of a completed offer now create no batch at all (log says 'all N eligible partners already fully paid, skipping batch'); partial reruns log filtered count. Avoids audit-trail noise of SUCCESS items that did zero work.  

Show All