From 142a4e97c99ef6eb50137b451aa12c4ab2538723 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Sat, 27 Mar 2021 14:45:12 -0400 Subject: [PATCH] currencies: finish up Signed-off-by: Galen Charlton --- .../admin/acq/currency/currencies.component.html | 18 ++- .../admin/acq/currency/currencies.component.ts | 48 ++++++- .../staff/admin/acq/currency/currencies.module.ts | 4 +- .../currency/exchange-rates-dialog.component.html | 49 ++++++++ .../currency/exchange-rates-dialog.component.ts | 138 +++++++++++++++++++++ 5 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.ts diff --git a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.html b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.html index f585cc8920..efef63c3c5 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.html @@ -58,12 +58,15 @@ - + - + + + + @@ -74,3 +77,14 @@ [preloadLinkedValues]="true" [readonlyFields]="readonlyFields"> + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.ts index 1b1c056293..72d3e4e67c 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.component.ts @@ -14,6 +14,10 @@ import {PermService} from '@eg/core/perm.service'; import {AuthService} from '@eg/core/auth.service'; import {NetService} from '@eg/core/net.service'; import {StringComponent} from '@eg/share/string/string.component'; +import {ExchangeRatesDialogComponent} from './exchange-rates-dialog.component'; +import {Observable, forkJoin, of} from 'rxjs'; +import {AlertDialogComponent} from '@eg/share/dialog/alert.component'; +import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; @Component({ templateUrl: './currencies.component.html' @@ -24,6 +28,9 @@ export class CurrenciesComponent extends AdminPageComponent implements OnInit { classLabel: string; @ViewChild('grid', { static: true }) grid: GridComponent; + @ViewChild('exchangeRatesDialog', { static: false }) exchangeRatesDialog: ExchangeRatesDialogComponent; + @ViewChild('alertDialog', {static: false}) private alertDialog: AlertDialogComponent; + @ViewChild('confirmDel', { static: true }) confirmDel: ConfirmDialogComponent; cellTextGenerator: GridCellTextGenerator; @@ -45,7 +52,7 @@ export class CurrenciesComponent extends AdminPageComponent implements OnInit { ngOnInit() { this.cellTextGenerator = { - name: row => row.name() + exchange_rates: row => '' }; this.fieldOrder = 'code,name'; this.defaultNewRecord = this.idl.create('acqct'); @@ -100,4 +107,43 @@ export class CurrenciesComponent extends AdminPageComponent implements OnInit { this.includeOrgDescendants = true; } + openExchangeRatesDialog(code: string) { + this.exchangeRatesDialog.currencyCode = code; + this.exchangeRatesDialog.open({size: 'lg'}); + } + + deleteIfPossible(rows: IdlObject[]) { + if (rows.length > 0) { + const code = rows[0].code(); + let can: boolean = true; + forkJoin([ + this.pcrud.search('acqexr', { from_currency: code }, { limit: 1 }, { atomic: true }), + this.pcrud.search('acqexr', { to_currency: code }, { limit: 1 }, { atomic: true }), + this.pcrud.search('acqf', { currency_type: code }, { limit: 1 }, { atomic: true }), + this.pcrud.search('acqpro', { currency_type: code }, { limit: 1 }, { atomic: true }), + this.pcrud.search('acqfdeb', { origin_currency_type: code }, { limit: 1 }, { atomic: true }), + this.pcrud.search('acqfs', { currency_type: code }, { limit: 1 }, { atomic: true }), + ]).subscribe( + results => { + results.forEach((res) => { + if (res.length > 0) { + can = false; + } + }); + }, + err => {}, + () => { + if (can) { + this.confirmDel.open().subscribe(confirmed => { + if (!confirmed) { return; } + super.deleteSelected([ rows[0] ]); + }); + } else { + this.alertDialog.open(); + } + } + ); + } + } + } diff --git a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.module.ts index 54cd1ce654..9b4f2582e2 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/currencies.module.ts @@ -3,10 +3,12 @@ import {StaffCommonModule} from '@eg/staff/common.module'; import {AdminCommonModule} from '@eg/staff/admin/common.module'; import {CurrenciesRoutingModule} from './routing.module'; import {CurrenciesComponent} from './currencies.component'; +import {ExchangeRatesDialogComponent} from './exchange-rates-dialog.component'; @NgModule({ declarations: [ - CurrenciesComponent + CurrenciesComponent, + ExchangeRatesDialogComponent ], imports: [ StaffCommonModule, diff --git a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.html new file mode 100644 index 0000000000..1459072eb6 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.html @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.ts new file mode 100644 index 0000000000..2b5c77c1a7 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/acq/currency/exchange-rates-dialog.component.ts @@ -0,0 +1,138 @@ +import {Component, Input, ViewChild, TemplateRef, OnInit} from '@angular/core'; +import {DialogComponent} from '@eg/share/dialog/dialog.component'; +import {NgForm} from '@angular/forms'; +import {IdlService, IdlObject} from '@eg/core/idl.service'; +import {EventService} from '@eg/core/event.service'; +import {NetService} from '@eg/core/net.service'; +import {AuthService} from '@eg/core/auth.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {Pager} from '@eg/share/util/pager'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {StringComponent} from '@eg/share/string/string.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {PermService} from '@eg/core/perm.service'; + +@Component({ + selector: 'eg-exchange-rates-dialog', + templateUrl: './exchange-rates-dialog.component.html' +}) + +export class ExchangeRatesDialogComponent + extends DialogComponent implements OnInit { + + @Input() currencyCode: string; + currency: IdlObject; + otherCurrencies: IdlObject[]; + existingRatios: {[toCurrency: string]: IdlObject} = {} + existingInverseRatios: {[fromCurrency: string]: IdlObject} = {} + ratios: IdlObject[]; + idlDef: any; + fieldOrder: any; + canUpdate: boolean = false; + doneLoading: boolean = false; + + @ViewChild('successString', { static: true }) successString: StringComponent; + @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent; + + constructor( + private idl: IdlService, + private evt: EventService, + private net: NetService, + private auth: AuthService, + private pcrud: PcrudService, + private perm: PermService, + private toast: ToastService, + private modal: NgbModal + ) { + super(modal); + } + + ngOnInit() { + this.currency = null; + this.onOpen$.subscribe(() => this._initRecord()); + this.idlDef = this.idl.classes['acqct']; + this.perm.hasWorkPermAt(['ADMIN_CURRENCY_TYPE'], true).then((perm) => { + if (perm['ADMIN_CURRENCY_TYPE'].length > 0) { + this.canUpdate = true; + } + }); + } + + private _initRecord() { + this.doneLoading = false; + this.ratios = []; + this.otherCurrencies = []; + this.existingRatios = {}; + this.existingInverseRatios = {}; + this.pcrud.retrieve('acqct', this.currencyCode, {} + ).subscribe(res => this.currency = res); + this.pcrud.search('acqexr', { from_currency: this.currencyCode }, { + flesh: 1, + flesh_fields: {'acqexr': ['to_currency']}, + }, {}).subscribe( + exr => this.existingRatios[exr.to_currency().code()] = exr, + err => {}, + () => this.pcrud.search('acqexr', { to_currency: this.currencyCode }, { + flesh: 1, + flesh_fields: {'acqexr': ['from_currency']}, + }, {}).subscribe( + exr => this.existingInverseRatios[exr.from_currency().code()] = exr, + err => {}, + () => this.pcrud.search('acqct', { code: { '!=': this.currencyCode } }, + { order_by: 'code ASC' }, { atomic: true }) + .subscribe( + currs => this.otherCurrencies = currs, + err => {}, + () => { this._mergeCurrenciesAndRates(); this.doneLoading = true; } + ) + ) + ); + } + + private _mergeCurrenciesAndRates() { + this.ratios = []; + this.otherCurrencies.forEach(curr => { + if (curr.code() in this.existingRatios) { + this.ratios.push(this.existingRatios[curr.code()]); + } else if (curr.code() in this.existingInverseRatios) { + const ratio = this.idl.clone(this.existingInverseRatios[curr.code()]); + // mark it as an inverse ratio that should not be directly edited + ratio.id(-1); + const toCur = ratio.to_currency(); + ratio.to_currency(ratio.from_currency()); + ratio.from_currency(toCur); + ratio.ratio(1.0/ratio.ratio()); + this.ratios.push(ratio); + } else { + const ratio = this.idl.create('acqexr'); + ratio.from_currency(this.currencyCode); + ratio.to_currency(curr); + this.ratios.push(ratio); + } + }); + } + + save() { + const updateBatch: IdlObject[] = []; + this.ratios.forEach(ratio => { + if (ratio.id() === -1) { + // ignore inverse entries + } else if (ratio.id() === undefined && ratio.ratio() !== undefined && ratio.ratio() !== null) { + // completely new entry + ratio.isnew(true); + updateBatch.push(ratio); + } else if (ratio.id() !== undefined && ratio.ratio() !== undefined && ratio.ratio() !== null) { + // entry that might have been updated + ratio.ischanged(true); + updateBatch.push(ratio); + } else if (ratio.id() !== undefined && (ratio.ratio() === undefined || ratio.ratio() === null)) { + // existing entry to delete + ratio.isdeleted(true); + updateBatch.push(ratio); + } + }); + this.pcrud.autoApply(updateBatch).toPromise().then(res => this.close(res)); + } + +} -- 2.11.0