Skip to content

Release 3.6.0#132

Closed
5Amogh wants to merge 18 commits intomainfrom
release-3.6.0
Closed

Release 3.6.0#132
5Amogh wants to merge 18 commits intomainfrom
release-3.6.0

Conversation

@5Amogh
Copy link
Copy Markdown
Member

@5Amogh 5Amogh commented Dec 3, 2025

Prodcution Pr for release-3.6.0 to main

Summary by CodeRabbit

  • New Features

    • Added item entry date to daily and monthly export headers.
    • Stronger privilege check at login with service-list handling and appropriate navigation.
  • Improvements

    • Standardized header formatting for inventory report exports for clearer column names.
    • Improved error handling to show clearer messages and force re-login on auth failures.
  • Bug Fixes

    • Adjusted cross-browser Excel download flow to better handle legacy/MS environments.
  • Chores

    • Bumped application version to 3.6.0.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 3, 2025

Walkthrough

Project version bumped to 3.6.0; multiple inventory report components refactored to (1) move Excel save logic into msSaveBlob branches and (2) convert header transformation from index-based to value-based with added itemEnteredDate in some exports. Login gains privilege/service validation; HTTP interceptor tightens auth error handling.

Changes

Cohort / File(s) Summary
Version Update
pom.xml
Updated project version from 3.4.0 to 3.6.0.
Report Components — Download Logic Restructuring
src/app/app-modules/inventory/reports/beneficiary-drug-issue-report/beneficiary-drug-issue-report.component.ts, src/app/app-modules/inventory/reports/consumption-report/consumption-report.component.ts, src/app/app-modules/inventory/reports/expiry-report/expiry-report.component.ts, src/app/app-modules/inventory/reports/inward-stock-report/inward-stock-report.component.ts, src/app/app-modules/inventory/reports/short-expiry-report/short-expiry-report.component.ts, src/app/app-modules/inventory/reports/transit-report/transit-report.component.ts
Moved unconditional saveAs(blob, wb_name + '.xlsx') into the navigator.msSaveBlob branch; non-IE paths continue to use link-based download.
Report Components — Header Transformation & itemEnteredDate
src/app/app-modules/inventory/reports/daily-stock-details-report/daily-stock-details-report.component.ts, src/app/app-modules/inventory/reports/daily-stock-summary-report/daily-stock-summary-report.component.ts, src/app/app-modules/inventory/reports/monthly-report/monthly-report.component.ts, src/app/app-modules/inventory/reports/yearly-report/yearly-report.component.ts
Replaced index-based modifyHeader(headers, i) with value-based modifyHeader(header: string): string; introduced prettyHeaders = headers.map(h => this.modifyHeader(h)) and use it when writing header rows. Added itemEnteredDate header in select exports. Also moved saveAs into msSaveBlob branch as above.
Login Component — Privilege & Service Validation
src/app/login/login.component.ts
Added guard requiring a 'Pharmacist' role (clears session and redirects to /login if absent). checkDesignationWithRole now computes/stores available services in session storage and navigates to /set-security-questions for new users or /service for existing users; alerts when no privileges present.
HTTP Interceptor — Error Handling
src/app/app-modules/core/services/http-interceptor.service.ts
Enhanced error handling: distinguishes 401/403 auth errors (shows session-expired alert), clears sessionStorage and localStorage, navigates to /login, shows spinner, and rethrows errors; non-auth errors show message or generic failure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to header refactor in the four report files to ensure header/value alignment and downstream export behavior.
  • Verify the moved saveAs calls do not cause double saves in IE/MS environments and check behavior across targeted browsers.
  • Review login.component.ts for session-storage key names, correct route/navigation, and alert behavior.
  • Confirm interceptor's storage clears and navigation integrate correctly with app routing and session lifecycle.

Poem

🐰 I hopped through rows and renamed each head,
Moved saves to corners where old browsers tread.
I checked the roles, kept privileges tight,
Cleared stale sessions in the midnight light.
Version three-six — a quiet, tidy sight.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Release 3.6.0' directly corresponds to the version bump from 3.4.0 to 3.6.0 in pom.xml, which is the primary structural change in this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch release-3.6.0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
src/app/app-modules/inventory/reports/beneficiary-drug-issue-report/beneficiary-drug-issue-report.component.ts (2)

250-262: Critical: Double download triggered in IE/Edge browsers.

Calling both saveAs(blob, wb_name + '.xlsx') on Line 251 and navigator.msSaveBlob(blob, wb_name) on Line 252 will trigger two separate download prompts in browsers that support msSaveBlob (older IE/Edge). The file-saver library's saveAs function already handles browser detection internally and will use msSaveBlob when available.

Additionally, Line 252 is missing the .xlsx file extension, which could cause issues if that code path executes.

Apply this diff to fix the issue:

       workbook.xlsx.writeBuffer().then((buffer) => {
         const blob = new Blob([buffer], {
           type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
         });
-        if (navigator.msSaveBlob) {
-          saveAs(blob, wb_name + '.xlsx');
-          navigator.msSaveBlob(blob, wb_name);
-        } else {
-          const link = document.createElement('a');
-          link.href = URL.createObjectURL(blob);
-          link.setAttribute('visibility', 'hidden');
-          link.download = wb_name.replace(/ /g, '_') + '.xlsx';
-          document.body.appendChild(link);
-          link.click();
-          document.body.removeChild(link);
-        }
+        saveAs(blob, wb_name.replace(/ /g, '_') + '.xlsx');
       });

Note: According to the AI summary, this same pattern exists in multiple report components (consumption-report, daily-stock-details-report, expiry-report, inward-stock-report, monthly-report, yearly-report, short-expiry-report, transit-report). Please ensure this fix is applied consistently across all affected files.


190-218: Header modification logic never applied to the worksheet.

The code computes modified header names using modifyHeader() on Line 211 but never applies them to the worksheet. Line 212 shows commented code that was likely intended to apply the headers, but it's disabled. As a result, the entire block (lines 190-218) is effectively dead code, and the raw unmodified headers from the head array are added to the worksheet on Line 225.

Either remove this dead code block or uncomment and fix Line 212 to properly apply the modified headers. If using ExcelJS (as imported on Line 24), you should modify the headers before adding them:

       const wb_name = 'Beneficiary Drug Issue Report';

-       // below code added to modify the headers
-
-       let i = 65; // starting from 65 since it is the ASCII code of 'A'.
-       let count = 0;
-       while (i < head.length + 65) {
-         let j;
-         if (count > 0) {
-           j = i - 26 * count;
-         } else {
-           j = i;
-         }
-         const cellPosition = String.fromCharCode(j);
-         let finalCellName: any;
-         if (count === 0) {
-           finalCellName = cellPosition + '1';
-           console.log(finalCellName);
-         } else {
-           const newcellPosition = String.fromCharCode(64 + count);
-           finalCellName = newcellPosition + cellPosition + '1';
-           console.log(finalCellName);
-         }
-         const newName = this.modifyHeader(head, i);
-         // delete report_worksheet[finalCellName].w; report_worksheet[finalCellName].v = newName;
-         i++;
-         if (i === 91 + count * 26) {
-           // i = 65;
-           count++;
-         }
-       }
-       // --------end--------
+       // Modify headers for better readability
+       const modifiedHeaders = head.map((_: any, index: number) => 
+         this.modifyHeader(head, index + 65)
+       );

       const workbook = new ExcelJS.Workbook();
       const criteria_worksheet = workbook.addWorksheet('Criteria');
       const report_worksheet = workbook.addWorksheet('Report');

-       report_worksheet.addRow(head);
+       report_worksheet.addRow(modifiedHeaders);
       criteria_worksheet.addRow(this.criteriaHead);
src/app/app-modules/inventory/reports/consumption-report/consumption-report.component.ts (1)

271-279: Remove redundant saveAs call to prevent double downloads on IE/Edge

Both saveAs(blob, wb_name + '.xlsx') and navigator.msSaveBlob(blob, wb_name) are called in the same if block. Since file-saver's saveAs internally delegates to navigator.msSaveBlob on IE/Edge, this creates a double-download issue on those browsers.

Use only navigator.msSaveBlob directly with the filename extension included for consistency:

           if (navigator.msSaveBlob) {
-            saveAs(blob, wb_name + '.xlsx');
             navigator.msSaveBlob(blob, wb_name + '.xlsx');
           } else {
src/app/login/login.component.ts (1)

292-337: Fix services array filtering to prevent null entries and runtime errors

The map() with conditional return creates null entries for items that don't match the serviceID filter. When stored in sessionStorage and retrieved in service.component.ts, the parsed array contains null values. Accessing properties like service.providerServiceID in selectService() will then throw "Cannot read property of null" errors.

The fix is to filter out invalid entries after safely checking the nested structure:

-      const services = loginDataResponse.previlegeObj.map((item: any) => {
-        if (
-          item.roles[0].serviceRoleScreenMappings[0].providerServiceMapping
-            .serviceID === 4 ||
-          item.roles[0].serviceRoleScreenMappings[0].providerServiceMapping
-            .serviceID === 2
-        ) {
-          return {
-            serviceID:
-              item.roles[0].serviceRoleScreenMappings[0].providerServiceMapping
-                .serviceID,
-            providerServiceID: item.serviceID,
-            serviceName: item.serviceName,
-            apimanClientKey: item.apimanClientKey,
-          };
-        }
-      });
-      if (services.length > 0) {
+      const services = (loginDataResponse.previlegeObj || [])
+        .map((item: any) => {
+          if (
+            !item.roles ||
+            !item.roles[0] ||
+            !item.roles[0].serviceRoleScreenMappings ||
+            !item.roles[0].serviceRoleScreenMappings[0] ||
+            !item.roles[0].serviceRoleScreenMappings[0].providerServiceMapping
+          ) {
+            return null;
+          }
+
+          const mapping =
+            item.roles[0].serviceRoleScreenMappings[0].providerServiceMapping;
+
+          if (mapping.serviceID === 4 || mapping.serviceID === 2) {
+            return {
+              serviceID: mapping.serviceID,
+              providerServiceID: item.serviceID,
+              serviceName: item.serviceName,
+              apimanClientKey: item.apimanClientKey,
+            };
+          }
+
+          return null;
+        })
+        .filter((service: any) => service !== null);
+
+      if (services.length > 0) {
         this.sessionstorage.setItem('services', JSON.stringify(services));

Also add 'error' severity to the alert for consistency with other error alerts in the codebase:

-        this.confirmationService.alert(
-          "User doesn't have previlege to access the application",
-        );
+        this.confirmationService.alert(
+          "User doesn't have previlege to access the application",
+          'error',
+        );
src/app/app-modules/inventory/reports/transit-report/transit-report.component.ts (1)

235-251: Redundant save mechanism in IE branch: calling both saveAs and navigator.msSaveBlob

In the writeBuffer callback, the IE path invokes both:

if (navigator.msSaveBlob) {
  saveAs(blob, wb_name + '.xlsx');
  navigator.msSaveBlob(blob, wb_name);
}

The saveAs function from file-saver already feature-detects and internally uses navigator.msSaveBlob when available, making the second call redundant. This pattern is duplicated across all 9 report components (transit-report, yearly-report, short-expiry-report, monthly-report, inward-stock-report, daily-stock-summary-report, daily-stock-details-report, expiry-report, consumption-report, beneficiary-drug-issue-report).

Additionally, there is an inconsistency in filename handling: the IE branch uses wb_name + '.xlsx' while the fallback branch uses wb_name.replace(/ /g, '_') + '.xlsx'.

Remove the navigator.msSaveBlob call from the IE branch and standardize filename handling across both branches.

♻️ Duplicate comments (8)
src/app/app-modules/inventory/reports/expiry-report/expiry-report.component.ts (1)

230-247: Excel export block mirrors TransitReportComponent behavior

This writeBuffer/download block is identical in structure to the one in TransitReportComponent: the IE path calls both saveAs and navigator.msSaveBlob, and non‑IE browsers rely only on the anchor.

Please apply whichever resolution you choose there (single call in IE branch, consistent use of file-saver vs anchor) here as well to keep behavior aligned.

src/app/app-modules/inventory/reports/inward-stock-report/inward-stock-report.component.ts (1)

267-283: Excel export block matches prior pattern in other reports

The navigator.msSaveBlob branch here also calls both saveAs and navigator.msSaveBlob, with non‑IE browsers using only the anchor fallback.

Please keep this in sync with the chosen pattern from TransitReportComponent to avoid inconsistent behavior (and potential double prompts) across reports.

src/app/app-modules/inventory/reports/short-expiry-report/short-expiry-report.component.ts (1)

207-223: Excel export: keep saveAs/msSaveBlob usage consistent with other reports

Same observation as in the other report components: IE branch calls both saveAs and navigator.msSaveBlob, while non‑IE browsers rely only on the anchor.

Once you settle on a single strategy for the IE path (and for whether to use file-saver vs the manual anchor in non‑IE), mirror that decision here for consistency.

src/app/app-modules/inventory/reports/yearly-report/yearly-report.component.ts (1)

236-247: Excel export block: same saveAs/msSaveBlob concern as other reports

This writeBuffer block uses the same pattern as TransitReportComponent (calling both saveAs and navigator.msSaveBlob in the IE path).

Please align this with the final decision taken there to avoid duplicate prompts in IE and to keep behavior consistent across reports.

src/app/app-modules/inventory/reports/daily-stock-summary-report/daily-stock-summary-report.component.ts (2)

188-200: Header transformation matches YearlyReportComponent; keep helper shared/consistent

The introduction of:

const prettyHeaders = headers.map((h) => this.modifyHeader(h));
report_worksheet.addRow(prettyHeaders);

plus the new modifyHeader(header: string) implementation mirrors the pattern in YearlyReportComponent and improves header readability in the export.

Same suggestions apply here: consider centralizing modifyHeader in a shared place, and handle the Sonar replace vs replaceAll warning consistently across all components based on your actual browser support policy.

Also applies to: 216-248, 300-305


271-287: Excel export: same saveAs/msSaveBlob behavior as other reports

The writeBuffer download logic is identical to the other report components, including the dual saveAs + navigator.msSaveBlob calls in the IE path.

Please keep this snippet in lockstep with whichever fix/refactor you adopt in one canonical place (e.g., Transit/Yearly report).

src/app/app-modules/inventory/reports/daily-stock-details-report/daily-stock-details-report.component.ts (1)

272-289: Excel export: same saveAs/msSaveBlob question as other reports

The writeBuffer block here matches the pattern already discussed in other components (dual saveAs + navigator.msSaveBlob in IE, anchor fallback elsewhere). Please align any fix/refactor you make there with this file as well.

src/app/app-modules/inventory/reports/monthly-report/monthly-report.component.ts (1)

267-283: Excel export: same saveAs/msSaveBlob pattern as other reports

The writeBuffer → download logic here is identical to the other report components. Please keep this in sync with your chosen resolution for the IE branch and file-saver vs anchor behavior.

🧹 Nitpick comments (7)
pom.xml (1)

58-58: Update stale build artifact name property.

The final-name property still references v3.0.0 while the project version has been bumped to 3.6.0. Consider updating this to reflect the current release version, or clarify if this property is intentionally decoupled from the project version.

Apply this diff if the artifact name should reflect the current version:

- <final-name>inventory-ui-v3.0.0</final-name>
+ <final-name>inventory-ui-${project.version}</final-name>

Alternatively, update it explicitly:

- <final-name>inventory-ui-v3.0.0</final-name>
+ <final-name>inventory-ui-v3.6.0</final-name>
src/app/app-modules/inventory/reports/beneficiary-drug-issue-report/beneficiary-drug-issue-report.component.ts (2)

283-283: Use slice() instead of deprecated substr().

The substr() method is deprecated. Use slice() or substring() instead.

Apply this diff:

-    modifiedHeader.charAt(0).toUpperCase() + modifiedHeader.substr(1);
+    modifiedHeader.charAt(0).toUpperCase() + modifiedHeader.slice(1);

88-88: Consider removing debug console.log statements for production.

Multiple console.log statements are present throughout the file (lines 88, 92, 117, 129, 137, 172, 187, 205, 209). These debug statements should typically be removed before a production release to avoid cluttering the console and potentially exposing sensitive data.

Also applies to: 92-92, 117-117, 129-137, 172-172, 187-187, 205-205, 209-209

src/app/login/login.component.ts (1)

221-240: Pharmacist-only guard: confirm business rule and align error message

The new hasPharmacist check is technically fine, but it hard-codes RoleName === 'Pharmacist' as the only allowed role. That will block any user whose role name differs even slightly (e.g., “Senior Pharmacist”, different casing, etc.) while still showing a generic “Designation is not matched with your roles” message, even though we never reach the designation check here.

If the intent is truly “only Pharmacist role can access this UI”, consider:

  • Either broadening the predicate (e.g., case-insensitive, supporting multiple allowed role names), or
  • Updating the alert text to clearly state that the user lacks the required Pharmacist role/privilege.

If other role names should still be allowed, this guard will be too restrictive.

src/app/app-modules/inventory/reports/yearly-report/yearly-report.component.ts (1)

152-215: Header prettification via prettyHeaders/modifyHeader looks good; consider dedup + Sonar context

Using:

const prettyHeaders = headers.map((h) => this.modifyHeader(h));
report_worksheet.addRow(prettyHeaders);

combined with:

modifyHeader(header: string): string {
  let modifiedHeader = header.replace(/([A-Z])/g, ' $1').trim();
  modifiedHeader =
    modifiedHeader.charAt(0).toUpperCase() + modifiedHeader.substr(1);
  return modifiedHeader.replace(/I D/g, 'ID');
}

is a clear improvement over per-cell mutation and produces sensible labels (e.g. unitCostPriceUnit Cost Price, facilityNameFacility Name).

Two follow‑ups to consider:

  • The same modifyHeader implementation now exists in several components (yearly, monthly, daily stock summary, daily stock details). Pulling this into a shared utility/service would avoid future drift.
  • Sonar’s “prefer replaceAll over replace” warning is tricky here: String.prototype.replaceAll is not available in IE, and this codebase still has IE‑specific handling via navigator.msSaveBlob. If IE support is still required, it’s safer to keep replace with a global regex; if IE is officially dropped, you can switch to replaceAll across all these helpers in one go.

Also applies to: 265-270

src/app/app-modules/inventory/reports/daily-stock-details-report/daily-stock-details-report.component.ts (1)

188-205: New itemEnteredDate column and header formatting

Adding 'itemEnteredDate' to the headers array and driving the header row via:

const prettyHeaders = headers.map((h) => this.modifyHeader(h));
report_worksheet.addRow(prettyHeaders);

is consistent with the other reports and will surface the entry timestamp cleanly as Item Entered Date.

A few points to verify/consider:

  • Ensure the objects in this.consumptionList always include an itemEnteredDate field; otherwise the new column will export as blank. If the field is optional, you may want to default it (e.g., to '' or a formatted date) when building the list.
  • The modifyHeader implementation is identical to the one in yearly/monthly/daily summary; consider centralizing it to avoid duplication and Sonar warnings being fixed in only one place.

Also applies to: 219-253, 302-307

src/app/app-modules/inventory/reports/monthly-report/monthly-report.component.ts (1)

181-199: Monthly export: added itemEnteredDate column and shared header helper

The monthly report now exports an itemEnteredDate column and formats headers via:

const prettyHeaders = headers.map((h) => this.modifyHeader(h));
report_worksheet.addRow(prettyHeaders);

with modifyHeader(header: string) matching the implementation used in the other refactored reports.

That all looks consistent; two small follow‑ups:

  • Confirm the backend monthly report payload actually includes itemEnteredDate for each row so this column is populated rather than empty.
  • As with the other components, consider extracting modifyHeader to a shared utility so any future tweaks (or a possible switch to replaceAll if IE support is dropped) are made in one place.

Also applies to: 215-248, 296-301

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3fe9abf and 63f32b0.

📒 Files selected for processing (12)
  • pom.xml (1 hunks)
  • src/app/app-modules/inventory/reports/beneficiary-drug-issue-report/beneficiary-drug-issue-report.component.ts (1 hunks)
  • src/app/app-modules/inventory/reports/consumption-report/consumption-report.component.ts (1 hunks)
  • src/app/app-modules/inventory/reports/daily-stock-details-report/daily-stock-details-report.component.ts (5 hunks)
  • src/app/app-modules/inventory/reports/daily-stock-summary-report/daily-stock-summary-report.component.ts (4 hunks)
  • src/app/app-modules/inventory/reports/expiry-report/expiry-report.component.ts (1 hunks)
  • src/app/app-modules/inventory/reports/inward-stock-report/inward-stock-report.component.ts (1 hunks)
  • src/app/app-modules/inventory/reports/monthly-report/monthly-report.component.ts (4 hunks)
  • src/app/app-modules/inventory/reports/short-expiry-report/short-expiry-report.component.ts (1 hunks)
  • src/app/app-modules/inventory/reports/transit-report/transit-report.component.ts (1 hunks)
  • src/app/app-modules/inventory/reports/yearly-report/yearly-report.component.ts (3 hunks)
  • src/app/login/login.component.ts (2 hunks)
🧰 Additional context used
🪛 GitHub Check: SonarCloud Code Analysis
src/app/app-modules/inventory/reports/monthly-report/monthly-report.component.ts

[warning] 297-297: Prefer String#replaceAll() over String#replace().

See more on https://sonarcloud.io/project/issues?id=PSMRI_Inventory-UI-NEXT&issues=AZri9l1vbqb12PUB2NHO&open=AZri9l1vbqb12PUB2NHO&pullRequest=132

src/app/app-modules/inventory/reports/daily-stock-summary-report/daily-stock-summary-report.component.ts

[warning] 301-301: Prefer String#replaceAll() over String#replace().

See more on https://sonarcloud.io/project/issues?id=PSMRI_Inventory-UI-NEXT&issues=AZri9l1Rbqb12PUB2NHN&open=AZri9l1Rbqb12PUB2NHN&pullRequest=132

src/app/app-modules/inventory/reports/daily-stock-details-report/daily-stock-details-report.component.ts

[warning] 303-303: Prefer String#replaceAll() over String#replace().

See more on https://sonarcloud.io/project/issues?id=PSMRI_Inventory-UI-NEXT&issues=AZri9l2Nbqb12PUB2NHP&open=AZri9l2Nbqb12PUB2NHP&pullRequest=132

src/app/app-modules/inventory/reports/yearly-report/yearly-report.component.ts

[warning] 266-266: Prefer String#replaceAll() over String#replace().

See more on https://sonarcloud.io/project/issues?id=PSMRI_Inventory-UI-NEXT&issues=AZri9l2fbqb12PUB2NHQ&open=AZri9l2fbqb12PUB2NHQ&pullRequest=132

🔇 Additional comments (2)
pom.xml (2)

8-8: Version bump to 3.6.0 is correct.

The production release version has been properly updated from 3.4.0 to 3.6.0 in the POM. Version syntax and format are correct.


1-185: Incomplete review context: Only pom.xml provided.

The AI summary indicates extensive changes across multiple components (beneficiary-drug-issue-report, consumption-report, daily-stock-details-report, daily-stock-summary-report, expiry-report, inward-stock-report, monthly-report, short-expiry-report, transit-report, yearly-report, and login.ts), but only pom.xml is provided for review.

For a production release PR, a complete review of all changed files is recommended to ensure:

  • Excel export logic refactoring is consistent across all report components
  • Header transformation changes are properly applied
  • Login privilege and service validation are correctly integrated
  • No regressions in export flows or access control

Please provide the remaining changed files for comprehensive review.

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
48.4% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 63f32b0 and adeb4b5.

📒 Files selected for processing (1)
  • src/app/app-modules/core/services/http-interceptor.service.ts (1 hunks)

Comment on lines +83 to +96
if (error.status === 401 || error.status === 403) {
this.confirmationService.alert(
'Session expired. Please log in again to continue',
'error',
);
} else
this.confirmationService.alert(
error.error.errorMessage ||
'Something went wrong. Please try again later.',
'error',
);
this.router.navigate(['/login']);
sessionStorage.clear();
localStorage.clear();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Move logout logic inside the auth error branch only.

Currently, the code clears storage and navigates to login for ALL HTTP errors, not just authentication errors. While the conditional distinguishes 401/403 from other errors with different messages, both paths proceed to log the user out. This means temporary network errors, server errors (500), or validation errors will all terminate the user's session, leading to poor UX and potential data loss.

Apply this diff to only logout on authentication errors:

-      catchError((error: HttpErrorResponse) => {
-        console.error(error);
-        if (error.status === 401 || error.status === 403) {
-          this.confirmationService.alert(
-            'Session expired. Please log in again to continue',
-            'error',
-          );
-        } else
-          this.confirmationService.alert(
-            error.error.errorMessage ||
-              'Something went wrong. Please try again later.',
-            'error',
-          );
-        this.router.navigate(['/login']);
-        sessionStorage.clear();
-        localStorage.clear();
-        this.spinnerService.show();
-        return throwError(error.error);
-      }),
+      catchError((error: HttpErrorResponse) => {
+        console.error(error);
+        if (error.status === 401 || error.status === 403) {
+          this.confirmationService.alert(
+            'Session expired. Please log in again to continue',
+            'error',
+          );
+          this.router.navigate(['/login']);
+          sessionStorage.clear();
+          localStorage.clear();
+        } else {
+          this.confirmationService.alert(
+            error.error.errorMessage ||
+              'Something went wrong. Please try again later.',
+            'error',
+          );
+        }
+        this.spinnerService.show();
+        return throwError(error.error);
+      }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (error.status === 401 || error.status === 403) {
this.confirmationService.alert(
'Session expired. Please log in again to continue',
'error',
);
} else
this.confirmationService.alert(
error.error.errorMessage ||
'Something went wrong. Please try again later.',
'error',
);
this.router.navigate(['/login']);
sessionStorage.clear();
localStorage.clear();
if (error.status === 401 || error.status === 403) {
this.confirmationService.alert(
'Session expired. Please log in again to continue',
'error',
);
this.router.navigate(['/login']);
sessionStorage.clear();
localStorage.clear();
} else {
this.confirmationService.alert(
error.error.errorMessage ||
'Something went wrong. Please try again later.',
'error',
);
}
🤖 Prompt for AI Agents
In src/app/app-modules/core/services/http-interceptor.service.ts around lines 83
to 96, the logout (router.navigate to '/login' and clearing
sessionStorage/localStorage) is executed for all HTTP errors; move the logout
logic so it only runs inside the 401/403 auth-error branch. Concretely: keep the
current confirmationService.alert messages as-is, but relocate the
this.router.navigate(['/login']); sessionStorage.clear(); localStorage.clear();
statements into the if (error.status === 401 || error.status === 403) block so
non-auth errors do not log out the user; ensure other branches only show the
error alert and return/exit without performing navigation or storage clearing.

Comment on lines +84 to +94
this.confirmationService.alert(
'Session expired. Please log in again to continue',
'error',
);
} else
this.confirmationService.alert(
error.error.errorMessage ||
'Something went wrong. Please try again later.',
'error',
);
this.router.navigate(['/login']);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider awaiting alert dismissal before navigation.

The confirmation alert is shown but navigation to /login happens immediately without waiting for the user to see or dismiss the alert. This race condition could result in the alert being destroyed during navigation, preventing the user from seeing the error message.

Consider subscribing to the alert's afterClosed() observable before navigating:

       catchError((error: HttpErrorResponse) => {
         console.error(error);
+        let alertMessage: string;
         if (error.status === 401 || error.status === 403) {
-          this.confirmationService.alert(
-            'Session expired. Please log in again to continue',
-            'error',
-          );
+          alertMessage = 'Session expired. Please log in again to continue';
         } else {
-          this.confirmationService.alert(
-            error.error.errorMessage ||
-              'Something went wrong. Please try again later.',
-            'error',
-          );
+          alertMessage = error.error.errorMessage ||
+            'Something went wrong. Please try again later.';
         }
+        this.confirmationService.alert(alertMessage, 'error')
+          .afterClosed()
+          .subscribe(() => {
-        this.router.navigate(['/login']);
-        sessionStorage.clear();
-        localStorage.clear();
+            this.router.navigate(['/login']);
+            sessionStorage.clear();
+            localStorage.clear();
+          });
         this.spinnerService.show();
         return throwError(error.error);
       }),

Note: This assumes the logout logic is moved inside the auth error branch as suggested in the previous comment.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/app/app-modules/core/services/http-interceptor.service.ts around lines
84-94, the code calls confirmationService.alert(...) and immediately calls
router.navigate(['/login']) causing the alert to be destroyed before the user
can see/dismiss it; change the flow to capture the alert/dialog reference
returned by confirmationService.alert and wait for its afterClosed() observable
(e.g., subscribe and take(1) or use firstValueFrom) and only then call
router.navigate(['/login']) (and perform any logout cleanup inside that
subscription) so navigation happens after the alert is dismissed.

@5Amogh 5Amogh requested a review from drtechie January 7, 2026 06:05
@5Amogh 5Amogh closed this Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants