bugs coverd

This commit is contained in:
Laxman 2026-05-15 20:20:15 +05:30
parent 1340f44485
commit 81d4dd493f
14 changed files with 44 additions and 30 deletions

View File

@ -273,7 +273,7 @@ export default function App() {
return 'Payment schedule, proofs, and audit notes for this onboarding application.';
}
if (pathname === '/finance-onboarding') {
return 'Validate security deposits, first fills, and related onboarding payments.';
return 'Validate Security Deposit, first fills, and related onboarding payments.';
}
if (pathname.startsWith('/finance-audit/')) {
return 'Finance audit trail and checklist for this application.';

View File

@ -52,14 +52,14 @@ export function FinanceDashboard({ onNavigate, onViewPaymentDetails, onViewAudit
const apps = response.data || [];
// Derive Onboarding Payments from Application + SecurityDeposit (Standardized nomenclature)
// This ensures applications in "Payment Pending" / "Security Details" are visible
// This ensures applications in "Payment Pending" / "Security Deposit" are visible
// even if no payment record has been manually initialized.
const consolidatedPayments: any[] = [];
apps.forEach((app: any) => {
const s = app.overallStatus || app.status;
const isPaymentStage = [
'Payment Pending', 'Security Details', 'LOI In Progress', 'LOI Issued',
'Payment Pending', 'Security Deposit', 'Security Details', 'LOI In Progress', 'LOI Issued',
'LOA Pending', 'Dealer Code Generation', 'LOA_APPROVAL'
].includes(s);
const deposits = app.securityDeposits || [];
@ -80,7 +80,7 @@ export function FinanceDashboard({ onNavigate, onViewPaymentDetails, onViewAudit
});
});
} else if (isPaymentStage) {
if (['Payment Pending', 'Security Details', 'LOI In Progress'].includes(s)) {
if (['Payment Pending', 'Security Deposit', 'Security Details', 'LOI In Progress'].includes(s)) {
// Virtual pending record for Security Deposit (5L)
consolidatedPayments.push({
id: `virtual-${app.id}-sd`,

View File

@ -73,7 +73,7 @@ export const SecurityDepositMaster: React.FC = () => {
Global Payment Settings
</CardTitle>
<CardDescription className="text-xs">
Configure base security deposit amounts for onboarding workflows.
Configure base Security Deposit amounts for onboarding workflows.
</CardDescription>
</div>
</div>

View File

@ -177,7 +177,7 @@ export function ApplicationDetailsSidebar(props: ApplicationDetailsSidebarProps)
<AlertTitle className="text-amber-900 font-semibold">LOA approval locked</AlertTitle>
<AlertDescription className="text-amber-800">
<span className="font-medium">First Fill</span> (later-stage payment) must be verified by Finance
before LOA approval can proceed. This is separate from the initial security deposit before LOI Issued.
before LOA approval can proceed. This is separate from the initial Security Deposit before LOI Issued.
</AlertDescription>
</Alert>
)}
@ -194,7 +194,7 @@ export function ApplicationDetailsSidebar(props: ApplicationDetailsSidebarProps)
Finance has verified the <span className="font-medium">First Fill</span> payment. The application
status was <span className="font-medium">not</span> changed until you reach{' '}
<span className="font-medium">LOA Pending</span>. When you get there, LOA approval will not be
blocked by payment (same pattern as recording the initial security deposit before the LOI
blocked by payment (same pattern as recording the initial Security Deposit before the LOI
security step).
</AlertDescription>
</Alert>
@ -203,7 +203,7 @@ export function ApplicationDetailsSidebar(props: ApplicationDetailsSidebarProps)
{permissions.isSecurityDetailsLocked && (
<Alert variant="destructive" className="mb-4 bg-amber-50 border-amber-200 text-amber-800" data-testid="onboarding-details-security-locked-alert">
<Lock className="w-4 h-4 text-amber-600" />
<AlertTitle className="text-amber-900 font-semibold">Security Details approval locked</AlertTitle>
<AlertTitle className="text-amber-900 font-semibold">Security Deposit approval locked</AlertTitle>
<AlertDescription className="text-amber-800">
Finance must verify the <span className="font-medium">Security Deposit</span> before this stage can be approved.
You can still use <span className="font-medium">Reject</span> if needed.
@ -211,12 +211,12 @@ export function ApplicationDetailsSidebar(props: ApplicationDetailsSidebarProps)
</Alert>
)}
{['Security Details', 'Payment Pending'].includes(application.status) && (
{['Security Deposit', 'Security Details', 'Payment Pending'].includes(application.status) && (
<Alert className="mb-4 border-sky-200 bg-sky-50/90 text-sky-900" data-testid="onboarding-details-security-review-alert">
<Info className="h-4 w-4 text-sky-700" />
<AlertTitle className="text-sky-950 font-semibold">Security Details review</AlertTitle>
<AlertTitle className="text-sky-950 font-semibold">Security Deposit review</AlertTitle>
<AlertDescription className="text-sm text-sky-900/90 leading-relaxed">
Check the initial security deposit on the <span className="font-medium">Payments</span> tab (Finance
Check the initial Security Deposit on the <span className="font-medium">Payments</span> tab (Finance
may have already marked it verified). When satisfied, use <span className="font-medium">Approve</span>{' '}
to move to <span className="font-medium">LOI Issued</span>.
</AlertDescription>

View File

@ -415,7 +415,8 @@ export function useApplicationDetailsAdminActions(params: UseApplicationDetailsA
case 'Level 3 Interview Pending': newStatus = 'Level 3 Approved'; break;
case 'Level 3 Approved': newStatus = 'FDD Verification'; break;
case 'FDD Verification': newStatus = 'LOI In Progress'; break;
case 'LOI In Progress': newStatus = 'Security Details'; break;
case 'LOI In Progress': newStatus = 'Security Deposit'; break;
case 'Security Deposit':
case 'Security Details':
case 'Payment Pending': newStatus = 'LOI Issued'; break;
case 'LOI Issued': newStatus = 'Dealer Code Generation'; break;

View File

@ -84,7 +84,9 @@ export function useApplicationDetailsData({ applicationId }: UseApplicationDetai
level3InterviewDate: getStageDate('3rd Level Interview', 'Level 3 Approved'),
fddDate: getStageDate('FDD', 'FDD Verification'),
loiApprovalDate: getStageDate('LOI Approval', 'LOI In Progress'),
securityDetailsDate: getStageDate('Security Details', 'Security Details'),
securityDetailsDate:
getStageDate('Security Deposit', 'Security Deposit') ||
getStageDate('Security Details', 'Security Details'),
loiIssueDate: getStageDate('LOI Issue', 'LOI Issued'),
dealerCodeDate: getStageDate('Dealer Code Generation', 'Dealer Code Generation'),
architectureAssignedDate: getStageDate('Architecture Team Assigned', 'Architecture Team Assigned'),

View File

@ -188,7 +188,7 @@ export function useApplicationDetailsPermissions({
const isAdminRole = ['DD Admin', 'Super Admin', 'NBH', 'DD Lead', 'DD Head', 'Finance', 'Finance Admin', 'FDD', 'ZBH', 'RBM'].includes(currentUser.role);
const isAdministrativeStage = [
'Level 3 Approved', 'FDD Verification',
'LOI In Progress', 'Security Details', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack',
'LOI In Progress', 'Security Deposit', 'Security Details', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack',
'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion',
'Statutory GST', 'Statutory PAN', 'Statutory Nodal', 'Statutory Check',
'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental',
@ -198,7 +198,7 @@ export function useApplicationDetailsPermissions({
const isLoaLocked = application.status === 'LOA Pending' && getDeposit('FIRST_FILL')?.status !== 'Verified';
const isSecurityDetailsLocked =
['Security Details', 'Payment Pending'].includes(application.status) &&
['Security Deposit', 'Security Details', 'Payment Pending'].includes(application.status) &&
getDeposit('SECURITY_DEPOSIT')?.status !== 'Verified';
const isFinalState = application.status === 'Onboarded' || application.status === 'Rejected';

View File

@ -40,6 +40,14 @@ export function useApplicationDetailsStageData({
return (documents || []).some((d) => d.documentType === docType);
};
const getSecurityDepositStageStatus = (): ProcessStage['status'] => {
const rows = application.progressTracking || [];
const row =
rows.find((ps: any) => ps.stageName === 'Security Deposit') ||
rows.find((ps: any) => ps.stageName === 'Security Details');
return row?.status ? (row.status as ProcessStage['status']) : 'pending';
};
const getStageStatus = (stageName: string, fallbackStatus: ProcessStage['status'] = 'pending'): ProcessStage['status'] => {
const backendStage = (application.progressTracking || []).find((ps: any) => ps.stageName === stageName);
return backendStage?.status ? (backendStage.status as any) : fallbackStatus;
@ -113,8 +121,8 @@ export function useApplicationDetailsStageData({
documentsUploaded: 1
},
{
id: 9, name: 'Security Details', status: getStageStatus('Security Details'),
date: application.securityDetailsDate, description: 'Security verification', documentsUploaded: 3
id: 9, name: 'Security Deposit', status: getSecurityDepositStageStatus(),
date: application.securityDetailsDate, description: 'Security Deposit verification', documentsUploaded: 3
},
{
id: 10, name: 'LOI Issue', status: getStageStatus('LOI Issue'),

View File

@ -242,6 +242,10 @@ export function AllApplicationsPage({ onViewDetails, initialFilter = 'all' }: Al
'Disqualified': 'bg-gray-100 text-gray-800',
'Onboarded': 'bg-emerald-100 text-emerald-800',
'LOI Approved': 'bg-sky-100 text-sky-800',
'Security Deposit In Progress': 'bg-amber-100 text-amber-800',
'Security Deposit Approved': 'bg-green-100 text-green-800',
'Security Deposit': 'bg-amber-100 text-amber-800',
/** Legacy overallStatus until DB migrated */
'Security Details In Progress': 'bg-amber-100 text-amber-800',
'Security Details Approved': 'bg-green-100 text-green-800',
'Security Details': 'bg-amber-100 text-amber-800',

View File

@ -273,14 +273,6 @@ export function ApplicationsPage({ onViewDetails, initialFilter }: ApplicationsP
<Label htmlFor="my-assignments" data-testid="onboarding-applications-assignments-label">My Assignments Only</Label>
</div>
<Select value={sortBy} onValueChange={(v) => setSortBy(v as any)}>
<SelectTrigger className="w-full lg:w-40" data-testid="onboarding-applications-sort-select">
<SelectValue placeholder="Sort By" />
</SelectTrigger>
<SelectContent>
<SelectItem value="date">Date</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex flex-wrap items-center gap-3 mt-4">

View File

@ -55,7 +55,7 @@ export function FinanceOnboardingPage({ onViewPaymentDetails }: FinanceOnboardin
const paymentRows = applications.flatMap((app: any) => {
const s = app.overallStatus || app.status;
const isPaymentStage = [
'Payment Pending', 'Security Details', 'LOI In Progress', 'LOI Issued',
'Payment Pending', 'Security Deposit', 'Security Details', 'LOI In Progress', 'LOI Issued',
'LOA Pending', 'Dealer Code Generation', 'LOA_APPROVAL'
].includes(s);
const deposits = app.securityDeposits || [];
@ -77,7 +77,7 @@ export function FinanceOnboardingPage({ onViewPaymentDetails }: FinanceOnboardin
// Keep virtual pending rows for in-flight cases with no deposit record yet
if (isPaymentStage) {
if (['Payment Pending', 'Security Details', 'LOI In Progress'].includes(s)) {
if (['Payment Pending', 'Security Deposit', 'Security Details', 'LOI In Progress'].includes(s)) {
return [{
id: `virtual-${app.id}-sd`,
applicationId: app.applicationId || app.id,
@ -134,7 +134,7 @@ export function FinanceOnboardingPage({ onViewPaymentDetails }: FinanceOnboardin
<div className="flex items-center justify-between bg-white p-6 rounded-2xl border border-slate-100 shadow-sm">
<div>
<h1 className="text-3xl font-bold text-slate-900 tracking-tight mb-1">Payment Verification</h1>
<p className="text-slate-500">Review and verify dealer security deposits and first fill payments</p>
<p className="text-slate-500">Review and verify Security Deposit and First Fill payments for dealers</p>
</div>
<div className="flex items-center gap-3">
<Button onClick={fetchApplications} variant="outline" size="sm" className="bg-white hover:bg-slate-50" data-testid="onboarding-finance-queue-sync-btn">

View File

@ -378,6 +378,9 @@ export function OpportunityRequestsPage({ onViewDetails }: OpportunityRequestsPa
'Level 3 Approved': 'bg-green-100 text-green-800',
'LOI In Progress': 'bg-sky-50 text-sky-700',
'LOI Approved': 'bg-green-100 text-green-800',
'Security Deposit In Progress': 'bg-blue-50 text-blue-700',
'Security Deposit Approved': 'bg-green-100 text-green-800',
'Security Deposit': 'bg-blue-100 text-blue-800',
'Security Details In Progress': 'bg-blue-50 text-blue-700',
'Security Details Approved': 'bg-green-100 text-green-800',
'Security Details': 'bg-blue-100 text-blue-800',

View File

@ -46,6 +46,10 @@ export type ApplicationStatus =
| 'Payment Pending'
| 'LOI In Progress'
| 'LOI Approved'
| 'Security Deposit In Progress'
| 'Security Deposit Approved'
| 'Security Deposit'
/** Legacy overallStatus from API / DB before rename */
| 'Security Details In Progress'
| 'Security Details Approved'
| 'Security Details'

View File

@ -132,12 +132,12 @@ export const onboardingService = {
},
getSecurityDeposit: async (applicationId: string) => {
const response: any = await API.getSecurityDeposit(applicationId);
if (!response.ok) throw new Error(response.data?.message || 'Failed to fetch security deposit');
if (!response.ok) throw new Error(response.data?.message || 'Failed to fetch Security Deposit');
return response.data?.data || response.data;
},
updateSecurityDeposit: async (data: any) => {
const response: any = await API.updateSecurityDeposit(data);
if (!response.ok) throw new Error(response.data?.message || 'Failed to update security deposit');
if (!response.ok) throw new Error(response.data?.message || 'Failed to update Security Deposit');
return response.data;
},
getSystemConfigs: async (params?: any) => {