FE-908. Create deposit (#86)

* withdrawals

* create deposit

* create deposit

* source was removed

* fixes

* another fixes
This commit is contained in:
Denis Ezhov 2019-10-04 12:53:00 +03:00 committed by GitHub
parent 4ed80347e1
commit 1e15ef75fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 273 additions and 9 deletions

@ -1 +1 @@
Subproject commit 9e92a504f08f2294e0451f4e902d376763d38180
Subproject commit b9b18f3ee375aa5fd105daf57189ac242c40f572

2
package-lock.json generated
View File

@ -14271,7 +14271,7 @@
},
"stream-http": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.3.1.tgz",
"resolved": "http://registry.npmjs.org/stream-http/-/stream-http-2.3.1.tgz",
"integrity": "sha1-fh3IcQLD4xsy5mDwTKMfI929HVI=",
"requires": {
"builtin-status-codes": "^2.0.0",

View File

@ -1,10 +1,12 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { MatIconModule, MatMenuModule } from '@angular/material';
xdescribe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent]
declarations: [AppComponent],
imports: [MatIconModule, MatMenuModule]
}).compileComponents();
}));
it('should create the app', async(() => {

View File

@ -33,7 +33,8 @@ export class AppComponent implements OnInit {
activateRole: 'adjustment:create'
},
{ name: 'Parties', route: '/parties', activateRole: 'party:get' },
{ name: 'Repairing', route: '/repairing', activateRole: 'party:get' }
{ name: 'Repairing', route: '/repairing', activateRole: 'party:get' },
{ name: 'Deposits', route: '/deposits', activateRole: 'deposit:write' }
];
const roles = this.keycloakService.getUserRoles();
return menuItems.filter(item => roles.includes(item.activateRole));

View File

@ -27,8 +27,9 @@ import { PayoutsModule } from './payouts/payouts.module';
import { PaymentAdjustmentModule } from './payment-adjustment/payment-adjustment.module';
import { PartiesModule } from './parties/parties.module';
import { PartyModule } from './party/party.module';
import { DomainModule } from './domain/domain.module';
import { DomainModule } from './domain';
import { RepairingModule } from './repairing/repairing.module';
import { DepositsModule } from './deposits/deposits.module';
@NgModule({
declarations: [AppComponent],
@ -50,7 +51,8 @@ import { RepairingModule } from './repairing/repairing.module';
PartiesModule,
PartyModule,
DomainModule,
RepairingModule
RepairingModule,
DepositsModule
],
providers: [
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } },

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input } from '@angular/core';
import { ClaimInfoContainer } from '../../model';
import { ClaimActionType } from '../../claim-action-type';

View File

@ -0,0 +1,26 @@
import { async, TestBed } from '@angular/core/testing';
import { ClaimInfoDetailsComponent } from './claim-info-details.component';
import { By } from '@angular/platform-browser';
describe('ClaimInfoDetailsComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ClaimInfoDetailsComponent]
})
.compileComponents()
.then(() => {
const fixture = TestBed.createComponent(ClaimInfoDetailsComponent);
const rendered = fixture.debugElement.componentInstance;
});
}));
it('should create component', async(() => {
const fixture = TestBed.createComponent(ClaimInfoDetailsComponent);
const component = fixture.debugElement.componentInstance;
expect(component).toBeTruthy();
}));
it('should render reason', async(() => {
const fixture = TestBed.createComponent(ClaimInfoDetailsComponent);
const rendered = fixture.debugElement.componentInstance;
expect(rendered).toBeTruthy();
}));
});

View File

@ -0,0 +1,25 @@
<form *ngIf="form" [formGroup]="form" fxLayout="column" fxLayoutGap="5px">
<mat-form-field>
<input matInput placeholder="Destination" formControlName="destination" required />
</mat-form-field>
<mat-form-field>
<input matInput type="number" placeholder="Amount" formControlName="amount" required />
</mat-form-field>
<mat-form-field>
<mat-label>Currency</mat-label>
<mat-select formControlName="currency" required>
<mat-option *ngFor="let currency of currencies" [value]="currency">
{{ currency.currency }}
</mat-option>
</mat-select>
</mat-form-field>
<button
[disabled]="(isLoading$ | async) || form.invalid"
mat-button
color="primary"
(click)="createDeposit()"
>
Create deposit
</button>
<mat-progress-bar mode="indeterminate" *ngIf="(isLoading$ | async)"></mat-progress-bar>
</form>

View File

@ -0,0 +1,29 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Observable } from 'rxjs';
import { CreateDepositService, CurrencySource } from './create-deposit.service';
@Component({
selector: 'cc-create-deposit',
templateUrl: 'create-deposit.component.html'
})
export class CreateDepositComponent implements OnInit {
form: FormGroup;
currencies: CurrencySource[];
isLoading$: Observable<boolean>;
constructor(private createDepositService: CreateDepositService) {}
ngOnInit() {
this.form = this.createDepositService.getForm();
this.currencies = this.createDepositService.getCurrencies();
this.isLoading$ = this.createDepositService.isLoading$;
}
createDeposit() {
this.createDepositService.createDeposit();
}
}

View File

@ -0,0 +1,83 @@
import { Injectable } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { BehaviorSubject } from 'rxjs';
import { DepositParams } from '../../fistful/gen-model/fistful';
import { FistfulAdminService } from '../../fistful/fistful-admin.service';
import { KeycloakService } from 'keycloak-angular';
import { MatSnackBar } from '@angular/material/snack-bar';
import * as uuid from 'uuid/v4';
import { toMajor } from '../to-major-amount';
export interface CurrencySource {
source: string;
currency: string;
}
const currencies: CurrencySource[] = [
{ source: '3', currency: 'RUB' },
{ source: '5', currency: 'UAH' },
{ source: 'eskin1', currency: 'USD' },
{ source: 'eskin2', currency: 'EUR' },
{ source: 'eskin3', currency: 'KZT' },
{ source: 'eskin5', currency: 'BYN' }
];
@Injectable()
export class CreateDepositService {
form: FormGroup;
isLoading$ = new BehaviorSubject(false);
constructor(
private fistfulAdminService: FistfulAdminService,
private keycloakService: KeycloakService,
private snackBar: MatSnackBar,
private fb: FormBuilder
) {
this.form = this.fb.group({
destination: ['', Validators.required],
amount: ['', [Validators.required, Validators.pattern(/^\d+([\,\.]\d{1,2})?$/)]],
currency: [currencies[0], Validators.required]
});
}
createDeposit() {
this.isLoading$.next(true);
const params = this.getParams();
this.fistfulAdminService.createDeposit(params).subscribe(
() => {
this.isLoading$.next(false);
this.snackBar.open('Deposit successfully created', 'OK', { duration: 3000 });
},
e => {
this.isLoading$.next(false);
this.snackBar.open('An error occurred while deposit create', 'OK');
console.error(e);
}
);
}
getCurrencies(): CurrencySource[] {
return currencies;
}
getForm(): FormGroup {
return this.form;
}
private getParams(): DepositParams {
const { destination, amount, currency } = this.form.value;
return {
id: `${this.keycloakService.getUsername()}-${uuid()}`,
source: currency.source,
destination,
body: {
amount: toMajor(amount),
currency: {
symbolic_code: currency.currency
}
}
};
}
}

View File

@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { AppAuthGuardService } from '../app-auth-guard.service';
import { DepositsComponent } from './deposits.component';
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'deposits',
component: DepositsComponent,
canActivate: [AppAuthGuardService],
data: {
roles: ['deposit:write']
}
}
])
],
exports: [RouterModule]
})
export class DepositsRoutingModule {}

View File

@ -0,0 +1,8 @@
<div fxFlex="100" fxLayoutAlign="center">
<cc-card-container fxFlex="30">
<mat-card>
<mat-card-subtitle>Deposits</mat-card-subtitle>
<mat-card-content> <cc-create-deposit></cc-create-deposit> </mat-card-content>
</mat-card>
</cc-card-container>
</div>

View File

@ -0,0 +1,6 @@
import { Component } from '@angular/core';
@Component({
templateUrl: 'deposits.component.html'
})
export class DepositsComponent {}

View File

@ -0,0 +1,38 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatCardModule } from '@angular/material/card';
import { SharedModule } from '../shared/shared.module';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { ReactiveFormsModule } from '@angular/forms';
import { DepositsRoutingModule } from './deposits-routing.module';
import { DepositsComponent } from './deposits.component';
import { CreateDepositComponent } from './create-deposit/create-deposit.component';
import { CreateDepositService } from './create-deposit/create-deposit.service';
import { FistfulAdminService } from '../fistful/fistful-admin.service';
@NgModule({
imports: [
CommonModule,
DepositsRoutingModule,
FlexLayoutModule,
MatCardModule,
SharedModule,
MatButtonToggleModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
ReactiveFormsModule,
MatSelectModule,
MatProgressBarModule
],
declarations: [DepositsComponent, CreateDepositComponent],
providers: [CreateDepositService, FistfulAdminService]
})
export class DepositsModule {}

View File

@ -0,0 +1,3 @@
import Int64 from 'thrift-ts/lib/int64';
export const toMajor = (amount: number): Int64 => new Int64(Math.round(amount * 100));

View File

@ -0,0 +1,18 @@
import { Injectable, NgZone } from '@angular/core';
import { Observable } from 'rxjs';
import { DepositParams } from './gen-model/fistful';
import { DepositParams as DepositParamsObject } from './gen-nodejs/fistful_types';
import { ThriftService } from '../thrift';
import * as FistfulAdmin from './gen-nodejs/FistfulAdmin';
@Injectable()
export class FistfulAdminService extends ThriftService {
constructor(zone: NgZone) {
super(zone, '/v1/admin', FistfulAdmin);
}
createDeposit(params: DepositParams): Observable<void> {
return this.toObservableAction('CreateDeposit')(new DepositParamsObject(params));
}
}

View File

@ -1,8 +1,9 @@
import { NgModule } from '@angular/core';
import { RepairerService } from './repairer.service';
import { FistfulAdminService } from './fistful-admin.service';
@NgModule({
providers: [RepairerService]
providers: [RepairerService, FistfulAdminService]
})
export class FistfulModule {}

View File

@ -28,7 +28,7 @@ import { SharedModule } from '../shared/shared.module';
import { MachinegunModule } from '../machinegun/machinegun.module';
import { RepairWithScenarioComponent } from './repair-with-scenario/repair-wirh-scenario.component';
import { RepairWithScenarioSettingsComponent } from './repair-with-scenario/repair-with-scenario-settings/repair-with-scenario-settings.component';
import { FistfulModule } from '../fistful/fistful.model';
import { FistfulModule } from '../fistful/fistful.module';
import { RepairComponent } from './repair/repair.component';
import { RepairSettingsComponent } from './repair/repair-settings/repair-settings.component';
import { AddIdsInputComponent } from './add-ids-input/add-ids-input.component';