<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>SmartDukaan &#x2013; /</title><description>WebSVN RSS feed &#x2013; SmartDukaan</description><lastBuildDate>Wed, 26 Aug 2026 03:27:07 +0530</lastBuildDate><generator>WebSVN 2.8.6-DEV</generator><language>en</language><link>https://svn.smartdukaan.com/log.php?repname=SmartDukaan&amp;path=%2F&amp;max=40&amp;peg=37365</link><atom:link href="https://svn.smartdukaan.com/rss.php?peg=37365&amp;repname=SmartDukaan" rel="self" type="application/rss+xml" />
<item><pubDate>Wed, 19 Aug 2026 20:33:08 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37365 – Debit note receive: surface the partner-declared condition and warn before ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;Debit note receive: surface the partner-declared condition and warn before rejecting&lt;br /&gt;
&lt;br /&gt;
The receive screen defaulted every row&apos;s condition to GOOD regardless of what the&lt;br /&gt;
partner declared, so a warehouse user could not see what they were disagreeing with -&lt;br /&gt;
and the backend treats any disagreement as a rejection of the whole debit note.&lt;br /&gt;
&lt;br /&gt;
- Show &apos;Declared By Partner&apos; per row and preselect the condition to match it, so&lt;br /&gt;
  submitting unchanged is a genuine agreement rather than an accident of the default.&lt;br /&gt;
- A changed row now switches the submit button to &apos;Reject Return&apos;, shows what rejection&lt;br /&gt;
  means (no refund; partner, Logistics, RBM and Sales notified), makes the remark&lt;br /&gt;
  mandatory and confirms before posting.&lt;br /&gt;
- SMTP timeouts raised to 30s connect / 120s read-write; the 10s read timeout was&lt;br /&gt;
  cutting off larger attachment sends.&lt;br /&gt;
- jsVersion 405 -&gt; 406 for the return.js change.&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/config/AppConfig.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/resources/js/business/return.js&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/receive-debit-note.vm&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37365&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37365&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 20:32:59 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37364 – Offer circular ingest: report discarded rows instead of counting attempts ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Offer circular ingest: report discarded rows instead of counting attempts&lt;br /&gt;
&lt;br /&gt;
Pairs with the repository change that makes insertBenefit/insertTenure/insertBank return&lt;br /&gt;
their affected row count. The summary now bumps only when a row actually landed, and&lt;br /&gt;
records a drop naming the likely unseeded master (offers.txn_mode / emi_scheme / bank)&lt;br /&gt;
when it did not. Without this an ingest over empty masters reported a full, healthy&lt;br /&gt;
parse while writing nothing.&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularIngestService.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37364&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37364&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 20:32:53 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37363 – Offer circular ingest: return affected rows so INSERT IGNORE cannot ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Offer circular ingest: return affected rows so INSERT IGNORE cannot hide an FK failure&lt;br /&gt;
&lt;br /&gt;
insertBenefit/insertTenure/insertBank use INSERT IGNORE for idempotency, which also&lt;br /&gt;
makes MySQL downgrade a foreign key violation to a warning. Production was bootstrapped&lt;br /&gt;
without the bank / txn_mode / emi_scheme masters, so all 872 benefit and tenure inserts&lt;br /&gt;
were silently discarded: the ingest reported PUBLISHED with 239 offers carrying no&lt;br /&gt;
amounts, no tenures and no bank eligibility, and nothing anywhere said so.&lt;br /&gt;
&lt;br /&gt;
The three methods now return the affected row count (1 written, 0 discarded) so the&lt;br /&gt;
caller can count what landed rather than what it attempted.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/CircularIngestRepository.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/CircularIngestRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37363&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37363&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 20:32:47 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37362 – External feed: keep placeholder &apos;Any Colour&apos; SKUs out of the ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;External feed: keep placeholder &apos;Any Colour&apos; SKUs out of the partner feed&lt;br /&gt;
&lt;br /&gt;
catalog.item rows whose color is a placeholder (&quot;Any Colour&quot;, &quot;f_Any Color&quot;, ...) are&lt;br /&gt;
not real sellable variants and must never reach partners. Excluded from every feed and&lt;br /&gt;
count query via a single NO_PLACEHOLDER_SKU predicate so the SKU list and its count&lt;br /&gt;
cannot drift apart. The boundary check leaves real colors like &quot;Rainbow&quot; untouched.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/external/ExternalFeedRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37362&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37362&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 20:32:41 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37361 – Mail outbox: one transaction per mail, retry once more, stable ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Mail outbox: one transaction per mail, retry once more, stable Message-ID&lt;br /&gt;
&lt;br /&gt;
processPendingMails ran the whole batch in a single REQUIRES_NEW transaction, so a&lt;br /&gt;
crash mid-batch rolled back the status of every mail already delivered in that cycle&lt;br /&gt;
and the next run re-sent them.&lt;br /&gt;
&lt;br /&gt;
- Split into selectPendingIds (read-only) plus sendOne per mail, each REQUIRES_NEW via&lt;br /&gt;
  a @Lazy self-reference so the proxy actually applies. Outcome is committed as soon&lt;br /&gt;
  as it is known; a crash now loses at most the mail in flight.&lt;br /&gt;
- MailOutbox.selectPending retries FAILED rows once more (retryCount &amp;lt; 2).&lt;br /&gt;
- Stable per-row Message-ID so a retry arrives as the same message and the receiving&lt;br /&gt;
  server can collapse it instead of showing a duplicate.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/mail/MailOutbox.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/mail/MailOutboxService.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37361&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37361&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 20:30:29 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37360 – ICICI policy issuance: stop losing policies to a proposal read ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;ICICI policy issuance: stop losing policies to a proposal read timeout&lt;br /&gt;
&lt;br /&gt;
hitAfinityProposal called ICICI&apos;s gadget proposal endpoint on the default 10s socket&lt;br /&gt;
timeout. That POST issues the policy, so a read timeout abandons a request ICICI is&lt;br /&gt;
still completing. The exception then unwound through generateIciciLombardPolicy into&lt;br /&gt;
the controller&apos;s @Transactional(rollbackFor = Throwable.class), rolling back the whole&lt;br /&gt;
request - including the wallet debit - before the tracker row was ever touched. Result:&lt;br /&gt;
policy possibly live at ICICI, no trace on our side, and the &apos;policy already exists&apos;&lt;br /&gt;
retry path dead-ends because its Redis cache is only written on a parsed success.&lt;br /&gt;
&lt;br /&gt;
- Proposal and policy-certificate calls move to a dedicated RestClient built on&lt;br /&gt;
  HttpClientFactory.insuranceIssuanceRequestConfig() (socket 45s). JWT and quote stay&lt;br /&gt;
  on the default client - fast, and no remote write.&lt;br /&gt;
- Transport failures are classified via HttpTransportFailures and reported as &apos;outcome&lt;br /&gt;
  unknown&apos;, not as an ICICI rejection.&lt;br /&gt;
- IciciPolicyTrackerBookkeeping writes the tracker in REQUIRES_NEW, so both the UNKNOWN&lt;br /&gt;
  outcome and the issued policy number survive the request rollback. Recovery from an&lt;br /&gt;
  UNKNOWN row is the existing recoverPolicyNumberByProposalNumber path.&lt;br /&gt;
&lt;br /&gt;
Code only, no DDL: status is varchar(20) and remarks is text on prod already.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/icicilombard/IciciLombardService.java&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/icicilombard/IciciPolicyTrackerBookkeeping.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37360&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37360&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 20:30:18 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37359 – ICICI proposal read timeout: add insurance-issuance HTTP config + shared ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;ICICI proposal read timeout: add insurance-issuance HTTP config + shared transport-failure classifier&lt;br /&gt;
&lt;br /&gt;
The default RestClient carries a 10s socket timeout, sized for quick lookups. ICICI&apos;s&lt;br /&gt;
gadget proposal endpoint underwrites and issues the policy synchronously and needs&lt;br /&gt;
longer; abandoning the read discards the only response carrying the policy and&lt;br /&gt;
proposal numbers for a policy that is already live at the insurer.&lt;br /&gt;
&lt;br /&gt;
- HttpClientFactory.insuranceIssuanceRequestConfig(): connect 5s, socket 45s. Not&lt;br /&gt;
  slowRegulatorRequestConfig() - its contract forbids request-thread use with an open&lt;br /&gt;
  transaction, which is exactly the ICICI call site.&lt;br /&gt;
- HttpTransportFailures: cause-chain check separating &apos;the call never completed&apos; from&lt;br /&gt;
  &apos;the remote said no&apos;. Needed because RestClient rewraps transport errors as&lt;br /&gt;
  RuntimeException(GE_1006), so the top-level exception type is uninformative.&lt;/div&gt;~ /trunk/profitmandi-common/src/main/java/com/spice/profitmandi/common/web/client/HttpClientFactory.java&lt;br /&gt;+ /trunk/profitmandi-common/src/main/java/com/spice/profitmandi/common/web/client/HttpTransportFailures.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37359&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37359&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 18:04:00 +0530</pubDate><dc:creator>ranu</dc:creator><title>Rev 37358 – total show on warehouse wise stock value on item detail</title><description>&lt;div&gt;&lt;strong&gt;ranu – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;total show on warehouse wise stock value on item detail&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/warehouse_item_details.vm&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37358&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37358&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 18:01:36 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37357 – Add CsService.getAuthUsersByPartnerIdAndCategory for partner+category+escalation lookup  sendMailForActionOnDispatch mailed every L1 ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Add CsService.getAuthUsersByPartnerIdAndCategory for partner+category+escalation lookup&lt;br /&gt;
&lt;br /&gt;
sendMailForActionOnDispatch mailed every L1 position on the partner, which on live data&lt;br /&gt;
means the DESIGN (17), SALES (4) and WAREHOUSE (11) owners as well as the RBM (18). It&lt;br /&gt;
also hand-rolled the partner_position -&gt; position -&gt; auth_user walk against repositories.&lt;br /&gt;
&lt;br /&gt;
Add a single reusable resolver on CsService: active auth users holding one position&lt;br /&gt;
category against a partner, optionally narrowed to escalation levels. It follows the&lt;br /&gt;
house resolver shape - the partner&apos;s own regions plus ALL_PARTNERS_REGION, partner_id in&lt;br /&gt;
(0, fofoId) - so region-wide mappings are honoured, and it short-circuits on empty id&lt;br /&gt;
lists because selectByIds builds an IN () predicate that breaks on an empty list.&lt;br /&gt;
&lt;br /&gt;
The call site in TransactionServiceImpl went in with r37356; without this commit trunk&lt;br /&gt;
does not compile.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/cs/CsService.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/cs/CsServiceImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37357&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37357&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 17:59:24 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37356 – Fixed max limit to 15 lac for Credit limit</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Fixed max limit to 15 lac for Credit limit&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/transaction/TransactionServiceImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37356&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37356&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 13:23:38 +0530</pubDate><dc:creator>aman</dc:creator><title>Rev 37355 – AI lead intake (fofo, live): assign new leads to a ...</title><description>&lt;div&gt;&lt;strong&gt;aman – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;AI lead intake (fofo, live): assign new leads to a random active BGC L1 instead of the hardcoded Khushbu/Archana round-robin&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/LeadController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37355&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37355&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 13:22:05 +0530</pubDate><dc:creator>aman</dc:creator><title>Rev 37354 – AI lead intake: pool is BGC L1 (category 20), not ...</title><description>&lt;div&gt;&lt;strong&gt;aman – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;AI lead intake: pool is BGC L1 (category 20), not Sales L1 - BGC is the desk that works AI leads&lt;/div&gt;~ /trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/controller/LeadController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37354&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37354&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 13:16:59 +0530</pubDate><dc:creator>aman</dc:creator><title>Rev 37353 – AI lead intake: assign new leads to a random active ...</title><description>&lt;div&gt;&lt;strong&gt;aman – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;AI lead intake: assign new leads to a random active Sales L1 instead of fixed auth id 53&lt;/div&gt;~ /trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/controller/LeadController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37353&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37353&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 12:30:38 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37352 – Fixed max limit to 15 lac for Credit limit</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Fixed max limit to 15 lac for Credit limit&lt;/div&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/PartnerLimitHelper.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37352&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37352&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 11:04:35 +0530</pubDate><dc:creator>ranu</dc:creator><title>Rev 37351 – code committed for sales l3 added in bi and other ...</title><description>&lt;div&gt;&lt;strong&gt;ranu – 5 file(s) modified&lt;/strong&gt;&lt;br/&gt;code committed for sales l3 added in bi and other model&lt;/div&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ScheduledTasks.java&lt;br /&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ScheduledTasksTest.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/model/BIRetailerModel.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/model/FofoReportingModel.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/cs/CsServiceImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37351&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37351&amp;peg=37365</guid></item>
<item><pubDate>Wed, 19 Aug 2026 09:52:34 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37350 – Fix SD Credit daily statement showing zero interest on overdue ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Fix SD Credit daily statement showing zero interest on overdue loans&lt;br /&gt;
&lt;br /&gt;
sdDirectService classified each day&apos;s interest by exact-matching the&lt;br /&gt;
loan_statement description (&apos;Interest On Loan Per Day&apos; /&lt;br /&gt;
&apos;Penalty On Loan Per Day&apos;). Once a loan crossed its due date the cron&lt;br /&gt;
switches the label to &apos;Overdue Interest On Loan Per Day&apos;, which matched&lt;br /&gt;
neither filter, so the daily statement reported 0.00 interest for every&lt;br /&gt;
overdue day even though the charge was booked correctly in&lt;br /&gt;
loan_statement and loan.interest_accured.&lt;br /&gt;
&lt;br /&gt;
Classify by tenure window against loan.getPenaltyDate() instead - the&lt;br /&gt;
same test addInterest() uses to pick the rate - and net the day&apos;s full&lt;br /&gt;
interest out of the opening balance so penalty days are consistent too.&lt;br /&gt;
&lt;br /&gt;
Seen on loan 120277 (invoice NSLCK35860): Rs.73-83/day accruing from&lt;br /&gt;
08-Aug, displayed as 0.00.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/transaction/SDCreditServiceImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37350&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37350&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 18:31:10 +0530</pubDate><dc:creator>ranu</dc:creator><title>Rev 37349 – super retailer club 5 live</title><description>&lt;div&gt;&lt;strong&gt;ranu – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;super retailer club 5 live&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/transaction/OrderRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37349&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37349&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 18:26:37 +0530</pubDate><dc:creator>ranu</dc:creator><title>Rev 37348 – super retailer club 5 live</title><description>&lt;div&gt;&lt;strong&gt;ranu – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;super retailer club 5 live&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/transaction/OrderRepository.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/transaction/OrderRepositoryImpl.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/DashboardController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37348&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37348&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 16:58:26 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37347 – Give the ingest runner a transaction; it had none on ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Give the ingest runner a transaction; it had none on its background thread&lt;br /&gt;
&lt;br /&gt;
Parsing failed instantly on production with&lt;br /&gt;
&lt;br /&gt;
  org.hibernate.HibernateException: Could not obtain transaction-synchronized&lt;br /&gt;
  Session for current thread&lt;br /&gt;
    at CircularIngestRepositoryImpl.claimForProcessing&lt;br /&gt;
    at CircularIngestRunner.processOne&lt;br /&gt;
&lt;br /&gt;
The runner works on a background thread. Nothing binds a Hibernate session to it, so&lt;br /&gt;
the very first repository call - the claim - threw. Worse, the failure handler called&lt;br /&gt;
markFailed, which threw for the same reason, so nothing was recorded: the document sat&lt;br /&gt;
in DRAFT with no error, no processed_at and no outward sign that anything had gone&lt;br /&gt;
wrong. CircularIngestService.ingest was never reached.&lt;br /&gt;
&lt;br /&gt;
This was latent in the cron version too. It never surfaced because that scheduler was&lt;br /&gt;
never actually deployed anywhere.&lt;br /&gt;
&lt;br /&gt;
- New CircularIngestBookkeeping: claim / document / published / failed /&lt;br /&gt;
  reclaimStalled, each REQUIRES_NEW. Independent transactions matter most for failed(),&lt;br /&gt;
  which runs after the ingest transaction has already rolled back and must not be&lt;br /&gt;
  dragged into it.&lt;br /&gt;
- It is a SEPARATE bean on purpose. @Transactional on the runner&apos;s own methods would be&lt;br /&gt;
  invoked from inside its own Runnable - a self-invocation never passes through the&lt;br /&gt;
  Spring proxy, so the annotation would be silently ignored and the bug would come back&lt;br /&gt;
  wearing a disguise.&lt;br /&gt;
- The runner no longer touches CircularIngestRepository at all.&lt;br /&gt;
&lt;br /&gt;
Not caught locally because the RunIngest harness uses JdbcIngestRepo, a plain-JDBC&lt;br /&gt;
implementation that bypasses Hibernate entirely - so it can reproduce the parsing but&lt;br /&gt;
never a session or transaction problem.&lt;/div&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularIngestBookkeeping.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularIngestRunner.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37347&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37347&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 16:45:26 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37346 – Sort sale returns so the ones still needing an action ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Sort sale returns so the ones still needing an action come first&lt;br /&gt;
&lt;br /&gt;
The Recently Received Debit Notes table was ordered purely by receive time, so a&lt;br /&gt;
return waiting on a refund or on the partner&apos;s acknowledgment sank below rows that&lt;br /&gt;
were already refunded and needed nothing. On a busy warehouse the actionable rows&lt;br /&gt;
were off the first screen.&lt;br /&gt;
&lt;br /&gt;
- recentOrders is now ranked pending-first (Received - Pending Refund, Rejected -&lt;br /&gt;
  Pending Acknowledgment) ahead of settled ones (Refunded, Cancelled), with the&lt;br /&gt;
  existing receiveTimestamp DESC kept as the tie-breaker inside each group&lt;br /&gt;
- getPendingActionRank follows the same precedence invoice-return.vm uses to pick&lt;br /&gt;
  the status badge - reject checked before refund - so the ordering can never&lt;br /&gt;
  disagree with the label the user sees&lt;br /&gt;
- ranked on the return&apos;s own state, not on the viewer&apos;s canReceive/canRefund&lt;br /&gt;
  permissions, so a pending return stays at the top for everyone looking at it&lt;br /&gt;
&lt;br /&gt;
Presentation only; no query, entity or lifecycle change. Note that returns never&lt;br /&gt;
received at all cannot surface here regardless, since the query filters on&lt;br /&gt;
receiveTimestamp BETWEEN the selected dates.&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/PurchaseReturnController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37346&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37346&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 16:12:06 +0530</pubDate><dc:creator>vikas</dc:creator><title>Rev 37345 – Beat Journey (today): LOI-based &apos;Onboarded&apos; + last-billing recency board columns, ...</title><description>&lt;div&gt;&lt;strong&gt;vikas – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Beat Journey (today): LOI-based &apos;Onboarded&apos; + last-billing recency board columns, level-filtered orders list (grouped by partner), and flag tuning — remove #1/#3, use per-visit total_distance for #4.&lt;br /&gt;
&lt;br /&gt;
Co-Authored-By: Claude Opus 4.8 (1M context) &amp;lt;&lt;a href=&quot;mailto:noreply@anthropic.com&quot;&gt;noreply@anthropic.com&lt;/a&gt;&gt;&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/BeatJourneyController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37345&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37345&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 16:05:12 +0530</pubDate><dc:creator>vikas</dc:creator><title>Rev 37344 – Beat Journey: LoiFormRepository.selectMaxApprovedAcquiredDateByBdm() — max approved-LOI acquiredDate per BDM, powering ...</title><description>&lt;div&gt;&lt;strong&gt;vikas – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Beat Journey: LoiFormRepository.selectMaxApprovedAcquiredDateByBdm() — max approved-LOI acquiredDate per BDM, powering the board &apos;Onboarded&apos; column (store.active_timestamp is null for all stores).&lt;br /&gt;
&lt;br /&gt;
Co-Authored-By: Claude Opus 4.8 (1M context) &amp;lt;&lt;a href=&quot;mailto:noreply@anthropic.com&quot;&gt;noreply@anthropic.com&lt;/a&gt;&gt;&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/LoiFormRepository.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/LoiFormRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37344&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37344&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 15:18:27 +0530</pubDate><dc:creator>vikas</dc:creator><title>Rev 37343 – Update PJP, Visit quality flags</title><description>&lt;div&gt;&lt;strong&gt;vikas – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Update PJP, Visit quality flags&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/BeatJourneyController.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/beat-journey.vm&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37343&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37343&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 14:59:37 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37342 – Allow re-ingest to start a circular already sitting in DRAFT ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Allow re-ingest to start a circular already sitting in DRAFT&lt;br /&gt;
&lt;br /&gt;
Moving the parse into the portal turned DRAFT into a dead end. Under the cron&lt;br /&gt;
scheduler DRAFT meant &quot;something will pick me up&quot;, so re-ingest only ever had to push&lt;br /&gt;
a document back into it, and PUBLISHED/FAILED were the only sensible sources. Nothing&lt;br /&gt;
polls DRAFT any more - the runner is triggered by the upload that created the&lt;br /&gt;
document - so a circular whose trigger never fired had no way to be started at all.&lt;br /&gt;
&lt;br /&gt;
That is not hypothetical: the Aug&apos;26 circular uploaded to production before the runner&lt;br /&gt;
was deployed sits in DRAFT, and pressing re-ingest matched zero rows and reported&lt;br /&gt;
&quot;not started&quot;.&lt;br /&gt;
&lt;br /&gt;
DRAFT now joins PUBLISHED and FAILED as a valid source state. PROCESSING stays&lt;br /&gt;
excluded - that one is genuinely in flight - and claimForProcessing remains the single&lt;br /&gt;
arbiter of who actually parses, so allowing DRAFT cannot cause a double parse.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCurationRepository.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCurationRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37342&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37342&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 14:52:54 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37341 – fix(rbm-dashboard): return full partner book and exclude inactive stores  ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;fix(rbm-dashboard): return full partner book and exclude inactive stores&lt;br /&gt;
&lt;br /&gt;
/v2/fofo/rbm-dashboard capped partners/alerts at 50 by default. The RBM home&lt;br /&gt;
searches and filters client-side, so any partner outside that slice was&lt;br /&gt;
unfindable while summary.totalPartners reported the real (much larger) count.&lt;br /&gt;
&lt;br /&gt;
- limit now defaults to 0 = uncapped; an explicit ?limit=n is still honoured&lt;br /&gt;
  up to RBM_DASHBOARD_MAX_LIMIT (200)&lt;br /&gt;
- deactivated stores are skipped for the whole computation, not just alerts:&lt;br /&gt;
  they have no target, scored 0% and sorted to the top of the action list&lt;br /&gt;
- summary.limit reports 0 when uncapped instead of Integer.MAX_VALUE&lt;/div&gt;~ /trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/v2/controller/fofo/V2FofoMonitorController.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37341&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37341&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 14:46:23 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37340 – Fixed max limit to 15 lac for Credit limit</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Fixed max limit to 15 lac for Credit limit&lt;/div&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/Application.java&lt;br /&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ScheduledTasks.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37340&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37340&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 13:48:38 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37339 – Fixed max limit to 15 lac for Credit limit</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Fixed max limit to 15 lac for Credit limit&lt;/div&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/PartnerLimitHelper.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37339&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37339&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 13:38:14 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37338 – Remove offer-circular ingest from cron - it now runs in ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;Remove offer-circular ingest from cron - it now runs in the portal&lt;br /&gt;
&lt;br /&gt;
Counterpart to the fofo commit that moved the parse into profitmandi-fofo. Nothing is&lt;br /&gt;
lost: all 13 parser classes and the test moved verbatim, and CircularIngestScheduler&lt;br /&gt;
was replaced by an executor-driven runner in the portal.&lt;br /&gt;
&lt;br /&gt;
- com.smartdukaan.cron.offercircular deleted, main and test&lt;br /&gt;
- tabula dependency removed; PDFBox no longer enters this artifact at all&lt;br /&gt;
- dumpCircularClasspath moved to fofo, where the parser and its classpath now live&lt;br /&gt;
&lt;br /&gt;
This module no longer knows anything about offer circulars, so a cron rebuild is no&lt;br /&gt;
longer a prerequisite for the feature to work - which was the entire problem.&lt;/div&gt;~ /trunk/profitmandi-cron/build.gradle&lt;br /&gt;x /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular&lt;br /&gt;x /trunk/profitmandi-cron/src/test/java/com/smartdukaan/cron/offercircular&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37338&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37338&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 13:37:58 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37337 – Move offer-circular ingest out of cron and into the portal ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 23 file(s) modified&lt;/strong&gt;&lt;br/&gt;Move offer-circular ingest out of cron and into the portal&lt;br /&gt;
&lt;br /&gt;
The parse now runs in profitmandi-fofo, on a background thread, triggered by the&lt;br /&gt;
upload that produced the document.&lt;br /&gt;
&lt;br /&gt;
Why: splitting one feature across two artifacts with independent deploy cadences&lt;br /&gt;
cost a full day. fofo shipped, cron did not, and a valid upload sat in DRAFT with&lt;br /&gt;
nothing on the server able to parse it - the deployed cron jar contained none of the&lt;br /&gt;
ingest classes. One 9-page PDF a month never justified a batch tier, and the portal&lt;br /&gt;
already ships two PDF stacks, so the isolation argument for keeping PDFBox out was&lt;br /&gt;
weaker than it looked.&lt;br /&gt;
&lt;br /&gt;
- 13 parser classes move verbatim from com.smartdukaan.cron.offercircular to&lt;br /&gt;
  com.spice.profitmandi.web.offercircular. No logic changed.&lt;br /&gt;
- CircularIngestScheduler becomes CircularIngestRunner: the @Scheduled(every 5 min)&lt;br /&gt;
  entry point and the offer.circular.ingest.enabled flag are gone, replaced by a&lt;br /&gt;
  single-threaded daemon executor. All claim, ingest and notification logic is&lt;br /&gt;
  unchanged.&lt;br /&gt;
- Upload hands the document id to the runner AFTER COMMIT, not inline. The DRAFT row&lt;br /&gt;
  is written inside the request transaction; a worker starting immediately would race&lt;br /&gt;
  that commit, find nothing to claim and silently do nothing - which is precisely the&lt;br /&gt;
  stuck-on-DRAFT symptom this change removes.&lt;br /&gt;
- The guarded claim is KEPT even though there is now one trigger. It still stops a&lt;br /&gt;
  double-submit, a second portal node, and a re-ingest racing an in-flight parse.&lt;br /&gt;
- Re-ingest parses immediately instead of queueing for a scheduler.&lt;br /&gt;
- The stall reaper runs when the review screen loads. There is no timer here any&lt;br /&gt;
  more, and a document stranded by a redeploy mid-parse only matters when somebody&lt;br /&gt;
  looks for it - which matters more now the parse lives in the web application.&lt;br /&gt;
- tabula moves to this module with its exclusions intact, as does the&lt;br /&gt;
  dumpCircularClasspath helper the local ingest harness depends on.&lt;br /&gt;
- Screen no longer claims &quot;the ingest job runs every 5 minutes&quot;, which was untrue the&lt;br /&gt;
  moment cron stopped being the route; poll interval 15s -&gt; 3s to match a parse that&lt;br /&gt;
  takes seconds. jsVersion 404 -&gt; 405.&lt;br /&gt;
- offer.circular.review.url added here, since the runner sends that email now.&lt;br /&gt;
&lt;br /&gt;
Verified: full ingest of the Aug&apos;26 circular through the relocated code is identical&lt;br /&gt;
to the reference - 239 offers, 663 products, 279 AUTO_EXACT, 361 benefits, 511&lt;br /&gt;
tenures, 911 bank links. ProductNamesTest 11/11 in its new home.&lt;/div&gt;~ /trunk/profitmandi-fofo/build.gradle&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/config/AppConfig.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/OfferCircularController.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/BankTextParser.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/BenefitParser.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CatalogIndex.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularExtractor.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularIngestRunner.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularIngestService.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/CircularRow.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/FootnoteParser.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/ProductAliases.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/ProductMatcher.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/ProductNames.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/ScopeConfig.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/SequenceRatio.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/offercircular/TenureParser.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/resources/META-INF/dev.properties&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/resources/META-INF/prod.properties&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/resources/js/offer-circular-review.js&lt;br /&gt;+ /trunk/profitmandi-fofo/src/test/java/com/spice/profitmandi/web/offercircular&lt;br /&gt;+ /trunk/profitmandi-fofo/src/test/java/com/spice/profitmandi/web/offercircular/ProductNamesTest.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37337&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37337&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 12:13:49 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37336 – Expose loginEmail to the admin views  admin.vm gates the ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 1 file(s) modified&lt;/strong&gt;&lt;br/&gt;Expose loginEmail to the admin views&lt;br /&gt;
&lt;br /&gt;
admin.vm gates the OFFER CIRCULAR sidebar entry on the exact logged-in email,&lt;br /&gt;
because visibility there is per-email and auth.menu can only express roles. Nothing&lt;br /&gt;
was setting that variable, so the #if was always false and the entry rendered for&lt;br /&gt;
nobody on a clean build - it only appeared where a working copy happened to carry&lt;br /&gt;
this line locally.&lt;br /&gt;
&lt;br /&gt;
Committed alongside r37331, which added the gate itself.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/AdminUser.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37336&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37336&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 12:12:09 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37335 – Show offer circular ingest state on the review screen  ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;Show offer circular ingest state on the review screen&lt;br /&gt;
&lt;br /&gt;
Upload and parsing run in different processes - the portal stores the PDF as DRAFT&lt;br /&gt;
and the cron job claims it minutes later - so the screen looked identical before and&lt;br /&gt;
after a successful ingest. A reviewer had no way to tell &quot;not parsed yet&quot; from&lt;br /&gt;
&quot;parsed and produced nothing&quot;, and a FAILED circular showed nothing at all.&lt;br /&gt;
&lt;br /&gt;
- the selected circular&apos;s state is shown as queued / parsing / parsed / failed,&lt;br /&gt;
  with the recorded reason on failure and the ingest summary on success&lt;br /&gt;
- while it is DRAFT or PROCESSING the screen polls every 15s and pulls in the rows&lt;br /&gt;
  the moment the parse lands. Polling stops as soon as the state settles, so it&lt;br /&gt;
  cannot spin forever, and a transient error keeps waiting rather than giving up&lt;br /&gt;
- jsVersion 403 -&gt; 404, since offer-circular-review.js is already being served and&lt;br /&gt;
  this is a modification rather than a new file&lt;br /&gt;
&lt;br /&gt;
Pairs with the stall reaper: a circular abandoned mid-parse is now both recovered&lt;br /&gt;
and explained on screen instead of sitting silently in PROCESSING.&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/config/AppConfig.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/resources/js/offer-circular-review.js&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/offer-circular-review.vm&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37335&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37335&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 12:11:53 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37334 – Sweep stalled offer circulars before each ingest run, and drop ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;Sweep stalled offer circulars before each ingest run, and drop stale scaffolding&lt;br /&gt;
&lt;br /&gt;
- The scheduler now calls reclaimStalledProcessing before looking for new work, so&lt;br /&gt;
  a circular stranded in PROCESSING by a dead or redeployed worker is failed with a&lt;br /&gt;
  reason instead of staying invisible forever. Threshold is 30 minutes against a&lt;br /&gt;
  parse that takes seconds, so it can only ever catch a genuinely dead worker. The&lt;br /&gt;
  sweep is wrapped so it can never stop the actual ingest.&lt;br /&gt;
- dumpCircularClasspath was labelled a temporary helper for diffing against the&lt;br /&gt;
  reference Python. That Python has been deleted, but the task is what lets an&lt;br /&gt;
  ingest be reproduced and measured locally per scripts/offer_circular/README.md,&lt;br /&gt;
  so the comment now says what it is for rather than telling the next reader to&lt;br /&gt;
  delete it.&lt;br /&gt;
- CircularExtractor&apos;s javadoc claimed verification against the Python reference.&lt;br /&gt;
  That proved equivalence, not correctness - both shared the missing-memory-unit&lt;br /&gt;
  bug that bound offers to the wrong SKU. Reworded so it cannot be read as a&lt;br /&gt;
  correctness guarantee, and points at the fixture and ProductNamesTest instead.&lt;br /&gt;
&lt;br /&gt;
Verified: full ingest of the Aug&apos;26 circular is byte-identical to the reference -&lt;br /&gt;
239 offers, 663 products, 279 AUTO_EXACT. ProductNamesTest 11/11.&lt;/div&gt;~ /trunk/profitmandi-cron/build.gradle&lt;br /&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CircularExtractor.java&lt;br /&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CircularIngestScheduler.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37334&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37334&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 12:11:38 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37333 – Reclaim offer circulars stranded in PROCESSING, and surface the ingest ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;Reclaim offer circulars stranded in PROCESSING, and surface the ingest reason&lt;br /&gt;
&lt;br /&gt;
A claim moves a circular DRAFT -&gt; PROCESSING, and selectDraftDocumentIds only ever&lt;br /&gt;
picks up DRAFT. So a worker that died, was redeployed, or hung mid-parse left that&lt;br /&gt;
document stranded in PROCESSING forever, invisible to every later sweep. The batch&lt;br /&gt;
tier looked like it provided retry semantics and did not.&lt;br /&gt;
&lt;br /&gt;
- reclaimStalledProcessing(minutes) fails anything left in PROCESSING past the&lt;br /&gt;
  threshold. Deliberately FAILED and not back to DRAFT: a circular that reliably&lt;br /&gt;
  kills the parser would otherwise be re-claimed on every sweep forever. FAILED is&lt;br /&gt;
  visible, carries the reason, and the existing re-ingest action already allows&lt;br /&gt;
  FAILED -&gt; DRAFT, so re-queueing is one click.&lt;br /&gt;
- claimForProcessing now stamps processed_at, which is what the stall is measured&lt;br /&gt;
  against. No DDL: that column is written only by this repository and read by&lt;br /&gt;
  nothing else, so it can carry the last-transition time.&lt;br /&gt;
- selectDocuments returns ingest_error and ingest_summary. Without the reason the&lt;br /&gt;
  screen would show a bare FAILED, which the reaper would now produce routinely.&lt;br /&gt;
&lt;br /&gt;
Verified against the local DB both ways: a claim aged 45 minutes is reclaimed with&lt;br /&gt;
its reason recorded, a fresh claim is untouched.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/CircularIngestRepository.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/CircularIngestRepositoryImpl.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCircularRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37333&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37333&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 11:18:51 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37332 – Move the offer-circular upload directory off a developer home path ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 3 file(s) modified&lt;/strong&gt;&lt;br/&gt;Move the offer-circular upload directory off a developer home path&lt;br /&gt;
&lt;br /&gt;
Every upload in production failed with a 400 on mkdirs. offer.circular.dir was&lt;br /&gt;
never set in any environment, so it fell back to the code default&lt;br /&gt;
/users/amit/uploads/offer-circulars; Tomcat runs as the tomcat user, which cannot&lt;br /&gt;
create /users at the filesystem root, and the controller threw &quot;Circular storage&lt;br /&gt;
directory is not writable&quot;.&lt;br /&gt;
&lt;br /&gt;
- default is now /var/lib/smartdukaan/offer-circulars, a real server path&lt;br /&gt;
- offer.circular.dir set explicitly in prod.properties, and pointed at the&lt;br /&gt;
  developer&apos;s own space in dev.properties, since /var/lib needs sudo on a&lt;br /&gt;
  workstation&lt;br /&gt;
- staging.properties deliberately untouched; the new default covers it&lt;br /&gt;
&lt;br /&gt;
The location has two hard constraints, now recorded on the field itself:&lt;br /&gt;
&lt;br /&gt;
- OUTSIDE webapps/. A redeploy wipes anything under it, and&lt;br /&gt;
  offer_document.stored_path is how both re-ingest and re-download resolve the&lt;br /&gt;
  PDF, so a wipe breaks them permanently. Stray PDFs are already sitting in&lt;br /&gt;
  WEB-INF/classes/META-INF on the server from exactly this mistake.&lt;br /&gt;
- OUTSIDE any web root. A circular carries the OEM&apos;s confidential cashback&lt;br /&gt;
  economics and must never be servable as a static file. Hence /var/lib rather&lt;br /&gt;
  than /var/www, whose local precedent /var/www/partner_stats is chmod 777.&lt;br /&gt;
&lt;br /&gt;
Only fofo needs the key: the cron ingest resolves the PDF from&lt;br /&gt;
offer_document.stored_path and reads it as root, so 0750 tomcat:tomcat is enough.&lt;br /&gt;
&lt;br /&gt;
Deploying this alone does not fix production - the directory must also exist and&lt;br /&gt;
be writable by tomcat.&lt;/div&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/OfferCircularController.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/resources/META-INF/dev.properties&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/resources/META-INF/prod.properties&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37332&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37332&amp;peg=37365</guid></item>
<item><pubDate>Tue, 18 Aug 2026 00:19:29 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37331 – Add offer circular review and curation screen  Shows the ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 5 file(s) modified&lt;/strong&gt;&lt;br/&gt;Add offer circular review and curation screen&lt;br /&gt;
&lt;br /&gt;
Shows the nine verbatim PDF columns beside what the parser made of them, uploads a&lt;br /&gt;
new monthly circular, and resolves the products the matcher could not.&lt;br /&gt;
&lt;br /&gt;
Upload deliberately does not parse - it stores the PDF, sha256-deduped, and&lt;br /&gt;
registers it DRAFT, so an upload can never half-populate the offer tables. The cron&lt;br /&gt;
ingest job picks it up from there.&lt;br /&gt;
&lt;br /&gt;
The curation queue groups by distinct (division, raw text) because that is the&lt;br /&gt;
product_alias key: one answer clears every row carrying that text, on this circular&lt;br /&gt;
and on every later one. On the Aug&apos;26 circular that turns 152 unresolved rows into&lt;br /&gt;
106 decisions. Three actions mirror product_alias.action - PIN to a catalog id,&lt;br /&gt;
REWRITE to the catalog&apos;s spelling and match again, or IGNORE.&lt;br /&gt;
&lt;br /&gt;
- Writes product_alias only, so nothing the screen does can set manually_curated&lt;br /&gt;
  and lock a circular against re-ingest. Coverage decisions, which do need that,&lt;br /&gt;
  are listed but visibly parked rather than offered a naming answer.&lt;br /&gt;
- A saved decision changes nothing until re-ingest, because aliases are read at&lt;br /&gt;
  ingest time; the queue says so and the re-ingest button puts the document back&lt;br /&gt;
  to DRAFT for the scheduler. The portal cannot run the ingest itself - that lives&lt;br /&gt;
  in profitmandi-cron, which fofo does not depend on.&lt;br /&gt;
- The closest rejected match is shown for context and never pre-selected. Four new&lt;br /&gt;
  OnePlus models each &quot;nearly&quot; matched a 2015 OnePlus 2 at 0.80-0.84, and offering&lt;br /&gt;
  that as a suggestion invites a reviewer to confirm it. Where the catalog has no&lt;br /&gt;
  such SKU the search says so and steers to IGNORE.&lt;br /&gt;
- aliasExport emits every decision as replayable SQL, because the portal writes to&lt;br /&gt;
  one database and environments would otherwise drift apart silently.&lt;br /&gt;
&lt;br /&gt;
Access is an email allowlist AND the admin role. Both are enforced in the&lt;br /&gt;
controller; the sidebar entry repeats the allowlist because visibility in auth.menu&lt;br /&gt;
is role-driven and cannot express a per-email rule.&lt;br /&gt;
&lt;br /&gt;
No jsVersion bump: offer-circular-review.js is a new file that was never cached,&lt;br /&gt;
so it needs no cache-buster, and churning that shared counter only conflicts with&lt;br /&gt;
whoever is mid-edit on it.&lt;/div&gt;+ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/OfferCircularController.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/js/offer-circular-review.js&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/admin.vm&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/include-scripts.vm&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/offer-circular-review.vm&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37331&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37331&amp;peg=37365</guid></item>
<item><pubDate>Mon, 17 Aug 2026 21:07:56 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37330 – Add Pine Labs affordability circular parsing and ingest  Turns ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 21 file(s) modified&lt;/strong&gt;&lt;br/&gt;Add Pine Labs affordability circular parsing and ingest&lt;br /&gt;
&lt;br /&gt;
Turns the monthly OEM &quot;Mobile &amp; Laptop Offers&quot; PDF into the offers schema: tabula&lt;br /&gt;
extraction to nine verbatim columns per row, per-cell parsers for benefit, tenure,&lt;br /&gt;
bank and footnote text, catalog matching, and a scheduler that claims DRAFT&lt;br /&gt;
documents uploaded from the FOFO portal and emails the uploader the outcome.&lt;br /&gt;
&lt;br /&gt;
Ships inert. offer.circular.ingest.enabled defaults to false, so the scheduler does&lt;br /&gt;
nothing until an environment opts in, and offer.circular.review.url defaults to&lt;br /&gt;
empty - neither key is required for the context to start.&lt;br /&gt;
&lt;br /&gt;
- tabula added here and not in profitmandi-common so PDFBox never reaches the&lt;br /&gt;
  web/fofo WARs; bouncycastle, slf4j-simple and jai-imageio excluded (version&lt;br /&gt;
  clash, duplicate SLF4J binding, and unused image decoding respectively)&lt;br /&gt;
- offer_raw_row holds all nine columns verbatim, so re-parsing reads the table and&lt;br /&gt;
  never the PDF again&lt;br /&gt;
- product_alias is consulted before matching, so a human confirmation recorded once&lt;br /&gt;
  keeps applying every following month&lt;br /&gt;
&lt;br /&gt;
ProductNamesTest locks in the product-name parsing, which decides which SKU an&lt;br /&gt;
offer&apos;s money lands on. Every case there is a real mis-parse, and they share one&lt;br /&gt;
root cause: characters or digits belonging to the model name being eaten as memory&lt;br /&gt;
or stripped as punctuation. Two worth naming:&lt;br /&gt;
&lt;br /&gt;
- A memory spec with no GB/TB unit is still a memory spec. Motorola writes&lt;br /&gt;
  &quot;(8+256)&quot; and vivo &quot;(8+256G)&quot;; unrecognised, the matcher believed no size was&lt;br /&gt;
  given and bound the offer to an arbitrary sibling - a 1,000 Edge 60 Pro 8+256&lt;br /&gt;
  offer and a 2,000 12+256 offer landed on the same SKU.&lt;br /&gt;
- Two variant groups written back-to-back are two products. &quot;Edge 70 Pro&lt;br /&gt;
  (8+256)(12+256)&quot; stayed one product bound to a single SKU while the 12+256&lt;br /&gt;
  variant silently got no offer at all.&lt;br /&gt;
&lt;br /&gt;
Bundled accessories are deliberately NOT stripped back to the bare phone. Doing so&lt;br /&gt;
resolves 30 CATALOG_GAP rows and looks safe on Oppo, whose bundled and bare rows&lt;br /&gt;
carry identical values - but vivo caps X300 Pro(16+512G) at 10,000 on its own row&lt;br /&gt;
and 11,000 on the &quot;+Extender&quot; row, the difference being the Extender. Merging them&lt;br /&gt;
would let the bundle&apos;s cap be claimed on a phone sold without the accessory.&lt;br /&gt;
Whether a bundle offer transfers to the bare SKU is a commercial question the PDF&lt;br /&gt;
does not answer, so it is a manual coverage decision, not a parsing rule.&lt;br /&gt;
&lt;br /&gt;
Verified against the Aug&apos;26 circular on the local DB: 324 rows in the PDF, 239&lt;br /&gt;
loaded, producing 361 benefits, 511 tenures, 911 bank links and 663 products, of&lt;br /&gt;
which 74% resolve automatically. ProductNamesTest 11/11.&lt;/div&gt;~ /trunk/profitmandi-cron/build.gradle&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/BankTextParser.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/BenefitParser.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CatalogIndex.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CircularExtractor.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CircularIngestScheduler.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CircularIngestService.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/CircularRow.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/FootnoteParser.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/ProductAliases.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/ProductMatcher.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/ProductNames.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/ScopeConfig.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/SequenceRatio.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/offercircular/TenureParser.java&lt;br /&gt;+ /trunk/profitmandi-cron/src/test/java/com&lt;br /&gt;+ /trunk/profitmandi-cron/src/test/java/com/smartdukaan&lt;br /&gt;+ /trunk/profitmandi-cron/src/test/java/com/smartdukaan/cron&lt;br /&gt;+ /trunk/profitmandi-cron/src/test/java/com/smartdukaan/cron/offercircular&lt;br /&gt;+ /trunk/profitmandi-cron/src/test/java/com/smartdukaan/cron/offercircular/ProductNamesTest.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37330&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37330&amp;peg=37365</guid></item>
<item><pubDate>Mon, 17 Aug 2026 21:07:00 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37329 – Add offers-schema repositories for the Pine Labs affordability circular  ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 7 file(s) modified&lt;/strong&gt;&lt;br/&gt;Add offers-schema repositories for the Pine Labs affordability circular&lt;br /&gt;
&lt;br /&gt;
Three repositories over the offers schema, split by who is allowed to write what:&lt;br /&gt;
&lt;br /&gt;
- OfferCircularRepository - read side for the review screen (verbatim rows,&lt;br /&gt;
  documents, per-offer parsed detail)&lt;br /&gt;
- CircularIngestRepository - write side for ingest; claims a DRAFT document with&lt;br /&gt;
  a guarded UPDATE and deletes only rows derived from that one document, so&lt;br /&gt;
  re-ingesting one month cannot disturb another&lt;br /&gt;
- OfferCurationRepository - write side for manual curation&lt;br /&gt;
&lt;br /&gt;
The split is deliberate: a caller that only displays circulars should not hold a&lt;br /&gt;
handle that can rewrite the scope config or the offer tables.&lt;br /&gt;
&lt;br /&gt;
OfferCurationRepository writes offers.product_alias and nothing else. An alias is&lt;br /&gt;
config, keyed on (division_id, raw_text), so re-ingest reproduces it and one&lt;br /&gt;
decision carries into every later circular. Writing offer_product instead would be&lt;br /&gt;
derived data that re-ingest deletes, which is why doing so has to set&lt;br /&gt;
manually_curated and freeze the circular permanently - not a trade worth making for&lt;br /&gt;
a naming decision, so this repository cannot make it.&lt;br /&gt;
&lt;br /&gt;
A PIN is validated against the division&apos;s own brand and category before it is&lt;br /&gt;
stored. Nothing downstream re-checks a pinned id - the matcher takes it at face&lt;br /&gt;
value - so an unverified exception would silently mismap money.&lt;/div&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/CircularIngestRepository.java&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/CircularIngestRepositoryImpl.java&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCircularRepository.java&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCircularRepositoryImpl.java&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCurationRepository.java&lt;br /&gt;+ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/offers/OfferCurationRepositoryImpl.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37329&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37329&amp;peg=37365</guid></item>
<item><pubDate>Mon, 17 Aug 2026 19:25:56 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37328 – Fetch a fresh EWB auth token when the cached one ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Fetch a fresh EWB auth token when the cached one is stale&lt;br /&gt;
&lt;br /&gt;
Two defects made an expired EWB token unrecoverable, surfacing as GSP102&lt;br /&gt;
&quot;eInvoice AuthToken not found or expired&quot; on every GET.&lt;br /&gt;
&lt;br /&gt;
1. ewbApiGet&apos;s retry was unreachable. NIC returns GSP102 with HTTP 400, and&lt;br /&gt;
   RestClient.execute throws GE_1005 on any non-2xx before returning the body, so the&lt;br /&gt;
   &apos;if (response.contains(&quot;GSP102&quot;))&apos; branch could never run. A failed first attempt is&lt;br /&gt;
   now treated as a possibly-stale token and retried once with a freshly minted one; a&lt;br /&gt;
   second failure propagates. The POST path was unaffected — executeJson does not check&lt;br /&gt;
   status, so its retry already worked.&lt;br /&gt;
&lt;br /&gt;
2. Eviction targeted the wrong cache. The token is cached in redisCacheManager but all&lt;br /&gt;
   three sites evicted through redisFortnightlyCacheManage, a different cache, so the&lt;br /&gt;
   eviction was a silent no-op and the stale token survived. Eviction now goes through&lt;br /&gt;
   GstProAuthService.evictEwbAuthToken, declared beside the @Cacheable and pinned to the&lt;br /&gt;
   same cacheManager so the two cannot drift apart again.&lt;br /&gt;
&lt;br /&gt;
Found while dry-running the EWB backfill, which failed on the first invoice.&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/gstpro/GstProAuthService.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/gstpro/GstProService.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37328&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37328&amp;peg=37365</guid></item>
<item><pubDate>Mon, 17 Aug 2026 17:46:07 +0530</pubDate><dc:creator>ranu</dc:creator><title>Rev 37327 – super retailer club 5 live</title><description>&lt;div&gt;&lt;strong&gt;ranu – 21 file(s) modified&lt;/strong&gt;&lt;br/&gt;super retailer club 5 live&lt;/div&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/fofo/FofoOrderRepository.java&lt;br /&gt;~ /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/fofo/FofoOrderRepositoryImpl.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/config/AppConfig.java&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/DashboardController.java&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/1 GM Gold Coin.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/accessories.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/calendar_.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/CURRENTLY AIMING FOR.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/download.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Group 4.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Maharaja.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Mobile And tv.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Raftaar.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Shuruaat.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Tarakki.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Target.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/TOTAL ACHIEVEMENT.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Udaan.png&lt;br /&gt;+ /trunk/profitmandi-fofo/src/main/webapp/resources/images/src-images/Vijeta.png&lt;br /&gt;~ /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/dashboard1.vm&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37327&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37327&amp;peg=37365</guid></item>
<item><pubDate>Mon, 17 Aug 2026 17:23:40 +0530</pubDate><dc:creator>amit</dc:creator><title>Rev 37326 – Add --backfillMissingEwb cron arg  Runs InvoiceService.backfillMissingEwb over an explicit ...</title><description>&lt;div&gt;&lt;strong&gt;amit – 2 file(s) modified&lt;/strong&gt;&lt;br/&gt;Add --backfillMissingEwb cron arg&lt;br /&gt;
&lt;br /&gt;
Runs InvoiceService.backfillMissingEwb over an explicit invoice list:&lt;br /&gt;
  --backfillMissingEwb --invoiceNumbers=A,B,C [--dryRun]&lt;br /&gt;
&lt;br /&gt;
Explicit list rather than a date window so the backfill only touches the invoices known&lt;br /&gt;
to have lost their EWB. NOT_SUPPORTED on the RunOnceTasks wrapper suspends the&lt;br /&gt;
class-level transaction, keeping the NIC lookups outside one.&lt;/div&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/Application.java&lt;br /&gt;~ /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/migrations/RunOnceTasks.java&lt;br /&gt;</description><link>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37326&amp;peg=37365</link><guid>https://svn.smartdukaan.com/revision.php?repname=SmartDukaan&amp;path=%2F&amp;isdir=1&amp;rev=37326&amp;peg=37365</guid></item>
</channel></rss>