cloud-ide-fees 0.0.22 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/cloud-ide-fees.mjs +792 -169
- package/fesm2022/cloud-ide-fees.mjs.map +1 -1
- package/index.d.ts +46 -0
- package/package.json +1 -1
|
@@ -2,17 +2,16 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { Component, inject, Injectable, DestroyRef, viewChild, signal, computed, input, ChangeDetectorRef, ViewChild, output } from '@angular/core';
|
|
3
3
|
import { authGuard } from 'cloud-ide-auth';
|
|
4
4
|
import { HttpClient } from '@angular/common/http';
|
|
5
|
-
import { generateStringFromObject, cidePath, hostManagerRoutesUrl, feesRoutesUrl, MFeeStructure, generateObjectFromString, AcaClassPrgBranchListPayload, academicsRoutesUrl, MPrgTrmSection, FeeStructureSaveUpdatePayload, MFeePayment, MFeePaymentInsertUpdatePayload, MFeeReceiptTemplateInsertUpdatePayload, MFeeReceiptTemplate, MFeeReceiptTemplateGetByIdPayload } from 'cloud-ide-lms-model';
|
|
5
|
+
import { generateStringFromObject, cidePath, hostManagerRoutesUrl, feesRoutesUrl, MFeeStructure, generateObjectFromString, AcaClassPrgBranchListPayload, academicsRoutesUrl, MPrgTrmSection, FeeStructureSaveUpdatePayload, MFeePayment, MFeePaymentInsertUpdatePayload, MFeeReceiptTemplateInsertUpdatePayload, MFeeReceiptTemplate, MFeeReceiptTemplateGetByIdPayload, coreRoutesUrl } from 'cloud-ide-lms-model';
|
|
6
6
|
import * as i1 from '@angular/common';
|
|
7
7
|
import { CommonModule, DatePipe } from '@angular/common';
|
|
8
8
|
import * as i1$1 from '@angular/forms';
|
|
9
9
|
import { FormsModule, FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
10
10
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
11
11
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
12
|
-
import { ConfirmationService, NotificationService, CideIconComponent, CideEleButtonComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideInputComponent, CideTextareaComponent, CideEleTabComponent, CideSelectComponent, CurrencyPipe } from 'cloud-ide-element';
|
|
13
|
-
import { AppStateHelperService, CideLytSharedWrapperComponent, AppStateService } from 'cloud-ide-layout';
|
|
14
|
-
import { ENTITY_SERVICE_TOKEN, ACADEMIC_YEAR_SERVICE_TOKEN, CLASS_PROGRAM_MASTER_SERVICE_TOKEN, PROGRAM_TERM_SECTION_SERVICE_TOKEN, ProgramSectionSelectorWrapperComponent } from 'cloud-ide-shared';
|
|
15
|
-
import { CideCoreGeneralMasterService } from 'cloud-ide-core';
|
|
12
|
+
import { ConfirmationService, NotificationService, CideIconComponent, CideEleButtonComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideInputComponent, CideTextareaComponent, CideEleTabComponent, CideSelectComponent, CideFormFieldErrorComponent, CurrencyPipe } from 'cloud-ide-element';
|
|
13
|
+
import { AppStateHelperService, RightsService, CideLytSharedWrapperComponent, AppStateService, ComponentContextService } from 'cloud-ide-layout';
|
|
14
|
+
import { ENTITY_SERVICE_TOKEN, ACADEMIC_YEAR_SERVICE_TOKEN, CLASS_PROGRAM_MASTER_SERVICE_TOKEN, PROGRAM_TERM_SECTION_SERVICE_TOKEN, GENERAL_MASTER_SERVICE_TOKEN, ProgramSectionSelectorWrapperComponent } from 'cloud-ide-shared';
|
|
16
15
|
import { forkJoin, startWith } from 'rxjs';
|
|
17
16
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
18
17
|
|
|
@@ -251,6 +250,7 @@ class FeeStructureListComponent {
|
|
|
251
250
|
appState = inject(AppStateHelperService);
|
|
252
251
|
confirmationService = inject(ConfirmationService);
|
|
253
252
|
notificationService = inject(NotificationService);
|
|
253
|
+
rightsService = inject(RightsService);
|
|
254
254
|
// Modern ViewChild signals for template renderers (Angular 20 approach)
|
|
255
255
|
feeStructureDetailsRendererTemplate = viewChild.required('feeStructureDetailsRendererTemplate');
|
|
256
256
|
statusRendererTemplate = viewChild.required('statusRendererTemplate');
|
|
@@ -398,7 +398,14 @@ class FeeStructureListComponent {
|
|
|
398
398
|
compact: false,
|
|
399
399
|
tableClass: 'tw-table-fixed tw-w-full tw-rounded-none'
|
|
400
400
|
}), ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
|
|
401
|
+
// Rights computed signals
|
|
402
|
+
canCreate = computed(() => this.rightsService.hasRight('CREATE'), ...(ngDevMode ? [{ debugName: "canCreate" }] : []));
|
|
403
|
+
canEdit = computed(() => this.rightsService.hasRight('EDIT'), ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
|
|
404
|
+
canDelete = computed(() => this.rightsService.hasRight('DELETE'), ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
|
|
405
|
+
canView = computed(() => this.rightsService.hasRight('VIEW'), ...(ngDevMode ? [{ debugName: "canView" }] : []));
|
|
401
406
|
ngOnInit() {
|
|
407
|
+
// Initialize rights for fee structure management
|
|
408
|
+
this.rightsService.initializeRights('fee_structure');
|
|
402
409
|
console.log('💰 Fee Structure List Component initialized');
|
|
403
410
|
this.initializeBreadcrumbData();
|
|
404
411
|
this.loadFeeStructures();
|
|
@@ -541,23 +548,39 @@ class FeeStructureListComponent {
|
|
|
541
548
|
}
|
|
542
549
|
// Fee Structure actions with proper typing
|
|
543
550
|
createFeeStructure() {
|
|
551
|
+
if (!this.rightsService.hasRight('CREATE')) {
|
|
552
|
+
this.notificationService.error('You do not have permission to create fee structures');
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
544
555
|
console.log('➕ Navigating to create fee structure');
|
|
545
556
|
this.notificationService.info('Opening form to create a new fee structure.');
|
|
546
557
|
this.router.navigate(['/control-panel/structure/create']);
|
|
547
558
|
}
|
|
548
559
|
viewFeeStructure(feeStructure) {
|
|
560
|
+
if (!this.rightsService.hasRight('VIEW')) {
|
|
561
|
+
this.notificationService.error('You do not have permission to view fee structures');
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
549
564
|
console.log('👁️ Viewing fee structure:', feeStructure);
|
|
550
565
|
this.notificationService.info(`Opening fee structure "${feeStructure.fees_structure_name}" for viewing.`);
|
|
551
566
|
const queryParams = generateStringFromObject({ fees_id: feeStructure._id });
|
|
552
567
|
this.router.navigate(['/control-panel/structure/view', queryParams]);
|
|
553
568
|
}
|
|
554
569
|
editFeeStructure(feeStructure) {
|
|
570
|
+
if (!this.rightsService.hasRight('EDIT')) {
|
|
571
|
+
this.notificationService.error('You do not have permission to edit fee structures');
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
555
574
|
console.log('✏️ Editing fee structure:', feeStructure);
|
|
556
575
|
this.notificationService.info(`Opening fee structure "${feeStructure.fees_structure_name}" for editing.`);
|
|
557
576
|
const queryParams = generateStringFromObject({ fees_id: feeStructure._id });
|
|
558
577
|
this.router.navigate(['/control-panel/structure/edit', queryParams]);
|
|
559
578
|
}
|
|
560
579
|
deleteFeeStructure(feeStructure) {
|
|
580
|
+
if (!this.rightsService.hasRight('DELETE')) {
|
|
581
|
+
this.notificationService.error('You do not have permission to delete fee structures');
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
561
584
|
console.log('🗑️ Deleting fee structure:', feeStructure);
|
|
562
585
|
this.confirmationService.ask({
|
|
563
586
|
title: 'Delete Fee Structure',
|
|
@@ -601,32 +624,37 @@ class FeeStructureListComponent {
|
|
|
601
624
|
* Get action dropdown items
|
|
602
625
|
*/
|
|
603
626
|
getActionDropdownItems(feeStructure) {
|
|
604
|
-
const items = [
|
|
605
|
-
|
|
627
|
+
const items = [];
|
|
628
|
+
if (this.canView()) {
|
|
629
|
+
items.push({
|
|
606
630
|
id: 'view',
|
|
607
631
|
label: 'View Details',
|
|
608
632
|
icon: 'visibility',
|
|
609
633
|
iconColor: 'tw-text-gray-400',
|
|
610
634
|
textColor: 'tw-text-gray-700',
|
|
611
635
|
hoverBgColor: 'hover:tw-bg-gray-100'
|
|
612
|
-
}
|
|
613
|
-
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
if (this.canEdit()) {
|
|
639
|
+
items.push({
|
|
614
640
|
id: 'edit',
|
|
615
641
|
label: 'Edit',
|
|
616
642
|
icon: 'edit',
|
|
617
643
|
iconColor: 'tw-text-blue-400',
|
|
618
644
|
textColor: 'tw-text-blue-600',
|
|
619
645
|
hoverBgColor: 'hover:tw-bg-blue-50'
|
|
620
|
-
}
|
|
621
|
-
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
if (this.canDelete()) {
|
|
649
|
+
items.push({
|
|
622
650
|
id: 'delete',
|
|
623
651
|
label: 'Delete',
|
|
624
652
|
icon: 'delete',
|
|
625
653
|
iconColor: 'tw-text-red-400',
|
|
626
654
|
textColor: 'tw-text-red-600',
|
|
627
655
|
hoverBgColor: 'hover:tw-bg-red-50'
|
|
628
|
-
}
|
|
629
|
-
|
|
656
|
+
});
|
|
657
|
+
}
|
|
630
658
|
return items;
|
|
631
659
|
}
|
|
632
660
|
/**
|
|
@@ -808,13 +836,14 @@ class FeeStructureCreateComponent {
|
|
|
808
836
|
academicYearService = inject(ACADEMIC_YEAR_SERVICE_TOKEN);
|
|
809
837
|
classProgramMasterService = inject(CLASS_PROGRAM_MASTER_SERVICE_TOKEN);
|
|
810
838
|
programTermSectionService = inject(PROGRAM_TERM_SECTION_SERVICE_TOKEN);
|
|
811
|
-
generalMasterService = inject(
|
|
839
|
+
generalMasterService = inject(GENERAL_MASTER_SERVICE_TOKEN);
|
|
812
840
|
http = inject(HttpClient);
|
|
813
841
|
router = inject(Router);
|
|
814
842
|
route = inject(ActivatedRoute);
|
|
815
843
|
notificationService = inject(NotificationService);
|
|
816
844
|
confirmationService = inject(ConfirmationService);
|
|
817
845
|
appStateService = inject(AppStateService);
|
|
846
|
+
componentContextService = inject(ComponentContextService);
|
|
818
847
|
// Form and state management
|
|
819
848
|
feeStructureForm;
|
|
820
849
|
activeTab = signal('basic', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
@@ -1319,7 +1348,10 @@ class FeeStructureCreateComponent {
|
|
|
1319
1348
|
const itemForm = feeItemsArray.at(itemIndex);
|
|
1320
1349
|
return itemForm.get('installments');
|
|
1321
1350
|
}
|
|
1351
|
+
rightsService = inject(RightsService);
|
|
1322
1352
|
ngOnInit() {
|
|
1353
|
+
// Initialize rights for fee structure management
|
|
1354
|
+
this.rightsService.initializeRights('fee_structure');
|
|
1323
1355
|
this.initializeComponent();
|
|
1324
1356
|
}
|
|
1325
1357
|
ngOnDestroy() {
|
|
@@ -2080,6 +2112,11 @@ class FeeStructureCreateComponent {
|
|
|
2080
2112
|
* Handle form submission
|
|
2081
2113
|
*/
|
|
2082
2114
|
onSubmit() {
|
|
2115
|
+
const requiredRight = this.isEditMode() ? 'EDIT' : 'CREATE';
|
|
2116
|
+
if (!this.rightsService.hasRight(requiredRight)) {
|
|
2117
|
+
this.notificationService.error(`You do not have permission to ${this.isEditMode() ? 'edit' : 'create'} fee structures`);
|
|
2118
|
+
return;
|
|
2119
|
+
}
|
|
2083
2120
|
if (this.submitting()) {
|
|
2084
2121
|
return;
|
|
2085
2122
|
}
|
|
@@ -2277,12 +2314,14 @@ class FeeStructureCreateComponent {
|
|
|
2277
2314
|
type: 'warning'
|
|
2278
2315
|
}).then((confirmed) => {
|
|
2279
2316
|
if (confirmed) {
|
|
2280
|
-
|
|
2317
|
+
// Use ComponentContextService to close tab or floating container
|
|
2318
|
+
this.componentContextService.close(['/control-panel/structure']);
|
|
2281
2319
|
}
|
|
2282
2320
|
});
|
|
2283
2321
|
}
|
|
2284
2322
|
else {
|
|
2285
|
-
|
|
2323
|
+
// Use ComponentContextService to close tab or floating container
|
|
2324
|
+
this.componentContextService.close(['/control-panel/structure']);
|
|
2286
2325
|
}
|
|
2287
2326
|
}
|
|
2288
2327
|
/**
|
|
@@ -2344,7 +2383,7 @@ class FeeStructureCreateComponent {
|
|
|
2344
2383
|
this.breadcrumbData.set(additionalItems);
|
|
2345
2384
|
}
|
|
2346
2385
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeeStructureCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2347
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: FeeStructureCreateComponent, isStandalone: true, selector: "lib-cide-fee-structure-create", ngImport: i0, template: "<!-- Fee Structure Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_structure' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <!-- Back Button in Breadcrumb Area (View Mode Only) -->\n @if (isViewMode()) {\n <div breadcrumb-actions>\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"arrow_back\">\n Back to List\n </button>\n </div>\n }\n \n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"feeStructureForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Tab Navigation -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-2 tw-py-0\">\n <cide-ele-tab [tabs]=\"feeStructureTabs()\" [activeTabId]=\"activeTab()\" size=\"sm\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-4 tw-py-4\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- Basic Information -->\n <div class=\"tw-space-y-4\">\n <!-- First Row: Fee Code (small), Fee Name, Academic Year - Always on one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 170px 1fr 1fr; gap: 1rem;\">\n <cide-ele-input label=\"Fee Structure Code\" formControlName=\"fees_structure_code\"\n placeholder=\"Auto-generated by API\" size=\"sm\" [disabled]=\"isEditMode()\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Fee Structure Name\" formControlName=\"fees_structure_name\"\n placeholder=\"e.g., Grade 10 Fee Structure 2024-25\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Academic Year\" \n formControlName=\"fees_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n [disabled]=\"true\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"fees_structure_description\"\n placeholder=\"Enter detailed description of the fee structure...\"\n rows=\"2\" size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Academic Dropdowns - Using Program Section Selector Component -->\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"feeStructureForm\"\n [classProgramControlName]=\"'fees_class_program_id_acacpm'\"\n [branchControlName]=\"'fees_class_program_branch_id_acabrn'\"\n [termControlName]=\"'fees_class_program_term_id_acapt'\"\n [sectionControlName]=\"'fees_program_term_section_id_acapts'\"\n [academicYearId]=\"feeStructureForm.get('fees_academic_year_id_acayr')?.value\"\n [entityId]=\"feeStructureForm.get('fees_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n [showLabels]=\"true\"\n [gridCols]=\"'tw-grid-cols-1 md:tw-grid-cols-3'\">\n </cide-shared-program-section-selector-wrapper>\n\n <!-- Reservation Category Dropdown -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-4 tw-mt-4\">\n <cide-ele-select \n label=\"Reservation Category\" \n formControlName=\"fees_student_category_id_sygms\"\n [options]=\"studentCategories()\"\n [loading]=\"studentCategoriesLoading()\"\n placeholder=\"Select reservation category\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"fees_is_active\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this fee structure</span>\n </div>\n </div>\n </div>\n }\n\n @case ('items') {\n <!-- Fee Items Section -->\n <div class=\"tw-space-y-3\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-m-0\">Fee Items</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-m-0\">Configure individual fee items for this structure</p>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-text-right\">\n <div class=\"tw-text-xs tw-text-gray-500\">Total Amount</div>\n <div class=\"tw-text-base tw-font-bold tw-text-green-600\">{{ formatCurrency(totalAmount()) }}</div>\n </div>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" leftIcon=\"add\"\n (click)=\"addFeeItem()\">\n Add Fee Item\n </button>\n </div>\n </div>\n\n <div formArrayName=\"fee_items\" class=\"tw-space-y-2 tw-pr-2\">\n @for (item of feeItemsArray.controls; track $index; let itemIndex = $index) {\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm hover:tw-shadow-md tw-transition-shadow tw-p-3\"\n [formGroupName]=\"itemIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1.5 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">Item #{{ itemIndex + 1 }}</h6>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (itemIndex > 0) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemUp(itemIndex)\" title=\"Move Up\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_upward</cide-ele-icon>\n </button>\n }\n @if (itemIndex < feeItemsArray.length - 1) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemDown(itemIndex)\" title=\"Move Down\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_downward</cide-ele-icon>\n </button>\n }\n <button cideEleButton type=\"button\" variant=\"danger\" size=\"xs\" leftIcon=\"delete\"\n (click)=\"removeFeeItem(itemIndex)\"\n [disabled]=\"feeItemsArray.length === 1\">\n Remove\n </button>\n </div>\n </div>\n\n <!-- Category, Code, Name in one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 1fr 170px 1fr; gap: 1rem;\">\n <cide-ele-select \n label=\"Category\" \n formControlName=\"feesi_category_id_sygms\"\n [options]=\"feeCategoriesOptions()\"\n [loading]=\"feeCategoriesLoading()\"\n size=\"sm\"\n placeholder=\"Select Fee Category\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Item Code\" \n formControlName=\"feesi_item_code\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Item Name\" \n formControlName=\"feesi_item_name\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-mt-2\">\n <cide-ele-textarea \n label=\"Description\" \n formControlName=\"feesi_description\"\n rows=\"1\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Amount Section -->\n <div class=\"tw-mt-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n [label]=\"item.get('feesi_is_amount_editable')?.value ? 'Base Amount (Default)' : 'Amount'\" \n formControlName=\"feesi_amount\"\n type=\"number\"\n size=\"sm\"\n [title]=\"item.get('feesi_is_amount_editable')?.value ? 'Default amount used when applying fee. Can be edited per student if editable.' : 'Fixed fee amount'\">\n </cide-ele-input>\n </div>\n\n <!-- Amount Editable Option -->\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mb-2\">\n <cide-ele-input formControlName=\"feesi_is_amount_editable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex-1\">\n <span class=\"tw-text-xs tw-font-semibold tw-text-blue-900\">Allow Amount to be Edited</span>\n <p class=\"tw-text-xs tw-text-blue-700 tw-mt-0.5\">\n Enable this for fees that vary per student (e.g., Transport fee based on distance). \n When applying fees, you'll be asked to enter the amount within the specified range.\n </p>\n </div>\n </div>\n\n <!-- Min/Max Amount Fields (shown when editable is checked) -->\n @if (item.get('feesi_is_amount_editable')?.value) {\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Minimum Amount\" \n formControlName=\"feesi_min_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No minimum\"\n title=\"Minimum amount allowed when editing (leave empty for no minimum)\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Maximum Amount\" \n formControlName=\"feesi_max_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No maximum\"\n title=\"Maximum amount allowed when editing (leave empty for no maximum)\">\n </cide-ele-input>\n </div>\n }\n </div>\n </div>\n\n <!-- Additional Options -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2 tw-mt-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_mandatory\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Mandatory</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_refundable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Refundable</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_installment_allowed\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Installment Allowed</span>\n </div>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <cide-ele-input \n label=\"Installment Count\" \n formControlName=\"feesi_installment_count\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n }\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_tax_applicable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Tax Applicable</span>\n </div>\n </div>\n\n @if (item.get('feesi_tax_applicable')?.value) {\n <div class=\"tw-mt-2\">\n <cide-ele-input \n label=\"Tax Percentage\" \n formControlName=\"feesi_tax_percentage\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n }\n\n <!-- Installment Details Table -->\n <div class=\"tw-mt-4 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment Details ({{ item.get('feesi_installment_count')?.value || 1 }} Installments)\n } @else {\n Payment Details (Single Payment)\n }\n </h6>\n </div>\n </div>\n\n <div formArrayName=\"installments\" class=\"tw-space-y-3\">\n @for (installment of getInstallmentsArray(itemIndex).controls; track $index; let installmentIndex = $index) {\n <div class=\"tw-bg-white tw-rounded tw-border tw-border-gray-300 tw-p-3\"\n [formGroupName]=\"installmentIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">payments</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment #{{ installment.get('installment_number')?.value }}\n } @else {\n Payment Details\n }\n </h6>\n </div>\n <div class=\"tw-text-sm tw-font-medium tw-text-green-600\">\n Amount: {{ formatCurrency(installment.get('installment_amount')?.value || 0) }}\n </div>\n </div>\n\n <!-- Installment Amount Distribution -->\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <div class=\"tw-p-2 tw-bg-yellow-50 tw-rounded tw-border tw-border-yellow-200 tw-mb-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2\">\n <cide-ele-select \n label=\"Distribution Type\" \n formControlName=\"distribution_type\"\n [options]=\"distributionTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n @if (installment.get('distribution_type')?.value === 'PERCENTAGE') {\n <cide-ele-input \n label=\"Percentage (%)\" \n formControlName=\"percentage\"\n type=\"number\"\n size=\"sm\"\n title=\"Percentage of total amount for this installment\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col tw-items-end tw-justify-end tw-gap-1\">\n @if (installmentIndex > 0) {\n <div class=\"tw-text-xs tw-text-blue-600 tw-font-medium\">\n Previous: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) }}%\n </div>\n }\n <div class=\"tw-text-xs tw-text-gray-600\">\n Calculated: {{ formatCurrency((item.get('feesi_amount')?.value || 0) * (installment.get('percentage')?.value || 0) / 100) }}\n </div>\n @if (installmentIndex === getInstallmentsArray(itemIndex).length - 1 && installmentIndex > 0) {\n <div class=\"tw-text-xs tw-font-semibold\" [class.tw-text-green-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) === 100\" [class.tw-text-red-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) !== 100\">\n Total: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0) }}%\n </div>\n }\n </div>\n }\n\n @if (installment.get('distribution_type')?.value === 'FIXED_AMOUNT') {\n <cide-ele-input \n label=\"Fixed Amount\" \n formControlName=\"fixed_amount\"\n type=\"number\"\n size=\"sm\"\n title=\"Fixed amount for this installment\">\n </cide-ele-input>\n }\n </div>\n </div>\n }\n\n <!-- Due Date Fields -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mb-2\">\n <cide-ele-input \n label=\"Due Date Offset (Days from Assignment)\" \n formControlName=\"due_date_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Due Date (Fixed Date - Alternative)\" \n formControlName=\"due_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n\n <!-- Collection Window -->\n <div class=\"tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-1.5 tw-mb-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-3 tw-h-3\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-blue-900 tw-m-0\">Collection Window</h6>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n label=\"Start Offset (Days from Assignment)\" \n formControlName=\"collection_start_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection can start\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Offset (Days from Assignment)\" \n formControlName=\"collection_end_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection window ends\">\n </cide-ele-input>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Start Date (Fixed Date - Alternative)\" \n formControlName=\"collection_start_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Date (Fixed Date - Alternative)\" \n formControlName=\"collection_end_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (feeItemsArray.length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\n <div class=\"tw-bg-white tw-p-3 tw-rounded-full tw-w-12 tw-h-12 tw-mx-auto tw-mb-3 tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"tw-w-6 tw-h-6 tw-text-gray-400\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-1\">No Fee Items Yet</h6>\n <p class=\"tw-text-xs tw-text-gray-500\">Click \"Add Fee Item\" to start adding fee items to this structure.</p>\n </div>\n }\n </div>\n }\n }\n \n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n @if (!isInstallmentPercentagesValid()) {\n <div class=\"tw-w-full tw-mb-3 tw-p-2 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded tw-text-sm\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-text-red-700\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">error</cide-ele-icon>\n <span class=\"tw-font-medium\">Validation Error:</span>\n </div>\n <p class=\"tw-text-red-600 tw-mt-1 tw-ml-6\">\n All installment percentages must total exactly 100% before saving. Please adjust the percentages to continue.\n </p>\n </div>\n }\n \n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || loading() || !isInstallmentPercentagesValid()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Fee Structure' : 'Create Fee Structure' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }, { kind: "component", type: ProgramSectionSelectorWrapperComponent, selector: "cide-shared-program-section-selector-wrapper", inputs: ["formGroup", "classProgramControlName", "branchControlName", "termControlName", "sectionControlName", "academicYearId", "entityId", "disabled", "showLabels", "gridCols", "showAllPrograms", "includeInactive"], outputs: ["valuesChange"] }] });
|
|
2386
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: FeeStructureCreateComponent, isStandalone: true, selector: "lib-cide-fee-structure-create", ngImport: i0, template: "<!-- Fee Structure Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_structure' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <!-- Back Button in Breadcrumb Area (View Mode Only) -->\n @if (isViewMode()) {\n <div breadcrumb-actions>\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"arrow_back\">\n Back to List\n </button>\n </div>\n }\n \n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"feeStructureForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Tab Navigation -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-2 tw-py-0\">\n <cide-ele-tab [tabs]=\"feeStructureTabs()\" [activeTabId]=\"activeTab()\" size=\"sm\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-4 tw-py-4\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- Basic Information -->\n <div class=\"tw-space-y-4\">\n <!-- First Row: Fee Code (small), Fee Name, Academic Year - Always on one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 170px 1fr 1fr; gap: 1rem;\">\n <cide-ele-input label=\"Fee Structure Code\" formControlName=\"fees_structure_code\"\n placeholder=\"Auto-generated by API\" size=\"sm\" [disabled]=\"isEditMode()\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Fee Structure Name\" formControlName=\"fees_structure_name\"\n placeholder=\"e.g., Grade 10 Fee Structure 2024-25\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Academic Year\" \n formControlName=\"fees_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n [disabled]=\"true\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"fees_structure_description\"\n placeholder=\"Enter detailed description of the fee structure...\"\n rows=\"2\" size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Academic Dropdowns - Using Program Section Selector Component -->\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"feeStructureForm\"\n [classProgramControlName]=\"'fees_class_program_id_acacpm'\"\n [branchControlName]=\"'fees_class_program_branch_id_acabrn'\"\n [termControlName]=\"'fees_class_program_term_id_acapt'\"\n [sectionControlName]=\"'fees_program_term_section_id_acapts'\"\n [academicYearId]=\"feeStructureForm.get('fees_academic_year_id_acayr')?.value\"\n [entityId]=\"feeStructureForm.get('fees_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n [showLabels]=\"true\"\n [gridCols]=\"'tw-grid-cols-1 md:tw-grid-cols-3'\">\n </cide-shared-program-section-selector-wrapper>\n\n <!-- Reservation Category Dropdown -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-4 tw-mt-4\">\n <cide-ele-select \n label=\"Reservation Category\" \n formControlName=\"fees_student_category_id_sygms\"\n [options]=\"studentCategories()\"\n [loading]=\"studentCategoriesLoading()\"\n placeholder=\"Select reservation category\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"fees_is_active\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this fee structure</span>\n </div>\n </div>\n </div>\n }\n\n @case ('items') {\n <!-- Fee Items Section -->\n <div class=\"tw-space-y-3\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-m-0\">Fee Items</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-m-0\">Configure individual fee items for this structure</p>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-text-right\">\n <div class=\"tw-text-xs tw-text-gray-500\">Total Amount</div>\n <div class=\"tw-text-base tw-font-bold tw-text-green-600\">{{ formatCurrency(totalAmount()) }}</div>\n </div>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" leftIcon=\"add\"\n (click)=\"addFeeItem()\">\n Add Fee Item\n </button>\n </div>\n </div>\n\n <div formArrayName=\"fee_items\" class=\"tw-space-y-2 tw-pr-2\">\n @for (item of feeItemsArray.controls; track $index; let itemIndex = $index) {\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm hover:tw-shadow-md tw-transition-shadow tw-p-3\"\n [formGroupName]=\"itemIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1.5 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">Item #{{ itemIndex + 1 }}</h6>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (itemIndex > 0) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemUp(itemIndex)\" title=\"Move Up\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_upward</cide-ele-icon>\n </button>\n }\n @if (itemIndex < feeItemsArray.length - 1) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemDown(itemIndex)\" title=\"Move Down\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_downward</cide-ele-icon>\n </button>\n }\n <button cideEleButton type=\"button\" variant=\"danger\" size=\"xs\" leftIcon=\"delete\"\n (click)=\"removeFeeItem(itemIndex)\"\n [disabled]=\"feeItemsArray.length === 1\">\n Remove\n </button>\n </div>\n </div>\n\n <!-- Category, Code, Name in one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 1fr 170px 1fr; gap: 1rem;\">\n <cide-ele-select \n label=\"Category\" \n formControlName=\"feesi_category_id_sygms\"\n [options]=\"feeCategoriesOptions()\"\n [loading]=\"feeCategoriesLoading()\"\n size=\"sm\"\n placeholder=\"Select Fee Category\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Item Code\" \n formControlName=\"feesi_item_code\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Item Name\" \n formControlName=\"feesi_item_name\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-mt-2\">\n <cide-ele-textarea \n label=\"Description\" \n formControlName=\"feesi_description\"\n rows=\"1\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Amount Section -->\n <div class=\"tw-mt-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n [label]=\"item.get('feesi_is_amount_editable')?.value ? 'Base Amount (Default)' : 'Amount'\" \n formControlName=\"feesi_amount\"\n type=\"number\"\n size=\"sm\"\n [title]=\"item.get('feesi_is_amount_editable')?.value ? 'Default amount used when applying fee. Can be edited per student if editable.' : 'Fixed fee amount'\">\n </cide-ele-input>\n </div>\n\n <!-- Amount Editable Option -->\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mb-2\">\n <cide-ele-input formControlName=\"feesi_is_amount_editable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex-1\">\n <span class=\"tw-text-xs tw-font-semibold tw-text-blue-900\">Allow Amount to be Edited</span>\n <p class=\"tw-text-xs tw-text-blue-700 tw-mt-0.5\">\n Enable this for fees that vary per student (e.g., Transport fee based on distance). \n When applying fees, you'll be asked to enter the amount within the specified range.\n </p>\n </div>\n </div>\n\n <!-- Min/Max Amount Fields (shown when editable is checked) -->\n @if (item.get('feesi_is_amount_editable')?.value) {\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Minimum Amount\" \n formControlName=\"feesi_min_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No minimum\"\n title=\"Minimum amount allowed when editing (leave empty for no minimum)\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Maximum Amount\" \n formControlName=\"feesi_max_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No maximum\"\n title=\"Maximum amount allowed when editing (leave empty for no maximum)\">\n </cide-ele-input>\n </div>\n }\n </div>\n </div>\n\n <!-- Additional Options -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2 tw-mt-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_mandatory\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Mandatory</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_refundable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Refundable</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_installment_allowed\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Installment Allowed</span>\n </div>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <cide-ele-input \n label=\"Installment Count\" \n formControlName=\"feesi_installment_count\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n }\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_tax_applicable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Tax Applicable</span>\n </div>\n </div>\n\n @if (item.get('feesi_tax_applicable')?.value) {\n <div class=\"tw-mt-2\">\n <cide-ele-input \n label=\"Tax Percentage\" \n formControlName=\"feesi_tax_percentage\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n }\n\n <!-- Installment Details Table -->\n <div class=\"tw-mt-4 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment Details ({{ item.get('feesi_installment_count')?.value || 1 }} Installments)\n } @else {\n Payment Details (Single Payment)\n }\n </h6>\n </div>\n </div>\n\n <div formArrayName=\"installments\" class=\"tw-space-y-3\">\n @for (installment of getInstallmentsArray(itemIndex).controls; track $index; let installmentIndex = $index) {\n <div class=\"tw-bg-white tw-rounded tw-border tw-border-gray-300 tw-p-3\"\n [formGroupName]=\"installmentIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">payments</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment #{{ installment.get('installment_number')?.value }}\n } @else {\n Payment Details\n }\n </h6>\n </div>\n <div class=\"tw-text-sm tw-font-medium tw-text-green-600\">\n Amount: {{ formatCurrency(installment.get('installment_amount')?.value || 0) }}\n </div>\n </div>\n\n <!-- Installment Amount Distribution -->\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <div class=\"tw-p-2 tw-bg-yellow-50 tw-rounded tw-border tw-border-yellow-200 tw-mb-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2\">\n <cide-ele-select \n label=\"Distribution Type\" \n formControlName=\"distribution_type\"\n [options]=\"distributionTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n @if (installment.get('distribution_type')?.value === 'PERCENTAGE') {\n <cide-ele-input \n label=\"Percentage (%)\" \n formControlName=\"percentage\"\n type=\"number\"\n size=\"sm\"\n title=\"Percentage of total amount for this installment\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col tw-items-end tw-justify-end tw-gap-1\">\n @if (installmentIndex > 0) {\n <div class=\"tw-text-xs tw-text-blue-600 tw-font-medium\">\n Previous: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) }}%\n </div>\n }\n <div class=\"tw-text-xs tw-text-gray-600\">\n Calculated: {{ formatCurrency((item.get('feesi_amount')?.value || 0) * (installment.get('percentage')?.value || 0) / 100) }}\n </div>\n @if (installmentIndex === getInstallmentsArray(itemIndex).length - 1 && installmentIndex > 0) {\n <div class=\"tw-text-xs tw-font-semibold\" [class.tw-text-green-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) === 100\" [class.tw-text-red-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) !== 100\">\n Total: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0) }}%\n </div>\n }\n </div>\n }\n\n @if (installment.get('distribution_type')?.value === 'FIXED_AMOUNT') {\n <cide-ele-input \n label=\"Fixed Amount\" \n formControlName=\"fixed_amount\"\n type=\"number\"\n size=\"sm\"\n title=\"Fixed amount for this installment\">\n </cide-ele-input>\n }\n </div>\n </div>\n }\n\n <!-- Due Date Fields -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mb-2\">\n <cide-ele-input \n label=\"Due Date Offset (Days from Assignment)\" \n formControlName=\"due_date_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Due Date (Fixed Date - Alternative)\" \n formControlName=\"due_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n\n <!-- Collection Window -->\n <div class=\"tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-1.5 tw-mb-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-3 tw-h-3\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-blue-900 tw-m-0\">Collection Window</h6>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n label=\"Start Offset (Days from Assignment)\" \n formControlName=\"collection_start_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection can start\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Offset (Days from Assignment)\" \n formControlName=\"collection_end_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection window ends\">\n </cide-ele-input>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Start Date (Fixed Date - Alternative)\" \n formControlName=\"collection_start_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Date (Fixed Date - Alternative)\" \n formControlName=\"collection_end_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (feeItemsArray.length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\n <div class=\"tw-bg-white tw-p-3 tw-rounded-full tw-w-12 tw-h-12 tw-mx-auto tw-mb-3 tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"tw-w-6 tw-h-6 tw-text-gray-400\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-1\">No Fee Items Yet</h6>\n <p class=\"tw-text-xs tw-text-gray-500\">Click \"Add Fee Item\" to start adding fee items to this structure.</p>\n </div>\n }\n </div>\n }\n }\n \n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <!-- Form Field Errors -->\n <div class=\"tw-w-full tw-mb-4\">\n <cide-form-field-error [formGroup]=\"feeStructureForm\"></cide-form-field-error>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n @if (!isEditMode()) {\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n }\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n @if (!isInstallmentPercentagesValid()) {\n <div class=\"tw-w-full tw-mb-3 tw-p-2 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded tw-text-sm\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-text-red-700\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">error</cide-ele-icon>\n <span class=\"tw-font-medium\">Validation Error:</span>\n </div>\n <p class=\"tw-text-red-600 tw-mt-1 tw-ml-6\">\n All installment percentages must total exactly 100% before saving. Please adjust the percentages to continue.\n </p>\n </div>\n }\n \n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || loading() || !isInstallmentPercentagesValid()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Fee Structure' : 'Create Fee Structure' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }, { kind: "component", type: ProgramSectionSelectorWrapperComponent, selector: "cide-shared-program-section-selector-wrapper", inputs: ["formGroup", "classProgramControlName", "branchControlName", "termControlName", "sectionControlName", "academicYearId", "entityId", "disabled", "showLabels", "gridCols", "showAllPrograms", "includeInactive"], outputs: ["valuesChange"] }, { kind: "component", type: CideFormFieldErrorComponent, selector: "cide-form-field-error", inputs: ["control", "formGroup", "fieldName", "customMessages"] }] });
|
|
2348
2387
|
}
|
|
2349
2388
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeeStructureCreateComponent, decorators: [{
|
|
2350
2389
|
type: Component,
|
|
@@ -2358,8 +2397,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
2358
2397
|
CideIconComponent,
|
|
2359
2398
|
CideSelectComponent,
|
|
2360
2399
|
CideLytSharedWrapperComponent,
|
|
2361
|
-
ProgramSectionSelectorWrapperComponent
|
|
2362
|
-
], template: "<!-- Fee Structure Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_structure' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <!-- Back Button in Breadcrumb Area (View Mode Only) -->\n @if (isViewMode()) {\n <div breadcrumb-actions>\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"arrow_back\">\n Back to List\n </button>\n </div>\n }\n \n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"feeStructureForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Tab Navigation -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-2 tw-py-0\">\n <cide-ele-tab [tabs]=\"feeStructureTabs()\" [activeTabId]=\"activeTab()\" size=\"sm\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-4 tw-py-4\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- Basic Information -->\n <div class=\"tw-space-y-4\">\n <!-- First Row: Fee Code (small), Fee Name, Academic Year - Always on one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 170px 1fr 1fr; gap: 1rem;\">\n <cide-ele-input label=\"Fee Structure Code\" formControlName=\"fees_structure_code\"\n placeholder=\"Auto-generated by API\" size=\"sm\" [disabled]=\"isEditMode()\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Fee Structure Name\" formControlName=\"fees_structure_name\"\n placeholder=\"e.g., Grade 10 Fee Structure 2024-25\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Academic Year\" \n formControlName=\"fees_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n [disabled]=\"true\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"fees_structure_description\"\n placeholder=\"Enter detailed description of the fee structure...\"\n rows=\"2\" size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Academic Dropdowns - Using Program Section Selector Component -->\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"feeStructureForm\"\n [classProgramControlName]=\"'fees_class_program_id_acacpm'\"\n [branchControlName]=\"'fees_class_program_branch_id_acabrn'\"\n [termControlName]=\"'fees_class_program_term_id_acapt'\"\n [sectionControlName]=\"'fees_program_term_section_id_acapts'\"\n [academicYearId]=\"feeStructureForm.get('fees_academic_year_id_acayr')?.value\"\n [entityId]=\"feeStructureForm.get('fees_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n [showLabels]=\"true\"\n [gridCols]=\"'tw-grid-cols-1 md:tw-grid-cols-3'\">\n </cide-shared-program-section-selector-wrapper>\n\n <!-- Reservation Category Dropdown -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-4 tw-mt-4\">\n <cide-ele-select \n label=\"Reservation Category\" \n formControlName=\"fees_student_category_id_sygms\"\n [options]=\"studentCategories()\"\n [loading]=\"studentCategoriesLoading()\"\n placeholder=\"Select reservation category\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"fees_is_active\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this fee structure</span>\n </div>\n </div>\n </div>\n }\n\n @case ('items') {\n <!-- Fee Items Section -->\n <div class=\"tw-space-y-3\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-m-0\">Fee Items</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-m-0\">Configure individual fee items for this structure</p>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-text-right\">\n <div class=\"tw-text-xs tw-text-gray-500\">Total Amount</div>\n <div class=\"tw-text-base tw-font-bold tw-text-green-600\">{{ formatCurrency(totalAmount()) }}</div>\n </div>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" leftIcon=\"add\"\n (click)=\"addFeeItem()\">\n Add Fee Item\n </button>\n </div>\n </div>\n\n <div formArrayName=\"fee_items\" class=\"tw-space-y-2 tw-pr-2\">\n @for (item of feeItemsArray.controls; track $index; let itemIndex = $index) {\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm hover:tw-shadow-md tw-transition-shadow tw-p-3\"\n [formGroupName]=\"itemIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1.5 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">Item #{{ itemIndex + 1 }}</h6>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (itemIndex > 0) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemUp(itemIndex)\" title=\"Move Up\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_upward</cide-ele-icon>\n </button>\n }\n @if (itemIndex < feeItemsArray.length - 1) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemDown(itemIndex)\" title=\"Move Down\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_downward</cide-ele-icon>\n </button>\n }\n <button cideEleButton type=\"button\" variant=\"danger\" size=\"xs\" leftIcon=\"delete\"\n (click)=\"removeFeeItem(itemIndex)\"\n [disabled]=\"feeItemsArray.length === 1\">\n Remove\n </button>\n </div>\n </div>\n\n <!-- Category, Code, Name in one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 1fr 170px 1fr; gap: 1rem;\">\n <cide-ele-select \n label=\"Category\" \n formControlName=\"feesi_category_id_sygms\"\n [options]=\"feeCategoriesOptions()\"\n [loading]=\"feeCategoriesLoading()\"\n size=\"sm\"\n placeholder=\"Select Fee Category\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Item Code\" \n formControlName=\"feesi_item_code\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Item Name\" \n formControlName=\"feesi_item_name\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-mt-2\">\n <cide-ele-textarea \n label=\"Description\" \n formControlName=\"feesi_description\"\n rows=\"1\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Amount Section -->\n <div class=\"tw-mt-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n [label]=\"item.get('feesi_is_amount_editable')?.value ? 'Base Amount (Default)' : 'Amount'\" \n formControlName=\"feesi_amount\"\n type=\"number\"\n size=\"sm\"\n [title]=\"item.get('feesi_is_amount_editable')?.value ? 'Default amount used when applying fee. Can be edited per student if editable.' : 'Fixed fee amount'\">\n </cide-ele-input>\n </div>\n\n <!-- Amount Editable Option -->\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mb-2\">\n <cide-ele-input formControlName=\"feesi_is_amount_editable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex-1\">\n <span class=\"tw-text-xs tw-font-semibold tw-text-blue-900\">Allow Amount to be Edited</span>\n <p class=\"tw-text-xs tw-text-blue-700 tw-mt-0.5\">\n Enable this for fees that vary per student (e.g., Transport fee based on distance). \n When applying fees, you'll be asked to enter the amount within the specified range.\n </p>\n </div>\n </div>\n\n <!-- Min/Max Amount Fields (shown when editable is checked) -->\n @if (item.get('feesi_is_amount_editable')?.value) {\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Minimum Amount\" \n formControlName=\"feesi_min_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No minimum\"\n title=\"Minimum amount allowed when editing (leave empty for no minimum)\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Maximum Amount\" \n formControlName=\"feesi_max_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No maximum\"\n title=\"Maximum amount allowed when editing (leave empty for no maximum)\">\n </cide-ele-input>\n </div>\n }\n </div>\n </div>\n\n <!-- Additional Options -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2 tw-mt-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_mandatory\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Mandatory</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_refundable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Refundable</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_installment_allowed\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Installment Allowed</span>\n </div>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <cide-ele-input \n label=\"Installment Count\" \n formControlName=\"feesi_installment_count\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n }\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_tax_applicable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Tax Applicable</span>\n </div>\n </div>\n\n @if (item.get('feesi_tax_applicable')?.value) {\n <div class=\"tw-mt-2\">\n <cide-ele-input \n label=\"Tax Percentage\" \n formControlName=\"feesi_tax_percentage\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n }\n\n <!-- Installment Details Table -->\n <div class=\"tw-mt-4 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment Details ({{ item.get('feesi_installment_count')?.value || 1 }} Installments)\n } @else {\n Payment Details (Single Payment)\n }\n </h6>\n </div>\n </div>\n\n <div formArrayName=\"installments\" class=\"tw-space-y-3\">\n @for (installment of getInstallmentsArray(itemIndex).controls; track $index; let installmentIndex = $index) {\n <div class=\"tw-bg-white tw-rounded tw-border tw-border-gray-300 tw-p-3\"\n [formGroupName]=\"installmentIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">payments</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment #{{ installment.get('installment_number')?.value }}\n } @else {\n Payment Details\n }\n </h6>\n </div>\n <div class=\"tw-text-sm tw-font-medium tw-text-green-600\">\n Amount: {{ formatCurrency(installment.get('installment_amount')?.value || 0) }}\n </div>\n </div>\n\n <!-- Installment Amount Distribution -->\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <div class=\"tw-p-2 tw-bg-yellow-50 tw-rounded tw-border tw-border-yellow-200 tw-mb-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2\">\n <cide-ele-select \n label=\"Distribution Type\" \n formControlName=\"distribution_type\"\n [options]=\"distributionTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n @if (installment.get('distribution_type')?.value === 'PERCENTAGE') {\n <cide-ele-input \n label=\"Percentage (%)\" \n formControlName=\"percentage\"\n type=\"number\"\n size=\"sm\"\n title=\"Percentage of total amount for this installment\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col tw-items-end tw-justify-end tw-gap-1\">\n @if (installmentIndex > 0) {\n <div class=\"tw-text-xs tw-text-blue-600 tw-font-medium\">\n Previous: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) }}%\n </div>\n }\n <div class=\"tw-text-xs tw-text-gray-600\">\n Calculated: {{ formatCurrency((item.get('feesi_amount')?.value || 0) * (installment.get('percentage')?.value || 0) / 100) }}\n </div>\n @if (installmentIndex === getInstallmentsArray(itemIndex).length - 1 && installmentIndex > 0) {\n <div class=\"tw-text-xs tw-font-semibold\" [class.tw-text-green-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) === 100\" [class.tw-text-red-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) !== 100\">\n Total: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0) }}%\n </div>\n }\n </div>\n }\n\n @if (installment.get('distribution_type')?.value === 'FIXED_AMOUNT') {\n <cide-ele-input \n label=\"Fixed Amount\" \n formControlName=\"fixed_amount\"\n type=\"number\"\n size=\"sm\"\n title=\"Fixed amount for this installment\">\n </cide-ele-input>\n }\n </div>\n </div>\n }\n\n <!-- Due Date Fields -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mb-2\">\n <cide-ele-input \n label=\"Due Date Offset (Days from Assignment)\" \n formControlName=\"due_date_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Due Date (Fixed Date - Alternative)\" \n formControlName=\"due_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n\n <!-- Collection Window -->\n <div class=\"tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-1.5 tw-mb-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-3 tw-h-3\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-blue-900 tw-m-0\">Collection Window</h6>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n label=\"Start Offset (Days from Assignment)\" \n formControlName=\"collection_start_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection can start\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Offset (Days from Assignment)\" \n formControlName=\"collection_end_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection window ends\">\n </cide-ele-input>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Start Date (Fixed Date - Alternative)\" \n formControlName=\"collection_start_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Date (Fixed Date - Alternative)\" \n formControlName=\"collection_end_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (feeItemsArray.length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\n <div class=\"tw-bg-white tw-p-3 tw-rounded-full tw-w-12 tw-h-12 tw-mx-auto tw-mb-3 tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"tw-w-6 tw-h-6 tw-text-gray-400\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-1\">No Fee Items Yet</h6>\n <p class=\"tw-text-xs tw-text-gray-500\">Click \"Add Fee Item\" to start adding fee items to this structure.</p>\n </div>\n }\n </div>\n }\n }\n \n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n @if (!isInstallmentPercentagesValid()) {\n <div class=\"tw-w-full tw-mb-3 tw-p-2 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded tw-text-sm\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-text-red-700\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">error</cide-ele-icon>\n <span class=\"tw-font-medium\">Validation Error:</span>\n </div>\n <p class=\"tw-text-red-600 tw-mt-1 tw-ml-6\">\n All installment percentages must total exactly 100% before saving. Please adjust the percentages to continue.\n </p>\n </div>\n }\n \n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || loading() || !isInstallmentPercentagesValid()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Fee Structure' : 'Create Fee Structure' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n" }]
|
|
2400
|
+
ProgramSectionSelectorWrapperComponent,
|
|
2401
|
+
CideFormFieldErrorComponent
|
|
2402
|
+
], template: "<!-- Fee Structure Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_structure' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <!-- Back Button in Breadcrumb Area (View Mode Only) -->\n @if (isViewMode()) {\n <div breadcrumb-actions>\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"arrow_back\">\n Back to List\n </button>\n </div>\n }\n \n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"feeStructureForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Tab Navigation -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-2 tw-py-0\">\n <cide-ele-tab [tabs]=\"feeStructureTabs()\" [activeTabId]=\"activeTab()\" size=\"sm\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-4 tw-py-4\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- Basic Information -->\n <div class=\"tw-space-y-4\">\n <!-- First Row: Fee Code (small), Fee Name, Academic Year - Always on one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 170px 1fr 1fr; gap: 1rem;\">\n <cide-ele-input label=\"Fee Structure Code\" formControlName=\"fees_structure_code\"\n placeholder=\"Auto-generated by API\" size=\"sm\" [disabled]=\"isEditMode()\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Fee Structure Name\" formControlName=\"fees_structure_name\"\n placeholder=\"e.g., Grade 10 Fee Structure 2024-25\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Academic Year\" \n formControlName=\"fees_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n [disabled]=\"true\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"fees_structure_description\"\n placeholder=\"Enter detailed description of the fee structure...\"\n rows=\"2\" size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Academic Dropdowns - Using Program Section Selector Component -->\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"feeStructureForm\"\n [classProgramControlName]=\"'fees_class_program_id_acacpm'\"\n [branchControlName]=\"'fees_class_program_branch_id_acabrn'\"\n [termControlName]=\"'fees_class_program_term_id_acapt'\"\n [sectionControlName]=\"'fees_program_term_section_id_acapts'\"\n [academicYearId]=\"feeStructureForm.get('fees_academic_year_id_acayr')?.value\"\n [entityId]=\"feeStructureForm.get('fees_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n [showLabels]=\"true\"\n [gridCols]=\"'tw-grid-cols-1 md:tw-grid-cols-3'\">\n </cide-shared-program-section-selector-wrapper>\n\n <!-- Reservation Category Dropdown -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-4 tw-mt-4\">\n <cide-ele-select \n label=\"Reservation Category\" \n formControlName=\"fees_student_category_id_sygms\"\n [options]=\"studentCategories()\"\n [loading]=\"studentCategoriesLoading()\"\n placeholder=\"Select reservation category\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"fees_is_active\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this fee structure</span>\n </div>\n </div>\n </div>\n }\n\n @case ('items') {\n <!-- Fee Items Section -->\n <div class=\"tw-space-y-3\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-m-0\">Fee Items</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-m-0\">Configure individual fee items for this structure</p>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-text-right\">\n <div class=\"tw-text-xs tw-text-gray-500\">Total Amount</div>\n <div class=\"tw-text-base tw-font-bold tw-text-green-600\">{{ formatCurrency(totalAmount()) }}</div>\n </div>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" leftIcon=\"add\"\n (click)=\"addFeeItem()\">\n Add Fee Item\n </button>\n </div>\n </div>\n\n <div formArrayName=\"fee_items\" class=\"tw-space-y-2 tw-pr-2\">\n @for (item of feeItemsArray.controls; track $index; let itemIndex = $index) {\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm hover:tw-shadow-md tw-transition-shadow tw-p-3\"\n [formGroupName]=\"itemIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1.5 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">Item #{{ itemIndex + 1 }}</h6>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (itemIndex > 0) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemUp(itemIndex)\" title=\"Move Up\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_upward</cide-ele-icon>\n </button>\n }\n @if (itemIndex < feeItemsArray.length - 1) {\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" \n (click)=\"moveItemDown(itemIndex)\" title=\"Move Down\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_downward</cide-ele-icon>\n </button>\n }\n <button cideEleButton type=\"button\" variant=\"danger\" size=\"xs\" leftIcon=\"delete\"\n (click)=\"removeFeeItem(itemIndex)\"\n [disabled]=\"feeItemsArray.length === 1\">\n Remove\n </button>\n </div>\n </div>\n\n <!-- Category, Code, Name in one row -->\n <div class=\"tw-grid\" style=\"grid-template-columns: 1fr 170px 1fr; gap: 1rem;\">\n <cide-ele-select \n label=\"Category\" \n formControlName=\"feesi_category_id_sygms\"\n [options]=\"feeCategoriesOptions()\"\n [loading]=\"feeCategoriesLoading()\"\n size=\"sm\"\n placeholder=\"Select Fee Category\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Item Code\" \n formControlName=\"feesi_item_code\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Item Name\" \n formControlName=\"feesi_item_name\"\n size=\"sm\"\n placeholder=\"Auto-filled from category\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-mt-2\">\n <cide-ele-textarea \n label=\"Description\" \n formControlName=\"feesi_description\"\n rows=\"1\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n <!-- Amount Section -->\n <div class=\"tw-mt-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n [label]=\"item.get('feesi_is_amount_editable')?.value ? 'Base Amount (Default)' : 'Amount'\" \n formControlName=\"feesi_amount\"\n type=\"number\"\n size=\"sm\"\n [title]=\"item.get('feesi_is_amount_editable')?.value ? 'Default amount used when applying fee. Can be edited per student if editable.' : 'Fixed fee amount'\">\n </cide-ele-input>\n </div>\n\n <!-- Amount Editable Option -->\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mb-2\">\n <cide-ele-input formControlName=\"feesi_is_amount_editable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex-1\">\n <span class=\"tw-text-xs tw-font-semibold tw-text-blue-900\">Allow Amount to be Edited</span>\n <p class=\"tw-text-xs tw-text-blue-700 tw-mt-0.5\">\n Enable this for fees that vary per student (e.g., Transport fee based on distance). \n When applying fees, you'll be asked to enter the amount within the specified range.\n </p>\n </div>\n </div>\n\n <!-- Min/Max Amount Fields (shown when editable is checked) -->\n @if (item.get('feesi_is_amount_editable')?.value) {\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Minimum Amount\" \n formControlName=\"feesi_min_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No minimum\"\n title=\"Minimum amount allowed when editing (leave empty for no minimum)\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Maximum Amount\" \n formControlName=\"feesi_max_amount\"\n type=\"number\"\n size=\"sm\"\n placeholder=\"No maximum\"\n title=\"Maximum amount allowed when editing (leave empty for no maximum)\">\n </cide-ele-input>\n </div>\n }\n </div>\n </div>\n\n <!-- Additional Options -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2 tw-mt-2\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_mandatory\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Mandatory</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_refundable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Refundable</span>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_is_installment_allowed\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Installment Allowed</span>\n </div>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <cide-ele-input \n label=\"Installment Count\" \n formControlName=\"feesi_installment_count\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n }\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"feesi_tax_applicable\" type=\"checkbox\" size=\"sm\">\n </cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Tax Applicable</span>\n </div>\n </div>\n\n @if (item.get('feesi_tax_applicable')?.value) {\n <div class=\"tw-mt-2\">\n <cide-ele-input \n label=\"Tax Percentage\" \n formControlName=\"feesi_tax_percentage\"\n type=\"number\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n }\n\n <!-- Installment Details Table -->\n <div class=\"tw-mt-4 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment Details ({{ item.get('feesi_installment_count')?.value || 1 }} Installments)\n } @else {\n Payment Details (Single Payment)\n }\n </h6>\n </div>\n </div>\n\n <div formArrayName=\"installments\" class=\"tw-space-y-3\">\n @for (installment of getInstallmentsArray(itemIndex).controls; track $index; let installmentIndex = $index) {\n <div class=\"tw-bg-white tw-rounded tw-border tw-border-gray-300 tw-p-3\"\n [formGroupName]=\"installmentIndex\">\n \n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-1 tw-rounded\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">payments</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-gray-900\">\n @if (item.get('feesi_is_installment_allowed')?.value) {\n Installment #{{ installment.get('installment_number')?.value }}\n } @else {\n Payment Details\n }\n </h6>\n </div>\n <div class=\"tw-text-sm tw-font-medium tw-text-green-600\">\n Amount: {{ formatCurrency(installment.get('installment_amount')?.value || 0) }}\n </div>\n </div>\n\n <!-- Installment Amount Distribution -->\n @if (item.get('feesi_is_installment_allowed')?.value) {\n <div class=\"tw-p-2 tw-bg-yellow-50 tw-rounded tw-border tw-border-yellow-200 tw-mb-2\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-2\">\n <cide-ele-select \n label=\"Distribution Type\" \n formControlName=\"distribution_type\"\n [options]=\"distributionTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n @if (installment.get('distribution_type')?.value === 'PERCENTAGE') {\n <cide-ele-input \n label=\"Percentage (%)\" \n formControlName=\"percentage\"\n type=\"number\"\n size=\"sm\"\n title=\"Percentage of total amount for this installment\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col tw-items-end tw-justify-end tw-gap-1\">\n @if (installmentIndex > 0) {\n <div class=\"tw-text-xs tw-text-blue-600 tw-font-medium\">\n Previous: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) }}%\n </div>\n }\n <div class=\"tw-text-xs tw-text-gray-600\">\n Calculated: {{ formatCurrency((item.get('feesi_amount')?.value || 0) * (installment.get('percentage')?.value || 0) / 100) }}\n </div>\n @if (installmentIndex === getInstallmentsArray(itemIndex).length - 1 && installmentIndex > 0) {\n <div class=\"tw-text-xs tw-font-semibold\" [class.tw-text-green-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) === 100\" [class.tw-text-red-600]=\"(getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0)) !== 100\">\n Total: {{ getPreviousInstallmentsPercentage(itemIndex, installmentIndex) + (installment.get('percentage')?.value || 0) }}%\n </div>\n }\n </div>\n }\n\n @if (installment.get('distribution_type')?.value === 'FIXED_AMOUNT') {\n <cide-ele-input \n label=\"Fixed Amount\" \n formControlName=\"fixed_amount\"\n type=\"number\"\n size=\"sm\"\n title=\"Fixed amount for this installment\">\n </cide-ele-input>\n }\n </div>\n </div>\n }\n\n <!-- Due Date Fields -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mb-2\">\n <cide-ele-input \n label=\"Due Date Offset (Days from Assignment)\" \n formControlName=\"due_date_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Due Date (Fixed Date - Alternative)\" \n formControlName=\"due_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n\n <!-- Collection Window -->\n <div class=\"tw-p-2 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-1.5 tw-mb-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-3 tw-h-3\">schedule</cide-ele-icon>\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-blue-900 tw-m-0\">Collection Window</h6>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2\">\n <cide-ele-input \n label=\"Start Offset (Days from Assignment)\" \n formControlName=\"collection_start_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection can start\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Offset (Days from Assignment)\" \n formControlName=\"collection_end_offset_days\"\n type=\"number\"\n size=\"sm\"\n title=\"Days from assignment date when collection window ends\">\n </cide-ele-input>\n </div>\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2 tw-mt-2\">\n <cide-ele-input \n label=\"Start Date (Fixed Date - Alternative)\" \n formControlName=\"collection_start_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"End Date (Fixed Date - Alternative)\" \n formControlName=\"collection_end_date\"\n type=\"date\"\n size=\"sm\"\n title=\"Use fixed date instead of offset\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (feeItemsArray.length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\n <div class=\"tw-bg-white tw-p-3 tw-rounded-full tw-w-12 tw-h-12 tw-mx-auto tw-mb-3 tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"tw-w-6 tw-h-6 tw-text-gray-400\">receipt</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-1\">No Fee Items Yet</h6>\n <p class=\"tw-text-xs tw-text-gray-500\">Click \"Add Fee Item\" to start adding fee items to this structure.</p>\n </div>\n }\n </div>\n }\n }\n \n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <!-- Form Field Errors -->\n <div class=\"tw-w-full tw-mb-4\">\n <cide-form-field-error [formGroup]=\"feeStructureForm\"></cide-form-field-error>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n @if (!isEditMode()) {\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n }\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n @if (!isInstallmentPercentagesValid()) {\n <div class=\"tw-w-full tw-mb-3 tw-p-2 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded tw-text-sm\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-text-red-700\">\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">error</cide-ele-icon>\n <span class=\"tw-font-medium\">Validation Error:</span>\n </div>\n <p class=\"tw-text-red-600 tw-mt-1 tw-ml-6\">\n All installment percentages must total exactly 100% before saving. Please adjust the percentages to continue.\n </p>\n </div>\n }\n \n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || loading() || !isInstallmentPercentagesValid()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Fee Structure' : 'Create Fee Structure' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n" }]
|
|
2363
2403
|
}], ctorParameters: () => [] });
|
|
2364
2404
|
|
|
2365
2405
|
var feeStructureCreate_component = /*#__PURE__*/Object.freeze({
|
|
@@ -2462,6 +2502,7 @@ class FeeAssignmentListComponent {
|
|
|
2462
2502
|
academicYearService = inject(ACADEMIC_YEAR_SERVICE_TOKEN);
|
|
2463
2503
|
classProgramService = inject(CLASS_PROGRAM_MASTER_SERVICE_TOKEN);
|
|
2464
2504
|
feeAssignmentService = inject(CideFeeFeeAssignmentService);
|
|
2505
|
+
rightsService = inject(RightsService);
|
|
2465
2506
|
studentDetailsRendererTemplate = viewChild.required('studentDetailsRendererTemplate');
|
|
2466
2507
|
amountRendererTemplate = viewChild.required('amountRendererTemplate');
|
|
2467
2508
|
statusRendererTemplate = viewChild.required('statusRendererTemplate');
|
|
@@ -2602,7 +2643,14 @@ class FeeAssignmentListComponent {
|
|
|
2602
2643
|
compact: false,
|
|
2603
2644
|
tableClass: 'tw-table-fixed tw-w-full tw-rounded-none'
|
|
2604
2645
|
}), ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
|
|
2646
|
+
// Rights computed signals
|
|
2647
|
+
canCreate = computed(() => this.rightsService.hasRight('CREATE'), ...(ngDevMode ? [{ debugName: "canCreate" }] : []));
|
|
2648
|
+
canEdit = computed(() => this.rightsService.hasRight('EDIT'), ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
|
|
2649
|
+
canDelete = computed(() => this.rightsService.hasRight('DELETE'), ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
|
|
2650
|
+
canView = computed(() => this.rightsService.hasRight('VIEW'), ...(ngDevMode ? [{ debugName: "canView" }] : []));
|
|
2605
2651
|
ngOnInit() {
|
|
2652
|
+
// Initialize rights for fee assignment management
|
|
2653
|
+
this.rightsService.initializeRights('fee_assignment');
|
|
2606
2654
|
console.log('💰 Fee Assignment List Component initialized');
|
|
2607
2655
|
this.initializeBreadcrumbData();
|
|
2608
2656
|
this.loadDropdownOptions();
|
|
@@ -2765,22 +2813,42 @@ class FeeAssignmentListComponent {
|
|
|
2765
2813
|
this.loadFeeAssignments();
|
|
2766
2814
|
}
|
|
2767
2815
|
navigateToAssign() {
|
|
2816
|
+
if (!this.rightsService.hasRight('CREATE')) {
|
|
2817
|
+
this.notificationService.error('You do not have permission to create fee assignments');
|
|
2818
|
+
return;
|
|
2819
|
+
}
|
|
2768
2820
|
this.router.navigate(['/control-panel/assignment/create']);
|
|
2769
2821
|
}
|
|
2770
2822
|
bulkAssign() {
|
|
2823
|
+
if (!this.rightsService.hasRight('BULK_ASSIGN')) {
|
|
2824
|
+
this.notificationService.error('You do not have permission to perform bulk assignments');
|
|
2825
|
+
return;
|
|
2826
|
+
}
|
|
2771
2827
|
this.notificationService.info('Bulk assignment feature will open in a new window.');
|
|
2772
2828
|
}
|
|
2773
2829
|
viewDetails(assignment) {
|
|
2830
|
+
if (!this.rightsService.hasRight('VIEW')) {
|
|
2831
|
+
this.notificationService.error('You do not have permission to view fee assignments');
|
|
2832
|
+
return;
|
|
2833
|
+
}
|
|
2774
2834
|
console.log('View details:', assignment);
|
|
2775
2835
|
const queryParams = generateStringFromObject({ feeas_id: assignment._id });
|
|
2776
2836
|
this.router.navigate(['/control-panel/assignment/view', queryParams]);
|
|
2777
2837
|
}
|
|
2778
2838
|
modifyAssignment(assignment) {
|
|
2839
|
+
if (!this.rightsService.hasRight('EDIT')) {
|
|
2840
|
+
this.notificationService.error('You do not have permission to modify fee assignments');
|
|
2841
|
+
return;
|
|
2842
|
+
}
|
|
2779
2843
|
console.log('Modify assignment:', assignment);
|
|
2780
2844
|
const queryParams = generateStringFromObject({ feeas_id: assignment._id });
|
|
2781
2845
|
this.router.navigate(['/control-panel/assignment/edit', queryParams]);
|
|
2782
2846
|
}
|
|
2783
2847
|
waiveOff(assignment) {
|
|
2848
|
+
if (!this.rightsService.hasRight('EDIT')) {
|
|
2849
|
+
this.notificationService.error('You do not have permission to waive fees');
|
|
2850
|
+
return;
|
|
2851
|
+
}
|
|
2784
2852
|
this.confirmationService.ask({
|
|
2785
2853
|
title: 'Waive Off Fee',
|
|
2786
2854
|
message: `Are you sure you want to waive off the fee for ${assignment.student_name}? This action cannot be undone.`,
|
|
@@ -2814,32 +2882,35 @@ class FeeAssignmentListComponent {
|
|
|
2814
2882
|
};
|
|
2815
2883
|
}
|
|
2816
2884
|
getActionDropdownItems(assignment) {
|
|
2817
|
-
const items = [
|
|
2818
|
-
|
|
2885
|
+
const items = [];
|
|
2886
|
+
if (this.canView()) {
|
|
2887
|
+
items.push({
|
|
2819
2888
|
id: 'view',
|
|
2820
2889
|
label: 'View Details',
|
|
2821
2890
|
icon: 'visibility',
|
|
2822
2891
|
iconColor: 'tw-text-gray-400',
|
|
2823
2892
|
textColor: 'tw-text-gray-700',
|
|
2824
2893
|
hoverBgColor: 'hover:tw-bg-gray-100'
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2894
|
+
});
|
|
2895
|
+
}
|
|
2896
|
+
if (this.canEdit()) {
|
|
2897
|
+
items.push({
|
|
2827
2898
|
id: 'modify',
|
|
2828
2899
|
label: 'Modify',
|
|
2829
2900
|
icon: 'edit',
|
|
2830
2901
|
iconColor: 'tw-text-blue-400',
|
|
2831
2902
|
textColor: 'tw-text-blue-600',
|
|
2832
2903
|
hoverBgColor: 'hover:tw-bg-blue-50'
|
|
2833
|
-
}
|
|
2834
|
-
{
|
|
2904
|
+
});
|
|
2905
|
+
items.push({
|
|
2835
2906
|
id: 'waive',
|
|
2836
2907
|
label: 'Waive Off',
|
|
2837
2908
|
icon: 'cancel',
|
|
2838
2909
|
iconColor: 'tw-text-red-400',
|
|
2839
2910
|
textColor: 'tw-text-red-600',
|
|
2840
2911
|
hoverBgColor: 'hover:tw-bg-red-50'
|
|
2841
|
-
}
|
|
2842
|
-
|
|
2912
|
+
});
|
|
2913
|
+
}
|
|
2843
2914
|
return items;
|
|
2844
2915
|
}
|
|
2845
2916
|
onDropdownItemClick(item, assignment) {
|
|
@@ -2895,7 +2966,7 @@ class FeeAssignmentListComponent {
|
|
|
2895
2966
|
return assignment.feeas_status || 'Unknown';
|
|
2896
2967
|
}
|
|
2897
2968
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeeAssignmentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2898
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.7", type: FeeAssignmentListComponent, isStandalone: true, selector: "cide-fee-assignment-list", viewQueries: [{ propertyName: "studentDetailsRendererTemplate", first: true, predicate: ["studentDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "amountRendererTemplate", first: true, predicate: ["amountRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "statusRendererTemplate", first: true, predicate: ["statusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Fee Assignment Container -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_assignment' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <!-- Action Buttons in Breadcrumb Area -->\n <div breadcrumb-actions>\n <button cideEleButton variant=\"primary\" size=\"sm\" leftIcon=\"add\" (click)=\"navigateToAssign()\">\n Assign Fees\n </button>\n <button cideEleButton variant=\"secondary\" size=\"sm\" leftIcon=\"group_add\" (click)=\"bulkAssign()\">\n Bulk Assignment\n </button>\n </div>\n\n <div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Stats Row -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-grid tw-grid-cols-1 sm:tw-grid-cols-4 tw-gap-4\">\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Total Assigned</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-gray-900\">{{ stats().total }}</div>\n </div>\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Pending</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-yellow-600\">{{ stats().pending }}</div>\n </div>\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Partially Paid</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-blue-600\">{{ stats().partial }}</div>\n </div>\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Paid</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-green-600\">{{ stats().paid }}</div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Filters Row -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-4 tw-gap-4\">\n <cide-ele-select \n label=\"Academic Year\" \n [options]=\"academicYearOptions()\"\n [ngModel]=\"selectedAcademicYearFilter()\"\n (ngModelChange)=\"onAcademicYearFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Academic Years\">\n </cide-ele-select>\n\n <cide-ele-select \n label=\"Class/Program\" \n [options]=\"classOptions()\"\n [ngModel]=\"selectedClassFilter()\"\n (ngModelChange)=\"onClassFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Classes\">\n </cide-ele-select>\n\n <cide-ele-select \n label=\"Section\" \n [options]=\"sectionOptions()\"\n [ngModel]=\"selectedSectionFilter()\"\n (ngModelChange)=\"onSectionFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Sections\">\n </cide-ele-select>\n\n <cide-ele-select \n label=\"Status\" \n [options]=\"[\n {value: '', label: 'All Status'},\n {value: 'PENDING', label: 'Pending'},\n {value: 'PARTIALLY_PAID', label: 'Partially Paid'},\n {value: 'PAID', label: 'Paid'},\n {value: 'WAIVED', label: 'Waived'}\n ]\"\n [ngModel]=\"selectedStatusFilter()\"\n (ngModelChange)=\"onStatusFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Status\">\n </cide-ele-select>\n </div>\n <div class=\"tw-mt-3\">\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"clearFilters()\">\n Clear Filters\n </button>\n </div>\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n\n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers()\"\n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n </div>\n</cide-lyt-shared-wrapper>\n\n<!-- Template Renderers -->\n<ng-template #studentDetailsRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-flex-col tw-w-full\">\n <div class=\"tw-font-medium tw-text-gray-900\">{{ row.student_name || 'N/A' }}</div>\n <div class=\"tw-text-sm tw-text-gray-500 tw-truncate\">{{ row.class || '' }} / {{ row.section || '' }}</div>\n </div>\n</ng-template>\n\n<ng-template #amountRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-flex-col tw-text-sm tw-items-end\">\n <span class=\"tw-text-gray-900 tw-font-semibold\">{{ formatCurrency(row.feeas_amount_original) }}</span>\n <div class=\"tw-text-xs tw-text-gray-500\">\n Paid: {{ formatCurrency(row.feeas_amount_paid) }}\n </div>\n <div class=\"tw-text-xs tw-font-semibold\" [ngClass]=\"row.feeas_amount_remaining > 0 ? 'tw-text-red-600' : 'tw-text-green-600'\">\n Outstanding: {{ formatCurrency(row.feeas_amount_remaining) }}\n </div>\n </div>\n</ng-template>\n\n<ng-template #statusRendererTemplate let-row=\"row\">\n <span class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-text-center\"\n [ngClass]=\"getStatusBadgeClass(row)\">\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">\n {{ row.feeas_status === 'PAID' ? 'check_circle' : \n row.feeas_status === 'PARTIALLY_PAID' ? 'schedule' : \n row.feeas_status === 'PENDING' ? 'pending' : 'cancel' }}\n </cide-ele-icon>\n {{ getStatusText(row) }}\n </span>\n</ng-template>\n\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getActionDropdownItems(row)\"\n [config]=\"getDropdownConfig()\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>\n\n", styles: [".fee-assignment-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }] });
|
|
2969
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.7", type: FeeAssignmentListComponent, isStandalone: true, selector: "cide-fee-assignment-list", viewQueries: [{ propertyName: "studentDetailsRendererTemplate", first: true, predicate: ["studentDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "amountRendererTemplate", first: true, predicate: ["amountRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "statusRendererTemplate", first: true, predicate: ["statusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Fee Assignment Container -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_assignment' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <!-- Action Buttons in Breadcrumb Area -->\n <div breadcrumb-actions>\n <button cideEleButton variant=\"primary\" size=\"sm\" leftIcon=\"add\" (click)=\"navigateToAssign()\">\n Assign Fees\n </button>\n <button cideEleButton variant=\"secondary\" size=\"sm\" leftIcon=\"group_add\" (click)=\"bulkAssign()\">\n Bulk Assignment\n </button>\n </div>\n\n <div class=\"tw-table tw-w-full tw-h-full\">\n\n <!-- Stats Row -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-grid tw-grid-cols-1 sm:tw-grid-cols-4 tw-gap-4\">\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Total Assigned</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-gray-900\">{{ stats().total }}</div>\n </div>\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Pending</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-yellow-600\">{{ stats().pending }}</div>\n </div>\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Partially Paid</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-blue-600\">{{ stats().partial }}</div>\n </div>\n <div class=\"tw-bg-white tw-p-4 tw-rounded-lg tw-border tw-border-gray-200\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Paid</div>\n <div class=\"tw-text-2xl tw-font-bold tw-text-green-600\">{{ stats().paid }}</div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Filters Row -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-px-6 tw-py-4 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-4 tw-gap-4\">\n <cide-ele-select \n label=\"Academic Year\" \n [options]=\"academicYearOptions()\"\n [ngModel]=\"selectedAcademicYearFilter()\"\n (ngModelChange)=\"onAcademicYearFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Academic Years\">\n </cide-ele-select>\n\n <cide-ele-select \n label=\"Class/Program\" \n [options]=\"classOptions()\"\n [ngModel]=\"selectedClassFilter()\"\n (ngModelChange)=\"onClassFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Classes\">\n </cide-ele-select>\n\n <cide-ele-select \n label=\"Section\" \n [options]=\"sectionOptions()\"\n [ngModel]=\"selectedSectionFilter()\"\n (ngModelChange)=\"onSectionFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Sections\">\n </cide-ele-select>\n\n <cide-ele-select \n label=\"Status\" \n [options]=\"[\n {value: '', label: 'All Status'},\n {value: 'PENDING', label: 'Pending'},\n {value: 'PARTIALLY_PAID', label: 'Partially Paid'},\n {value: 'PAID', label: 'Paid'},\n {value: 'WAIVED', label: 'Waived'}\n ]\"\n [ngModel]=\"selectedStatusFilter()\"\n (ngModelChange)=\"onStatusFilterChange($event)\"\n size=\"sm\"\n placeholder=\"All Status\">\n </cide-ele-select>\n </div>\n <div class=\"tw-mt-3\">\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"clearFilters()\">\n Clear Filters\n </button>\n </div>\n </div>\n </div>\n\n <!-- Main Content Area -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n\n <!-- Data Grid Component -->\n <div class=\"tw-h-full tw-overflow-auto\">\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers()\"\n (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n\n </div>\n </div>\n\n </div>\n</cide-lyt-shared-wrapper>\n\n<!-- Template Renderers -->\n<ng-template #studentDetailsRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-flex-col tw-w-full\">\n <div class=\"tw-font-medium tw-text-gray-900\">{{ row.student_name || 'N/A' }}</div>\n <div class=\"tw-text-sm tw-text-gray-500 tw-truncate\">{{ row.class || '' }} / {{ row.section || '' }}</div>\n </div>\n</ng-template>\n\n<ng-template #amountRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-flex-col tw-text-sm tw-items-end\">\n <span class=\"tw-text-gray-900 tw-font-semibold\">{{ formatCurrency(row.feeas_amount_original) }}</span>\n <div class=\"tw-text-xs tw-text-gray-500\">\n Paid: {{ formatCurrency(row.feeas_amount_paid) }}\n </div>\n <div class=\"tw-text-xs tw-font-semibold\" [ngClass]=\"row.feeas_amount_remaining > 0 ? 'tw-text-red-600' : 'tw-text-green-600'\">\n Outstanding: {{ formatCurrency(row.feeas_amount_remaining) }}\n </div>\n </div>\n</ng-template>\n\n<ng-template #statusRendererTemplate let-row=\"row\">\n <span class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-text-center\"\n [ngClass]=\"getStatusBadgeClass(row)\">\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">\n {{ row.feeas_status === 'PAID' ? 'check_circle' : \n row.feeas_status === 'PARTIALLY_PAID' ? 'schedule' : \n row.feeas_status === 'PENDING' ? 'pending' : 'cancel' }}\n </cide-ele-icon>\n {{ getStatusText(row) }}\n </span>\n</ng-template>\n\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\n <cide-ele-dropdown \n [items]=\"getActionDropdownItems(row)\"\n [config]=\"getDropdownConfig()\"\n (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>\n\n", styles: [".fee-assignment-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }] });
|
|
2899
2970
|
}
|
|
2900
2971
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeeAssignmentListComponent, decorators: [{
|
|
2901
2972
|
type: Component,
|
|
@@ -2927,6 +2998,7 @@ class FeeAssignmentCreateComponent {
|
|
|
2927
2998
|
academicYearService = inject(ACADEMIC_YEAR_SERVICE_TOKEN);
|
|
2928
2999
|
feeStructureService = inject(CideFeeFeeStructureService);
|
|
2929
3000
|
feeAssignmentService = inject(CideFeeFeeAssignmentService);
|
|
3001
|
+
componentContextService = inject(ComponentContextService);
|
|
2930
3002
|
assignmentForm;
|
|
2931
3003
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
2932
3004
|
submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : []));
|
|
@@ -3048,7 +3120,10 @@ class FeeAssignmentCreateComponent {
|
|
|
3048
3120
|
this.onStudentSearch(value);
|
|
3049
3121
|
});
|
|
3050
3122
|
}
|
|
3123
|
+
rightsService = inject(RightsService);
|
|
3051
3124
|
ngOnInit() {
|
|
3125
|
+
// Initialize rights for fee assignment management
|
|
3126
|
+
this.rightsService.initializeRights('fee_assignment');
|
|
3052
3127
|
this.initializeComponent();
|
|
3053
3128
|
}
|
|
3054
3129
|
ngOnDestroy() {
|
|
@@ -3418,6 +3493,11 @@ class FeeAssignmentCreateComponent {
|
|
|
3418
3493
|
}, 0);
|
|
3419
3494
|
}, ...(ngDevMode ? [{ debugName: "totalFinalAmount" }] : []));
|
|
3420
3495
|
onSubmit() {
|
|
3496
|
+
const requiredRight = this.isEditMode() ? 'EDIT' : 'CREATE';
|
|
3497
|
+
if (!this.rightsService.hasRight(requiredRight)) {
|
|
3498
|
+
this.notificationService.error(`You do not have permission to ${this.isEditMode() ? 'edit' : 'create'} fee assignments`);
|
|
3499
|
+
return;
|
|
3500
|
+
}
|
|
3421
3501
|
if (this.assignmentForm.invalid || this.submitting()) {
|
|
3422
3502
|
this.assignmentForm.markAllAsTouched();
|
|
3423
3503
|
this.notificationService.warning('Please fill in all required fields correctly.');
|
|
@@ -3512,28 +3592,35 @@ class FeeAssignmentCreateComponent {
|
|
|
3512
3592
|
}
|
|
3513
3593
|
}
|
|
3514
3594
|
resetForm() {
|
|
3515
|
-
if (this.
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3595
|
+
if (this.isEditMode() && this.assignmentId()) {
|
|
3596
|
+
// Reload data in edit mode
|
|
3597
|
+
this.loadAssignmentData(this.assignmentId());
|
|
3598
|
+
}
|
|
3599
|
+
else {
|
|
3600
|
+
// Reset to defaults in create mode
|
|
3601
|
+
if (this.assignmentForm.dirty) {
|
|
3602
|
+
this.confirmationService.ask({
|
|
3603
|
+
title: 'Reset Form?',
|
|
3604
|
+
message: 'Are you sure you want to reset the form? All unsaved changes will be lost.',
|
|
3605
|
+
confirmText: 'Reset',
|
|
3606
|
+
cancelText: 'Cancel',
|
|
3607
|
+
type: 'warning'
|
|
3608
|
+
}).then((confirmed) => {
|
|
3609
|
+
if (confirmed) {
|
|
3610
|
+
this.assignmentForm.reset({
|
|
3611
|
+
fee_source: 'STRUCTURE',
|
|
3612
|
+
feeas_fee_type: 'ONE_TIME',
|
|
3613
|
+
feeas_original_amount: 0,
|
|
3614
|
+
feeas_discount_amount: 0,
|
|
3615
|
+
feeas_scholarship_amount: 0,
|
|
3616
|
+
feeas_installment_count: 1
|
|
3617
|
+
});
|
|
3618
|
+
this.assignmentId.set('');
|
|
3619
|
+
this.isEditMode.set(false);
|
|
3620
|
+
this.notificationService.info('Form has been reset.');
|
|
3621
|
+
}
|
|
3622
|
+
});
|
|
3623
|
+
}
|
|
3537
3624
|
}
|
|
3538
3625
|
}
|
|
3539
3626
|
onCancel() {
|
|
@@ -3546,12 +3633,12 @@ class FeeAssignmentCreateComponent {
|
|
|
3546
3633
|
type: 'warning'
|
|
3547
3634
|
}).then((confirmed) => {
|
|
3548
3635
|
if (confirmed) {
|
|
3549
|
-
this.
|
|
3636
|
+
this.componentContextService.close(['/fees/assignment']);
|
|
3550
3637
|
}
|
|
3551
3638
|
});
|
|
3552
3639
|
}
|
|
3553
3640
|
else {
|
|
3554
|
-
this.
|
|
3641
|
+
this.componentContextService.close(['/fees/assignment']);
|
|
3555
3642
|
}
|
|
3556
3643
|
}
|
|
3557
3644
|
getAcademicYearOptions() {
|
|
@@ -3604,7 +3691,7 @@ class FeeAssignmentCreateComponent {
|
|
|
3604
3691
|
this.breadcrumbData.set(additionalItems);
|
|
3605
3692
|
}
|
|
3606
3693
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeeAssignmentCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3607
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: FeeAssignmentCreateComponent, isStandalone: true, selector: "cide-fee-assignment-create", ngImport: i0, template: "<!-- Fee Assignment Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_assignment' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"assignmentForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Form Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n <div class=\"tw-space-y-6\">\n\n <!-- Student Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Student Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <div>\n <cide-ele-input \n label=\"Student *\" \n formControlName=\"student_search\"\n placeholder=\"Search student by name or ID...\"\n size=\"sm\"\n leadingIcon=\"search\">\n </cide-ele-input>\n </div>\n\n <cide-ele-select \n label=\"Academic Year *\" \n formControlName=\"feeas_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-select>\n </div>\n \n <!-- Hidden entity field (populated from app state) -->\n <input type=\"hidden\" formControlName=\"feeas_entity_id_syen\">\n </div>\n\n <!-- Academic Information (for fee structure loading) -->\n @if (showFeeStructureField()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-pb-2 tw-border-b-2 tw-border-indigo-200 dark:tw-border-indigo-800 tw-mb-4\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-indigo-600 dark:tw-text-indigo-400\">school</cide-ele-icon>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">Academic Information</h6>\n </div>\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"assignmentForm\"\n classProgramControlName=\"class_program_id\"\n branchControlName=\"branch_id\"\n termControlName=\"term_id\"\n sectionControlName=\"section_id\"\n [academicYearId]=\"assignmentForm.get('feeas_academic_year_id_acayr')?.value\"\n [entityId]=\"assignmentForm.get('feeas_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n (valuesChange)=\"onProgramSectionValuesChange($event)\">\n </cide-shared-program-section-selector-wrapper>\n </div>\n }\n\n <!-- Fee Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Fee Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Source *\" \n formControlName=\"fee_source\"\n [options]=\"feeSourceOptions\"\n size=\"sm\"\n leadingIcon=\"source\">\n </cide-ele-select>\n </div>\n\n <!-- Custom Fee Fields -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-mt-4 tw-space-y-4\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Category *\" \n formControlName=\"feeas_fee_category_sygms\"\n [options]=\"feeCategoryOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Fee Name *\" \n formControlName=\"feeas_fee_name\"\n placeholder=\"Enter fee name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Type *\" \n formControlName=\"feeas_fee_type\"\n [options]=\"feeTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Amount *\" \n formControlName=\"feeas_original_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n size=\"sm\"\n leadingIcon=\"currency_rupee\">\n </cide-ele-input>\n </div>\n </div>\n }\n </div>\n\n <!-- Payment Details -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Payment Details</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Due Date *\" \n formControlName=\"feeas_due_date\"\n type=\"date\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Installments\" \n formControlName=\"feeas_installment_count\"\n type=\"number\"\n placeholder=\"1\"\n min=\"1\"\n max=\"12\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Fee Insights (for fee structure) -->\n @if (showFeeStructureField() && assignmentForm.get('term_id')?.value) {\n <div class=\"tw-bg-blue-50 dark:tw-bg-blue-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-blue-600 dark:tw-text-blue-400\">account_balance</cide-ele-icon>\n Fee Insights\n </h6>\n @if (feesLoading()) {\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading fees...</span>\n }\n </div>\n\n @if (feesLoading()) {\n <div class=\"tw-text-center tw-py-4\">\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading applicable fees...</span>\n </div>\n } @else if (applicableFees().length > 0) {\n <div class=\"tw-overflow-x-auto\">\n <table class=\"tw-min-w-full tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n <thead class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Fee Name</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Category</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Original Amount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Discount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Scholarship</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Final Amount</th>\n </tr>\n </thead>\n <tbody class=\"tw-bg-white dark:tw-bg-gray-800 tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n @for (fee of applicableFees(); track getFeeId(fee)) {\n <tr>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100\">{{ getFeeName(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-600 dark:tw-text-gray-400\">{{ getFeeCategory(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">{{ formatCurrency(getFeeAmount(fee)) }}</td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getDiscountControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getScholarshipControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(calculateFinalAmount(fee)) }}\n </td>\n </tr>\n }\n </tbody>\n <tfoot class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <td colspan=\"2\" class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">Total:</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(totalOriginalAmount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-blue-600 dark:tw-text-blue-400 tw-text-right\">\n {{ formatCurrency(totalDiscount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-purple-600 dark:tw-text-purple-400 tw-text-right\">\n {{ formatCurrency(totalScholarship()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-bold tw-text-green-600 dark:tw-text-green-400 tw-text-right\">\n {{ formatCurrency(totalFinalAmount()) }}\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n } @else {\n <div class=\"tw-text-center tw-py-4 tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">\n No fee structure found for the selected program/term. Please select a program and term to view applicable fees.\n </div>\n }\n </div>\n }\n\n <!-- Discounts & Scholarships (for custom fees) -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Discounts & Scholarships</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Discount Amount\" \n formControlName=\"feeas_discount_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"percent\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Scholarship Amount\" \n formControlName=\"feeas_scholarship_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"school\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Amount Summary (for custom fees) -->\n <div class=\"tw-bg-gradient-to-r tw-from-blue-50 dark:tw-from-blue-900/20 tw-to-indigo-50 dark:tw-to-indigo-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-blue-900 dark:tw-text-blue-100 tw-mb-3\">Amount Summary</h6>\n \n <div class=\"tw-space-y-2\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Original Amount:</span>\n <span class=\"tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">{{ formatCurrency(assignmentForm.get('feeas_original_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Discount:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_discount_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Scholarship:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_scholarship_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-t-2 tw-border-blue-300 dark:tw-border-blue-700 tw-mt-2\">\n <span class=\"tw-text-base tw-font-bold tw-text-blue-900 dark:tw-text-blue-100\">Total Amount:</span>\n <span class=\"tw-text-xl tw-font-bold tw-text-blue-700 dark:tw-text-blue-300\">{{ formatCurrency(totalAmount()) }}</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Remarks -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <cide-ele-textarea \n label=\"Remarks\" \n formControlName=\"feeas_remarks\"\n placeholder=\"Enter any additional remarks...\"\n rows=\"2\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n </div>\n\n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || assignmentForm.invalid || loading()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Assignment' : 'Assign Fee' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }, { kind: "component", type: ProgramSectionSelectorWrapperComponent, selector: "cide-shared-program-section-selector-wrapper", inputs: ["formGroup", "classProgramControlName", "branchControlName", "termControlName", "sectionControlName", "academicYearId", "entityId", "disabled", "showLabels", "gridCols", "showAllPrograms", "includeInactive"], outputs: ["valuesChange"] }] });
|
|
3694
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: FeeAssignmentCreateComponent, isStandalone: true, selector: "cide-fee-assignment-create", ngImport: i0, template: "<!-- Fee Assignment Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_assignment' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"assignmentForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Form Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n <div class=\"tw-space-y-6\">\n\n <!-- Student Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Student Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <div>\n <cide-ele-input \n label=\"Student *\" \n formControlName=\"student_search\"\n placeholder=\"Search student by name or ID...\"\n size=\"sm\"\n leadingIcon=\"search\">\n </cide-ele-input>\n </div>\n\n <cide-ele-select \n label=\"Academic Year *\" \n formControlName=\"feeas_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-select>\n </div>\n \n <!-- Hidden entity field (populated from app state) -->\n <input type=\"hidden\" formControlName=\"feeas_entity_id_syen\">\n </div>\n\n <!-- Academic Information (for fee structure loading) -->\n @if (showFeeStructureField()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-pb-2 tw-border-b-2 tw-border-indigo-200 dark:tw-border-indigo-800 tw-mb-4\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-indigo-600 dark:tw-text-indigo-400\">school</cide-ele-icon>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">Academic Information</h6>\n </div>\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"assignmentForm\"\n classProgramControlName=\"class_program_id\"\n branchControlName=\"branch_id\"\n termControlName=\"term_id\"\n sectionControlName=\"section_id\"\n [academicYearId]=\"assignmentForm.get('feeas_academic_year_id_acayr')?.value\"\n [entityId]=\"assignmentForm.get('feeas_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n (valuesChange)=\"onProgramSectionValuesChange($event)\">\n </cide-shared-program-section-selector-wrapper>\n </div>\n }\n\n <!-- Fee Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Fee Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Source *\" \n formControlName=\"fee_source\"\n [options]=\"feeSourceOptions\"\n size=\"sm\"\n leadingIcon=\"source\">\n </cide-ele-select>\n </div>\n\n <!-- Custom Fee Fields -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-mt-4 tw-space-y-4\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Category *\" \n formControlName=\"feeas_fee_category_sygms\"\n [options]=\"feeCategoryOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Fee Name *\" \n formControlName=\"feeas_fee_name\"\n placeholder=\"Enter fee name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Type *\" \n formControlName=\"feeas_fee_type\"\n [options]=\"feeTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Amount *\" \n formControlName=\"feeas_original_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n size=\"sm\"\n leadingIcon=\"currency_rupee\">\n </cide-ele-input>\n </div>\n </div>\n }\n </div>\n\n <!-- Payment Details -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Payment Details</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Due Date *\" \n formControlName=\"feeas_due_date\"\n type=\"date\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Installments\" \n formControlName=\"feeas_installment_count\"\n type=\"number\"\n placeholder=\"1\"\n min=\"1\"\n max=\"12\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Fee Insights (for fee structure) -->\n @if (showFeeStructureField() && assignmentForm.get('term_id')?.value) {\n <div class=\"tw-bg-blue-50 dark:tw-bg-blue-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-blue-600 dark:tw-text-blue-400\">account_balance</cide-ele-icon>\n Fee Insights\n </h6>\n @if (feesLoading()) {\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading fees...</span>\n }\n </div>\n\n @if (feesLoading()) {\n <div class=\"tw-text-center tw-py-4\">\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading applicable fees...</span>\n </div>\n } @else if (applicableFees().length > 0) {\n <div class=\"tw-overflow-x-auto\">\n <table class=\"tw-min-w-full tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n <thead class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Fee Name</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Category</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Original Amount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Discount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Scholarship</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Final Amount</th>\n </tr>\n </thead>\n <tbody class=\"tw-bg-white dark:tw-bg-gray-800 tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n @for (fee of applicableFees(); track getFeeId(fee)) {\n <tr>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100\">{{ getFeeName(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-600 dark:tw-text-gray-400\">{{ getFeeCategory(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">{{ formatCurrency(getFeeAmount(fee)) }}</td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getDiscountControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getScholarshipControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(calculateFinalAmount(fee)) }}\n </td>\n </tr>\n }\n </tbody>\n <tfoot class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <td colspan=\"2\" class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">Total:</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(totalOriginalAmount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-blue-600 dark:tw-text-blue-400 tw-text-right\">\n {{ formatCurrency(totalDiscount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-purple-600 dark:tw-text-purple-400 tw-text-right\">\n {{ formatCurrency(totalScholarship()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-bold tw-text-green-600 dark:tw-text-green-400 tw-text-right\">\n {{ formatCurrency(totalFinalAmount()) }}\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n } @else {\n <div class=\"tw-text-center tw-py-4 tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">\n No fee structure found for the selected program/term. Please select a program and term to view applicable fees.\n </div>\n }\n </div>\n }\n\n <!-- Discounts & Scholarships (for custom fees) -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Discounts & Scholarships</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Discount Amount\" \n formControlName=\"feeas_discount_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"percent\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Scholarship Amount\" \n formControlName=\"feeas_scholarship_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"school\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Amount Summary (for custom fees) -->\n <div class=\"tw-bg-gradient-to-r tw-from-blue-50 dark:tw-from-blue-900/20 tw-to-indigo-50 dark:tw-to-indigo-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-blue-900 dark:tw-text-blue-100 tw-mb-3\">Amount Summary</h6>\n \n <div class=\"tw-space-y-2\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Original Amount:</span>\n <span class=\"tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">{{ formatCurrency(assignmentForm.get('feeas_original_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Discount:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_discount_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Scholarship:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_scholarship_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-t-2 tw-border-blue-300 dark:tw-border-blue-700 tw-mt-2\">\n <span class=\"tw-text-base tw-font-bold tw-text-blue-900 dark:tw-text-blue-100\">Total Amount:</span>\n <span class=\"tw-text-xl tw-font-bold tw-text-blue-700 dark:tw-text-blue-300\">{{ formatCurrency(totalAmount()) }}</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Remarks -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <cide-ele-textarea \n label=\"Remarks\" \n formControlName=\"feeas_remarks\"\n placeholder=\"Enter any additional remarks...\"\n rows=\"2\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n </div>\n\n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <div class=\"tw-w-full tw-mt-6\">\n <cide-form-field-error [formGroup]=\"assignmentForm\"></cide-form-field-error>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n @if (!isEditMode()) {\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n }\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || assignmentForm.invalid || loading()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Assignment' : 'Assign Fee' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }, { kind: "component", type: ProgramSectionSelectorWrapperComponent, selector: "cide-shared-program-section-selector-wrapper", inputs: ["formGroup", "classProgramControlName", "branchControlName", "termControlName", "sectionControlName", "academicYearId", "entityId", "disabled", "showLabels", "gridCols", "showAllPrograms", "includeInactive"], outputs: ["valuesChange"] }, { kind: "component", type: CideFormFieldErrorComponent, selector: "cide-form-field-error", inputs: ["control", "formGroup", "fieldName", "customMessages"] }] });
|
|
3608
3695
|
}
|
|
3609
3696
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeeAssignmentCreateComponent, decorators: [{
|
|
3610
3697
|
type: Component,
|
|
@@ -3617,8 +3704,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
3617
3704
|
CideSelectComponent,
|
|
3618
3705
|
CideIconComponent,
|
|
3619
3706
|
CideLytSharedWrapperComponent,
|
|
3620
|
-
ProgramSectionSelectorWrapperComponent
|
|
3621
|
-
], template: "<!-- Fee Assignment Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_assignment' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"assignmentForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Form Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n <div class=\"tw-space-y-6\">\n\n <!-- Student Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Student Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <div>\n <cide-ele-input \n label=\"Student *\" \n formControlName=\"student_search\"\n placeholder=\"Search student by name or ID...\"\n size=\"sm\"\n leadingIcon=\"search\">\n </cide-ele-input>\n </div>\n\n <cide-ele-select \n label=\"Academic Year *\" \n formControlName=\"feeas_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-select>\n </div>\n \n <!-- Hidden entity field (populated from app state) -->\n <input type=\"hidden\" formControlName=\"feeas_entity_id_syen\">\n </div>\n\n <!-- Academic Information (for fee structure loading) -->\n @if (showFeeStructureField()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-pb-2 tw-border-b-2 tw-border-indigo-200 dark:tw-border-indigo-800 tw-mb-4\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-indigo-600 dark:tw-text-indigo-400\">school</cide-ele-icon>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">Academic Information</h6>\n </div>\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"assignmentForm\"\n classProgramControlName=\"class_program_id\"\n branchControlName=\"branch_id\"\n termControlName=\"term_id\"\n sectionControlName=\"section_id\"\n [academicYearId]=\"assignmentForm.get('feeas_academic_year_id_acayr')?.value\"\n [entityId]=\"assignmentForm.get('feeas_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n (valuesChange)=\"onProgramSectionValuesChange($event)\">\n </cide-shared-program-section-selector-wrapper>\n </div>\n }\n\n <!-- Fee Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Fee Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Source *\" \n formControlName=\"fee_source\"\n [options]=\"feeSourceOptions\"\n size=\"sm\"\n leadingIcon=\"source\">\n </cide-ele-select>\n </div>\n\n <!-- Custom Fee Fields -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-mt-4 tw-space-y-4\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Category *\" \n formControlName=\"feeas_fee_category_sygms\"\n [options]=\"feeCategoryOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Fee Name *\" \n formControlName=\"feeas_fee_name\"\n placeholder=\"Enter fee name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Type *\" \n formControlName=\"feeas_fee_type\"\n [options]=\"feeTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Amount *\" \n formControlName=\"feeas_original_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n size=\"sm\"\n leadingIcon=\"currency_rupee\">\n </cide-ele-input>\n </div>\n </div>\n }\n </div>\n\n <!-- Payment Details -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Payment Details</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Due Date *\" \n formControlName=\"feeas_due_date\"\n type=\"date\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Installments\" \n formControlName=\"feeas_installment_count\"\n type=\"number\"\n placeholder=\"1\"\n min=\"1\"\n max=\"12\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Fee Insights (for fee structure) -->\n @if (showFeeStructureField() && assignmentForm.get('term_id')?.value) {\n <div class=\"tw-bg-blue-50 dark:tw-bg-blue-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-blue-600 dark:tw-text-blue-400\">account_balance</cide-ele-icon>\n Fee Insights\n </h6>\n @if (feesLoading()) {\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading fees...</span>\n }\n </div>\n\n @if (feesLoading()) {\n <div class=\"tw-text-center tw-py-4\">\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading applicable fees...</span>\n </div>\n } @else if (applicableFees().length > 0) {\n <div class=\"tw-overflow-x-auto\">\n <table class=\"tw-min-w-full tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n <thead class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Fee Name</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Category</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Original Amount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Discount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Scholarship</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Final Amount</th>\n </tr>\n </thead>\n <tbody class=\"tw-bg-white dark:tw-bg-gray-800 tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n @for (fee of applicableFees(); track getFeeId(fee)) {\n <tr>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100\">{{ getFeeName(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-600 dark:tw-text-gray-400\">{{ getFeeCategory(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">{{ formatCurrency(getFeeAmount(fee)) }}</td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getDiscountControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getScholarshipControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(calculateFinalAmount(fee)) }}\n </td>\n </tr>\n }\n </tbody>\n <tfoot class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <td colspan=\"2\" class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">Total:</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(totalOriginalAmount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-blue-600 dark:tw-text-blue-400 tw-text-right\">\n {{ formatCurrency(totalDiscount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-purple-600 dark:tw-text-purple-400 tw-text-right\">\n {{ formatCurrency(totalScholarship()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-bold tw-text-green-600 dark:tw-text-green-400 tw-text-right\">\n {{ formatCurrency(totalFinalAmount()) }}\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n } @else {\n <div class=\"tw-text-center tw-py-4 tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">\n No fee structure found for the selected program/term. Please select a program and term to view applicable fees.\n </div>\n }\n </div>\n }\n\n <!-- Discounts & Scholarships (for custom fees) -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Discounts & Scholarships</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Discount Amount\" \n formControlName=\"feeas_discount_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"percent\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Scholarship Amount\" \n formControlName=\"feeas_scholarship_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"school\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Amount Summary (for custom fees) -->\n <div class=\"tw-bg-gradient-to-r tw-from-blue-50 dark:tw-from-blue-900/20 tw-to-indigo-50 dark:tw-to-indigo-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-blue-900 dark:tw-text-blue-100 tw-mb-3\">Amount Summary</h6>\n \n <div class=\"tw-space-y-2\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Original Amount:</span>\n <span class=\"tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">{{ formatCurrency(assignmentForm.get('feeas_original_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Discount:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_discount_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Scholarship:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_scholarship_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-t-2 tw-border-blue-300 dark:tw-border-blue-700 tw-mt-2\">\n <span class=\"tw-text-base tw-font-bold tw-text-blue-900 dark:tw-text-blue-100\">Total Amount:</span>\n <span class=\"tw-text-xl tw-font-bold tw-text-blue-700 dark:tw-text-blue-300\">{{ formatCurrency(totalAmount()) }}</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Remarks -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <cide-ele-textarea \n label=\"Remarks\" \n formControlName=\"feeas_remarks\"\n placeholder=\"Enter any additional remarks...\"\n rows=\"2\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n </div>\n\n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || assignmentForm.invalid || loading()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Assignment' : 'Assign Fee' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n" }]
|
|
3707
|
+
ProgramSectionSelectorWrapperComponent,
|
|
3708
|
+
CideFormFieldErrorComponent
|
|
3709
|
+
], template: "<!-- Fee Assignment Form -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'fee_assignment' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n <div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"assignmentForm\" \n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Form Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n <div class=\"tw-space-y-6\">\n\n <!-- Student Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Student Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <div>\n <cide-ele-input \n label=\"Student *\" \n formControlName=\"student_search\"\n placeholder=\"Search student by name or ID...\"\n size=\"sm\"\n leadingIcon=\"search\">\n </cide-ele-input>\n </div>\n\n <cide-ele-select \n label=\"Academic Year *\" \n formControlName=\"feeas_academic_year_id_acayr\"\n [options]=\"getAcademicYearOptions()\"\n [loading]=\"academicYearLoading()\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-select>\n </div>\n \n <!-- Hidden entity field (populated from app state) -->\n <input type=\"hidden\" formControlName=\"feeas_entity_id_syen\">\n </div>\n\n <!-- Academic Information (for fee structure loading) -->\n @if (showFeeStructureField()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-pb-2 tw-border-b-2 tw-border-indigo-200 dark:tw-border-indigo-800 tw-mb-4\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-indigo-600 dark:tw-text-indigo-400\">school</cide-ele-icon>\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">Academic Information</h6>\n </div>\n \n <cide-shared-program-section-selector-wrapper\n [formGroup]=\"assignmentForm\"\n classProgramControlName=\"class_program_id\"\n branchControlName=\"branch_id\"\n termControlName=\"term_id\"\n sectionControlName=\"section_id\"\n [academicYearId]=\"assignmentForm.get('feeas_academic_year_id_acayr')?.value\"\n [entityId]=\"assignmentForm.get('feeas_entity_id_syen')?.value\"\n [disabled]=\"isViewMode()\"\n (valuesChange)=\"onProgramSectionValuesChange($event)\">\n </cide-shared-program-section-selector-wrapper>\n </div>\n }\n\n <!-- Fee Information -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Fee Information</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Source *\" \n formControlName=\"fee_source\"\n [options]=\"feeSourceOptions\"\n size=\"sm\"\n leadingIcon=\"source\">\n </cide-ele-select>\n </div>\n\n <!-- Custom Fee Fields -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-mt-4 tw-space-y-4\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Category *\" \n formControlName=\"feeas_fee_category_sygms\"\n [options]=\"feeCategoryOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Fee Name *\" \n formControlName=\"feeas_fee_name\"\n placeholder=\"Enter fee name\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-select \n label=\"Fee Type *\" \n formControlName=\"feeas_fee_type\"\n [options]=\"feeTypeOptions\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input \n label=\"Amount *\" \n formControlName=\"feeas_original_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n size=\"sm\"\n leadingIcon=\"currency_rupee\">\n </cide-ele-input>\n </div>\n </div>\n }\n </div>\n\n <!-- Payment Details -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Payment Details</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Due Date *\" \n formControlName=\"feeas_due_date\"\n type=\"date\"\n size=\"sm\"\n leadingIcon=\"calendar_today\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Installments\" \n formControlName=\"feeas_installment_count\"\n type=\"number\"\n placeholder=\"1\"\n min=\"1\"\n max=\"12\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Fee Insights (for fee structure) -->\n @if (showFeeStructureField() && assignmentForm.get('term_id')?.value) {\n <div class=\"tw-bg-blue-50 dark:tw-bg-blue-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-w-5 tw-h-5 tw-text-blue-600 dark:tw-text-blue-400\">account_balance</cide-ele-icon>\n Fee Insights\n </h6>\n @if (feesLoading()) {\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading fees...</span>\n }\n </div>\n\n @if (feesLoading()) {\n <div class=\"tw-text-center tw-py-4\">\n <span class=\"tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">Loading applicable fees...</span>\n </div>\n } @else if (applicableFees().length > 0) {\n <div class=\"tw-overflow-x-auto\">\n <table class=\"tw-min-w-full tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n <thead class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Fee Name</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-left tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Category</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Original Amount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Discount</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Scholarship</th>\n <th class=\"tw-px-4 tw-py-2 tw-text-right tw-text-xs tw-font-medium tw-text-gray-700 dark:tw-text-gray-300 tw-uppercase\">Final Amount</th>\n </tr>\n </thead>\n <tbody class=\"tw-bg-white dark:tw-bg-gray-800 tw-divide-y tw-divide-gray-200 dark:tw-divide-gray-700\">\n @for (fee of applicableFees(); track getFeeId(fee)) {\n <tr>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100\">{{ getFeeName(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-600 dark:tw-text-gray-400\">{{ getFeeCategory(fee) }}</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">{{ formatCurrency(getFeeAmount(fee)) }}</td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getDiscountControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2\">\n <cide-ele-input\n type=\"number\"\n [formControl]=\"getScholarshipControl(getFeeId(fee))\"\n placeholder=\"0.00\"\n size=\"sm\"\n class=\"tw-w-24\"\n [disabled]=\"isViewMode()\">\n </cide-ele-input>\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(calculateFinalAmount(fee)) }}\n </td>\n </tr>\n }\n </tbody>\n <tfoot class=\"tw-bg-gray-50 dark:tw-bg-gray-800\">\n <tr>\n <td colspan=\"2\" class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">Total:</td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-text-right\">\n {{ formatCurrency(totalOriginalAmount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-blue-600 dark:tw-text-blue-400 tw-text-right\">\n {{ formatCurrency(totalDiscount()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-semibold tw-text-purple-600 dark:tw-text-purple-400 tw-text-right\">\n {{ formatCurrency(totalScholarship()) }}\n </td>\n <td class=\"tw-px-4 tw-py-2 tw-text-sm tw-font-bold tw-text-green-600 dark:tw-text-green-400 tw-text-right\">\n {{ formatCurrency(totalFinalAmount()) }}\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n } @else {\n <div class=\"tw-text-center tw-py-4 tw-text-sm tw-text-gray-500 dark:tw-text-gray-400\">\n No fee structure found for the selected program/term. Please select a program and term to view applicable fees.\n </div>\n }\n </div>\n }\n\n <!-- Discounts & Scholarships (for custom fees) -->\n @if (showCustomFeeFields()) {\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100 tw-mb-3\">Discounts & Scholarships</h6>\n \n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\n <cide-ele-input \n label=\"Discount Amount\" \n formControlName=\"feeas_discount_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"percent\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Scholarship Amount\" \n formControlName=\"feeas_scholarship_amount\"\n type=\"number\"\n placeholder=\"0.00\"\n min=\"0\"\n size=\"sm\"\n leadingIcon=\"school\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Amount Summary (for custom fees) -->\n <div class=\"tw-bg-gradient-to-r tw-from-blue-50 dark:tw-from-blue-900/20 tw-to-indigo-50 dark:tw-to-indigo-900/20 tw-rounded-lg tw-border tw-border-blue-200 dark:tw-border-blue-800 tw-p-4\">\n <h6 class=\"tw-text-base tw-font-semibold tw-text-blue-900 dark:tw-text-blue-100 tw-mb-3\">Amount Summary</h6>\n \n <div class=\"tw-space-y-2\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Original Amount:</span>\n <span class=\"tw-font-semibold tw-text-gray-900 dark:tw-text-gray-100\">{{ formatCurrency(assignmentForm.get('feeas_original_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Discount:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_discount_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-1\">\n <span class=\"tw-text-sm tw-text-gray-700 dark:tw-text-gray-300\">Scholarship:</span>\n <span class=\"tw-font-semibold tw-text-red-600 dark:tw-text-red-400\">-{{ formatCurrency(assignmentForm.get('feeas_scholarship_amount')?.value || 0) }}</span>\n </div>\n \n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-t-2 tw-border-blue-300 dark:tw-border-blue-700 tw-mt-2\">\n <span class=\"tw-text-base tw-font-bold tw-text-blue-900 dark:tw-text-blue-100\">Total Amount:</span>\n <span class=\"tw-text-xl tw-font-bold tw-text-blue-700 dark:tw-text-blue-300\">{{ formatCurrency(totalAmount()) }}</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Remarks -->\n <div class=\"tw-bg-white dark:tw-bg-gray-800 tw-rounded-lg tw-border tw-border-gray-200 dark:tw-border-gray-700 tw-p-4\">\n <cide-ele-textarea \n label=\"Remarks\" \n formControlName=\"feeas_remarks\"\n placeholder=\"Enter any additional remarks...\"\n rows=\"2\" \n size=\"sm\">\n </cide-ele-textarea>\n </div>\n\n </div>\n\n <!-- Form Validation Errors -->\n @if (!isViewMode()) {\n <div class=\"tw-w-full tw-mt-6\">\n <cide-form-field-error [formGroup]=\"assignmentForm\"></cide-form-field-error>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\n @if (!isEditMode()) {\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n }\n\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \n [disabled]=\"submitting() || assignmentForm.invalid || loading()\" \n [loading]=\"submitting()\" \n leftIcon=\"save\">\n {{ isEditMode() ? 'Update Assignment' : 'Assign Fee' }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </form>\n </div>\n</cide-lyt-shared-wrapper>\n\n" }]
|
|
3622
3710
|
}], ctorParameters: () => [] });
|
|
3623
3711
|
|
|
3624
3712
|
var feeAssignmentCreate_component = /*#__PURE__*/Object.freeze({
|
|
@@ -3706,6 +3794,7 @@ class FeePaymentListComponent {
|
|
|
3706
3794
|
appState = inject(AppStateHelperService);
|
|
3707
3795
|
confirmationService = inject(ConfirmationService);
|
|
3708
3796
|
notificationService = inject(NotificationService);
|
|
3797
|
+
rightsService = inject(RightsService);
|
|
3709
3798
|
paymentDetailsRendererTemplate = viewChild.required('paymentDetailsRendererTemplate');
|
|
3710
3799
|
amountRendererTemplate = viewChild.required('amountRendererTemplate');
|
|
3711
3800
|
statusRendererTemplate = viewChild.required('statusRendererTemplate');
|
|
@@ -3833,7 +3922,14 @@ class FeePaymentListComponent {
|
|
|
3833
3922
|
compact: false,
|
|
3834
3923
|
tableClass: 'tw-table-fixed tw-w-full tw-rounded-none'
|
|
3835
3924
|
}), ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
|
|
3925
|
+
// Rights computed signals
|
|
3926
|
+
canCreate = computed(() => this.rightsService.hasRight('CREATE'), ...(ngDevMode ? [{ debugName: "canCreate" }] : []));
|
|
3927
|
+
canEdit = computed(() => this.rightsService.hasRight('EDIT'), ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
|
|
3928
|
+
canDelete = computed(() => this.rightsService.hasRight('DELETE'), ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
|
|
3929
|
+
canView = computed(() => this.rightsService.hasRight('VIEW'), ...(ngDevMode ? [{ debugName: "canView" }] : []));
|
|
3836
3930
|
ngOnInit() {
|
|
3931
|
+
// Initialize rights for fee payment management
|
|
3932
|
+
this.rightsService.initializeRights('fee_payment');
|
|
3837
3933
|
console.log('💰 Fee Payment List Component initialized');
|
|
3838
3934
|
this.loadFeePayments();
|
|
3839
3935
|
}
|
|
@@ -3949,9 +4045,17 @@ class FeePaymentListComponent {
|
|
|
3949
4045
|
this.loadFeePayments();
|
|
3950
4046
|
}
|
|
3951
4047
|
processPayment() {
|
|
4048
|
+
if (!this.rightsService.hasRight('CREATE')) {
|
|
4049
|
+
this.notificationService.error('You do not have permission to process payments');
|
|
4050
|
+
return;
|
|
4051
|
+
}
|
|
3952
4052
|
this.router.navigate(['/control-panel/payment/process']);
|
|
3953
4053
|
}
|
|
3954
4054
|
viewPayment(payment) {
|
|
4055
|
+
if (!this.rightsService.hasRight('VIEW')) {
|
|
4056
|
+
this.notificationService.error('You do not have permission to view payments');
|
|
4057
|
+
return;
|
|
4058
|
+
}
|
|
3955
4059
|
const queryParams = generateStringFromObject({ feepay_id: payment._id });
|
|
3956
4060
|
this.router.navigate(['/control-panel/payment/view', queryParams]);
|
|
3957
4061
|
}
|
|
@@ -4088,6 +4192,7 @@ class FeePaymentProcessComponent {
|
|
|
4088
4192
|
feeAssignmentService = inject(CideFeeFeeAssignmentService);
|
|
4089
4193
|
notificationService = inject(NotificationService);
|
|
4090
4194
|
confirmationService = inject(ConfirmationService);
|
|
4195
|
+
rightsService = inject(RightsService);
|
|
4091
4196
|
paymentForm = this.fb.group({
|
|
4092
4197
|
student_id: ['', [Validators.required]],
|
|
4093
4198
|
student_search: [''],
|
|
@@ -4170,6 +4275,8 @@ class FeePaymentProcessComponent {
|
|
|
4170
4275
|
return this.paymentForm.get('fee_items');
|
|
4171
4276
|
}
|
|
4172
4277
|
ngOnInit() {
|
|
4278
|
+
// Initialize rights for fee payment management
|
|
4279
|
+
this.rightsService.initializeRights('fee_payment');
|
|
4173
4280
|
this.setupPaymentMethodListener();
|
|
4174
4281
|
}
|
|
4175
4282
|
setupPaymentMethodListener() {
|
|
@@ -4349,6 +4456,10 @@ class FeePaymentProcessComponent {
|
|
|
4349
4456
|
}
|
|
4350
4457
|
}
|
|
4351
4458
|
onSubmit() {
|
|
4459
|
+
if (!this.rightsService.hasRight('CREATE')) {
|
|
4460
|
+
this.notificationService.error('You do not have permission to process payments');
|
|
4461
|
+
return;
|
|
4462
|
+
}
|
|
4352
4463
|
if (this.paymentForm.invalid || this.submitting()) {
|
|
4353
4464
|
this.paymentForm.markAllAsTouched();
|
|
4354
4465
|
this.notificationService.warning('Please fill in all required fields correctly.');
|
|
@@ -4441,7 +4552,7 @@ class FeePaymentProcessComponent {
|
|
|
4441
4552
|
return new Date(date) < new Date();
|
|
4442
4553
|
}
|
|
4443
4554
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeePaymentProcessComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4444
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: FeePaymentProcessComponent, isStandalone: true, selector: "cide-fee-payment-process", ngImport: i0, template: "<!-- Payment Process Form -->\r\n<div class=\"tw-w-full tw-h-full\">\r\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"paymentForm\" \r\n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">payment</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Record Payment</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <!-- Back button or other actions can be added here if needed -->\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\r\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\r\n <div class=\"tw-space-y-4\">\r\n\r\n <!-- Student Information -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-p-4\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-mb-3\">Student Information</h6>\r\n \r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <div>\r\n <cide-ele-input \r\n label=\"Search Student *\" \r\n formControlName=\"student_search\"\r\n placeholder=\"Enter student name or ID...\"\r\n size=\"sm\"\r\n leadingIcon=\"search\"\r\n (ngModelChange)=\"onStudentSearch($event)\">\r\n </cide-ele-input>\r\n \r\n @if (selectedStudent()) {\r\n <div class=\"tw-mt-2 tw-p-2 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-green-900\">{{ selectedStudent()?.name }}</div>\r\n <div class=\"tw-text-xs tw-text-green-700\">ID: {{ selectedStudent()?.student_id }}</div>\r\n @if (selectedStudent()?.class) {\r\n <div class=\"tw-text-xs tw-text-green-600\">{{ selectedStudent()?.class }} / {{ selectedStudent()?.section }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <cide-ele-input \r\n label=\"Payment Date *\" \r\n formControlName=\"feepay_payment_date\"\r\n type=\"date\"\r\n size=\"sm\"\r\n leadingIcon=\"calendar_today\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n\r\n <!-- Fee Selection -->\r\n @if (selectedStudent() && outstandingFees().length > 0) {\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-p-4\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900\">Select Fees to Pay</h6>\r\n <div class=\"tw-flex tw-items-center tw-gap-3\">\r\n <div class=\"tw-flex tw-items-center tw-gap-2\">\r\n <cide-ele-input \r\n formControlName=\"pay_full_outstanding\" \r\n type=\"checkbox\" \r\n size=\"sm\"\r\n (change)=\"togglePayFullOutstanding()\">\r\n </cide-ele-input>\r\n <span class=\"tw-text-sm tw-text-gray-700\">Pay full outstanding</span>\r\n </div>\r\n <button cideEleButton type=\"button\" variant=\"success\" size=\"xs\" (click)=\"selectAllFees()\">\r\n Select All\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"xs\" (click)=\"clearAllFees()\">\r\n Clear\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div formArrayName=\"fee_items\" class=\"tw-space-y-2 tw-max-h-80 tw-overflow-y-auto tw-border tw-border-gray-200 tw-rounded-lg tw-p-3\">\r\n @for (item of feeItemsArray.controls; track $index) {\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-p-2 tw-bg-gray-50 tw-rounded tw-border tw-border-gray-200\"\r\n [formGroupName]=\"$index\">\r\n \r\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-flex-1\">\r\n <cide-ele-input \r\n formControlName=\"is_selected\" \r\n type=\"checkbox\" \r\n size=\"sm\"\r\n (change)=\"toggleFeeItem($index)\">\r\n </cide-ele-input>\r\n \r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900\">\r\n {{ item.get('fee_head')?.value }}\r\n </div>\r\n <div class=\"tw-text-xs tw-text-gray-500\">\r\n Outstanding: {{ formatCurrency(item.get('outstanding_amount')?.value || 0) }}\r\n @if (item.get('late_fee')?.value > 0) {\r\n <span class=\"tw-text-red-600\"> | Late Fee: {{ formatCurrency(item.get('late_fee')?.value) }}</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"tw-flex tw-items-center tw-gap-2\">\r\n <cide-ele-input \r\n formControlName=\"amount_paid\"\r\n type=\"number\"\r\n placeholder=\"0.00\"\r\n size=\"sm\"\r\n [disabled]=\"!item.get('is_selected')?.value\"\r\n (ngModelChange)=\"onAmountChange($index, $event)\"\r\n class=\"tw-w-28\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Payment Details -->\r\n @if (selectedStudent()) {\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-p-4\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-mb-3\">Payment Details</h6>\r\n \r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <cide-ele-select \r\n label=\"Payment Method *\" \r\n formControlName=\"feepay_payment_method\"\r\n [options]=\"paymentMethodOptions\"\r\n size=\"sm\"\r\n leadingIcon=\"payment\">\r\n </cide-ele-select>\r\n\r\n <cide-ele-select \r\n label=\"Payment Mode *\" \r\n formControlName=\"feepay_payment_mode\"\r\n [options]=\"[{value: 'OFFLINE', label: 'Offline'}, {value: 'ONLINE', label: 'Online'}]\"\r\n size=\"sm\">\r\n </cide-ele-select>\r\n </div>\r\n\r\n <!-- Cheque/DD Details -->\r\n @if (showChequeDetails()) {\r\n <div class=\"tw-mt-4 tw-p-3 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\r\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-blue-900 tw-mb-3\">Cheque/DD Details</h6>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input \r\n label=\"Cheque/DD Number *\" \r\n formControlName=\"feepay_cheque_number\"\r\n placeholder=\"Enter cheque/DD number\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Cheque/DD Date *\" \r\n formControlName=\"feepay_cheque_date\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-mt-3\">\r\n <cide-ele-input \r\n label=\"Bank Name *\" \r\n formControlName=\"feepay_bank_name\"\r\n placeholder=\"Enter bank name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Branch Name *\" \r\n formControlName=\"feepay_bank_branch_name\"\r\n placeholder=\"Enter branch name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-input \r\n label=\"IFSC Code *\" \r\n formControlName=\"feepay_bank_ifsc_code\"\r\n placeholder=\"Enter IFSC code\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-input \r\n label=\"Instrument Date *\" \r\n formControlName=\"feepay_instrument_date\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Bank Transfer Details -->\r\n @if (showBankDetails()) {\r\n <div class=\"tw-mt-4 tw-p-3 tw-bg-green-50 tw-rounded tw-border tw-border-green-200\">\r\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-green-900 tw-mb-3\">Bank Transfer Details</h6>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input \r\n label=\"Bank Name\" \r\n formControlName=\"feepay_bank_name\"\r\n placeholder=\"Enter bank name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Branch Name\" \r\n formControlName=\"feepay_bank_branch_name\"\r\n placeholder=\"Enter branch name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-mt-3\">\r\n <cide-ele-input \r\n label=\"IFSC Code\" \r\n formControlName=\"feepay_bank_ifsc_code\"\r\n placeholder=\"Enter IFSC code\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Account Number\" \r\n formControlName=\"feepay_bank_account_number\"\r\n placeholder=\"Enter account number\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-input \r\n label=\"Transaction Reference *\" \r\n formControlName=\"feepay_transaction_reference\"\r\n placeholder=\"Enter transaction reference\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Discount Section -->\r\n <div class=\"tw-mt-4 tw-p-3 tw-bg-purple-50 tw-rounded tw-border tw-border-purple-200\">\r\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-purple-900 tw-mb-3\">Discount Information</h6>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input \r\n label=\"Discount (%)\" \r\n formControlName=\"feepay_discount_percentage\"\r\n type=\"number\"\r\n placeholder=\"0\"\r\n size=\"sm\"\r\n [min]=\"0\"\r\n [max]=\"100\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-select \r\n label=\"Discount On\" \r\n formControlName=\"feepay_discount_on\"\r\n [options]=\"[{value: 'SUB_TOTAL', label: 'Sub Total'}, {value: 'FEE_HEAD', label: 'Fee Head'}, {value: 'TOTAL', label: 'Total'}, {value: 'INSTALLMENT', label: 'Installment'}]\"\r\n size=\"sm\">\r\n </cide-ele-select>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-textarea \r\n label=\"Discount Reason\" \r\n formControlName=\"feepay_discount_reason\"\r\n placeholder=\"Enter reason for discount...\"\r\n rows=\"2\"\r\n size=\"sm\">\r\n </cide-ele-textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Payment Reference -->\r\n <div class=\"tw-mt-4\">\r\n <cide-ele-input \r\n label=\"Payment Reference\" \r\n formControlName=\"feepay_payment_reference\"\r\n placeholder=\"Enter payment reference number\"\r\n size=\"sm\"\r\n leadingIcon=\"receipt\">\r\n </cide-ele-input>\r\n </div>\r\n\r\n <!-- Remarks -->\r\n <div class=\"tw-mt-4\">\r\n <cide-ele-textarea \r\n label=\"Remarks\" \r\n formControlName=\"feepay_remarks\"\r\n placeholder=\"Enter any additional remarks...\"\r\n rows=\"2\" \r\n size=\"sm\">\r\n </cide-ele-textarea>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Payment Summary -->\r\n @if (selectedStudent() && selectedFeeItems().length > 0) {\r\n <div class=\"tw-bg-gradient-to-r tw-from-green-50 tw-to-emerald-50 tw-rounded-lg tw-border tw-border-green-200 tw-p-4\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-green-900 tw-mb-3\">Payment Summary</h6>\r\n \r\n <div class=\"tw-space-y-3\">\r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-b tw-border-green-200\">\r\n <span class=\"tw-text-gray-700\">Fee Amount:</span>\r\n <span class=\"tw-font-semibold tw-text-gray-900\">{{ formatCurrency(totalFeeAmount()) }}</span>\r\n </div>\r\n \r\n @if (totalLateFee() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-b tw-border-green-200\">\r\n <span class=\"tw-text-gray-700\">Late Fee Amount:</span>\r\n <span class=\"tw-font-semibold tw-text-red-600\">{{ formatCurrency(totalLateFee()) }}</span>\r\n </div>\r\n }\r\n \r\n @if (totalPenalty() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-b tw-border-green-200\">\r\n <span class=\"tw-text-gray-700\">Penalty Amount:</span>\r\n <span class=\"tw-font-semibold tw-text-red-600\">{{ formatCurrency(totalPenalty()) }}</span>\r\n </div>\r\n }\r\n \r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-3 tw-border-t-2 tw-border-green-300 tw-mt-2\">\r\n <span class=\"tw-text-lg tw-font-bold tw-text-green-900\">Total Payable:</span>\r\n <span class=\"tw-text-2xl tw-font-bold tw-text-green-700\">{{ formatCurrency(totalPayable()) }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Form Validation Errors -->\r\n <!-- Action Buttons -->\r\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\r\n [disabled]=\"loading()\">\r\n Cancel\r\n </button>\r\n\r\n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \r\n [disabled]=\"submitting() || paymentForm.invalid || selectedFeeItems().length === 0 || loading()\" \r\n [loading]=\"submitting()\" \r\n leftIcon=\"save\">\r\n {{ submitting() ? 'Processing...' : 'Record Payment' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n</div>\r\n\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }] });
|
|
4555
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: FeePaymentProcessComponent, isStandalone: true, selector: "cide-fee-payment-process", ngImport: i0, template: "<!-- Payment Process Form -->\r\n<div class=\"tw-w-full tw-h-full\">\r\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"paymentForm\" \r\n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">payment</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Record Payment</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <!-- Back button or other actions can be added here if needed -->\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\r\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\r\n <div class=\"tw-space-y-4\">\r\n\r\n <!-- Student Information -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-p-4\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-mb-3\">Student Information</h6>\r\n \r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <div>\r\n <cide-ele-input \r\n label=\"Search Student *\" \r\n formControlName=\"student_search\"\r\n placeholder=\"Enter student name or ID...\"\r\n size=\"sm\"\r\n leadingIcon=\"search\"\r\n (ngModelChange)=\"onStudentSearch($event)\">\r\n </cide-ele-input>\r\n \r\n @if (selectedStudent()) {\r\n <div class=\"tw-mt-2 tw-p-2 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-green-900\">{{ selectedStudent()?.name }}</div>\r\n <div class=\"tw-text-xs tw-text-green-700\">ID: {{ selectedStudent()?.student_id }}</div>\r\n @if (selectedStudent()?.class) {\r\n <div class=\"tw-text-xs tw-text-green-600\">{{ selectedStudent()?.class }} / {{ selectedStudent()?.section }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <cide-ele-input \r\n label=\"Payment Date *\" \r\n formControlName=\"feepay_payment_date\"\r\n type=\"date\"\r\n size=\"sm\"\r\n leadingIcon=\"calendar_today\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n\r\n <!-- Fee Selection -->\r\n @if (selectedStudent() && outstandingFees().length > 0) {\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-p-4\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900\">Select Fees to Pay</h6>\r\n <div class=\"tw-flex tw-items-center tw-gap-3\">\r\n <div class=\"tw-flex tw-items-center tw-gap-2\">\r\n <cide-ele-input \r\n formControlName=\"pay_full_outstanding\" \r\n type=\"checkbox\" \r\n size=\"sm\"\r\n (change)=\"togglePayFullOutstanding()\">\r\n </cide-ele-input>\r\n <span class=\"tw-text-sm tw-text-gray-700\">Pay full outstanding</span>\r\n </div>\r\n <button cideEleButton type=\"button\" variant=\"success\" size=\"xs\" (click)=\"selectAllFees()\">\r\n Select All\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"xs\" (click)=\"clearAllFees()\">\r\n Clear\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div formArrayName=\"fee_items\" class=\"tw-space-y-2 tw-max-h-80 tw-overflow-y-auto tw-border tw-border-gray-200 tw-rounded-lg tw-p-3\">\r\n @for (item of feeItemsArray.controls; track $index) {\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-p-2 tw-bg-gray-50 tw-rounded tw-border tw-border-gray-200\"\r\n [formGroupName]=\"$index\">\r\n \r\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-flex-1\">\r\n <cide-ele-input \r\n formControlName=\"is_selected\" \r\n type=\"checkbox\" \r\n size=\"sm\"\r\n (change)=\"toggleFeeItem($index)\">\r\n </cide-ele-input>\r\n \r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900\">\r\n {{ item.get('fee_head')?.value }}\r\n </div>\r\n <div class=\"tw-text-xs tw-text-gray-500\">\r\n Outstanding: {{ formatCurrency(item.get('outstanding_amount')?.value || 0) }}\r\n @if (item.get('late_fee')?.value > 0) {\r\n <span class=\"tw-text-red-600\"> | Late Fee: {{ formatCurrency(item.get('late_fee')?.value) }}</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"tw-flex tw-items-center tw-gap-2\">\r\n <cide-ele-input \r\n formControlName=\"amount_paid\"\r\n type=\"number\"\r\n placeholder=\"0.00\"\r\n size=\"sm\"\r\n [disabled]=\"!item.get('is_selected')?.value\"\r\n (ngModelChange)=\"onAmountChange($index, $event)\"\r\n class=\"tw-w-28\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Payment Details -->\r\n @if (selectedStudent()) {\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-p-4\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-gray-900 tw-mb-3\">Payment Details</h6>\r\n \r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <cide-ele-select \r\n label=\"Payment Method *\" \r\n formControlName=\"feepay_payment_method\"\r\n [options]=\"paymentMethodOptions\"\r\n size=\"sm\"\r\n leadingIcon=\"payment\">\r\n </cide-ele-select>\r\n\r\n <cide-ele-select \r\n label=\"Payment Mode *\" \r\n formControlName=\"feepay_payment_mode\"\r\n [options]=\"[{value: 'OFFLINE', label: 'Offline'}, {value: 'ONLINE', label: 'Online'}]\"\r\n size=\"sm\">\r\n </cide-ele-select>\r\n </div>\r\n\r\n <!-- Cheque/DD Details -->\r\n @if (showChequeDetails()) {\r\n <div class=\"tw-mt-4 tw-p-3 tw-bg-blue-50 tw-rounded tw-border tw-border-blue-200\">\r\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-blue-900 tw-mb-3\">Cheque/DD Details</h6>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input \r\n label=\"Cheque/DD Number *\" \r\n formControlName=\"feepay_cheque_number\"\r\n placeholder=\"Enter cheque/DD number\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Cheque/DD Date *\" \r\n formControlName=\"feepay_cheque_date\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-mt-3\">\r\n <cide-ele-input \r\n label=\"Bank Name *\" \r\n formControlName=\"feepay_bank_name\"\r\n placeholder=\"Enter bank name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Branch Name *\" \r\n formControlName=\"feepay_bank_branch_name\"\r\n placeholder=\"Enter branch name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-input \r\n label=\"IFSC Code *\" \r\n formControlName=\"feepay_bank_ifsc_code\"\r\n placeholder=\"Enter IFSC code\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-input \r\n label=\"Instrument Date *\" \r\n formControlName=\"feepay_instrument_date\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Bank Transfer Details -->\r\n @if (showBankDetails()) {\r\n <div class=\"tw-mt-4 tw-p-3 tw-bg-green-50 tw-rounded tw-border tw-border-green-200\">\r\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-green-900 tw-mb-3\">Bank Transfer Details</h6>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input \r\n label=\"Bank Name\" \r\n formControlName=\"feepay_bank_name\"\r\n placeholder=\"Enter bank name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Branch Name\" \r\n formControlName=\"feepay_bank_branch_name\"\r\n placeholder=\"Enter branch name\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-mt-3\">\r\n <cide-ele-input \r\n label=\"IFSC Code\" \r\n formControlName=\"feepay_bank_ifsc_code\"\r\n placeholder=\"Enter IFSC code\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input \r\n label=\"Account Number\" \r\n formControlName=\"feepay_bank_account_number\"\r\n placeholder=\"Enter account number\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-input \r\n label=\"Transaction Reference *\" \r\n formControlName=\"feepay_transaction_reference\"\r\n placeholder=\"Enter transaction reference\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Discount Section -->\r\n <div class=\"tw-mt-4 tw-p-3 tw-bg-purple-50 tw-rounded tw-border tw-border-purple-200\">\r\n <h6 class=\"tw-text-xs tw-font-semibold tw-text-purple-900 tw-mb-3\">Discount Information</h6>\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input \r\n label=\"Discount (%)\" \r\n formControlName=\"feepay_discount_percentage\"\r\n type=\"number\"\r\n placeholder=\"0\"\r\n size=\"sm\"\r\n [min]=\"0\"\r\n [max]=\"100\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-select \r\n label=\"Discount On\" \r\n formControlName=\"feepay_discount_on\"\r\n [options]=\"[{value: 'SUB_TOTAL', label: 'Sub Total'}, {value: 'FEE_HEAD', label: 'Fee Head'}, {value: 'TOTAL', label: 'Total'}, {value: 'INSTALLMENT', label: 'Installment'}]\"\r\n size=\"sm\">\r\n </cide-ele-select>\r\n </div>\r\n <div class=\"tw-mt-3\">\r\n <cide-ele-textarea \r\n label=\"Discount Reason\" \r\n formControlName=\"feepay_discount_reason\"\r\n placeholder=\"Enter reason for discount...\"\r\n rows=\"2\"\r\n size=\"sm\">\r\n </cide-ele-textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Payment Reference -->\r\n <div class=\"tw-mt-4\">\r\n <cide-ele-input \r\n label=\"Payment Reference\" \r\n formControlName=\"feepay_payment_reference\"\r\n placeholder=\"Enter payment reference number\"\r\n size=\"sm\"\r\n leadingIcon=\"receipt\">\r\n </cide-ele-input>\r\n </div>\r\n\r\n <!-- Remarks -->\r\n <div class=\"tw-mt-4\">\r\n <cide-ele-textarea \r\n label=\"Remarks\" \r\n formControlName=\"feepay_remarks\"\r\n placeholder=\"Enter any additional remarks...\"\r\n rows=\"2\" \r\n size=\"sm\">\r\n </cide-ele-textarea>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Payment Summary -->\r\n @if (selectedStudent() && selectedFeeItems().length > 0) {\r\n <div class=\"tw-bg-gradient-to-r tw-from-green-50 tw-to-emerald-50 tw-rounded-lg tw-border tw-border-green-200 tw-p-4\">\r\n <h6 class=\"tw-text-base tw-font-semibold tw-text-green-900 tw-mb-3\">Payment Summary</h6>\r\n \r\n <div class=\"tw-space-y-3\">\r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-b tw-border-green-200\">\r\n <span class=\"tw-text-gray-700\">Fee Amount:</span>\r\n <span class=\"tw-font-semibold tw-text-gray-900\">{{ formatCurrency(totalFeeAmount()) }}</span>\r\n </div>\r\n \r\n @if (totalLateFee() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-b tw-border-green-200\">\r\n <span class=\"tw-text-gray-700\">Late Fee Amount:</span>\r\n <span class=\"tw-font-semibold tw-text-red-600\">{{ formatCurrency(totalLateFee()) }}</span>\r\n </div>\r\n }\r\n \r\n @if (totalPenalty() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-2 tw-border-b tw-border-green-200\">\r\n <span class=\"tw-text-gray-700\">Penalty Amount:</span>\r\n <span class=\"tw-font-semibold tw-text-red-600\">{{ formatCurrency(totalPenalty()) }}</span>\r\n </div>\r\n }\r\n \r\n <div class=\"tw-flex tw-justify-between tw-items-center tw-py-3 tw-border-t-2 tw-border-green-300 tw-mt-2\">\r\n <span class=\"tw-text-lg tw-font-bold tw-text-green-900\">Total Payable:</span>\r\n <span class=\"tw-text-2xl tw-font-bold tw-text-green-700\">{{ formatCurrency(totalPayable()) }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Form Validation Errors -->\r\n <!-- Action Buttons -->\r\n <div class=\"tw-flex tw-justify-end tw-gap-3 tw-mt-6\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"onCancel()\" leftIcon=\"close\"\r\n [disabled]=\"loading()\">\r\n Cancel\r\n </button>\r\n\r\n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"sm\" \r\n [disabled]=\"submitting() || paymentForm.invalid || selectedFeeItems().length === 0 || loading()\" \r\n [loading]=\"submitting()\" \r\n leftIcon=\"save\">\r\n {{ submitting() ? 'Processing...' : 'Record Payment' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n</div>\r\n\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }] });
|
|
4445
4556
|
}
|
|
4446
4557
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FeePaymentProcessComponent, decorators: [{
|
|
4447
4558
|
type: Component,
|
|
@@ -4467,6 +4578,8 @@ class FeePaymentViewComponent {
|
|
|
4467
4578
|
router = inject(Router);
|
|
4468
4579
|
feePaymentService = inject(CideFeeFeePaymentService);
|
|
4469
4580
|
notificationService = inject(NotificationService);
|
|
4581
|
+
http = inject(HttpClient);
|
|
4582
|
+
rightsService = inject(RightsService);
|
|
4470
4583
|
shared_wrapper_setup_param = {
|
|
4471
4584
|
sypg_page_code: "fee_payment",
|
|
4472
4585
|
breadcrumb_right_template: ''
|
|
@@ -4474,7 +4587,15 @@ class FeePaymentViewComponent {
|
|
|
4474
4587
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
4475
4588
|
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
4476
4589
|
feePayment = signal(null, ...(ngDevMode ? [{ debugName: "feePayment" }] : []));
|
|
4590
|
+
generatingReceipt = signal(false, ...(ngDevMode ? [{ debugName: "generatingReceipt" }] : []));
|
|
4591
|
+
receiptHtml = signal(null, ...(ngDevMode ? [{ debugName: "receiptHtml" }] : []));
|
|
4592
|
+
// Rights computed signals
|
|
4593
|
+
canView = computed(() => this.rightsService.hasRight('VIEW'), ...(ngDevMode ? [{ debugName: "canView" }] : []));
|
|
4594
|
+
canPrint = computed(() => this.rightsService.hasRight('PRINT'), ...(ngDevMode ? [{ debugName: "canPrint" }] : []));
|
|
4595
|
+
canDownload = computed(() => this.rightsService.hasRight('DOWNLOAD'), ...(ngDevMode ? [{ debugName: "canDownload" }] : []));
|
|
4477
4596
|
ngOnInit() {
|
|
4597
|
+
// Initialize rights for fee payment management
|
|
4598
|
+
this.rightsService.initializeRights('fee_payment');
|
|
4478
4599
|
const query = this.route.snapshot.paramMap.get('query');
|
|
4479
4600
|
if (query) {
|
|
4480
4601
|
try {
|
|
@@ -4571,10 +4692,185 @@ class FeePaymentViewComponent {
|
|
|
4571
4692
|
}).format(amount);
|
|
4572
4693
|
}
|
|
4573
4694
|
printReceipt() {
|
|
4574
|
-
|
|
4695
|
+
const payment = this.feePayment();
|
|
4696
|
+
if (!payment?._id) {
|
|
4697
|
+
this.notificationService.error('Payment ID not found');
|
|
4698
|
+
return;
|
|
4699
|
+
}
|
|
4700
|
+
// Generate receipt if not already generated
|
|
4701
|
+
if (!this.receiptHtml()) {
|
|
4702
|
+
this.generateReceipt(() => {
|
|
4703
|
+
this.printReceiptHtml();
|
|
4704
|
+
});
|
|
4705
|
+
}
|
|
4706
|
+
else {
|
|
4707
|
+
this.printReceiptHtml();
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
printReceiptHtml() {
|
|
4711
|
+
const html = this.receiptHtml();
|
|
4712
|
+
if (html) {
|
|
4713
|
+
const printWindow = window.open('', '_blank');
|
|
4714
|
+
if (printWindow) {
|
|
4715
|
+
printWindow.document.write(html);
|
|
4716
|
+
printWindow.document.close();
|
|
4717
|
+
printWindow.focus();
|
|
4718
|
+
setTimeout(() => {
|
|
4719
|
+
printWindow.print();
|
|
4720
|
+
printWindow.close();
|
|
4721
|
+
}, 250);
|
|
4722
|
+
}
|
|
4723
|
+
}
|
|
4724
|
+
else {
|
|
4725
|
+
// Fallback to browser print
|
|
4726
|
+
window.print();
|
|
4727
|
+
}
|
|
4575
4728
|
}
|
|
4576
4729
|
downloadReceipt() {
|
|
4577
|
-
this.
|
|
4730
|
+
if (!this.rightsService.hasRight('DOWNLOAD_RECEIPT')) {
|
|
4731
|
+
this.notificationService.error('You do not have permission to download receipts');
|
|
4732
|
+
return;
|
|
4733
|
+
}
|
|
4734
|
+
const payment = this.feePayment();
|
|
4735
|
+
if (!payment?._id) {
|
|
4736
|
+
this.notificationService.error('Payment ID not found');
|
|
4737
|
+
return;
|
|
4738
|
+
}
|
|
4739
|
+
// Generate receipt if not already generated
|
|
4740
|
+
if (!this.receiptHtml()) {
|
|
4741
|
+
this.generateReceipt(() => {
|
|
4742
|
+
this.downloadReceiptPdf();
|
|
4743
|
+
});
|
|
4744
|
+
}
|
|
4745
|
+
else {
|
|
4746
|
+
this.downloadReceiptPdf();
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
downloadReceiptPdf() {
|
|
4750
|
+
const payment = this.feePayment();
|
|
4751
|
+
if (!payment?._id) {
|
|
4752
|
+
return;
|
|
4753
|
+
}
|
|
4754
|
+
const paymentId = payment._id;
|
|
4755
|
+
const receiptUrl = cidePath.join([
|
|
4756
|
+
hostManagerRoutesUrl.cideSuiteHost,
|
|
4757
|
+
'fees',
|
|
4758
|
+
'receipt',
|
|
4759
|
+
paymentId,
|
|
4760
|
+
'pdf'
|
|
4761
|
+
]);
|
|
4762
|
+
// Open in new tab for download
|
|
4763
|
+
window.open(receiptUrl, '_blank');
|
|
4764
|
+
this.notificationService.info('Downloading receipt PDF...');
|
|
4765
|
+
}
|
|
4766
|
+
generateReceipt(callback) {
|
|
4767
|
+
if (!this.rightsService.hasRight('VIEW')) {
|
|
4768
|
+
this.notificationService.error('You do not have permission to generate receipts');
|
|
4769
|
+
return;
|
|
4770
|
+
}
|
|
4771
|
+
const payment = this.feePayment();
|
|
4772
|
+
if (!payment?._id) {
|
|
4773
|
+
this.notificationService.error('Payment ID not found');
|
|
4774
|
+
return;
|
|
4775
|
+
}
|
|
4776
|
+
this.generatingReceipt.set(true);
|
|
4777
|
+
const paymentId = payment._id;
|
|
4778
|
+
const generateUrl = cidePath.join([
|
|
4779
|
+
hostManagerRoutesUrl.cideSuiteHost,
|
|
4780
|
+
'fees',
|
|
4781
|
+
'receipt',
|
|
4782
|
+
'generate',
|
|
4783
|
+
paymentId
|
|
4784
|
+
]);
|
|
4785
|
+
this.http.post(generateUrl, {}).subscribe({
|
|
4786
|
+
next: (response) => {
|
|
4787
|
+
this.generatingReceipt.set(false);
|
|
4788
|
+
if (response?.success && response?.data) {
|
|
4789
|
+
// Store receipt HTML if available
|
|
4790
|
+
if (response.data.receiptHtml) {
|
|
4791
|
+
this.receiptHtml.set(response.data.receiptHtml);
|
|
4792
|
+
}
|
|
4793
|
+
this.notificationService.success('Receipt generated successfully');
|
|
4794
|
+
if (callback) {
|
|
4795
|
+
callback();
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4798
|
+
else {
|
|
4799
|
+
this.notificationService.error(response?.message || 'Failed to generate receipt');
|
|
4800
|
+
}
|
|
4801
|
+
},
|
|
4802
|
+
error: (err) => {
|
|
4803
|
+
console.error('Error generating receipt:', err);
|
|
4804
|
+
this.generatingReceipt.set(false);
|
|
4805
|
+
this.notificationService.error('Failed to generate receipt');
|
|
4806
|
+
}
|
|
4807
|
+
});
|
|
4808
|
+
}
|
|
4809
|
+
viewReceipt() {
|
|
4810
|
+
if (!this.rightsService.hasRight('VIEW')) {
|
|
4811
|
+
this.notificationService.error('You do not have permission to view receipts');
|
|
4812
|
+
return;
|
|
4813
|
+
}
|
|
4814
|
+
const payment = this.feePayment();
|
|
4815
|
+
if (!payment?._id) {
|
|
4816
|
+
this.notificationService.error('Payment ID not found');
|
|
4817
|
+
return;
|
|
4818
|
+
}
|
|
4819
|
+
// Generate receipt if not already generated
|
|
4820
|
+
if (!this.receiptHtml()) {
|
|
4821
|
+
this.generateReceipt(() => {
|
|
4822
|
+
this.openReceiptInNewTab();
|
|
4823
|
+
});
|
|
4824
|
+
}
|
|
4825
|
+
else {
|
|
4826
|
+
this.openReceiptInNewTab();
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
openReceiptInNewTab() {
|
|
4830
|
+
const html = this.receiptHtml();
|
|
4831
|
+
if (html) {
|
|
4832
|
+
const newWindow = window.open('', '_blank');
|
|
4833
|
+
if (newWindow) {
|
|
4834
|
+
newWindow.document.write(html);
|
|
4835
|
+
newWindow.document.close();
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
else {
|
|
4839
|
+
// Fallback: get receipt HTML from API
|
|
4840
|
+
const payment = this.feePayment();
|
|
4841
|
+
if (payment?._id) {
|
|
4842
|
+
const paymentId = payment._id;
|
|
4843
|
+
const receiptUrl = cidePath.join([
|
|
4844
|
+
hostManagerRoutesUrl.cideSuiteHost,
|
|
4845
|
+
'fees',
|
|
4846
|
+
'receipt',
|
|
4847
|
+
paymentId,
|
|
4848
|
+
'html'
|
|
4849
|
+
]);
|
|
4850
|
+
this.http.get(receiptUrl).subscribe({
|
|
4851
|
+
next: (response) => {
|
|
4852
|
+
if (response?.success && response?.data) {
|
|
4853
|
+
const receiptHtml = response.data.html || response.data.receiptHtml;
|
|
4854
|
+
if (receiptHtml) {
|
|
4855
|
+
this.receiptHtml.set(receiptHtml);
|
|
4856
|
+
const newWindow = window.open('', '_blank');
|
|
4857
|
+
if (newWindow) {
|
|
4858
|
+
newWindow.document.write(receiptHtml);
|
|
4859
|
+
newWindow.document.close();
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
else {
|
|
4863
|
+
this.notificationService.warning('Receipt HTML not available');
|
|
4864
|
+
}
|
|
4865
|
+
}
|
|
4866
|
+
},
|
|
4867
|
+
error: (err) => {
|
|
4868
|
+
console.error('Error loading receipt HTML:', err);
|
|
4869
|
+
this.notificationService.error('Failed to load receipt');
|
|
4870
|
+
}
|
|
4871
|
+
});
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4578
4874
|
}
|
|
4579
4875
|
goBack() {
|
|
4580
4876
|
this.router.navigate(['/control-panel/payment']);
|
|
@@ -4619,12 +4915,22 @@ class FeePaymentViewComponent {
|
|
|
4619
4915
|
</div>
|
|
4620
4916
|
</div>
|
|
4621
4917
|
<div class="tw-flex tw-items-center tw-gap-2 tw-flex-shrink-0">
|
|
4918
|
+
@if (!receiptHtml() && !generatingReceipt()) {
|
|
4919
|
+
<button cideEleButton type="button" variant="primary" size="sm" leftIcon="receipt"
|
|
4920
|
+
(btnClick)="generateReceipt()" title="Generate Receipt" [loading]="generatingReceipt()">
|
|
4921
|
+
Generate Receipt
|
|
4922
|
+
</button>
|
|
4923
|
+
}
|
|
4924
|
+
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="visibility"
|
|
4925
|
+
(btnClick)="viewReceipt()" title="View Receipt" [disabled]="generatingReceipt()">
|
|
4926
|
+
View
|
|
4927
|
+
</button>
|
|
4622
4928
|
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="print"
|
|
4623
|
-
(btnClick)="printReceipt()" title="Print Receipt">
|
|
4929
|
+
(btnClick)="printReceipt()" title="Print Receipt" [disabled]="generatingReceipt()">
|
|
4624
4930
|
Print
|
|
4625
4931
|
</button>
|
|
4626
4932
|
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="download"
|
|
4627
|
-
(btnClick)="downloadReceipt()" title="Download Receipt">
|
|
4933
|
+
(btnClick)="downloadReceipt()" title="Download Receipt" [disabled]="generatingReceipt()">
|
|
4628
4934
|
Download
|
|
4629
4935
|
</button>
|
|
4630
4936
|
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="arrow_back"
|
|
@@ -4811,12 +5117,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
4811
5117
|
</div>
|
|
4812
5118
|
</div>
|
|
4813
5119
|
<div class="tw-flex tw-items-center tw-gap-2 tw-flex-shrink-0">
|
|
5120
|
+
@if (!receiptHtml() && !generatingReceipt()) {
|
|
5121
|
+
<button cideEleButton type="button" variant="primary" size="sm" leftIcon="receipt"
|
|
5122
|
+
(btnClick)="generateReceipt()" title="Generate Receipt" [loading]="generatingReceipt()">
|
|
5123
|
+
Generate Receipt
|
|
5124
|
+
</button>
|
|
5125
|
+
}
|
|
5126
|
+
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="visibility"
|
|
5127
|
+
(btnClick)="viewReceipt()" title="View Receipt" [disabled]="generatingReceipt()">
|
|
5128
|
+
View
|
|
5129
|
+
</button>
|
|
4814
5130
|
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="print"
|
|
4815
|
-
(btnClick)="printReceipt()" title="Print Receipt">
|
|
5131
|
+
(btnClick)="printReceipt()" title="Print Receipt" [disabled]="generatingReceipt()">
|
|
4816
5132
|
Print
|
|
4817
5133
|
</button>
|
|
4818
5134
|
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="download"
|
|
4819
|
-
(btnClick)="downloadReceipt()" title="Download Receipt">
|
|
5135
|
+
(btnClick)="downloadReceipt()" title="Download Receipt" [disabled]="generatingReceipt()">
|
|
4820
5136
|
Download
|
|
4821
5137
|
</button>
|
|
4822
5138
|
<button cideEleButton type="button" variant="ghost" size="sm" leftIcon="arrow_back"
|
|
@@ -6230,7 +6546,7 @@ class TemplateDesignerComponent extends CideLytSharedWrapperComponent {
|
|
|
6230
6546
|
});
|
|
6231
6547
|
}
|
|
6232
6548
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TemplateDesignerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6233
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: TemplateDesignerComponent, isStandalone: true, selector: "cide-receipt-template-designer", inputs: { shared_wrapper_setup_param: { classPropertyName: "shared_wrapper_setup_param", publicName: "shared_wrapper_setup_param", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "htmlEditorRef", first: true, predicate: ["htmlEditor"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<!-- Receipt Template Designer -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"shared_wrapper_setup_param()\">\n \n <!-- Action Buttons in Breadcrumb Area -->\n <div breadcrumb-actions class=\"tw-flex tw-items-center tw-gap-2\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"loadTemplates()\" leftIcon=\"folder_open\">\n Load Template\n </button>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"saveTemplate()\" leftIcon=\"save\"\n [disabled]=\"saving() || templateForm.invalid\" [loading]=\"saving()\">\n Save Template\n </button>\n </div>\n\n <!-- Main Content - Three Column Layout -->\n <div class=\"tw-w-full tw-h-full tw-overflow-hidden tw-flex tw-flex-col\" style=\"height: calc(100vh - 120px); max-width: 100vw;\">\n <div class=\"tw-grid tw-grid-cols-12 tw-gap-3 tw-flex-1 tw-min-h-0 tw-p-3\">\n \n <!-- Left Sidebar - Tag Categories & Tags -->\n <div class=\"tw-col-span-12 lg:tw-col-span-3 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden tw-flex tw-flex-col tw-min-w-0 tw-h-full\">\n <!-- Tag Categories Header -->\n <div class=\"tw-p-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-flex-shrink-0\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-mb-2\">Available Tags</h6>\n <form [formGroup]=\"templateForm\">\n <cide-ele-input\n formControlName=\"tag_search\"\n placeholder=\"Search tags...\"\n size=\"sm\"\n leadingIcon=\"search\">\n </cide-ele-input>\n </form>\n </div>\n\n <!-- Category Tabs -->\n <div class=\"tw-flex tw-flex-wrap tw-gap-1 tw-p-2 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-overflow-x-auto\">\n @for (category of tagCategories; track category.id) {\n <button\n type=\"button\"\n class=\"tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded tw-transition-colors tw-whitespace-nowrap\"\n [class.tw-bg-blue-100]=\"activeCategory() === category.id\"\n [class.tw-text-blue-700]=\"activeCategory() === category.id\"\n [class.tw-bg-gray-100]=\"activeCategory() !== category.id\"\n [class.tw-text-gray-700]=\"activeCategory() !== category.id\"\n (click)=\"onCategoryChange(category.id)\"\n [title]=\"category.name\">\n <cide-ele-icon class=\"tw-w-3 tw-h-3 tw-inline-block tw-mr-1\">{{ category.icon }}</cide-ele-icon>\n <span class=\"tw-hidden sm:tw-inline\">{{ category.name }}</span>\n </button>\n }\n </div>\n\n <!-- Tags List -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-2 tw-min-h-0\">\n @if (filteredTags().length > 0) {\n <div class=\"tw-space-y-1\">\n @for (tag of filteredTags(); track tag.code) {\n <button\n type=\"button\"\n class=\"tw-w-full tw-text-left tw-p-2 tw-rounded tw-border tw-border-gray-200 tw-bg-white hover:tw-bg-blue-50 hover:tw-border-blue-300 tw-transition-colors tw-cursor-pointer tw-group\"\n (click)=\"insertTag(tag)\"\n [title]=\"tag.description\">\n <div class=\"tw-flex tw-items-start tw-justify-between tw-gap-2\">\n <div class=\"tw-flex-1 tw-min-w-0\">\n <code class=\"tw-text-xs tw-font-mono tw-text-blue-600 tw-font-semibold tw-block tw-break-all\">\n {{ tag.code }}\n </code>\n <span class=\"tw-text-xs tw-text-gray-600 tw-block tw-mt-1\">{{ tag.description }}</span>\n @if (tag.example) {\n <span class=\"tw-text-xs tw-text-gray-400 tw-block tw-mt-0.5\">e.g., {{ tag.example }}</span>\n }\n </div>\n <cide-ele-icon class=\"tw-w-4 tw-h-4 tw-text-gray-400 group-hover:tw-text-blue-600 tw-flex-shrink-0 tw-mt-0.5\">add_circle</cide-ele-icon>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\n <cide-ele-icon class=\"tw-w-8 tw-h-8 tw-mx-auto tw-mb-2 tw-text-gray-400\">search_off</cide-ele-icon>\n <p class=\"tw-text-xs\">No tags found</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Middle Column - HTML Editor -->\n <div class=\"tw-col-span-12 lg:tw-col-span-5 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col tw-overflow-hidden tw-min-h-0 tw-min-w-0 tw-h-full\">\n <div class=\"tw-p-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-mb-4\">Template Configuration</h6>\n \n <form [formGroup]=\"templateForm\" class=\"tw-space-y-3\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-input\n label=\"Template Name *\"\n formControlName=\"template_name\"\n placeholder=\"e.g., Standard Receipt\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input\n label=\"Template Code *\"\n formControlName=\"template_code\"\n placeholder=\"e.g., STD_RECEIPT_01\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-select\n label=\"Template Type *\"\n formControlName=\"template_type\"\n [options]=\"[{value: 'PAYMENT', label: 'Payment Receipt'}, {value: 'REFUND', label: 'Refund Receipt'}, {value: 'PROVISIONAL', label: 'Provisional Receipt'}]\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-select\n label=\"Template For\"\n formControlName=\"template_for\"\n [options]=\"[{value: 'STUDENT', label: 'Student'}, {value: 'OFFICE', label: 'Office'}, {value: 'BOTH', label: 'Both'}]\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"is_default\" type=\"checkbox\" size=\"sm\"></cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Set as Default Template</span>\n </div>\n </form>\n </div>\n\n <div class=\"tw-flex-1 tw-flex tw-flex-col tw-overflow-hidden tw-min-h-0 tw-h-full\">\n <div class=\"tw-p-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-flex-shrink-0\">\n <div class=\"tw-flex tw-items-center tw-justify-between\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">HTML Template *</h6>\n <span class=\"tw-text-xs tw-text-gray-500\">Click tags on left to insert or paste HTML here</span>\n </div>\n </div>\n <div class=\"tw-flex-1 tw-p-3 tw-overflow-hidden tw-min-h-0 tw-h-full\">\n <form [formGroup]=\"templateForm\" class=\"tw-h-full\">\n <textarea\n #htmlEditor\n formControlName=\"template_html\"\n placeholder=\"Enter HTML template code here... Use tags from the left sidebar or paste your HTML design.\"\n class=\"template-html-editor tw-w-full tw-h-full tw-p-3 tw-border tw-border-gray-300 tw-rounded-md tw-font-mono tw-text-xs tw-leading-relaxed tw-resize-none focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-blue-500 tw-bg-white tw-text-gray-900\"\n spellcheck=\"false\"></textarea>\n </form>\n </div>\n </div>\n </div>\n\n <!-- Right Column - Live Preview -->\n <div class=\"tw-col-span-12 lg:tw-col-span-4 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col tw-overflow-hidden tw-min-w-0 tw-h-full\">\n <div class=\"tw-p-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div class=\"tw-flex tw-items-center tw-justify-between\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">Live Preview</h6>\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-select\n formControlName=\"preview_type\"\n [options]=\"[{value: 'STUDENT', label: 'Student'}, {value: 'OFFICE', label: 'Office'}]\"\n size=\"xs\"\n class=\"tw-w-24\">\n </cide-ele-select>\n <cide-ele-icon class=\"tw-w-4 tw-h-4 tw-text-gray-400\" title=\"Auto-refreshes on template change\">sync</cide-ele-icon>\n </div>\n </div>\n </div>\n \n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-4 tw-bg-gray-50 tw-min-h-0\">\n <div class=\"tw-bg-white tw-shadow-sm tw-rounded tw-p-4\" [innerHTML]=\"previewHtml()\"></div>\n </div>\n </div>\n\n </div>\n </div>\n</cide-lyt-shared-wrapper>\n\n", styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;max-width:100vw;overflow:hidden}:host .template-html-editor{height:100%!important;min-height:0;resize:none;font-family:Courier New,Monaco,Consolas,Menlo,monospace;font-size:13px;line-height:1.6;tab-size:2;-moz-tab-size:2;white-space:pre;overflow-wrap:normal;overflow-x:auto;overflow-y:auto;box-sizing:border-box;width:100%;max-width:100%}:host .template-html-editor::placeholder{color:#9ca3af;font-style:italic}:host .template-html-editor:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}:host .tw-grid{height:100%;max-width:100%;overflow:hidden;min-height:0}:host .tw-overflow-hidden{min-height:0;max-width:100%;overflow:hidden}:host .tw-flex-col{min-height:0;max-width:100%;height:100%}:host [class*=tw-col-span]{display:flex;flex-direction:column;min-height:0;min-width:0;max-width:100%;overflow:hidden;height:100%}:host *{max-width:100%;box-sizing:border-box}:host [breadcrumb-actions]{display:flex;align-items:center;gap:.5rem;flex-wrap:nowrap}button[type=button]:hover{transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}button[type=button]:active{transform:translateY(0)}[innerHTML] img{max-width:100%;height:auto}[innerHTML] table{width:100%;border-collapse:collapse}[innerHTML] *{max-width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }] });
|
|
6549
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: TemplateDesignerComponent, isStandalone: true, selector: "cide-receipt-template-designer", inputs: { shared_wrapper_setup_param: { classPropertyName: "shared_wrapper_setup_param", publicName: "shared_wrapper_setup_param", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "htmlEditorRef", first: true, predicate: ["htmlEditor"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<!-- Receipt Template Designer -->\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"shared_wrapper_setup_param()\">\n \n <!-- Action Buttons in Breadcrumb Area -->\n <div breadcrumb-actions class=\"tw-flex tw-items-center tw-gap-2\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"loadTemplates()\" leftIcon=\"folder_open\">\n Load Template\n </button>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"saveTemplate()\" leftIcon=\"save\"\n [disabled]=\"saving() || templateForm.invalid\" [loading]=\"saving()\">\n Save Template\n </button>\n </div>\n\n <!-- Main Content - Three Column Layout -->\n <div class=\"tw-w-full tw-h-full tw-overflow-hidden tw-flex tw-flex-col\" style=\"height: calc(100vh - 120px); max-width: 100vw;\">\n <div class=\"tw-grid tw-grid-cols-12 tw-gap-3 tw-flex-1 tw-min-h-0 tw-p-3\">\n \n <!-- Left Sidebar - Tag Categories & Tags -->\n <div class=\"tw-col-span-12 lg:tw-col-span-3 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden tw-flex tw-flex-col tw-min-w-0 tw-h-full\">\n <!-- Tag Categories Header -->\n <div class=\"tw-p-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-flex-shrink-0\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-mb-2\">Available Tags</h6>\n <form [formGroup]=\"templateForm\">\n <cide-ele-input\n formControlName=\"tag_search\"\n placeholder=\"Search tags...\"\n size=\"sm\"\n leadingIcon=\"search\">\n </cide-ele-input>\n </form>\n </div>\n\n <!-- Category Tabs -->\n <div class=\"tw-flex tw-flex-wrap tw-gap-1 tw-p-2 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-overflow-x-auto\">\n @for (category of tagCategories; track category.id) {\n <button\n type=\"button\"\n class=\"tw-px-2 tw-py-1 tw-text-xs tw-font-medium tw-rounded tw-transition-colors tw-whitespace-nowrap\"\n [class.tw-bg-blue-100]=\"activeCategory() === category.id\"\n [class.tw-text-blue-700]=\"activeCategory() === category.id\"\n [class.tw-bg-gray-100]=\"activeCategory() !== category.id\"\n [class.tw-text-gray-700]=\"activeCategory() !== category.id\"\n (click)=\"onCategoryChange(category.id)\"\n [title]=\"category.name\">\n <cide-ele-icon class=\"tw-w-3 tw-h-3 tw-inline-block tw-mr-1\">{{ category.icon }}</cide-ele-icon>\n <span class=\"tw-hidden sm:tw-inline\">{{ category.name }}</span>\n </button>\n }\n </div>\n\n <!-- Tags List -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-2 tw-min-h-0\">\n @if (filteredTags().length > 0) {\n <div class=\"tw-space-y-1\">\n @for (tag of filteredTags(); track tag.code) {\n <button\n type=\"button\"\n class=\"tw-w-full tw-text-left tw-p-2 tw-rounded tw-border tw-border-gray-200 tw-bg-white hover:tw-bg-blue-50 hover:tw-border-blue-300 tw-transition-colors tw-cursor-pointer tw-group\"\n (click)=\"insertTag(tag)\"\n [title]=\"tag.description\">\n <div class=\"tw-flex tw-items-start tw-justify-between tw-gap-2\">\n <div class=\"tw-flex-1 tw-min-w-0\">\n <code class=\"tw-text-xs tw-font-mono tw-text-blue-600 tw-font-semibold tw-block tw-break-all\">\n {{ tag.code }}\n </code>\n <span class=\"tw-text-xs tw-text-gray-600 tw-block tw-mt-1\">{{ tag.description }}</span>\n @if (tag.example) {\n <span class=\"tw-text-xs tw-text-gray-400 tw-block tw-mt-0.5\">e.g., {{ tag.example }}</span>\n }\n </div>\n <cide-ele-icon class=\"tw-w-4 tw-h-4 tw-text-gray-400 group-hover:tw-text-blue-600 tw-flex-shrink-0 tw-mt-0.5\">add_circle</cide-ele-icon>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\n <cide-ele-icon class=\"tw-w-8 tw-h-8 tw-mx-auto tw-mb-2 tw-text-gray-400\">search_off</cide-ele-icon>\n <p class=\"tw-text-xs\">No tags found</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Middle Column - HTML Editor -->\n <div class=\"tw-col-span-12 lg:tw-col-span-5 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col tw-overflow-hidden tw-min-h-0 tw-min-w-0 tw-h-full\">\n <div class=\"tw-p-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-mb-4\">Template Configuration</h6>\n \n <form [formGroup]=\"templateForm\" class=\"tw-space-y-3\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-input\n label=\"Template Name *\"\n formControlName=\"template_name\"\n placeholder=\"e.g., Standard Receipt\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input\n label=\"Template Code *\"\n formControlName=\"template_code\"\n placeholder=\"e.g., STD_RECEIPT_01\"\n size=\"sm\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-select\n label=\"Template Type *\"\n formControlName=\"template_type\"\n [options]=\"[{value: 'PAYMENT', label: 'Payment Receipt'}, {value: 'REFUND', label: 'Refund Receipt'}, {value: 'PROVISIONAL', label: 'Provisional Receipt'}]\"\n size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-select\n label=\"Template For\"\n formControlName=\"template_for\"\n [options]=\"[{value: 'STUDENT', label: 'Student'}, {value: 'OFFICE', label: 'Office'}, {value: 'BOTH', label: 'Both'}]\"\n size=\"sm\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-2 tw-bg-gray-50 tw-rounded\">\n <cide-ele-input formControlName=\"is_default\" type=\"checkbox\" size=\"sm\"></cide-ele-input>\n <span class=\"tw-text-xs tw-text-gray-700\">Set as Default Template</span>\n </div>\n </form>\n </div>\n\n <div class=\"tw-flex-1 tw-flex tw-flex-col tw-overflow-hidden tw-min-h-0 tw-h-full\">\n <div class=\"tw-p-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-flex-shrink-0\">\n <div class=\"tw-flex tw-items-center tw-justify-between\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">HTML Template *</h6>\n <span class=\"tw-text-xs tw-text-gray-500\">Click tags on left to insert or paste HTML here</span>\n </div>\n </div>\n <div class=\"tw-flex-1 tw-p-3 tw-overflow-hidden tw-min-h-0 tw-h-full\">\n <form [formGroup]=\"templateForm\" class=\"tw-h-full\">\n <textarea\n #htmlEditor\n formControlName=\"template_html\"\n placeholder=\"Enter HTML template code here... Use tags from the left sidebar or paste your HTML design.\"\n class=\"template-html-editor tw-w-full tw-h-full tw-p-3 tw-border tw-border-gray-300 tw-rounded-md tw-font-mono tw-text-xs tw-leading-relaxed tw-resize-none focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-blue-500 tw-bg-white tw-text-gray-900\"\n spellcheck=\"false\"></textarea>\n </form>\n </div>\n </div>\n </div>\n\n <!-- Right Column - Live Preview -->\n <div class=\"tw-col-span-12 lg:tw-col-span-4 tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-flex tw-flex-col tw-overflow-hidden tw-min-w-0 tw-h-full\">\n <div class=\"tw-p-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div class=\"tw-flex tw-items-center tw-justify-between\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">Live Preview</h6>\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-select\n formControlName=\"preview_type\"\n [options]=\"[{value: 'STUDENT', label: 'Student'}, {value: 'OFFICE', label: 'Office'}]\"\n size=\"xs\"\n class=\"tw-w-24\">\n </cide-ele-select>\n <cide-ele-icon class=\"tw-w-4 tw-h-4 tw-text-gray-400\" title=\"Auto-refreshes on template change\">sync</cide-ele-icon>\n </div>\n </div>\n </div>\n \n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-4 tw-bg-gray-50 tw-min-h-0\">\n <div class=\"tw-bg-white tw-shadow-sm tw-rounded tw-p-4\" [innerHTML]=\"previewHtml()\"></div>\n </div>\n </div>\n\n </div>\n </div>\n</cide-lyt-shared-wrapper>\n\n", styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;max-width:100vw;overflow:hidden}:host .template-html-editor{height:100%!important;min-height:0;resize:none;font-family:Courier New,Monaco,Consolas,Menlo,monospace;font-size:13px;line-height:1.6;tab-size:2;-moz-tab-size:2;white-space:pre;overflow-wrap:normal;overflow-x:auto;overflow-y:auto;box-sizing:border-box;width:100%;max-width:100%}:host .template-html-editor::placeholder{color:#9ca3af;font-style:italic}:host .template-html-editor:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}:host .tw-grid{height:100%;max-width:100%;overflow:hidden;min-height:0}:host .tw-overflow-hidden{min-height:0;max-width:100%;overflow:hidden}:host .tw-flex-col{min-height:0;max-width:100%;height:100%}:host [class*=tw-col-span]{display:flex;flex-direction:column;min-height:0;min-width:0;max-width:100%;overflow:hidden;height:100%}:host *{max-width:100%;box-sizing:border-box}:host [breadcrumb-actions]{display:flex;align-items:center;gap:.5rem;flex-wrap:nowrap}button[type=button]:hover{transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}button[type=button]:active{transform:translateY(0)}[innerHTML] img{max-width:100%;height:auto}[innerHTML] table{width:100%;border-collapse:collapse}[innerHTML] *{max-width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }] });
|
|
6234
6550
|
}
|
|
6235
6551
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TemplateDesignerComponent, decorators: [{
|
|
6236
6552
|
type: Component,
|
|
@@ -6610,7 +6926,7 @@ class CollectionReportComponent {
|
|
|
6610
6926
|
return `₹${amount.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
6611
6927
|
}
|
|
6612
6928
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CollectionReportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6613
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CollectionReportComponent, isStandalone: true, selector: "cide-collection-report", ngImport: i0, template: "<!-- Collection Report Container -->\r\n<div class=\"tw-w-full tw-h-full\">\r\n <div class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">assessment</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Fee Collection Report</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-items-center tw-gap-3\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"exportToPDF()\" leftIcon=\"picture_as_pdf\">\r\n Export PDF\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"exportToExcel()\" leftIcon=\"table_chart\">\r\n Export Excel\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Section -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <form [formGroup]=\"filterForm\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-5 tw-gap-4\">\r\n <cide-ele-input\r\n label=\"Date From\"\r\n formControlName=\"date_from\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input\r\n label=\"Date To\"\r\n formControlName=\"date_to\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-select\r\n label=\"Academic Year\"\r\n formControlName=\"academic_year\"\r\n [options]=\"academicYearOptions()\"\r\n size=\"sm\"\r\n placeholder=\"All Years\">\r\n </cide-ele-select>\r\n\r\n <cide-ele-select\r\n label=\"Class/Program\"\r\n formControlName=\"class_program\"\r\n [options]=\"classOptions()\"\r\n size=\"sm\"\r\n placeholder=\"All Classes\">\r\n </cide-ele-select>\r\n\r\n <cide-ele-select\r\n label=\"Payment Mode\"\r\n formControlName=\"payment_mode\"\r\n [options]=\"paymentModeOptions\"\r\n size=\"sm\"\r\n placeholder=\"All Modes\">\r\n </cide-ele-select>\r\n </div>\r\n\r\n <div class=\"tw-flex tw-justify-end\">\r\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"applyFilters()\" leftIcon=\"search\"\r\n [disabled]=\"loading()\" [loading]=\"loading()\">\r\n Generate Report\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Summary Cards -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4 tw-border-b tw-border-gray-200\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4\">\r\n <!-- Total Collection Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-green-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-green-600 tw-w-6 tw-h-6\">account_balance_wallet</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Total Collection</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-green-600\">{{ formatCurrency(summary().total_collection) }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Total Receipts Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-blue-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-6 tw-h-6\">receipt</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Total Receipts</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-blue-600\">{{ summary().total_receipts }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Online Payments Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-cyan-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-cyan-600 tw-w-6 tw-h-6\">language</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Online Payments</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-cyan-600\">{{ formatCurrency(summary().online_payments) }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Cash Payments Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-yellow-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-yellow-600 tw-w-6 tw-h-6\">money</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Cash Payments</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-yellow-600\">{{ formatCurrency(summary().cash_payments) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Main Content Area -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4\">\r\n <div class=\"tw-space-y-6\">\r\n \r\n <!-- Collection by Date Section -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Collection by Date</h6>\r\n </div>\r\n <div class=\"tw-p-4\">\r\n <cide-ele-data-grid \r\n [config]=\"dateGridConfig()\" \r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n \r\n <!-- Footer Totals -->\r\n <div class=\"tw-mt-4 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-grid tw-grid-cols-7 tw-gap-4 tw-text-sm\">\r\n <div class=\"tw-font-semibold tw-text-gray-900\">TOTAL</div>\r\n <div class=\"tw-font-semibold tw-text-center tw-text-gray-900\">{{ totalReceipts() }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalCash()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalOnline()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalCheque()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalOther()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-green-600\">{{ formatCurrency(grandTotal()) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Collection by Class Section -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Collection by Class/Program</h6>\r\n </div>\r\n <div class=\"tw-p-4\">\r\n <cide-ele-data-grid \r\n [config]=\"classGridConfig()\" \r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [":host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }] });
|
|
6929
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CollectionReportComponent, isStandalone: true, selector: "cide-collection-report", ngImport: i0, template: "<!-- Collection Report Container -->\r\n<div class=\"tw-w-full tw-h-full\">\r\n <div class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">assessment</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Fee Collection Report</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-items-center tw-gap-3\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"exportToPDF()\" leftIcon=\"picture_as_pdf\">\r\n Export PDF\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"exportToExcel()\" leftIcon=\"table_chart\">\r\n Export Excel\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Section -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <form [formGroup]=\"filterForm\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-5 tw-gap-4\">\r\n <cide-ele-input\r\n label=\"Date From\"\r\n formControlName=\"date_from\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-input\r\n label=\"Date To\"\r\n formControlName=\"date_to\"\r\n type=\"date\"\r\n size=\"sm\">\r\n </cide-ele-input>\r\n\r\n <cide-ele-select\r\n label=\"Academic Year\"\r\n formControlName=\"academic_year\"\r\n [options]=\"academicYearOptions()\"\r\n size=\"sm\"\r\n placeholder=\"All Years\">\r\n </cide-ele-select>\r\n\r\n <cide-ele-select\r\n label=\"Class/Program\"\r\n formControlName=\"class_program\"\r\n [options]=\"classOptions()\"\r\n size=\"sm\"\r\n placeholder=\"All Classes\">\r\n </cide-ele-select>\r\n\r\n <cide-ele-select\r\n label=\"Payment Mode\"\r\n formControlName=\"payment_mode\"\r\n [options]=\"paymentModeOptions\"\r\n size=\"sm\"\r\n placeholder=\"All Modes\">\r\n </cide-ele-select>\r\n </div>\r\n\r\n <div class=\"tw-flex tw-justify-end\">\r\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"applyFilters()\" leftIcon=\"search\"\r\n [disabled]=\"loading()\" [loading]=\"loading()\">\r\n Generate Report\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Summary Cards -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4 tw-border-b tw-border-gray-200\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4\">\r\n <!-- Total Collection Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-green-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-green-600 tw-w-6 tw-h-6\">account_balance_wallet</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Total Collection</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-green-600\">{{ formatCurrency(summary().total_collection) }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Total Receipts Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-blue-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-6 tw-h-6\">receipt</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Total Receipts</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-blue-600\">{{ summary().total_receipts }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Online Payments Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-cyan-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-cyan-600 tw-w-6 tw-h-6\">language</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Online Payments</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-cyan-600\">{{ formatCurrency(summary().online_payments) }}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Cash Payments Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-p-4 tw-flex tw-items-center tw-gap-4\">\r\n <div class=\"tw-bg-yellow-100 tw-rounded-full tw-p-3\">\r\n <cide-ele-icon class=\"tw-text-yellow-600 tw-w-6 tw-h-6\">money</cide-ele-icon>\r\n </div>\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-text-xs tw-text-gray-600 tw-mb-1\">Cash Payments</div>\r\n <div class=\"tw-text-xl tw-font-bold tw-text-yellow-600\">{{ formatCurrency(summary().cash_payments) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Main Content Area -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4\">\r\n <div class=\"tw-space-y-6\">\r\n \r\n <!-- Collection by Date Section -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Collection by Date</h6>\r\n </div>\r\n <div class=\"tw-p-4\">\r\n <cide-ele-data-grid \r\n [config]=\"dateGridConfig()\" \r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n \r\n <!-- Footer Totals -->\r\n <div class=\"tw-mt-4 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-grid tw-grid-cols-7 tw-gap-4 tw-text-sm\">\r\n <div class=\"tw-font-semibold tw-text-gray-900\">TOTAL</div>\r\n <div class=\"tw-font-semibold tw-text-center tw-text-gray-900\">{{ totalReceipts() }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalCash()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalOnline()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalCheque()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-gray-900\">{{ formatCurrency(totalOther()) }}</div>\r\n <div class=\"tw-font-semibold tw-text-right tw-text-green-600\">{{ formatCurrency(grandTotal()) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Collection by Class Section -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Collection by Class/Program</h6>\r\n </div>\r\n <div class=\"tw-p-4\">\r\n <cide-ele-data-grid \r\n [config]=\"classGridConfig()\" \r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [":host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }] });
|
|
6614
6930
|
}
|
|
6615
6931
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CollectionReportComponent, decorators: [{
|
|
6616
6932
|
type: Component,
|
|
@@ -6633,6 +6949,11 @@ var collectionReport_component = /*#__PURE__*/Object.freeze({
|
|
|
6633
6949
|
class MyFeeStatementComponent {
|
|
6634
6950
|
router = inject(Router);
|
|
6635
6951
|
notificationService = inject(NotificationService);
|
|
6952
|
+
http = inject(HttpClient);
|
|
6953
|
+
appStateHelper = inject(AppStateHelperService);
|
|
6954
|
+
feeAssignmentService = inject(CideFeeFeeAssignmentService);
|
|
6955
|
+
feePaymentService = inject(CideFeeFeePaymentService);
|
|
6956
|
+
rightsService = inject(RightsService);
|
|
6636
6957
|
statusRendererTemplate = viewChild.required('statusRendererTemplate');
|
|
6637
6958
|
actionsRendererTemplate = viewChild.required('actionsRendererTemplate');
|
|
6638
6959
|
paymentHistoryRendererTemplate = viewChild.required('paymentHistoryRendererTemplate');
|
|
@@ -6844,79 +7165,193 @@ class MyFeeStatementComponent {
|
|
|
6844
7165
|
paymentHistoryRenderer: this.paymentHistoryRendererTemplate()
|
|
6845
7166
|
}), ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
|
|
6846
7167
|
ngOnInit() {
|
|
7168
|
+
// Initialize rights for fee statement (view-only)
|
|
7169
|
+
this.rightsService.initializeRights('fee_statement');
|
|
6847
7170
|
this.loadFeeDetails();
|
|
6848
7171
|
this.loadPaymentHistory();
|
|
6849
7172
|
}
|
|
6850
7173
|
loadFeeDetails() {
|
|
6851
7174
|
this.loading.set(true);
|
|
6852
|
-
//
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
this.
|
|
6856
|
-
{
|
|
6857
|
-
_id: '1',
|
|
6858
|
-
fee_head: 'Tuition Fee - Term 1',
|
|
6859
|
-
amount: 30000,
|
|
6860
|
-
discount: 2000,
|
|
6861
|
-
net_amount: 28000,
|
|
6862
|
-
paid: 28000,
|
|
6863
|
-
outstanding: 0,
|
|
6864
|
-
due_date: new Date(today.getFullYear(), today.getMonth() - 1, 15),
|
|
6865
|
-
status: 'PAID'
|
|
6866
|
-
},
|
|
6867
|
-
{
|
|
6868
|
-
_id: '2',
|
|
6869
|
-
fee_head: 'Exam Fee',
|
|
6870
|
-
amount: 5000,
|
|
6871
|
-
discount: 0,
|
|
6872
|
-
net_amount: 5000,
|
|
6873
|
-
paid: 3000,
|
|
6874
|
-
outstanding: 2000,
|
|
6875
|
-
due_date: new Date(today.getFullYear(), today.getMonth(), 5),
|
|
6876
|
-
status: 'PARTIALLY_PAID'
|
|
6877
|
-
},
|
|
6878
|
-
{
|
|
6879
|
-
_id: '3',
|
|
6880
|
-
fee_head: 'Lab Fee',
|
|
6881
|
-
amount: 10000,
|
|
6882
|
-
discount: 0,
|
|
6883
|
-
net_amount: 10000,
|
|
6884
|
-
paid: 0,
|
|
6885
|
-
outstanding: 10000,
|
|
6886
|
-
due_date: new Date(today.getFullYear(), today.getMonth() - 1, 20),
|
|
6887
|
-
status: 'OVERDUE'
|
|
6888
|
-
}
|
|
6889
|
-
]);
|
|
7175
|
+
// Get current user ID from app state
|
|
7176
|
+
const currentUser = this.appStateHelper.getCurrentUser();
|
|
7177
|
+
if (!currentUser?._id) {
|
|
7178
|
+
this.notificationService.error('User not authenticated');
|
|
6890
7179
|
this.loading.set(false);
|
|
6891
|
-
|
|
7180
|
+
return;
|
|
7181
|
+
}
|
|
7182
|
+
// Get student ID from admission form using user_id
|
|
7183
|
+
const userId = currentUser._id;
|
|
7184
|
+
const queryParams = new URLSearchParams({ admap_user_id_auth: userId }).toString();
|
|
7185
|
+
const admissionUrl = `${cidePath}${coreRoutesUrl}/admission/${queryParams}`;
|
|
7186
|
+
this.http.get(admissionUrl).subscribe({
|
|
7187
|
+
next: (admissionResponse) => {
|
|
7188
|
+
let studentId = null;
|
|
7189
|
+
let admissionData = null;
|
|
7190
|
+
if (admissionResponse?.success && admissionResponse?.data) {
|
|
7191
|
+
admissionData = Array.isArray(admissionResponse.data)
|
|
7192
|
+
? admissionResponse.data[0]
|
|
7193
|
+
: admissionResponse.data;
|
|
7194
|
+
studentId = admissionData?.admap_student_id || null;
|
|
7195
|
+
// Update student info
|
|
7196
|
+
if (admissionData) {
|
|
7197
|
+
const studentName = `${admissionData.admap_first_name || ''} ${admissionData.admap_middle_name || ''} ${admissionData.admap_last_name || ''}`.trim();
|
|
7198
|
+
this.studentInfo.set({
|
|
7199
|
+
id: studentId || 'N/A',
|
|
7200
|
+
name: studentName || 'N/A',
|
|
7201
|
+
class: admissionData.admap_class_program_name || 'N/A',
|
|
7202
|
+
section: admissionData.admap_program_term_section_name || 'N/A',
|
|
7203
|
+
avatar: admissionData.admap_photo_id_cyfm || ''
|
|
7204
|
+
});
|
|
7205
|
+
}
|
|
7206
|
+
}
|
|
7207
|
+
if (!studentId) {
|
|
7208
|
+
this.notificationService.warning('Student ID not found. Please ensure your admission is confirmed.');
|
|
7209
|
+
this.loading.set(false);
|
|
7210
|
+
return;
|
|
7211
|
+
}
|
|
7212
|
+
// Load fee assignments for this student
|
|
7213
|
+
const payload = {
|
|
7214
|
+
feeas_student_id: studentId,
|
|
7215
|
+
pageSize: 100 // Get all assignments
|
|
7216
|
+
};
|
|
7217
|
+
this.feeAssignmentService.getFeeAssignmentList(payload).subscribe({
|
|
7218
|
+
next: (response) => {
|
|
7219
|
+
if (response?.success && response?.data) {
|
|
7220
|
+
const today = new Date();
|
|
7221
|
+
const feeDetailsData = response.data.map((assignment) => {
|
|
7222
|
+
const originalAmount = assignment.feeas_original_amount || assignment.feeas_final_amount || 0;
|
|
7223
|
+
const discountAmount = assignment.feeas_discount_amount || 0;
|
|
7224
|
+
const netAmount = assignment.feeas_final_amount || (originalAmount - discountAmount);
|
|
7225
|
+
const paidAmount = assignment.feeas_amount_paid || assignment.feeas_paid_amount || 0;
|
|
7226
|
+
const outstandingAmount = assignment.feeas_outstanding_amount ||
|
|
7227
|
+
assignment.feeas_amount_remaining ||
|
|
7228
|
+
(netAmount - paidAmount);
|
|
7229
|
+
const dueDate = assignment.feeas_due_date ? new Date(assignment.feeas_due_date) : new Date();
|
|
7230
|
+
const isOverdue = dueDate < today && outstandingAmount > 0;
|
|
7231
|
+
let status = 'PENDING';
|
|
7232
|
+
if (outstandingAmount <= 0) {
|
|
7233
|
+
status = 'PAID';
|
|
7234
|
+
}
|
|
7235
|
+
else if (paidAmount > 0) {
|
|
7236
|
+
status = isOverdue ? 'OVERDUE' : 'PARTIALLY_PAID';
|
|
7237
|
+
}
|
|
7238
|
+
else {
|
|
7239
|
+
status = isOverdue ? 'OVERDUE' : 'PENDING';
|
|
7240
|
+
}
|
|
7241
|
+
return {
|
|
7242
|
+
_id: assignment._id,
|
|
7243
|
+
fee_head: assignment.feeas_fee_name || 'Fee',
|
|
7244
|
+
amount: originalAmount,
|
|
7245
|
+
discount: discountAmount,
|
|
7246
|
+
net_amount: netAmount,
|
|
7247
|
+
paid: paidAmount,
|
|
7248
|
+
outstanding: outstandingAmount,
|
|
7249
|
+
due_date: dueDate,
|
|
7250
|
+
status: status
|
|
7251
|
+
};
|
|
7252
|
+
});
|
|
7253
|
+
this.feeDetails.set(feeDetailsData);
|
|
7254
|
+
}
|
|
7255
|
+
else {
|
|
7256
|
+
this.feeDetails.set([]);
|
|
7257
|
+
}
|
|
7258
|
+
},
|
|
7259
|
+
error: (err) => {
|
|
7260
|
+
console.error('Error loading fee details:', err);
|
|
7261
|
+
this.notificationService.error('Failed to load fee details');
|
|
7262
|
+
this.feeDetails.set([]);
|
|
7263
|
+
this.loading.set(false);
|
|
7264
|
+
},
|
|
7265
|
+
complete: () => {
|
|
7266
|
+
this.loading.set(false);
|
|
7267
|
+
}
|
|
7268
|
+
});
|
|
7269
|
+
},
|
|
7270
|
+
error: (err) => {
|
|
7271
|
+
console.error('Error loading admission data:', err);
|
|
7272
|
+
this.notificationService.error('Failed to load student information');
|
|
7273
|
+
this.loading.set(false);
|
|
7274
|
+
}
|
|
7275
|
+
});
|
|
6892
7276
|
}
|
|
6893
7277
|
loadPaymentHistory() {
|
|
6894
|
-
//
|
|
6895
|
-
this.
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
7278
|
+
// Get current user ID from app state
|
|
7279
|
+
const currentUser = this.appStateHelper.getCurrentUser();
|
|
7280
|
+
if (!currentUser?._id) {
|
|
7281
|
+
return;
|
|
7282
|
+
}
|
|
7283
|
+
// Get student ID from admission form using user_id
|
|
7284
|
+
const userId = currentUser._id;
|
|
7285
|
+
const queryParams = new URLSearchParams({ admap_user_id_auth: userId }).toString();
|
|
7286
|
+
const admissionUrl = `${cidePath}${coreRoutesUrl}/admission/${queryParams}`;
|
|
7287
|
+
this.http.get(admissionUrl).subscribe({
|
|
7288
|
+
next: (admissionResponse) => {
|
|
7289
|
+
let studentId = null;
|
|
7290
|
+
if (admissionResponse?.success && admissionResponse?.data) {
|
|
7291
|
+
const admissionData = Array.isArray(admissionResponse.data)
|
|
7292
|
+
? admissionResponse.data[0]
|
|
7293
|
+
: admissionResponse.data;
|
|
7294
|
+
studentId = admissionData?.admap_student_id || null;
|
|
7295
|
+
}
|
|
7296
|
+
if (!studentId) {
|
|
7297
|
+
return;
|
|
7298
|
+
}
|
|
7299
|
+
// Load payment history for this student
|
|
7300
|
+
const payload = {
|
|
7301
|
+
feepay_student_id: studentId,
|
|
7302
|
+
pageSize: 100 // Get all payments
|
|
7303
|
+
};
|
|
7304
|
+
this.feePaymentService.getFeePaymentList(payload).subscribe({
|
|
7305
|
+
next: (response) => {
|
|
7306
|
+
if (response?.success && response?.data) {
|
|
7307
|
+
const paymentHistoryData = response.data.map((payment) => ({
|
|
7308
|
+
_id: payment._id,
|
|
7309
|
+
receipt_number: payment.feepay_receipt_number || 'N/A',
|
|
7310
|
+
date: payment.feepay_payment_date ? new Date(payment.feepay_payment_date) : new Date(),
|
|
7311
|
+
amount: payment.feepay_total_amount || 0,
|
|
7312
|
+
mode: payment.feepay_payment_mode || 'N/A',
|
|
7313
|
+
reference: payment.feepay_transaction_reference ||
|
|
7314
|
+
payment.feepay_cheque_number ||
|
|
7315
|
+
payment.feepay_payment_reference ||
|
|
7316
|
+
'N/A'
|
|
7317
|
+
}));
|
|
7318
|
+
this.paymentHistory.set(paymentHistoryData);
|
|
7319
|
+
}
|
|
7320
|
+
else {
|
|
7321
|
+
this.paymentHistory.set([]);
|
|
7322
|
+
}
|
|
7323
|
+
},
|
|
7324
|
+
error: (err) => {
|
|
7325
|
+
console.error('Error loading payment history:', err);
|
|
7326
|
+
this.notificationService.error('Failed to load payment history');
|
|
7327
|
+
this.paymentHistory.set([]);
|
|
7328
|
+
}
|
|
7329
|
+
});
|
|
6903
7330
|
},
|
|
6904
|
-
{
|
|
6905
|
-
|
|
6906
|
-
receipt_number: 'RCP-2024-001235',
|
|
6907
|
-
date: new Date('2024-11-05'),
|
|
6908
|
-
amount: 3000,
|
|
6909
|
-
mode: 'Online',
|
|
6910
|
-
reference: 'TXN-123456'
|
|
7331
|
+
error: (err) => {
|
|
7332
|
+
console.error('Error loading admission data for payment history:', err);
|
|
6911
7333
|
}
|
|
6912
|
-
|
|
7334
|
+
});
|
|
6913
7335
|
}
|
|
6914
7336
|
makePayment() {
|
|
6915
|
-
this.router.navigate(['/control-panel/payment']);
|
|
7337
|
+
this.router.navigate(['/control-panel/fees/payment']);
|
|
6916
7338
|
}
|
|
6917
7339
|
downloadReceipt(payment) {
|
|
7340
|
+
if (!payment._id) {
|
|
7341
|
+
this.notificationService.error('Payment ID not found');
|
|
7342
|
+
return;
|
|
7343
|
+
}
|
|
7344
|
+
// Get receipt PDF from API
|
|
7345
|
+
const receiptUrl = cidePath.join([
|
|
7346
|
+
hostManagerRoutesUrl.cideSuiteHost,
|
|
7347
|
+
'fees',
|
|
7348
|
+
'receipt',
|
|
7349
|
+
payment._id,
|
|
7350
|
+
'pdf'
|
|
7351
|
+
]);
|
|
7352
|
+
// Open in new tab for download
|
|
7353
|
+
window.open(receiptUrl, '_blank');
|
|
6918
7354
|
this.notificationService.info(`Downloading receipt: ${payment.receipt_number}`);
|
|
6919
|
-
// TODO: Implement receipt download
|
|
6920
7355
|
}
|
|
6921
7356
|
isOverdue(fee) {
|
|
6922
7357
|
return new Date(fee.due_date) < new Date() && fee.outstanding > 0;
|
|
@@ -6952,6 +7387,8 @@ class MyOnlinePaymentComponent {
|
|
|
6952
7387
|
notificationService = inject(NotificationService);
|
|
6953
7388
|
confirmationService = inject(ConfirmationService);
|
|
6954
7389
|
feeAssignmentService = inject(CideFeeFeeAssignmentService);
|
|
7390
|
+
appStateHelper = inject(AppStateHelperService);
|
|
7391
|
+
http = inject(HttpClient);
|
|
6955
7392
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
6956
7393
|
submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : []));
|
|
6957
7394
|
selectedFees = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedFees" }] : []));
|
|
@@ -6993,56 +7430,95 @@ class MyOnlinePaymentComponent {
|
|
|
6993
7430
|
}, ...(ngDevMode ? [{ debugName: "convenienceFee" }] : []));
|
|
6994
7431
|
totalPayable = computed(() => this.subtotal() + this.convenienceFee(), ...(ngDevMode ? [{ debugName: "totalPayable" }] : []));
|
|
6995
7432
|
selectedPaymentMethod = computed(() => this.paymentForm.get('payment_method')?.value, ...(ngDevMode ? [{ debugName: "selectedPaymentMethod" }] : []));
|
|
7433
|
+
studentId = null;
|
|
7434
|
+
entityId = null;
|
|
7435
|
+
academicYearId = null;
|
|
6996
7436
|
ngOnInit() {
|
|
6997
7437
|
this.loadOutstandingFees();
|
|
6998
7438
|
}
|
|
6999
7439
|
loadOutstandingFees() {
|
|
7000
7440
|
this.loading.set(true);
|
|
7001
|
-
//
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
.
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
return {
|
|
7026
|
-
id: assignment._id || '',
|
|
7027
|
-
fee_head: assignment.feeas_fee_name || 'Fee',
|
|
7028
|
-
due_date: dueDate || new Date(),
|
|
7029
|
-
outstanding: outstanding,
|
|
7030
|
-
late_fee: lateFee,
|
|
7031
|
-
is_overdue: dueDate ? dueDate < today : false
|
|
7032
|
-
};
|
|
7033
|
-
});
|
|
7034
|
-
this.outstandingFees.set(outstandingFees);
|
|
7441
|
+
// Get current user ID from app state
|
|
7442
|
+
const currentUser = this.appStateHelper.getCurrentUser();
|
|
7443
|
+
if (!currentUser?._id) {
|
|
7444
|
+
this.notificationService.error('User not authenticated');
|
|
7445
|
+
this.loading.set(false);
|
|
7446
|
+
return;
|
|
7447
|
+
}
|
|
7448
|
+
// Get student ID from admission form using user_id
|
|
7449
|
+
const userId = currentUser._id;
|
|
7450
|
+
// Use list endpoint with filter for admap_user_id_auth
|
|
7451
|
+
const queryParams = new URLSearchParams({ admap_user_id_auth: userId }).toString();
|
|
7452
|
+
const admissionUrl = `${cidePath}${coreRoutesUrl}/admission/${queryParams}`;
|
|
7453
|
+
this.http.get(admissionUrl).subscribe({
|
|
7454
|
+
next: (admissionResponse) => {
|
|
7455
|
+
let studentId = null;
|
|
7456
|
+
if (admissionResponse?.success && admissionResponse?.data) {
|
|
7457
|
+
// Get student ID from admission form (data might be array or single object)
|
|
7458
|
+
const admissionData = Array.isArray(admissionResponse.data)
|
|
7459
|
+
? admissionResponse.data[0]
|
|
7460
|
+
: admissionResponse.data;
|
|
7461
|
+
studentId = admissionData?.admap_student_id || null;
|
|
7462
|
+
this.studentId = studentId;
|
|
7463
|
+
this.entityId = admissionData?.admap_entity_id_syen || null;
|
|
7464
|
+
this.academicYearId = admissionData?.admap_academic_year_id_acayr || null;
|
|
7035
7465
|
}
|
|
7036
|
-
|
|
7037
|
-
this.
|
|
7466
|
+
if (!studentId) {
|
|
7467
|
+
this.notificationService.warning('Student ID not found. Please ensure your admission is confirmed.');
|
|
7468
|
+
this.loading.set(false);
|
|
7469
|
+
return;
|
|
7038
7470
|
}
|
|
7471
|
+
// Get outstanding fees from fee assignments
|
|
7472
|
+
const payload = {
|
|
7473
|
+
feeas_student_id: studentId,
|
|
7474
|
+
feeas_payment_status: 'PENDING' // Get only pending or partially paid assignments
|
|
7475
|
+
// Note: feeas_payment_status field name matches the schema
|
|
7476
|
+
};
|
|
7477
|
+
this.feeAssignmentService.getFeeAssignmentList(payload).subscribe({
|
|
7478
|
+
next: (response) => {
|
|
7479
|
+
if (response?.success && response?.data) {
|
|
7480
|
+
const today = new Date();
|
|
7481
|
+
const outstandingFees = response.data
|
|
7482
|
+
.filter((assignment) => {
|
|
7483
|
+
// Only include assignments with outstanding amount > 0
|
|
7484
|
+
const outstanding = assignment.feeas_amount_remaining ||
|
|
7485
|
+
(assignment.feeas_final_amount || 0) - (assignment.feeas_amount_paid || 0);
|
|
7486
|
+
return outstanding > 0;
|
|
7487
|
+
})
|
|
7488
|
+
.map((assignment) => {
|
|
7489
|
+
const dueDate = assignment.feeas_due_date ? new Date(assignment.feeas_due_date) : null;
|
|
7490
|
+
const outstanding = assignment.feeas_amount_remaining ||
|
|
7491
|
+
(assignment.feeas_final_amount || 0) - (assignment.feeas_amount_paid || 0);
|
|
7492
|
+
const lateFee = assignment.feeas_late_fee_applied || 0;
|
|
7493
|
+
return {
|
|
7494
|
+
id: assignment._id || '',
|
|
7495
|
+
fee_head: assignment.feeas_fee_name || 'Fee',
|
|
7496
|
+
due_date: dueDate || new Date(),
|
|
7497
|
+
outstanding: outstanding,
|
|
7498
|
+
late_fee: lateFee,
|
|
7499
|
+
is_overdue: dueDate ? dueDate < today : false
|
|
7500
|
+
};
|
|
7501
|
+
});
|
|
7502
|
+
this.outstandingFees.set(outstandingFees);
|
|
7503
|
+
}
|
|
7504
|
+
else {
|
|
7505
|
+
this.outstandingFees.set([]);
|
|
7506
|
+
}
|
|
7507
|
+
},
|
|
7508
|
+
error: (err) => {
|
|
7509
|
+
console.error('Error loading outstanding fees:', err);
|
|
7510
|
+
this.notificationService.error('Failed to load outstanding fees');
|
|
7511
|
+
this.outstandingFees.set([]);
|
|
7512
|
+
this.loading.set(false);
|
|
7513
|
+
},
|
|
7514
|
+
complete: () => {
|
|
7515
|
+
this.loading.set(false);
|
|
7516
|
+
}
|
|
7517
|
+
});
|
|
7039
7518
|
},
|
|
7040
7519
|
error: (err) => {
|
|
7041
|
-
console.error('Error loading
|
|
7042
|
-
this.notificationService.error('Failed to load
|
|
7043
|
-
this.outstandingFees.set([]);
|
|
7044
|
-
},
|
|
7045
|
-
complete: () => {
|
|
7520
|
+
console.error('Error loading admission data:', err);
|
|
7521
|
+
this.notificationService.error('Failed to load student information');
|
|
7046
7522
|
this.loading.set(false);
|
|
7047
7523
|
}
|
|
7048
7524
|
});
|
|
@@ -7107,13 +7583,157 @@ class MyOnlinePaymentComponent {
|
|
|
7107
7583
|
});
|
|
7108
7584
|
}
|
|
7109
7585
|
submitPayment() {
|
|
7586
|
+
if (!this.studentId) {
|
|
7587
|
+
this.notificationService.error('Student ID not found');
|
|
7588
|
+
return;
|
|
7589
|
+
}
|
|
7110
7590
|
this.submitting.set(true);
|
|
7111
|
-
//
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7591
|
+
// Get selected fee assignment IDs
|
|
7592
|
+
const selectedAssignmentIds = Array.from(this.selectedFees());
|
|
7593
|
+
const totalAmount = this.totalPayable();
|
|
7594
|
+
// Create payment order on backend
|
|
7595
|
+
const orderPayload = {
|
|
7596
|
+
amount: totalAmount,
|
|
7597
|
+
currency: 'INR',
|
|
7598
|
+
student_id: this.studentId,
|
|
7599
|
+
fee_assignment_ids: selectedAssignmentIds,
|
|
7600
|
+
entity_id: this.entityId,
|
|
7601
|
+
academic_year_id: this.academicYearId
|
|
7602
|
+
};
|
|
7603
|
+
const orderUrl = cidePath.join([
|
|
7604
|
+
hostManagerRoutesUrl.cideSuiteHost,
|
|
7605
|
+
'payments',
|
|
7606
|
+
'create-order'
|
|
7607
|
+
]);
|
|
7608
|
+
this.http.post(orderUrl, orderPayload).subscribe({
|
|
7609
|
+
next: (orderResponse) => {
|
|
7610
|
+
if (orderResponse?.success && orderResponse?.data) {
|
|
7611
|
+
const orderData = orderResponse.data;
|
|
7612
|
+
// Initialize Razorpay checkout
|
|
7613
|
+
this.initializeRazorpayCheckout({
|
|
7614
|
+
orderId: orderData.orderId,
|
|
7615
|
+
amount: orderData.amount * 100, // Convert to paise
|
|
7616
|
+
currency: orderData.currency || 'INR',
|
|
7617
|
+
name: 'Fee Payment',
|
|
7618
|
+
description: `Payment for ${selectedAssignmentIds.length} fee(s)`,
|
|
7619
|
+
prefill: {
|
|
7620
|
+
contact: this.appStateHelper.getCurrentUser()?.user_mobileno || '',
|
|
7621
|
+
email: this.appStateHelper.getCurrentUser()?.user_emailid || ''
|
|
7622
|
+
},
|
|
7623
|
+
notes: {
|
|
7624
|
+
student_id: this.studentId,
|
|
7625
|
+
fee_assignment_ids: selectedAssignmentIds.join(',')
|
|
7626
|
+
},
|
|
7627
|
+
handler: (response) => {
|
|
7628
|
+
this.handlePaymentSuccess(response, orderData.orderId, totalAmount, selectedAssignmentIds);
|
|
7629
|
+
},
|
|
7630
|
+
modal: {
|
|
7631
|
+
ondismiss: () => {
|
|
7632
|
+
this.submitting.set(false);
|
|
7633
|
+
this.notificationService.info('Payment cancelled');
|
|
7634
|
+
}
|
|
7635
|
+
}
|
|
7636
|
+
});
|
|
7637
|
+
}
|
|
7638
|
+
else {
|
|
7639
|
+
this.notificationService.error(orderResponse?.message || 'Failed to create payment order');
|
|
7640
|
+
this.submitting.set(false);
|
|
7641
|
+
}
|
|
7642
|
+
},
|
|
7643
|
+
error: (err) => {
|
|
7644
|
+
console.error('Error creating payment order:', err);
|
|
7645
|
+
this.notificationService.error('Failed to initialize payment. Please try again.');
|
|
7646
|
+
this.submitting.set(false);
|
|
7647
|
+
}
|
|
7648
|
+
});
|
|
7649
|
+
}
|
|
7650
|
+
initializeRazorpayCheckout(options) {
|
|
7651
|
+
// Check if Razorpay is available
|
|
7652
|
+
if (typeof Razorpay === 'undefined') {
|
|
7653
|
+
// Load Razorpay script dynamically
|
|
7654
|
+
const script = document.createElement('script');
|
|
7655
|
+
script.src = 'https://checkout.razorpay.com/v1/checkout.js';
|
|
7656
|
+
script.onload = () => {
|
|
7657
|
+
this.openRazorpayCheckout(options);
|
|
7658
|
+
};
|
|
7659
|
+
script.onerror = () => {
|
|
7660
|
+
this.notificationService.error('Failed to load payment gateway. Please refresh and try again.');
|
|
7661
|
+
this.submitting.set(false);
|
|
7662
|
+
};
|
|
7663
|
+
document.body.appendChild(script);
|
|
7664
|
+
}
|
|
7665
|
+
else {
|
|
7666
|
+
this.openRazorpayCheckout(options);
|
|
7667
|
+
}
|
|
7668
|
+
}
|
|
7669
|
+
openRazorpayCheckout(options) {
|
|
7670
|
+
try {
|
|
7671
|
+
const razorpayOptions = {
|
|
7672
|
+
key: process.env['RAZORPAY_KEY_ID'] || 'rzp_test_1DP5mmOlF5G5ag',
|
|
7673
|
+
amount: options.amount,
|
|
7674
|
+
currency: options.currency,
|
|
7675
|
+
name: options.name,
|
|
7676
|
+
description: options.description,
|
|
7677
|
+
order_id: options.orderId,
|
|
7678
|
+
prefill: options.prefill,
|
|
7679
|
+
notes: options.notes,
|
|
7680
|
+
handler: options.handler,
|
|
7681
|
+
modal: options.modal,
|
|
7682
|
+
theme: {
|
|
7683
|
+
color: '#2563eb'
|
|
7684
|
+
}
|
|
7685
|
+
};
|
|
7686
|
+
const razorpay = new Razorpay(razorpayOptions);
|
|
7687
|
+
razorpay.open();
|
|
7688
|
+
}
|
|
7689
|
+
catch (error) {
|
|
7690
|
+
console.error('Error opening Razorpay checkout:', error);
|
|
7691
|
+
this.notificationService.error('Failed to open payment gateway');
|
|
7115
7692
|
this.submitting.set(false);
|
|
7116
|
-
}
|
|
7693
|
+
}
|
|
7694
|
+
}
|
|
7695
|
+
handlePaymentSuccess(paymentResponse, orderId, amount, assignmentIds) {
|
|
7696
|
+
// Verify payment on backend
|
|
7697
|
+
const verifyPayload = {
|
|
7698
|
+
payment_id: paymentResponse.razorpay_payment_id,
|
|
7699
|
+
order_id: orderId,
|
|
7700
|
+
signature: paymentResponse.razorpay_signature,
|
|
7701
|
+
amount: amount,
|
|
7702
|
+
student_id: this.studentId,
|
|
7703
|
+
fee_assignment_ids: assignmentIds,
|
|
7704
|
+
entity_id: this.entityId,
|
|
7705
|
+
academic_year_id: this.academicYearId
|
|
7706
|
+
};
|
|
7707
|
+
const verifyUrl = cidePath.join([
|
|
7708
|
+
hostManagerRoutesUrl.cideSuiteHost,
|
|
7709
|
+
'payments',
|
|
7710
|
+
'verify'
|
|
7711
|
+
]);
|
|
7712
|
+
this.http.post(verifyUrl, verifyPayload).subscribe({
|
|
7713
|
+
next: (verifyResponse) => {
|
|
7714
|
+
if (verifyResponse?.success && verifyResponse?.data?.verified) {
|
|
7715
|
+
this.notificationService.success('Payment processed successfully!');
|
|
7716
|
+
// Navigate to receipt or statement
|
|
7717
|
+
if (verifyResponse.data.receiptNumber) {
|
|
7718
|
+
// Navigate to receipt view
|
|
7719
|
+
this.router.navigate(['/control-panel/fees/payment/view', verifyResponse.data.paymentId]);
|
|
7720
|
+
}
|
|
7721
|
+
else {
|
|
7722
|
+
// Navigate to statement
|
|
7723
|
+
this.router.navigate(['/control-panel/fees/statement']);
|
|
7724
|
+
}
|
|
7725
|
+
}
|
|
7726
|
+
else {
|
|
7727
|
+
this.notificationService.error(verifyResponse?.message || 'Payment verification failed');
|
|
7728
|
+
this.submitting.set(false);
|
|
7729
|
+
}
|
|
7730
|
+
},
|
|
7731
|
+
error: (err) => {
|
|
7732
|
+
console.error('Error verifying payment:', err);
|
|
7733
|
+
this.notificationService.error('Payment verification failed. Please contact support.');
|
|
7734
|
+
this.submitting.set(false);
|
|
7735
|
+
}
|
|
7736
|
+
});
|
|
7117
7737
|
}
|
|
7118
7738
|
cancel() {
|
|
7119
7739
|
this.router.navigate(['/control-panel/my-fees/statement']);
|
|
@@ -7125,7 +7745,7 @@ class MyOnlinePaymentComponent {
|
|
|
7125
7745
|
return `₹${amount.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
7126
7746
|
}
|
|
7127
7747
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MyOnlinePaymentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7128
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: MyOnlinePaymentComponent, isStandalone: true, selector: "cide-my-online-payment", ngImport: i0, template: "<!-- My Online Payment Container -->\r\n<div class=\"tw-w-full tw-h-full\">\r\n <div class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">payment</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Online Fee Payment</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-items-center tw-gap-3\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"cancel()\" leftIcon=\"arrow_back\">\r\n Back to Statement\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Main Content Area -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\r\n \r\n <!-- Left Panel - Fee Selection -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden tw-flex tw-flex-col\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Select Fees to Pay</h6>\r\n </div>\r\n \r\n <!-- Quick Actions -->\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-flex tw-gap-2\">\r\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" (click)=\"selectAll()\">\r\n Select All\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" (click)=\"selectOverdue()\">\r\n Select Overdue\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" (click)=\"clearSelection()\">\r\n Clear\r\n </button>\r\n </div>\r\n\r\n <!-- Fee Items List -->\r\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-4 tw-space-y-3\">\r\n @if (outstandingFees().length === 0) {\r\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\r\n <cide-ele-icon class=\"tw-w-12 tw-h-12 tw-mx-auto tw-mb-2 tw-text-gray-400\">check_circle</cide-ele-icon>\r\n <p class=\"tw-text-sm\">No outstanding fees</p>\r\n </div>\r\n } @else {\r\n @for (fee of outstandingFees(); track fee.id) {\r\n <div class=\"tw-p-3 tw-rounded-lg tw-border-2 tw-cursor-pointer tw-transition-colors\"\r\n [class.tw-border-blue-500]=\"isSelected(fee)\"\r\n [class.tw-bg-blue-50]=\"isSelected(fee)\"\r\n [class.tw-border-yellow-400]=\"!isSelected(fee) && isOverdue(fee)\"\r\n [class.tw-bg-yellow-50]=\"!isSelected(fee) && isOverdue(fee)\"\r\n [class.tw-border-gray-200]=\"!isSelected(fee) && !isOverdue(fee)\"\r\n (click)=\"toggleFee(fee)\">\r\n <div class=\"tw-flex tw-items-start tw-justify-between tw-gap-3\">\r\n <div class=\"tw-flex tw-items-start tw-gap-3 tw-flex-1\">\r\n <input \r\n type=\"checkbox\" \r\n [checked]=\"isSelected(fee)\"\r\n (change)=\"toggleFee(fee); $event.stopPropagation()\"\r\n class=\"tw-mt-1\">\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mb-1\">\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ fee.fee_head }}</span>\r\n @if (isOverdue(fee)) {\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-yellow-100 tw-text-yellow-800\">\r\n Overdue\r\n </span>\r\n }\r\n </div>\r\n <div class=\"tw-text-xs tw-text-gray-600\">\r\n Due Date: {{ fee.due_date | date:'dd/MM/yyyy' }}\r\n </div>\r\n @if (fee.late_fee > 0) {\r\n <div class=\"tw-text-xs tw-text-red-600 tw-mt-1\">\r\n Late Fee: {{ formatCurrency(fee.late_fee) }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"tw-text-right\">\r\n <div class=\"tw-font-semibold tw-text-gray-900\">{{ formatCurrency(fee.outstanding) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Right Panel - Payment Summary & Gateway -->\r\n <div class=\"tw-space-y-4\">\r\n \r\n <!-- Payment Summary Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Payment Summary</h6>\r\n </div>\r\n <div class=\"tw-p-4 tw-space-y-3\">\r\n <div class=\"tw-flex tw-justify-between tw-text-sm\">\r\n <span class=\"tw-text-gray-600\">Selected Items</span>\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ selectedCount() }}</span>\r\n </div>\r\n <div class=\"tw-flex tw-justify-between tw-text-sm\">\r\n <span class=\"tw-text-gray-600\">Fee Amount</span>\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ formatCurrency(totalFeeAmount()) }}</span>\r\n </div>\r\n @if (totalLateFee() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-text-sm tw-text-red-600\">\r\n <span>Late Fee</span>\r\n <span class=\"tw-font-medium\">{{ formatCurrency(totalLateFee()) }}</span>\r\n </div>\r\n }\r\n <div class=\"tw-flex tw-justify-between tw-text-sm tw-font-semibold tw-pt-2 tw-border-t tw-border-gray-200\">\r\n <span>Subtotal</span>\r\n <span>{{ formatCurrency(subtotal()) }}</span>\r\n </div>\r\n @if (convenienceFee() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-text-sm\">\r\n <span class=\"tw-text-gray-600\">Convenience Fee (2%)</span>\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ formatCurrency(convenienceFee()) }}</span>\r\n </div>\r\n }\r\n <div class=\"tw-flex tw-justify-between tw-text-lg tw-font-bold tw-pt-3 tw-border-t-2 tw-border-gray-300 tw-text-green-600\">\r\n <span>Total Payable</span>\r\n <span>{{ formatCurrency(totalPayable()) }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Payment Method Selection -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Select Payment Method</h6>\r\n </div>\r\n <div class=\"tw-p-4\">\r\n <form [formGroup]=\"paymentForm\" class=\"tw-space-y-4\">\r\n \r\n <!-- Payment Method Cards -->\r\n <div class=\"tw-grid tw-grid-cols-3 tw-gap-3 tw-mb-4\">\r\n @for (method of paymentMethodOptions; track method.value) {\r\n <button\r\n type=\"button\"\r\n class=\"tw-p-4 tw-rounded-lg tw-border-2 tw-text-center tw-transition-colors\"\r\n [class.tw-border-blue-500]=\"selectedPaymentMethod() === method.value\"\r\n [class.tw-bg-blue-50]=\"selectedPaymentMethod() === method.value\"\r\n [class.tw-border-gray-200]=\"selectedPaymentMethod() !== method.value\"\r\n (click)=\"selectPaymentMethod(method.value)\">\r\n <cide-ele-icon class=\"tw-w-8 tw-h-8 tw-mx-auto tw-mb-2\"\r\n [class.tw-text-blue-600]=\"selectedPaymentMethod() === method.value\"\r\n [class.tw-text-gray-400]=\"selectedPaymentMethod() !== method.value\">\r\n @switch (method.value) {\r\n @case ('UPI') { account_balance_wallet }\r\n @case ('CARD') { credit_card }\r\n @case ('NET_BANKING') { account_balance }\r\n }\r\n </cide-ele-icon>\r\n <div class=\"tw-text-xs tw-font-medium\">{{ method.label }}</div>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- UPI Details -->\r\n @if (selectedPaymentMethod() === 'UPI') {\r\n <div class=\"tw-p-3 tw-bg-blue-50 tw-rounded-lg tw-border tw-border-blue-200\">\r\n <cide-ele-input\r\n label=\"UPI ID *\"\r\n formControlName=\"upi_id\"\r\n placeholder=\"username@upi\"\r\n size=\"sm\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n </div>\r\n }\r\n\r\n <!-- Card Details -->\r\n @if (selectedPaymentMethod() === 'CARD') {\r\n <div class=\"tw-p-3 tw-bg-blue-50 tw-rounded-lg tw-border tw-border-blue-200 tw-space-y-3\">\r\n <cide-ele-input\r\n label=\"Card Number *\"\r\n formControlName=\"card_number\"\r\n placeholder=\"1234 5678 9012 3456\"\r\n size=\"sm\"\r\n maxLength=\"19\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input\r\n label=\"Expiry Date *\"\r\n formControlName=\"expiry\"\r\n placeholder=\"MM/YY\"\r\n size=\"sm\"\r\n maxLength=\"5\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n <cide-ele-input\r\n label=\"CVV *\"\r\n formControlName=\"cvv\"\r\n type=\"password\"\r\n placeholder=\"***\"\r\n size=\"sm\"\r\n maxLength=\"3\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Net Banking Details -->\r\n @if (selectedPaymentMethod() === 'NET_BANKING') {\r\n <div class=\"tw-p-3 tw-bg-blue-50 tw-rounded-lg tw-border tw-border-blue-200\">\r\n <cide-ele-select\r\n label=\"Select Bank *\"\r\n formControlName=\"bank\"\r\n [options]=\"bankOptions\"\r\n size=\"sm\"\r\n placeholder=\"Select Bank\"\r\n [required]=\"true\">\r\n </cide-ele-select>\r\n </div>\r\n }\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"tw-flex tw-gap-3 tw-pt-4\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"cancel()\" class=\"tw-flex-1\">\r\n Cancel\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"proceedToPayment()\"\r\n [disabled]=\"!canProceed() || submitting()\" [loading]=\"submitting()\" class=\"tw-flex-1\" leftIcon=\"payment\">\r\n Pay {{ formatCurrency(totalPayable()) }}\r\n </button>\r\n </div>\r\n\r\n <!-- Security Info -->\r\n <div class=\"tw-flex tw-items-center tw-justify-center tw-gap-2 tw-pt-2 tw-text-xs tw-text-gray-500\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">lock</cide-ele-icon>\r\n <span>Secure payment powered by Razorpay</span>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [":host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
|
|
7748
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: MyOnlinePaymentComponent, isStandalone: true, selector: "cide-my-online-payment", ngImport: i0, template: "<!-- My Online Payment Container -->\r\n<div class=\"tw-w-full tw-h-full\">\r\n <div class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">payment</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Online Fee Payment</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-items-center tw-gap-3\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"cancel()\" leftIcon=\"arrow_back\">\r\n Back to Statement\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Main Content Area -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\r\n \r\n <!-- Left Panel - Fee Selection -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden tw-flex tw-flex-col\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Select Fees to Pay</h6>\r\n </div>\r\n \r\n <!-- Quick Actions -->\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-flex tw-gap-2\">\r\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" (click)=\"selectAll()\">\r\n Select All\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" (click)=\"selectOverdue()\">\r\n Select Overdue\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"ghost\" size=\"xs\" (click)=\"clearSelection()\">\r\n Clear\r\n </button>\r\n </div>\r\n\r\n <!-- Fee Items List -->\r\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-4 tw-space-y-3\">\r\n @if (outstandingFees().length === 0) {\r\n <div class=\"tw-text-center tw-py-8 tw-text-gray-500\">\r\n <cide-ele-icon class=\"tw-w-12 tw-h-12 tw-mx-auto tw-mb-2 tw-text-gray-400\">check_circle</cide-ele-icon>\r\n <p class=\"tw-text-sm\">No outstanding fees</p>\r\n </div>\r\n } @else {\r\n @for (fee of outstandingFees(); track fee.id) {\r\n <div class=\"tw-p-3 tw-rounded-lg tw-border-2 tw-cursor-pointer tw-transition-colors\"\r\n [class.tw-border-blue-500]=\"isSelected(fee)\"\r\n [class.tw-bg-blue-50]=\"isSelected(fee)\"\r\n [class.tw-border-yellow-400]=\"!isSelected(fee) && isOverdue(fee)\"\r\n [class.tw-bg-yellow-50]=\"!isSelected(fee) && isOverdue(fee)\"\r\n [class.tw-border-gray-200]=\"!isSelected(fee) && !isOverdue(fee)\"\r\n (click)=\"toggleFee(fee)\">\r\n <div class=\"tw-flex tw-items-start tw-justify-between tw-gap-3\">\r\n <div class=\"tw-flex tw-items-start tw-gap-3 tw-flex-1\">\r\n <input \r\n type=\"checkbox\" \r\n [checked]=\"isSelected(fee)\"\r\n (change)=\"toggleFee(fee); $event.stopPropagation()\"\r\n class=\"tw-mt-1\">\r\n <div class=\"tw-flex-1\">\r\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mb-1\">\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ fee.fee_head }}</span>\r\n @if (isOverdue(fee)) {\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-yellow-100 tw-text-yellow-800\">\r\n Overdue\r\n </span>\r\n }\r\n </div>\r\n <div class=\"tw-text-xs tw-text-gray-600\">\r\n Due Date: {{ fee.due_date | date:'dd/MM/yyyy' }}\r\n </div>\r\n @if (fee.late_fee > 0) {\r\n <div class=\"tw-text-xs tw-text-red-600 tw-mt-1\">\r\n Late Fee: {{ formatCurrency(fee.late_fee) }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"tw-text-right\">\r\n <div class=\"tw-font-semibold tw-text-gray-900\">{{ formatCurrency(fee.outstanding) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Right Panel - Payment Summary & Gateway -->\r\n <div class=\"tw-space-y-4\">\r\n \r\n <!-- Payment Summary Card -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Payment Summary</h6>\r\n </div>\r\n <div class=\"tw-p-4 tw-space-y-3\">\r\n <div class=\"tw-flex tw-justify-between tw-text-sm\">\r\n <span class=\"tw-text-gray-600\">Selected Items</span>\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ selectedCount() }}</span>\r\n </div>\r\n <div class=\"tw-flex tw-justify-between tw-text-sm\">\r\n <span class=\"tw-text-gray-600\">Fee Amount</span>\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ formatCurrency(totalFeeAmount()) }}</span>\r\n </div>\r\n @if (totalLateFee() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-text-sm tw-text-red-600\">\r\n <span>Late Fee</span>\r\n <span class=\"tw-font-medium\">{{ formatCurrency(totalLateFee()) }}</span>\r\n </div>\r\n }\r\n <div class=\"tw-flex tw-justify-between tw-text-sm tw-font-semibold tw-pt-2 tw-border-t tw-border-gray-200\">\r\n <span>Subtotal</span>\r\n <span>{{ formatCurrency(subtotal()) }}</span>\r\n </div>\r\n @if (convenienceFee() > 0) {\r\n <div class=\"tw-flex tw-justify-between tw-text-sm\">\r\n <span class=\"tw-text-gray-600\">Convenience Fee (2%)</span>\r\n <span class=\"tw-font-medium tw-text-gray-900\">{{ formatCurrency(convenienceFee()) }}</span>\r\n </div>\r\n }\r\n <div class=\"tw-flex tw-justify-between tw-text-lg tw-font-bold tw-pt-3 tw-border-t-2 tw-border-gray-300 tw-text-green-600\">\r\n <span>Total Payable</span>\r\n <span>{{ formatCurrency(totalPayable()) }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Payment Method Selection -->\r\n <div class=\"tw-bg-white tw-rounded-lg tw-border tw-border-gray-200 tw-shadow-sm tw-overflow-hidden\">\r\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-m-0\">Select Payment Method</h6>\r\n </div>\r\n <div class=\"tw-p-4\">\r\n <form [formGroup]=\"paymentForm\" class=\"tw-space-y-4\">\r\n \r\n <!-- Payment Method Cards -->\r\n <div class=\"tw-grid tw-grid-cols-3 tw-gap-3 tw-mb-4\">\r\n @for (method of paymentMethodOptions; track method.value) {\r\n <button\r\n type=\"button\"\r\n class=\"tw-p-4 tw-rounded-lg tw-border-2 tw-text-center tw-transition-colors\"\r\n [class.tw-border-blue-500]=\"selectedPaymentMethod() === method.value\"\r\n [class.tw-bg-blue-50]=\"selectedPaymentMethod() === method.value\"\r\n [class.tw-border-gray-200]=\"selectedPaymentMethod() !== method.value\"\r\n (click)=\"selectPaymentMethod(method.value)\">\r\n <cide-ele-icon class=\"tw-w-8 tw-h-8 tw-mx-auto tw-mb-2\"\r\n [class.tw-text-blue-600]=\"selectedPaymentMethod() === method.value\"\r\n [class.tw-text-gray-400]=\"selectedPaymentMethod() !== method.value\">\r\n @switch (method.value) {\r\n @case ('UPI') { account_balance_wallet }\r\n @case ('CARD') { credit_card }\r\n @case ('NET_BANKING') { account_balance }\r\n }\r\n </cide-ele-icon>\r\n <div class=\"tw-text-xs tw-font-medium\">{{ method.label }}</div>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- UPI Details -->\r\n @if (selectedPaymentMethod() === 'UPI') {\r\n <div class=\"tw-p-3 tw-bg-blue-50 tw-rounded-lg tw-border tw-border-blue-200\">\r\n <cide-ele-input\r\n label=\"UPI ID *\"\r\n formControlName=\"upi_id\"\r\n placeholder=\"username@upi\"\r\n size=\"sm\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n </div>\r\n }\r\n\r\n <!-- Card Details -->\r\n @if (selectedPaymentMethod() === 'CARD') {\r\n <div class=\"tw-p-3 tw-bg-blue-50 tw-rounded-lg tw-border tw-border-blue-200 tw-space-y-3\">\r\n <cide-ele-input\r\n label=\"Card Number *\"\r\n formControlName=\"card_number\"\r\n placeholder=\"1234 5678 9012 3456\"\r\n size=\"sm\"\r\n maxLength=\"19\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-3\">\r\n <cide-ele-input\r\n label=\"Expiry Date *\"\r\n formControlName=\"expiry\"\r\n placeholder=\"MM/YY\"\r\n size=\"sm\"\r\n maxLength=\"5\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n <cide-ele-input\r\n label=\"CVV *\"\r\n formControlName=\"cvv\"\r\n type=\"password\"\r\n placeholder=\"***\"\r\n size=\"sm\"\r\n maxLength=\"3\"\r\n [required]=\"true\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Net Banking Details -->\r\n @if (selectedPaymentMethod() === 'NET_BANKING') {\r\n <div class=\"tw-p-3 tw-bg-blue-50 tw-rounded-lg tw-border tw-border-blue-200\">\r\n <cide-ele-select\r\n label=\"Select Bank *\"\r\n formControlName=\"bank\"\r\n [options]=\"bankOptions\"\r\n size=\"sm\"\r\n placeholder=\"Select Bank\"\r\n [required]=\"true\">\r\n </cide-ele-select>\r\n </div>\r\n }\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"tw-flex tw-gap-3 tw-pt-4\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"sm\" (click)=\"cancel()\" class=\"tw-flex-1\">\r\n Cancel\r\n </button>\r\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"sm\" (click)=\"proceedToPayment()\"\r\n [disabled]=\"!canProceed() || submitting()\" [loading]=\"submitting()\" class=\"tw-flex-1\" leftIcon=\"payment\">\r\n Pay {{ formatCurrency(totalPayable()) }}\r\n </button>\r\n </div>\r\n\r\n <!-- Security Info -->\r\n <div class=\"tw-flex tw-items-center tw-justify-center tw-gap-2 tw-pt-2 tw-text-xs tw-text-gray-500\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">lock</cide-ele-icon>\r\n <span>Secure payment powered by Razorpay</span>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [":host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "step", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton], cide-ele-button", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
|
|
7129
7749
|
}
|
|
7130
7750
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: MyOnlinePaymentComponent, decorators: [{
|
|
7131
7751
|
type: Component,
|
|
@@ -7159,11 +7779,14 @@ class FeeDetailsViewerComponent {
|
|
|
7159
7779
|
feeStructureService = inject(CideFeeFeeStructureService);
|
|
7160
7780
|
feeAssignmentService = inject(CideFeeFeeAssignmentService);
|
|
7161
7781
|
notificationService = inject(NotificationService);
|
|
7782
|
+
rightsService = inject(RightsService);
|
|
7162
7783
|
// State
|
|
7163
7784
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
7164
7785
|
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
7165
7786
|
feeDetails = signal(null, ...(ngDevMode ? [{ debugName: "feeDetails" }] : []));
|
|
7166
7787
|
ngOnInit() {
|
|
7788
|
+
// Initialize rights for fee details viewer (view-only)
|
|
7789
|
+
this.rightsService.initializeRights('fee_statement');
|
|
7167
7790
|
// Watch for changes in inputs and reload when they change
|
|
7168
7791
|
this.loadFeeDetails();
|
|
7169
7792
|
}
|