Subversion Repositories SmartDukaan

Rev

Show changed files | Directory listing | RSS feed

Filtering Options

Rev Age Author Path Log message Diff
37469 46 m ranu /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/ rbm drr dashboard , all today po rbm view maped  
37468 1 h 12 m ranu /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/ rbm drr dashboard new ui looks  
37467 2 h 55 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/itelImeiActivation/ Fix Itel/Tecno activation pull: live session tokens, correct credentials, per-account isolation

The imwav pull has never worked since it replaced the SAP feed. Three defects:

- Login response was discarded and the listing call sent p-auth/utoken values
captured by hand in Jul-2023, so every request went out with an expired session.
Now takes utoken/urToken from the login response.
- Itel (IN404338I) carried a stale password (Dukaan@1234), which is why its pull
started failing Feb-2026. Corrected, and the two missing Tecno branch accounts
(Noida IN411226T, Lucknow IN404339T) added - the code previously knew only
IN404338T, which has no enterprise scope and returns nothing.
- Existing rows were looked up by the activation date string instead of the IMEI.
serial_number is the primary key, so the lookup always missed and re-persisted a
row that already existed, colliding on duplicate key on any re-pull.

Also pulls each account independently so one dead login cannot abort the remaining
accounts, and fails loudly when the portal rejects a login or the report call
instead of proceeding into a confusing downstream error.
 
37466 3 h 16 m amit /trunk/profitmandi-fofo/src/main/webapp/WEB-INF/views/ftl/ Show aged Apple stock on the partner Total Investment breakdown

Adds an 'Apple Stock More Than 30 Days' row below 'Unbilled Activated Stock'
so the reason a partner's suggested credit limit dropped is visible. Display
only -- the figure is not deducted from the other rows.

Value comes from partnerStat.tmp, so it reads 0 until the cron that rebuilds
that file has run against the new build.
 
37465 3 h 16 m amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Exclude aged Apple stock from investment when suggesting partner credit limits

Apple handsets a partner has held more than 30 days from GRN no longer count
toward the investment that drives the suggested limit. Applied in
getSuggestedAmount via getCreditableInvestment, covering the SDDIRECT,
hundred-percent and SIDBI branches. The aged amount is logged alongside each
limit change so a drop can be traced.

Scoped to the limit calculation only -- getTotalInvestment() is untouched, so
checkout payment options, the investment-OK gates and partner-facing screens
see the same stock value as before.

Measured on prod at time of commit: 580 units / ~3.94 Cr across 88 partners.
 
37464 3 h 16 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/ Track aged Apple stock on partner investment; add category filter to stock value lookup

selectPartnerStockValueMap now takes a nullable categoryId so the same query
serves both the existing Live Demo exclusion (null = all categories) and the
new Apple handset lookup (category 10006). Existing callers pass null and are
behaviourally unchanged.

PartnerDailyInvestment carries agedAppleStockAmount, populated in both the
single and batch investment paths. It is JPA-@Transient, so no schema change,
and it still travels through the partnerStat.tmp serialization the FOFO
investment screen reads. Deliberately not part of getTotalInvestment() -- the
deduction is a credit-limit policy, so stock value is unchanged for checkout,
the investment-OK gates and partner-facing screens.
 
37463 3 h 17 m amit /trunk/profitmandi-common/src/main/java/com/spice/profitmandi/common/model/ Add aged-stock constants for Apple credit-limit haircut

Apple handsets held by a partner beyond AGED_STOCK_APPLE_DAYS (30) days
from GRN are excluded from the investment used to suggest a credit limit.
 
37462 3 h 18 m amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/event/ Fire TagListing Solr update after commit instead of inside the write transaction

TagListingChangeListener used a plain @EventListener, so the async Solr rebuild
ran on a separate thread in a new transaction while the publishing controller
transaction was still open. FofoSolr.updateSingleCatalog then re-read
tag_listing on a connection that could not see the uncommitted rows and
re-indexed the pre-change price; for a catalog's first-ever listing it read
zero rows, took the isEmpty branch and deleted the doc from Solr.

Switched to @TransactionalEventListener(phase = AFTER_COMMIT). All publish
sites (TagListingController, PriceDropController, IndentController,
InventoryController, ModelHotDealServiceImpl) are inside a @Transactional
boundary, so no event is dropped.
 
37461 1 d 22 h ranu /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/model/ rbm drr dashboard new ui looks  
37460 1 d 22 h ranu /trunk/ rbm drr dashboard new ui looks  
37459 1 d 23 h amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Motorola IMEI activation: secondary + tertiary in one browser session

Mirrors the oppo/realme combined jobs. MotorolaImeiActivationService drives
CheckMotorolaWarrantyTask, with MotorolaChallengeSolver for the challenge.

Cadence comes from the pool query, which defers an imei for `days` after each
attempt (saveActivation bumps createTimestamp even when no date came back), so
days=2 retries everything every two days. Pending pool measured 1,534
(1,182 secondary + 352 tertiary); at ~10-14s/imei, 60 per invocation is about
12 minutes of driver time and clearing the pool inside 48h needs roughly 26
invocations, i.e. an OS cron entry every 90 minutes.

Do NOT schedule it inside the oppo/realme window: each driver tree costs
~850MB and this box has been OOM-killed twice with tomcat the victim, so peak
concurrent drivers is the number that matters.
 
37458 2 d 1 h aman /trunk/profitmandi-fofo/src/main/ LOI payment screenshot: report upload failures instead of reporting the field as missing

Submit validated the hidden #payment-sc-docId, but a file input keeps displaying the
chosen filename regardless of what happens next - so a failed /document-upload left the
field looking attached to the operator and missing to the validator ("The following
fields are required: Payment screenshot" on a form that was in fact filled in).

The failure was silent three ways: doAjaxUploadRequestHandler had no error handler; the
global ajaxError reporter calls bootbox, which loads from cdnjs and throws if that is
blocked; and the confirm('Confirm file upload ?') gate returned false with no trace once
Chrome's "prevent this page from creating additional dialogs" box was ticked.

- common.js: optional error callback on doAjaxUploadRequestHandler (additive, opts out of
the generic global dialog via suppressGlobalError); uploadErrorMessage() extracts the
server's real reason from the JSON body or the plain-text duplicate-request body;
uploadDocument() pre-checks size/type, verifies a document_id actually came back, and
reports a message naming the file - .HEIC and .webp get specific guidance;
showAlert() falls back to native alert when bootbox is absent.
- loi-form.js: drop the confirm() gate, 'input' -> 'change', and clear the file input
whenever the id does not land so the widget can never claim an unuploaded file. Status
line under the field (Uploading... / Attached: name / Not attached). Submit now
distinguishes not-picked, still-uploading and upload-failed. Same treatment for the
OnboardingDocumentTable and mk_brand-fee-collection-details uploads, and the brand-fee
dialog names the Attachment field instead of echoing the raw form key.
- loi-form.vm, pendingForm.vm: accept="..." on both file inputs plus the status span.
- FileUploadController: reject empty files, report actual size against the actual limit,
and resolveExtension() falls back to the filename when the browser sends a generic MIME
type (Android file managers send application/octet-stream for ordinary JPG/PNG/PDF).
- AppConfig: static resource version 395 -> 396 for the JS change.
 
37457 2 d 6 h amit /trunk/profitmandi-fofo/src/main/ Lock the KYC state to the GSTIN on the LOI

The LOI already captures and validates a GSTIN, and the first two characters of a
GSTIN are its GST state code - so once the LOI exists the KYC state is a fact
about that number, not something to re-type. When one is present the state
dropdown is prefilled from it and locked; otherwise it stays a normal
master-backed select.

Derived from the GSTIN rather than loi_form.gstState: that column is typed by
hand and holds values like 'UP', 'UTTAR PARDESH' and 'MADHAY PARDESH' which
resolve against nothing, and it is blank on 3 rows. Checked against prod - all
693 GSTINs on record are 15 characters and every one resolves through
statemaster.stateCode, and in all 14 rows where the two disagree the GSTIN is
right and the typed value is wrong or empty.

The lock is per row, not per page: the KYC screens list many onboardings, so the
derived state is passed as a map keyed by onboarding id. Blank rows carry their
onboarding id so a new KYC entry is locked too, which is the case that matters.

data-gst-locked keeps the row's dblclick edit toggle from re-enabling the field;
the value still submits because the JS reads it explicitly with .val().
 
37456 2 d 6 h amit /trunk/ Block billing when NIC rejects the transporter GSTIN for e-way bills

NIC files the e-way bill alongside the IRN, so a deregistered transporter
GSTIN returns Status=1 with InfoDtls[InfCd=EWBERR] (3029 "GSTIN - ... is
not active"): the IRN is valid while ewb_no stays null. Nothing downstream
reads that as a failure, so invoices kept being issued for goods that
could not legally move.

Cache the rejected transporter GSTIN in Redis and refuse to bill through
it. The block is keyed on the GSTIN, since one GSTIN is shared by several
warehouse_provider rows, and it carries the day it was raised so it lapses
at midnight and each new day re-tests NIC once. Correcting the GSTIN in
the provider panel lifts it immediately.

Only errors that are the transporter's fault block billing - NIC's 3029,
or any message naming the GSTIN we sent as TransId. Every other EWBERR
behaves as before: the IRN is filed and the e-way bill is retried later.

Guard sits in addBillingDetailsForGrouppedOrders before the pessimistic
lock and before any mutation, mirroring LogisticsServiceImpl#getEwbDetails
(order's own warehouse; self-pickup and runner skipped, as they travel on
a vehicle number rather than a transporter id).
 
37455 2 d 6 h amit /trunk/profitmandi-fofo/src/main/ Make the KYC state a master-backed dropdown instead of free text

fofo-kyc-row.vm and legal-kyc-row.vm captured state as a free-text input, so
nothing stopped a spelling the master does not hold. That state is resolved back
through inventory.statemaster by name later, and an unresolvable one cannot be
turned into a state code. Both now render a $stateNames select, and all five
render paths in PartnerOnBoardingPanelController supply the list.

panel-listing.js reads these fields positionally, by td index and
input[type='text']. A select does not match that selector, so the value would
have come back undefined and KYC would have saved a blank state silently -
both selectors now target the select. Row editing is unaffected: the enable
toggle uses :input, which covers select.

Bump the asset version for the panel-listing.js change.
 
37454 2 d 7 h amit /trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/config/ Build googleMailSender as AuthenticatedIdentityMailSender

The bean authenticates as sdtech@smartdukaan.com, so Google Workspace only permits
that address in From. Callers hardcode noreply@, which Gmail refuses with 535
'Authenticated user is not authorized to send mail', silently dropping every alert
sent through it. The sender now rewrites From to its own username at send time.

See profitmandi-common r37451.
 
37453 2 d 7 h amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/ Build googleMailSender as AuthenticatedIdentityMailSender

The bean authenticates as sdtech@smartdukaan.com, so Google Workspace only permits
that address in From. Callers hardcode noreply@, which Gmail refuses with 535
'Authenticated user is not authorized to send mail', silently dropping every alert
sent through it. The sender now rewrites From to its own username at send time.

See profitmandi-common r37451.
 
37452 2 d 7 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/service/integrations/gstpro/ Fix e-invoice IRN failure when the NIC auth token is about to expire

NIC reissues the same auth token until it genuinely expires, so evicting the cache
inside the 5 minute leeway hands back the identical near-dead token. getAuthenticatedHeaders
checked the leeway once, before that re-fetch, and never inspected what came back.
NSUPHR1770 filed with a token that had 12 seconds of life left and the gateway answered
412/GSP752 'eInvoice AuthToken not found or expired'; the invoice filed a minute later,
past the expiry and so on a genuinely new token, succeeded.

getUsableAuthToken re-checks the refetched token and, when it is still inside a 60s
floor, waits out the remainder before minting again. The wait is bounded by that floor
and every caller on this path is a cron/async thread already running against a 60s NIC
timeout with no transaction held open.

Also make the gateway's own failures legible. NIC rejections arrive as
{Status, ErrorDetails}, but failures the ASP raises in front of NIC use
{status_cd, error{error_cd, message}}, which shares no field name with RespPl: Gson
produced an all-null object and the stored reason degraded to the literal
'RespPl{Status=0, Data=null, ErrorDetails=null, InfoDtls=null}', indistinguishable from
NIC rejecting the document. RespGSPErr already modelled that envelope but was a
non-static inner class and so could not be instantiated by Gson; made it static and
copy the code and message into ErrorDetails, which every caller already reads.
 
37451 2 d 7 h amit /trunk/profitmandi-common/src/main/java/com/spice/profitmandi/common/services/ Send authenticated mail as the account that actually authenticates

googleMailSender logs in to smtp.gmail.com as sdtech@smartdukaan.com, but callers
build their From as noreply@smartdukaan.com. Google Workspace binds an authenticated
session to one identity and refuses the mismatch with 535 'Authorization failed:
Authenticated user is not authorized to send mail' - the password is accepted, the
message is not. Every alert routed through that sender was therefore lost at the SMTP
layer, the e-invoice failure alert for NSUPHR1770 among them.

AuthenticatedIdentityMailSender rewrites From to the sender's own username at send
time, keeping whatever display name the caller chose. Senders that do not authenticate
are left alone: gmailRelaySender is the IP-authorised relay and has no username, and
sendGridMailSender's username is the literal 'apikey', so both keep noreply@.

Enforced in the sender rather than at the ~40 call sites that build their own
MimeMessage and hardcode noreply@, so it covers the ones added next too.
 
37450 2 d 7 h amit /trunk/profitmandi-cron/src/main/java/com/smartdukaan/cron/scheduled/ Oppo: find only the hole, and let a low-contrast hole be found at all

60% of oppo attempts never got past detection -- getMatCircles2 returned null and
the attempt was wasted before any aiming happened. That is a bigger loss than
everything the scheduling work addressed put together.

Two causes, both visible once real puzzles are captured and looked at.

1. param1 is the Canny HIGH threshold, and it was 100. Edges weaker than that are
discarded before circle finding begins. Measured hole-vs-background contrast on
four live puzzles: 98, 103, 28, 117. The 28 -- a pale lilac background -- cannot
produce an edge at 100, so no circle exists to find. Dropped to 50.

2. It insisted on TWO circles whose radii matched within 3px, and returned null
otherwise. So a puzzle where the hole was located perfectly still failed if the
ring was missed, or if the two radii differed by 4px.

The second is the sillier one: the ring is a DOM element,
dx_captcha_basic_sub-slider_, whose exact position aim() already reads via
pieceCentreX(). Detection was re-finding something known exactly, and then
throwing away a good hole because it could not confirm it. Now the ring position
is passed in and hough only has to find one thing.

Lowering param1 without the pairing check would let textured backgrounds (the
sand images especially) supply spurious circles with nothing to reject them, so
the candidate is verified as an actual hole: its core must be at least 15
luminance below the frame mean. Real holes measure 28-117 below, so 15 rejects
noise with margin.

Validated against live puzzles before committing:
ring is at rel 42px on every sample; hole lands at 113-194px, separation
71-152px -- so RING_EXCLUSION_PX = 30 never rejects a real hole
hole contrast 28-117 against MIN_HOLE_DARKNESS = 15

Not validated locally: the hough call itself. opencv 3.4.2-0 ships no osx/arm64
native and every JDK on this machine is arm64, so the detection path cannot run
here. param1 = 50 is reasoned from the measured contrasts, not measured. If the
detection rate does not move, 40 is the next value to try -- the darkness check is
what makes going lower safe.

Watch "Detected N circle(s) but all sat on the ring" and "Rejecting circle at Npx"
in the log: the first means hough found nothing but the ring, the second means the
darkness check is doing its job.
 

Show All