Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/app/core/models/public-policy-expense.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ export interface PublicPolicyExpense {
cost_center_code?: string;
transcription_state?: string;
verification_state?: string;
org_category?: string;
sub_category?: string;
org_category_code?: string;
corporate_credit_card_expense_group_id?: string;
Expand Down
1 change: 0 additions & 1 deletion src/app/core/models/unformatted-transaction.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export interface UnformattedTransaction {
cost_center_code: string;
transcription_state: string;
verification_state: string;
org_category: string;
sub_category: string;
org_category_code: string;
user_review_needed: boolean;
Expand Down
4 changes: 2 additions & 2 deletions src/app/core/models/v1/transaction.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ExpenseTransactionStatus } from '../../enums/platform/v1/expense-transaction-status.enum';
import { Destination } from '../destination.model';
import { PlatformCategory } from '../platform/platform-category.model';
import { File } from '../platform/v1/file.model';
import { TxnCustomProperties } from '../txn-custom-properties.model';

Expand All @@ -12,7 +13,6 @@ export interface Transaction {
amount?: number;
billable?: boolean;
bus_travel_class?: string;
category?: string;
cost_center_id?: number;
created_at?: Date;
creator_id?: string;
Expand Down Expand Up @@ -98,7 +98,7 @@ export interface Transaction {
cost_center_code?: string;
transcription_state?: string;
verification_state?: string;
org_category?: string;
category?: Pick<PlatformCategory, 'code' | 'id' | 'display_name' | 'name' | 'sub_category' | 'system_category'>;
sub_category?: string;
org_category_code?: string;
user_review_needed?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/services/deep-link.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ describe('DeepLinkService', () => {
tx: {
...unflattenedTxnData.tx,
state: item.state,
org_category: item.category,
category: { name: item.category, ...unflattenedTxnData.tx.category },
},
});
expect(result).toEqual(item.route);
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/services/deep-link.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class DeepLinkService {
}

getExpenseRoute(etxn: Partial<UnflattenedTransaction>): string[] {
const category = etxn.tx.org_category?.toLowerCase();
const category = etxn.tx.category?.name?.toLowerCase();
const canEditTxn = ['DRAFT', 'COMPLETE', 'APPROVER_PENDING'].includes(etxn.tx.state);
Comment on lines 135 to 137
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Graceful fallback when category.name is absent

Some older/edge payloads might miss category.name. Fall back to fyle_category to keep routing sharp.

Apply this diff:

-    const category = etxn.tx.category?.name?.toLowerCase();
+    const category = (etxn.tx.category?.name ?? etxn.tx.fyle_category)?.toLowerCase();
📝 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
getExpenseRoute(etxn: Partial<UnflattenedTransaction>): string[] {
const category = etxn.tx.org_category?.toLowerCase();
const category = etxn.tx.category?.name?.toLowerCase();
const canEditTxn = ['DRAFT', 'COMPLETE', 'APPROVER_PENDING'].includes(etxn.tx.state);
getExpenseRoute(etxn: Partial<UnflattenedTransaction>): string[] {
const category = (etxn.tx.category?.name ?? etxn.tx.fyle_category)?.toLowerCase();
const canEditTxn = ['DRAFT', 'COMPLETE', 'APPROVER_PENDING'].includes(etxn.tx.state);
🤖 Prompt for AI Agents
In src/app/core/services/deep-link.service.ts around lines 135 to 137, the code
reads category = etxn.tx.category?.name?.toLowerCase() which breaks or yields
undefined for older payloads missing category.name; modify the logic to fall
back to etxn.tx.fyle_category (e.g., use etxn.tx.category?.name ??
etxn.tx.fyle_category) and then call toLowerCase() only when the resulting value
is defined (null-safe), so routing uses fyle_category when category.name is
absent while avoiding runtime errors.


let route: string[] = [];
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/services/transaction.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ export class TransactionService {
spent_at: expense.spent_at,
categoryDisplayName: expense.category?.display_name,
files: expense.files,
org_category: expense.category?.name,
category: expense.category,
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Category object mapping: solid move, boss.

Switching to the full category object aligns the service with the new model and keeps consumers future-proof.

Run this quick scan to ensure there are no lingering references to org_category that could break callers:


🏁 Script executed:

#!/bin/bash
rg -n --type=ts -S '\borg_category\b|tx\.org_category\b' -g '!**/dist/**' -g '!**/node_modules/**'

Length of output: 148


Boss, no files got scanned—let’s expand the search across all .ts files:


🏁 Script executed:

#!/bin/bash
rg -n '\borg_category\b|tx\.org_category\b' -g '**/*.ts' -g '!**/dist/**' -g '!**/node_modules/**'

Length of output: 8483


Replace all org_category references in specs and mock-data with the new category object.
Boss, tests under src/app/fyle and data in src/app/core/mock-data still use tx.org_category—update them to use tx.category (e.g. tx.category.name) to match the service change.

🤖 Prompt for AI Agents
In src/app/core/services/transaction.service.ts around line 609, the service now
uses expense.category but many tests and mock fixtures still reference
tx.org_category; update all occurrences in specs under src/app/fyle and in mock
data under src/app/core/mock-data to use the new category object (e.g. replace
tx.org_category.name with tx.category.name, tx.org_category.id with
tx.category.id, or adjust to the nested shape used by the service), and make
corresponding changes to mock-data objects so they include a category property
with the expected fields; ensure tests/assertions and any type imports reflect
the renamed property.

fyle_category: expense.category?.system_category,
state: expense.state,
admin_amount: expense.admin_amount,
Expand Down
10 changes: 5 additions & 5 deletions src/app/fyle/add-edit-expense/add-edit-expense.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2857,8 +2857,8 @@ export class AddEditExpensePage implements OnInit {
goToTransaction(expense: Partial<UnflattenedTransaction>, reviewList: string[], activeIndex: number): void {
let category: string;

if (expense.tx.org_category) {
category = expense.tx.org_category.toLowerCase();
if (expense.tx.category?.name) {
category = expense.tx.category.name.toLowerCase();
}
Comment on lines 2858 to 2862
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Simplify and harden category routing

Inline with a fallback to fyle_category so navigation doesn’t miss a beat.

Apply this diff:

-    let category: string;
-
-    if (expense.tx.category?.name) {
-      category = expense.tx.category.name.toLowerCase();
-    }
+    const category = (expense.tx.category?.name ?? expense.tx.fyle_category)?.toLowerCase();
📝 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
let category: string;
if (expense.tx.org_category) {
category = expense.tx.org_category.toLowerCase();
if (expense.tx.category?.name) {
category = expense.tx.category.name.toLowerCase();
}
const category = (expense.tx.category?.name ?? expense.tx.fyle_category)?.toLowerCase();
🤖 Prompt for AI Agents
In src/app/fyle/add-edit-expense/add-edit-expense.page.ts around lines 2858 to
2862, the category extraction currently only sets category when
expense.tx.category.name exists; change it to always initialize category using
the category name with a fallback to expense.tx.fyle_category and defensively
handle undefined before calling toLowerCase. For example, set category to
(expense.tx.category?.name || expense.tx.fyle_category || '').toLowerCase() so
routing always has a lowercase string to use without throwing when values are
missing.


if (category === 'mileage') {
Expand Down Expand Up @@ -4068,7 +4068,7 @@ export class AddEditExpensePage implements OnInit {
Type: 'Receipt',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Category:
etxn.tx.category_id && this.presetCategoryId && etxn.tx.category_id === this.presetCategoryId,
Expand Down Expand Up @@ -4317,7 +4317,7 @@ export class AddEditExpensePage implements OnInit {
Type: 'Receipt',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Category:
etxn.tx.category_id && this.presetCategoryId && etxn.tx.category_id === this.presetCategoryId,
Comment on lines 4317 to 4323
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Tracking on add: same fallback for Category

Consistency, machi. Make the pipeline smile.

Apply this diff:

-        Category: etxn.tx.category?.name,
+        Category: etxn.tx.category?.name ?? etxn.tx.fyle_category,
📝 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
Type: 'Receipt',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Category:
etxn.tx.category_id && this.presetCategoryId && etxn.tx.category_id === this.presetCategoryId,
Type: 'Receipt',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.category?.name ?? etxn.tx.fyle_category,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Category:
etxn.tx.category_id && this.presetCategoryId && etxn.tx.category_id === this.presetCategoryId,
🤖 Prompt for AI Agents
In src/app/fyle/add-edit-expense/add-edit-expense.page.ts around lines 4317 to
4323, the Category field on add uses etxn.tx.category?.name only; update it to
use the same fallback as elsewhere by setting Category to etxn.tx.category?.name
|| this.presetCategory?.name (or the equivalent null-coalescing expression used
in the file) so the preset category name is used when tx.category is absent,
leaving the rest of the object (Type, Amount, Currency, Time_Spent,
Used_Autofilled_Category) unchanged.

Expand Down Expand Up @@ -4398,7 +4398,7 @@ export class AddEditExpensePage implements OnInit {
Type: 'Receipt',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Category:
etxn.tx.category_id && this.presetCategoryId && etxn.tx.category_id === this.presetCategoryId,
Expand Down
9 changes: 4 additions & 5 deletions src/app/fyle/add-edit-mileage/add-edit-mileage.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,8 @@ export class AddEditMileagePage implements OnInit {
goToTransaction(expense: Partial<UnflattenedTransaction>, reviewList, activeIndex: number): void {
let category: string;

if (expense.tx.org_category) {
category = expense.tx.org_category.toLowerCase();
if (expense.tx.category?.name) {
category = expense.tx.category.name.toLowerCase();
}

Comment on lines 469 to 474
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Style with substance: fallback routing for category.

Mirror the per-diem hardening so navigation never guesses wrong.

-    let category: string;
-
-    if (expense.tx.category?.name) {
-      category = expense.tx.category.name.toLowerCase();
-    }
+    const category =
+      (expense.tx.category?.name || expense.tx.fyle_category || expense.tx.sub_category)?.toLowerCase();
📝 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
let category: string;
if (expense.tx.org_category) {
category = expense.tx.org_category.toLowerCase();
if (expense.tx.category?.name) {
category = expense.tx.category.name.toLowerCase();
}
const category =
(expense.tx.category?.name || expense.tx.fyle_category || expense.tx.sub_category)?.toLowerCase();
🤖 Prompt for AI Agents
In src/app/fyle/add-edit-mileage/add-edit-mileage.page.ts around lines 469-474,
the code conditionally sets category only when expense.tx.category?.name exists
which can leave category undefined and allow downstream routing to "guess";
change to always assign category using a safe fallback and lowercasing, e.g. set
category = (expense.tx.category?.name || '').toLowerCase(); or an explicit
fallback token like 'unknown' depending on routing expectations, so navigation
never relies on an undefined value.

if (category === 'mileage') {
Expand Down Expand Up @@ -970,7 +970,6 @@ export class AddEditMileagePage implements OnInit {
state: 'COMPLETE',
spent_at: new Date(),
category_id: mileageContainer.defaultMileageCategory && mileageContainer.defaultMileageCategory.id,
org_category: mileageContainer.defaultMileageCategory && mileageContainer.defaultMileageCategory.name,
sub_category:
mileageContainer.defaultMileageCategory && mileageContainer.defaultMileageCategory.sub_category,
currency: homeCurrency,
Expand Down Expand Up @@ -2458,7 +2457,7 @@ export class AddEditMileagePage implements OnInit {
Type: 'Mileage',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Telemetry, kaboom! Never log an empty category.

Add a robust default for Category in edit/create tracking.

-      Category: etxn.tx.category?.name,
+      Category: etxn.tx.category?.name || etxn.tx.fyle_category || 'Mileage',

Also applies to: 2727-2727

🤖 Prompt for AI Agents
In src/app/fyle/add-edit-mileage/add-edit-mileage.page.ts around lines 2460 and
2727 the telemetry payload sets Category: etxn.tx.category?.name which can be
undefined or empty; replace this with a robust default by using a fallback
(e.g., etxn.tx.category?.name || 'Uncategorized' or a localized "No Category"
string) so the telemetry never logs an empty category value; ensure the fallback
is applied consistently in both locations.

Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Project:
etxn.tx.project_id && this.presetProjectId && etxn.tx.project_id === this.presetProjectId,
Expand Down Expand Up @@ -2725,7 +2724,7 @@ export class AddEditMileagePage implements OnInit {
Type: 'Mileage',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Project:
etxn.tx.project_id && this.presetProjectId && etxn.tx.project_id === this.presetProjectId,
Expand Down
9 changes: 4 additions & 5 deletions src/app/fyle/add-edit-per-diem/add-edit-per-diem.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,8 @@ export class AddEditPerDiemPage implements OnInit {
goToTransaction(expense: Partial<UnflattenedTransaction>, reviewList: string[], activeIndex: number): void {
let category: string;

if (expense.tx.org_category) {
category = expense.tx.org_category.toLowerCase();
if (expense.tx.category?.name) {
category = expense.tx.category.name.toLowerCase();
}
Comment on lines 461 to 464
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Good switch, but make it fail-proof, boss. Add a fallback for routing.

If category object is missing, navigation silently falls back to generic expense. Use fyle_category/sub_category as backup so review flow doesn’t misroute.

-    let category: string;
-
-    if (expense.tx.category?.name) {
-      category = expense.tx.category.name.toLowerCase();
-    }
+    const category =
+      (expense.tx.category?.name || expense.tx.fyle_category || expense.tx.sub_category)?.toLowerCase();
📝 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 (expense.tx.org_category) {
category = expense.tx.org_category.toLowerCase();
if (expense.tx.category?.name) {
category = expense.tx.category.name.toLowerCase();
}
const category =
(expense.tx.category?.name || expense.tx.fyle_category || expense.tx.sub_category)?.toLowerCase();
🤖 Prompt for AI Agents
In src/app/fyle/add-edit-per-diem/add-edit-per-diem.page.ts around lines 461 to
464, the current code only sets category from expense.tx.category.name which can
be missing and cause misrouting; update the logic to fall back to
expense.tx.fyle_category or expense.tx.fyle_sub_category (in that order) when
category or its name is absent, normalize the chosen value to lowercase, and use
that fallback value for routing so the review flow doesn’t silently default to
generic expense.


if (category === 'mileage') {
Expand Down Expand Up @@ -675,7 +675,6 @@ export class AddEditPerDiemPage implements OnInit {
skip_reimbursement: false,
source: 'MOBILE',
category_id: categoryContainer.defaultPerDiemCategory && categoryContainer.defaultPerDiemCategory.id,
org_category: categoryContainer.defaultPerDiemCategory && categoryContainer.defaultPerDiemCategory.name,
sub_category:
categoryContainer.defaultPerDiemCategory && categoryContainer.defaultPerDiemCategory.sub_category,
amount: 0,
Expand Down Expand Up @@ -1892,7 +1891,7 @@ export class AddEditPerDiemPage implements OnInit {
Type: 'Receipt',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Telemetry shouldn’t go mute. Add a Category fallback.

On fresh add/edit, category object can be absent; log a sensible default.

-              Category: etxn.tx.category?.name,
+              Category: etxn.tx.category?.name || etxn.tx.fyle_category || 'Per Diem',

Also applies to: 2064-2064

🤖 Prompt for AI Agents
In src/app/fyle/add-edit-per-diem/add-edit-per-diem.page.ts around lines 1894
and 2064, the telemetry log uses etxn.tx.category?.name which can be undefined
on fresh add/edit; replace it with a safe fallback (e.g. use the category name
if present otherwise a sensible default like "Uncategorized" or "Unknown
Category") so the logged Category is never empty.

Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Project:
etxn.tx.project_id && this.presetProjectId && etxn.tx.project_id === this.presetProjectId,
Expand Down Expand Up @@ -2062,7 +2061,7 @@ export class AddEditPerDiemPage implements OnInit {
Type: 'Per Diem',
Amount: etxn.tx.amount,
Currency: etxn.tx.currency,
Category: etxn.tx.org_category,
Category: etxn.tx.category?.name,
Time_Spent: this.getTimeSpentOnPage() + ' secs',
Used_Autofilled_Project:
etxn.tx.project_id && this.presetProjectId && etxn.tx.project_id === this.presetProjectId,
Expand Down
4 changes: 2 additions & 2 deletions src/app/fyle/dashboard/tasks/tasks.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,8 @@ export class TasksComponent implements OnInit {
.subscribe(({ initial, allExpenseIds }) => {
let category;

if (initial.tx.org_category) {
category = initial.tx.org_category.toLowerCase();
if (initial.tx.category?.name) {
category = initial.tx.category.name.toLowerCase();
}
Comment on lines 555 to 559
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Route robustly even if category.name is missing

Make the route logic rock-solid by falling back to fyle_category. One liner, maximum impact.

Apply this diff:

-        let category;
-
-        if (initial.tx.category?.name) {
-          category = initial.tx.category.name.toLowerCase();
-        }
+        const category = (initial.tx.category?.name ?? initial.tx.fyle_category)?.toLowerCase();
📝 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
let category;
if (initial.tx.org_category) {
category = initial.tx.org_category.toLowerCase();
if (initial.tx.category?.name) {
category = initial.tx.category.name.toLowerCase();
}
const category = (initial.tx.category?.name ?? initial.tx.fyle_category)?.toLowerCase();
🤖 Prompt for AI Agents
In src/app/fyle/dashboard/tasks/tasks.component.ts around lines 555 to 559, the
code assumes initial.tx.category.name exists; change the logic to set category
using a single-line fallback that uses initial.tx.category?.name or
initial.tx.fyle_category (e.g., assign category = (initial.tx.category?.name ||
initial.tx.fyle_category).toLowerCase() while guarding against undefined before
calling toLowerCase) so routing works even when category.name is missing.


if (category === 'mileage') {
Expand Down
3 changes: 0 additions & 3 deletions src/app/fyle/split-expense/split-expense.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,14 +441,12 @@ export class SplitExpensePage implements OnDestroy {
splitTxn.project_id = project.project_id;
splitTxn.project_name = project.project_name;
splitTxn.category_id = null;
splitTxn.org_category = null;
if (
this.transaction.category_id &&
(!isProjectCategoryRestrictionsEnabled ||
(project.project_org_category_ids && project.project_org_category_ids.includes(this.transaction.category_id)))
) {
splitTxn.category_id = this.transaction.category_id;
splitTxn.org_category = this.transaction.org_category;
}
}

Expand All @@ -465,7 +463,6 @@ export class SplitExpensePage implements OnDestroy {
this.setSplitExpenseValuesBasedOnProject(splitTxn, project, isProjectCategoryRestrictionsEnabled);
} else if (splitFormValue.category?.id) {
splitTxn.category_id = splitFormValue.category.id;
splitTxn.org_category = splitFormValue.category.name;
splitTxn.project_id = null;
splitTxn.project_name = null;
if (
Expand Down
Loading