FRONTEND-542,543,545: Add payment institution & create shop fixes (#451)

This commit is contained in:
Rinat Arsaev 2021-04-30 17:11:22 +03:00 committed by GitHub
parent 8714939d3e
commit 7b319b96dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 256 additions and 203 deletions

View File

@ -7,7 +7,7 @@
"build": "ng build --prod --extraWebpackConfig webpack.extra.js --progress=false",
"test": "ng test",
"test-ci": "ng run dashboard:test-ci",
"lint": "eslint \"src/**/*.{ts,js,html}\" --max-warnings 2379",
"lint": "eslint \"src/**/*.{ts,js,html}\" --max-warnings 2361",
"lint-errors": "npm run lint -- --quiet",
"lint-fix": "npm run lint -- --fix",
"e2e": "ng e2e",

View File

@ -6,7 +6,7 @@ import {
import { createBaseContractModification } from './create-base-contract-modification';
export function createContractPayoutToolModification(
export function createContractPayoutToolCreationModification(
id: string,
payoutToolID: string,
params: Omit<ContractPayoutToolModification, 'payoutToolModificationType'>

View File

@ -0,0 +1,30 @@
import {
ContractModification,
ContractPayoutToolModification,
PartyModification,
} from '@dsh/api-codegen/claim-management';
import { createBaseContractModification } from './create-base-contract-modification';
export function createContractPayoutToolInfoModification(
id: string,
payoutToolID: string,
params: Omit<ContractPayoutToolModification, 'payoutToolModificationType'>
): PartyModification {
return {
...createBaseContractModification({
id,
modification: {
contractModificationType:
ContractModification.ContractModificationTypeEnum.ContractPayoutToolModificationUnit,
payoutToolID,
modification: {
payoutToolModificationType:
ContractPayoutToolModification.PayoutToolModificationTypeEnum
.ContractPayoutToolInfoModification,
...params,
},
},
}),
};
}

View File

@ -1,5 +1,5 @@
import { InternationalBankAccount, PartyModification, PayoutToolInfo } from '@dsh/api-codegen/claim-management';
import { createContractPayoutToolModification } from '@dsh/api/claims/claim-party-modification';
import { createContractPayoutToolCreationModification } from '@dsh/api/claims/claim-party-modification';
import PayoutToolTypeEnum = PayoutToolInfo.PayoutToolTypeEnum;
@ -8,7 +8,7 @@ export function createInternationalContractPayoutToolModification(
payoutToolID: string,
params: Omit<InternationalBankAccount, 'payoutToolType'>
): PartyModification {
return createContractPayoutToolModification(id, payoutToolID, {
return createContractPayoutToolCreationModification(id, payoutToolID, {
currency: {
symbolicCode: 'USD',
},

View File

@ -1,14 +1,14 @@
import { PartyModification, PayoutToolInfo, RussianBankAccount } from '@dsh/api-codegen/claim-management';
import { RussianShopCreateData } from '../../../../sections/payment-section/integrations/shops/shop-creation/create-russian-shop-entity/types/russian-shop-create-data';
import { createContractPayoutToolModification } from './create-contract-payout-tool-modification';
import { createContractPayoutToolCreationModification } from './create-contract-payout-tool-creation-modification';
export function createRussianContractPayoutToolModification(
export function createRussianContractPayoutToolCreationModification(
id: string,
payoutToolID: string,
params: Omit<RussianBankAccount, 'payoutToolType'>
): PartyModification {
return createContractPayoutToolModification(id, payoutToolID, {
return createContractPayoutToolCreationModification(id, payoutToolID, {
currency: {
symbolicCode: 'RUB',
},
@ -19,12 +19,12 @@ export function createRussianContractPayoutToolModification(
});
}
export function createTestRussianContractPayoutToolModification(
export function createTestRussianContractPayoutToolCreationModification(
id: string,
payoutToolID: string,
{ bankAccount: { account, bankName, bankPostAccount, bankBik } }: RussianShopCreateData
): PartyModification {
return createRussianContractPayoutToolModification(id, payoutToolID, {
return createRussianContractPayoutToolCreationModification(id, payoutToolID, {
account,
bankName,
bankPostAccount,

View File

@ -0,0 +1,16 @@
import { PartyModification, PayoutToolInfo, RussianBankAccount } from '@dsh/api-codegen/claim-management';
import { createContractPayoutToolInfoModification } from './create-contract-payout-tool-info-modification';
export function createRussianContractPayoutToolInfoModification(
id: string,
payoutToolID: string,
params: Omit<RussianBankAccount, 'payoutToolType'>
): PartyModification {
return createContractPayoutToolInfoModification(id, payoutToolID, {
payoutToolInfo: {
payoutToolType: PayoutToolInfo.PayoutToolTypeEnum.RussianBankAccount,
...params,
},
});
}

View File

@ -1,3 +1,4 @@
export * from './create-contract-payout-tool-modification';
export * from './create-contract-payout-tool-creation-modification';
export * from './create-contract-creation-modification';
export * from './create-russian-contract-payout-tool-modification';
export * from './create-russian-contract-payout-tool-creation-modification';
export * from './create-russian-contract-payout-tool-info-modification';

View File

@ -9,7 +9,7 @@ import {
} from '../../../../api-codegen/claim-management';
import {
createContractCreationModification,
createRussianContractPayoutToolModification,
createRussianContractPayoutToolCreationModification,
} from '../claim-contract-modification';
import { createContractLegalAgreementBindingModification } from '../claim-contract-modification/create-contract-legal-agreement-binding-modification';
import {
@ -67,6 +67,6 @@ export const createTestShopModifications = ({
createRussianLegalEntityModification(contractorID, TEST_RUSSIAN_LEGAL_ENTITY),
createContractCreationModification(contractID, { contractorID }),
createContractLegalAgreementBindingModification(contractID, createTestLegalAgreement()),
createRussianContractPayoutToolModification(contractID, payoutToolID, TEST_RUSSIAN_BANK_ACCOUNT),
createRussianContractPayoutToolCreationModification(contractID, payoutToolID, TEST_RUSSIAN_BANK_ACCOUNT),
createShopCreationModification(shopID, { ...TEST_SHOP_CREATION, contractID, payoutToolID }),
];

View File

@ -38,14 +38,14 @@ describe('ShopContractDetailsService', () => {
it('should tick contract value if contracts came with no errors', () => {
const creationDate = new Date();
// can't test it with cold/hot marbles cause it's an subject
service.shopContract$.pipe(take(1)).subscribe((data: Contract) => {
service.shopContract$.pipe(take(1)).subscribe((data) => {
expect(data).toEqual({
id: 'my_id',
createdAt: creationDate,
status: Contract.StatusEnum.Active,
contractor: {
contractorType: 'LegalEntity',
},
} as any,
paymentInstitutionID: 2,
});
});

View File

@ -1,42 +1,50 @@
import { Injectable } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { BehaviorSubject, defer, Observable, of, ReplaySubject, Subject } from 'rxjs';
import { catchError, distinctUntilChanged, filter, switchMap, tap } from 'rxjs/operators';
import { Overwrite } from 'utility-types';
import { Contract } from '@dsh/api-codegen/capi';
import { RussianLegalEntity } from '@dsh/api-codegen/claim-management';
import { ContractsService } from '@dsh/api/contracts';
@UntilDestroy()
@Injectable()
export class ShopContractDetailsService {
shopContract$: Observable<Contract>;
errorOccurred$: Observable<boolean>;
shopContract$: Observable<Overwrite<Contract, { contractor: RussianLegalEntity }>> = defer(() =>
this.contract$.asObservable()
);
errorOccurred$: Observable<boolean> = defer(() => this.error$.asObservable());
isLoading$: Observable<boolean> = defer(() => this._isLoading$.asObservable());
private contractRequest$: Subject<string> = new Subject();
private error$: Subject<any> = new BehaviorSubject(false);
private contract$: Subject<Contract> = new Subject();
// TODO: contract errors not forwarded
private error$ = new BehaviorSubject<boolean>(false);
private contract$ = new ReplaySubject<Overwrite<Contract, { contractor: RussianLegalEntity }>>();
private _isLoading$ = new BehaviorSubject<boolean>(false);
constructor(private contractsService: ContractsService) {
this.shopContract$ = this.contract$.asObservable();
this.errorOccurred$ = this.error$.asObservable();
this.contractRequest$
.pipe(
tap(() => this.error$.next(false)),
distinctUntilChanged(),
tap(() => this._isLoading$.next(true)),
switchMap((contractID) =>
this.contractsService.getContractByID(contractID).pipe(
catchError((e) => {
console.error(e);
this.error$.next(true);
return of('error');
})
)
contractID
? this.contractsService.getContractByID(contractID).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((contract) => this.contract$.next(contract as Contract));
.subscribe((contract) => this.contract$.next(contract));
}
requestContract(contractID: string): void {

View File

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { BehaviorSubject, Observable, of, ReplaySubject, Subject } from 'rxjs';
import { BehaviorSubject, defer, Observable, of, ReplaySubject, Subject } from 'rxjs';
import { catchError, distinctUntilChanged, filter, switchMap, tap } from 'rxjs/operators';
import { PayoutTool } from '@dsh/api-codegen/capi';
@ -13,10 +13,12 @@ import { PayoutToolParams } from '../../shops-list/shop-details/types/payout-too
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();
@ -26,19 +28,27 @@ export class ShopPayoutToolDetailsService {
.pipe(
tap(() => this.error$.next(false)),
distinctUntilChanged(),
switchMap(({ contractID, payoutToolID }) =>
this.payoutsService.getPayoutToolByID(contractID, payoutToolID).pipe(
catchError((e) => {
console.error(e);
this.error$.next(true);
return of('error');
})
)
tap(() => this._isLoading$.next(true)),
switchMap((payoutToolParams) =>
payoutToolParams
? this.payoutsService
.getPayoutToolByID(payoutToolParams.contractID, 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));
.subscribe((payoutTool: PayoutTool) => {
this.payoutTool$.next(payoutTool);
});
}
requestPayoutTool(params: PayoutToolParams): void {

View File

@ -12,5 +12,16 @@
[scrollableWindow]="contentWindow"
>
</dsh-autocomplete-virtual-scroll>
<dsh-payout-tool-details *ngIf="payoutTool" [payoutToolDetails]="payoutTool.details"></dsh-payout-tool-details>
<ng-container *transloco="let t">
<div *ngIf="isLoading; else hasError ? error : loaded" class="dsh-body-1">{{ t('loading') }}</div>
<ng-template #error>
<div class="dsh-body-1">{{ t('errors.common') }}</div>
</ng-template>
<ng-template #loaded>
<dsh-payout-tool-details
*ngIf="payoutTool"
[payoutToolDetails]="payoutTool.details"
></dsh-payout-tool-details>
</ng-template>
</ng-container>
</form>

View File

@ -21,6 +21,8 @@ import { ShopOptionsSelectionService } from '../../services/shop-options-selecti
export class ExistingBankAccountComponent implements OnInit {
@Input() form: FormGroup;
@Input() payoutTool: PayoutTool;
@Input() isLoading: boolean;
@Input() hasError: boolean;
@Input() contentWindow: HTMLElement;
shopsList$: Observable<BaseOption<string>[]> = this.shopOptionsService.options$;

View File

@ -12,18 +12,24 @@
[scrollableWindow]="contentWindow"
>
</dsh-autocomplete-virtual-scroll>
<ng-container *ngTemplateOutlet="contractDetails; context: { $implicit: contract$ | async }"></ng-container>
</div>
<ng-template #contractDetails let-data>
<ng-container *transloco="let t; scope: 'api-model-details'; read: 'apiModelDetails.russianLegalEntity'">
<div *ngIf="data" fxLayout fxLayoutGap="24px">
<dsh-details-item fxFlex [title]="t('registeredName')">
{{ data.contractor.registeredName }}
</dsh-details-item>
<dsh-details-item fxFlex [title]="t('inn')">
{{ data.contractor.inn }}
</dsh-details-item>
<ng-container class="dsh-body-1" *transloco="let t">
<div *ngIf="isLoading$ | async; else (hasError$ | async) ? error : loaded" class="dsh-body-1">
{{ t('loading') }}
</div>
<ng-template #error>
<div class="dsh-body-1">{{ t('errors.common') }}</div>
</ng-template>
<ng-template #loaded>
<ng-container *transloco="let d; scope: 'api-model-details'; read: 'apiModelDetails.russianLegalEntity'">
<div *ngIf="contract$ | async as data" fxLayout fxLayoutGap="24px">
<dsh-details-item fxFlex [title]="d('registeredName')">
{{ data.contractor.registeredName }}
</dsh-details-item>
<dsh-details-item fxFlex [title]="d('inn')">
{{ data.contractor.inn }}
</dsh-details-item>
</div>
</ng-container>
</ng-template>
</ng-container>
</ng-template>
</div>

View File

@ -102,7 +102,7 @@ describe('ShopContractComponent', () => {
};
const componentControl = new FormControl();
when(mockShopContractDetailsService.shopContract$).thenReturn(of(contract));
when(mockShopContractDetailsService.shopContract$).thenReturn(of(contract as any));
await getTestingModule();
createComponent();

View File

@ -2,10 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import { Shop } from '@dsh/api-codegen/anapi';
import { Contract } from '@dsh/api-codegen/capi';
import { BaseOption } from '@dsh/app/shared/components/selects/autocomplete-virtual-scroll/types/base-option';
import { ShopContractDetailsService } from '../../../../services/shop-contract-details/shop-contract-details.service';
@ -23,7 +20,9 @@ export class ShopContractComponent implements OnInit {
shopsList$: Observable<BaseOption<string>[]> = this.shopOptionsService.options$;
shopControl: FormControl = this.shopOptionsService.control;
contract$: Observable<Contract> = this.contractService.shopContract$;
contract$ = this.contractService.shopContract$;
isLoading$ = this.contractService.isLoading$;
hasError$ = this.contractService.errorOccurred$;
constructor(
private shopOptionsService: ShopOptionsSelectionService,
@ -36,13 +35,13 @@ export class ShopContractComponent implements OnInit {
}
private initContractRequests(): void {
this.shopOptionsService.selectedShop$.pipe(filter(Boolean), untilDestroyed(this)).subscribe((shop: Shop) => {
this.contractService.requestContract(shop.contractID);
this.shopOptionsService.selectedShop$.pipe(untilDestroyed(this)).subscribe((shop) => {
this.contractService.requestContract(shop?.contractID);
});
}
private initContractUpdater(): void {
this.contract$.pipe(untilDestroyed(this)).subscribe((contract: Contract) => {
this.contract$.pipe(untilDestroyed(this)).subscribe((contract) => {
this.control.setValue(contract);
});
}

View File

@ -47,6 +47,8 @@
*ngIf="isExistingBankAccount"
[form]="form"
[payoutTool]="payoutTool"
[isLoading]="isLoading"
[hasError]="hasError"
[contentWindow]="contentWindow"
></dsh-existing-bank-account>
</div>

View File

@ -20,6 +20,8 @@ import { BankAccountType } from '../../types/bank-account-type';
export class ShopFormComponent implements OnInit {
@Input() form: FormGroup;
@Input() payoutTool: PayoutTool;
@Input() isLoading: boolean;
@Input() hasError: boolean;
@Input() contentWindow: HTMLElement;
shops$: Observable<Shop[]> = this.shopService.allShops$;

View File

@ -1,6 +1,13 @@
<ng-container *transloco="let t; scope: 'create-shop'; read: 'createShop.russianLegalEntity'">
<dsh-base-dialog [title]="t('title')" (cancel)="cancelCreation()">
<dsh-shop-form #content [form]="form" [payoutTool]="payoutTool$ | async" [contentWindow]="contentElement">
<dsh-shop-form
#content
[form]="form"
[payoutTool]="payoutTool$ | async"
[isLoading]="isLoading$ | async"
[hasError]="hasError$ | async"
[contentWindow]="contentElement"
>
</dsh-shop-form>
<div dshBaseDialogActions fxLayout="row" fxLayoutAlign="space-between center">
<button *transloco="let t" dsh-stroked-button color="warn" fxFlex="126px" (click)="cancelCreation()">

View File

@ -163,7 +163,7 @@ describe('CreateRussianShopEntityComponent', () => {
expect().nothing();
});
it('should do nothing if selected shop was not found in shopsList', () => {
it('should call with null if selected shop was not found in shopsList', () => {
const mockList = generateMockShopsList(5);
when(mockFetchShopsService.allShops$).thenReturn(of(mockList));
when(mockShopPayoutToolDetailsService.requestPayoutTool).thenReturn(() => null);
@ -172,7 +172,7 @@ describe('CreateRussianShopEntityComponent', () => {
component.form.get(BANK_SHOP_ID_FIELD).setValue(null);
verify(mockShopPayoutToolDetailsService.requestPayoutTool).never();
verify(mockShopPayoutToolDetailsService.requestPayoutTool).once();
expect().nothing();
});
});

View File

@ -14,13 +14,15 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import pick from 'lodash-es/pick';
import { Observable, of } from 'rxjs';
import { filter, map, switchMap, take, withLatestFrom } from 'rxjs/operators';
import { map, pluck, switchMap, take, withLatestFrom } from 'rxjs/operators';
import { BankAccount, PayoutTool, Shop } from '@dsh/api-codegen/capi';
import { FetchShopsService } from '../../services/fetch-shops/fetch-shops.service';
import { ShopPayoutToolDetailsService } from '../../services/shop-payout-tool-details/shop-payout-tool-details.service';
import { PayoutToolParams } from '../../shops-list/shop-details/types/payout-tool-params';
import {
BANK_ACCOUNT_TYPE_FIELD,
BANK_SHOP_ID_FIELD,
@ -34,7 +36,6 @@ import {
} from './consts';
import { CreateRussianShopEntityService } from './services/create-russian-shop-entity/create-russian-shop-entity.service';
import { BankAccountType } from './types/bank-account-type';
import { RussianShopCreateData } from './types/russian-shop-create-data';
import { RussianShopEntity } from './types/russian-shop-entity';
@UntilDestroy()
@ -67,6 +68,8 @@ export class CreateRussianShopEntityComponent implements OnInit, AfterViewInit {
});
payoutTool$: Observable<PayoutTool> = this.payoutToolService.shopPayoutTool$;
isLoading$ = this.payoutToolService.isLoading$;
hasError$ = this.payoutToolService.errorOccurred$;
get contentElement(): HTMLElement | undefined {
return this.contentRef?.nativeElement?.parentElement;
@ -89,11 +92,12 @@ export class CreateRussianShopEntityComponent implements OnInit, AfterViewInit {
.valueChanges.pipe(
withLatestFrom(this.shopService.allShops$),
map(([shopID, shops]: [string, Shop[]]) => shops.find(({ id }: Shop) => id === shopID)),
filter(Boolean),
untilDestroyed(this)
)
.subscribe(({ contractID, payoutToolID }: Shop) => {
this.payoutToolService.requestPayoutTool({ contractID, payoutToolID });
.subscribe((shop) => {
this.payoutToolService.requestPayoutTool(
shop ? (pick(shop, ['contractID', 'payoutToolID']) as PayoutToolParams) : null
);
});
}
@ -109,29 +113,27 @@ export class CreateRussianShopEntityComponent implements OnInit, AfterViewInit {
createShop(): void {
const { url, name, bankAccountType, newBankAccount, contract } = this.form.value as RussianShopEntity;
let bankAccount$: Observable<BankAccount> = of(newBankAccount);
let payoutToolID$: Observable<string | null> = of(null);
let payoutToolId$: Observable<string> = of<string>(null);
if (bankAccountType === BankAccountType.Existing) {
bankAccount$ = this.payoutTool$.pipe(map(({ details }: PayoutTool) => (details as any) as BankAccount));
payoutToolID$ = this.payoutTool$.pipe(map(({ id }: PayoutTool) => id));
bankAccount$ = this.payoutTool$.pipe(map(({ details }) => (details as any) as BankAccount));
payoutToolId$ = this.payoutTool$.pipe(pluck('id'));
}
bankAccount$
.pipe(
withLatestFrom(payoutToolID$),
map(([bankAccount, payoutToolID]: [BankAccount, string | null]) => {
return {
withLatestFrom(payoutToolId$),
switchMap(([bankAccount, payoutToolID]) =>
this.createShopRussianLegalEntityService.createShop({
url,
name,
contract,
payoutToolID,
bankAccount,
};
}),
switchMap((createData: RussianShopCreateData) => {
return this.createShopRussianLegalEntityService.createShop(createData);
}),
take(1)
})
),
take(1),
untilDestroyed(this)
)
.subscribe(
({ id }) => {

View File

@ -2,12 +2,12 @@ import { TestBed } from '@angular/core/testing';
import { cold } from 'jasmine-marbles';
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
import { deepEqual, instance, mock, verify, when } from 'ts-mockito';
import { anything, deepEqual, instance, mock, verify, when } from 'ts-mockito';
import { Contract } from '@dsh/api-codegen/capi';
import { Claim, Modification } from '@dsh/api-codegen/claim-management';
import { ClaimsService } from '@dsh/api/claims';
import { createTestContractCreationModification } from '@dsh/api/claims/claim-party-modification';
import { createContractCreationModification } from '@dsh/api/claims/claim-party-modification';
import { IdGeneratorService } from '@dsh/app/shared/services/id-generator/id-generator.service';
import { createTestLegalEntityModification } from '../../tests/create-test-legal-entity-modification';
@ -18,6 +18,36 @@ import { CreateRussianShopEntityService } from './create-russian-shop-entity.ser
const TEST_UUID = 'test-uuid';
const CREATION_DATA: RussianShopCreateData = {
payoutToolID: 'my_id',
url: 'www.example.com',
name: 'test shop',
bankAccount: {
bankBik: '0000000',
bankName: 'test bank',
bankPostAccount: 'post account',
account: 'account',
},
contract: {
id: 'contract_id',
createdAt: new Date(),
status: Contract.StatusEnum.Active,
paymentInstitutionID: 1,
contractor: {
contractorType: 'LegalEntity',
actualAddress: 'actualAddress',
bankAccount: 'bankAccount',
inn: 'inn',
postAddress: 'postAddress',
registeredName: 'registeredName',
registeredNumber: 'registeredNumber',
representativeDocument: 'representativeDocument',
representativeFullName: 'representativeFullName',
representativePosition: 'representativePosition',
} as any,
},
};
describe('CreateRussianShopEntityService', () => {
let service: CreateRussianShopEntityService;
let mockClaimsService: ClaimsService;
@ -58,35 +88,7 @@ describe('CreateRussianShopEntityService', () => {
revision: 5,
createdAt: new Date(),
};
let creationData: RussianShopCreateData = {
payoutToolID: 'my_id',
url: 'www.example.com',
name: 'test shop',
bankAccount: {
bankBik: '0000000',
bankName: 'test bank',
bankPostAccount: 'post account',
account: 'account',
},
contract: {
id: 'contract_id',
createdAt: new Date(),
status: Contract.StatusEnum.Active,
paymentInstitutionID: 1,
contractor: {
contractorType: 'LegalEntity',
actualAddress: 'actualAddress',
bankAccount: 'bankAccount',
inn: 'inn',
postAddress: 'postAddress',
registeredName: 'registeredName',
registeredNumber: 'registeredNumber',
representativeDocument: 'representativeDocument',
representativeFullName: 'representativeFullName',
representativePosition: 'representativePosition',
} as any,
},
};
let creationData: RussianShopCreateData = CREATION_DATA;
let modifications: Modification[];
beforeEach(() => {
@ -98,43 +100,18 @@ describe('CreateRussianShopEntityService', () => {
});
it('should call create claim with existing payout tool modifications', () => {
creationData = {
payoutToolID: 'my_id',
url: 'www.example.com',
name: 'test shop',
bankAccount: {
bankBik: '0000000',
bankName: 'test bank',
bankPostAccount: 'post account',
account: 'account',
},
contract: {
id: 'contract_id',
createdAt: new Date(),
status: Contract.StatusEnum.Active,
paymentInstitutionID: 1,
contractor: {
contractorType: 'LegalEntity',
actualAddress: 'actualAddress',
bankAccount: 'bankAccount',
inn: 'inn',
postAddress: 'postAddress',
registeredName: 'registeredName',
registeredNumber: 'registeredNumber',
representativeDocument: 'representativeDocument',
representativeFullName: 'representativeFullName',
representativePosition: 'representativePosition',
} as any,
},
};
creationData = CREATION_DATA;
modifications = [
createTestLegalEntityModification(TEST_UUID, creationData),
createTestContractCreationModification(TEST_UUID, TEST_UUID),
createContractCreationModification(TEST_UUID, {
contractorID: TEST_UUID,
paymentInstitution: { id: creationData.contract.paymentInstitutionID },
}),
createTestShopCreationModification(TEST_UUID, TEST_UUID, 'my_id', creationData),
];
when(mockClaimsService.createClaim(deepEqual(modifications))).thenReturn(of(claim));
when(mockClaimsService.createClaim(anything())).thenReturn(of(claim));
when(mockClaimsService.requestReviewClaimByID).thenReturn(() => of(null));
service.createShop(creationData);
@ -143,39 +120,14 @@ describe('CreateRussianShopEntityService', () => {
});
it('should call create claim with new payout tool modifications', () => {
creationData = {
payoutToolID: null,
url: 'www.example.com',
name: 'test shop',
bankAccount: {
bankBik: '0000000',
bankName: 'test bank',
bankPostAccount: 'post account',
account: 'account',
},
contract: {
id: 'contract_id',
createdAt: new Date(),
status: Contract.StatusEnum.Active,
paymentInstitutionID: 1,
contractor: {
contractorType: 'LegalEntity',
actualAddress: 'actualAddress',
bankAccount: 'bankAccount',
inn: 'inn',
postAddress: 'postAddress',
registeredName: 'registeredName',
registeredNumber: 'registeredNumber',
representativeDocument: 'representativeDocument',
representativeFullName: 'representativeFullName',
representativePosition: 'representativePosition',
} as any,
},
};
creationData = { ...CREATION_DATA, payoutToolID: null };
modifications = [
createTestLegalEntityModification(TEST_UUID, creationData),
createTestContractCreationModification(TEST_UUID, TEST_UUID),
createContractCreationModification(TEST_UUID, {
contractorID: TEST_UUID,
paymentInstitution: { id: creationData.contract.paymentInstitutionID },
}),
createTestRussianContractPayoutToolModification(TEST_UUID, TEST_UUID, creationData),
createTestShopCreationModification(TEST_UUID, TEST_UUID, TEST_UUID, creationData),
];

View File

@ -1,14 +1,13 @@
import { Injectable } from '@angular/core';
import isNil from 'lodash-es/isNil';
import { forkJoin, Observable, of } from 'rxjs';
import { pluck, switchMap } from 'rxjs/operators';
import { Claim, PartyModification } from '@dsh/api-codegen/claim-management';
import { Claim, PartyModification, RussianBankAccount, RussianLegalEntity } from '@dsh/api-codegen/claim-management';
import { ClaimsService } from '@dsh/api/claims';
import {
createContractCreationModification,
createRussianBankAccountModification,
createRussianContractPayoutToolModification,
createRussianContractPayoutToolCreationModification,
createRussianLegalEntityModification,
createShopCreationModification,
makeShopLocation,
@ -34,29 +33,13 @@ export class CreateRussianShopEntityService {
url,
name,
contract,
payoutToolID: shopPayoutToolID,
payoutToolID,
bankAccount: { account, bankName, bankPostAccount, bankBik },
}: RussianShopCreateData): PartyModification[] {
const contractorID = this.idGenerator.generateUUID();
const contractID = this.idGenerator.generateUUID();
const shopID = this.idGenerator.generateUUID();
let payoutToolID = this.idGenerator.generateUUID();
const payoutChangeset: PartyModification[] = [];
if (isNil(shopPayoutToolID)) {
payoutChangeset.push(
createRussianContractPayoutToolModification(contractID, payoutToolID, {
account,
bankName,
bankPostAccount,
bankBik,
})
);
} else {
payoutToolID = shopPayoutToolID;
}
const {
actualAddress,
bankAccount: russianBankAccount,
@ -67,10 +50,16 @@ export class CreateRussianShopEntityService {
representativeDocument,
representativeFullName,
representativePosition,
} = contract.contractor as any;
// TODO: add valid type for contractor object
} = (contract.contractor as unknown) as RussianLegalEntity & { bankAccount: RussianBankAccount }; // TODO: add valid type for contractor object
return [
const bankAccount: Omit<RussianBankAccount, 'payoutToolType'> = {
account,
bankName,
bankPostAccount,
bankBik,
};
const result: PartyModification[] = [
createRussianLegalEntityModification(contractorID, {
actualAddress,
russianBankAccount: createRussianBankAccountModification(russianBankAccount),
@ -84,8 +73,21 @@ export class CreateRussianShopEntityService {
}),
createContractCreationModification(contractID, {
contractorID,
paymentInstitution: { id: contract.paymentInstitutionID },
}),
...payoutChangeset,
];
if (!payoutToolID) {
payoutToolID = this.idGenerator.generateUUID();
result.push(
createRussianContractPayoutToolCreationModification(
contractID,
this.idGenerator.generateUUID(),
bankAccount
)
);
}
return [
...result,
createShopCreationModification(shopID, {
category: {
categoryID: 1,

View File

@ -50,7 +50,6 @@ export class ShopOptionsSelectionService {
return shopsList.find((shop: Shop) => shop.id === selected.id);
}),
map((shop: Shop | undefined | null) => (isNil(shop) ? null : shop)),
shareReplay(SHARE_REPLAY_CONF),
untilDestroyed(this)
)
.subscribe((selectedShop: Shop | null) => {

View File

@ -1,5 +1,5 @@
import { PartyModification } from '@dsh/api-codegen/claim-management';
import { createRussianContractPayoutToolModification } from '@dsh/api/claims/claim-party-modification';
import { createRussianContractPayoutToolCreationModification } from '@dsh/api/claims/claim-party-modification';
import { RussianShopCreateData } from '../types/russian-shop-create-data';
@ -8,7 +8,7 @@ export function createTestRussianContractPayoutToolModification(
payoutToolID: string,
{ bankAccount: { account, bankName, bankPostAccount, bankBik } }: RussianShopCreateData
): PartyModification {
return createRussianContractPayoutToolModification(id, payoutToolID, {
return createRussianContractPayoutToolCreationModification(id, payoutToolID, {
account,
bankName,
bankPostAccount,

View File

@ -9,7 +9,7 @@
[required]="required"
/>
<button mat-button *ngIf="searchControl.value" matSuffix mat-icon-button aria-label="Clear" (click)="clearValue()">
<mat-icon>close</mat-icon>
<mat-icon svgIcon="cross"></mat-icon>
</button>
<mat-autocomplete #autocomplete="matAutocomplete" (opened)="panelOpened()">
<cdk-virtual-scroll-viewport

View File

@ -149,6 +149,7 @@
"confirm": "Подтвердить"
},
"errors": {
"common": "Произошла ошибка",
"saveConversationsFailed": "Не удалось сохранить комментарий",
"revokeClaimByIDFailed": "Не удалось отозвать заявку",
"requestReviewClaimByIDFailed": "Не удалось отправить заявку на рассмотрение",

View File

@ -1 +1,4 @@
/**
* @deprecated use utility-types/Overwrite
*/
export type Replace<T, K> = Omit<T, keyof K> & K;