bugs coverd
This commit is contained in:
parent
1340f44485
commit
81d4dd493f
@ -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.';
|
||||
|
||||
@ -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`,
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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'),
|
||||
|
||||
@ -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';
|
||||
|
||||
|
||||
@ -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'),
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user