multi iteration flow added and the external dealer api aded
This commit is contained in:
parent
5be1e319b0
commit
7488ae3bee
@ -1 +1 @@
|
||||
import{a as s}from"./index-BCZm9H2Q.js";import"./radix-vendor-CYvDqP9X.js";import"./charts-vendor-BVfwAPj-.js";import"./utils-vendor-BTBPSQfW.js";import"./ui-vendor-CX5oLBI_.js";import"./socket-vendor-TjCxX7sJ.js";import"./redux-vendor-tbZCm13o.js";import"./router-vendor-B_rK4TXr.js";async function m(n){return(await s.post(`/conclusions/${n}/generate`)).data.data}async function f(n,t){return(await s.post(`/conclusions/${n}/finalize`,{finalRemark:t})).data.data}async function d(n){var t;try{return(await s.get(`/conclusions/${n}`)).data.data}catch(o){if(((t=o.response)==null?void 0:t.status)===404)return null;throw o}}export{f as finalizeConclusion,m as generateConclusion,d as getConclusion};
|
||||
import{a as s}from"./index-yOqi1S1C.js";import"./radix-vendor-CYvDqP9X.js";import"./charts-vendor-BVfwAPj-.js";import"./utils-vendor-BTBPSQfW.js";import"./ui-vendor-CX5oLBI_.js";import"./socket-vendor-TjCxX7sJ.js";import"./redux-vendor-tbZCm13o.js";import"./router-vendor-B_rK4TXr.js";async function m(n){return(await s.post(`/conclusions/${n}/generate`)).data.data}async function f(n,t){return(await s.post(`/conclusions/${n}/finalize`,{finalRemark:t})).data.data}async function d(n){var t;try{return(await s.get(`/conclusions/${n}`)).data.data}catch(o){if(((t=o.response)==null?void 0:t.status)===404)return null;throw o}}export{f as finalizeConclusion,m as generateConclusion,d as getConclusion};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
build/assets/index-XBJXaMj2.css
Normal file
1
build/assets/index-XBJXaMj2.css
Normal file
File diff suppressed because one or more lines are too long
64
build/assets/index-yOqi1S1C.js
Normal file
64
build/assets/index-yOqi1S1C.js
Normal file
File diff suppressed because one or more lines are too long
@ -13,7 +13,7 @@
|
||||
<!-- Preload essential fonts and icons -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<script type="module" crossorigin src="/assets/index-BCZm9H2Q.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-yOqi1S1C.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/charts-vendor-BVfwAPj-.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/radix-vendor-CYvDqP9X.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/utils-vendor-BTBPSQfW.js">
|
||||
@ -21,7 +21,7 @@
|
||||
<link rel="modulepreload" crossorigin href="/assets/socket-vendor-TjCxX7sJ.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/redux-vendor-tbZCm13o.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/router-vendor-B_rK4TXr.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DjE6S9VF.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-XBJXaMj2.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@ -1183,10 +1183,18 @@ export class DealerClaimService {
|
||||
hsnCode: item.hsnCode || '',
|
||||
gstRate: Number(item.gstRate) || 0,
|
||||
gstAmt: Number(item.gstAmt) || 0,
|
||||
cgstRate: Number(item.cgstRate) || 0,
|
||||
cgstAmt: Number(item.cgstAmt) || 0,
|
||||
sgstRate: Number(item.sgstRate) || 0,
|
||||
sgstAmt: Number(item.sgstAmt) || 0,
|
||||
igstRate: Number(item.igstRate) || 0,
|
||||
igstAmt: Number(item.igstAmt) || 0,
|
||||
totalAmt: Number(item.totalAmt) || 0
|
||||
utgstRate: Number(item.utgstRate) || 0,
|
||||
utgstAmt: Number(item.utgstAmt) || 0,
|
||||
cessRate: Number(item.cessRate) || 0,
|
||||
cessAmt: Number(item.cessAmt) || 0,
|
||||
totalAmt: Number(item.totalAmt) || 0,
|
||||
isService: !!item.isService
|
||||
}));
|
||||
}
|
||||
// Note: costBreakup JSONB field has been removed - only using separate table now
|
||||
@ -1268,6 +1276,7 @@ export class DealerClaimService {
|
||||
proposalDetails: transformedProposalDetails,
|
||||
completionDetails: serializedCompletionDetails,
|
||||
internalOrder: serializedInternalOrder,
|
||||
internalOrders: serializedInternalOrders, // Return full list for UI
|
||||
// New normalized tables
|
||||
budgetTracking: serializedBudgetTracking,
|
||||
invoice: serializedInvoice,
|
||||
@ -1766,11 +1775,35 @@ export class DealerClaimService {
|
||||
// If blocking amount is 0 but ioNumber is provided, just save the IO details without blocking
|
||||
if (blockedAmount <= 0) {
|
||||
// Allow saving IO details (ioNumber only) even without blocking amount
|
||||
// This is useful when Requestor Evaluation is in progress but amount hasn't been blocked yet
|
||||
// This is useful when Step 3/Requestor Evaluation is in progress but amount hasn't been blocked yet or for linking IO
|
||||
if (ioData.ioNumber) {
|
||||
const organizedBy = organizedByUserId || null;
|
||||
|
||||
// Always create a new Internal Order record for each block/provision (supporting multiple IOs)
|
||||
// Check if an IO record already exists for this request and IO number
|
||||
// This prevents duplicate 0-amount "provisioned" records when re-saving IO details
|
||||
const existingIO = await InternalOrder.findOne({
|
||||
where: {
|
||||
requestId,
|
||||
ioNumber: ioData.ioNumber
|
||||
}
|
||||
});
|
||||
|
||||
if (existingIO) {
|
||||
// Update existing record with latest remark and organizer info if provided
|
||||
await existingIO.update({
|
||||
ioRemark: ioData.ioRemark || existingIO.ioRemark || '',
|
||||
organizedBy: organizedBy || existingIO.organizedBy || undefined,
|
||||
organizedAt: new Date(),
|
||||
});
|
||||
|
||||
logger.info(`[DealerClaimService] Existing IO record updated for request: ${requestId}`, {
|
||||
ioNumber: ioData.ioNumber,
|
||||
status: existingIO.status
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new Internal Order record if none exists for this IO and request
|
||||
await InternalOrder.create({
|
||||
requestId,
|
||||
ioNumber: ioData.ioNumber,
|
||||
@ -1915,15 +1948,6 @@ export class DealerClaimService {
|
||||
}
|
||||
}
|
||||
|
||||
// Update budget tracking with blocked amount FIRST
|
||||
await ClaimBudgetTracking.upsert({
|
||||
requestId,
|
||||
ioBlockedAmount: finalBlockedAmount,
|
||||
ioBlockedAt: new Date(),
|
||||
budgetStatus: BudgetStatus.BLOCKED,
|
||||
currency: 'INR',
|
||||
});
|
||||
|
||||
// Save IO history AFTER budget tracking update succeeds (only if ioLevel exists)
|
||||
if (ioLevel && ioHistoryUserId) {
|
||||
try {
|
||||
@ -2576,6 +2600,22 @@ export class DealerClaimService {
|
||||
costItems: costItems.map(i => ({
|
||||
description: i.itemDescription,
|
||||
amount: Number(i.amount || 0),
|
||||
quantity: Number(i.quantity || 1),
|
||||
hsnCode: i.hsnCode || '',
|
||||
gstRate: Number(i.gstRate || 0),
|
||||
gstAmt: Number(i.gstAmt || 0),
|
||||
cgstRate: Number(i.cgstRate || 0),
|
||||
cgstAmt: Number(i.cgstAmt || 0),
|
||||
sgstRate: Number(i.sgstRate || 0),
|
||||
sgstAmt: Number(i.sgstAmt || 0),
|
||||
igstRate: Number(i.igstRate || 0),
|
||||
igstAmt: Number(i.igstAmt || 0),
|
||||
utgstRate: Number(i.utgstRate || 0),
|
||||
utgstAmt: Number(i.utgstAmt || 0),
|
||||
cessRate: Number(i.cessRate || 0),
|
||||
cessAmt: Number(i.cessAmt || 0),
|
||||
totalAmt: Number(i.totalAmt || 0),
|
||||
isService: !!i.isService,
|
||||
order: i.itemOrder
|
||||
})),
|
||||
otherDocuments: supportingDocs.map(doc => ({
|
||||
|
||||
@ -284,84 +284,84 @@ export class DealerClaimApprovalService {
|
||||
// Fallback: proceed to Step 4 normally if history check fails
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.info(`[DealerClaimApproval] No next level found after level ${currentLevelNumber} - this may be the final approval`);
|
||||
}
|
||||
|
||||
if (nextLevel) {
|
||||
// Check if next level is paused - if so, don't activate it
|
||||
if ((nextLevel as any).isPaused || (nextLevel as any).status === 'PAUSED') {
|
||||
logger.warn(`[DealerClaimApproval] Cannot activate next level ${nextLevelNumber} - level is paused`);
|
||||
throw new Error('Cannot activate next level - the next approval level is currently paused. Please resume it first.');
|
||||
}
|
||||
// Important: Update nextLevelNumber in case nextLevel was shifted (e.g. Step 4 skip)
|
||||
// This ensures WorkflowRequest.currentLevel is updated to the correct active level
|
||||
const finalNextLevelNumber = nextLevel ? (nextLevel.levelNumber || 0) : null;
|
||||
|
||||
// Activate next level
|
||||
await nextLevel.update({
|
||||
status: ApprovalStatus.IN_PROGRESS,
|
||||
levelStartTime: now,
|
||||
tatStartTime: now
|
||||
});
|
||||
|
||||
// Schedule TAT jobs for the next level
|
||||
try {
|
||||
const workflowPriority = (wf as any)?.priority || 'STANDARD';
|
||||
|
||||
await tatSchedulerService.scheduleTatJobs(
|
||||
level.requestId,
|
||||
(nextLevel as any).levelId,
|
||||
(nextLevel as any).approverId,
|
||||
Number((nextLevel as any).tatHours),
|
||||
now,
|
||||
workflowPriority
|
||||
);
|
||||
logger.info(`[DealerClaimApproval] TAT jobs scheduled for next level ${nextLevelNumber} (Priority: ${workflowPriority})`);
|
||||
} catch (tatError) {
|
||||
logger.error(`[DealerClaimApproval] Failed to schedule TAT jobs for next level:`, tatError);
|
||||
// Don't fail the approval if TAT scheduling fails
|
||||
}
|
||||
|
||||
// Update workflow current level
|
||||
if (nextLevelNumber !== null) {
|
||||
await WorkflowRequest.update(
|
||||
{ currentLevel: nextLevelNumber },
|
||||
{ where: { requestId: level.requestId } }
|
||||
);
|
||||
|
||||
// Update the APPROVE snapshot's changeReason to include movement information
|
||||
// This ensures the approval snapshot shows both the approval and the movement
|
||||
// We don't create a separate WORKFLOW snapshot for approvals - only APPROVE snapshot
|
||||
try {
|
||||
const { DealerClaimHistory } = await import('@models/DealerClaimHistory');
|
||||
const { SnapshotType } = await import('@models/DealerClaimHistory');
|
||||
|
||||
const approvalHistory = await DealerClaimHistory.findOne({
|
||||
where: {
|
||||
requestId: level.requestId,
|
||||
approvalLevelId: level.levelId,
|
||||
snapshotType: SnapshotType.APPROVE
|
||||
},
|
||||
order: [['createdAt', 'DESC']]
|
||||
});
|
||||
|
||||
if (approvalHistory) {
|
||||
// Use the robust approvalComment from outer scope
|
||||
const updatedChangeReason = approvalComment
|
||||
? `Approved by ${level.approverName || level.approverEmail}, moved to next level (${nextLevelNumber}). Comment: ${approvalComment}`
|
||||
: `Approved by ${level.approverName || level.approverEmail}, moved to next level (${nextLevelNumber})`;
|
||||
|
||||
await approvalHistory.update({
|
||||
changeReason: updatedChangeReason
|
||||
});
|
||||
}
|
||||
} catch (updateError) {
|
||||
// Log error but don't fail - this is just updating the changeReason for better display
|
||||
logger.warn(`[DealerClaimApproval] Failed to update approval history changeReason (non-critical):`, updateError);
|
||||
if (nextLevel) {
|
||||
// Check if next level is paused - if so, don't activate it
|
||||
if ((nextLevel as any).isPaused || (nextLevel as any).status === 'PAUSED') {
|
||||
logger.warn(`[DealerClaimApproval] Cannot activate next level ${finalNextLevelNumber} - level is paused`);
|
||||
throw new Error('Cannot activate next level - the next approval level is currently paused. Please resume it first.');
|
||||
}
|
||||
|
||||
logger.info(`[DealerClaimApproval] Approved level ${level.levelNumber}. Activated next level ${nextLevelNumber} for workflow ${level.requestId}`);
|
||||
}
|
||||
// Activate next level
|
||||
await nextLevel.update({
|
||||
status: ApprovalStatus.IN_PROGRESS,
|
||||
levelStartTime: now,
|
||||
tatStartTime: now
|
||||
});
|
||||
|
||||
// Handle dealer claim-specific step processing
|
||||
// Schedule TAT jobs for the next level
|
||||
try {
|
||||
const workflowPriority = (wf as any)?.priority || 'STANDARD';
|
||||
|
||||
await tatSchedulerService.scheduleTatJobs(
|
||||
level.requestId,
|
||||
(nextLevel as any).levelId,
|
||||
(nextLevel as any).approverId,
|
||||
Number((nextLevel as any).tatHours),
|
||||
now,
|
||||
workflowPriority
|
||||
);
|
||||
logger.info(`[DealerClaimApproval] TAT jobs scheduled for next level ${finalNextLevelNumber} (Priority: ${workflowPriority})`);
|
||||
} catch (tatError) {
|
||||
logger.error(`[DealerClaimApproval] Failed to schedule TAT jobs for next level:`, tatError);
|
||||
// Don't fail the approval if TAT scheduling fails
|
||||
}
|
||||
|
||||
// Update workflow current level
|
||||
if (finalNextLevelNumber !== null) {
|
||||
await WorkflowRequest.update(
|
||||
{ currentLevel: finalNextLevelNumber },
|
||||
{ where: { requestId: level.requestId } }
|
||||
);
|
||||
|
||||
// Update the APPROVE snapshot's changeReason to include movement information
|
||||
// This ensures the approval snapshot shows both the approval and the movement
|
||||
// We don't create a separate WORKFLOW snapshot for approvals - only APPROVE snapshot
|
||||
try {
|
||||
const { DealerClaimHistory } = await import('@models/DealerClaimHistory');
|
||||
const { SnapshotType } = await import('@models/DealerClaimHistory');
|
||||
|
||||
const approvalHistory = await DealerClaimHistory.findOne({
|
||||
where: {
|
||||
requestId: level.requestId,
|
||||
approvalLevelId: level.levelId,
|
||||
snapshotType: SnapshotType.APPROVE
|
||||
},
|
||||
order: [['createdAt', 'DESC']]
|
||||
});
|
||||
|
||||
if (approvalHistory) {
|
||||
// Use the robust approvalComment from outer scope
|
||||
const updatedChangeReason = approvalComment
|
||||
? `Approved by ${level.approverName || level.approverEmail}, moved to next level (${finalNextLevelNumber}). Comment: ${approvalComment}`
|
||||
: `Approved by ${level.approverName || level.approverEmail}, moved to next level (${finalNextLevelNumber})`;
|
||||
|
||||
await approvalHistory.update({
|
||||
changeReason: updatedChangeReason
|
||||
});
|
||||
}
|
||||
} catch (updateError) {
|
||||
// Log error but don't fail - this is just updating the changeReason for better display
|
||||
logger.warn(`[DealerClaimApproval] Failed to update approval history changeReason (non-critical):`, updateError);
|
||||
}
|
||||
|
||||
logger.info(`[DealerClaimApproval] Approved level ${level.levelNumber}. Activated next level ${finalNextLevelNumber} for workflow ${level.requestId}`);
|
||||
}
|
||||
} // Handle dealer claim-specific step processing
|
||||
const currentLevelName = (level.levelName || '').toLowerCase();
|
||||
// Check by levelName first, use levelNumber only as fallback if levelName is missing
|
||||
// This handles cases where additional approvers shift step numbers
|
||||
|
||||
@ -114,12 +114,10 @@ export class PWCIntegrationService {
|
||||
// Extract State Code from Dealer GSTIN
|
||||
let dealerGst = dealer?.gstin;
|
||||
|
||||
const uatGst = '24AAAPI3182M002';
|
||||
const isDevOrUat = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'uat';
|
||||
|
||||
if (isDevOrUat) {
|
||||
logger.info(`[PWC] Using Dev/UAT authorized GSTIN replacement: ${uatGst} (Original: ${dealerGst || 'empty'})`);
|
||||
dealerGst = uatGst;
|
||||
logger.info(`[PWC] Running in ${process.env.NODE_ENV} mode. Original Dealer GST: ${dealerGst || 'empty'}`);
|
||||
}
|
||||
|
||||
logger.info(`[PWC] Final GSTIN being used for authentication and seller: ${dealerGst}`);
|
||||
@ -434,7 +432,7 @@ export class PWCIntegrationService {
|
||||
TrdNm: dealer?.dealerName || 'Dealer',
|
||||
Addr1: dealer?.city || "Address Line 1",
|
||||
Loc: dealer?.city || "Location",
|
||||
Pin: Number(dealer?.pincode || (dealerGst === uatGst ? 380001 : 600001)),
|
||||
Pin: Number(dealer?.pincode || 600001),
|
||||
Stcd: dealerStateCode,
|
||||
Ph: dealer?.phone || "9998887776",
|
||||
Em: dealer?.email || "Supplier@inv.com"
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user