-
Notifications
You must be signed in to change notification settings - Fork 0
fix: JE fixes #1093
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: JE fixes #1093
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||
| import { BusinessCentralDestinationAttributes } from "../business-central/db/business-central-destination-attribute.model"; | ||||||
| import { QbdDirectDestinationAttribute } from "../qbd-direct/db/qbd-direct-destination-attribuite.model"; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typo in import path The import path contains a spelling error: "attribuite" should be "attribute". -import { QbdDirectDestinationAttribute } from "../qbd-direct/db/qbd-direct-destination-attribuite.model";
+import { QbdDirectDestinationAttribute } from "../qbd-direct/db/qbd-direct-destination-attribute.model";📝 Committable suggestion
Suggested change
|
||||||
| import { Sage300DestinationAttributes } from "../sage300/db/sage300-destination-attribuite.model"; | ||||||
| import { PaginatedResponse } from "./paginated-response.model"; | ||||||
|
|
||||||
|
|
@@ -36,7 +37,7 @@ export interface PaginatedDestinationAttribute extends PaginatedResponse { | |||||
| } | ||||||
|
|
||||||
| export type GroupedDestinationAttribute = { | ||||||
| ACCOUNT: Sage300DestinationAttributes[] | BusinessCentralDestinationAttributes[], | ||||||
| ACCOUNT: Sage300DestinationAttributes[] | BusinessCentralDestinationAttributes[] | QbdDirectDestinationAttribute[], | ||||||
| EXPENSE_TYPE: Sage300DestinationAttributes[], | ||||||
| EXPENSE_PAYMENT_TYPE: Sage300DestinationAttributes[] | BusinessCentralDestinationAttributes[], | ||||||
| VENDOR_PAYMENT_ACCOUNT: DestinationAttribute[], | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -29,6 +29,15 @@ export class QbdDirectAdvancedSettingsModel extends AdvancedSettingsModel { | |||||||||||||||||||||||||||||||||
| return ["employee_name", "Expense/Report ID"]; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| static topMemoExpenseKeyNameConversion(keys: string[]): string[] { | ||||||||||||||||||||||||||||||||||
| keys.forEach((key: string, index: number) => { | ||||||||||||||||||||||||||||||||||
| if (key === 'expense_key') { | ||||||||||||||||||||||||||||||||||
| keys[index] = 'Expense/Report ID'; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
| return keys; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+32
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve method implementation to follow best practices The current implementation has potential issues:
Consider this safer implementation: - static topMemoExpenseKeyNameConversion(keys: string[]): string[] {
- keys.forEach((key: string, index: number) => {
- if (key === 'expense_key') {
- keys[index] = 'Expense/Report ID';
- }
- });
- return keys;
- }
+ static topMemoExpenseKeyNameConversion(keys: string[] | null | undefined): string[] {
+ if (!keys?.length) {
+ return [];
+ }
+ return keys.map((key: string) =>
+ key === 'expense_key' ? 'Expense/Report ID' : key
+ );
+ }📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| static formatMemoStructure(memoStructure: string[], defaultMemoOptions: string[]): string[] { | ||||||||||||||||||||||||||||||||||
| const originMemo: string[] = []; | ||||||||||||||||||||||||||||||||||
| defaultMemoOptions.forEach((field, index) => { | ||||||||||||||||||||||||||||||||||
|
|
@@ -43,7 +52,7 @@ export class QbdDirectAdvancedSettingsModel extends AdvancedSettingsModel { | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return new FormGroup({ | ||||||||||||||||||||||||||||||||||
| expenseMemoStructure: new FormControl(advancedSettings?.line_level_memo_structure && advancedSettings?.line_level_memo_structure.length > 0 ? this.formatMemoStructure(this.defaultMemoFields(), advancedSettings?.line_level_memo_structure) : this.defaultMemoFields(), Validators.required), | ||||||||||||||||||||||||||||||||||
| topMemoStructure: new FormControl(advancedSettings?.top_level_memo_structure && advancedSettings?.top_level_memo_structure.length > 0 ? advancedSettings?.top_level_memo_structure : this.defaultTopMemoOptions(), Validators.required), | ||||||||||||||||||||||||||||||||||
| topMemoStructure: new FormControl(advancedSettings?.top_level_memo_structure && advancedSettings?.top_level_memo_structure.length > 0 ? this.topMemoExpenseKeyNameConversion(advancedSettings?.top_level_memo_structure) : this.defaultTopMemoOptions(), Validators.required), | ||||||||||||||||||||||||||||||||||
| exportSchedule: new FormControl(advancedSettings?.schedule_is_enabled ? advancedSettings?.schedule_is_enabled : false), | ||||||||||||||||||||||||||||||||||
| email: new FormControl(advancedSettings?.emails_selected ? advancedSettings?.emails_selected : null), | ||||||||||||||||||||||||||||||||||
| exportScheduleFrequency: new FormControl(advancedSettings?.schedule_is_enabled ? advancedSettings?.interval_hours : 1), | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -174,6 +174,8 @@ export class QbdDirectExportSettingModel extends ExportSettingModel { | |
| return form.controls.creditCardExportType.value === QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY; | ||
| case 'defaultCreditCardAccountName': | ||
| return form.controls.creditCardExportType.value === QBDCorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE; | ||
| case 'employeeMapping': | ||
| return !form.get('reimbursableExportType')?.value && form.get('creditCardExportType')?.value && form.get('creditCardExportType')?.value === QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY; | ||
|
Comment on lines
+177
to
+178
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Review the employeeMapping mandatory field logic The current condition for making employeeMapping mandatory seems inconsistent. It only requires employeeMapping when reimbursableExportType is NOT set, but the validation rules later show that employeeMapping is required for both BILL and JOURNAL_ENTRY types. This could lead to validation inconsistencies. Consider updating the condition to: case 'employeeMapping':
- return !form.get('reimbursableExportType')?.value && form.get('creditCardExportType')?.value && form.get('creditCardExportType')?.value === QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY;
+ return (form.get('reimbursableExportType')?.value === QBDReimbursableExpensesObject.BILL ||
+ form.get('reimbursableExportType')?.value === QBDReimbursableExpensesObject.JOURNAL_ENTRY) ||
+ (form.get('creditCardExportType')?.value === QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY);
|
||
| default: | ||
| return false; | ||
| } | ||
|
|
@@ -182,23 +184,23 @@ export class QbdDirectExportSettingModel extends ExportSettingModel { | |
| static getValidators(): [ExportSettingValidatorRule, ExportModuleRule[]] { | ||
|
|
||
| const exportSettingValidatorRule: ExportSettingValidatorRule = { | ||
| reimbursableExpense: ['reimbursableExportType', 'reimbursableExportGroup', 'reimbursableExportDate', 'reimbursableExpenseState', 'employeeMapping'], | ||
| reimbursableExpense: ['reimbursableExportType', 'reimbursableExportGroup', 'reimbursableExportDate', 'reimbursableExpenseState'], | ||
| creditCardExpense: ['creditCardExportType', 'creditCardExportGroup', 'creditCardExportDate', 'creditCardExpenseState'] | ||
| }; | ||
|
|
||
| const exportModuleRule: ExportModuleRule[] = [ | ||
| { | ||
| formController: 'reimbursableExportType', | ||
| requiredValue: { | ||
| [QbdDirectReimbursableExpensesObject.BILL]: [], | ||
| [QbdDirectReimbursableExpensesObject.JOURNAL_ENTRY]: ['defaultReimbursableAccountsPayableAccountName'] | ||
| [QbdDirectReimbursableExpensesObject.BILL]: ['employeeMapping'], | ||
| [QbdDirectReimbursableExpensesObject.JOURNAL_ENTRY]: ['defaultReimbursableAccountsPayableAccountName', 'employeeMapping'] | ||
| } | ||
| }, | ||
| { | ||
| formController: 'creditCardExportType', | ||
| requiredValue: { | ||
| [QBDCorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE]: ['defaultCreditCardAccountName'], | ||
| [QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY]: ['defaultCCCAccountsPayableAccountName', 'nameInJE'] | ||
| [QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY]: ['defaultCCCAccountsPayableAccountName', 'nameInJE', 'employeeMapping'] | ||
| } | ||
| } | ||
| ]; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -78,6 +78,8 @@ export class QbdDirectDashboardComponent implements OnInit { | |||||
|
|
||||||
| importCodeFields: any; | ||||||
|
|
||||||
| chartOfAccounts: string[]; | ||||||
|
|
||||||
| constructor( | ||||||
| private accountingExportService: AccountingExportService, | ||||||
| private dashboardService: DashboardService, | ||||||
|
|
@@ -151,6 +153,8 @@ export class QbdDirectDashboardComponent implements OnInit { | |||||
|
|
||||||
| this.importCodeFields = responses[5].import_settings?.import_code_fields; | ||||||
|
|
||||||
| this.chartOfAccounts = responses[5].import_settings.chart_of_accounts; | ||||||
|
|
||||||
|
Comment on lines
+156
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null safety check for import_settings The code assumes - this.chartOfAccounts = responses[5].import_settings.chart_of_accounts;
+ this.chartOfAccounts = responses[5].import_settings?.chart_of_accounts ?? [];📝 Committable suggestion
Suggested change
|
||||||
| const queuedTasks: QbdDirectTaskLog[] = responses[2].results.filter((task: QbdDirectTaskLog) => this.exportLogProcessingStates.includes(task.status)); | ||||||
| this.failedExpenseGroupCount = responses[2].results.filter((task: QbdDirectTaskLog) => task.status === TaskLogState.FAILED || task.status === TaskLogState.FATAL).length; | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -108,7 +108,7 @@ export class QbdDirectExportSettingsComponent implements OnInit{ | |||||||||||||||||||||||||||||||||||
| return this.destinationOptionsWatcher(['Bank', 'AccountsPayable', 'CreditCard', 'OtherCurrentLiability', 'LongTermLiability'], this.destinationAccounts); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| cccAccpuntOptions(cccExportType: string): DestinationAttribute[] { | ||||||||||||||||||||||||||||||||||||
| cccAccountOptions(cccExportType: string): DestinationAttribute[] { | ||||||||||||||||||||||||||||||||||||
| if (cccExportType === QBDCorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE) { | ||||||||||||||||||||||||||||||||||||
| return this.destinationOptionsWatcher(['CreditCard'], this.destinationAccounts); | ||||||||||||||||||||||||||||||||||||
| } else if (cccExportType === QBDCorporateCreditCardExpensesObject.JOURNAL_ENTRY && this.exportSettingsForm.controls.employeeMapping.value === EmployeeFieldMapping.EMPLOYEE && this.exportSettingsForm.controls.nameInJE.value === EmployeeFieldMapping.EMPLOYEE) { | ||||||||||||||||||||||||||||||||||||
|
|
@@ -182,7 +182,7 @@ export class QbdDirectExportSettingsComponent implements OnInit{ | |||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| cccExportTypeWatcher(): void { | ||||||||||||||||||||||||||||||||||||
| this.exportSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportTypeValue) => { | ||||||||||||||||||||||||||||||||||||
| this.exportSettingsForm.controls.creditCardExportGroup.patchValue(this.creditCardExpenseGroupingFieldOptions[1].value); | ||||||||||||||||||||||||||||||||||||
| this.exportSettingsForm.controls.creditCardExportGroup.patchValue(QbdDirectExportSettingModel.expenseGroupingFieldOptions()[1].value); | ||||||||||||||||||||||||||||||||||||
| this.exportSettingsForm.controls.creditCardExportGroup.disable(); | ||||||||||||||||||||||||||||||||||||
| this.creditCardExpenseGroupingFieldOptions = [QbdDirectExportSettingModel.expenseGroupingFieldOptions()[1]]; | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
184
to
188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace hardcoded index with explicit value reference Using a hardcoded index [1] for accessing options is fragile and could break if the options array changes. Consider using a constant or finding the option by value. cccExportTypeWatcher(): void {
this.exportSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportTypeValue) => {
- this.exportSettingsForm.controls.creditCardExportGroup.patchValue(QbdDirectExportSettingModel.expenseGroupingFieldOptions()[1].value);
+ const defaultOption = QbdDirectExportSettingModel.expenseGroupingFieldOptions().find(option =>
+ option.value === QbdDirectExpenseGroupBy.EXPENSE
+ );
+ if (!defaultOption) {
+ throw new Error('Default expense grouping option not found');
+ }
+ this.exportSettingsForm.controls.creditCardExportGroup.patchValue(defaultOption.value);
this.exportSettingsForm.controls.creditCardExportGroup.disable();
- this.creditCardExpenseGroupingFieldOptions = [QbdDirectExportSettingModel.expenseGroupingFieldOptions()[1]];
+ this.creditCardExpenseGroupingFieldOptions = [defaultOption];
});
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,6 +13,7 @@ import { MappingService } from 'src/app/core/services/common/mapping.service'; | |||||||||||||||||||||||
| import { TrackingService } from 'src/app/core/services/integration/tracking.service'; | ||||||||||||||||||||||||
| import { WindowService } from 'src/app/core/services/common/window.service'; | ||||||||||||||||||||||||
| import { HelperService } from 'src/app/core/services/common/helper.service'; | ||||||||||||||||||||||||
| import { QbdDirectDestinationAttribute } from 'src/app/core/models/qbd-direct/db/qbd-direct-destination-attribuite.model'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||
| selector: 'app-dashboard-error-section', | ||||||||||||||||||||||||
|
|
@@ -51,6 +52,8 @@ export class DashboardErrorSectionComponent implements OnInit { | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @Input() importCodeFields: string[]; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @Input() chartOfAccounts: string[]; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| filteredMappings: ExtendedGenericMapping[]; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| destinationOptions: DestinationAttribute[]; | ||||||||||||||||||||||||
|
|
@@ -134,6 +137,10 @@ export class DashboardErrorSectionComponent implements OnInit { | |||||||||||||||||||||||
| }, 100); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| destinationOptionsWatcher(detailAccountType: string[], destinationOptions: QbdDirectDestinationAttribute[]): DestinationAttribute[] { | ||||||||||||||||||||||||
| return destinationOptions.filter((account: QbdDirectDestinationAttribute) => detailAccountType.includes(account.detail.account_type)); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+140
to
+142
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider improving method name and robustness. The current implementation could be enhanced for better clarity and safety:
- destinationOptionsWatcher(detailAccountType: string[], destinationOptions: QbdDirectDestinationAttribute[]): DestinationAttribute[] {
- return destinationOptions.filter((account: QbdDirectDestinationAttribute) => detailAccountType.includes(account.detail.account_type));
+ private filterDestinationOptionsByAccountType(detailAccountType: string[], destinationOptions: QbdDirectDestinationAttribute[]): DestinationAttribute[] {
+ if (!detailAccountType?.length || !destinationOptions?.length) {
+ return [];
+ }
+ return destinationOptions.filter((account: QbdDirectDestinationAttribute) =>
+ account.detail?.account_type && detailAccountType.includes(account.detail.account_type)
+ );📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private getDestinationOptionsV2(errorType: AccountingErrorType) { | ||||||||||||||||||||||||
| this.mappingService.getGroupedDestinationAttributes([this.destinationField], 'v2').subscribe(groupedDestinationResponse => { | ||||||||||||||||||||||||
| if (this.sourceField === 'EMPLOYEE') { | ||||||||||||||||||||||||
|
|
@@ -142,7 +149,7 @@ export class DashboardErrorSectionComponent implements OnInit { | |||||||||||||||||||||||
| if (this.destinationField === 'EXPENSE_TYPE') { | ||||||||||||||||||||||||
| this.destinationOptions = groupedDestinationResponse.EXPENSE_TYPE; | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| this.destinationOptions = groupedDestinationResponse.ACCOUNT; | ||||||||||||||||||||||||
| this.destinationOptions = this.appName !== AppName.QBD_DIRECT ? groupedDestinationResponse.ACCOUNT : this.destinationOptionsWatcher( this.chartOfAccounts, groupedDestinationResponse.ACCOUNT as QbdDirectDestinationAttribute[]); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider refactoring the growing list of exceptions.
The current approach of listing specific field names as exceptions is becoming unwieldy and harder to maintain. The comment "Temporary hack" also suggests this needs improvement.
Consider refactoring to a more maintainable solution:
This approach: