Skip to content

Commit

Permalink
Check contract limits before negotiating a new one (#804)
Browse files Browse the repository at this point in the history
  • Loading branch information
illfixit authored Aug 27, 2024
1 parent e507c51 commit 9ab4084
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 56 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ the detailed section referring to by linking pull requests or issues.

#### Patch

- Check contract limits before negotiating a new one.

## [v4.1.2] - 2024-08-20

### Overview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,13 @@
*ngIf="!data.asset.isOwnConnector"
mat-raised-button
color="primary"
[matTooltip]="
limitsExceeded
? 'You have reached the maximum number of consuming contracts. Please terminate one of the existing contracts to negotiate a new one.'
: ''
"
[disabled]="
limitsExceeded ||
contractNegotiationService.negotiationState(
data.dataOffer!.contractOffers[0]
) != 'ready'
Expand Down Expand Up @@ -226,8 +232,7 @@
"
mat-raised-button
color="primary"
[matTooltip]="data.contractAgreement?.statusTooltipText ?? ''"
[disabled]="!data.contractAgreement?.canTransfer"
[disabled]="data.contractAgreement?.isTerminated"
(click)="onTransferClick()">
Transfer
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {filter, finalize, takeUntil} from 'rxjs/operators';
import {UiContractOffer} from '@sovity.de/edc-client';
import {MailtoLinkBuilder} from 'src/app/core/services/mailto-link-builder';
import {EdcApiService} from '../../../core/services/api/edc-api.service';
import {ConnectorLimitsService} from '../../../core/services/connector-limits.service';
import {ContractNegotiationService} from '../../../core/services/contract-negotiation.service';
import {UiAssetMapped} from '../../../core/services/models/ui-asset-mapped';
import {NotificationService} from '../../../core/services/notification.service';
Expand Down Expand Up @@ -44,6 +45,8 @@ export class AssetDetailDialogComponent implements OnDestroy {
asset!: UiAssetMapped;
propGroups!: PropertyGridGroup[];

limitsExceeded: boolean | null = null;

loading = false;

get isProgressBarVisible(): boolean {
Expand Down Expand Up @@ -78,6 +81,7 @@ export class AssetDetailDialogComponent implements OnDestroy {
constructor(
private edcApiService: EdcApiService,
private notificationService: NotificationService,
private connectorLimitsService: ConnectorLimitsService,
private matDialog: MatDialog,
private matDialogRef: MatDialogRef<AssetDetailDialogComponent>,
@Inject(MAT_DIALOG_DATA)
Expand All @@ -99,6 +103,14 @@ export class AssetDetailDialogComponent implements OnDestroy {
this.data = data;
this.asset = this.data.asset;
this.propGroups = this.data.propertyGridGroups;

if (this.limitsExceeded == null && this.data.type === 'data-offer') {
this.connectorLimitsService
.isConsumingAgreementLimitExceeded()
.subscribe((limitsExceeded) => {
this.limitsExceeded = limitsExceeded;
});
}
}

onContactClick() {
Expand Down Expand Up @@ -132,10 +144,22 @@ export class AssetDetailDialogComponent implements OnDestroy {
}

onNegotiateClick(contractOffer: UiContractOffer) {
this.contractNegotiationService.negotiate(
this.data.dataOffer!,
contractOffer,
);
this.connectorLimitsService
.isConsumingAgreementLimitExceeded()
.subscribe((limitExceeded) => {
if (!limitExceeded) {
this.limitsExceeded = false;
this.contractNegotiationService.negotiate(
this.data.dataOffer!,
contractOffer,
);
} else {
this.limitsExceeded = true;
this.notificationService.showError(
'Cannot negotiate. Maximum number of active consuming contracts reached.',
);
}
});
}

onTransferClick() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,9 @@ export class AssetPropertyGridGroupBuilder {

if (contractAgreement.isConsumingLimitsEnforced) {
properties.push({
icon: contractAgreement.canTransfer ? 'sync' : 'sync_disabled',
icon: contractAgreement.isTerminated ? 'sync_disabled' : 'sync',
label: 'Status',
tooltip: contractAgreement.statusTooltipText,
textIconAfter: contractAgreement.statusTooltipText ? 'help' : null,
text: contractAgreement.statusText,
additionalClasses: contractAgreement.canTransfer ? '' : 'text-warn',
additionalClasses: contractAgreement.isTerminated ? 'text-warn' : '',
});
}

Expand Down
31 changes: 31 additions & 0 deletions src/app/core/services/connector-limits.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {Injectable} from '@angular/core';
import {Observable, of} from 'rxjs';
import {map} from 'rxjs/operators';
import {ConnectorLimits} from '@sovity.de/edc-client';
import {ActiveFeatureSet} from '../config/active-feature-set';
import {EdcApiService} from './api/edc-api.service';

@Injectable({
providedIn: 'root',
})
export class ConnectorLimitsService {
constructor(
private edcApiService: EdcApiService,
private activeFeatureSet: ActiveFeatureSet,
) {}

isConsumingAgreementLimitExceeded(): Observable<boolean> {
return this.activeFeatureSet.hasConnectorLimits()
? this.edcApiService
.getEnterpriseEditionConnectorLimits()
.pipe(map(this.limitsExceeded))
: of(false);
}

private limitsExceeded = (limits: ConnectorLimits) => {
const max = limits.maxActiveConsumingContractAgreements;
const current = limits.numActiveConsumingContractAgreements;

return max != null && current >= max;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ export class ContractAgreementCardMappedService {
),
isConsumingLimitsEnforced: false,
isTerminated: isTerminated,
showStatus: isTerminated,
statusText: isTerminated ? 'Terminated' : '',
statusTooltipText: '',
canTransfer: !isTerminated,
searchTargets: [
contractAgreement.contractAgreementId,
contractAgreement.counterPartyId,
Expand All @@ -53,8 +49,6 @@ export class ContractAgreementCardMappedService {
maxConsumingContracts: number,
agreements: ContractAgreementCardMapped[],
): ContractAgreementCardMapped[] {
let activeContractCounter = 0;

return agreements.map((it) => {
if (it.isTerminated) {
return it;
Expand All @@ -63,30 +57,8 @@ export class ContractAgreementCardMappedService {
const modifiedAgreement = {
...it,
isConsumingLimitsEnforced: true,
showStatus: true,
statusText:
activeContractCounter < maxConsumingContracts ? 'Active' : 'Inactive',
statusTooltipText: this.getConsumingContractsInfoText(
activeContractCounter,
maxConsumingContracts,
),
canTransfer: activeContractCounter < maxConsumingContracts,
};
activeContractCounter++;
return modifiedAgreement;
});
}

private getConsumingContractsInfoText(
index: number,
maxConsumingContracts: number,
): string {
if (index >= maxConsumingContracts) {
return `This connector is licensed for a maximum number of ${maxConsumingContracts} consuming contract${
maxConsumingContracts == 1 ? '' : 's'
}. When negotiating new contracts, older contracts will be deactivated.`;
} else {
return '';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,5 @@ export type ContractAgreementCardMapped = Omit<
isInProgress: boolean;
isConsumingLimitsEnforced: boolean;
isTerminated: boolean;
showStatus: boolean;
statusText: string;
statusTooltipText: string;
canTransfer: boolean;
searchTargets: (string | null)[];
};
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,12 @@
</div>
</div>
<!-- Status -->
<div
*ngIf="card.showStatus"
class="flex flex-col"
[matTooltip]="card.statusTooltipText">
<div class="flex flex-col">
<div class="text-slate text-sm uppercase tracking-wider text-right">
Status
</div>
<div class="text-right" [class.text-warn]="!card.canTransfer">
{{ card.statusText }}
<mat-icon *ngIf="card.statusTooltipText" class="mat-icon-[12px]">
help
</mat-icon>
<div class="text-right" [class.text-warn]="card.isTerminated">
{{ card.isTerminated ? 'Terminated' : 'Active' }}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,6 @@ export class ContractAgreementPageComponent implements OnInit, OnDestroy {
map(([oldCard, newCard]) => ({
...newCard,
isConsumingLimitsEnforced: oldCard.isConsumingLimitsEnforced,
statusText: oldCard.statusText,
showStatus: oldCard.showStatus,
canTransfer: oldCard.canTransfer,
statusTooltipText: oldCard.statusTooltipText,
})),
);

Expand Down

0 comments on commit 9ab4084

Please sign in to comment.