| Rev |
Age |
Author |
Path |
Log message |
Diff |
| 37741 |
49 m |
amit |
/trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/ |
fix(fofo): show Pine Labs monthly EMI in rupees, not paise
Plural sends Money.value in paise; the EMI offers modal printed it raw
(185959 INR instead of Rs 1,859.59). Converted at the view only - the
web API hands the same DTO to the app, which expects paise. |
|
| 37740 |
2 h 28 m |
amit |
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/transaction/ |
SD credit: getAvailableAmount no longer writes utilized_limit - it is a read path, but the managed entity was dirty-checked so every availability query (gateway callback, both sanction screens, bulk order creation) flushed an UPDATE; availability is now computed locally as limit - liveUtilization, same value |
|
| 37739 |
2 h 32 m |
amit |
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/gstpro/ |
GstProService: drop imports only the removed Perfios block used
HttpHostConnectException and JSONObject had no other use after r37736. |
|
| 37738 |
3 h 6 m |
vikas |
/trunk/ |
LMS checklist for call |
|
| 37737 |
3 h 8 m |
vikas |
/trunk/ |
LMS checklist for call |
|
| 37736 |
3 h 23 m |
amit |
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/gstpro/ |
Remove dead Perfios GST-return OTP block from GstProService
Commented-out since it was added; the Perfios UAT URL and auth key were the
only trace of that integration. Part of the dead-integrations cleanup
(r37730-37735). |
|
| 37735 |
3 h 34 m |
amit |
/trunk/profitmandi-cron/src/main/ |
Remove dead third-party integrations: cron
- Toffee: attachToffeeInvoices (schedule already commented out), toffeeRollback
and the --tc option; tofee.* keys in run.properties
- Bharti Assist: sendBAGPendingPolicies, testBag/mapBag and the --bag /
--mapbag options
- HyperTrack geofence one-offs (--createGeofence, --getAllGeofences,
--deleteGeofences) and their hardcoded account keys
- SmartPing injection in ScheduledTasks; leftover DTDC comment
- aramex.tracking.url in run.properties |
|
| 37734 |
3 h 34 m |
amit |
/trunk/profitmandi-fofo/src/ |
Remove dead third-party integrations: fofo
- SpiceMoney: controller, spiceform.vm, logo, the Quick Links popover on
analysisDashboard / dashboard-readonly (its button was already commented
out in dashboard1.vm) and the /spicemoney/callback auth exclusions
- FundFina controller and the /fundfina/** auth exclusions
- Wiseapp: the Quick Links popover on 12dashboard34 (its only entry) and logos
- SmartPing injection in WebHookController; the Knowlarity webhooks keep
working with the models now in kommuno/model
- Unused Toffee model reference in WarehouseController
- tofee.* keys, aramex.tracking.url and the PAYU PAY payment option in
main and test resources |
|
| 37733 |
3 h 34 m |
amit |
/trunk/profitmandi-web/src/main/ |
Remove dead third-party integrations: web
- PayU: /payu-pay and the payu-pay-response/cancelled handlers (bodies were
already commented out), PayuHandler, payment/ helpers, PayU POJOs, and the
PAYU PAY option served by checkout/payment-options.
PayuPayController stays: it holds the live CCAvenue, Razorpay and Pine Labs
callbacks.
- SmartPing: GET /click2call/{toMobile} (v1 + v2) and the caller-ID hook
/smartping/receipt + /v2/hookCallerID, which only logged
- HyperTrack: device location, partner location and geofence endpoints plus
HyperTrackService. The attendance endpoints (/getPunchHistory,
/employee/attendance) never called HyperTrack and are kept, moved to
EmployeeAttendanceController / V2EmployeeAttendanceController.
- Affiliate click-outs and live pricing (Amazon/Flipkart/Snapdeal via OMG):
ClicksController, LivePricingController and v2 wrappers. Live pricing was
already returning an empty list.
- Thriwe controller (fully commented out), SpiceMoney and FundFina v2 controllers
- Aramex branch of /track; tofee.* keys in dev/prod properties |
|
| 37732 |
3 h 35 m |
amit |
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/fofo/ |
purchase return: look up the open return against a document
selectOpenByDocumentReference returns the return still outstanding against a
document reference - neither refunded nor rejected - or null when none is.
Backs a duplicate guard on the invoice-return submit path: the same invoice was
being submitted twice, the closest pair eight seconds apart, and finance was
rejecting the extras by hand. A settled return deliberately does not count, since
rejecting a return is precisely what frees the invoice to be raised again.
Repository lands first so the method exists before the caller uses it. |
|
| 37731 |
3 h 35 m |
amit |
/trunk/profitmandi-dao/src/main/ |
Remove dead third-party integrations: dao
Nothing removed here had a live caller. No tables are touched.
- Toffee Insurance client + models, and the tofee.* keys in shared-*.properties
- Bharti Assist (BAG) service and its certificate/brand models. BagPlanModel
and PlanVariant stay in bharti/model: OneAssist and ICICI Lombard use them.
- Private, uncalled Toffee/BAG request builders in InsuranceServiceImpl
- Wiseapp insurance client and ZestResponseModel
- SmartPing client. CallDetailModel and PushCallLogModel move to
kommuno/model because the Knowlarity webhooks still parse them.
- SpiceMoney SSO (2-partner pilot), Thriwe stub + DTOs, DTDC/Shipsy (demo
URLs only), Blue Dart SOAP stubs, legacy Pine Labs v1 client
- FundFina pre-approval entity/repository, HyperTrack key entity/repository,
affiliate Click entity/repository
- Speqtra SMS constant; aramex.tracking.url keys
- PAYU PAY entry in payment-options.json
Gateway.MANDII and Gateway.FUNDFINA stay: historical fofo.payment rows. |
|
| 37730 |
3 h 35 m |
amit |
/trunk/profitmandi-common/src/main/java/com/spice/profitmandi/common/ |
Remove dead third-party integrations: common
Part of the integrations cleanup across all modules. Nothing here had a
live caller.
- Snapdeal product-page parser and UserMessagePojo (affiliate live pricing)
- FundFina request/response DTOs (inbound lender API, removed)
- Aramex XML tracking client (only reachable via /track provider=2)
- WiseApp insurance model
- URL constants for PayU, the SmartPing caller-ID hook, affiliate clicks and
live pricing; the SmartPing agent map |
|
| 37729 |
3 h 36 m |
amit |
/trunk/ |
lead: one workable lead per mobile, with a 6-month supersede and an L2+ override
There was no choke point for lead creation. Ten sites did `new Lead()` across four
modules -- three in web's LeadController, two in V2FofoLeadController, three in fofo's
LeadController, one in TrialServiceImpl and one in the cron LeadSyncRunner -- and only
ONE of them (fofo /createLead) checked for an existing lead at all. Result on live data:
5,137 mobiles carrying duplicate leads over 12,156 rows, worst case 29 on one number,
and two agents unknowingly working the same shop.
THE RULE, in new LeadCreationService, which all ten now route through:
no active lead on the number -> create
active, last activity >= 6 months -> retire the old one, create the new one, SILENTLY
active, last activity < 6 months -> BLOCK; only an L2+ user may override
Active = status in (pending, followUp) AND the assignee is still an active auth_user.
Last activity = GREATEST(lead.updated/created, MAX(lead_activity.created)).
The stale branch is deliberately quiet. A shop enquiring again after six months is a
handover, not a clash, and mailing on it would train the desk to ignore the alert -- so
only a genuine collision notifies. Live split: 195 stale against 1,241 fresh, and roughly
three blocks a month.
WHY "ACTIVE" ALSO MEANS A LIVE OWNER
331 open leads are assigned to 11 DEACTIVATED accounts (157 to sm@smartdukaan.com alone,
whose newest lead is from 2022). Counting them as active would block fresh enquiries
behind an account nobody can log in to and therefore nobody can close. Requiring a live
owner defuses all 331 without retiring a single row. Retirement here is only ever
REACTIVE -- triggered by a new entry on the same number. Nothing runs on a schedule.
ASSUMPTION worth flagging: a superseded lead becomes status=notInterested (stage DROPPED)
with closure_timestamp and reason 'Superseded after 6 months inactivity', rather than a
new `expired` status. "Closed" is an explicit allow-list in the UI --
Arrays.asList(notInterested, finalized) at V2FofoLeadController:150 and fofo
LeadController:313 -- and there are ~107 references to specific LeadStatus values, so a
new enum value would make these leads vanish from BOTH the open and closed screens.
Stage DROPPED keeps the nuance (the shop never said no) and still maps to notInterested
via LeadStage.toLegacyStatus().
OVERRIDE is L2+ in ANY team, not Call Center only: Sales L1 owns 1,063 of the 1,776 open
leads, so a Call-Center-only gate would funnel every team's collisions through three
people. The MAIL still goes to Call Center L2+, resolved from cs.position at send time
rather than hardcoded. An override is a TAKEOVER -- it closes the existing lead -- because
a second live lead is the exact thing the rule exists to prevent.
UNATTENDED CALLERS (cron sync, CSV upload, trial registration, AI intake) have nobody to
offer an override to, so they use createUnattended: skip the colliding row and mail the
desk rather than throwing. CSV reports imported/duplicateSkipped/duplicateMobiles back to
the operator instead of failing the whole file over one number.
ALSO FIXES selectByMobileNumber, which called getSingleResult and therefore threw
NonUniqueResultException on any mobile with more than one lead -- GlitchTip #99 and #1359,
both still firing. It now prefers the open lead, then the most recently touched.
NOT INCLUDED, deliberately: no DB unique constraint. 10 mobiles already carry more than
one open lead and would have to be resolved by hand first, which conflicts with the
no-auto-retirement rule. The service enforces the invariant going forward.
NEEDS A DBA STEP: user.lead.mobile is unindexed on 37,580 rows, so this check is a full
scan on every create. Index DDL is in the accompanying note; it has NOT been applied. |
|
| 37728 |
3 h 49 m |
amit |
/trunk/ |
logging: stop three non-defects reporting to the error board as ERROR
log4j2.xml ships ERROR and above to GlitchTip, so the log level IS the filter.
Three sources of ordinary, expected behaviour were logging at ERROR and between
them accounted for 51,244 events -- 43% of the whole board -- none of them a bug.
GlobalExceptionHandler already logs ProfitMandiBusinessException at WARN and is
unchanged; every leak below bypassed it.
1. Session state (27,302 events, 23% of the board). CookiesProcessor and the two
interceptors logged a missing or expired cookie at ERROR. A logged-out or
anonymous visitor is the normal case -- the code already handles it by
redirecting to /login or returning 403 -- and each of these sits in a class
whose surrounding lines already log at DEBUG. These never reach the handler,
which is why its WARN-level treatment never applied. Now DEBUG.
2. Client disconnect (19,349 events). There was no handler for it, so a client
hanging up mid-response fell through to @ExceptionHandler(Exception.class) and
was recorded as an unhandled server bug. Adds an IOException handler to both
GlobalExceptionHandlers that logs a disconnect at DEBUG and everything else at
ERROR with its 500 intact.
⚠ ClientAbortException CANNOT be imported here: catalina is provided by the
container and is not on either module's compileClasspath (verified against
the configuration, not assumed). The match is therefore on the simple class
name plus the "broken pipe"/"connection reset" messages, walked down the cause
chain. A genuine IOException matches none of those and keeps its ERROR.
The handler returns null for a disconnect rather than a body: the connection
that would carry it is already closed, and writing to it is what raised the
exception. Null is the supported way to say "handled, no body" --
HttpEntityMethodProcessor marks the request handled before reading the value.
3. Business exceptions re-logged at ERROR (11 sites). Each catches a
ProfitMandiBusinessException, logs it, and CONTINUES with a fallback -- a
missing wallet history defaults to an empty list, a user not found by primary
email is retried against the secondary. That is an expected outcome being
reported as a failure, and logging it at ERROR pre-empted the handler that
would have logged it at WARN. Now WARN.
Selenium/WebDriver (58,776 events) is deliberately untouched: that is a genuinely
broken ChromeDriver, and muting it would hide Oppo/Realme IMEI activation failing.
It looks like noise only because one broken thing repeated 52,000 times. |
|
| 37727 |
3 h 54 m |
amit |
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/transaction/ |
Fixed mail sender everywhere |
|
| 37726 |
1 d 23 h |
amit |
/trunk/ |
sentry: stop developer laptops reporting to the live GlitchTip board
GlitchTip #586 was 57 events tagged environment=production whose stack read
/opt/homebrew/Cellar/tomcat@8/8.5.100/libexec/... with server_name set to a
developer's machine. Nothing was wrong on prod: a laptop was posting into the
production project and was indistinguishable from it.
Two things combined to allow that. The DSN lives in log4j2.xml, which ships inside
every build, so any machine running this code can report. And the Sentry SDK
defaults `environment` to "production" when it is not set -- which it never was --
so local runs arrived pre-labelled as prod.
Adds sentry.properties to each module, read off the classpath by the SDK itself
(io.sentry.config.PropertiesProviderFactory) and merged over the appender's config.
Both keys used here are honoured by io.sentry.ExternalOptions in 7.22.6 (verified
against the jar): `enabled` and `environment`.
The COMMITTED values are the safe ones -- enabled=false, environment=dev -- so a
plain local build is silent. build.gradle rewrites both from -Penv= alongside the
env.property it already writes, so only a deliberate -Penv=staging|prod build
reports, and it carries the right environment tag. tasks.build.doLast restores the
safe default afterwards, mirroring the existing handling of env.property.
Verified both directions: default build leaves enabled=false/environment=dev,
-Penv=prod yields enabled=true/environment=prod.
Note this makes the board trustworthy rather than merely quieter: events can now be
filtered on environment, and anything unlabelled is a build that predates this. |
|
| 37725 |
2 d 20 h |
amit |
/trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ |
Fixed mail sender everywhere |
|
| 37724 |
2 d 21 h |
amit |
/trunk/profitmandi-dao/src/main/resources/sql/ |
chore(hot-deals): restore 5 catalogs to OEM brand, add POCO M7 Plus 5G (4GB 128GB)_s to Hot Deal
Applied on hadb1 2026-09-18. Removed 1025252/1025253 (Samsung A06) and
1026085/1026403/1026408 (Refurbished iPhones) via _hot_deal_brand_freeze;
added catalog 1026568 (item 40832) with freeze + scope rows. |
|
| 37723 |
2 d 22 h |
amit |
/trunk/profitmandi-fofo/src/ |
Bulk-uploaded movement rows are validated on screen; popup shows arriving stock per PO
Bulk upload only fills the PO screen - the PO is created from the screen. It used to price
with resolvePrices(qty), so one row over what could move rejected the whole file. It now prices
from describeAvailability (same cost layer order creation uses) and never refuses on quantity:
over-cap rows turn red on render, createPO blocks while any row is red and lists them, and
the server checks again on create. An item with no stock and nothing arriving still fails
the upload (nothing to price).
Popup reads in stock + arriving (per PO, <- supplier) - promised (per PO) = can move; the
'Of these, still to arrive' line is gone. Tests for the Oppo A6 UP->Noida case. jsVersion 433.
Needs dao r37722. |
|
| 37722 |
2 d 22 h |
amit |
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ |
Movement PO availability: list stock arriving into the sending warehouse, per PO
The popup showed in stock, promised and can-move, but not stock on its way in once it was
fully promised - so UP to Noida read 'in stock 0, promised 4, can move 0' with the 4 units
arriving on PO 54031 nowhere, and looked wrong. It now reads as a sum:
in stock + arriving - promised = can move.
- selectOpenInboundPurchases: open POs into the warehouse, one row per PO, same filter as the
pending-stock layer so the rows add up to the arriving total
- InternalMovementAvailabilityModel: arrivingTotal (before holds) + arriving breakup;
inbound (after holds) unchanged, still used by the refusal message
- describeAvailability (single + batch) carries both; batch doc: quantities are no longer
checked at bulk upload, the screen flags them and order creation enforces them |
|