Merge pull request #2526 from alberto-art3ch/enhancement/manual_journal_entry_with_asset_external_owner

WEB-220: Extend Manual Journal entry to support Asset Externalization
This commit is contained in:
Felix van Hove
2025-07-08 17:03:51 +02:00
committed by GitHub
22 changed files with 114 additions and 19 deletions
@@ -62,6 +62,7 @@ import { ProvisioningJournalEntriesResolver } from './provisioning-entries/view-
import { ViewJournalEntryTransactionComponent } from 'app/shared/accounting/view-journal-entry-transaction/view-journal-entry-transaction.component';
import { JournalEntryTransactionResolver } from './common-resolvers/journal-entry-transaction.resolver';
import { ExternalAssetOwnerJournalEntryResolver } from 'app/loans/common-resolvers/external-asset-owner-journal-entry.resolver';
import { ExternalAssetConfigurationResolver } from './common-resolvers/external-asset-configuration.resolver';
/** Accounting Routes */
const routes: Routes = [
@@ -105,7 +106,8 @@ const routes: Routes = [
offices: OfficesResolver,
currencies: CurrenciesResolver,
paymentTypes: PaymentTypesResolver,
glAccounts: GlAccountsResolver
glAccounts: GlAccountsResolver,
globalConfig: ExternalAssetConfigurationResolver
}
},
{
@@ -419,7 +421,8 @@ const routes: Routes = [
ProvisioningEntryEntriesResolver,
LoanProductsResolver,
ProvisioningCategoriesResolver,
ProvisioningJournalEntriesResolver
ProvisioningJournalEntriesResolver,
ExternalAssetConfigurationResolver
]
})
export class AccountingRoutingModule {}
@@ -0,0 +1,27 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { SystemService } from 'app/system/system.service';
/**
* Offices data resolver.
*/
@Injectable()
export class ExternalAssetConfigurationResolver {
/**
* @param {AccountingService} accountingService Accounting service.
*/
constructor(private systemService: SystemService) {}
/**
* Returns the offices data.
* @returns {Observable<any>}
*/
resolve(): Observable<any> {
return this.systemService.getConfigurationByName(SystemService.CONFIG_ASSET_EXTERNALIZATION);
}
}
@@ -16,7 +16,7 @@
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48">
<mat-form-field class="flex-24">
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
<mat-select required formControlName="currencyCode">
<mat-option *ngFor="let currency of currencyData" [value]="currency.code">
@@ -29,6 +29,11 @@
</mat-error>
</mat-form-field>
<mat-form-field class="flex-24" *ngIf="assetExternalizationEnabled">
<mat-label>{{ 'labels.inputs.External Asset Owner' | translate }}</mat-label>
<input matInput formControlName="externalAssetOwner" />
</mat-form-field>
<div
class="flex-fill layout-row-wrap responsive-column"
formArrayName="debits"
@@ -1,13 +1,7 @@
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import {
UntypedFormGroup,
UntypedFormBuilder,
Validators,
UntypedFormArray,
ReactiveFormsModule
} from '@angular/forms';
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormArray, UntypedFormControl } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
/** Custom Services */
@@ -54,6 +48,9 @@ export class CreateJournalEntryComponent implements OnInit, AfterViewInit {
paymentTypeData: any;
/** Gl Account data. */
glAccountData: any;
/** Asset Externalization */
assetExternalizationConfig: any;
assetExternalizationEnabled = false;
/* Reference of create journal form */
@ViewChild('createJournalFormRef') createJournalFormRef: ElementRef<any>;
@@ -81,12 +78,16 @@ export class CreateJournalEntryComponent implements OnInit, AfterViewInit {
private configurationWizardService: ConfigurationWizardService,
private popoverService: PopoverService
) {
this.route.data.subscribe((data: { offices: any; currencies: any; paymentTypes: any; glAccounts: any }) => {
this.officeData = data.offices;
this.currencyData = data.currencies.selectedCurrencyOptions;
this.paymentTypeData = data.paymentTypes;
this.glAccountData = data.glAccounts;
});
this.assetExternalizationEnabled = false;
this.route.data.subscribe(
(data: { offices: any; currencies: any; paymentTypes: any; glAccounts: any; globalConfig: any }) => {
this.officeData = data.offices;
this.currencyData = data.currencies.selectedCurrencyOptions;
this.paymentTypeData = data.paymentTypes;
this.glAccountData = data.glAccounts;
this.assetExternalizationConfig = data.globalConfig;
}
);
}
/**
@@ -192,6 +193,9 @@ export class CreateJournalEntryComponent implements OnInit, AfterViewInit {
this.settingsService.dateFormat
);
}
if (!journalEntry['externalAssetOwner']) {
delete journalEntry['externalAssetOwner'];
}
this.accountingService.createJournalEntry(journalEntry).subscribe((response) => {
this.router.navigate(
[
@@ -228,6 +232,10 @@ export class CreateJournalEntryComponent implements OnInit, AfterViewInit {
this.showPopover(this.templateCreateJournalFormRef, this.createJournalFormRef.nativeElement, 'top', true);
});
}
this.assetExternalizationEnabled = this.assetExternalizationConfig.enabled;
if (this.assetExternalizationEnabled) {
this.journalEntryForm.addControl('externalAssetOwner', new UntypedFormControl());
}
}
/**
@@ -15,7 +15,7 @@
</div>
<div class="container m-b-20" *ngIf="isViewTransaction()">
<mat-card class="mat-elevation-z8" *ngIf="dataSource">
<mat-card class="mat-elevation-z8" ngClass="{{ journalEntryColor() }}" *ngIf="dataSource">
<mat-card-content>
<div class="layout-row-wrap">
<div class="flex-25 header">
@@ -49,6 +49,22 @@
<div class="flex-25">
{{ dataSource.data[0].submittedOnDate | datetimeFormat }}
</div>
<div class="flex-25 header">
{{ 'labels.inputs.Manual Journal Entry' | translate }}
</div>
<div class="flex-25">
{{ dataSource.data[0].manualEntry | yesNo }}
</div>
<div class="flex-25 header" *ngIf="dataSource.data[0].externalAssetOwner">
{{ 'labels.inputs.External Asset Owner' | translate }}
</div>
<div class="flex-25" *ngIf="dataSource.data[0].externalAssetOwner">
{{ dataSource.data[0].externalAssetOwner }}
</div>
</div>
</mat-card-content>
</mat-card>
@@ -1,3 +1,6 @@
@use 'assets/styles/helper';
@use 'assets/styles/colours' as *;
table {
width: 100%;
@@ -5,3 +8,7 @@ table {
cursor: pointer;
}
}
.manual-entry {
background-color: $manual-entry;
}
@@ -25,6 +25,7 @@ import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { DatetimeFormatPipe } from '../../../pipes/datetime-format.pipe';
import { FormatNumberPipe } from '../../../pipes/format-number.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { YesnoPipe } from '@pipes/yesno.pipe';
@Component({
selector: 'mifosx-view-journal-entry-transaction',
@@ -47,7 +48,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatRow,
DateFormatPipe,
DatetimeFormatPipe,
FormatNumberPipe
FormatNumberPipe,
YesnoPipe
]
})
export class ViewJournalEntryTransactionComponent implements OnInit {
@@ -76,6 +78,8 @@ export class ViewJournalEntryTransactionComponent implements OnInit {
isJournalEntryLoaded = false;
isManualJournalEntry = false;
/**
* @param {AccountingService} accountingService Accounting Service.
* @param {ActivatedRoute} route Activated Route.
@@ -102,6 +106,7 @@ export class ViewJournalEntryTransactionComponent implements OnInit {
if (data.transaction.pageItems.length > 0) {
this.isJournalEntryLoaded = true;
this.transactionId = data.transaction.pageItems[0].transactionId;
this.isManualJournalEntry = data.transaction.pageItems[0].manualEntry;
}
} else if (this.isViewTransfer()) {
this.journalEntriesData = data.transferJournalEntryData.journalEntryData.content;
@@ -185,4 +190,11 @@ export class ViewJournalEntryTransactionComponent implements OnInit {
goBack(): void {
this.location.back();
}
journalEntryColor(): string {
if (this.isManualJournalEntry) {
return 'manual-entry';
}
return '';
}
}
+2
View File
@@ -13,6 +13,8 @@ import { RunJobWithParamPayloadType } from './manage-jobs/scheduler-jobs/custom-
providedIn: 'root'
})
export class SystemService {
public static CONFIG_ASSET_EXTERNALIZATION = 'asset-externalization-of-non-active-loans';
emptyPayload: any = {};
/**
+2
View File
@@ -84,6 +84,8 @@ $subStatus-contract-termination: #b3b3b3;
$error-log: #ffa726;
$manual-entry: #d7e3ff;
.column-mandatory {
color: $status-active;
text-align: center;
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Povinné",
"Mandatory Guarantee(%)": "Povinná záruka (%)",
"Manual Entries Allowed": "Ruční vkládání povoleno",
"Manual Journal Entry": "Ruční zápis do deníku",
"Mapper Key": "Mapper Key",
"Mapper Value": "Hodnota mapovače",
"Mapping id": "ID mapování",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Obligatorisch",
"Mandatory Guarantee(%)": "Obligatorische Garantie (%)",
"Manual Entries Allowed": "Manuelle Eingaben erlaubt",
"Manual Journal Entry": "Manuelle Journalbuchung",
"Mapper Key": "Mapper-Schlüssel",
"Mapper Value": "Mapper-Wert",
"Mapping id": "Zuordnungs-ID",
+1
View File
@@ -1889,6 +1889,7 @@
"Mandatory": "Mandatory",
"Mandatory Guarantee(%)": "Mandatory Guarantee(%)",
"Manual Entries Allowed": "Manual Entries Allowed",
"Manual Journal Entry": "Manual Journal Entry",
"Mapper Key": "Mapper Key",
"Mapper Value": "Mapper Value",
"Mapping id": "Mapping id",
+1
View File
@@ -1883,6 +1883,7 @@
"Mandatory": "Obligatorio",
"Mandatory Guarantee(%)": "Garantía obligatoria(%)",
"Manual Entries Allowed": "Permitir Entradas manuales",
"Manual Journal Entry": "Entrada de diario manual",
"Mapper Key": "Clave del asignador",
"Mapper Value": "Valor del asignador",
"Mapping id": "Identificación de mapeo",
+1
View File
@@ -1883,6 +1883,7 @@
"Mandatory": "Obligatorio",
"Mandatory Guarantee(%)": "Garantía obligatoria(%)",
"Manual Entries Allowed": "Permitir Entradas manuales",
"Manual Journal Entry": "Entrada de diario manual",
"Mapper Key": "Clave del asignador",
"Mapper Value": "Valor del asignador",
"Mapping id": "Identificación de mapeo",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Obligatoire",
"Mandatory Guarantee(%)": "Garantie obligatoire (%)",
"Manual Entries Allowed": "Entrées manuelles autorisées",
"Manual Journal Entry": "Écriture de journal manuelle",
"Mapper Key": "Clé du mappeur",
"Mapper Value": "Valeur du mappeur",
"Mapping id": "Identifiant de mappage",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Obbligatorio",
"Mandatory Guarantee(%)": "Garanzia Obbligatoria(%)",
"Manual Entries Allowed": "Inserimenti manuali consentiti",
"Manual Journal Entry": "Registrazione manuale del giornale",
"Mapper Key": "Chiave del mappatore",
"Mapper Value": "Valore del mappatore",
"Mapping id": "ID mappatura",
+1
View File
@@ -1885,6 +1885,7 @@
"Mandatory": "필수적인",
"Mandatory Guarantee(%)": "의무보증(%)",
"Manual Entries Allowed": "수동 입력이 허용됨",
"Manual Journal Entry": "수동 저널 입력",
"Mapper Key": "매퍼 키",
"Mapper Value": "매퍼 값",
"Mapping id": "매핑 ID",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Privaloma",
"Mandatory Guarantee(%)": "Privaloma garantija (%)",
"Manual Entries Allowed": "Leidžiami rankiniai įvedimai",
"Manual Journal Entry": "Rankinis žurnalo įrašas",
"Mapper Key": "Žemėlapio kūrėjo raktas",
"Mapper Value": "Žemėlapio vertė",
"Mapping id": "Atvaizdavimo ID",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Obligāts",
"Mandatory Guarantee(%)": "Obligātā garantija (%)",
"Manual Entries Allowed": "Manuālas ievades ir atļautas",
"Manual Journal Entry": "Manuālais žurnāla ieraksts",
"Mapper Key": "Mapper Key",
"Mapper Value": "Kartētāja vērtība",
"Mapping id": "Kartēšanas ID",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "अनिवार्य",
"Mandatory Guarantee(%)": "अनिवार्य ग्यारेन्टी (%)",
"Manual Entries Allowed": "म्यानुअल प्रविष्टिहरूलाई अनुमति दिइएको छ",
"Manual Journal Entry": "म्यानुअल जर्नल प्रविष्टि",
"Mapper Key": "म्यापर कुञ्जी",
"Mapper Value": "म्यापर मान",
"Mapping id": "म्यापिङ आईडी",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Obrigatório",
"Mandatory Guarantee(%)": "Garantia Obrigatória(%)",
"Manual Entries Allowed": "Entradas manuais permitidas",
"Manual Journal Entry": "Lançamento Manual de Diário",
"Mapper Key": "Chave do mapeador",
"Mapper Value": "Valor do mapeador",
"Mapping id": "ID de mapeamento",
+1
View File
@@ -1884,6 +1884,7 @@
"Mandatory": "Lazima",
"Mandatory Guarantee(%)": "Dhamana ya Lazima(%)",
"Manual Entries Allowed": "Maingizo Mwongozo Yanaruhusiwa",
"Manual Journal Entry": "Kuingia kwa Jarida kwa Mwongozo",
"Mapper Key": "Ufunguo wa ramani",
"Mapper Value": "Thamani ya ramani",
"Mapping id": "Kitambulisho cha ramani",