Skip to content

Commit

Permalink
Feat: retry transfer in activity log
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterSmallenbroek authored and aberonni committed Feb 13, 2025
1 parent 68a0755 commit 7f63ca0
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 74 deletions.
2 changes: 1 addition & 1 deletion e2e/portalicious/pages/PaymentsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class PaymentsPage extends BasePage {
});
this.paymentAmount = this.page.getByTestId('metric-tile-component');
this.retryFailedTransfersButton = this.page.getByRole('button', {
name: 'Retry failed transfers',
name: 'Retry failed transfer(s)',
});
this.popupRetryTransferButton = this.page.getByRole('button', {
name: 'Retry transfers',
Expand Down
2 changes: 1 addition & 1 deletion interfaces/Portalicious/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module.exports = tseslint.config(
],
'@angular-eslint/component-max-inline-declarations': [
'error',
{ template: 30 },
{ template: 10 },
],
'@angular-eslint/no-async-lifecycle-method': ['error'],
'@angular-eslint/no-conflicting-lifecycle': ['error'],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<app-confirmation-dialog
#retryTransfersConfirmationDialog
header="Retry failed transfers"
header="Retry failed transfer(s)"
i18n-header="@@retry-failed-transfers"
headerIcon="pi pi-refresh"
proceedLabel="Retry transfers"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import {
import { injectMutation } from '@tanstack/angular-query-experimental';

import { ConfirmationDialogComponent } from '~/components/confirmation-dialog/confirmation-dialog.component';
import { QueryTableComponent } from '~/components/query-table/query-table.component';
import { MetricApiService } from '~/domains/metric/metric.api.service';
import { PaymentMetricDetails } from '~/domains/metric/metric.model';
import { PaymentApiService } from '~/domains/payment/payment.api.service';
import { ToastService } from '~/services/toast.service';

Expand All @@ -30,7 +28,6 @@ export class RetryTransfersDialogComponent {

private metricApiService = inject(MetricApiService);
private paymentApiService = inject(PaymentApiService);
private toastService = inject(ToastService);

readonly referenceIdsForRetryTransfers = signal<string[]>([]);

Expand All @@ -55,37 +52,7 @@ export class RetryTransfersDialogComponent {
},
}));

public retryFailedTransfers({
table,
triggeredFromContextMenu,
contextMenuItem,
}: {
table: QueryTableComponent<PaymentMetricDetails, never>;
triggeredFromContextMenu: boolean;
contextMenuItem?: PaymentMetricDetails;
}) {
const actionData = table.getActionData({
triggeredFromContextMenu,
contextMenuItem,
fieldForFilter: 'referenceId',
noSelectionToastMessage: $localize`:@@no-registrations-selected:Select one or more registrations and try again.`,
});

if (!actionData) {
return;
}

const selection = actionData.selection;

if (!Array.isArray(selection) || selection.length === 0) {
this.toastService.showGenericError(); // Should never happen
return;
}

const referenceIds = selection.map(
(transaction) => transaction.referenceId,
);

public retryFailedTransfers({ referenceIds }: { referenceIds: string[] }) {
this.referenceIdsForRetryTransfers.set(referenceIds);
this.retryTransfersConfirmationDialog().askForConfirmation();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ <h1 class="me-auto">
>
@if (canRetryTransfers()) {
<p-button
label="Retry failed transfers"
label="Retry failed transfer(s)"
i18n-label="@@retry-failed-transfers"
rounded
outlined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,11 +354,30 @@ export class ProjectPaymentPageComponent {
});
return;
}

this.retryTransfersDialog().retryFailedTransfers({
table: this.table(),
const actionData = this.table().getActionData({
triggeredFromContextMenu,
contextMenuItem: this.contextMenuSelection(),
fieldForFilter: 'referenceId',
noSelectionToastMessage: $localize`:@@no-registrations-selected:Select one or more registrations and try again.`,
});

if (!actionData) {
return;
}

const selection = actionData.selection;

if (!Array.isArray(selection) || selection.length === 0) {
this.toastService.showGenericError(); // Should never happen
return;
}

const referenceIds = selection.map(
(transaction) => transaction.referenceId,
);

this.retryTransfersDialog().retryFailedTransfers({
referenceIds,
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<div class="flex w-full content-between items-center">
@if (!!overview()) {
<span class="max-w-96 truncate text-ellipsis">{{ overview() }}</span>
}

<div
class="me-auto"
[ngClass]="{
'ms-2': !!overview(),
}"
>
@if (chipData()) {
<app-colored-chip
[label]="chipData()!.chipLabel"
[variant]="chipData()!.chipVariant"
/>
}

@if (canRetryTransfer()) {
<p-button
[ngClass]="{
'ms-1': !!chipData(),
}"
label="Retry transfer"
i18n-label="@@retry-transfer"
rounded
size="small"
(click)="retryTransfer()"
/>
}
</div>

@let dialogData = voucherDialogData();
@if (dialogData) {
<app-activity-log-voucher-dialog
[projectId]="dialogData.projectId"
[paymentId]="dialogData.paymentId"
[totalTransfers]="dialogData.totalTransfers"
[voucherReferenceId]="dialogData.voucherReferenceId"
/>
}
</div>

@let payment = paymentId();
@if (payment) {
<app-retry-transfers-dialog
#retryTransfersDialog
[projectId]="context().projectId()"
[paymentId]="payment"
/>
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ import {
inject,
input,
LOCALE_ID,
viewChild,
} from '@angular/core';

import { injectQuery } from '@tanstack/angular-query-experimental';
import { ButtonModule } from 'primeng/button';
import { ChipModule } from 'primeng/chip';

import { ActivityTypeEnum } from '@121-service/src/activities/enum/activity-type.enum';
import { FinancialServiceProviders } from '@121-service/src/financial-service-providers/enum/financial-service-provider-name.enum';
import { TransactionStatusEnum } from '@121-service/src/payments/transactions/enums/transaction-status.enum';
import { GenericRegistrationAttributes } from '@121-service/src/registration/enum/registration-attribute.enum';
import { PermissionEnum } from '@121-service/src/user/enum/permission.enum';

import { ColoredChipComponent } from '~/components/colored-chip/colored-chip.component';
import {
Expand All @@ -25,8 +29,10 @@ import { TableCellComponent } from '~/components/query-table/components/table-ce
import { MESSAGE_CONTENT_TYPE_LABELS } from '~/domains/message/message.helper';
import { REGISTRATION_STATUS_LABELS } from '~/domains/registration/registration.helper';
import { Activity } from '~/domains/registration/registration.model';
import { RetryTransfersDialogComponent } from '~/pages/project-payment/components/retry-transfers-dialog/retry-transfers-dialog.component';
import { ActivityLogVoucherDialogComponent } from '~/pages/project-registration-activity-log/components/activity-log-voucher-dialog/activity-log-voucher-dialog.component';
import { ActivityLogTableCellContext } from '~/pages/project-registration-activity-log/project-registration-activity-log.page';
import { AuthService } from '~/services/auth.service';
import { RegistrationAttributeService } from '~/services/registration-attribute.service';
import { Locale } from '~/utils/locale';

Expand All @@ -37,38 +43,10 @@ import { Locale } from '~/utils/locale';
ColoredChipComponent,
ActivityLogVoucherDialogComponent,
NgClass,
ButtonModule,
RetryTransfersDialogComponent,
],
template: `
<div class="flex w-full content-between items-center">
@if (!!overview()) {
<span class="max-w-96 truncate text-ellipsis">{{ overview() }}</span>
}
@if (chipData()) {
<div
class="me-auto"
[ngClass]="{
'ms-2': !!overview(),
}"
>
<app-colored-chip
[label]="chipData()!.chipLabel"
[variant]="chipData()!.chipVariant"
/>
</div>
}
@let dialogData = voucherDialogData();
@if (dialogData) {
<app-activity-log-voucher-dialog
[projectId]="dialogData.projectId"
[paymentId]="dialogData.paymentId"
[totalTransfers]="dialogData.totalTransfers"
[voucherReferenceId]="dialogData.voucherReferenceId"
/>
}
</div>
`,
templateUrl: './table-cell-overview.component.html',
styles: ``,
changeDetection: ChangeDetectionStrategy.OnPush,
})
Expand All @@ -79,7 +57,11 @@ export class TableCellOverviewComponent
readonly context = input.required<ActivityLogTableCellContext>();
locale = inject<Locale>(LOCALE_ID);

readonly retryTransfersDialog =
viewChild.required<RetryTransfersDialogComponent>('retryTransfersDialog');

readonly registrationAttributeService = inject(RegistrationAttributeService);
readonly authService = inject(AuthService);

readonly registrationAttributes = injectQuery(
this.registrationAttributeService.getRegistrationAttributes(this.context),
Expand All @@ -99,6 +81,14 @@ export class TableCellOverviewComponent
return undefined;
});

readonly paymentId = computed(() => {
const item = this.value();
if (item.type === ActivityTypeEnum.Transaction) {
return item.attributes.payment.toString();
}
return undefined;
});

readonly overview = computed(() => {
const item = this.value();
switch (item.type) {
Expand All @@ -125,6 +115,27 @@ export class TableCellOverviewComponent
}
});

readonly canRetryTransfer = computed(() => {
const item = this.value();
if (
!this.authService.hasAllPermissions({
projectId: this.context().projectId(),
requiredPermissions: [
PermissionEnum.PaymentREAD,
PermissionEnum.PaymentCREATE,
PermissionEnum.PaymentTransactionREAD,
],
})
) {
return false;
}

if (item.type !== ActivityTypeEnum.Transaction) {
return false;
}
return item.attributes.status === TransactionStatusEnum.error;
});

readonly voucherDialogData = computed(() => {
const item = this.value();
const referenceId = this.context().referenceId;
Expand All @@ -148,4 +159,22 @@ export class TableCellOverviewComponent
voucherReferenceId: referenceId,
};
});

retryTransfer() {
// TODO AB#33349: Not sure if this still needs to be checked
// if (this.paymentStatus.data()?.inProgress) {
// this.toastService.showToast({
// severity: 'warn',
// detail: $localize`A payment is currently in progress. Please wait until it has finished.`,
// });
// return;
// }
const referenceId = this.context().referenceId;
if (referenceId) {
const referenceIds = [referenceId];
this.retryTransfersDialog().retryFailedTransfers({
referenceIds,
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { ACTIVITY_LOG_ITEM_TYPE_LABELS } from '~/domains/registration/registrati
import { Activity } from '~/domains/registration/registration.model';
import { ActivityLogExpandedRowComponent } from '~/pages/project-registration-activity-log/components/activity-log-expanded-row/activity-log-expanded-row.component';
import { TableCellActivityComponent } from '~/pages/project-registration-activity-log/components/table-cell-activity.component';
import { TableCellOverviewComponent } from '~/pages/project-registration-activity-log/components/table-cell-overview.component';
import { TableCellOverviewComponent } from '~/pages/project-registration-activity-log/components/table-cell-overview/table-cell-overview.component';

export interface ActivityLogTableCellContext {
projectId: Signal<string>;
Expand Down
5 changes: 4 additions & 1 deletion interfaces/Portalicious/src/locale/messages.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@
<source>You are about to retry <x equiv-text="{{ referenceIdsForRetryTransfers().length }}" id="INTERPOLATION"/> payment(s). The transfer status will change to Pending until received by the registration.</source>
</trans-unit>
<trans-unit id="retry-failed-transfers" datatype="html">
<source>Retry failed transfers</source>
<source>Retry failed transfer(s)</source>
</trans-unit>
<trans-unit id="payment-report" datatype="html">
<source>Payment report</source>
Expand Down Expand Up @@ -1533,6 +1533,9 @@
<trans-unit id="attribute-edit-info-inclusionScore" datatype="html">
<source>Inclusion score generated by the answers of the Kobo form.</source>
</trans-unit>
<trans-unit id="retry-transfer" datatype="html">
<source>Retry transfer</source>
</trans-unit>
</body>
</file>
</xliff>

0 comments on commit 7f63ca0

Please sign in to comment.