Bump swag payments (#189)

This commit is contained in:
Ildar Galeev 2024-07-05 18:46:22 +07:00 committed by GitHub
parent 872dc7a008
commit 4f8cfd3076
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
112 changed files with 9 additions and 3247 deletions

8
package-lock.json generated
View File

@ -26,7 +26,7 @@
"@vality/swag-api-keys-v2": "0.1.2-321124b.0", "@vality/swag-api-keys-v2": "0.1.2-321124b.0",
"@vality/swag-claim-management": "0.1.1-b5248eb.0", "@vality/swag-claim-management": "0.1.1-b5248eb.0",
"@vality/swag-organizations": "1.0.1-e863566.0", "@vality/swag-organizations": "1.0.1-e863566.0",
"@vality/swag-payments": "0.1.3-5760b7e.0", "@vality/swag-payments": "0.1.3-44bac58.0",
"@vality/swag-url-shortener": "0.1.1-9659896.0", "@vality/swag-url-shortener": "0.1.1-9659896.0",
"@vality/swag-wallet": "0.1.3-54f56db.0", "@vality/swag-wallet": "0.1.3-54f56db.0",
"angular-file": "^3.0.1", "angular-file": "^3.0.1",
@ -7212,9 +7212,9 @@
} }
}, },
"node_modules/@vality/swag-payments": { "node_modules/@vality/swag-payments": {
"version": "0.1.3-5760b7e.0", "version": "0.1.3-44bac58.0",
"resolved": "https://registry.npmjs.org/@vality/swag-payments/-/swag-payments-0.1.3-5760b7e.0.tgz", "resolved": "https://registry.npmjs.org/@vality/swag-payments/-/swag-payments-0.1.3-44bac58.0.tgz",
"integrity": "sha512-DqCP2Z3k7JVM9Ik+3fPCzPkYwQ8uQmuKHxmTr5s5zr6DSiiQ3KWzPfeWI1FZ1yqcScrbiWNCLKtZOM2XmrPyCg==", "integrity": "sha512-F1yf1Dt1q04+z7PzqQ8BNWCFG5rWnF4Yfb/BEa/1efBBg7L6tnD2//dnOpgQyaHA777eRpqC5byGmKsnoMJm9w==",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },

View File

@ -43,7 +43,7 @@
"@vality/swag-api-keys-v2": "0.1.2-321124b.0", "@vality/swag-api-keys-v2": "0.1.2-321124b.0",
"@vality/swag-claim-management": "0.1.1-b5248eb.0", "@vality/swag-claim-management": "0.1.1-b5248eb.0",
"@vality/swag-organizations": "1.0.1-e863566.0", "@vality/swag-organizations": "1.0.1-e863566.0",
"@vality/swag-payments": "0.1.3-5760b7e.0", "@vality/swag-payments": "0.1.3-44bac58.0",
"@vality/swag-url-shortener": "0.1.1-9659896.0", "@vality/swag-url-shortener": "0.1.1-9659896.0",
"@vality/swag-wallet": "0.1.3-54f56db.0", "@vality/swag-wallet": "0.1.3-54f56db.0",
"angular-file": "^3.0.1", "angular-file": "^3.0.1",

View File

@ -9,7 +9,6 @@ export * from './countries.service';
export * from './shops.service'; export * from './shops.service';
export * from './webhooks.service'; export * from './webhooks.service';
export * from './payments.service'; export * from './payments.service';
export * from './payouts.service';
export * from './invoices.service'; export * from './invoices.service';
export * from './contracts.service'; export * from './contracts.service';
export * from './payments-dictionary.service'; export * from './payments-dictionary.service';

View File

@ -1,22 +0,0 @@
import { Injectable, Injector } from '@angular/core';
import { PayoutsService as ApiPayoutsService } from '@vality/swag-payments';
import { PartyIdExtension, PartyIdPatchMethodService } from '@dsh/app/api/utils/extensions';
import { createApi } from '../utils';
@Injectable({
providedIn: 'root',
})
export class PayoutsService extends createApi(ApiPayoutsService, [PartyIdExtension]) {
constructor(
injector: Injector,
private partyIdPatchMethodService: PartyIdPatchMethodService,
) {
super(injector);
this.createPayout = partyIdPatchMethodService.patch(
this.createPayout,
(params, partyId) => (params.payoutParams.partyID = partyId),
);
}
}

View File

@ -1,51 +0,0 @@
<div
*transloco="let t; scope: 'payment-section'; read: 'paymentSection.payouts.createPayoutReport'"
fxLayout="column"
fxLayoutGap="32px"
>
<div class="dsh-headline">{{ t('title') }}</div>
<ng-container *ngIf="reportCreated$ | async; else elseBlock">
<div class="dsh-body-1">{{ t('descriptionStep2') }}</div>
</ng-container>
<ng-template #elseBlock
><div class="dsh-body-1">{{ t('descriptionStep1') }}</div></ng-template
>
<div
fxLayout="row"
fxLayout.xs="column"
fxLayoutAlign="space-between stretch"
fxLayoutGap="24px"
fxLayoutGap.xs="16px"
>
<button
[disabled]="isLoading$ | async"
color="warn"
dsh-text-button
fxFlex="160px"
fxFlex.xs="none"
(click)="cancel()"
>
{{ t('cancel') }}
</button>
<button
*ngIf="!(reportCreated$ | async)"
[disabled]="isLoading$ | async"
color="accent"
dsh-button
fxFlex="160px"
fxFlex.xs="none"
(click)="create()"
>
{{ t('create') }}
</button>
<button
*ngIf="reportCreated$ | async"
color="accent"
dsh-button
fxFlex.xs="none"
(click)="toReports()"
>
{{ t('toReports') }}
</button>
</div>
</div>

View File

@ -1,53 +0,0 @@
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';
import { NotifyLogService } from '@vality/ng-core';
import { Payout } from '@vality/swag-anapi-v2';
import { CreatePayoutReportDialogService } from './create-payout-report-dialog.service';
@Component({
templateUrl: 'create-payout-report-dialog.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [CreatePayoutReportDialogService],
})
export class CreatePayoutReportDialogComponent implements OnInit {
isLoading$ = this.createPayoutReportDialogService.isLoading$;
reportCreated$ = this.createPayoutReportDialogService.reportCreated$;
constructor(
private dialogRef: MatDialogRef<CreatePayoutReportDialogComponent>,
private router: Router,
private createPayoutReportDialogService: CreatePayoutReportDialogService,
private transloco: TranslocoService,
private log: NotifyLogService,
@Inject(MAT_DIALOG_DATA) private data: { payout: Payout },
) {}
ngOnInit() {
this.createPayoutReportDialogService.errorOccurred$.subscribe((err) =>
this.log.error(
err,
this.transloco.selectTranslate(
'payouts.errors.createReportError',
null,
'payment-section',
),
),
);
}
create() {
this.createPayoutReportDialogService.create(this.data.payout);
}
toReports() {
void this.router.navigate([...this.router.url.split('/').slice(0, -1), 'reports']);
this.dialogRef.close();
}
cancel() {
this.dialogRef.close();
}
}

View File

@ -1,57 +0,0 @@
import { Injectable } from '@angular/core';
import { Payout } from '@vality/swag-anapi-v2';
import { BehaviorSubject, of, Subject } from 'rxjs';
import { catchError, filter, switchMap, tap } from 'rxjs/operators';
import { ReportsService } from '@dsh/app/api/anapi';
@Injectable()
export class CreatePayoutReportDialogService {
private create$: Subject<Payout> = new Subject();
private loading$ = new BehaviorSubject(false);
private created$ = new BehaviorSubject(false);
private error$ = new Subject<void>();
// eslint-disable-next-line @typescript-eslint/member-ordering
isLoading$ = this.loading$.asObservable();
// eslint-disable-next-line @typescript-eslint/member-ordering
errorOccurred$ = this.error$.asObservable();
// eslint-disable-next-line @typescript-eslint/member-ordering
reportCreated$ = this.created$.asObservable();
constructor(private reportsService: ReportsService) {
this.create$
.pipe(
tap(() => {
this.loading$.next(true);
this.created$.next(false);
}),
switchMap((payout) =>
this.reportsService
.createReport({
// TODO: fix
fromTime: payout.createdAt,
toTime: payout.createdAt,
reportType: 'paymentRegistry',
})
.pipe(
catchError((e) => {
console.error(e);
this.loading$.next(false);
this.error$.next();
return of('error');
}),
),
),
filter((result) => result !== 'error'),
)
.subscribe(() => {
this.loading$.next(false);
this.created$.next(true);
});
}
create(payout: Payout) {
this.create$.next(payout);
}
}

View File

@ -1,27 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { ButtonModule } from '@dsh/components/buttons';
import { CreatePayoutReportDialogComponent } from './create-payout-report-dialog.component';
import { CreatePayoutReportService } from './create-payout-report.service';
@NgModule({
imports: [
CommonModule,
TranslocoModule,
MatSnackBarModule,
MatDialogModule,
FlexLayoutModule,
ButtonModule,
MatInputModule,
],
declarations: [CreatePayoutReportDialogComponent],
providers: [CreatePayoutReportService],
})
export class CreatePayoutReportModule {}

View File

@ -1,40 +0,0 @@
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Payout } from '@vality/swag-anapi-v2';
import { Subject } from 'rxjs';
import { switchMap, takeUntil } from 'rxjs/operators';
import { CreatePayoutReportDialogComponent } from './create-payout-report-dialog.component';
@Injectable()
export class CreatePayoutReportService {
private destroy$: Subject<void> = new Subject();
private createPayoutReport$: Subject<Payout> = new Subject();
constructor(private dialog: MatDialog) {}
createPayoutReport(payout: Payout) {
this.createPayoutReport$.next(payout);
}
init() {
this.createPayoutReport$
.pipe(
takeUntil(this.destroy$),
switchMap((payout) =>
this.dialog
.open(CreatePayoutReportDialogComponent, {
data: {
payout,
},
})
.afterClosed(),
),
)
.subscribe();
}
destroy() {
this.destroy$.next();
}
}

View File

@ -1,2 +0,0 @@
export * from './create-payout-report.module';
export * from './create-payout-report.service';

View File

@ -1,81 +0,0 @@
<ng-container *transloco="let p; scope: 'payment-section'; read: 'paymentSection.payouts.payouts'">
<dsh-base-dialog [title]="p('title')" (cancel)="cancel()">
<div [formGroup]="form" fxLayout="column" fxLayoutGap="32px">
<div fxLayout="column" fxLayoutGap="20px">
<mat-form-field fxFill>
<mat-label>{{ p('shop') }}</mat-label>
<mat-select
formControlName="shopID"
required
(selectionChange)="onShopSelectionChange($event.value)"
>
<mat-option>
{{ p('any') }}
</mat-option>
<mat-option
*ngFor="let shopInfo of shopsInfo$ | async"
[value]="shopInfo.shopID"
>
{{ shopInfo.name }}
</mat-option>
</mat-select>
</mat-form-field>
<ng-container *ngIf="hasSelectedShop">
<ng-container *ngIf="!(isPayoutToolsLoading$ | async); else loading">
<ng-container *ngIf="hasPayoutTools$ | async; else noPayoutTools">
<mat-form-field fxFill>
<mat-label>{{ p('payoutTool') }}</mat-label>
<mat-select formControlName="payoutToolID">
<mat-option
*ngFor="let payoutTool of payoutTools$ | async"
[value]="payoutTool.id"
(onSelectionChange)="
onPayoutToolSelectionChange(payoutTool.currency)
"
>
{{
payoutTool.details.detailsType
| payoutToolDetailsType
| async
}}: {{ payoutTool.details.walletID }} ({{
payoutTool.currency
}})
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFill>
<mat-label>{{ p('amount') }}</mat-label>
<dsh-format-input
format="amount"
formControlName="amount"
required
></dsh-format-input>
</mat-form-field>
</ng-container>
<ng-template #noPayoutTools>
<div class="mat-body-1" fxFlexFill fxLayoutAlign="center">
{{ p('noPayoutTools') }}
</div>
</ng-template>
</ng-container>
<ng-template #loading>
<div>
<dsh-spinner></dsh-spinner>
</div>
</ng-template>
</ng-container>
</div>
</div>
<ng-container dshBaseDialogActions>
<button
[disabled]="form.invalid || !(hasPayoutTools$ | async)"
color="accent"
dsh-button
fxFlex.gt-sm="160px"
(click)="create(form.value)"
>
{{ p('createPayout') }}
</button>
</ng-container>
</dsh-base-dialog>
</ng-container>

View File

@ -1,90 +0,0 @@
import { Component, Inject, OnInit } from '@angular/core';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { TranslocoService } from '@ngneat/transloco';
import { NotifyLogService } from '@vality/ng-core';
import { of } from 'rxjs';
import { ShopsDataService } from '@dsh/app/shared';
import { amountValidator } from '@dsh/components/form-controls';
import { filterShopsByRealm, mapToShopInfo } from '../../operations/operators';
import { CreatePayoutDialogService } from './create-payout-dialog.service';
@Component({
selector: 'dsh-create-payout-dialog',
templateUrl: 'create-payout-dialog.component.html',
providers: [CreatePayoutDialogService],
})
export class CreatePayoutDialogComponent implements OnInit {
form = this.fb.group({
shopID: null,
});
hasSelectedShop = false;
currentPayoutToolCurrency: string;
shopsInfo$ = of(this.data.realm).pipe(
filterShopsByRealm(this.shopsDataService.shops$),
mapToShopInfo,
);
isPayoutToolsLoading$ = this.createPayoutDialogService.isLoading$;
payoutTools$ = this.createPayoutDialogService.payoutTools$;
hasPayoutTools$ = this.createPayoutDialogService.hasPayoutTools$;
constructor(
private dialogRef: MatDialogRef<CreatePayoutDialogComponent>,
private fb: UntypedFormBuilder,
private createPayoutDialogService: CreatePayoutDialogService,
private log: NotifyLogService,
private transloco: TranslocoService,
private shopsDataService: ShopsDataService,
@Inject(MAT_DIALOG_DATA) private data: { realm: string },
) {}
ngOnInit() {
this.createPayoutDialogService.payoutCreated$.subscribe(() =>
this.dialogRef.close('created'),
);
this.createPayoutDialogService.errorOccurred$.subscribe((err) =>
this.log.error(
err,
this.transloco.selectTranslate(
'payouts.errors.createError',
null,
'payment-section',
),
),
);
}
cancel() {
this.dialogRef.close();
}
create(formValue: { shopID: string; payoutToolID: string; amount: number }) {
this.createPayoutDialogService.createPayout(formValue);
}
onShopSelectionChange(shopID: string) {
this.hasSelectedShop = !!shopID;
if (this.hasSelectedShop) {
this.createPayoutDialogService.changeShopID(shopID);
this.form.addControl('payoutToolID', this.fb.control('', [Validators.required]));
this.form.addControl(
'amount',
this.fb.control('', [Validators.required, amountValidator, Validators.min(1)]),
);
} else {
this.form.removeControl('payoutToolID');
this.form.removeControl('amount');
}
}
onPayoutToolSelectionChange(payoutToolCurrency: string) {
this.currentPayoutToolCurrency = payoutToolCurrency;
}
}

View File

@ -1,92 +0,0 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, forkJoin, merge, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, switchMap, take, tap } from 'rxjs/operators';
import { PayoutsService } from '@dsh/app/api/payments';
import { ShopsDataService } from '@dsh/app/shared';
import { toPayoutParams } from './to-payout-params';
@Injectable()
export class CreatePayoutDialogService {
private currentShopID$ = new Subject<string>();
private create$ = new Subject<{ shopID: string; payoutToolID: string; amount: number }>();
private loading$ = new BehaviorSubject(false);
private error$ = new Subject<void>();
private created$ = new Subject();
// eslint-disable-next-line @typescript-eslint/member-ordering
isLoading$ = this.loading$.asObservable();
// eslint-disable-next-line @typescript-eslint/member-ordering
errorOccurred$ = this.error$.asObservable();
// eslint-disable-next-line @typescript-eslint/member-ordering
payoutCreated$ = this.created$.asObservable();
// eslint-disable-next-line @typescript-eslint/member-ordering
payoutTools$ = this.currentShopID$.pipe(
switchMap((shopID) =>
this.shopsDataService.shops$.pipe(
map((shops) => shops.find(({ id }) => id === shopID)),
),
),
switchMap(({ contractID }) => this.payoutsService.getPayoutToolsForParty({ contractID })),
map((tools) =>
tools.filter((tool) => tool.details.detailsType === 'PayoutToolDetailsWalletInfo'),
),
shareReplay(1),
);
// eslint-disable-next-line @typescript-eslint/member-ordering
hasPayoutTools$ = this.payoutTools$.pipe(
map((tools) => !!tools.length),
shareReplay(1),
);
constructor(
private shopsDataService: ShopsDataService,
private payoutsService: PayoutsService,
) {
merge(this.payoutTools$, this.hasPayoutTools$).subscribe();
this.create$
.pipe(
tap(() => {
this.loading$.next(true);
this.created$.next(false);
}),
switchMap((params) =>
forkJoin([
of(params),
this.shopsDataService.shops$.pipe(
take(1),
map((shops) => shops.find(({ id }) => id === params.shopID)?.currency),
),
]),
),
map(([params, currency]) => toPayoutParams(params, currency)),
switchMap((payoutParams) =>
this.payoutsService.createPayout({ payoutParams }).pipe(
catchError((e) => {
console.error(e);
this.loading$.next(false);
this.error$.next();
return of('error');
}),
),
),
filter((result) => result !== 'error'),
)
.subscribe(() => {
this.loading$.next(false);
this.created$.next(true);
});
}
changeShopID(id: string) {
this.currentShopID$.next(id);
}
createPayout(formValue: { shopID: string; payoutToolID: string; amount: number }) {
this.create$.next(formValue);
}
}

View File

@ -1,37 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { BaseDialogModule } from '@dsh/app/shared/components/dialog/base-dialog';
import { ApiModelTypesModule } from '@dsh/app/shared/pipes';
import { ButtonModule } from '@dsh/components/buttons';
import { FormatInputModule } from '@dsh/components/form-controls';
import { SpinnerModule } from '@dsh/components/indicators';
import { CreatePayoutDialogComponent } from './create-payout-dialog.component';
@NgModule({
imports: [
CommonModule,
TranslocoModule,
MatSnackBarModule,
MatDialogModule,
FlexLayoutModule,
ButtonModule,
MatInputModule,
ReactiveFormsModule,
MatSelectModule,
SpinnerModule,
FormatInputModule,
ApiModelTypesModule,
BaseDialogModule,
],
declarations: [CreatePayoutDialogComponent],
})
export class CreatePayoutModule {}

View File

@ -1 +0,0 @@
export * from './create-payout.module';

View File

@ -1,16 +0,0 @@
import { toMinor } from '@vality/ng-core';
import { PayoutParams } from '@vality/swag-payments';
import { v4 as uuid } from 'uuid';
export const toPayoutParams = (
{ shopID, payoutToolID, amount }: { shopID: string; payoutToolID: string; amount: number },
currency: string,
): PayoutParams => {
return {
id: uuid(),
shopID,
payoutToolID,
amount: toMinor(amount, currency),
currency,
};
};

View File

@ -1,34 +0,0 @@
import { Injectable } from '@angular/core';
import { Payout } from '@vality/swag-anapi-v2';
import { Observable } from 'rxjs';
import { shareReplay } from 'rxjs/operators';
import { SearchService } from '@dsh/app/api/anapi';
import { mapToTimestamp } from '@dsh/app/custom-operators';
import { PartialFetcher } from '@dsh/app/shared';
import { SearchParams } from './types/search-params';
@Injectable()
export class FetchPayoutsService extends PartialFetcher<Payout, SearchParams> {
isLoading$: Observable<boolean> = this.doAction$.pipe(shareReplay(1));
lastUpdated$: Observable<string> = this.searchResult$.pipe(mapToTimestamp, shareReplay(1));
constructor(private searchService: SearchService) {
super();
}
protected fetch(
{ fromTime, toTime, realm, ...restParams }: SearchParams,
continuationToken: string,
) {
return this.searchService.searchPayouts({
...restParams,
fromTime,
toTime,
limit: 10,
paymentInstitutionRealm: realm,
continuationToken,
});
}
}

View File

@ -1,2 +0,0 @@
export * from './payouts.module';
export * from './payouts.component';

View File

@ -1 +0,0 @@
export * from './payouts-details.module';

View File

@ -1 +0,0 @@
export * from './payout-actions.component';

View File

@ -1,12 +0,0 @@
<div
*transloco="let t; scope: 'payment-section'; read: 'paymentSection.payouts.panel'"
fxLayout="column"
fxLayoutGap="24px"
>
<div class="dsh-title">{{ t('actions') }}</div>
<div>
<button color="accent" dsh-text-button (click)="createReport.emit()">
{{ t('createReport') }}
</button>
</div>
</div>

View File

@ -1,10 +0,0 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'dsh-payout-actions',
templateUrl: 'payout-actions.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutActionsComponent {
@Output() createReport: EventEmitter<void> = new EventEmitter<void>();
}

View File

@ -1 +0,0 @@
export * from './payout-main-info.component';

View File

@ -1,13 +0,0 @@
<div
*transloco="let p; scope: 'payment-section'; read: 'paymentSection.payouts.panel'"
gdColumns="1fr"
gdColumns.gt-sm="1fr 1fr 1fr"
gdGap="24px"
>
<div class="dsh-headline">
{{ payout?.amount | amountCurrency: payout?.currency }}
</div>
<dsh-details-item [title]="p('shop')" gdRow="2fr">
{{ payout?.shopID | shopDetails }}
</dsh-details-item>
</div>

View File

@ -1,11 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Payout } from '@vality/swag-anapi-v2';
@Component({
selector: 'dsh-payout-main-info',
templateUrl: 'payout-main-info.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutMainInfoComponent {
@Input() payout: Payout;
}

View File

@ -1,13 +0,0 @@
<div fxLayout="column" fxLayoutGap="24px">
<dsh-payout-main-info [payout]="payout"></dsh-payout-main-info>
<mat-divider></mat-divider>
<div class="dsh-title">
{{ payout?.payoutToolDetails?.detailsType | payoutToolDetailsType | async }}
</div>
<dsh-payout-tool-details
[payoutToolDetails]="payout?.payoutToolDetails"
></dsh-payout-tool-details>
<!-- TODO fix create report fromTime toTime-->
<!-- <mat-divider></mat-divider>-->
<!-- <dsh-payout-actions (createReport)="createReport()"></dsh-payout-actions>-->
</div>

View File

@ -1,16 +0,0 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { Payout } from '@vality/swag-anapi-v2';
@Component({
selector: 'dsh-payouts-details',
templateUrl: 'payouts-details.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutsDetailsComponent {
@Input() payout: Payout;
@Output() createPayoutReport: EventEmitter<Payout> = new EventEmitter<Payout>();
createReport(): void {
this.createPayoutReport.emit(this.payout);
}
}

View File

@ -1,44 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { PayoutToolDetailsModule } from '@dsh/app/shared/components';
import {
ApiModelRefsModule,
ApiModelTypesModule,
AmountCurrencyModule,
} from '@dsh/app/shared/pipes';
import { ButtonModule } from '@dsh/components/buttons';
import { IndicatorsModule } from '@dsh/components/indicators';
import { LayoutModule } from '@dsh/components/layout';
import { CreatePayoutReportModule } from '../create-payout-report';
import { PayoutActionsComponent } from './payout-actions';
import { PayoutMainInfoComponent } from './payout-main-info';
import { PayoutsDetailsComponent } from './payouts-details.component';
@NgModule({
imports: [
TranslocoModule,
LayoutModule,
ButtonModule,
FlexLayoutModule,
CommonModule,
MatSnackBarModule,
MatDividerModule,
IndicatorsModule,
ApiModelRefsModule,
CreatePayoutReportModule,
PayoutToolDetailsModule,
ApiModelTypesModule,
AmountCurrencyModule,
],
declarations: [PayoutsDetailsComponent, PayoutActionsComponent, PayoutMainInfoComponent],
exports: [PayoutsDetailsComponent],
})
export class PayoutsDetailsModule {}

View File

@ -1,27 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Payout } from '@vality/swag-anapi-v2';
import { Observable } from 'rxjs';
import { ExpandedIdManager } from '@dsh/app/shared/services';
import { FetchPayoutsService } from './fetch-payouts.service';
@Injectable()
export class PayoutsExpandedIdManager extends ExpandedIdManager<Payout> {
constructor(
protected route: ActivatedRoute,
protected router: Router,
private fetchPayoutsService: FetchPayoutsService,
) {
super(route, router);
}
protected fragmentNotFound(): void {
this.fetchPayoutsService.fetchMore();
}
protected get dataSet$(): Observable<Payout[]> {
return this.fetchPayoutsService.searchResult$;
}
}

View File

@ -1,2 +0,0 @@
export * from './payouts-list.component';
export * from './payouts-list.module';

View File

@ -1 +0,0 @@
export * from './payout-row-header.component';

View File

@ -1,12 +0,0 @@
<dsh-row
*transloco="let t; scope: 'payment-section'; read: 'paymentSection.payouts.headerRow'"
gdAlignColumns="center center"
gdColumns="repeat(2, 1fr)"
gdColumns.gt-sm="repeat(4, 1fr)"
gdGap="24px"
>
<dsh-row-header-label>{{ t('createdAt') }}</dsh-row-header-label>
<dsh-row-header-label>{{ t('amount') }}</dsh-row-header-label>
<dsh-row-header-label fxHide.lt-md>{{ t('payoutTool') }}</dsh-row-header-label>
<dsh-row-header-label fxHide.lt-md> {{ t('shop') }} </dsh-row-header-label>
</dsh-row>

View File

@ -1,8 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'dsh-payout-row-header',
templateUrl: 'payout-row-header.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutRowHeaderComponent {}

View File

@ -1 +0,0 @@
export * from './payout-row.component';

View File

@ -1,19 +0,0 @@
<dsh-row
gdAlignColumns="center center"
gdColumns="repeat(2, 1fr)"
gdColumns.gt-sm="repeat(4, 1fr)"
gdGap="24px"
>
<dsh-row-label>
{{ payout.createdAt | date: 'dd MMMM yyyy, HH:mm' }}
</dsh-row-label>
<dsh-row-label fxHide.lt-md>
{{ payout.amount | amountCurrency: payout.currency }}
</dsh-row-label>
<dsh-row-label>{{
payout?.payoutToolDetails?.detailsType | payoutToolDetailsType | async
}}</dsh-row-label>
<dsh-row-label fxHide.lt-md>
{{ payout.shopID | shopDetails }}
</dsh-row-label>
</dsh-row>

View File

@ -1,11 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Payout } from '@vality/swag-anapi-v2';
@Component({
selector: 'dsh-payout-row',
templateUrl: 'payout-row.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutRowComponent {
@Input() payout: Payout;
}

View File

@ -1,31 +0,0 @@
<div fxLayout="column" fxLayoutGap="16px">
<dsh-last-updated [lastUpdated]="lastUpdated" (update)="refreshData.emit()"></dsh-last-updated>
<dsh-payout-row-header></dsh-payout-row-header>
<dsh-accordion
[expanded]="expandedId"
fxLayout="column"
fxLayoutGap="16px"
(expandedChange)="expandedIdChange.emit($event)"
>
<dsh-accordion-item #accordionItem *ngFor="let payout of payouts">
<dsh-payout-row [payout]="payout"></dsh-payout-row>
<dsh-accordion-item-content>
<dsh-card fxLayout="column" fxLayoutGap="32px">
<dsh-accordion-item-content-header
*transloco="
let t;
scope: 'payment-section';
read: 'paymentSection.payouts.panel'
"
(collapse)="accordionItem.collapse($event)"
>{{ t('payoutID', { num: payout.id }) }}</dsh-accordion-item-content-header
>
<dsh-payouts-details
[payout]="payout"
(createPayoutReport)="createPayoutReport($event)"
></dsh-payouts-details>
</dsh-card>
</dsh-accordion-item-content>
</dsh-accordion-item>
</dsh-accordion>
</div>

View File

@ -1,30 +0,0 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { Payout } from '@vality/swag-anapi-v2';
import { CreatePayoutReportService } from '../create-payout-report';
@Component({
selector: 'dsh-payouts-list',
templateUrl: 'payouts-list.component.html',
})
export class PayoutsListComponent implements OnInit, OnDestroy {
@Input() payouts: Payout[];
@Input() expandedId: number;
@Input() lastUpdated: string;
@Output() expandedIdChange: EventEmitter<number> = new EventEmitter();
@Output() refreshData: EventEmitter<void> = new EventEmitter();
constructor(private createPayoutReportService: CreatePayoutReportService) {}
createPayoutReport(payout: Payout) {
this.createPayoutReportService.createPayoutReport(payout);
}
ngOnInit() {
this.createPayoutReportService.init();
}
ngOnDestroy(): void {
this.createPayoutReportService.destroy();
}
}

View File

@ -1,38 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import {
ApiModelRefsModule,
ApiModelTypesModule,
AmountCurrencyModule,
} from '@dsh/app/shared/pipes';
import { IndicatorsModule } from '@dsh/components/indicators';
import { LayoutModule } from '@dsh/components/layout';
import { PayoutsDetailsModule } from '../payouts-details';
import { PayoutRowComponent } from './payout-row';
import { PayoutRowHeaderComponent } from './payout-row-header';
import { PayoutsListComponent } from './payouts-list.component';
@NgModule({
imports: [
TranslocoModule,
MatSnackBarModule,
LayoutModule,
FlexLayoutModule,
CommonModule,
IndicatorsModule,
PayoutsDetailsModule,
ApiModelTypesModule,
ApiModelRefsModule,
AmountCurrencyModule,
],
declarations: [PayoutsListComponent, PayoutRowHeaderComponent, PayoutRowComponent],
exports: [PayoutsListComponent],
})
export class PayoutsListModule {}

View File

@ -1,17 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PayoutsComponent } from './payouts.component';
const ROUTES: Routes = [
{
path: '',
component: PayoutsComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(ROUTES)],
exports: [RouterModule],
})
export class PayoutsRoutingModule {}

View File

@ -1 +0,0 @@
export * from './payouts-search-filters.module';

View File

@ -1,8 +0,0 @@
<dsh-filters-group [formGroup]="form">
<dsh-date-range-filter
[default]="defaultDateRange"
[maxDate]="defaultDateRange.end"
formControlName="dateRange"
></dsh-date-range-filter>
<dsh-shops-filter [shops]="shops" formControlName="shopIDs"></dsh-shops-filter>
</dsh-filters-group>

View File

@ -1,56 +0,0 @@
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
} from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { ComponentChanges } from '@vality/ng-core';
import { Shop } from '@vality/swag-payments';
import {
createDateRangeWithPreset,
DateRangeWithPreset,
Preset,
} from '@dsh/components/date-range-filter';
import { getFormValueChanges } from '@dsh/utils';
import { SearchParams } from '../types/search-params';
export interface Filters {
shopIDs: Shop['id'][];
dateRange: DateRangeWithPreset;
}
@UntilDestroy()
@Component({
selector: 'dsh-payouts-search-filters',
templateUrl: 'payouts-search-filters.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutsSearchFiltersComponent implements OnInit, OnChanges {
@Input() initParams: SearchParams;
@Input() shops: Shop[];
@Output() searchParamsChanges = new EventEmitter<Filters>();
defaultDateRange = createDateRangeWithPreset(Preset.Last90days);
form = this.fb.group<Filters>({ shopIDs: null, dateRange: this.defaultDateRange });
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
getFormValueChanges(this.form)
.pipe(untilDestroyed(this))
.subscribe((filters) => this.searchParamsChanges.next(filters as unknown as Filters));
}
ngOnChanges({ initParams }: ComponentChanges<PayoutsSearchFiltersComponent>): void {
if (initParams?.firstChange && initParams.currentValue) {
this.form.patchValue(initParams.currentValue as unknown);
}
}
}

View File

@ -1,24 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { FlexLayoutModule } from 'ng-flex-layout';
import { ShopsFilterModule } from '@dsh/app/shared/components/filters/shops-filter';
import { DateRangeFilterModule } from '@dsh/components/date-range-filter';
import { FiltersGroupModule } from '@dsh/components/filters-group';
import { PayoutsSearchFiltersComponent } from './payouts-search-filters.component';
@NgModule({
imports: [
CommonModule,
FlexLayoutModule,
ShopsFilterModule,
ReactiveFormsModule,
FiltersGroupModule,
DateRangeFilterModule,
],
exports: [PayoutsSearchFiltersComponent],
declarations: [PayoutsSearchFiltersComponent],
})
export class PayoutsSearchFiltersModule {}

View File

@ -1,42 +0,0 @@
<div
*transloco="let t; scope: 'payment-section'; read: 'paymentSection.payouts'"
fxLayout="column"
fxLayoutGap="32px"
>
<div
gdAlignColumns="center center"
gdAlignRows="space-between start"
gdColumns="1fr"
gdColumns.gt-sm="repeat(2, auto)"
gdGap="32px"
>
<button color="accent" dsh-button (click)="createPayout()">
{{ t('payouts.createPayout') }}
</button>
<dsh-payouts-search-filters
[initParams]="params$ | async"
[shops]="shops$ | async"
gdRow.gt-sm="1"
(searchParamsChanges)="searchParamsChanges($event)"
></dsh-payouts-search-filters>
</div>
<div fxLayout="column" fxLayoutGap="16px">
<dsh-payouts-list
[expandedId]="expandedId$ | async"
[lastUpdated]="lastUpdated$ | async"
[payouts]="payouts$ | async"
(expandedIdChange)="expandedIdChange($event)"
(refreshData)="refresh()"
></dsh-payouts-list>
<dsh-show-more-panel
*ngIf="hasMore$ | async"
[isLoading]="isLoading$ | async"
(showMore)="fetchMore()"
></dsh-show-more-panel>
</div>
<dsh-empty-search-result
*ngIf="!(fetchErrors$ | async) && (payouts$ | async)?.length === 0"
></dsh-empty-search-result>
<dsh-spinner *ngIf="isLoading$ | async" fxLayoutAlign="center"></dsh-spinner>
</div>
<dsh-scroll-up></dsh-scroll-up>

View File

@ -1,109 +0,0 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { TranslocoService } from '@ngneat/transloco';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { NotifyLogService, QueryParamsService } from '@vality/ng-core';
import { Subject } from 'rxjs';
import { filter, first, switchMap, switchMapTo } from 'rxjs/operators';
import { RealmMixService, PaymentInstitutionRealmService, RealmShopsService } from '../services';
import { CreatePayoutDialogComponent } from './create-payout/create-payout-dialog.component';
import { FetchPayoutsService } from './fetch-payouts.service';
import { PayoutsExpandedIdManager } from './payouts-expanded-id-manager.service';
import { Filters } from './payouts-search-filters/payouts-search-filters.component';
import { SearchParams } from './types/search-params';
@UntilDestroy()
@Component({
selector: 'dsh-payouts',
templateUrl: 'payouts.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [FetchPayoutsService, PayoutsExpandedIdManager, RealmMixService],
})
export class PayoutsComponent implements OnInit {
payouts$ = this.fetchPayoutsService.searchResult$;
isLoading$ = this.fetchPayoutsService.isLoading$;
hasMore$ = this.fetchPayoutsService.hasMore$;
lastUpdated$ = this.fetchPayoutsService.lastUpdated$;
expandedId$ = this.payoutsExpandedIdManager.expandedId$;
params$ = this.qp.params$;
fetchErrors$ = this.fetchPayoutsService.errors$;
shops$ = this.realmShopsService.shops$;
private createPayout$ = new Subject<void>();
constructor(
private fetchPayoutsService: FetchPayoutsService,
private payoutsExpandedIdManager: PayoutsExpandedIdManager,
private log: NotifyLogService,
private transloco: TranslocoService,
private realmService: PaymentInstitutionRealmService,
private qp: QueryParamsService<Filters>,
private dialog: MatDialog,
private realmShopsService: RealmShopsService,
private realmMixService: RealmMixService<SearchParams>,
) {}
ngOnInit(): void {
this.fetchPayoutsService.errors$
.pipe(untilDestroyed(this))
.subscribe((err) =>
this.log.error(
err,
this.transloco.selectTranslate('shared.httpError', null, 'components'),
),
);
this.realmMixService.mixedValue$
.pipe(untilDestroyed(this))
.subscribe((v) => this.fetchPayoutsService.search(v));
this.createPayout$
.pipe(
switchMapTo(this.realmService.realm$.pipe(first())),
switchMap((realm) =>
this.dialog
.open(CreatePayoutDialogComponent, { data: { realm } })
.afterClosed()
.pipe(filter((r) => r === 'created')),
),
untilDestroyed(this),
)
.subscribe(() => {
this.log.success(
this.transloco.selectTranslate(
'payouts.payouts.created',
null,
'payment-section',
),
);
this.refresh();
});
}
createPayout(): void {
this.createPayout$.next();
}
searchParamsChanges(p: Filters): void {
void this.qp.set(p);
const { dateRange, ...otherParams } = p;
this.realmMixService.mix({
fromTime: dateRange.start.clone().utc().format(),
toTime: dateRange.end.clone().utc().format(),
realm: null,
...otherParams,
});
}
expandedIdChange(id: number): void {
this.payoutsExpandedIdManager.expandedIdChange(id);
}
fetchMore(): void {
this.fetchPayoutsService.fetchMore();
}
refresh(): void {
this.fetchPayoutsService.refresh();
}
}

View File

@ -1,56 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatCommonModule, MatOptionModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { ApiModelTypesModule } from '@dsh/app/shared/pipes';
import { ButtonModule } from '@dsh/components/buttons';
import { DateRangeFilterModule } from '@dsh/components/date-range-filter';
import { EmptySearchResultModule } from '@dsh/components/empty-search-result';
import { FormatInputModule } from '@dsh/components/form-controls';
import { SpinnerModule } from '@dsh/components/indicators';
import { LayoutModule } from '@dsh/components/layout';
import { ScrollUpModule } from '@dsh/components/navigation';
import { ShowMorePanelModule } from '@dsh/components/show-more-panel';
import { CreatePayoutModule } from './create-payout';
import { PayoutsListModule } from './payouts-list';
import { PayoutsRoutingModule } from './payouts-routing.module';
import { PayoutsSearchFiltersModule } from './payouts-search-filters';
import { PayoutsComponent } from './payouts.component';
@NgModule({
imports: [
PayoutsRoutingModule,
MatCommonModule,
FlexLayoutModule,
ButtonModule,
TranslocoModule,
ReactiveFormsModule,
FormsModule,
LayoutModule,
MatFormFieldModule,
MatOptionModule,
CommonModule,
MatSelectModule,
MatInputModule,
SpinnerModule,
ScrollUpModule,
ShowMorePanelModule,
FormatInputModule,
ApiModelTypesModule,
PayoutsSearchFiltersModule,
PayoutsListModule,
EmptySearchResultModule,
CreatePayoutModule,
DateRangeFilterModule,
],
declarations: [PayoutsComponent],
exports: [PayoutsComponent],
})
export class PayoutsModule {}

View File

@ -1,10 +0,0 @@
import { PaymentInstitution } from '@vality/swag-payments';
import RealmEnum = PaymentInstitution.RealmEnum;
export interface SearchParams {
fromTime: string;
toTime: string;
realm: RealmEnum;
shopIDs?: string[];
}

View File

@ -1,89 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { PayoutTool } from '@vality/swag-payments';
import { cold } from 'jasmine-marbles';
import { of } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { instance, mock, when } from 'ts-mockito';
import { PayoutsService } from '@dsh/app/api/payouts';
import { ShopPayoutToolDetailsService } from './shop-payout-tool-details.service';
describe('ShopPayoutToolDetailsService', () => {
let service: ShopPayoutToolDetailsService;
let mockPayoutsService: PayoutsService;
beforeEach(() => {
mockPayoutsService = mock(PayoutsService);
});
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ShopPayoutToolDetailsService,
{
provide: PayoutsService,
useFactory: () => instance(mockPayoutsService),
},
],
});
service = TestBed.inject(ShopPayoutToolDetailsService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('getContract', () => {
it('should tick contract value if contracts came with no errors', () => {
// can't test it with cold/hot marbles cause it's an subject
service.shopPayoutTool$.pipe(take(1)).subscribe((data: PayoutTool) => {
expect(data).toEqual({
currency: 'USD',
details: {
detailsType: 'any',
},
id: 'my_id',
});
});
when(mockPayoutsService.getPayoutToolByID('contract_id', 'payout_tool_id')).thenReturn(
of({
currency: 'USD',
details: {
detailsType: 'any',
},
id: 'my_id',
}),
);
service.requestPayoutTool({
contractID: 'contract_id',
payoutToolID: 'payout_tool_id',
});
expect().nothing();
});
it('should tick errors value if contracts came with errors', () => {
when(mockPayoutsService.getPayoutToolByID('contract_id', 'payout_tool_id')).thenReturn(
of(null).pipe(
map(() => {
throw new Error(`[TEST_ERROR]: Error in observable`);
}),
),
);
service.requestPayoutTool({
contractID: 'contract_id',
payoutToolID: 'payout_tool_id',
});
expect(service.errorOccurred$).toBeObservable(
cold('a', {
a: true,
}),
);
});
});
});

View File

@ -1,60 +0,0 @@
import { Injectable } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { PayoutTool } from '@vality/swag-payments';
import { BehaviorSubject, defer, Observable, of, ReplaySubject, Subject } from 'rxjs';
import { catchError, distinctUntilChanged, filter, switchMap, tap } from 'rxjs/operators';
import { PayoutsService } from '@dsh/app/api/payments';
import { PayoutToolParams } from '../../shops-list/shop-details/types/payout-tool-params';
@UntilDestroy()
@Injectable()
export class ShopPayoutToolDetailsService {
shopPayoutTool$: Observable<PayoutTool>;
errorOccurred$: Observable<boolean>;
isLoading$ = defer(() => this._isLoading$.asObservable());
private getPayoutTool$ = new Subject<PayoutToolParams>();
private error$ = new BehaviorSubject<boolean>(false);
private payoutTool$ = new ReplaySubject<PayoutTool>(1);
private _isLoading$ = new BehaviorSubject<boolean>(false);
constructor(private payoutsService: PayoutsService) {
this.shopPayoutTool$ = this.payoutTool$.asObservable();
this.errorOccurred$ = this.error$.asObservable();
this.getPayoutTool$
.pipe(
tap(() => this.error$.next(false)),
distinctUntilChanged(),
tap(() => this._isLoading$.next(true)),
switchMap((payoutToolParams) =>
payoutToolParams
? this.payoutsService
.getPayoutToolByIDForParty({
contractID: payoutToolParams.contractID,
payoutToolID: payoutToolParams.payoutToolID,
})
.pipe(
catchError((e) => {
console.error(e);
this.error$.next(true);
return of('error');
}),
)
: of(null),
),
tap(() => this._isLoading$.next(false)),
filter((result) => result !== 'error'),
untilDestroyed(this),
)
.subscribe((payoutTool: PayoutTool) => {
this.payoutTool$.next(payoutTool);
});
}
requestPayoutTool(params: PayoutToolParams): void {
this.getPayoutTool$.next(params);
}
}

View File

@ -1,12 +0,0 @@
<div
*transloco="let t; scope: 'payment-section'; read: 'paymentSection.shops.shopPayoutTool'"
fxLayout="column"
fxLayoutGap="24px"
>
<div class="dsh-title">{{ t('title') }}</div>
<dsh-payout-tool
*ngIf="payoutTool$ | async as payoutTool"
[payoutTool]="payoutTool"
></dsh-payout-tool>
<div *ngIf="errorOccurred$ | async" class="dsh-body-1">{{ t('error') }}</div>
</div>

View File

@ -1,78 +0,0 @@
import { ChangeDetectionStrategy } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { deepEqual, instance, mock, verify, when } from 'ts-mockito';
import { getTranslocoModule } from '@dsh/app/shared/tests/get-transloco-module';
import { ShopPayoutToolDetailsService } from '../../../../services/shop-payout-tool-details/shop-payout-tool-details.service';
import { ShopPayoutToolDetailsComponent } from './shop-payout-tool-details.component';
describe('ShopPayoutToolDetailsComponent', () => {
let component: ShopPayoutToolDetailsComponent;
let fixture: ComponentFixture<ShopPayoutToolDetailsComponent>;
let mockPayoutsService: ShopPayoutToolDetailsService;
beforeEach(() => {
mockPayoutsService = mock(ShopPayoutToolDetailsService);
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [getTranslocoModule()],
declarations: [ShopPayoutToolDetailsComponent],
providers: [
{
provide: ShopPayoutToolDetailsService,
useFactory: () => instance(mockPayoutsService),
},
],
})
.overrideComponent(ShopPayoutToolDetailsComponent, {
set: {
providers: [],
changeDetection: ChangeDetectionStrategy.Default,
},
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ShopPayoutToolDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('contractID', () => {
it('should call getContract on id change', () => {
when(
mockPayoutsService.requestPayoutTool(
deepEqual({
contractID: 'my_contract_id',
payoutToolID: 'my_payout_tool_id',
}),
),
).thenReturn();
component.payoutToolParams = {
contractID: 'my_contract_id',
payoutToolID: 'my_payout_tool_id',
};
verify(
mockPayoutsService.requestPayoutTool(
deepEqual({
contractID: 'my_contract_id',
payoutToolID: 'my_payout_tool_id',
}),
),
).once();
expect().nothing();
});
});
});

View File

@ -1,22 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ShopPayoutToolDetailsService } from '../../../../services/shop-payout-tool-details/shop-payout-tool-details.service';
import { PayoutToolParams } from '../../types/payout-tool-params';
@Component({
selector: 'dsh-shop-payout-tool-details',
templateUrl: 'shop-payout-tool-details.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ShopPayoutToolDetailsService],
})
export class ShopPayoutToolDetailsComponent {
@Input()
set payoutToolParams(p: PayoutToolParams) {
this.shopPayoutToolDetailsService.requestPayoutTool(p);
}
payoutTool$ = this.shopPayoutToolDetailsService.shopPayoutTool$;
errorOccurred$ = this.shopPayoutToolDetailsService.errorOccurred$;
constructor(private shopPayoutToolDetailsService: ShopPayoutToolDetailsService) {}
}

View File

@ -4,10 +4,6 @@
<dsh-shop-id [id]="shop.id"></dsh-shop-id> <dsh-shop-id [id]="shop.id"></dsh-shop-id>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<dsh-shop-contract-details [contractID]="shop.contractID"></dsh-shop-contract-details> <dsh-shop-contract-details [contractID]="shop.contractID"></dsh-shop-contract-details>
<mat-divider></mat-divider>
<dsh-shop-payout-tool-details
[payoutToolParams]="{ contractID: shop.contractID, payoutToolID: shop.payoutToolID }"
></dsh-shop-payout-tool-details>
<ng-container *ngIf="!shop.isBlocked"> <ng-container *ngIf="!shop.isBlocked">
<mat-divider></mat-divider> <mat-divider></mat-divider>
<dsh-shop-actions [shop]="shop" (updateData)="requestUpdateData()"></dsh-shop-actions> <dsh-shop-actions [shop]="shop" (updateData)="requestUpdateData()"></dsh-shop-actions>

View File

@ -1,142 +0,0 @@
import { ClipboardModule } from '@angular/cdk/clipboard';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialogModule } from '@angular/material/dialog';
import { MatDividerModule } from '@angular/material/divider';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TranslocoTestingModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { of } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';
import { CategoriesModule } from '@dsh/app/api/categories';
import { ContractsModule } from '@dsh/app/api/contracts';
import { ContractDetailsModule, PayoutToolModule } from '@dsh/app/shared/components';
import { ShopContractDetailsService } from '@dsh/app/shared/services/shop-contract-details';
import { ButtonModule } from '@dsh/components/buttons';
import { DetailsItemModule } from '@dsh/components/layout';
import { ShopPayoutToolDetailsService } from '../../services/shop-payout-tool-details/shop-payout-tool-details.service';
import { generateMockShopItem } from '../../tests/generate-shop-item';
import { ShopBalanceModule } from '../shop-balance';
import { ShopActionsComponent } from './components/shop-actions/shop-actions.component';
import { ShopContractDetailsComponent } from './components/shop-contract-details/shop-contract-details.component';
import { ShopIdComponent } from './components/shop-id/shop-id.component';
import { ShopInfoComponent } from './components/shop-info/shop-info.component';
import { ShopPayoutToolDetailsComponent } from './components/shop-payout-tool-details/shop-payout-tool-details.component';
import { CategoryService } from './services/category/category.service';
import { ShopActionsService } from './services/shop-actions/shop-actions.service';
import { ShopDetailsComponent } from './shop-details.component';
import { ShopActionResult } from './types/shop-action-result';
describe('ShopDetailsComponent', () => {
let component: ShopDetailsComponent;
let fixture: ComponentFixture<ShopDetailsComponent>;
let mockCategoryService: CategoryService;
let mockContractsService: ShopContractDetailsService;
let mockPayoutsService: ShopPayoutToolDetailsService;
let mockActionsService: ShopActionsService;
beforeEach(() => {
mockCategoryService = mock(CategoryService);
mockContractsService = mock(ShopContractDetailsService);
mockPayoutsService = mock(ShopPayoutToolDetailsService);
mockActionsService = mock(ShopActionsService);
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
FlexLayoutModule,
ButtonModule,
TranslocoTestingModule.withLangs({
en: {},
}),
MatDividerModule,
DetailsItemModule,
ClipboardModule,
ContractDetailsModule,
PayoutToolModule,
ShopBalanceModule,
CategoriesModule,
ContractsModule,
MatSnackBarModule,
MatDialogModule,
],
declarations: [
ShopDetailsComponent,
ShopContractDetailsComponent,
ShopPayoutToolDetailsComponent,
ShopActionsComponent,
ShopIdComponent,
ShopInfoComponent,
],
providers: [
{
provide: CategoryService,
useFactory: () => instance(mockCategoryService),
},
{
provide: ShopContractDetailsService,
useFactory: () => instance(mockContractsService),
},
{
provide: ShopPayoutToolDetailsService,
useFactory: () => instance(mockPayoutsService),
},
{
provide: ShopActionsService,
useValue: mockActionsService,
},
],
})
.overrideComponent(ShopActionsComponent, {
set: {
providers: [],
},
})
.overrideComponent(ShopContractDetailsComponent, {
set: {
providers: [],
},
})
.overrideComponent(ShopPayoutToolDetailsComponent, {
set: {
providers: [],
},
})
.compileComponents();
});
beforeEach(() => {
when(mockCategoryService.category$).thenReturn(of(undefined));
when(mockContractsService.shopContract$).thenReturn(of(null));
when(mockContractsService.errorOccurred$).thenReturn(of(false));
when(mockPayoutsService.shopPayoutTool$).thenReturn(of(null));
when(mockPayoutsService.errorOccurred$).thenReturn(of(false));
when(mockActionsService.suspend).thenReturn(() => of(ShopActionResult.Success));
when(mockActionsService.activate).thenReturn(() => of(ShopActionResult.Success));
});
beforeEach(() => {
fixture = TestBed.createComponent(ShopDetailsComponent);
component = fixture.componentInstance;
component.shop = generateMockShopItem(1);
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('requestUpdateData', () => {
it('should emit updateData', () => {
const spyOnUpdateData = spyOn(component.updateData, 'emit').and.callThrough();
component.requestUpdateData();
expect(spyOnUpdateData).toHaveBeenCalledTimes(1);
});
});
});

View File

@ -7,7 +7,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TranslocoModule } from '@ngneat/transloco'; import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout'; import { FlexLayoutModule } from 'ng-flex-layout';
import { ContractDetailsModule, PayoutToolModule } from '@dsh/app/shared/components'; import { ContractDetailsModule } from '@dsh/app/shared/components';
import { ShopContractDetailsModule } from '@dsh/app/shared/services/shop-contract-details'; import { ShopContractDetailsModule } from '@dsh/app/shared/services/shop-contract-details';
import { ButtonModule } from '@dsh/components/buttons'; import { ButtonModule } from '@dsh/components/buttons';
import { DetailsItemModule } from '@dsh/components/layout'; import { DetailsItemModule } from '@dsh/components/layout';
@ -18,7 +18,6 @@ import { ShopActionsComponent } from './components/shop-actions/shop-actions.com
import { ShopContractDetailsComponent } from './components/shop-contract-details/shop-contract-details.component'; import { ShopContractDetailsComponent } from './components/shop-contract-details/shop-contract-details.component';
import { ShopIdComponent } from './components/shop-id/shop-id.component'; import { ShopIdComponent } from './components/shop-id/shop-id.component';
import { ShopInfoComponent } from './components/shop-info/shop-info.component'; import { ShopInfoComponent } from './components/shop-info/shop-info.component';
import { ShopPayoutToolDetailsComponent } from './components/shop-payout-tool-details/shop-payout-tool-details.component';
import { CategoryService } from './services/category/category.service'; import { CategoryService } from './services/category/category.service';
import { ShopDetailsComponent } from './shop-details.component'; import { ShopDetailsComponent } from './shop-details.component';
@ -32,7 +31,6 @@ import { ShopDetailsComponent } from './shop-details.component';
DetailsItemModule, DetailsItemModule,
ClipboardModule, ClipboardModule,
ContractDetailsModule, ContractDetailsModule,
PayoutToolModule,
ShopBalanceModule, ShopBalanceModule,
MatSnackBarModule, MatSnackBarModule,
MatDialogModule, MatDialogModule,
@ -41,7 +39,6 @@ import { ShopDetailsComponent } from './shop-details.component';
declarations: [ declarations: [
ShopDetailsComponent, ShopDetailsComponent,
ShopContractDetailsComponent, ShopContractDetailsComponent,
ShopPayoutToolDetailsComponent,
ShopActionsComponent, ShopActionsComponent,
ShopIdComponent, ShopIdComponent,
ShopInfoComponent, ShopInfoComponent,

View File

@ -5,7 +5,6 @@ export enum NavbarRouterLink {
Shops = 'shops', Shops = 'shops',
Analytics = 'analytics', Analytics = 'analytics',
Operations = 'operations', Operations = 'operations',
Payouts = 'payouts',
Reports = 'reports', Reports = 'reports',
Integrations = 'integrations', Integrations = 'integrations',
} }
@ -24,7 +23,7 @@ export const toNavbarItemConfig = ({
operations, operations,
reports, reports,
}: Record< }: Record<
'shops' | 'analytics' | 'integrations' | 'operations' | 'payouts' | 'reports', 'shops' | 'analytics' | 'integrations' | 'operations' | 'reports',
string string
>): NavbarItemConfig[] => [ >): NavbarItemConfig[] => [
{ {
@ -49,12 +48,6 @@ export const toNavbarItemConfig = ({
RoleAccessName.ViewRefunds, RoleAccessName.ViewRefunds,
], ],
}, },
// {
// routerLink: NavbarRouterLink.Payouts,
// icon: BootstrapIconName.ArrowRightCircle,
// label: payouts,
// roles: [RoleAccessName.ViewPayouts],
// },
{ {
routerLink: NavbarRouterLink.Reports, routerLink: NavbarRouterLink.Reports,
icon: BootstrapIconName.FileText, icon: BootstrapIconName.FileText,

View File

@ -1,8 +1,6 @@
export * from './contract-details'; export * from './contract-details';
export * from './contractor-details'; export * from './contractor-details';
export * from './bank-account-details'; export * from './bank-account-details';
export * from './payout-tool-details';
export * from './payout-tool';
export * from './webhook-api-key'; export * from './webhook-api-key';
export * from './refund-details'; export * from './refund-details';
export * from './invoice-details'; export * from './invoice-details';

View File

@ -1,2 +0,0 @@
export * from './payout-tool-details.module';
export * from './payout-tool-details.component';

View File

@ -1 +0,0 @@
export * from './international-bank-account.component';

View File

@ -1,63 +0,0 @@
<div
*transloco="
let t;
scope: 'components';
read: 'components.apiModelDetails.payoutToolDetails.internationalBankAccount'
"
fxLayout="column"
fxLayoutGap="24px"
>
<dsh-details-item *ngIf="internationalBankAccount?.number" [title]="t('number')">
{{ internationalBankAccount?.number }}
</dsh-details-item>
<dsh-details-item *ngIf="internationalBankAccount?.iban" [title]="t('iban')">
{{ internationalBankAccount?.iban }}
</dsh-details-item>
<ng-container *ngIf="internationalBankAccount?.bankDetails as bankDetails">
<ng-container
*transloco="
let d;
scope: 'components';
read: 'components.apiModelDetails.payoutToolDetails.internationalBankAccount.bankDetails'
"
gdColumns="1fr"
gdColumns.gt-sm="1fr 1fr 1fr"
gdGap="24px"
>
<dsh-details-item *ngIf="bankDetails?.name" [title]="d('name')">
{{ bankDetails?.name }}
</dsh-details-item>
<dsh-details-item *ngIf="bankDetails?.bic" [title]="d('bic')">
{{ bankDetails?.bic }}
</dsh-details-item>
<dsh-details-item *ngIf="bankDetails?.abartn" [title]="d('abartn')">
{{ bankDetails?.abartn }}
</dsh-details-item>
<dsh-details-item
*ngIf="bankDetails?.address"
[title]="d('address')"
gdColumn.gt-sm="1/-1"
>
{{ bankDetails?.address }}
</dsh-details-item>
<dsh-details-item
*ngIf="bankDetails?.countryCode"
[title]="d('countryCode')"
gdColumn.gt-sm="1/-1"
>
{{ bankDetails?.countryCode }}
</dsh-details-item>
</ng-container>
</ng-container>
<div
*ngIf="internationalBankAccount?.correspondentBankAccount"
fxLayout="column"
fxLayoutGap="24px"
>
<mat-divider></mat-divider>
<div class="mat-h2">{{ t('correspondentBankAccount') }}</div>
<dsh-international-bank-account
[internationalBankAccount]="internationalBankAccount?.correspondentBankAccount"
></dsh-international-bank-account>
</div>
</div>

View File

@ -1,11 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { InternationalCorrespondentBankAccount } from '@vality/swag-payments';
@Component({
selector: 'dsh-international-bank-account',
templateUrl: 'international-bank-account.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InternationalBankAccountComponent {
@Input() internationalBankAccount: InternationalCorrespondentBankAccount;
}

View File

@ -1,12 +0,0 @@
<dsh-bank-account-details
*ngIf="payoutToolDetails?.detailsType === 'PayoutToolDetailsBankAccount'"
[bankAccount]="payoutToolDetails"
></dsh-bank-account-details>
<dsh-international-bank-account
*ngIf="payoutToolDetails?.detailsType === 'PayoutToolDetailsInternationalBankAccount'"
[internationalBankAccount]="payoutToolDetails"
></dsh-international-bank-account>
<dsh-wallet
*ngIf="payoutToolDetails?.detailsType === 'PayoutToolDetailsWalletInfo'"
[wallet]="payoutToolDetails"
></dsh-wallet>

View File

@ -1,11 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { PayoutToolDetails } from '@vality/swag-payments';
@Component({
selector: 'dsh-payout-tool-details',
templateUrl: 'payout-tool-details.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutToolDetailsComponent {
@Input() payoutToolDetails: PayoutToolDetails;
}

View File

@ -1,31 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { RouterModule } from '@angular/router';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { LayoutModule } from '@dsh/components/layout';
import { ApiModelRefsModule } from '../../../pipes';
import { BankAccountDetailsModule } from '../bank-account-details';
import { InternationalBankAccountComponent } from './international-bank-account';
import { PayoutToolDetailsComponent } from './payout-tool-details.component';
import { WalletComponent } from './wallet';
@NgModule({
imports: [
FlexLayoutModule,
TranslocoModule,
CommonModule,
LayoutModule,
BankAccountDetailsModule,
MatDividerModule,
ApiModelRefsModule,
RouterModule,
],
declarations: [PayoutToolDetailsComponent, InternationalBankAccountComponent, WalletComponent],
exports: [PayoutToolDetailsComponent],
})
export class PayoutToolDetailsModule {}

View File

@ -1 +0,0 @@
export * from './wallet.component';

View File

@ -1,15 +0,0 @@
<div
*transloco="
let t;
scope: 'components';
read: 'components.apiModelDetails.payoutToolDetails.wallet'
"
fxLayout="column"
fxLayoutGap="24px"
>
<dsh-details-item [title]="t('walletName')">
<dsh-link-label (click)="goToWalletDetails(wallet?.walletID)">{{
wallet?.walletID | walletDetails
}}</dsh-link-label>
</dsh-details-item>
</div>

View File

@ -1,18 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Router } from '@angular/router';
import { PayoutToolDetailsWalletInfo } from '@vality/swag-payments';
@Component({
selector: 'dsh-wallet',
templateUrl: 'wallet.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class WalletComponent {
@Input() wallet: PayoutToolDetailsWalletInfo;
constructor(private router: Router) {}
goToWalletDetails(walletID: string): void {
void this.router.navigate(['wallet-section', 'wallets', walletID]);
}
}

View File

@ -1,2 +0,0 @@
export * from './payout-tool.module';
export * from './payout-tool.component';

View File

@ -1,10 +0,0 @@
<div
*transloco="let t; scope: 'components'; read: 'components.apiModelDetails.payoutTool'"
fxLayout="column"
fxLayoutGap="24px"
>
<dsh-details-item [title]="t('currency')">
{{ payoutTool?.currency }}
</dsh-details-item>
<dsh-payout-tool-details [payoutToolDetails]="payoutTool?.details"></dsh-payout-tool-details>
</div>

View File

@ -1,11 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { PayoutTool } from '@vality/swag-payments';
@Component({
selector: 'dsh-payout-tool',
templateUrl: 'payout-tool.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PayoutToolComponent {
@Input() payoutTool: PayoutTool;
}

View File

@ -1,27 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { TranslocoModule } from '@ngneat/transloco';
import { FlexLayoutModule } from 'ng-flex-layout';
import { LayoutModule } from '@dsh/components/layout';
import { BankAccountDetailsModule } from '../bank-account-details';
import { PayoutToolDetailsModule } from '../payout-tool-details';
import { PayoutToolComponent } from './payout-tool.component';
@NgModule({
imports: [
FlexLayoutModule,
TranslocoModule,
CommonModule,
LayoutModule,
BankAccountDetailsModule,
MatDividerModule,
PayoutToolDetailsModule,
],
declarations: [PayoutToolComponent],
exports: [PayoutToolComponent],
})
export class PayoutToolModule {}

View File

@ -1,22 +0,0 @@
<div
*transloco="let t; scope: 'components'; read: 'components.internationalBankAccountForm'"
[formGroup]="control"
fxLayout="column"
fxLayoutGap="24px"
>
<div fxLayout="column" fxLayoutGap="16px">
<dsh-payout-tool-form formControlName="payoutTool"></dsh-payout-tool-form>
<dsh-currency-autocomplete-field
formControlName="currency"
></dsh-currency-autocomplete-field>
</div>
<mat-checkbox
[checked]="control.controls.correspondentPayoutTool.enabled"
(change)="toggleCorrespondentPayoutTool()"
>{{ t('correspondentAccount') }}</mat-checkbox
>
<dsh-payout-tool-form
*ngIf="control.controls.correspondentPayoutTool.enabled"
formControlName="correspondentPayoutTool"
></dsh-payout-tool-form>
</div>

View File

@ -1,40 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { createControlProviders, FormGroupSuperclass } from '@vality/ng-core';
import { PayoutToolForm } from '../payout-tool-form/types/payout-tool-form';
export interface InternationalBankAccountForm {
payoutTool: PayoutToolForm;
currency: string;
correspondentPayoutTool?: PayoutToolForm;
}
@Component({
selector: 'dsh-international-bank-account-form',
templateUrl: 'international-bank-account-form.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: createControlProviders(() => InternationalBankAccountFormComponent),
})
export class InternationalBankAccountFormComponent extends FormGroupSuperclass<
Partial<InternationalBankAccountForm>
> {
control = this.fb.group({
payoutTool: null,
currency: null,
correspondentPayoutTool: { value: null, disabled: true },
}) as FormGroup;
constructor(private fb: FormBuilder) {
super();
}
toggleCorrespondentPayoutTool(): void {
const { correspondentPayoutTool } = this.control.controls;
if (correspondentPayoutTool.disabled) {
correspondentPayoutTool.enable();
} else {
correspondentPayoutTool.disable();
}
}
}

View File

@ -1,44 +0,0 @@
<form
*transloco="let t; scope: 'components'; read: 'components.payoutToolForm'"
[formGroup]="control"
fxLayout="column"
fxLayoutGap="16px"
>
<mat-form-field>
<mat-label>{{ t('accountNumber') }}</mat-label>
<input aria-label="accountNumber" formControlName="number" matInput />
</mat-form-field>
<div class="dsh-body-1">{{ t('description') }}</div>
<mat-form-field>
<mat-label>{{ t('iban') }}</mat-label>
<input aria-label="iban" formControlName="iban" matInput />
</mat-form-field>
<mat-form-field>
<mat-label>{{ t('bic') }}</mat-label>
<input aria-label="bic" formControlName="bic" matInput />
</mat-form-field>
<mat-form-field>
<mat-label>{{ t('abaRtn') }}</mat-label>
<input aria-label="abaRtn" formControlName="abaRtn" matInput />
</mat-form-field>
<mat-form-field>
<mat-label>{{ t('bankName') }}</mat-label>
<input aria-label="bankName" formControlName="name" matInput />
</mat-form-field>
<dsh-country-autocomplete-field
[label]="t('bankCountry')"
formControlName="country"
required
></dsh-country-autocomplete-field>
<mat-form-field>
<mat-label>{{ t('bankAddress') }}</mat-label>
<input aria-label="bankAddress" formControlName="address" matInput />
</mat-form-field>
</form>

View File

@ -1,31 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Validators, FormBuilder } from '@angular/forms';
import { createControlProviders, FormGroupSuperclass } from '@vality/ng-core';
import { PayoutToolForm } from './types/payout-tool-form';
import { payoutToolFormValidator } from './utils/payout-tool-form-validator';
@Component({
selector: 'dsh-payout-tool-form',
templateUrl: 'payout-tool-form.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: createControlProviders(() => PayoutToolFormComponent),
})
export class PayoutToolFormComponent extends FormGroupSuperclass<Partial<PayoutToolForm>> {
control = this.fb.group(
{
number: ['', [Validators.pattern(/^[0-9A-Z]{8,40}$/)]],
iban: ['', [Validators.pattern(/^[A-Z0-9]{14,35}$/)]],
bic: ['', [Validators.pattern(/^([A-Z0-9]{8}|[A-Z0-9]{11})$/)]],
abaRtn: ['', [Validators.pattern(/^[0-9]{9}$/)]],
name: ['', [Validators.maxLength(100)]],
country: [null],
address: ['', [Validators.maxLength(1000)]],
},
{ validators: payoutToolFormValidator },
);
constructor(private fb: FormBuilder) {
super();
}
}

View File

@ -1,9 +0,0 @@
export interface PayoutToolForm {
number: string;
iban: string;
abaRtn: string;
address: string;
bic: string;
name: string;
country: string;
}

View File

@ -1,26 +0,0 @@
import { ValidatorFn } from '@angular/forms';
import { FormGroupByValue } from '@vality/ng-core';
import isEmpty from 'lodash-es/isEmpty';
import { PayoutToolForm } from '../types/payout-tool-form';
// bic | iban | abaRtn | country & address & name should be provided;
export const payoutToolFormValidator: ValidatorFn = (
form: FormGroupByValue<PayoutToolForm>,
): { error: boolean } | null => {
const { bic, iban, abaRtn, country, address, name } = form.controls;
const isValidNumbers = [
!isEmpty(bic.value) && bic.valid,
!isEmpty(iban.value) && iban.valid,
!isEmpty(abaRtn.value) && abaRtn.valid,
].some(Boolean);
const isValidGeo = [
!isEmpty(country.value) && country.valid,
!isEmpty(address.value) && address.valid,
!isEmpty(name.value) && name.valid,
].every(Boolean);
return isValidNumbers || isValidGeo ? null : { error: true };
};

View File

@ -28,20 +28,4 @@
[label]="t('paymentInstitution')" [label]="t('paymentInstitution')"
formControlName="paymentInstitution" formControlName="paymentInstitution"
></dsh-payment-institution-field> ></dsh-payment-institution-field>
<mat-divider></mat-divider>
<h2 class="dsh-title">{{ t('payoutToolTitle') }}</h2>
<dsh-created-existing-switch [form]="control.controls.bankAccount" formGroupName="bankAccount">
<dsh-international-bank-account-form
*dshCreatedCase
formControlName="created"
></dsh-international-bank-account-form>
<dsh-existing-bank-account
*dshExistingCase
bankAccountType="PayoutToolDetailsInternationalBankAccount"
formControlName="existing"
></dsh-existing-bank-account>
</dsh-created-existing-switch>
</form> </form>

View File

@ -18,7 +18,6 @@ export class ShopFormComponent extends FormGroupSuperclass<
shopDetails: null, shopDetails: null,
orgDetails: createTypeUnionDefaultForm(), orgDetails: createTypeUnionDefaultForm(),
paymentInstitution: null, paymentInstitution: null,
bankAccount: createTypeUnionDefaultForm(),
}) as FormGroup; }) as FormGroup;
constructor(private fb: FormBuilder) { constructor(private fb: FormBuilder) {

View File

@ -1,161 +0,0 @@
import { Component, Input } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormGroup } from '@angular/forms';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';
import { Claim } from '@vality/swag-claim-management';
import { FlexLayoutModule } from 'ng-flex-layout';
import { of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { deepEqual, instance, mock, verify, when } from 'ts-mockito';
import { getTranslocoModule } from '@dsh/app/shared/tests/get-transloco-module';
import { ButtonModule } from '@dsh/components/buttons';
import { CreateInternationalShopEntityComponent } from './create-international-shop-entity.component';
import { CreateInternationalShopEntityService } from './services/create-international-shop-entity/create-international-shop-entity.service';
@Component({
selector: 'dsh-shop-form',
template: '',
})
class MockShopFormComponent {
@Input() form: FormGroup;
}
describe('CreateInternationalShopEntityComponent', () => {
let fixture: ComponentFixture<CreateInternationalShopEntityComponent>;
let component: CreateInternationalShopEntityComponent;
let mockCreateInternationalShopEntityService: CreateInternationalShopEntityService;
let mockTranslocoService: TranslocoService;
let mockMatSnackBar: MatSnackBar;
let mockRouter: Router;
beforeEach(() => {
mockCreateInternationalShopEntityService = mock(CreateInternationalShopEntityService);
mockTranslocoService = mock(TranslocoService);
mockMatSnackBar = mock(MatSnackBar);
mockRouter = mock(Router);
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [getTranslocoModule(), MatDialogModule, ButtonModule, FlexLayoutModule],
declarations: [CreateInternationalShopEntityComponent, MockShopFormComponent],
providers: [
{
provide: CreateInternationalShopEntityService,
useFactory: () => instance(mockCreateInternationalShopEntityService),
},
{
provide: mockTranslocoService,
useFactory: () => instance(TranslocoService),
},
{
provide: MatSnackBar,
useFactory: () => instance(mockMatSnackBar),
},
{
provide: Router,
useFactory: () => instance(mockRouter),
},
],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CreateInternationalShopEntityComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('createShop', () => {
const claim: Claim = {
id: 100500,
status: 'active',
changeset: [],
revision: 5,
createdAt: new Date(),
};
it('should call create shop with form value', () => {
when(
mockCreateInternationalShopEntityService.createShop(
deepEqual(component.form.value),
),
).thenReturn(of(claim));
component.createShop();
verify(
mockCreateInternationalShopEntityService.createShop(
deepEqual(component.form.value),
),
).once();
expect().nothing();
});
it('should emit send on success', () => {
const spyOnSend = spyOn(component.send, 'emit').and.callThrough();
when(
mockCreateInternationalShopEntityService.createShop(
deepEqual(component.form.value),
),
).thenReturn(of(claim));
component.createShop();
expect(spyOnSend).toHaveBeenCalledTimes(1);
});
it('should navigate to claim with claim id', () => {
when(
mockCreateInternationalShopEntityService.createShop(
deepEqual(component.form.value),
),
).thenReturn(of(claim));
when(
mockRouter.navigate(deepEqual(['claim-section', 'claims', claim.id])),
).thenReturn();
component.createShop();
verify(mockRouter.navigate(deepEqual(['claim-section', 'claims', claim.id]))).once();
expect().nothing();
});
it('should show error snack bar if error happened', () => {
const error = new Error('Test error');
when(mockCreateInternationalShopEntityService.createShop).thenReturn(() =>
of(claim).pipe(
switchMap(() => {
throw error;
}),
),
);
when(mockMatSnackBar.open('Что-то пошло не так', 'OK')).thenReturn();
component.createShop();
verify(mockMatSnackBar.open('Что-то пошло не так', 'OK')).once();
expect().nothing();
});
});
describe('cancelCreation', () => {
it('should emit cancel', () => {
const spyOnCancel = spyOn(component.cancel, 'emit').and.callThrough();
component.cancelCreation();
expect(spyOnCancel).toHaveBeenCalledTimes(1);
});
});
});

View File

@ -1,6 +1,5 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core'; import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco'; import { TranslocoService } from '@ngneat/transloco';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { progressTo, NotifyLogService } from '@vality/ng-core'; import { progressTo, NotifyLogService } from '@vality/ng-core';
@ -27,7 +26,6 @@ export class CreateInternationalShopEntityComponent {
private createShopInternationalLegalEntityService: CreateInternationalShopEntityService, private createShopInternationalLegalEntityService: CreateInternationalShopEntityService,
private transloco: TranslocoService, private transloco: TranslocoService,
private log: NotifyLogService, private log: NotifyLogService,
private router: Router,
) {} ) {}
createShop(): void { createShop(): void {

View File

@ -15,10 +15,8 @@ import { CategoryAutocompleteFieldModule } from '@dsh/app/shared/components/inpu
import { CountryAutocompleteFieldModule } from '@dsh/app/shared/components/inputs/country-autocomplete-field'; import { CountryAutocompleteFieldModule } from '@dsh/app/shared/components/inputs/country-autocomplete-field';
import { PaymentInstitutionFieldModule } from '@dsh/app/shared/components/inputs/payment-institution-field'; import { PaymentInstitutionFieldModule } from '@dsh/app/shared/components/inputs/payment-institution-field';
import { ShopFieldModule } from '@dsh/app/shared/components/inputs/shop-field'; import { ShopFieldModule } from '@dsh/app/shared/components/inputs/shop-field';
import { InternationalBankAccountFormComponent } from '@dsh/app/shared/components/shop-creation/create-international-shop-entity/components/international-bank-account-form/international-bank-account-form.component';
import { NewContractorFormComponent } from '@dsh/app/shared/components/shop-creation/create-international-shop-entity/components/new-contractor-form/new-contractor-form.component'; import { NewContractorFormComponent } from '@dsh/app/shared/components/shop-creation/create-international-shop-entity/components/new-contractor-form/new-contractor-form.component';
import { CreatedExistingSwitchModule } from '@dsh/app/shared/components/shop-creation/created-existing-switch/created-existing-switch.module'; import { CreatedExistingSwitchModule } from '@dsh/app/shared/components/shop-creation/created-existing-switch/created-existing-switch.module';
import { ExistingBankAccountModule } from '@dsh/app/shared/components/shop-creation/existing-bank-account/existing-bank-account.module';
import { ExistingContractFormModule } from '@dsh/app/shared/components/shop-creation/existing-contract-form/existing-contract-form.module'; import { ExistingContractFormModule } from '@dsh/app/shared/components/shop-creation/existing-contract-form/existing-contract-form.module';
import { ShopDetailsFormModule } from '@dsh/app/shared/components/shop-creation/shop-details-form'; import { ShopDetailsFormModule } from '@dsh/app/shared/components/shop-creation/shop-details-form';
import { CountryCodesModule } from '@dsh/app/shared/services'; import { CountryCodesModule } from '@dsh/app/shared/services';
@ -26,7 +24,6 @@ import { ButtonModule } from '@dsh/components/buttons';
import { CurrencyAutocompleteFieldModule } from '../../inputs/currency-autocomplete-field'; import { CurrencyAutocompleteFieldModule } from '../../inputs/currency-autocomplete-field';
import { PayoutToolFormComponent } from './components/payout-tool-form/payout-tool-form.component';
import { ShopFormComponent } from './components/shop-form/shop-form.component'; import { ShopFormComponent } from './components/shop-form/shop-form.component';
import { CreateInternationalShopEntityComponent } from './create-international-shop-entity.component'; import { CreateInternationalShopEntityComponent } from './create-international-shop-entity.component';
import { CreateInternationalShopEntityService } from './services/create-international-shop-entity/create-international-shop-entity.service'; import { CreateInternationalShopEntityService } from './services/create-international-shop-entity/create-international-shop-entity.service';
@ -54,15 +51,12 @@ import { CreateInternationalShopEntityService } from './services/create-internat
ContractorDetailsModule, ContractorDetailsModule,
ErrorMessageModule, ErrorMessageModule,
ExistingContractFormModule, ExistingContractFormModule,
ExistingBankAccountModule,
CurrencyAutocompleteFieldModule, CurrencyAutocompleteFieldModule,
], ],
declarations: [ declarations: [
CreateInternationalShopEntityComponent, CreateInternationalShopEntityComponent,
PayoutToolFormComponent,
ShopFormComponent, ShopFormComponent,
NewContractorFormComponent, NewContractorFormComponent,
InternationalBankAccountFormComponent,
], ],
exports: [CreateInternationalShopEntityComponent], exports: [CreateInternationalShopEntityComponent],
providers: [CreateInternationalShopEntityService], providers: [CreateInternationalShopEntityService],

View File

@ -10,17 +10,11 @@ import {
createInternationalLegalEntityModification, createInternationalLegalEntityModification,
createShopCreationModification, createShopCreationModification,
makeShopLocation, makeShopLocation,
createInternationalContractPayoutToolModification,
} from '@dsh/app/api/claim-management'; } from '@dsh/app/api/claim-management';
import { IdGeneratorService } from '@dsh/app/shared/services/id-generator'; import { IdGeneratorService } from '@dsh/app/shared/services/id-generator';
import { InternationalShopEntityFormValue } from '../../types/international-shop-entity-form-value'; import { InternationalShopEntityFormValue } from '../../types/international-shop-entity-form-value';
import {
payoutToolDetailsInternationalBankAccountToInternationalBankAccount,
payoutToolFormToInternationalBankAccount,
} from './utils';
@Injectable() @Injectable()
export class CreateInternationalShopEntityService { export class CreateInternationalShopEntityService {
constructor( constructor(
@ -47,7 +41,6 @@ export class CreateInternationalShopEntityService {
shopDetails, shopDetails,
orgDetails: { created: newContractor, existing: contract }, orgDetails: { created: newContractor, existing: contract },
paymentInstitution, paymentInstitution,
bankAccount: { created: newBankAccount, existing: payoutTool },
}: InternationalShopEntityFormValue): Modification[] { }: InternationalShopEntityFormValue): Modification[] {
const contractorID = this.idGenerator.uuid(); const contractorID = this.idGenerator.uuid();
const contractID = this.idGenerator.uuid(); const contractID = this.idGenerator.uuid();
@ -80,30 +73,6 @@ export class CreateInternationalShopEntityService {
contractorID, contractorID,
paymentInstitution: { id: paymentInstitution?.id ?? 1 }, paymentInstitution: { id: paymentInstitution?.id ?? 1 },
}), }),
createInternationalContractPayoutToolModification(
contractID,
payoutToolID,
newBankAccount ? newBankAccount.currency : payoutTool.currency,
newBankAccount
? {
...payoutToolFormToInternationalBankAccount(newBankAccount.payoutTool),
correspondentAccount: newBankAccount.correspondentPayoutTool
? payoutToolFormToInternationalBankAccount(
newBankAccount.correspondentPayoutTool,
)
: null,
}
: {
...payoutToolDetailsInternationalBankAccountToInternationalBankAccount(
payoutTool.details,
),
correspondentAccount: payoutTool.details.correspondentBankAccount
? payoutToolDetailsInternationalBankAccountToInternationalBankAccount(
payoutTool.details.correspondentBankAccount,
)
: null,
},
),
createShopCreationModification(shopID, { createShopCreationModification(shopID, {
category: { category: {
categoryID: shopDetails.category?.categoryID ?? 1, categoryID: shopDetails.category?.categoryID ?? 1,

View File

@ -1,2 +0,0 @@
export * from './payout-tool-details-international-bank-account-to-international-bank-account';
export * from './payout-tool-form-to-international-bank-account';

View File

@ -1,19 +0,0 @@
import { InternationalBankAccount } from '@vality/swag-claim-management';
import { PayoutToolDetailsInternationalBankAccount } from '@vality/swag-payments';
export function payoutToolDetailsInternationalBankAccountToInternationalBankAccount(
form: Omit<PayoutToolDetailsInternationalBankAccount, 'detailsType'>,
): Required<Pick<InternationalBankAccount, 'iban' | 'number' | 'bank'>> {
const { bankDetails } = form;
return {
iban: form.iban,
number: form.number,
bank: {
abaRtn: bankDetails?.abartn,
address: bankDetails?.address,
bic: bankDetails?.bic,
name: bankDetails?.name,
country: bankDetails?.countryCode,
},
};
}

View File

@ -1,19 +0,0 @@
import { InternationalBankAccount } from '@vality/swag-claim-management';
import { PayoutToolForm } from '../../../components/payout-tool-form/types/payout-tool-form';
export function payoutToolFormToInternationalBankAccount(
form: PayoutToolForm,
): Required<Pick<InternationalBankAccount, 'iban' | 'number' | 'bank'>> {
return {
iban: form.iban,
number: form.number,
bank: {
abaRtn: form.abaRtn,
address: form.address,
bic: form.bic,
name: form.name,
country: form.country,
},
};
}

View File

@ -1,19 +1,13 @@
import { PaymentInstitution } from '@vality/swag-payments'; import { PaymentInstitution } from '@vality/swag-payments';
import { TypeUnion } from '@dsh/app/shared/components/shop-creation/created-existing-switch/created-existing-switch.component'; import { TypeUnion } from '@dsh/app/shared/components/shop-creation/created-existing-switch/created-existing-switch.component';
import { ExistingBankAccountForm } from '@dsh/app/shared/components/shop-creation/existing-bank-account/existing-bank-account.component';
import { ShopDetailsForm } from '@dsh/app/shared/components/shop-creation/shop-details-form/shop-details-form.component'; import { ShopDetailsForm } from '@dsh/app/shared/components/shop-creation/shop-details-form/shop-details-form.component';
import { ExistingContractForm } from '../../existing-contract-form/existing-contract-form.component'; import { ExistingContractForm } from '../../existing-contract-form/existing-contract-form.component';
import { InternationalBankAccountForm } from '../components/international-bank-account-form/international-bank-account-form.component';
import { NewContractorForm } from '../components/new-contractor-form/new-contractor-form.component'; import { NewContractorForm } from '../components/new-contractor-form/new-contractor-form.component';
export interface InternationalShopEntityFormValue { export interface InternationalShopEntityFormValue {
shopDetails: ShopDetailsForm; shopDetails: ShopDetailsForm;
orgDetails: TypeUnion<NewContractorForm, ExistingContractForm<'InternationalLegalEntity'>>; orgDetails: TypeUnion<NewContractorForm, ExistingContractForm<'InternationalLegalEntity'>>;
paymentInstitution: PaymentInstitution; paymentInstitution: PaymentInstitution;
bankAccount: TypeUnion<
InternationalBankAccountForm,
ExistingBankAccountForm<'PayoutToolDetailsInternationalBankAccount'>
>;
} }

View File

@ -1,78 +0,0 @@
<div [formGroup]="control" fxLayout="column" fxLayoutGap="24px">
<div
*transloco="let p; scope: 'components'; read: 'components.newContractorForm'"
fxLayout="column"
fxLayoutGap="16px"
>
<mat-form-field>
<mat-label>{{ p('form.registeredName') }}</mat-label>
<input
autocomplete="off"
formControlName="registeredName"
matInput
required
type="text"
/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('form.inn') }}</mat-label>
<dsh-format-input
format="individualOrLegalEntityInn"
formControlName="inn"
required
></dsh-format-input>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('form.registeredNumber') }}</mat-label>
<dsh-format-input
format="ogrn"
formControlName="registeredNumber"
required
></dsh-format-input>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('form.actualAddress') }}</mat-label>
<input
autocomplete="off"
formControlName="actualAddress"
matInput
required
type="text"
/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('form.representativePosition') }}</mat-label>
<input
autocomplete="off"
formControlName="representativePosition"
matInput
required
type="text"
/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('form.representativeFullName') }}</mat-label>
<input
autocomplete="off"
formControlName="representativeFullName"
matInput
required
type="text"
/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('form.representativeDocument') }}</mat-label>
<input
autocomplete="off"
formControlName="representativeDocument"
matInput
required
type="text"
/>
</mat-form-field>
</div>
<mat-divider></mat-divider>
<dsh-russian-bank-account-form formControlName="bankAccount"></dsh-russian-bank-account-form>
</div>

View File

@ -1,40 +0,0 @@
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { UntilDestroy } from '@ngneat/until-destroy';
import { FormGroupSuperclass, createControlProviders } from '@vality/ng-core';
import { RussianBankAccountForm } from '../russian-bank-account-form/types/bank-account-form-data';
export interface NewContractorForm {
registeredName: string;
inn: string;
registeredNumber: string;
actualAddress: string;
representativePosition: string;
representativeFullName: string;
representativeDocument: string;
bankAccount: RussianBankAccountForm;
}
@UntilDestroy()
@Component({
selector: 'dsh-new-contractor-form',
templateUrl: 'new-contractor-form.component.html',
providers: createControlProviders(() => NewContractorFormComponent),
})
export class NewContractorFormComponent extends FormGroupSuperclass<Partial<NewContractorForm>> {
control = this.fb.group<NewContractorForm>({
registeredName: null,
inn: null,
registeredNumber: null,
actualAddress: null,
representativePosition: null,
representativeFullName: null,
representativeDocument: null,
bankAccount: null,
});
constructor(private fb: FormBuilder) {
super();
}
}

View File

@ -1,19 +0,0 @@
<div
*transloco="let p; scope: 'components'; read: 'components.orgDetailsForm'"
fxLayout="column"
fxLayoutGap="24px"
>
<h2 class="dsh-title">{{ p('title') }}</h2>
<dsh-created-existing-switch [form]="control" [formGroup]="control">
<dsh-new-contractor-form
*dshCreatedCase
formControlName="created"
></dsh-new-contractor-form>
<dsh-existing-contract-form
*dshExistingCase
entityType="RussianLegalEntity"
formControlName="existing"
></dsh-existing-contract-form>
</dsh-created-existing-switch>
</div>

View File

@ -1,30 +0,0 @@
import { Component } from '@angular/core';
import { UntilDestroy } from '@ngneat/until-destroy';
import { createControlProviders, FormGroupSuperclass } from '@vality/ng-core';
import {
createTypeUnionDefaultForm,
TypeUnion,
} from '@dsh/app/shared/components/shop-creation/created-existing-switch/created-existing-switch.component';
import { ExistingContractForm } from '../../../existing-contract-form/existing-contract-form.component';
import { NewContractorForm } from './../new-contractor-form/new-contractor-form.component';
export type OrgDetailsForm = TypeUnion<
NewContractorForm,
ExistingContractForm<'RussianLegalEntity'>
>;
@UntilDestroy()
@Component({
selector: 'dsh-org-details-form',
templateUrl: 'org-details-form.component.html',
providers: createControlProviders(() => OrgDetailsFormComponent),
})
export class OrgDetailsFormComponent extends FormGroupSuperclass<Partial<OrgDetailsForm>> {
control = createTypeUnionDefaultForm<
NewContractorForm,
ExistingContractForm<'RussianLegalEntity'>
>();
}

View File

@ -1,33 +0,0 @@
<div
*transloco="let p; scope: 'components'; read: 'components.russianBankAccountForm'"
[formGroup]="control"
fxLayout="column"
fxLayoutGap="16px"
>
<div gdColumns="1fr" gdColumns.gt-sm="1fr 1fr" gdGap="24px">
<mat-form-field gdColumn="1/-1">
<mat-label>{{ p('name') }}</mat-label>
<input aria-label="bankName" formControlName="bankName" matInput required />
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('bik') }}</mat-label>
<dsh-format-input format="bik" formControlName="bankBik" required></dsh-format-input>
</mat-form-field>
<mat-form-field>
<mat-label>{{ p('postAccount') }}</mat-label>
<dsh-format-input
format="bankPostAccount"
formControlName="bankPostAccount"
required
></dsh-format-input>
</mat-form-field>
<mat-form-field gdColumn="1/-1">
<mat-label>{{ p('account') }}</mat-label>
<dsh-format-input
format="bankAccount"
formControlName="account"
required
></dsh-format-input>
</mat-form-field>
</div>
</div>

View File

@ -1,26 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { createControlProviders, FormGroupSuperclass } from '@vality/ng-core';
import { RussianBankAccountForm } from './types/bank-account-form-data';
@Component({
selector: 'dsh-russian-bank-account-form',
templateUrl: 'russian-bank-account-form.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: createControlProviders(() => RussianBankAccountFormComponent),
})
export class RussianBankAccountFormComponent extends FormGroupSuperclass<
Partial<RussianBankAccountForm>
> {
control = this.fb.group<RussianBankAccountForm>({
account: null,
bankName: null,
bankPostAccount: null,
bankBik: null,
});
constructor(private fb: FormBuilder) {
super();
}
}

View File

@ -1,6 +0,0 @@
export interface RussianBankAccountForm {
bankName: string;
bankBik: string;
bankPostAccount: string;
account: string;
}

View File

@ -1,35 +0,0 @@
<div [formGroup]="control" fxLayout="column" fxLayoutGap="24px">
<dsh-shop-details-form formControlName="shopDetails"></dsh-shop-details-form>
<mat-divider></mat-divider>
<dsh-payment-institution-field
formControlName="paymentInstitution"
></dsh-payment-institution-field>
<mat-divider></mat-divider>
<dsh-org-details-form formControlName="orgDetails"></dsh-org-details-form>
<mat-divider></mat-divider>
<ng-container *transloco="let p; scope: 'components'; read: 'components.shopForm'">
<div fxLayout="column" fxLayoutGap="16px">
<h2 class="dsh-title">{{ p('title') }}</h2>
<div class="dsh-body-1">{{ p('description') }}</div>
</div>
<dsh-created-existing-switch
[form]="control.controls.bankAccount"
formGroupName="bankAccount"
>
<div *dshCreatedCase fxLayout="column" fxLayoutGap="16px">
<dsh-russian-bank-account-form
formControlName="created"
></dsh-russian-bank-account-form>
<dsh-currency-autocomplete-field
[formControl]="control.controls.currency"
></dsh-currency-autocomplete-field>
</div>
<dsh-existing-bank-account
*dshExistingCase
bankAccountType="PayoutToolDetailsBankAccount"
formControlName="existing"
></dsh-existing-bank-account>
</dsh-created-existing-switch>
</ng-container>
</div>

View File

@ -1,28 +0,0 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { UntilDestroy } from '@ngneat/until-destroy';
import { createControlProviders, FormGroupSuperclass } from '@vality/ng-core';
import { createTypeUnionDefaultForm } from '../../../created-existing-switch/created-existing-switch.component';
import { RussianShopForm } from '../../types/russian-shop-entity';
@UntilDestroy()
@Component({
selector: 'dsh-shop-form',
templateUrl: 'shop-form.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: createControlProviders(() => ShopFormComponent),
})
export class ShopFormComponent extends FormGroupSuperclass<Partial<RussianShopForm>> {
control = this.fb.group({
shopDetails: null,
orgDetails: null,
bankAccount: createTypeUnionDefaultForm(),
paymentInstitution: null,
currency: null,
}) as FormGroup;
constructor(private fb: FormBuilder) {
super();
}
}

View File

@ -1,19 +0,0 @@
<dsh-base-dialog
*transloco="let t; scope: 'components'; read: 'components.createRussianShopEntity'"
[title]="t('title')"
(cancel)="cancelCreation()"
>
<dsh-shop-form [formControl]="form"> </dsh-shop-form>
<div dshBaseDialogActions fxLayout fxLayoutAlign="stretch" fxLayoutAlign.gt-sm="end">
<button
[disabled]="form.invalid"
color="accent"
dsh-button
fxFlex
fxFlex.gt-sm="none"
(click)="createShop()"
>
{{ t('send') }}
</button>
</div>
</dsh-base-dialog>

View File

@ -1,3 +0,0 @@
mat-dialog-actions {
padding-bottom: 24px;
}

View File

@ -1,53 +0,0 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { NotifyLogService } from '@vality/ng-core';
import { CreateRussianShopEntityService } from './services/create-russian-shop-entity/create-russian-shop-entity.service';
@UntilDestroy()
@Component({
selector: 'dsh-create-russian-shop-entity',
templateUrl: 'create-russian-shop-entity.component.html',
styleUrls: ['create-russian-shop-entity.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [CreateRussianShopEntityService],
})
export class CreateRussianShopEntityComponent {
@Output() cancel = new EventEmitter<void>();
@Output() send = new EventEmitter<void>();
form = new FormControl();
constructor(
private createShopRussianLegalEntityService: CreateRussianShopEntityService,
private transloco: TranslocoService,
private log: NotifyLogService,
private router: Router,
) {}
cancelCreation(): void {
this.cancel.emit();
}
createShop(): void {
this.createShopRussianLegalEntityService
.createShop(this.form.value)
.pipe(untilDestroyed(this))
.subscribe({
next: () => {
this.send.emit();
// TODO: Claims page disabled
// void this.router.navigate(['claim-section', 'claims', id]);
},
error: (err) => {
this.log.error(
err,
this.transloco.selectTranslate('shared.commonError', null, 'components'),
);
},
});
}
}

Some files were not shown because too many files have changed in this diff Show More