mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
FE-642: Claim management. (#2)
This commit is contained in:
parent
e056314a15
commit
8a8eb6ea9d
5
Jenkinsfile
vendored
5
Jenkinsfile
vendored
@ -15,9 +15,7 @@ build('control-center', 'docker-host') {
|
||||
pipeDefault() {
|
||||
runStage('init') {
|
||||
withGithubSshCredentials {
|
||||
withWsCache("node_modules") {
|
||||
sh 'make wc_init'
|
||||
}
|
||||
sh 'make wc_init'
|
||||
}
|
||||
}
|
||||
runStage('build') {
|
||||
@ -40,4 +38,3 @@ build('control-center', 'docker-host') {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
5
Makefile
5
Makefile
@ -38,7 +38,7 @@ submodules: $(SUBTARGETS)
|
||||
init:
|
||||
npm install
|
||||
|
||||
build: src/gen-nodejs src/gen-json
|
||||
build: lint src/gen-nodejs src/gen-json
|
||||
npm run build
|
||||
|
||||
clean:
|
||||
@ -50,3 +50,6 @@ src/gen-nodejs: node_modules/damsel/proto/domain_config.thrift
|
||||
|
||||
src/gen-json: node_modules/damsel/proto/domain_config.thrift
|
||||
thrift -r -gen json -o ./src/assets ./node_modules/damsel/proto/domain_config.thrift
|
||||
|
||||
lint:
|
||||
npm run lint
|
||||
|
@ -4,6 +4,6 @@
|
||||
|
||||
make wc_shell
|
||||
|
||||
thrift -r -gen js:node,runtime_package=woody_js/src/client/gen -o ./src/app/domain ./node_modules/damsel/proto/domain_config.thrift
|
||||
thrift -r -gen js:node,runtime_package=woody_js/dist/thrift -o ./src/app/domain ./node_modules/damsel/proto/domain_config.thrift
|
||||
|
||||
thrift -r -gen json -o ./src/assets ./node_modules/damsel/proto/domain_config.thrift
|
||||
|
5654
package-lock.json
generated
5654
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -3,8 +3,8 @@
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "./node_modules/.bin/ng",
|
||||
"start": "ng serve --proxy-config proxy.conf.json",
|
||||
"build": "ng build",
|
||||
"start": "ng serve --proxy-config proxy.conf.json --port 7000",
|
||||
"build": "ng build --prod",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
@ -16,18 +16,24 @@
|
||||
"@angular/common": "^6.1.0",
|
||||
"@angular/compiler": "^6.1.0",
|
||||
"@angular/core": "^6.1.0",
|
||||
"@angular/flex-layout": "^6.0.0-beta.17",
|
||||
"@angular/forms": "^6.1.0",
|
||||
"@angular/http": "^6.1.0",
|
||||
"@angular/material": "^6.4.2",
|
||||
"@angular/platform-browser": "^6.1.0",
|
||||
"@angular/platform-browser-dynamic": "^6.1.0",
|
||||
"@angular/router": "^6.1.0",
|
||||
"angular2-prettyjson": "3.0.1",
|
||||
"core-js": "^2.5.4",
|
||||
"damsel": "git+ssh://git@github.com/rbkmoney/damsel.git#1510cd7caa1e4338429a3a0783289d36e140472a",
|
||||
"hammerjs": "^2.0.8",
|
||||
"keycloak-angular": "3.0.2",
|
||||
"keycloak-js": "3.4.0",
|
||||
"lodash-es": "^4.17.10",
|
||||
"moment": "^2.22.2",
|
||||
"rxjs": "^6.0.0",
|
||||
"woody_js": "git+ssh://git@github.com/rbkmoney/woody_js.git#e6e3eaeebc3933315abb6af4a099cb698424f830",
|
||||
"uuid": "^3.3.2",
|
||||
"woody_js": "git+ssh://git@github.com/rbkmoney/woody_js.git#dfe1ec26573de991f59952aa64b409280fec6c58",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -37,7 +43,9 @@
|
||||
"@angular/language-service": "^6.1.0",
|
||||
"@types/jasmine": "~2.8.6",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/lodash-es": "^4.17.1",
|
||||
"@types/node": "~8.9.4",
|
||||
"@types/uuid": "^3.4.3",
|
||||
"codelyzer": "~4.2.1",
|
||||
"jasmine-core": "~2.99.1",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
@ -46,7 +54,7 @@
|
||||
"karma-coverage-istanbul-reporter": "~2.0.0",
|
||||
"karma-jasmine": "~1.1.1",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"protractor": "~5.3.0",
|
||||
"protractor": "^5.4.0",
|
||||
"ts-node": "~5.0.1",
|
||||
"tslint": "~5.9.1",
|
||||
"typescript": "~2.7.2"
|
||||
|
18
src/app/app-routing.module.ts
Normal file
18
src/app/app-routing.module.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/claims',
|
||||
pathMatch: 'full'
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AppRoutingModule {}
|
@ -1,3 +1,7 @@
|
||||
.spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
@ -4,14 +4,14 @@
|
||||
</button>
|
||||
<span>Control Center</span>
|
||||
<span class="spacer"></span>
|
||||
<span>Lexa Svotin</span>
|
||||
<span>{{username}}</span>
|
||||
<button mat-icon-button [matMenuTriggerFor]="userMenu">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
<mat-menu #userMenu="matMenu">
|
||||
<button mat-menu-item>Logout</button>
|
||||
<button mat-menu-item (click)="logout()">Logout</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-sidenav-container>
|
||||
@ -22,12 +22,14 @@
|
||||
fixedInViewport="true"
|
||||
fixedTopGap="64">
|
||||
<mat-nav-list>
|
||||
<mat-list-item *ngFor="let item of menuItems">
|
||||
{{item}}
|
||||
<mat-list-item *ngFor="let item of menuItems"
|
||||
[routerLink]="item.route"
|
||||
[routerLinkActive]="['active']">
|
||||
{{item.name}}
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content role="main">
|
||||
<!--<router-outlet></router-outlet>-->
|
||||
<router-outlet></router-outlet>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
||||
|
@ -1,14 +1,35 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
selector: 'cc-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
menuItems: string[] = [
|
||||
'Domain config',
|
||||
'Выплаты',
|
||||
'Заявки'
|
||||
];
|
||||
export class AppComponent implements OnInit {
|
||||
|
||||
username: string;
|
||||
|
||||
menuItems: { name: string, route: string }[] = [];
|
||||
|
||||
constructor(private keycloakService: KeycloakService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.username = this.keycloakService.getUsername();
|
||||
this.menuItems = this.getMenuItems();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.keycloakService.logout();
|
||||
}
|
||||
|
||||
private getMenuItems() {
|
||||
const menuItems = [
|
||||
// {name: 'Domain config', route: '/domain', activateRole: 'dmt:checkout'},
|
||||
{name: 'Payouts', route: '/payouts', activateRole: 'payout:read'},
|
||||
{name: 'Claims', route: '/claims', activateRole: 'claim:get'}
|
||||
];
|
||||
const roles = this.keycloakService.getUserRoles();
|
||||
return menuItems.filter((item) => roles.includes(item.activateRole));
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,10 @@ import {
|
||||
} from '@angular/material';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { CoreModule } from './core/core.module';
|
||||
import { ClaimsModule } from './claims/claims.module';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { ClaimModule } from './claim/claim.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -19,15 +23,18 @@ import { AppComponent } from './app.component';
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
AppRoutingModule,
|
||||
CoreModule,
|
||||
MatToolbarModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatListModule
|
||||
MatListModule,
|
||||
ClaimsModule,
|
||||
ClaimModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
export class AppModule {}
|
||||
|
12
src/app/claim/accept-claim/accept-claim.component.html
Normal file
12
src/app/claim/accept-claim/accept-claim.component.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div class="mat-dialog-title">Confirm claim accepting</div>
|
||||
<mat-dialog-actions fxLayout="column" fxLayoutGap="10px">
|
||||
<div>
|
||||
<button mat-button
|
||||
[disabled]="isLoading"
|
||||
color="primary"
|
||||
(click)="accept()">CONFIRM
|
||||
</button>
|
||||
<button [disabled]="isLoading" mat-button [mat-dialog-close]="false">CANCEL</button>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="isLoading" mode="indeterminate"></mat-progress-bar>
|
||||
</mat-dialog-actions>
|
30
src/app/claim/accept-claim/accept-claim.component.ts
Normal file
30
src/app/claim/accept-claim/accept-claim.component.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatDialogRef, MatSnackBar } from '@angular/material';
|
||||
|
||||
import { ClaimService } from '../claim.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'accept-claim.component.html'
|
||||
})
|
||||
export class AcceptClaimComponent {
|
||||
|
||||
isLoading = false;
|
||||
|
||||
constructor(
|
||||
private dialogRef: MatDialogRef<AcceptClaimComponent>,
|
||||
private claimService: ClaimService,
|
||||
private snackBar: MatSnackBar
|
||||
) {}
|
||||
|
||||
accept() {
|
||||
this.isLoading = true;
|
||||
this.claimService.acceptClaim().subscribe(() => {
|
||||
this.isLoading = false;
|
||||
this.dialogRef.close();
|
||||
this.snackBar.open('Claim accepted', 'OK', {duration: 3000});
|
||||
}, () => {
|
||||
this.isLoading = false;
|
||||
this.snackBar.open('An error occurred while claim accepting', 'OK');
|
||||
});
|
||||
}
|
||||
}
|
12
src/app/claim/claim-actions/claim-action.ts
Normal file
12
src/app/claim/claim-actions/claim-action.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { ContractModificationName, ShopModificationName } from '../model';
|
||||
|
||||
export enum ActionType {
|
||||
contractAction = 'contractAction',
|
||||
shopAction = 'shopAction',
|
||||
domainAction = 'domainAction'
|
||||
}
|
||||
|
||||
export interface ClaimAction {
|
||||
type: ActionType;
|
||||
name?: ContractModificationName | ShopModificationName;
|
||||
}
|
13
src/app/claim/claim-actions/claim-actions.component.html
Normal file
13
src/app/claim/claim-actions/claim-actions.component.html
Normal file
@ -0,0 +1,13 @@
|
||||
<mat-nav-list>
|
||||
<a mat-list-item *ngFor="let contractAction of contractActions" (click)="select(contractAction)">
|
||||
{{contractAction.name | ccContainerName:"ContractModification"}}
|
||||
</a>
|
||||
<mat-divider></mat-divider>
|
||||
<a mat-list-item *ngFor="let shopAction of shopActions" (click)="select(shopAction)">
|
||||
{{shopAction.name | ccContainerName:"ShopModification"}}
|
||||
</a>
|
||||
<mat-divider></mat-divider>
|
||||
<a mat-list-item *ngFor="let domainAction of domainActions" (click)="select(domainAction)">
|
||||
Domain config modification: Add terminal
|
||||
</a>
|
||||
</mat-nav-list>
|
62
src/app/claim/claim-actions/claim-actions.component.ts
Normal file
62
src/app/claim/claim-actions/claim-actions.component.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatBottomSheetRef, MatDialog } from '@angular/material';
|
||||
|
||||
import { ShopModificationName, ContractModificationName } from '../model';
|
||||
import { ActionType, ClaimAction } from './claim-action';
|
||||
import { CreateChangeComponent } from '../create-change/create-change.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'claim-actions.component.html'
|
||||
})
|
||||
export class ClaimActionsComponent {
|
||||
|
||||
constructor(private bottomSheetRef: MatBottomSheetRef,
|
||||
private dialog: MatDialog) {
|
||||
}
|
||||
|
||||
contractActions: ClaimAction[] = [
|
||||
{
|
||||
type: ActionType.contractAction,
|
||||
name: ContractModificationName.legalAgreementBinding
|
||||
},
|
||||
{
|
||||
type: ActionType.contractAction,
|
||||
name: ContractModificationName.reportPreferencesModification
|
||||
},
|
||||
{
|
||||
type: ActionType.contractAction,
|
||||
name: ContractModificationName.adjustmentModification
|
||||
},
|
||||
];
|
||||
|
||||
shopActions: ClaimAction[] = [
|
||||
{
|
||||
type: ActionType.shopAction,
|
||||
name: ShopModificationName.categoryModification
|
||||
},
|
||||
{
|
||||
type: ActionType.shopAction,
|
||||
name: ShopModificationName.shopAccountCreation
|
||||
},
|
||||
{
|
||||
type: ActionType.shopAction,
|
||||
name: ShopModificationName.payoutScheduleModification
|
||||
}
|
||||
];
|
||||
|
||||
domainActions: ClaimAction[] = [
|
||||
{
|
||||
type: ActionType.domainAction
|
||||
}
|
||||
];
|
||||
|
||||
select(action: ClaimAction) {
|
||||
this.bottomSheetRef.dismiss();
|
||||
const config = {
|
||||
data: action,
|
||||
width: '720px',
|
||||
disableClose: true
|
||||
};
|
||||
this.dialog.open<CreateChangeComponent, ClaimAction>(CreateChangeComponent, config);
|
||||
}
|
||||
}
|
21
src/app/claim/claim-auth-guard.service.ts
Normal file
21
src/app/claim/claim-auth-guard.service.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class ClaimAuthGuardService extends KeycloakAuthGuard {
|
||||
|
||||
constructor(protected router: Router, protected keycloakAngular: KeycloakService) {
|
||||
super(router, keycloakAngular);
|
||||
}
|
||||
|
||||
isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.roles || this.roles.length === 0) {
|
||||
resolve(false);
|
||||
}
|
||||
const granted = this.roles.includes('claim:get');
|
||||
resolve(granted);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<div fxLayout="row" fxLayoutGap="10px" fxLayout.sm="column" fxLayout.xs="column">
|
||||
<div fxFlex="50" fxLayout="column" fxLayoutGap="10px">
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Claim ID:</label>
|
||||
<div>{{claimInfoContainer?.claimId}}</div>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Status:</label>
|
||||
<div>{{claimInfoContainer?.status}}</div>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Revision:</label>
|
||||
<div>{{claimInfoContainer?.revision}}</div>
|
||||
</div>
|
||||
<div *ngIf="claimInfoContainer?.reason" fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Reason:</label>
|
||||
<div>{{claimInfoContainer?.reason}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div fxFlex="50" fxLayout="column" fxLayoutGap="10px">
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Party ID:</label>
|
||||
<div>{{claimInfoContainer?.partyId}}</div>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Created At:</label>
|
||||
<div>{{claimInfoContainer?.createdAt | date: "dd.MM.yyyy HH:mm:ss"}}</div>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<label fxFlex="20">Updated At:</label>
|
||||
<div>{{claimInfoContainer?.updatedAt | date: "dd.MM.yyyy HH:mm:ss"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,14 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { ClaimInfoContainer } from '../../model';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-claim-info-details',
|
||||
templateUrl: 'claim-info-details.component.html',
|
||||
styleUrls: ['./claim-info-details.component.css']
|
||||
})
|
||||
export class ClaimInfoDetailsComponent {
|
||||
|
||||
@Input()
|
||||
claimInfoContainer: ClaimInfoContainer;
|
||||
|
||||
}
|
45
src/app/claim/claim-info/claim-info.component.ts
Normal file
45
src/app/claim/claim-info/claim-info.component.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatBottomSheet, MatDialog } from '@angular/material';
|
||||
|
||||
import { ClaimService } from '../claim.service';
|
||||
import { ClaimInfoContainer } from '../model';
|
||||
import { ClaimActionsComponent } from '../claim-actions/claim-actions.component';
|
||||
import { AcceptClaimComponent } from '../accept-claim/accept-claim.component';
|
||||
import { DenyClaimComponent } from '../deny-claim/deny-claim.component';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-claim-info',
|
||||
templateUrl: 'claim.info.component.html'
|
||||
})
|
||||
export class ClaimInfoComponent implements OnInit {
|
||||
|
||||
claimInfoContainer: ClaimInfoContainer;
|
||||
|
||||
constructor(private claimService: ClaimService,
|
||||
private bottomSheet: MatBottomSheet,
|
||||
private dialog: MatDialog) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.claimService.claimInfoContainer$.subscribe((container) => {
|
||||
this.claimInfoContainer = container;
|
||||
});
|
||||
}
|
||||
|
||||
openClaimActions() {
|
||||
this.bottomSheet.open(ClaimActionsComponent);
|
||||
}
|
||||
|
||||
accept() {
|
||||
this.dialog.open(AcceptClaimComponent, {
|
||||
disableClose: true
|
||||
});
|
||||
}
|
||||
|
||||
deny() {
|
||||
this.dialog.open(DenyClaimComponent, {
|
||||
disableClose: true,
|
||||
width: '30vw'
|
||||
});
|
||||
}
|
||||
}
|
28
src/app/claim/claim-info/claim.info.component.html
Normal file
28
src/app/claim/claim-info/claim.info.component.html
Normal file
@ -0,0 +1,28 @@
|
||||
<mat-card *ngIf="claimInfoContainer">
|
||||
<mat-card-subtitle>
|
||||
Claim details
|
||||
</mat-card-subtitle>
|
||||
<mat-card-content>
|
||||
<cc-claim-info-details [claimInfoContainer]="claimInfoContainer"></cc-claim-info-details>
|
||||
</mat-card-content>
|
||||
<mat-card-actions fxLayout="row" fxLayoutAlign="space-between stretch">
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<button mat-button
|
||||
[disabled]="claimInfoContainer?.status !== 'pending'"
|
||||
(click)="openClaimActions()">CREATE CHANGE
|
||||
</button>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<button mat-button
|
||||
color="primary"
|
||||
[disabled]="claimInfoContainer?.status !== 'pending'"
|
||||
(click)="accept()">ACCEPT CLAIM
|
||||
</button>
|
||||
<button mat-button
|
||||
color="warn"
|
||||
[disabled]="claimInfoContainer?.status !== 'pending'"
|
||||
(click)="deny()">DENY CLAIM
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
24
src/app/claim/claim-routing.module.ts
Normal file
24
src/app/claim/claim-routing.module.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ClaimComponent } from './claim.component';
|
||||
import { ClaimAuthGuardService } from './claim-auth-guard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'claims/:partyId/:claimId',
|
||||
component: ClaimComponent,
|
||||
canActivate: [ClaimAuthGuardService]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
],
|
||||
providers: [
|
||||
ClaimAuthGuardService
|
||||
]
|
||||
})
|
||||
export class ClaimRoutingModule {}
|
6
src/app/claim/claim.component.html
Normal file
6
src/app/claim/claim.component.html
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="container">
|
||||
<div class="card-container" fxLayout="column" fxLayoutGap="20px">
|
||||
<cc-claim-info></cc-claim-info>
|
||||
<cc-party-modifications></cc-party-modifications>
|
||||
</div>
|
||||
</div>
|
25
src/app/claim/claim.component.ts
Normal file
25
src/app/claim/claim.component.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { switchMap } from 'rxjs/internal/operators';
|
||||
|
||||
import { ClaimService } from './claim.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'claim.component.html',
|
||||
styleUrls: ['../shared/container.css']
|
||||
})
|
||||
export class ClaimComponent {
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private claimService: ClaimService,
|
||||
private snackBar: MatSnackBar) {
|
||||
this.route.params.pipe(switchMap((params) => {
|
||||
const {partyId, claimId} = params;
|
||||
return this.claimService.resolveClaimInfo(partyId, claimId);
|
||||
})).subscribe(null, (error) => {
|
||||
console.error(error);
|
||||
this.snackBar.open('An error occurred while claim resolving', 'OK');
|
||||
});
|
||||
}
|
||||
}
|
109
src/app/claim/claim.module.ts
Normal file
109
src/app/claim/claim.module.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import {
|
||||
MatBottomSheetModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDatepickerModule,
|
||||
MatDialogModule,
|
||||
MatDividerModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatListModule,
|
||||
MatNativeDateModule,
|
||||
MatProgressBarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatRadioModule,
|
||||
MatSelectModule,
|
||||
MatSnackBarModule,
|
||||
MatTabsModule
|
||||
} from '@angular/material';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { PrettyJsonModule } from 'angular2-prettyjson';
|
||||
|
||||
import { PapiModule } from '../papi/papi.module';
|
||||
import { DomainModule } from '../domain/domain.module';
|
||||
import { ClaimRoutingModule } from './claim-routing.module';
|
||||
import { ClaimComponent } from './claim.component';
|
||||
import { ClaimInfoComponent } from './claim-info/claim-info.component';
|
||||
import { ClaimInfoDetailsComponent } from './claim-info/claim-info-details/claim-info-details.component';
|
||||
import { PartyModificationsComponent } from './party-modifications/party-modifications.component';
|
||||
import { PartyModificationContainerComponent } from './party-modification-container/party-modification-container.component';
|
||||
import { ClaimActionsComponent } from './claim-actions/claim-actions.component';
|
||||
import { CreateChangeComponent } from './create-change/create-change.component';
|
||||
import { CreateLegalAgreementComponent } from './create-change/create-legal-agreement/create-legal-agreement.component';
|
||||
import { CreateCategoryRefComponent } from './create-change/create-category-ref/create-category-ref.component';
|
||||
import { ClaimService } from './claim.service';
|
||||
import { CreateCurrencyRefComponent } from './create-change/create-currency-ref/create-currency-ref.component';
|
||||
import { CreateContractTemplateComponent } from './create-change/create-contract-template/create-contract-template.component';
|
||||
import { AcceptClaimComponent } from './accept-claim/accept-claim.component';
|
||||
import { DenyClaimComponent } from './deny-claim/deny-claim.component';
|
||||
import { CreateBusinessScheduleRefComponent } from './create-change/create-business-schedule-ref/create-business-schedule-ref.component';
|
||||
import {
|
||||
CreateServiceAcceptanceActPreferencesComponent
|
||||
} from './create-change/create-service-acceptance-act-preferences/create-service-acceptance-act-preferences.component';
|
||||
import { CreateTerminalObjectComponent } from './create-change/create-terminal-object/create-terminal-object.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ContainerNamePipe } from './container-name.pipe';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
PapiModule,
|
||||
DomainModule,
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
ReactiveFormsModule,
|
||||
ClaimRoutingModule,
|
||||
FlexLayoutModule,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatTabsModule,
|
||||
MatBottomSheetModule,
|
||||
MatListModule,
|
||||
MatIconModule,
|
||||
MatDialogModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule,
|
||||
MatDividerModule,
|
||||
MatSelectModule,
|
||||
MatProgressBarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSnackBarModule,
|
||||
MatRadioModule,
|
||||
PrettyJsonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
declarations: [
|
||||
ClaimComponent,
|
||||
ClaimInfoComponent,
|
||||
ClaimInfoDetailsComponent,
|
||||
PartyModificationsComponent,
|
||||
PartyModificationContainerComponent,
|
||||
ClaimActionsComponent,
|
||||
CreateChangeComponent,
|
||||
CreateLegalAgreementComponent,
|
||||
CreateCategoryRefComponent,
|
||||
CreateCurrencyRefComponent,
|
||||
CreateContractTemplateComponent,
|
||||
CreateBusinessScheduleRefComponent,
|
||||
CreateServiceAcceptanceActPreferencesComponent,
|
||||
AcceptClaimComponent,
|
||||
DenyClaimComponent,
|
||||
CreateTerminalObjectComponent,
|
||||
ContainerNamePipe
|
||||
],
|
||||
entryComponents: [
|
||||
ClaimActionsComponent,
|
||||
CreateChangeComponent,
|
||||
AcceptClaimComponent,
|
||||
DenyClaimComponent
|
||||
],
|
||||
providers: [
|
||||
ClaimService
|
||||
]
|
||||
})
|
||||
export class ClaimModule {
|
||||
}
|
188
src/app/claim/claim.service.ts
Normal file
188
src/app/claim/claim.service.ts
Normal file
@ -0,0 +1,188 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||
import { delay, map, repeatWhen, switchMap, takeWhile, tap } from 'rxjs/internal/operators';
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import get from 'lodash-es/get';
|
||||
import toNumber from 'lodash-es/toNumber';
|
||||
|
||||
import { ClaimService as ClaimPapi } from '../papi/claim.service';
|
||||
import { ClaimInfo, PartyModificationUnit } from '../papi/model';
|
||||
import { ShopModification, ContractModification, PartyModification } from '../damsel';
|
||||
import {
|
||||
ClaimInfoContainer,
|
||||
DomainModificationInfo,
|
||||
PartyModificationContainerType
|
||||
} from './model';
|
||||
import { PartyModificationContainerConverter } from './party-modification-container-converter';
|
||||
|
||||
@Injectable()
|
||||
export class ClaimService {
|
||||
|
||||
claimInfoContainer$: Subject<ClaimInfoContainer> = new Subject();
|
||||
|
||||
domainModificationInfo$: Subject<DomainModificationInfo> = new BehaviorSubject(null);
|
||||
|
||||
private claimInfoContainer: ClaimInfoContainer;
|
||||
|
||||
constructor(private papiClaimService: ClaimPapi) {
|
||||
}
|
||||
|
||||
resolveClaimInfo(partyID: string, claimID: string): Observable<void> {
|
||||
return this.papiClaimService.getClaim(partyID, toNumber(claimID))
|
||||
.pipe(
|
||||
tap((claimInfo) => {
|
||||
this.claimInfoContainer = this.toClaimInfoContainer(claimInfo);
|
||||
const domainModificationInfo = this.toDomainModificationInfo(claimInfo, this.claimInfoContainer.extractedIds.shopId);
|
||||
this.domainModificationInfo$.next(domainModificationInfo);
|
||||
this.claimInfoContainer$.next(this.claimInfoContainer);
|
||||
}),
|
||||
map(() => null)
|
||||
);
|
||||
}
|
||||
|
||||
createChange(type: PartyModificationContainerType, modification: ShopModification | ContractModification): Observable<void> {
|
||||
const {partyId, claimId} = this.claimInfoContainer;
|
||||
const unit = this.toModificationUnit(type, modification);
|
||||
return this.papiClaimService.getClaim(partyId, claimId)
|
||||
.pipe(
|
||||
switchMap((claimInfo) =>
|
||||
this.papiClaimService
|
||||
.updateClaim(partyId, claimId, claimInfo.revision, unit)
|
||||
.pipe(map(() => claimInfo.revision))),
|
||||
switchMap((revision) =>
|
||||
this.pollClaimChange(revision))
|
||||
);
|
||||
}
|
||||
|
||||
acceptClaim(): Observable<void> {
|
||||
const {claimId, partyId} = this.claimInfoContainer;
|
||||
return this.papiClaimService.getClaim(partyId, claimId)
|
||||
.pipe(
|
||||
switchMap((claimInfo) =>
|
||||
this.papiClaimService
|
||||
.acceptClaim({partyId, claimId, revision: claimInfo.revision})
|
||||
.pipe(map(() => claimInfo.revision))),
|
||||
switchMap((revision) =>
|
||||
this.pollClaimChange(revision))
|
||||
);
|
||||
}
|
||||
|
||||
denyClaim(reason: string): Observable<void> {
|
||||
const {claimId, partyId} = this.claimInfoContainer;
|
||||
return this.papiClaimService.getClaim(partyId, claimId)
|
||||
.pipe(
|
||||
switchMap((claimInfo) =>
|
||||
this.papiClaimService
|
||||
.denyClaim({claimId, partyId, revision: claimInfo.revision, reason})
|
||||
.pipe(map(() => claimInfo.revision))),
|
||||
switchMap((revision) =>
|
||||
this.pollClaimChange(revision))
|
||||
);
|
||||
}
|
||||
|
||||
private toModificationUnit(type: PartyModificationContainerType, modification: ShopModification | ContractModification): PartyModificationUnit {
|
||||
const result = {
|
||||
modifications: []
|
||||
};
|
||||
let unit;
|
||||
const {contractId, shopId} = this.claimInfoContainer.extractedIds;
|
||||
switch (type) {
|
||||
case PartyModificationContainerType.ContractModification:
|
||||
unit = {
|
||||
contractModification: {
|
||||
id: contractId,
|
||||
modification
|
||||
}
|
||||
};
|
||||
break;
|
||||
case PartyModificationContainerType.ShopModification:
|
||||
unit = {
|
||||
shopModification: {
|
||||
id: shopId,
|
||||
modification
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
result.modifications.push(unit);
|
||||
return result;
|
||||
}
|
||||
|
||||
private toClaimInfoContainer(claimInfo: ClaimInfo): ClaimInfoContainer {
|
||||
const modifications = claimInfo.modifications.modifications;
|
||||
const {claimId, partyId, revision, status, reason, createdAt, updatedAt} = claimInfo;
|
||||
const partyModificationUnits = PartyModificationContainerConverter.convert(modifications);
|
||||
const extractedIds = this.extractIds(modifications);
|
||||
return {
|
||||
claimId,
|
||||
partyId,
|
||||
revision,
|
||||
status,
|
||||
reason,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
extractedIds,
|
||||
partyModificationUnits
|
||||
};
|
||||
}
|
||||
|
||||
private toDomainModificationInfo(claimInfo: ClaimInfo, shopId: string): DomainModificationInfo {
|
||||
const modifications = claimInfo.modifications.modifications;
|
||||
return {
|
||||
shopUrl: this.findShopUrl(modifications),
|
||||
shopId,
|
||||
partyId: claimInfo.partyId
|
||||
};
|
||||
}
|
||||
|
||||
private findShopUrl(modifications: PartyModification[]): string {
|
||||
const found = modifications.find((item) =>
|
||||
!!(item.shopModification && item.shopModification.modification.creation));
|
||||
return get(found, 'shopModification.modification.creation.location.url');
|
||||
}
|
||||
|
||||
private extractIds(modifications: PartyModification[]): { shopId: string, contractId: string } {
|
||||
return modifications.reduce((prev, current) => {
|
||||
if (!prev.shopId && current.shopModification) {
|
||||
const shopId = current.shopModification.id;
|
||||
return {...prev, shopId};
|
||||
} else if (!prev.contractId && current.contractModification) {
|
||||
const contractId = current.contractModification.id;
|
||||
return {...prev, contractId};
|
||||
} else {
|
||||
return prev;
|
||||
}
|
||||
}, {shopId: null, contractId: null});
|
||||
}
|
||||
|
||||
private pollClaimChange(revision: string, delayMs = 2000, retryCount = 15): Observable<void> {
|
||||
const container = this.claimInfoContainer;
|
||||
const {partyId, claimId, status} = container;
|
||||
const currentPair = {status, revision};
|
||||
let newPair = {};
|
||||
return Observable.create((observer) => {
|
||||
this.papiClaimService.getClaim(partyId, claimId)
|
||||
.pipe(
|
||||
repeatWhen((notifications) => {
|
||||
return notifications.pipe(
|
||||
delay(delayMs),
|
||||
takeWhile((value, retries) =>
|
||||
isEqual(newPair, currentPair) && retries <= retryCount)
|
||||
);
|
||||
})
|
||||
)
|
||||
.subscribe((claimInfo) => {
|
||||
newPair = {
|
||||
status: claimInfo.status,
|
||||
revision: claimInfo.revision
|
||||
};
|
||||
if (!isEqual(newPair, currentPair)) {
|
||||
this.claimInfoContainer = this.toClaimInfoContainer(claimInfo);
|
||||
this.claimInfoContainer$.next(this.claimInfoContainer);
|
||||
observer.next();
|
||||
observer.complete();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
71
src/app/claim/container-name.pipe.ts
Normal file
71
src/app/claim/container-name.pipe.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
import {
|
||||
PartyModificationContainerType,
|
||||
ShopModificationName,
|
||||
ContractModificationName
|
||||
} from './model';
|
||||
|
||||
@Pipe({
|
||||
name: 'ccContainerName'
|
||||
})
|
||||
export class ContainerNamePipe implements PipeTransform {
|
||||
|
||||
transform(value: any, ...args: any[]): any {
|
||||
if (args.length < 1) {
|
||||
return value;
|
||||
}
|
||||
const type = args[0] as PartyModificationContainerType;
|
||||
switch (type) {
|
||||
case PartyModificationContainerType.ShopModification:
|
||||
return this.transformShopModification(value);
|
||||
case PartyModificationContainerType.ContractModification:
|
||||
return this.transformContractModificationName(value);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private transformShopModification(value: ShopModificationName): string {
|
||||
switch (value) {
|
||||
case ShopModificationName.creation:
|
||||
return 'Shop creation';
|
||||
case ShopModificationName.categoryModification:
|
||||
return 'Shop category modification';
|
||||
case ShopModificationName.detailsModification:
|
||||
return 'Shop details modification';
|
||||
case ShopModificationName.contractModification:
|
||||
return 'Shop contract modification';
|
||||
case ShopModificationName.payoutToolModification:
|
||||
return 'Shop payout tool modification';
|
||||
case ShopModificationName.locationModification:
|
||||
return 'Shop location modification';
|
||||
case ShopModificationName.shopAccountCreation:
|
||||
return 'Shop account creation';
|
||||
case ShopModificationName.payoutScheduleModification:
|
||||
return 'Shop payout schedule modification';
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private transformContractModificationName(value: ContractModificationName): string {
|
||||
switch (value) {
|
||||
case ContractModificationName.creation:
|
||||
return 'Contract creation';
|
||||
case ContractModificationName.termination:
|
||||
return 'Contract termination';
|
||||
case ContractModificationName.adjustmentModification:
|
||||
return 'Contract adjustment modification';
|
||||
case ContractModificationName.payoutToolModification:
|
||||
return 'Contract payout tool modification';
|
||||
case ContractModificationName.legalAgreementBinding:
|
||||
return 'Contract legal agreement binding';
|
||||
case ContractModificationName.reportPreferencesModification:
|
||||
return 'Contract report preferences modification';
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<form fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="20px"
|
||||
[formGroup]="form">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-select placeholder="Select payout schedule"
|
||||
formControlName="id">
|
||||
<mat-option *ngFor="let schedule of payoutSchedules$ | async" [value]="schedule.ref.id" required>
|
||||
{{schedule.ref.id}} {{schedule.data.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</form>
|
@ -0,0 +1,27 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { CreateBusinessScheduleRefService } from './create-business-schedule-ref.service';
|
||||
import { BusinessScheduleObject } from '../../../damsel/domain';
|
||||
import { DomainTypedManager } from '../../../domain/domain-typed-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-business-schedule-ref',
|
||||
templateUrl: 'create-business-schedule-ref.component.html'
|
||||
})
|
||||
export class CreateBusinessScheduleRefComponent implements OnInit {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
payoutSchedules$: Observable<BusinessScheduleObject[]>;
|
||||
|
||||
constructor(
|
||||
private createBusinessScheduleRefService: CreateBusinessScheduleRefService,
|
||||
private domainManager: DomainTypedManager) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = this.createBusinessScheduleRefService.form;
|
||||
this.payoutSchedules$ = this.domainManager.getBusinessScheduleObjects();
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { ShopModification } from '../../../damsel/payment-processing';
|
||||
|
||||
@Injectable()
|
||||
export class CreateBusinessScheduleRefService implements CreateChangeItem {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
}
|
||||
|
||||
getValue(): ShopModification {
|
||||
return {
|
||||
payoutScheduleModification: {
|
||||
schedule: this.form.value
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
id: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<form fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="20px"
|
||||
[formGroup]="form">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-select placeholder="Select category"
|
||||
formControlName="id">
|
||||
<mat-option *ngFor="let category of categories$ | async" [value]="category.id" required>
|
||||
{{category.id}} {{category.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</form>
|
@ -0,0 +1,31 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/internal/operators';
|
||||
import sortBy from 'lodash-es/sortBy';
|
||||
|
||||
import { Category } from '../../../papi/model/category';
|
||||
import { CreateCategoryRefService } from './create-category-ref.service';
|
||||
import { CategoryService } from '../../../papi/category.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-category-ref',
|
||||
templateUrl: 'create-category-ref.component.html'
|
||||
})
|
||||
export class CreateCategoryRefComponent implements OnInit {
|
||||
|
||||
categories$: Observable<Category[]>;
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(
|
||||
private createCategoryService: CreateCategoryRefService,
|
||||
private categoryService: CategoryService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = this.createCategoryService.form;
|
||||
this.categories$ = this.categoryService
|
||||
.getCategories()
|
||||
.pipe(map((categories) => sortBy(categories, 'id')));
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { ShopModification } from '../../../damsel';
|
||||
import { CategoryService } from '../../../papi/category.service';
|
||||
|
||||
@Injectable()
|
||||
export class CreateCategoryRefService implements CreateChangeItem {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private categoryService: CategoryService,
|
||||
private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
}
|
||||
|
||||
getValue(): ShopModification {
|
||||
return {
|
||||
categoryModification: this.form.value
|
||||
};
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
id: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
8
src/app/claim/create-change/create-change-item.ts
Normal file
8
src/app/claim/create-change/create-change-item.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { ContractModification, ShopModification } from '../../damsel';
|
||||
import { CreateTerminalParams } from '../../domain/domain-typed-manager';
|
||||
|
||||
export interface CreateChangeItem {
|
||||
getValue(): ContractModification | ShopModification | CreateTerminalParams;
|
||||
|
||||
isValid(): boolean;
|
||||
}
|
41
src/app/claim/create-change/create-change.component.html
Normal file
41
src/app/claim/create-change/create-change.component.html
Normal file
@ -0,0 +1,41 @@
|
||||
<div class="mat-dialog-title">{{claimAction.name | ccContainerName:getContainerType(claimAction.type)}}</div>
|
||||
<mat-dialog-content>
|
||||
<div *ngIf="claimAction.type === ActionType.contractAction">
|
||||
<cc-create-legal-agreement
|
||||
*ngIf="claimAction.name === ContractModificationName.legalAgreementBinding">
|
||||
</cc-create-legal-agreement>
|
||||
<cc-create-contract-template
|
||||
*ngIf="claimAction.name === ContractModificationName.adjustmentModification">
|
||||
</cc-create-contract-template>
|
||||
<cc-create-service-acceptance-act-preferences
|
||||
*ngIf="claimAction.name === ContractModificationName.reportPreferencesModification">
|
||||
</cc-create-service-acceptance-act-preferences>
|
||||
</div>
|
||||
<div *ngIf="claimAction.type === ActionType.shopAction">
|
||||
<cc-create-category-ref
|
||||
*ngIf="claimAction.name === ShopModificationName.categoryModification">
|
||||
</cc-create-category-ref>
|
||||
<cc-create-currency-ref
|
||||
*ngIf="claimAction.name === ShopModificationName.shopAccountCreation">
|
||||
</cc-create-currency-ref>
|
||||
<cc-create-business-schedule-ref
|
||||
*ngIf="claimAction.name === ShopModificationName.payoutScheduleModification">
|
||||
</cc-create-business-schedule-ref>
|
||||
</div>
|
||||
<div *ngIf="claimAction.type === ActionType.domainAction">
|
||||
<cc-create-terminal-object
|
||||
[domainModificationInfo]="(domainModificationInfo$ | async)">
|
||||
</cc-create-terminal-object>
|
||||
</div>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions fxLayout="column" fxLayoutGap="10px">
|
||||
<div>
|
||||
<button mat-button
|
||||
[disabled]="!isFormValid() || isLoading"
|
||||
color="primary"
|
||||
(click)="create()">CREATE
|
||||
</button>
|
||||
<button [disabled]="isLoading" mat-button [mat-dialog-close]="false">CANCEL</button>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="isLoading" mode="indeterminate"></mat-progress-bar>
|
||||
</mat-dialog-actions>
|
85
src/app/claim/create-change/create-change.component.ts
Normal file
85
src/app/claim/create-change/create-change.component.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef, MatSnackBar } from '@angular/material';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { ActionType, ClaimAction } from '../claim-actions/claim-action';
|
||||
import { CreateChangeService } from './create-change.service';
|
||||
import { CreateLegalAgreementService } from './create-legal-agreement/create-legal-agreement.service';
|
||||
import { CreateCategoryRefService } from './create-category-ref/create-category-ref.service';
|
||||
import { CreateCurrencyRefService } from './create-currency-ref/create-currency-ref.service';
|
||||
import { CreateContractTemplateService } from './create-contract-template/create-contract-template.service';
|
||||
import { CreateBusinessScheduleRefService } from './create-business-schedule-ref/create-business-schedule-ref.service';
|
||||
import { CreateServiceAcceptanceActPreferencesService } from './create-service-acceptance-act-preferences/create-service-acceptance-act-preferences.service';
|
||||
import { CreateTerminalObjectService } from './create-terminal-object/create-terminal-object.service';
|
||||
import {
|
||||
ContractModificationName,
|
||||
DomainModificationInfo,
|
||||
ShopModificationName,
|
||||
PartyModificationContainerType
|
||||
} from '../model';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'create-change.component.html',
|
||||
providers: [
|
||||
CreateChangeService,
|
||||
CreateLegalAgreementService,
|
||||
CreateCategoryRefService,
|
||||
CreateCurrencyRefService,
|
||||
CreateContractTemplateService,
|
||||
CreateBusinessScheduleRefService,
|
||||
CreateServiceAcceptanceActPreferencesService,
|
||||
CreateTerminalObjectService
|
||||
]
|
||||
})
|
||||
export class CreateChangeComponent implements OnInit {
|
||||
|
||||
ActionType = ActionType;
|
||||
|
||||
ContractModificationName = ContractModificationName;
|
||||
|
||||
ShopModificationName = ShopModificationName;
|
||||
|
||||
isLoading = false;
|
||||
|
||||
domainModificationInfo$: Observable<DomainModificationInfo>;
|
||||
|
||||
constructor(
|
||||
private dialogRef: MatDialogRef<CreateChangeComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public claimAction: ClaimAction,
|
||||
private snackBar: MatSnackBar,
|
||||
private createChangeService: CreateChangeService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.domainModificationInfo$ = this.createChangeService.domainModificationInfo$;
|
||||
}
|
||||
|
||||
create() {
|
||||
const {name} = this.claimAction;
|
||||
this.isLoading = true;
|
||||
this.createChangeService.createChange(this.claimAction).subscribe(() => {
|
||||
this.isLoading = false;
|
||||
this.dialogRef.close();
|
||||
this.snackBar.open(`${name} created`, 'OK', {duration: 3000});
|
||||
}, (error) => {
|
||||
console.error(error);
|
||||
this.isLoading = false;
|
||||
this.snackBar.open(`An error occurred while creating ${name}`, 'OK');
|
||||
});
|
||||
}
|
||||
|
||||
isFormValid() {
|
||||
return this.createChangeService.isFormValid(this.claimAction);
|
||||
}
|
||||
|
||||
getContainerType(type: ActionType): string {
|
||||
switch (type) {
|
||||
case ActionType.shopAction:
|
||||
return PartyModificationContainerType.ShopModification;
|
||||
case ActionType.contractAction:
|
||||
return PartyModificationContainerType.ContractModification;
|
||||
case ActionType.domainAction:
|
||||
return 'Domain modification';
|
||||
}
|
||||
}
|
||||
}
|
104
src/app/claim/create-change/create-change.service.ts
Normal file
104
src/app/claim/create-change/create-change.service.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/internal/operators';
|
||||
|
||||
import { CreateLegalAgreementService } from './create-legal-agreement/create-legal-agreement.service';
|
||||
import { CreateCategoryRefService } from './create-category-ref/create-category-ref.service';
|
||||
import { ActionType, ClaimAction } from '../claim-actions/claim-action';
|
||||
import { CreateCurrencyRefService } from './create-currency-ref/create-currency-ref.service';
|
||||
import { CreateContractTemplateService } from './create-contract-template/create-contract-template.service';
|
||||
import { CreateBusinessScheduleRefService } from './create-business-schedule-ref/create-business-schedule-ref.service';
|
||||
import { CreateServiceAcceptanceActPreferencesService } from './create-service-acceptance-act-preferences/create-service-acceptance-act-preferences.service';
|
||||
import { CreateTerminalObjectService } from './create-terminal-object/create-terminal-object.service';
|
||||
import { CreateTerminalParams, DomainTypedManager } from '../../domain/domain-typed-manager';
|
||||
import {
|
||||
ContractModificationName,
|
||||
DomainModificationInfo,
|
||||
PartyModificationContainerType,
|
||||
ShopModificationName
|
||||
} from '../model';
|
||||
import { CreateChangeItem } from './create-change-item';
|
||||
import { ClaimService } from '../claim.service';
|
||||
import { ContractModification, ShopModification } from '../../damsel';
|
||||
|
||||
@Injectable()
|
||||
export class CreateChangeService {
|
||||
|
||||
domainModificationInfo$: Observable<DomainModificationInfo>;
|
||||
|
||||
constructor(private createLegalAgreementService: CreateLegalAgreementService,
|
||||
private createCategoryRefService: CreateCategoryRefService,
|
||||
private createCurrencyRefService: CreateCurrencyRefService,
|
||||
private createContractTemplateService: CreateContractTemplateService,
|
||||
private createBusinessScheduleRefService: CreateBusinessScheduleRefService,
|
||||
private createServiceAcceptanceActPreferencesService: CreateServiceAcceptanceActPreferencesService,
|
||||
private createTerminalObjectService: CreateTerminalObjectService,
|
||||
private claimService: ClaimService,
|
||||
private domainTypedManager: DomainTypedManager) {
|
||||
this.domainModificationInfo$ = this.claimService.domainModificationInfo$;
|
||||
}
|
||||
|
||||
createChange(claimAction: ClaimAction): Observable<void> {
|
||||
const instance = this.getCreateServiceInstance(claimAction);
|
||||
const value = instance.getValue();
|
||||
switch (claimAction.type) {
|
||||
case ActionType.shopAction:
|
||||
case ActionType.contractAction:
|
||||
const partyType = this.toPartyModificationType(claimAction.type);
|
||||
return this.claimService
|
||||
.createChange(partyType, value as ShopModification | ContractModification);
|
||||
case ActionType.domainAction:
|
||||
return this.domainTypedManager
|
||||
.createTerminal(value as CreateTerminalParams)
|
||||
.pipe(map(() => {}));
|
||||
}
|
||||
}
|
||||
|
||||
isFormValid(claimAction: ClaimAction): boolean {
|
||||
const instance = this.getCreateServiceInstance(claimAction);
|
||||
return instance.isValid();
|
||||
}
|
||||
|
||||
private getCreateServiceInstance(action: ClaimAction): CreateChangeItem {
|
||||
switch (action.type) {
|
||||
case ActionType.contractAction:
|
||||
return this.getContractServiceInstance(action);
|
||||
case ActionType.shopAction:
|
||||
return this.getShopServiceInstance(action);
|
||||
case ActionType.domainAction:
|
||||
return this.createTerminalObjectService;
|
||||
}
|
||||
}
|
||||
|
||||
private getContractServiceInstance(action: ClaimAction): CreateChangeItem {
|
||||
switch (action.name) {
|
||||
case ContractModificationName.legalAgreementBinding:
|
||||
return this.createLegalAgreementService;
|
||||
case ContractModificationName.adjustmentModification:
|
||||
return this.createContractTemplateService;
|
||||
case ContractModificationName.reportPreferencesModification:
|
||||
return this.createServiceAcceptanceActPreferencesService;
|
||||
}
|
||||
}
|
||||
|
||||
private getShopServiceInstance(action: ClaimAction): CreateChangeItem {
|
||||
switch (action.name) {
|
||||
case ShopModificationName.categoryModification:
|
||||
return this.createCategoryRefService;
|
||||
case ShopModificationName.shopAccountCreation:
|
||||
return this.createCurrencyRefService;
|
||||
case ShopModificationName.payoutScheduleModification:
|
||||
return this.createBusinessScheduleRefService;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private toPartyModificationType(type: ActionType): PartyModificationContainerType {
|
||||
switch (type) {
|
||||
case ActionType.contractAction:
|
||||
return PartyModificationContainerType.ContractModification;
|
||||
case ActionType.shopAction:
|
||||
return PartyModificationContainerType.ShopModification;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<form fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="20px"
|
||||
[formGroup]="form">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-select placeholder="Select contract template"
|
||||
formControlName="id">
|
||||
<mat-option *ngFor="let contract of contracts$ | async" [value]="contract.id" required>
|
||||
{{contract.id}} {{contract.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</form>
|
@ -0,0 +1,31 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/internal/operators';
|
||||
import sortBy from 'lodash-es/sortBy';
|
||||
|
||||
import { CreateContractTemplateService } from './create-contract-template.service';
|
||||
import { ContractTemplate } from '../../../papi/model';
|
||||
import { ContractService } from '../../../papi/contract.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-contract-template',
|
||||
templateUrl: 'create-contract-template.component.html'
|
||||
})
|
||||
export class CreateContractTemplateComponent implements OnInit {
|
||||
|
||||
contracts$: Observable<ContractTemplate[]>;
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(
|
||||
private createContractTemplateService: CreateContractTemplateService,
|
||||
private contractService: ContractService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = this.createContractTemplateService.form;
|
||||
this.contracts$ = this.contractService
|
||||
.getContractTemplates()
|
||||
.pipe(map((contracts) => sortBy(contracts, 'id')));
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import * as uuid from 'uuid/v4';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { ContractModification } from '../../../damsel/payment-processing';
|
||||
|
||||
@Injectable()
|
||||
export class CreateContractTemplateService implements CreateChangeItem {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
}
|
||||
|
||||
getValue(): ContractModification {
|
||||
return {
|
||||
adjustmentModification: {
|
||||
adjustmentId: uuid(),
|
||||
modification: {
|
||||
creation: {
|
||||
template: this.form.value
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
id: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<form fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="20px"
|
||||
[formGroup]="form">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Symbolic Code"
|
||||
formControlName="symbolicCode"
|
||||
required>
|
||||
</mat-form-field>
|
||||
</form>
|
@ -0,0 +1,20 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { CreateCurrencyRefService } from './create-currency-ref.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-currency-ref',
|
||||
templateUrl: 'create-currency-ref.component.html'
|
||||
})
|
||||
export class CreateCurrencyRefComponent implements OnInit {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private createCurrencyRefService: CreateCurrencyRefService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = this.createCurrencyRefService.form;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { ShopModification } from '../../../damsel/payment-processing';
|
||||
|
||||
@Injectable()
|
||||
export class CreateCurrencyRefService implements CreateChangeItem {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
}
|
||||
|
||||
getValue(): ShopModification {
|
||||
return {
|
||||
shopAccountCreation: {
|
||||
currency: this.form.value
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
symbolicCode: ['RUB', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<form fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="20px"
|
||||
[formGroup]="form">
|
||||
<mat-form-field fxFlex="50">
|
||||
<input matInput
|
||||
placeholder="Legal agreement ID"
|
||||
formControlName="legalAgreementId"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="50">
|
||||
<input matInput
|
||||
[matDatepicker]="signedAtDatepicker"
|
||||
placeholder="Signed at"
|
||||
formControlName="signedAt"
|
||||
required>
|
||||
<mat-datepicker-toggle matSuffix [for]="signedAtDatepicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #signedAtDatepicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</form>
|
@ -0,0 +1,20 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { CreateLegalAgreementService } from './create-legal-agreement.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-legal-agreement',
|
||||
templateUrl: './create-legal-agreement.component.html'
|
||||
})
|
||||
export class CreateLegalAgreementComponent implements OnInit {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private createLegalAgreementService: CreateLegalAgreementService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = this.createLegalAgreementService.form;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import * as moment from 'moment';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { ContractModification } from '../../../damsel';
|
||||
|
||||
@Injectable()
|
||||
export class CreateLegalAgreementService implements CreateChangeItem {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
}
|
||||
|
||||
getValue(): ContractModification {
|
||||
const {legalAgreementId, signedAt} = this.form.value;
|
||||
return {
|
||||
legalAgreementBinding: {
|
||||
legalAgreementId,
|
||||
signedAt: moment(signedAt).utc().format()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
private prepareForm() {
|
||||
return this.fb.group({
|
||||
legalAgreementId: ['', Validators.required],
|
||||
signedAt: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<form [formGroup]="form" fxLayout="column">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Schedule ID"
|
||||
formControlName="scheduleID"
|
||||
type="number"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<div fxFlex>
|
||||
<div fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Full Name"
|
||||
formControlName="fullName"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Position"
|
||||
formControlName="position"
|
||||
required>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-select placeholder="Document type" formControlName="documentType">
|
||||
<mat-option *ngFor="let documentType of documentTypes" [value]="documentType">
|
||||
{{documentType}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div fxLayout="column" *ngIf="form.value.documentType === 'PowerOfAttorney'" formGroupName="signer">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Legal Agreement ID"
|
||||
formControlName="legalAgreementId"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<div fxFlex>
|
||||
<div fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
[matDatepicker]="signedAtPicker"
|
||||
placeholder="Signed At"
|
||||
formControlName="signedAt"
|
||||
required>
|
||||
<mat-datepicker-toggle matSuffix [for]="signedAtPicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #signedAtPicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
[matDatepicker]="validUntilPicker"
|
||||
placeholder="Valid Until"
|
||||
formControlName="validUntil"
|
||||
required>
|
||||
<mat-datepicker-toggle matSuffix [for]="validUntilPicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #validUntilPicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -0,0 +1,23 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { CreateServiceAcceptanceActPreferencesService } from './create-service-acceptance-act-preferences.service';
|
||||
import { RepresentativeDocumentType } from '../../../damsel/domain/representative-document';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-service-acceptance-act-preferences',
|
||||
templateUrl: 'create-service-acceptance-act-preferences.component.html'
|
||||
})
|
||||
export class CreateServiceAcceptanceActPreferencesComponent {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
documentTypes = [
|
||||
RepresentativeDocumentType.PowerOfAttorney,
|
||||
RepresentativeDocumentType.ArticlesOfAssociation
|
||||
];
|
||||
|
||||
constructor(private createServiceAcceptanceActPreferencesService: CreateServiceAcceptanceActPreferencesService) {
|
||||
this.form = this.createServiceAcceptanceActPreferencesService.form;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import toNumber from 'lodash-es/toNumber';
|
||||
import * as moment from 'moment';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { ContractModification } from '../../../damsel/payment-processing';
|
||||
import { RepresentativeDocument, RepresentativeDocumentType } from '../../../damsel/domain/representative-document';
|
||||
|
||||
@Injectable()
|
||||
export class CreateServiceAcceptanceActPreferencesService implements CreateChangeItem {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
this.form.controls.documentType.valueChanges.subscribe((documentType) => {
|
||||
switch (documentType) {
|
||||
case RepresentativeDocumentType.PowerOfAttorney:
|
||||
this.form.setControl('signer', this.getPowerOfAttorneyGroup());
|
||||
break;
|
||||
case RepresentativeDocumentType.ArticlesOfAssociation:
|
||||
this.form.removeControl('signer');
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getValue(): ContractModification {
|
||||
const {scheduleID, fullName, position, documentType, signer} = this.form.value;
|
||||
return {
|
||||
reportPreferencesModification: {
|
||||
serviceAcceptanceActPreferences: {
|
||||
schedule: {
|
||||
id: toNumber(scheduleID)
|
||||
},
|
||||
signer: {
|
||||
fullName,
|
||||
position,
|
||||
document: this.getDocument(documentType, signer)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
private getDocument(type: RepresentativeDocumentType, signerValue: any): RepresentativeDocument {
|
||||
switch (type) {
|
||||
case RepresentativeDocumentType.PowerOfAttorney:
|
||||
const {legalAgreementId, validUntil, signedAt} = signerValue;
|
||||
return {
|
||||
powerOfAttorney: {
|
||||
legalAgreementId,
|
||||
validUntil: moment(validUntil).utc().format(),
|
||||
signedAt: moment(signedAt).utc().format()
|
||||
}
|
||||
};
|
||||
case RepresentativeDocumentType.ArticlesOfAssociation:
|
||||
return {
|
||||
articlesOfAssociation: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
scheduleID: ['', Validators.required],
|
||||
fullName: ['', Validators.required],
|
||||
position: ['', Validators.required],
|
||||
documentType: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
private getPowerOfAttorneyGroup(): FormGroup {
|
||||
return this.fb.group({
|
||||
legalAgreementId: ['', Validators.required],
|
||||
signedAt: ['', Validators.required],
|
||||
validUntil: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
<form *ngIf="form" [formGroup]="form" fxLayout="column" fxLayoutGap="20px">
|
||||
<div fxLayout>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-select placeholder="Provider name" formControlName="providerID" required>
|
||||
<mat-option *ngFor="let provider of providerObjects$ | async" [value]="provider.ref.id">
|
||||
{{provider.ref.id}} {{provider.data.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.sm="column" fxLayout.xs="column" fxLayoutGap="10px">
|
||||
<label fxFlex="25">Bank options template:</label>
|
||||
<mat-radio-group fxFlex="70" fxLayout fxLayoutAlign="space-between center"
|
||||
formControlName="bankOptionsTemplate">
|
||||
<mat-radio-button *ngFor="let template of optionTemplates"
|
||||
fxFlex
|
||||
[value]="template"
|
||||
(click)="setBankOptionsTemplate(template)">{{template}}
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.sm="column" fxLayout.xs="column">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Terminal name"
|
||||
formControlName="terminalName"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Terminal description"
|
||||
formControlName="terminalDescription"
|
||||
required>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.sm="column" fxLayout.xs="column" fxLayoutGap="10px">
|
||||
<label fxFlex="25">Risk coverage:</label>
|
||||
<mat-radio-group fxFlex="50" fxLayout fxLayoutAlign="space-between center"
|
||||
formControlName="riskCoverage">
|
||||
<mat-radio-button *ngFor="let coverage of riskCoverages"
|
||||
fxFlex
|
||||
[value]="coverage.value">{{coverage.name}}
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
<div fxLayout="column" fxLayoutGap="10px">
|
||||
<div>Options:</div>
|
||||
<div formArrayName="options">
|
||||
<div fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
*ngFor="let option of form.controls.options.controls; let i=index"
|
||||
[formGroupName]="i">
|
||||
<mat-form-field fxFlex="30">
|
||||
<input matInput
|
||||
placeholder="Key"
|
||||
formControlName="key"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
placeholder="Value"
|
||||
formControlName="value"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<button mat-icon-button color="basic" fxFlex="40px" (click)="removeOption(i)">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout fxLayoutAlign="end center">
|
||||
<button mat-icon-button color="basic" fxFlex="40px" (click)="addOption()">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -0,0 +1,54 @@
|
||||
import { Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { CreateTerminalObjectService } from './create-terminal-object.service';
|
||||
import { DomainTypedManager } from '../../../domain/domain-typed-manager';
|
||||
import { ProviderObject } from '../../../damsel/domain';
|
||||
import { DomainModificationInfo } from '../../model';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-create-terminal-object',
|
||||
templateUrl: 'create-terminal-object.component.html'
|
||||
})
|
||||
export class CreateTerminalObjectComponent implements OnInit, OnChanges {
|
||||
|
||||
@Input()
|
||||
domainModificationInfo: DomainModificationInfo;
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
providerObjects$: Observable<ProviderObject[]>;
|
||||
|
||||
optionTemplates: string[];
|
||||
|
||||
riskCoverages: Array<{ name: string, value: number }>;
|
||||
|
||||
constructor(private createTerminalObjectService: CreateTerminalObjectService,
|
||||
private domainTypedManager: DomainTypedManager) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.providerObjects$ = this.domainTypedManager.getProviderObjects();
|
||||
this.optionTemplates = this.createTerminalObjectService.optionTemplates;
|
||||
this.riskCoverages = this.createTerminalObjectService.riskCoverages;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.domainModificationInfo) {
|
||||
this.form = this.createTerminalObjectService.initForm(this.domainModificationInfo);
|
||||
}
|
||||
}
|
||||
|
||||
setBankOptionsTemplate(selectedOption: string) {
|
||||
this.createTerminalObjectService.setBankOptionsTemplate(selectedOption);
|
||||
}
|
||||
|
||||
addOption() {
|
||||
this.createTerminalObjectService.addOption();
|
||||
}
|
||||
|
||||
removeOption(index: number) {
|
||||
this.createTerminalObjectService.removeOption(index);
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { CreateChangeItem } from '../create-change-item';
|
||||
import { CreateTerminalParams, TerminalOption } from '../../../domain/domain-typed-manager';
|
||||
import { getOptions, prepareTerminalName } from './form-default-values';
|
||||
import { DomainModificationInfo } from '../../model';
|
||||
|
||||
const toFormArray = (fb: FormBuilder, options: TerminalOption[]): FormArray =>
|
||||
fb.array(options.map((option) => fb.group(option)));
|
||||
|
||||
@Injectable()
|
||||
export class CreateTerminalObjectService implements CreateChangeItem {
|
||||
|
||||
optionTemplates: string[] = ['VTB', 'TCS', 'RIET', 'SNGB', 'none'];
|
||||
|
||||
riskCoverages = [
|
||||
{
|
||||
name: 'low',
|
||||
value: 0
|
||||
}, {
|
||||
name: 'high',
|
||||
value: 100
|
||||
}, {
|
||||
name: 'fatal',
|
||||
value: 9999
|
||||
}
|
||||
];
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
private domainModificationInfo: DomainModificationInfo;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
}
|
||||
|
||||
getValue(): CreateTerminalParams {
|
||||
const {partyId, shopId} = this.domainModificationInfo;
|
||||
return this.toCreateTerminalParams(partyId, shopId);
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.form ? this.form.valid : false;
|
||||
}
|
||||
|
||||
addOption() {
|
||||
(this.form.controls.options as FormArray).push(this.getOption());
|
||||
}
|
||||
|
||||
removeOption(index: number) {
|
||||
const options = this.form.controls.options as FormArray;
|
||||
if (options.length > 1) {
|
||||
options.removeAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
initForm(info: DomainModificationInfo): FormGroup {
|
||||
this.domainModificationInfo = info;
|
||||
this.form = this.prepareForm(info);
|
||||
return this.form;
|
||||
}
|
||||
|
||||
setBankOptionsTemplate(option: string) {
|
||||
this.form.setControl('options', toFormArray(this.fb, getOptions(option, this.domainModificationInfo)));
|
||||
this.form.patchValue({
|
||||
terminalName: prepareTerminalName(option, this.domainModificationInfo.shopUrl)
|
||||
});
|
||||
}
|
||||
|
||||
private prepareForm(param: DomainModificationInfo): FormGroup {
|
||||
const defaultOption = 'VTB';
|
||||
return this.fb.group({
|
||||
providerID: ['', Validators.required],
|
||||
terminalName: [prepareTerminalName(defaultOption, param.shopUrl), Validators.required],
|
||||
terminalDescription: 'No',
|
||||
riskCoverage: [100, Validators.required],
|
||||
bankOptionsTemplate: [defaultOption],
|
||||
options: toFormArray(this.fb, getOptions(defaultOption, param))
|
||||
});
|
||||
}
|
||||
|
||||
private getOption(): FormGroup {
|
||||
return this.fb.group({
|
||||
key: '',
|
||||
value: ''
|
||||
});
|
||||
}
|
||||
|
||||
private toCreateTerminalParams(partyID: string, shopID: string): CreateTerminalParams {
|
||||
const {
|
||||
providerID,
|
||||
terminalName,
|
||||
terminalDescription,
|
||||
riskCoverage,
|
||||
options
|
||||
} = this.form.value;
|
||||
return {
|
||||
providerID,
|
||||
terminalName,
|
||||
terminalDescription,
|
||||
riskCoverage,
|
||||
options,
|
||||
partyID,
|
||||
shopID
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
export const getHost = (shopUrl: string) => {
|
||||
let host;
|
||||
try {
|
||||
host = new URL(shopUrl).host;
|
||||
} catch (ex) {
|
||||
console.warn(ex);
|
||||
}
|
||||
return host;
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
import { getVtbTemplateOptions } from './get-vtb-template-options';
|
||||
import { getTcsTemplateOptions } from './get-tcs-template-options';
|
||||
import { getRietTemplateOptions } from './get-riet-template-options';
|
||||
import { getSngbTemplateOptions } from './get-sngb-template-options';
|
||||
import { TerminalOption } from '../../../../domain/domain-typed-manager';
|
||||
import { DomainModificationInfo } from '../../../model';
|
||||
|
||||
export const getOptions = (option: string, param: DomainModificationInfo): TerminalOption[] => {
|
||||
const {shopUrl, partyId} = param;
|
||||
let options = [{key: '', value: ''}];
|
||||
switch (option) {
|
||||
case 'VTB':
|
||||
options = getVtbTemplateOptions(shopUrl, partyId);
|
||||
break;
|
||||
case 'TCS':
|
||||
options = getTcsTemplateOptions(shopUrl);
|
||||
break;
|
||||
case 'RIET':
|
||||
options = getRietTemplateOptions();
|
||||
break;
|
||||
case 'SNGB':
|
||||
options = getSngbTemplateOptions();
|
||||
break;
|
||||
|
||||
}
|
||||
return options;
|
||||
};
|
@ -0,0 +1,21 @@
|
||||
import { TerminalOption } from '../../../../domain/domain-typed-manager';
|
||||
|
||||
export const getRietTemplateOptions = (): TerminalOption[] =>
|
||||
([
|
||||
{
|
||||
key: 'custom_return_url',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'routing',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'routing_recurrent',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'terminal_id',
|
||||
value: ''
|
||||
}
|
||||
]);
|
@ -0,0 +1,14 @@
|
||||
export const getSngbTemplateOptions = () => ([
|
||||
{
|
||||
key: 'mpiEnable',
|
||||
value: 'true'
|
||||
},
|
||||
{
|
||||
key: 'terminal_id',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'tran_portal_password',
|
||||
value: ''
|
||||
}
|
||||
]);
|
@ -0,0 +1,34 @@
|
||||
import { getHost } from './get-host';
|
||||
import { TerminalOption } from '../../../../domain/domain-typed-manager';
|
||||
|
||||
export const getTcsTemplateOptions = (shopUrl: string): TerminalOption[] =>
|
||||
([
|
||||
{
|
||||
key: 'terminalIdNon3ds',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'terminalId3ds',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'submerchantId',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'mpiEnable',
|
||||
value: 'true'
|
||||
},
|
||||
{
|
||||
key: 'merchantId',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'merchantName',
|
||||
value: getHost(shopUrl)
|
||||
},
|
||||
{
|
||||
key: 'merchantUrl',
|
||||
value: shopUrl
|
||||
}
|
||||
]);
|
@ -0,0 +1,47 @@
|
||||
import last from 'lodash-es/last';
|
||||
import { getHost } from './get-host';
|
||||
import { TerminalOption } from '../../../../domain/domain-typed-manager';
|
||||
|
||||
const partyIDToSmid = (partyID: string) => last(partyID.split('-'));
|
||||
|
||||
const prepareMerchantName = (shopUrl: string) => `${getHost(shopUrl)}@RBKmoney`;
|
||||
|
||||
export const getVtbTemplateOptions = (shopUrl: string, partyID: string): TerminalOption[] =>
|
||||
([
|
||||
{
|
||||
key: 'PFSNAME',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'SMADDRESS',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'SMCITY',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'SMID',
|
||||
value: partyIDToSmid(partyID)
|
||||
},
|
||||
{
|
||||
key: 'SMMCC',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'SMPOSTCODE',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'merchant_id',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
key: 'merchant_name',
|
||||
value: prepareMerchantName(shopUrl)
|
||||
},
|
||||
{
|
||||
key: 'term_id',
|
||||
value: ''
|
||||
}
|
||||
]);
|
@ -0,0 +1,2 @@
|
||||
export * from './get-options';
|
||||
export * from './prepare-terminal-name';
|
@ -0,0 +1,3 @@
|
||||
import { getHost } from './get-host';
|
||||
|
||||
export const prepareTerminalName = (bankOption: string, shopUrl: string) => `${bankOption} / ${getHost(shopUrl)}`;
|
23
src/app/claim/deny-claim/deny-claim.component.html
Normal file
23
src/app/claim/deny-claim/deny-claim.component.html
Normal file
@ -0,0 +1,23 @@
|
||||
<div class="mat-dialog-title">Confirm claim denying</div>
|
||||
<mat-dialog-content>
|
||||
<form fxLayout="row">
|
||||
<mat-form-field fxFlex class="example-full-width">
|
||||
<textarea matInput
|
||||
placeholder="Reason"
|
||||
[(ngModel)]="reason"
|
||||
name="reason">
|
||||
</textarea>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions fxLayout="column" fxLayoutGap="10px">
|
||||
<div>
|
||||
<button mat-button
|
||||
[disabled]="isLoading"
|
||||
color="primary"
|
||||
(click)="deny()">CONFIRM
|
||||
</button>
|
||||
<button [disabled]="isLoading" mat-button [mat-dialog-close]="false">CANCEL</button>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="isLoading" mode="indeterminate"></mat-progress-bar>
|
||||
</mat-dialog-actions>
|
33
src/app/claim/deny-claim/deny-claim.component.ts
Normal file
33
src/app/claim/deny-claim/deny-claim.component.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatDialogRef, MatSnackBar } from '@angular/material';
|
||||
|
||||
import { ClaimService } from '../claim.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'deny-claim.component.html'
|
||||
})
|
||||
export class DenyClaimComponent {
|
||||
|
||||
isLoading = false;
|
||||
|
||||
reason = '';
|
||||
|
||||
constructor(
|
||||
private dialogRef: MatDialogRef<DenyClaimComponent>,
|
||||
private claimService: ClaimService,
|
||||
private snackBar: MatSnackBar
|
||||
) {
|
||||
}
|
||||
|
||||
deny() {
|
||||
this.isLoading = true;
|
||||
this.claimService.denyClaim(this.reason).subscribe(() => {
|
||||
this.isLoading = false;
|
||||
this.dialogRef.close();
|
||||
this.snackBar.open('Claim denied', 'OK', {duration: 3000});
|
||||
}, () => {
|
||||
this.isLoading = false;
|
||||
this.snackBar.open('An error occurred while claim denying', 'OK');
|
||||
});
|
||||
}
|
||||
}
|
16
src/app/claim/model/claim-info-container.ts
Normal file
16
src/app/claim/model/claim-info-container.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { PartyModificationUnit } from './party-modification-unit';
|
||||
|
||||
export class ClaimInfoContainer {
|
||||
status: string;
|
||||
partyId: string;
|
||||
claimId: number;
|
||||
revision: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
reason: string;
|
||||
partyModificationUnits: PartyModificationUnit[];
|
||||
extractedIds: {
|
||||
shopId: string,
|
||||
contractId: string
|
||||
};
|
||||
}
|
9
src/app/claim/model/contract-modification-name.ts
Normal file
9
src/app/claim/model/contract-modification-name.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export enum ContractModificationName {
|
||||
creation = 'creation',
|
||||
termination = 'termination',
|
||||
adjustmentModification = 'adjustmentModification',
|
||||
payoutToolModification = 'payoutToolModification',
|
||||
legalAgreementBinding = 'legalAgreementBinding',
|
||||
reportPreferencesModification = 'reportPreferencesModification',
|
||||
unknown = 'unknown'
|
||||
}
|
5
src/app/claim/model/domain-modification-info.ts
Normal file
5
src/app/claim/model/domain-modification-info.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export class DomainModificationInfo {
|
||||
shopUrl: string;
|
||||
shopId: string;
|
||||
partyId: string;
|
||||
}
|
8
src/app/claim/model/index.ts
Normal file
8
src/app/claim/model/index.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export * from './claim-info-container';
|
||||
export * from './contract-modification-name';
|
||||
export * from './party-modification-container';
|
||||
export * from './party-modification-unit-type';
|
||||
export * from './party-modification-unit';
|
||||
export * from './shop-modification-name';
|
||||
export * from './party-modification-container-type';
|
||||
export * from './domain-modification-info';
|
4
src/app/claim/model/party-modification-container-type.ts
Normal file
4
src/app/claim/model/party-modification-container-type.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export enum PartyModificationContainerType {
|
||||
ContractModification = 'ContractModification',
|
||||
ShopModification = 'ShopModification'
|
||||
}
|
10
src/app/claim/model/party-modification-container.ts
Normal file
10
src/app/claim/model/party-modification-container.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { ContractModificationName } from './contract-modification-name';
|
||||
import { ShopModificationName } from './shop-modification-name';
|
||||
import { ShopModificationUnit, ContractModificationUnit } from '../../damsel';
|
||||
import { PartyModificationContainerType } from './party-modification-container-type';
|
||||
|
||||
export class PartyModificationContainer {
|
||||
type: PartyModificationContainerType;
|
||||
name: ContractModificationName | ShopModificationName;
|
||||
modifications: ContractModificationUnit[] | ShopModificationUnit[];
|
||||
}
|
5
src/app/claim/model/party-modification-unit-type.ts
Normal file
5
src/app/claim/model/party-modification-unit-type.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum PartyModificationUnitType {
|
||||
ShopModification = 'ShopModification',
|
||||
ContractModification = 'ContractModification',
|
||||
unknown = 'unknown'
|
||||
}
|
7
src/app/claim/model/party-modification-unit.ts
Normal file
7
src/app/claim/model/party-modification-unit.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { PartyModificationUnitType } from './party-modification-unit-type';
|
||||
import { PartyModificationContainer } from './party-modification-container';
|
||||
|
||||
export class PartyModificationUnit {
|
||||
type: PartyModificationUnitType;
|
||||
containers: PartyModificationContainer[];
|
||||
}
|
11
src/app/claim/model/shop-modification-name.ts
Normal file
11
src/app/claim/model/shop-modification-name.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export enum ShopModificationName {
|
||||
creation = 'creation',
|
||||
categoryModification = 'categoryModification',
|
||||
detailsModification = 'detailsModification',
|
||||
contractModification = 'contractModification',
|
||||
payoutToolModification = 'payoutToolModification',
|
||||
locationModification = 'locationModification',
|
||||
shopAccountCreation = 'shopAccountCreation',
|
||||
payoutScheduleModification = 'payoutScheduleModification',
|
||||
unknown = 'unknown'
|
||||
}
|
136
src/app/claim/party-modification-container-converter.ts
Normal file
136
src/app/claim/party-modification-container-converter.ts
Normal file
@ -0,0 +1,136 @@
|
||||
import groupBy from 'lodash-es/groupBy';
|
||||
import reduce from 'lodash-es/reduce';
|
||||
import map from 'lodash-es/map';
|
||||
|
||||
import {
|
||||
PartyModification,
|
||||
ShopModificationUnit,
|
||||
ContractModificationUnit
|
||||
} from '../damsel';
|
||||
import {
|
||||
PartyModificationUnitType,
|
||||
PartyModificationContainer,
|
||||
PartyModificationUnit,
|
||||
ContractModificationName,
|
||||
ShopModificationName,
|
||||
PartyModificationContainerType
|
||||
} from './model';
|
||||
|
||||
export class PartyModificationContainerConverter {
|
||||
|
||||
static convert(modificationUnits: PartyModification[]): PartyModificationUnit[] {
|
||||
const grouped = groupBy(modificationUnits, (item: PartyModification) => {
|
||||
const {shopModification, contractModification} = item;
|
||||
if (shopModification) {
|
||||
return PartyModificationUnitType.ShopModification;
|
||||
}
|
||||
if (contractModification) {
|
||||
return PartyModificationUnitType.ContractModification;
|
||||
}
|
||||
return PartyModificationUnitType.unknown;
|
||||
});
|
||||
return reduce(grouped, (result, group, type) => {
|
||||
switch (type) {
|
||||
case PartyModificationUnitType.ContractModification:
|
||||
result.push({type, ...this.resolveContractContainers(group)});
|
||||
break;
|
||||
case PartyModificationUnitType.ShopModification:
|
||||
result.push({type, ...this.resolveShopContainers(group)});
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
|
||||
private static resolveContractContainers(contracts: PartyModification[]) {
|
||||
const modifications = contracts.map((modification) => modification.contractModification);
|
||||
return {containers: this.toContractContainers(modifications)};
|
||||
}
|
||||
|
||||
private static resolveShopContainers(shops: PartyModification[]) {
|
||||
const modifications = shops.map((modification) => modification.shopModification);
|
||||
return {containers: this.toShopContainer(modifications)};
|
||||
}
|
||||
|
||||
private static toContractContainers(modification: ContractModificationUnit[]): PartyModificationContainer[] {
|
||||
const grouped = groupBy(modification, (item: ContractModificationUnit) => {
|
||||
const {
|
||||
creation,
|
||||
termination,
|
||||
adjustmentModification,
|
||||
payoutToolModification,
|
||||
legalAgreementBinding,
|
||||
reportPreferencesModification,
|
||||
} = item.modification;
|
||||
if (creation) {
|
||||
return ContractModificationName.creation;
|
||||
}
|
||||
if (termination) {
|
||||
return ContractModificationName.termination;
|
||||
}
|
||||
if (adjustmentModification) {
|
||||
return ContractModificationName.adjustmentModification;
|
||||
}
|
||||
if (payoutToolModification) {
|
||||
return ContractModificationName.payoutToolModification;
|
||||
}
|
||||
if (legalAgreementBinding) {
|
||||
return ContractModificationName.legalAgreementBinding;
|
||||
}
|
||||
if (reportPreferencesModification) {
|
||||
return ContractModificationName.reportPreferencesModification;
|
||||
}
|
||||
return ContractModificationName.unknown;
|
||||
});
|
||||
return map(grouped, (modifications, name: ContractModificationName) => ({
|
||||
type: PartyModificationContainerType.ContractModification,
|
||||
name,
|
||||
modifications
|
||||
}));
|
||||
}
|
||||
|
||||
private static toShopContainer(modification: ShopModificationUnit[]): PartyModificationContainer[] {
|
||||
const grouped = groupBy(modification, (item: ShopModificationUnit) => {
|
||||
const {
|
||||
creation,
|
||||
categoryModification,
|
||||
detailsModification,
|
||||
contractModification,
|
||||
payoutToolModification,
|
||||
locationModification,
|
||||
shopAccountCreation,
|
||||
payoutScheduleModification
|
||||
} = item.modification;
|
||||
if (creation) {
|
||||
return ShopModificationName.creation;
|
||||
}
|
||||
if (categoryModification) {
|
||||
return ShopModificationName.categoryModification;
|
||||
}
|
||||
if (detailsModification) {
|
||||
return ShopModificationName.detailsModification;
|
||||
}
|
||||
if (contractModification) {
|
||||
return ShopModificationName.contractModification;
|
||||
}
|
||||
if (payoutToolModification) {
|
||||
return ShopModificationName.payoutToolModification;
|
||||
}
|
||||
if (locationModification) {
|
||||
return ShopModificationName.locationModification;
|
||||
}
|
||||
if (shopAccountCreation) {
|
||||
return ShopModificationName.shopAccountCreation;
|
||||
}
|
||||
if (payoutScheduleModification) {
|
||||
return ShopModificationName.payoutScheduleModification;
|
||||
}
|
||||
return ShopModificationName.unknown;
|
||||
});
|
||||
return map(grouped, (modifications, name: ShopModificationName) => ({
|
||||
type: PartyModificationContainerType.ShopModification,
|
||||
name,
|
||||
modifications
|
||||
}));
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<mat-card>
|
||||
<mat-card-subtitle>{{container.name | ccContainerName:container.type }}</mat-card-subtitle>
|
||||
<mat-card-content>
|
||||
<mat-tab-group>
|
||||
<mat-tab *ngFor="let unit of modifications" label="Modification unit">
|
||||
<pre [innerHtml]="unit | ccThriftEncode | prettyjson:2"></pre>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
@ -0,0 +1,48 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
|
||||
import { PartyModificationContainer } from '../model';
|
||||
import { ContractModificationUnit, ShopModificationUnit } from '../../damsel';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-party-modification-container',
|
||||
templateUrl: 'party-modification-container.component.html',
|
||||
styles: [`
|
||||
:host /deep/ .string {
|
||||
color: #008000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:host /deep/ .number {
|
||||
color: #0000FF;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:host /deep/ .boolean {
|
||||
color: #000080;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:host /deep/ .null {
|
||||
color: magenta;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:host /deep/ .key {
|
||||
color: #660E7A;
|
||||
font-weight: bold;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class PartyModificationContainerComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
container: PartyModificationContainer;
|
||||
|
||||
modifications: ContractModificationUnit[] | ShopModificationUnit[];
|
||||
|
||||
ngOnInit() {
|
||||
this.modifications = this.container.modifications
|
||||
.slice()
|
||||
.reverse();
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<div fxLayout="row" fxLayout.md="column" fxLayout.sm="column" fxLayout.xs="column" fxLayoutGap="20px">
|
||||
<div *ngIf="shopUnit" fxFlex="50" fxLayout="column" fxLayoutGap="20px">
|
||||
<mat-card>
|
||||
<mat-card-subtitle fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="10px"
|
||||
fxLayoutAlign="space-between stretch">
|
||||
<div>Shop modifications</div>
|
||||
<div>Shop ID: {{extractedIds.shopId}}</div>
|
||||
</mat-card-subtitle>
|
||||
</mat-card>
|
||||
<cc-party-modification-container
|
||||
*ngFor="let container of shopUnit.containers"
|
||||
[container]="container">
|
||||
</cc-party-modification-container>
|
||||
</div>
|
||||
<div *ngIf="contractUnit" fxFlex="50" fxLayout="column" fxLayoutGap="20px">
|
||||
<mat-card>
|
||||
<mat-card-subtitle fxLayout="row"
|
||||
fxLayout.sm="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutGap="10px"
|
||||
fxLayoutAlign="space-between stretch">
|
||||
<div>Contract modifications</div>
|
||||
<div>Contract ID: {{extractedIds.contractId}}</div>
|
||||
</mat-card-subtitle>
|
||||
</mat-card>
|
||||
<cc-party-modification-container
|
||||
*ngFor="let container of contractUnit.containers"
|
||||
[container]="container">
|
||||
</cc-party-modification-container>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,48 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
|
||||
import { ClaimService } from '../claim.service';
|
||||
import { PartyModificationUnit, PartyModificationUnitType } from '../model';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-party-modifications',
|
||||
templateUrl: 'party-modifications.component.html'
|
||||
})
|
||||
export class PartyModificationsComponent implements OnInit {
|
||||
|
||||
shopUnit: PartyModificationUnit;
|
||||
|
||||
contractUnit: PartyModificationUnit;
|
||||
|
||||
extractedIds: {
|
||||
shopId: string;
|
||||
contractId: string;
|
||||
};
|
||||
|
||||
constructor(private claimService: ClaimService,
|
||||
private snackBar: MatSnackBar) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.claimService.claimInfoContainer$.subscribe((container) => {
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
this.extractedIds = container.extractedIds;
|
||||
const units = container.partyModificationUnits;
|
||||
for (const unit of units) {
|
||||
switch (unit.type) {
|
||||
case PartyModificationUnitType.ShopModification:
|
||||
this.shopUnit = unit;
|
||||
break;
|
||||
case PartyModificationUnitType.ContractModification:
|
||||
this.contractUnit = unit;
|
||||
break;
|
||||
case PartyModificationUnitType.unknown:
|
||||
this.snackBar.open('Detected unknown party modification unit', 'OK');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
21
src/app/claims/claims-auth-guard.service.ts
Normal file
21
src/app/claims/claims-auth-guard.service.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class ClaimsAuthGuardService extends KeycloakAuthGuard {
|
||||
|
||||
constructor(protected router: Router, protected keycloakAngular: KeycloakService) {
|
||||
super(router, keycloakAngular);
|
||||
}
|
||||
|
||||
isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.roles || this.roles.length === 0) {
|
||||
resolve(false);
|
||||
}
|
||||
const granted = this.roles.includes('claim:get');
|
||||
resolve(granted);
|
||||
});
|
||||
}
|
||||
}
|
24
src/app/claims/claims-routing.module.ts
Normal file
24
src/app/claims/claims-routing.module.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ClaimsComponent } from './claims.component';
|
||||
import { ClaimsAuthGuardService } from './claims-auth-guard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'claims',
|
||||
component: ClaimsComponent,
|
||||
canActivate: [ClaimsAuthGuardService]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
],
|
||||
providers: [
|
||||
ClaimsAuthGuardService
|
||||
]
|
||||
})
|
||||
export class ClaimsRoutingModule {}
|
7
src/app/claims/claims-table/claims-table.component.css
Normal file
7
src/app/claims/claims-table/claims-table.component.css
Normal file
@ -0,0 +1,7 @@
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action-cell {
|
||||
width: 10px;
|
||||
}
|
36
src/app/claims/claims-table/claims-table.component.html
Normal file
36
src/app/claims/claims-table/claims-table.component.html
Normal file
@ -0,0 +1,36 @@
|
||||
<table mat-table [dataSource]="claims" class="mat-elevation-z2">
|
||||
<ng-container matColumnDef="partyID">
|
||||
<th mat-header-cell *matHeaderCellDef>Party ID</th>
|
||||
<td mat-cell *matCellDef="let claim">{{ claim.partyId }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="claimID">
|
||||
<th fxHide.sm fxHide.xs mat-header-cell *matHeaderCellDef>Claim ID</th>
|
||||
<td fxHide.sm fxHide.xs mat-cell *matCellDef="let claim">{{ claim.claimId }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef>Status</th>
|
||||
<td mat-cell *matCellDef="let claim">{{ claim.status }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="revision">
|
||||
<th fxHide.sm fxHide.xs mat-header-cell *matHeaderCellDef>Revision</th>
|
||||
<td fxHide.sm fxHide.xs mat-cell *matCellDef="let claim">{{ claim.revision }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="createdAt">
|
||||
<th fxHide.xs mat-header-cell *matHeaderCellDef>Created at</th>
|
||||
<td fxHide.xs mat-cell *matCellDef="let claim">{{ claim.createdAt | date: "dd.MM.yyyy HH:mm:ss" }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="updatedAt">
|
||||
<th fxHide.sm fxHide.xs mat-header-cell *matHeaderCellDef>Updated at</th>
|
||||
<td fxHide.sm fxHide.xs mat-cell *matCellDef="let claim">{{ claim.updatedAt | date: "dd.MM.yyyy HH:mm:ss" }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="claimDetailButton">
|
||||
<th mat-header-cell *matHeaderCellDef class="action-cell"></th>
|
||||
<td mat-cell *matCellDef="let claim;" class="action-cell">
|
||||
<button mat-icon-button (click)="navigateToClaim(claim)">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let claim; columns: displayedColumns;"></tr>
|
||||
</table>
|
31
src/app/claims/claims-table/claims-table.component.ts
Normal file
31
src/app/claims/claims-table/claims-table.component.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ClaimInfo } from '../../papi/model';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-claims-table',
|
||||
templateUrl: 'claims-table.component.html',
|
||||
styleUrls: ['./claims-table.component.css']
|
||||
})
|
||||
export class ClaimsTableComponent {
|
||||
|
||||
@Input()
|
||||
claims: ClaimInfo[];
|
||||
|
||||
displayedColumns = [
|
||||
'partyID',
|
||||
'claimID',
|
||||
'status',
|
||||
'revision',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'claimDetailButton'
|
||||
];
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
navigateToClaim(claim: ClaimInfo) {
|
||||
this.router.navigate([`/claims/${claim.partyId}/${claim.claimId}`]);
|
||||
}
|
||||
}
|
16
src/app/claims/claims.component.html
Normal file
16
src/app/claims/claims.component.html
Normal file
@ -0,0 +1,16 @@
|
||||
<div class="container">
|
||||
<div class="card-container" fxLayout="column" fxLayoutGap="20px">
|
||||
<mat-card>
|
||||
<mat-card-subtitle>
|
||||
Search claims
|
||||
</mat-card-subtitle>
|
||||
<mat-card-content>
|
||||
<cc-search-form (valueChanges)="search($event)"></cc-search-form>
|
||||
</mat-card-content>
|
||||
<mat-card-footer *ngIf="isLoading">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</mat-card-footer>
|
||||
</mat-card>
|
||||
<cc-claims-table [claims]="claims"></cc-claims-table>
|
||||
</div>
|
||||
</div>
|
37
src/app/claims/claims.component.ts
Normal file
37
src/app/claims/claims.component.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
|
||||
import { ClaimService } from '../papi/claim.service';
|
||||
import { ClaimSearchParams } from '../papi/params';
|
||||
import { ClaimInfo } from '../papi/model';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'claims.component.html',
|
||||
styleUrls: ['../shared/container.css'],
|
||||
})
|
||||
export class ClaimsComponent implements OnInit {
|
||||
|
||||
isLoading = false;
|
||||
|
||||
claims: ClaimInfo[];
|
||||
|
||||
constructor(private claimService: ClaimService,
|
||||
private snackBar: MatSnackBar) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.search({claimStatus: 'pending'});
|
||||
}
|
||||
|
||||
search(params: ClaimSearchParams) {
|
||||
this.isLoading = true;
|
||||
this.claimService.getClaims(params).subscribe((claims) => {
|
||||
this.isLoading = false;
|
||||
this.claims = claims.reverse();
|
||||
}, (error: HttpErrorResponse) => {
|
||||
this.isLoading = false;
|
||||
this.snackBar.open(`${error.status}: ${error.message}`, 'OK');
|
||||
});
|
||||
}
|
||||
}
|
51
src/app/claims/claims.module.ts
Normal file
51
src/app/claims/claims.module.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatMenuModule,
|
||||
MatProgressBarModule,
|
||||
MatSelectModule,
|
||||
MatSnackBarModule,
|
||||
MatTableModule
|
||||
} from '@angular/material';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { CdkTableModule } from '@angular/cdk/table';
|
||||
|
||||
import { ClaimsComponent } from './claims.component';
|
||||
import { ClaimsRoutingModule } from './claims-routing.module';
|
||||
import { PapiModule } from '../papi/papi.module';
|
||||
import { SearchFormComponent } from './search-form/search-form.component';
|
||||
import { ClaimsTableComponent } from './claims-table/claims-table.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
ClaimsRoutingModule,
|
||||
FlexLayoutModule,
|
||||
PapiModule,
|
||||
ReactiveFormsModule,
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
MatProgressBarModule,
|
||||
MatSnackBarModule,
|
||||
MatTableModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
CdkTableModule
|
||||
],
|
||||
declarations: [
|
||||
ClaimsComponent,
|
||||
SearchFormComponent,
|
||||
ClaimsTableComponent
|
||||
]
|
||||
})
|
||||
export class ClaimsModule {
|
||||
}
|
11
src/app/claims/search-form/search-form.component.html
Normal file
11
src/app/claims/search-form/search-form.component.html
Normal file
@ -0,0 +1,11 @@
|
||||
<form fxLayout="row" fxLayout.xs="column" fxLayoutGap="20px" [formGroup]="form">
|
||||
<mat-form-field fxFlex="15" fxFlex.sm="30">
|
||||
<mat-select placeholder="Claim status" formControlName="claimStatus">
|
||||
<mat-option [value]="null">any</mat-option>
|
||||
<mat-option *ngFor="let status of claimStatuses" [value]="status">{{status}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="30" fxFlex.sm="70">
|
||||
<input matInput placeholder="Party ID" formControlName="partyId">
|
||||
</mat-form-field>
|
||||
</form>
|
33
src/app/claims/search-form/search-form.component.ts
Normal file
33
src/app/claims/search-form/search-form.component.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { SearchFormService } from './search-form.service';
|
||||
import { ClaimSearchParams } from '../../papi/params';
|
||||
import { debounceTime } from 'rxjs/internal/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-search-form',
|
||||
templateUrl: 'search-form.component.html',
|
||||
providers: [SearchFormService]
|
||||
})
|
||||
export class SearchFormComponent implements OnInit {
|
||||
|
||||
@Output()
|
||||
valueChanges: EventEmitter<ClaimSearchParams> = new EventEmitter();
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
claimStatuses: string[];
|
||||
|
||||
constructor(private searchFormService: SearchFormService) {}
|
||||
|
||||
ngOnInit() {
|
||||
const {claimStatuses, form, formValueToSearchParams} = this.searchFormService;
|
||||
this.claimStatuses = claimStatuses;
|
||||
this.form = form;
|
||||
this.form.valueChanges
|
||||
.pipe(debounceTime(300))
|
||||
.subscribe((value) =>
|
||||
this.valueChanges.emit(formValueToSearchParams(value)));
|
||||
}
|
||||
}
|
40
src/app/claims/search-form/search-form.service.ts
Normal file
40
src/app/claims/search-form/search-form.service.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import values from 'lodash-es/values';
|
||||
import mapValues from 'lodash-es/mapValues';
|
||||
import isString from 'lodash-es/isString';
|
||||
|
||||
import { ClaimStatus } from '../../papi/model/claim-statuses';
|
||||
import { ClaimSearchParams } from '../../papi/params';
|
||||
|
||||
@Injectable()
|
||||
export class SearchFormService {
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
claimStatuses: string[];
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
this.claimStatuses = values(ClaimStatus);
|
||||
}
|
||||
|
||||
formValueToSearchParams(formValue): ClaimSearchParams {
|
||||
return mapValues(formValue, (value) => {
|
||||
let result = value;
|
||||
if (value === '') {
|
||||
result = null;
|
||||
} else if (isString(value)) {
|
||||
result = value.trim();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
claimStatus: 'pending',
|
||||
partyId: ''
|
||||
});
|
||||
}
|
||||
}
|
26
src/app/core/config.service.ts
Normal file
26
src/app/core/config.service.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
export interface AppConfig {
|
||||
papiEndpoint: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
|
||||
config: AppConfig;
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
load() {
|
||||
return new Promise((resolve) => {
|
||||
this.http
|
||||
.get<AppConfig>('assets/appConfig.json')
|
||||
.subscribe((config) => {
|
||||
this.config = config;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
39
src/app/core/core.module.ts
Normal file
39
src/app/core/core.module.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
|
||||
|
||||
import { ConfigService } from './config.service';
|
||||
|
||||
const initializer = (keycloak: KeycloakService, configService: ConfigService) =>
|
||||
() => Promise.all([
|
||||
configService.load(),
|
||||
keycloak.init({
|
||||
config: '/assets/authConfig.json',
|
||||
initOptions: {
|
||||
onLoad: 'login-required',
|
||||
checkLoginIframe: true
|
||||
},
|
||||
enableBearerInterceptor: true,
|
||||
bearerExcludedUrls: [
|
||||
'/assets'
|
||||
],
|
||||
bearerPrefix: 'Bearer'
|
||||
})
|
||||
]);
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
KeycloakAngularModule
|
||||
],
|
||||
providers: [
|
||||
ConfigService,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initializer,
|
||||
multi: true,
|
||||
deps: [KeycloakService, ConfigService]
|
||||
}
|
||||
]
|
||||
})
|
||||
export class CoreModule {}
|
5
src/app/damsel/domain-config/commit.ts
Normal file
5
src/app/damsel/domain-config/commit.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { Operation } from './operation';
|
||||
|
||||
export class Commit {
|
||||
ops: Operation[];
|
||||
}
|
2
src/app/damsel/domain-config/head.ts
Normal file
2
src/app/damsel/domain-config/head.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// tslint:disable-next-line:interface-over-type-literal
|
||||
export type Head = {};
|
9
src/app/damsel/domain-config/index.ts
Normal file
9
src/app/damsel/domain-config/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export * from './snapshot';
|
||||
export * from './version';
|
||||
export * from './commit';
|
||||
export * from './insert-op';
|
||||
export * from './operation';
|
||||
export * from './remove-op';
|
||||
export * from './update-op';
|
||||
export * from './head';
|
||||
export * from './reference';
|
5
src/app/damsel/domain-config/insert-op.ts
Normal file
5
src/app/damsel/domain-config/insert-op.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { DomainObject } from '../domain';
|
||||
|
||||
export class InsertOp {
|
||||
object: DomainObject;
|
||||
}
|
9
src/app/damsel/domain-config/operation.ts
Normal file
9
src/app/damsel/domain-config/operation.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { InsertOp } from './insert-op';
|
||||
import { UpdateOp } from './update-op';
|
||||
import { RemoveOp } from './remove-op';
|
||||
|
||||
export class Operation {
|
||||
insert?: InsertOp;
|
||||
update?: UpdateOp;
|
||||
remove?: RemoveOp;
|
||||
}
|
7
src/app/damsel/domain-config/reference.ts
Normal file
7
src/app/damsel/domain-config/reference.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Version } from './version';
|
||||
import { Head } from './head';
|
||||
|
||||
export class Reference {
|
||||
version?: Version;
|
||||
head?: Head;
|
||||
}
|
5
src/app/damsel/domain-config/remove-op.ts
Normal file
5
src/app/damsel/domain-config/remove-op.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { DomainObject } from '../domain';
|
||||
|
||||
export class RemoveOp {
|
||||
object: DomainObject;
|
||||
}
|
7
src/app/damsel/domain-config/snapshot.ts
Normal file
7
src/app/damsel/domain-config/snapshot.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Domain } from '../domain';
|
||||
import { Version } from './version';
|
||||
|
||||
export class Snapshot {
|
||||
version: Version;
|
||||
domain: Domain;
|
||||
}
|
6
src/app/damsel/domain-config/update-op.ts
Normal file
6
src/app/damsel/domain-config/update-op.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { DomainObject } from '../domain';
|
||||
|
||||
export class UpdateOp {
|
||||
oldObject: DomainObject;
|
||||
newObject: DomainObject;
|
||||
}
|
1
src/app/damsel/domain-config/version.ts
Normal file
1
src/app/damsel/domain-config/version.ts
Normal file
@ -0,0 +1 @@
|
||||
export type Version = number;
|
6
src/app/damsel/domain/abstract-domain-object.ts
Normal file
6
src/app/damsel/domain/abstract-domain-object.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { AbstractDomainRef } from './abstract-domain-ref';
|
||||
|
||||
export class AbstractDomainObject {
|
||||
ref: AbstractDomainRef;
|
||||
data: any;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user