</ng-template>
<ng-template #dialogContent>
<div class="modal-header bg-info">
- <h3 class="modal-title" i18n>Fund Details - {{fund?.name()}} ({{fund?.code()}} {{fund?.year()}})</h3>
+ <h3 class="modal-title" i18n>Fund Details - {{fund?.name()}} ({{fund?.code()}} ({{fund?.year()}}) ({{fund?.org().shortname()}}))</h3>
<button type="button" class="close"
i18n-aria-label aria-label="Close" (click)="close()">
<span aria-hidden="true">×</span>
</div>
<div class="modal-body">
<div class="row mt-3">
- <div class="col-lg-12 text-right pb-1">
- <button class="btn btn-secondary btn-sm" [disabled]="activeTab == defaultTabType"
+ <div class="col-lg-3">
+ <button class="btn btn-primary"
+ (click)="allocateToFund()" i18n>Create Allocation</button>
+ <button class="btn btn-primary ml-1"
+ (click)="doTransfer()" i18n>Transfer Money</button>
+ </div>
+ <div class="col-lg-9 text-right pb-1">
+ <button class="btn btn-secondary btn-xs" [disabled]="activeTab == defaultTabType"
(click)="setDefaultTab()" i18n>Set Default View</button>
</div>
</div>
[preloadLinkedValues]="true"
[readonlyFields]="readonlyFields">
</eg-fm-record-editor>
+
+<eg-fm-record-editor #allocateToFundDialog idlClass="acqfa">
+</eg-fm-record-editor>
+
+<eg-fund-transfer-dialog #transferDialog></eg-fund-transfer-dialog>
import {StringComponent} from '@eg/share/string/string.component';
import {ToastService} from '@eg/share/toast/toast.service';
import {FundTagsComponent} from './fund-tags.component';
+import {FundTransferDialogComponent} from './fund-transfer-dialog.component';
@Component({
selector: 'eg-fund-details-dialog',
acqfdebDataSource: GridDataSource
@ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
+ @ViewChild('transferDialog', { static: false }) transferDialog: FundTransferDialogComponent;
+ @ViewChild('allocateToFundDialog', { static: true }) allocateToFundDialog: FmRecordEditorComponent;
@ViewChild('successString', { static: true }) successString: StringComponent;
@ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent;
);
}
+ allocateToFund() {
+ const allocation = this.idl.create('acqfa');
+ allocation.fund(this.fundId);
+ allocation.allocator(this.auth.user().id());
+ this.allocateToFundDialog.defaultNewRecord = allocation;
+ this.allocateToFundDialog.mode = 'create';
+
+ this.allocateToFundDialog.hiddenFieldsList = ['id', 'fund', 'allocator', 'create_time'];
+ this.allocateToFundDialog.fieldOrder = 'funding_source,amount,note';
+ this.allocateToFundDialog.open().subscribe(
+ result => {
+ this.successString.current()
+ .then(str => this.toast.success(str));
+ this._initRecord();
+ },
+ error => {
+ this.updateFailedString.current()
+ .then(str => this.toast.danger(str));
+ }
+ );
+ }
+
+ doTransfer() {
+ this.transferDialog.sourceFund = this.fund;
+ this.transferDialog.open().subscribe(
+ ok => this._initRecord()
+ )
+ }
+
setDefaultTab() {
this.defaultTabType = this.activeTab;
this.store.setLocalItem('eg.acq.fund_details.default_tab', this.activeTab);
--- /dev/null
+<eg-string #successString i18n-text text="Fund Transfer Succeeded"></eg-string>
+<eg-string #updateFailedString i18n-text text="Fund Transfer Failed"></eg-string>
+
+<ng-template #dialogContent>
+ <div class="modal-header bg-info" *ngIf="doneLoading">
+ <h3 class="modal-title" i18n>Transfer from Fund {{sourceFund?.name()}} ({{sourceFund?.code()}} ({{sourceFund?.year()}}) ({{sourceFund?.org().shortname()}}))</h3>
+ <button type="button" class="close"
+ i18n-aria-label aria-label="Close" (click)="close()">
+ <span aria-hidden="true">×</span>
+ </button>
+ </div>
+ <div class="modal-body" [hidden]="!doneLoading">
+ <form #xfrForm="ngForm" role="form" class="form-validated">
+ <div class="form-group row mt-2">
+ <label for="dest-fund" class="col-sm-4 col-form-label" i18n>Destination Fund</label>
+ <div class="col-sm-8">
+ <eg-combobox #fundSelector [asyncSupportsEmptyTermClick]="true"
+ name="dest_fund" id="dest-fund"
+ [(ngModel)]="destFund" [asyncDataSource]="fundDataSource"
+ i18n-placeholder placeholder="Select fund..."></eg-combobox>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label for="source_amount" class="col-sm-4 col-form-label" i18n>Source Amount</label>
+ <div class="col-sm-8">
+ <input class="form-control" type="number" name="source_amount" id="source_amount" [(ngModel)]="sourceAmount">
+ </div>
+ </div>
+ <div class="form-group row">
+ <div class="col-sm-4"></div>
+ <div class="col-sm-8" i18n>
+ <i>Amount to transfer from {{sourceFund?.name()}} ({{sourceFund?.code()}} ({{sourceFund?.year()}}) ({{sourceFund?.org().shortname()}}))</i>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label for="note" class="col-sm-4 col-form-label" i18n>Note</label>
+ <div class="col-sm-8">
+ <input class="form-control" type="text" name="note" id="note" [(ngModel)]="note">
+ </div>
+ </div>
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-info"
+ [disabled]="!destFund || (sourceAmount <= 0)"
+ (click)="transfer()" i18n>Transfer</button>
+ <button type="button" class="btn btn-warning"
+ (click)="close()" i18n>Close</button>
+ </div>
+</ng-template>
--- /dev/null
+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';
+import {ComboboxComponent} from '@eg/share/combobox/combobox.component';
+import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {Observable} from 'rxjs';
+import {map} from 'rxjs/operators';
+
+@Component({
+ selector: 'eg-fund-transfer-dialog',
+ templateUrl: './fund-transfer-dialog.component.html'
+})
+
+export class FundTransferDialogComponent
+ extends DialogComponent implements OnInit {
+
+ @Input() sourceFund: IdlObject;
+ doneLoading: boolean = false;
+
+ @ViewChild('successString', { static: true }) successString: StringComponent;
+ @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent;
+ @ViewChild('fundSelector', { static: false }) tagSelector: ComboboxComponent;
+
+ fundDataSource: (term: string) => Observable<ComboboxEntry>;
+ destFund: ComboboxEntry = null;
+ sourceAmount: number = 0.0;
+ note = null;
+
+ 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.destFund = null;
+ this.onOpen$.subscribe(() => this._initRecord());
+ this.fundDataSource = term => {
+ const field = 'code';
+ const args = {};
+ const extra_args = { order_by : {} };
+ args[field] = {'ilike': `%${term}%`}; // could -or search on label
+ args['active'] = 't';
+ extra_args['order_by']['acqf'] = field;
+ extra_args['limit'] = 100;
+ extra_args['flesh'] = 1;
+ const flesh_fields: Object = {};
+ flesh_fields['acqf'] = ['org'];
+ extra_args['flesh_fields'] = flesh_fields;
+ return this.pcrud.search('acqf', args, extra_args).pipe(map(data => {
+ return {
+ id: data.id(),
+ label: data.code()
+ + ' (' + data.year() + ')'
+ + ' (' + data.org().shortname() + ')',
+ fm: data
+ };
+ }));
+ };
+ }
+
+ private _initRecord() {
+ this.doneLoading = false;
+ this.destFund = null;
+ this.sourceAmount = 0;
+ this.note = null;
+ this.doneLoading = true;
+ }
+
+ transfer() {
+ this.net.request(
+ 'open-ils.acq',
+ 'open-ils.acq.funds.transfer_money',
+ this.auth.token(),
+ this.sourceFund.id(),
+ this.sourceAmount,
+ this.destFund.id,
+ null,
+ this.note
+ ).subscribe(
+ res => {
+ this.successString.current()
+ .then(str => this.toast.success(str));
+ this.close(true);
+ },
+ res => {
+ this.updateFailedString.current()
+ .then(str => this.toast.danger(str));
+ this.close(false);
+ }
+ )
+ }
+
+}
import {FundingSourcesComponent} from './funding-sources.component';
import {FundingSourceTransactionsDialogComponent} from './funding-source-transactions-dialog.component';
import {FundTagsComponent} from './fund-tags.component';
+import {FundTransferDialogComponent} from './fund-transfer-dialog.component';
@NgModule({
declarations: [
FundDetailsDialogComponent,
FundingSourcesComponent,
FundingSourceTransactionsDialogComponent,
- FundTagsComponent
+ FundTagsComponent,
+ FundTransferDialogComponent
],
imports: [
StaffCommonModule,