IMP-251: Create shop claim without payout (#389)
Some checks failed
Main / Deploy (push) Has been cancelled
Main / Notify (push) Has been cancelled

This commit is contained in:
Rinat Arsaev 2024-09-18 16:42:50 +05:00 committed by GitHub
parent 693b90fb1f
commit 6a9a0b5ffe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 43 additions and 320 deletions

View File

@ -46,7 +46,6 @@
"@vality/machinegun-proto", "@vality/machinegun-proto",
"@vality/magista-proto", "@vality/magista-proto",
"@vality/messages-proto", "@vality/messages-proto",
"@vality/payout-manager-proto",
"@vality/repairer-proto", "@vality/repairer-proto",
"@vality/fistful-proto", "@vality/fistful-proto",
"@vality/file-storage-proto", "@vality/file-storage-proto",

14
package-lock.json generated
View File

@ -21,14 +21,13 @@
"@angular/router": "18.2.4", "@angular/router": "18.2.4",
"@ngneat/input-mask": "6.0.0", "@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0", "@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-e5d3c83.0", "@vality/domain-proto": "2.0.1-7762f6c.0",
"@vality/dominator-proto": "1.0.1-41bee97.0", "@vality/dominator-proto": "1.0.1-41bee97.0",
"@vality/fistful-proto": "2.0.1-88e69a5.0", "@vality/fistful-proto": "2.0.1-88e69a5.0",
"@vality/machinegun-proto": "1.0.0", "@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-ec1bdb9.0", "@vality/magista-proto": "2.0.2-ec1bdb9.0",
"@vality/ng-core": "18.3.1-pr-68-2c4891d.0", "@vality/ng-core": "18.3.1-pr-68-2c4891d.0",
"@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0", "@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0",
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
"@vality/repairer-proto": "2.0.2-07b73e9.0", "@vality/repairer-proto": "2.0.2-07b73e9.0",
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0", "@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
"@vality/thrift-ts": "2.4.1-8ad5123.0", "@vality/thrift-ts": "2.4.1-8ad5123.0",
@ -5926,9 +5925,9 @@
"integrity": "sha512-mokuK6w+ExASdDE6+L9bM2SaS0yVPSyBvXavY8rRtNzZgVdmj7KSRiyGmXz41grhS6jcvD8aR85Nj4o7/iogmQ==" "integrity": "sha512-mokuK6w+ExASdDE6+L9bM2SaS0yVPSyBvXavY8rRtNzZgVdmj7KSRiyGmXz41grhS6jcvD8aR85Nj4o7/iogmQ=="
}, },
"node_modules/@vality/domain-proto": { "node_modules/@vality/domain-proto": {
"version": "2.0.1-e5d3c83.0", "version": "2.0.1-7762f6c.0",
"resolved": "https://registry.npmjs.org/@vality/domain-proto/-/domain-proto-2.0.1-e5d3c83.0.tgz", "resolved": "https://registry.npmjs.org/@vality/domain-proto/-/domain-proto-2.0.1-7762f6c.0.tgz",
"integrity": "sha512-G6FpLCyx7kZZIox90PFUe0FsiAzUTtHZ42gqK7pTyHn2mOzampUuQyyn9MwPkQv6atGLXXiSzEY+qmZIWWkvHQ==" "integrity": "sha512-QYwo9fnw6Yx7L55+FRMNAmWNPYB+7QgXDrPAhdOkd/6knn0qVXdvN0/f676zAtUjOkfDGAddBn/zRF+/e7A6KQ=="
}, },
"node_modules/@vality/dominator-proto": { "node_modules/@vality/dominator-proto": {
"version": "1.0.1-41bee97.0", "version": "1.0.1-41bee97.0",
@ -6018,11 +6017,6 @@
"utility-types": "^3.0.0" "utility-types": "^3.0.0"
} }
}, },
"node_modules/@vality/payout-manager-proto": {
"version": "2.0.1-eb4091a.0",
"resolved": "https://registry.npmjs.org/@vality/payout-manager-proto/-/payout-manager-proto-2.0.1-eb4091a.0.tgz",
"integrity": "sha512-hP8sKbNxmBHXP64eUK6FPXFB1sJQ8eIwnfz6sqObmNbeyZDRh0UYufyTJAgAmtjOWhAxievWyoU8OG6glgoEuw=="
},
"node_modules/@vality/prettier-config": { "node_modules/@vality/prettier-config": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/@vality/prettier-config/-/prettier-config-3.1.0.tgz", "resolved": "https://registry.npmjs.org/@vality/prettier-config/-/prettier-config-3.1.0.tgz",

View File

@ -30,14 +30,13 @@
"@angular/router": "18.2.4", "@angular/router": "18.2.4",
"@ngneat/input-mask": "6.0.0", "@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0", "@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-e5d3c83.0", "@vality/domain-proto": "2.0.1-7762f6c.0",
"@vality/dominator-proto": "1.0.1-41bee97.0", "@vality/dominator-proto": "1.0.1-41bee97.0",
"@vality/fistful-proto": "2.0.1-88e69a5.0", "@vality/fistful-proto": "2.0.1-88e69a5.0",
"@vality/machinegun-proto": "1.0.0", "@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-ec1bdb9.0", "@vality/magista-proto": "2.0.2-ec1bdb9.0",
"@vality/ng-core": "18.3.1-pr-68-2c4891d.0", "@vality/ng-core": "18.3.1-pr-68-2c4891d.0",
"@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0", "@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0",
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
"@vality/repairer-proto": "2.0.2-07b73e9.0", "@vality/repairer-proto": "2.0.2-07b73e9.0",
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0", "@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
"@vality/thrift-ts": "2.4.1-8ad5123.0", "@vality/thrift-ts": "2.4.1-8ad5123.0",

View File

@ -1 +0,0 @@
export * from './payout-management.service';

View File

@ -1,62 +0,0 @@
import { Injectable } from '@angular/core';
import {
payout_manager_PayoutManagementCodegenClient,
ThriftAstMetadata,
payout_manager_PayoutManagement,
} from '@vality/payout-manager-proto';
import { PayoutParams, Payout, PayoutID } from '@vality/payout-manager-proto/payout_manager';
import { combineLatest, from, map, Observable, switchMap } from 'rxjs';
import { KeycloakTokenInfoService, toWachterHeaders } from '@cc/app/shared/services';
import { environment } from '@cc/environments/environment';
import { ConfigService } from '../../core/config.service';
@Injectable({ providedIn: 'root' })
export class PayoutManagementService {
private client$: Observable<payout_manager_PayoutManagementCodegenClient>;
constructor(
private keycloakTokenInfoService: KeycloakTokenInfoService,
configService: ConfigService,
) {
const headers$ = this.keycloakTokenInfoService.info$.pipe(
map(toWachterHeaders('PayoutManagement')),
);
const metadata$ = from(
import('@vality/payout-manager-proto/metadata.json').then(
(m) => m.default as ThriftAstMetadata[],
),
);
this.client$ = combineLatest([metadata$, headers$]).pipe(
switchMap(([metadata, headers]) =>
payout_manager_PayoutManagement({
metadata,
headers,
logging: environment.logging.requests,
...configService.config.api.wachter,
}),
),
);
}
// eslint-disable-next-line @typescript-eslint/naming-convention
CreatePayout(payoutParams: PayoutParams): Observable<Payout> {
return this.client$.pipe(switchMap((c) => c.CreatePayout(payoutParams)));
}
// eslint-disable-next-line @typescript-eslint/naming-convention
GetPayout(payoutId: PayoutID): Observable<Payout> {
return this.client$.pipe(switchMap((c) => c.GetPayout(payoutId)));
}
// eslint-disable-next-line @typescript-eslint/naming-convention
ConfirmPayout(payoutId: PayoutID): Observable<void> {
return this.client$.pipe(switchMap((c) => c.ConfirmPayout(payoutId)));
}
// eslint-disable-next-line @typescript-eslint/naming-convention
CancelPayout(payoutId: PayoutID, details: string): Observable<void> {
return this.client$.pipe(switchMap((c) => c.CancelPayout(payoutId, details)));
}
}

View File

@ -92,7 +92,10 @@
Change status Change status
</button> </button>
<button mat-raised-button (click)="createWallet()">Add wallet modification</button> <button mat-raised-button (click)="createWallet()">Add wallet modification</button>
<button mat-raised-button (click)="createShop()">Add shop modifications</button> <button mat-raised-button (click)="createShop(false)">Add shop modifications</button>
<button color="accent" mat-raised-button (click)="createShop(true)">
Add shop modifications without payout
</button>
<button color="primary" mat-raised-button (click)="addModification()"> <button color="primary" mat-raised-button (click)="addModification()">
Add modification Add modification
</button> </button>

View File

@ -115,13 +115,13 @@ export class ClaimComponent {
}); });
} }
createShop() { createShop(withoutPayout = true) {
combineLatest([this.party$, this.claim$]) combineLatest([this.party$, this.claim$])
.pipe( .pipe(
first(), first(),
switchMap(([party, claim]) => switchMap(([party, claim]) =>
this.dialogService this.dialogService
.open(CreateShopDialogComponent, { party, claim }) .open(CreateShopDialogComponent, { party, claim, withoutPayout })
.afterClosed(), .afterClosed(),
), ),
takeUntilDestroyed(this.destroyRef), takeUntilDestroyed(this.destroyRef),

View File

@ -74,7 +74,10 @@ const DEFAULT_SHOP_LOCATION: ShopLocation = {
styles: ``, styles: ``,
}) })
export class CreateShopDialogComponent export class CreateShopDialogComponent
extends DialogSuperclass<CreateShopDialogComponent, { party: Party; claim: Claim }> extends DialogSuperclass<
CreateShopDialogComponent,
{ party: Party; claim: Claim; withoutPayout: boolean }
>
implements OnInit implements OnInit
{ {
static defaultDialogConfig = DEFAULT_DIALOG_CONFIG.large; static defaultDialogConfig = DEFAULT_DIALOG_CONFIG.large;
@ -185,6 +188,9 @@ export class CreateShopDialogComponent
}, },
}, },
}, },
...(this.dialogData.withoutPayout
? []
: [
{ {
party_modification: { party_modification: {
contract_modification: { contract_modification: {
@ -206,6 +212,7 @@ export class CreateShopDialogComponent
}, },
}, },
}, },
]),
{ {
party_modification: { party_modification: {
shop_modification: { shop_modification: {
@ -216,7 +223,9 @@ export class CreateShopDialogComponent
category: category, category: category,
location: DEFAULT_SHOP_LOCATION, location: DEFAULT_SHOP_LOCATION,
contract_id: contractId, contract_id: contractId,
payout_tool_id: payoutToolId, ...(this.dialogData.withoutPayout
? {}
: { payout_tool_id: payoutToolId }),
}, },
}, },
}, },

View File

@ -1,7 +1,5 @@
export * from './status'; export * from './status';
export * from './shop-field'; export * from './shop-field';
export * from './shop-details'; export * from './shop-details';
export * from './payout-tool-details';
export * from './payout-tool-field';
export * from './page-layout'; export * from './page-layout';
export * from './wallet-field'; export * from './wallet-field';

View File

@ -1,11 +0,0 @@
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px">
<cc-details-item title="BIC">{{ internationalBankAccount.bank.bic }}</cc-details-item>
<cc-details-item title="Country">{{ internationalBankAccount.bank.country }}</cc-details-item>
<cc-details-item title="Address">{{ internationalBankAccount.bank.address }}</cc-details-item>
<cc-details-item title="ABA RTN">{{ internationalBankAccount.bank.aba_rtn }}</cc-details-item>
<cc-details-item title="Account Holder">{{
internationalBankAccount.account_holder
}}</cc-details-item>
<cc-details-item title="IBAN">{{ internationalBankAccount.iban }}</cc-details-item>
<cc-details-item title="Number">{{ internationalBankAccount.number }}</cc-details-item>
</div>

View File

@ -1,10 +0,0 @@
import { Component, Input } from '@angular/core';
import { InternationalBankAccount } from '@vality/domain-proto/domain';
@Component({
selector: 'cc-international-bank-account-details',
templateUrl: './international-bank-account-details.component.html',
})
export class InternationalBankAccountDetailsComponent {
@Input() internationalBankAccount: InternationalBankAccount;
}

View File

@ -1,8 +0,0 @@
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px">
<cc-details-item title="Bank Name">{{ russianBankAccount.bank_name }}</cc-details-item>
<cc-details-item title="BIK">{{ russianBankAccount.bank_bik }}</cc-details-item>
<cc-details-item title="Bank Post Account">{{
russianBankAccount.bank_post_account
}}</cc-details-item>
<cc-details-item title="Account">{{ russianBankAccount.account }}</cc-details-item>
</div>

View File

@ -1,10 +0,0 @@
import { Component, Input } from '@angular/core';
import { RussianBankAccount } from '@vality/domain-proto/domain';
@Component({
selector: 'cc-russian-bank-account-details',
templateUrl: './russian-bank-account-details.component.html',
})
export class RussianBankAccountDetailsComponent {
@Input() russianBankAccount: RussianBankAccount;
}

View File

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

View File

@ -1,48 +0,0 @@
<div style="display: grid; gap: 16px">
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px">
<cc-details-item title="ID">{{ payoutTool.id }}</cc-details-item>
<cc-details-item title="Created At">{{ payoutTool.created_at }}</cc-details-item>
<cc-details-item title="Currency">{{ payoutTool.currency?.symbolic_code }}</cc-details-item>
</div>
<ng-container
*ngIf="(payoutTool.payout_tool_info | ngtUnionKey) === 'international_bank_account'"
>
<h2 class="mat-h3">International bank account</h2>
<cc-international-bank-account-details
[internationalBankAccount]="payoutTool.payout_tool_info.international_bank_account"
></cc-international-bank-account-details>
<ng-container
*ngIf="payoutTool.payout_tool_info.international_bank_account?.correspondent_account"
>
<h2 class="mat-h3">Correspondent account</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px">
<cc-international-bank-account-details
[internationalBankAccount]="
payoutTool.payout_tool_info.international_bank_account.correspondent_account
"
></cc-international-bank-account-details>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="(payoutTool.payout_tool_info | ngtUnionKey) === 'russian_bank_account'">
<h2 class="mat-h3">Russian bank account</h2>
<cc-russian-bank-account-details
[russianBankAccount]="payoutTool.payout_tool_info.russian_bank_account"
></cc-russian-bank-account-details>
</ng-container>
<ng-container *ngIf="(payoutTool.payout_tool_info | ngtUnionKey) === 'wallet_info'">
<h2 class="mat-h3">Wallet</h2>
<cc-details-item title="Wallet ID">{{
payoutTool.payout_tool_info.wallet_info.wallet_id
}}</cc-details-item>
</ng-container>
<ng-container
*ngIf="(payoutTool.payout_tool_info | ngtUnionKey) === 'payment_institution_account'"
>
<h2 class="mat-h3">Payment institution account</h2>
</ng-container>
</div>

View File

@ -1,10 +0,0 @@
import { Component, Input } from '@angular/core';
import { PayoutTool } from '@vality/domain-proto/domain';
@Component({
selector: 'cc-payout-tool-details',
templateUrl: './payout-tool-details.component.html',
})
export class PayoutToolDetailsComponent {
@Input() payoutTool: PayoutTool;
}

View File

@ -1,20 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ThriftPipesModule } from '@vality/ng-thrift';
import { DetailsItemModule } from '@cc/components/details-item';
import { InternationalBankAccountDetailsComponent } from './components/international-bank-account-details/international-bank-account-details.component';
import { RussianBankAccountDetailsComponent } from './components/russian-bank-account-details/russian-bank-account-details.component';
import { PayoutToolDetailsComponent } from './payout-tool-details.component';
@NgModule({
declarations: [
PayoutToolDetailsComponent,
RussianBankAccountDetailsComponent,
InternationalBankAccountDetailsComponent,
],
imports: [CommonModule, DetailsItemModule, ThriftPipesModule],
exports: [PayoutToolDetailsComponent],
})
export class PayoutToolDetailsModule {}

View File

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

View File

@ -1,7 +0,0 @@
<v-select-field
[disabled]="!(partyId$ | async) || !(shopId$ | async)"
[formControl]="control"
[label]="label || 'Payout Tool'"
[options]="options$ | async"
[required]="required"
></v-select-field>

View File

@ -1,66 +0,0 @@
import { Component, Input, OnInit, booleanAttribute } from '@angular/core';
import { PayoutTool } from '@vality/domain-proto/domain';
import { PartyID, ShopID } from '@vality/domain-proto/payment_processing';
import {
FormControlSuperclass,
Option,
createControlProviders,
NotifyLogService,
handleError,
} from '@vality/ng-core';
import { BehaviorSubject, combineLatest, defer, Observable, of, switchMap } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { PartyManagementService } from '@cc/app/api/payment-processing';
@Component({
selector: 'cc-payout-tool-field',
templateUrl: 'payout-tool-field.component.html',
providers: createControlProviders(() => PayoutToolFieldComponent),
})
export class PayoutToolFieldComponent
extends FormControlSuperclass<PayoutTool['id']>
implements OnInit
{
@Input() label: string;
@Input({ transform: booleanAttribute }) required: boolean;
@Input() set partyId(partyId: PartyID) {
this.partyId$.next(partyId);
}
@Input() set shopId(shopId: ShopID) {
this.shopId$.next(shopId);
}
partyId$ = new BehaviorSubject<PartyID>(null);
shopId$ = new BehaviorSubject<ShopID>(null);
options$: Observable<Option<PayoutTool['id']>[]> = defer(() => this.payoutTools$).pipe(
map((payoutTools) =>
payoutTools.map((t) => ({ label: t.id, value: t.id, description: t.id })),
),
shareReplay({ refCount: true, bufferSize: 1 }),
);
private payoutTools$ = combineLatest([this.partyId$, this.shopId$]).pipe(
switchMap(([partyId, shopId]) =>
partyId && shopId
? this.partyManagementService
.GetShop(partyId, shopId)
.pipe(
switchMap(({ contract_id }) =>
this.partyManagementService.GetContract(partyId, contract_id),
),
map((contract) => contract.payout_tools),
)
.pipe(handleError(this.log.error, []))
: of<PayoutTool[]>([]),
),
shareReplay({ refCount: true, bufferSize: 1 }),
);
constructor(
private partyManagementService: PartyManagementService,
private log: NotifyLogService,
) {
super();
}
}

View File

@ -1,23 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { SelectFieldModule } from '@vality/ng-core';
import { PayoutToolFieldComponent } from './payout-tool-field.component';
@NgModule({
imports: [
MatFormFieldModule,
ReactiveFormsModule,
MatAutocompleteModule,
MatInputModule,
CommonModule,
SelectFieldModule,
],
declarations: [PayoutToolFieldComponent],
exports: [PayoutToolFieldComponent],
})
export class PayoutToolFieldModule {}

View File

@ -7,6 +7,5 @@ export enum Services {
ClaimManagement = 'ClaimManagement', ClaimManagement = 'ClaimManagement',
Invoicing = 'Invoicing', Invoicing = 'Invoicing',
RepairManagement = 'RepairManagement', RepairManagement = 'RepairManagement',
PayoutManagement = 'PayoutManagement',
Dominator = 'Dominator', Dominator = 'Dominator',
} }