From 4fee83707ab836239f8836d3efd5c69945c1be70 Mon Sep 17 00:00:00 2001 From: Cyril Joseph Date: Sun, 7 Sep 2025 21:56:17 -0300 Subject: [PATCH] feedback updates --- src/app/core/models/holder-type.ts | 5 + .../models/service-provider/cargo-rate.ts | 12 + .../service-provider/security-deposit.ts | 1 + .../core/services/common/common.service.ts | 13 + .../service-provider/cargo-rate.service.ts | 70 +++++ .../security-deposit.service.ts | 3 + .../param/table/param-table.component.html | 8 +- .../add/add-service-provider.component.html | 9 + .../add/add-service-provider.component.ts | 8 +- .../cargo-rate/cargo-rate.component.html | 192 ++++++++++++++ .../cargo-rate/cargo-rate.component.scss | 191 ++++++++++++++ .../cargo-rate/cargo-rate.component.ts | 244 ++++++++++++++++++ .../edit/edit-service-provider.component.html | 8 + .../edit/edit-service-provider.component.ts | 3 +- .../security-deposit.component.html | 20 +- .../security-deposit.component.scss | 2 +- .../security-deposit.component.ts | 27 +- 17 files changed, 799 insertions(+), 17 deletions(-) create mode 100644 src/app/core/models/holder-type.ts create mode 100644 src/app/core/models/service-provider/cargo-rate.ts create mode 100644 src/app/core/services/service-provider/cargo-rate.service.ts create mode 100644 src/app/service-provider/cargo-rate/cargo-rate.component.html create mode 100644 src/app/service-provider/cargo-rate/cargo-rate.component.scss create mode 100644 src/app/service-provider/cargo-rate/cargo-rate.component.ts diff --git a/src/app/core/models/holder-type.ts b/src/app/core/models/holder-type.ts new file mode 100644 index 0000000..c393c57 --- /dev/null +++ b/src/app/core/models/holder-type.ts @@ -0,0 +1,5 @@ +export interface HolderType { + name: string; + id: string; + value: string; +} diff --git a/src/app/core/models/service-provider/cargo-rate.ts b/src/app/core/models/service-provider/cargo-rate.ts new file mode 100644 index 0000000..712137f --- /dev/null +++ b/src/app/core/models/service-provider/cargo-rate.ts @@ -0,0 +1,12 @@ +export interface CargoRate { + id: number, + spid: number, + startSets: number, + endSets: number, + carnetType: string, + effectiveDate: Date, + rate: number, + dateCreated?: Date | null; + createdBy?: string | null; + expired?: boolean; +} diff --git a/src/app/core/models/service-provider/security-deposit.ts b/src/app/core/models/service-provider/security-deposit.ts index 755874e..1ad42b6 100644 --- a/src/app/core/models/service-provider/security-deposit.ts +++ b/src/app/core/models/service-provider/security-deposit.ts @@ -5,6 +5,7 @@ export interface SecurityDeposit { specialCommodity: string; specialCountry: string; rate: number; + rateInPercentage: number; effectiveDate: Date; spid: number; dateCreated?: Date | null; diff --git a/src/app/core/services/common/common.service.ts b/src/app/core/services/common/common.service.ts index 3cd406d..06b9ae8 100644 --- a/src/app/core/services/common/common.service.ts +++ b/src/app/core/services/common/common.service.ts @@ -13,6 +13,7 @@ import { CargoSurety } from '../../models/cargo-surety'; import { CarnetStatus } from '../../models/carnet-status'; import { Country } from '../../models/country'; import { UserService } from './user.service'; +import { HolderType } from '../../models/holder-type'; @Injectable({ providedIn: 'root' @@ -150,6 +151,18 @@ export class CommonService { ); } + getHolderTypes(): Observable { + return this.http.get(`${this.apiUrl}/${this.apiDb}/GetParamValues?P_PARAMTYPE=017&P_SPID=${this.userService.getUserSpid()}`).pipe( + map((response) => + response.map((item) => ({ + name: item.PARAMDESC, + id: item.PARAMID, + value: item.PARAMVALUE, + })) + ) + ); + } + formatUSDate(datetime: Date): string { const date = new Date(datetime); const month = String(date.getUTCMonth() + 1).padStart(2, '0'); diff --git a/src/app/core/services/service-provider/cargo-rate.service.ts b/src/app/core/services/service-provider/cargo-rate.service.ts new file mode 100644 index 0000000..cb9b5db --- /dev/null +++ b/src/app/core/services/service-provider/cargo-rate.service.ts @@ -0,0 +1,70 @@ +import { inject, Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { map, Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { CommonService } from '../common/common.service'; +import { UserService } from '../common/user.service'; +import { CargoRate } from '../../models/service-provider/cargo-rate'; + +@Injectable({ + providedIn: 'root' +}) +export class CargoRateService { + private apiUrl = environment.apiUrl; + private apiDb = environment.apiDb; + + private http = inject(HttpClient); + private userService = inject(UserService); + private commonService = inject(CommonService); + + getCargoRates(spid: number): Observable { + return this.http.get(`${this.apiUrl}/${this.apiDb}/GetCargoRates/${spid}/ACTIVE`).pipe( + map(response => this.mapToCargoRates(response))); + } + + private mapToCargoRates(data: any[]): CargoRate[] { + return data.map(item => ({ + id: item.CARGORATESETUPID, + spid: item.SPID, + startSets: item.STARTSETS, + endSets: item.ENDSETS, + carnetType: item.CARNETTYPE, + effectiveDate: item.EFFDATE, + rate: item.RATE, + createdBy: item.CREATEDBY || null, + dateCreated: item.DATECREATED || null, + expired: item.EXPDATE ? new Date(item.EXPDATE) < new Date() : false + })); + } + + addCargoRate(spid: number, data: CargoRate): Observable { + + const cargoRate = { + P_SPID: spid, + P_STARTSETS: data.startSets, + P_ENDSETS: data.endSets, + P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate), + P_CARNETTYPE: data.carnetType, + P_RATE: data.rate, + P_USERID: this.userService.getUser() + } + + return this.http.post(`${this.apiUrl}/${this.apiDb}/CreateCargoRate`, cargoRate); + } + + updateCargoRate(id: number, data: CargoRate): Observable { + + const cargoRate = { + P_CARGORATESETUPID: id, + P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate), + P_RATE: data.rate, + P_USERID: this.userService.getUser() + } + + return this.http.patch(`${this.apiUrl}/${this.apiDb}//UpdateCargoRate`, cargoRate); + } + + // deleteCargo(id: string): Observable { + // return this.http.delete(`${this.apiUrl}/${this.apiDb}/InactivateSPContact/${id}`); + // } +} diff --git a/src/app/core/services/service-provider/security-deposit.service.ts b/src/app/core/services/service-provider/security-deposit.service.ts index 4f36307..15390ba 100644 --- a/src/app/core/services/service-provider/security-deposit.service.ts +++ b/src/app/core/services/service-provider/security-deposit.service.ts @@ -30,6 +30,7 @@ export class SecurityDepositService { specialCommodity: item.SPCLCOMMODITY, specialCountry: item.SPCLCOUNTRY, rate: item.RATE, + rateInPercentage: item.RATE * 100, effectiveDate: item.EFFDATE, spid: item.SPID, createdBy: item.CREATEDBY || null, @@ -48,6 +49,7 @@ export class SecurityDepositService { P_SPCLCOMMODITY: data.specialCommodity, P_SPCLCOUNTRY: data.specialCountry, P_RATE: data.rate, + P_PCT_VALUE: data.rateInPercentage.toString(), P_USERID: this.userService.getUser() } @@ -60,6 +62,7 @@ export class SecurityDepositService { P_BONDRATESETUPID: id, P_EFFDATE: this.commonService.formatUSDate(data.effectiveDate), P_RATE: data.rate, + P_PCT_VALUE: data.rateInPercentage.toString(), P_USERID: this.userService.getUser() } diff --git a/src/app/param/table/param-table.component.html b/src/app/param/table/param-table.component.html index 7f55792..573fb45 100644 --- a/src/app/param/table/param-table.component.html +++ b/src/app/param/table/param-table.component.html @@ -86,18 +86,18 @@ - diff --git a/src/app/service-provider/add/add-service-provider.component.html b/src/app/service-provider/add/add-service-provider.component.html index 12bef29..6e5d229 100644 --- a/src/app/service-provider/add/add-service-provider.component.html +++ b/src/app/service-provider/add/add-service-provider.component.html @@ -83,5 +83,14 @@ [userPreferences]="userPreferences"> + + + Cargo Rate Setup + + + + + \ No newline at end of file diff --git a/src/app/service-provider/add/add-service-provider.component.ts b/src/app/service-provider/add/add-service-provider.component.ts index a6dc710..e366662 100644 --- a/src/app/service-provider/add/add-service-provider.component.ts +++ b/src/app/service-provider/add/add-service-provider.component.ts @@ -13,11 +13,12 @@ import { SecurityDepositComponent } from '../security-deposit/security-deposit.c import { ContinuationSheetFeeComponent } from "../continuation-sheet-fee/continuation-sheet-fee.component"; import { UserPreferences } from '../../core/models/user-preference'; import { UserPreferencesService } from '../../core/services/user-preference.service'; +import { CargoRateComponent } from '../cargo-rate/cargo-rate.component'; @Component({ selector: 'app-add-service-provider', imports: [BasicDetailsComponent, AngularMaterialModule, CommonModule, ContactsComponent, CarnetSequenceComponent, - CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, ContinuationSheetFeeComponent], + CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, ContinuationSheetFeeComponent, CargoRateComponent], templateUrl: './add-service-provider.component.html', styleUrl: './add-service-provider.component.scss' }) @@ -37,6 +38,7 @@ export class AddServiceProviderComponent { continuationSheetFeeCompleted: boolean = false; expeditedFeeCompleted: boolean = false; securityDepositCompleted: boolean = false; + cargoRateCompleted: boolean = false; constructor(userPrefenceService: UserPreferencesService) { this.userPreferences = userPrefenceService.getPreferences(); @@ -79,6 +81,10 @@ export class AddServiceProviderComponent { this.securityDepositCompleted = event; } + onCargoRateSaved(event: boolean): void { + this.cargoRateCompleted = event; + } + onStepChange(event: StepperSelectionEvent): void { this.currentStep = event.selectedIndex; } diff --git a/src/app/service-provider/cargo-rate/cargo-rate.component.html b/src/app/service-provider/cargo-rate/cargo-rate.component.html new file mode 100644 index 0000000..13f6978 --- /dev/null +++ b/src/app/service-provider/cargo-rate/cargo-rate.component.html @@ -0,0 +1,192 @@ +
+
+ + Show Expired Records + + +
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Carnet Type + {{ getOptionLabel(carnetTypes, item.carnetType) }} + Start Sets{{ item.startSets }}End Sets{{ item.endSets }}Rate{{ item.rate | currency }}Effective Date + {{ item.effectiveDate | date:'mediumDate':'UTC' }} + Actions + + +
+ info + No cargo rate setups available +
+ + +
+ + +
+
+
+

{{ isEditing ? 'Edit Cargo Rate Setup' : 'Add New Cargo Rate Setup' }}

+
+ +
+ Carnet Type + + + {{ type.label }} + + + + Carnet type is required + +
+ +
+ + Start Sets + + + Start sets is required + + + Must be a valid number + + + Must be greater than 0 + + + + + End Sets + + + End sets is required + + + Must be a valid number + + + Must be greater than 0 + + +
+ + + End sets must be greater than start sets + + +
+ + Rate + + + + Rate is required + + + Must be a valid dollar amount + + + Must be 0 or greater + + + + + Effective Date + + + + + Effective date is required + + +
+ +
+
+
+ +
+ +
+ {{readOnlyFields.lastChangedBy || 'N/A'}} +
+
+
+
+ +
+ +
+ {{(readOnlyFields.lastChangedDate | date:'mediumDate':'UTC') || 'N/A'}} +
+
+
+
+
+ +
+ + +
+
+
+
\ No newline at end of file diff --git a/src/app/service-provider/cargo-rate/cargo-rate.component.scss b/src/app/service-provider/cargo-rate/cargo-rate.component.scss new file mode 100644 index 0000000..9ef5645 --- /dev/null +++ b/src/app/service-provider/cargo-rate/cargo-rate.component.scss @@ -0,0 +1,191 @@ +.cargorate-container { + padding: 0.5rem; + display: flex; + flex-direction: column; + gap: 24px; + + .actions-bar { + clear: both; + margin-bottom: -16px; + + mat-slide-toggle { + transform: scale(0.8); + margin-left: -0.5rem; + } + + button { + float: right; + } + } + + .table-container { + position: relative; + overflow: auto; + border-radius: 8px; + + .loading-shade { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(255, 255, 255, 0.7); + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + } + + mat-table { + width: 100%; + + mat-icon { + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + transform: scale(1.1); + } + } + + .mat-column-actions { + width: 120px; + text-align: center; + } + } + + .no-data-message { + text-align: center; + padding: 0.9rem; + color: rgba(0, 0, 0, 0.54); + + mat-icon { + font-size: 1rem; + width: 1rem; + height: 1rem; + margin-bottom: -3px; + } + } + + mat-paginator { + border-top: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 0 0 8px 8px; + padding-top: 4px; + } + } + + .form-container { + background-color: white; + padding: 24px; + border-radius: 8px; + margin-top: 16px; + + .form-header { + // margin-bottom: 24px; + + h3 { + margin: 0; + color: var(--mat-sys-primary); + font-weight: 500; + } + } + + form { + display: flex; + flex-direction: column; + gap: 16px; + + .form-row { + display: flex; + gap: 16px; + align-items: start; + + mat-form-field { + flex: 1; + } + + mat-label { + font-size: 0.875rem; + } + } + + .form-error { + margin-top: -16px; + margin-bottom: 8px; + display: block; + color: var(--mat-form-field-error-text-color, var(--mat-sys-error)); + font-size: 12px; + } + + .form-actions { + display: flex; + justify-content: flex-end; + gap: 16px; + margin-top: 16px; + } + + .horizontal-group { + display: flex; + gap: 16px; + flex-wrap: wrap; + } + + ::ng-deep .mat-radio-button.mat-accent .mat-radio-outer-circle { + border-color: #3f51b5; + } + + ::ng-deep .mat-radio-button.mat-accent .mat-radio-inner-circle { + background-color: #3f51b5; + } + + .dollar-prefix { + padding-left: 4px; + } + + .readonly-section { + padding-top: 0.5rem; + border-top: 1px solid #eee; + + .readonly-fields { + display: flex; + gap: 2rem; + + .field-column { + flex: 1; + display: flex; + flex-direction: column; + gap: 1.5rem; + } + } + + .readonly-field { + label { + display: block; + font-size: 0.875rem; + color: #666; + margin-bottom: 0.25rem; + } + + .readonly-value { + padding: 0.25rem; + font-size: 0.875rem; + display: flex; + align-items: center; + } + } + } + } + } +} + +// Responsive adjustments +@media (max-width: 768px) { + .cargorate-container { + padding: 16px; + + .form-row { + flex-direction: column; + gap: 16px !important; + } + } +} \ No newline at end of file diff --git a/src/app/service-provider/cargo-rate/cargo-rate.component.ts b/src/app/service-provider/cargo-rate/cargo-rate.component.ts new file mode 100644 index 0000000..80df456 --- /dev/null +++ b/src/app/service-provider/cargo-rate/cargo-rate.component.ts @@ -0,0 +1,244 @@ +import { Component, EventEmitter, inject, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import { AngularMaterialModule } from '../../shared/module/angular-material.module'; +import { CommonModule } from '@angular/common'; +import { CustomPaginator } from '../../shared/custom-paginator'; +import { UserPreferences } from '../../core/models/user-preference'; +import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service'; +import { NotificationService } from '../../core/services/common/notification.service'; +import { finalize } from 'rxjs'; +import { CargoRate } from '../../core/models/service-provider/cargo-rate'; +import { CargoRateService } from '../../core/services/service-provider/cargo-rate.service'; + +@Component({ + selector: 'app-cargo-rate', + imports: [AngularMaterialModule, CommonModule, ReactiveFormsModule], + templateUrl: './cargo-rate.component.html', + styleUrl: './cargo-rate.component.scss', + providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }], +}) +export class CargoRateComponent implements OnInit { + @ViewChild(MatPaginator) paginator!: MatPaginator; + @ViewChild(MatSort) sort!: MatSort; + + displayedColumns: string[] = ['carnetType', 'startSets', 'endSets', 'rate', 'effectiveDate', 'actions']; + dataSource = new MatTableDataSource(); + cargoRateForm: FormGroup; + isEditing = false; + currentCargoRateId: number | null = null; + isLoading = false; + changeInProgress = false; + showForm = false; + showExpiredRecords = false; + cargoRates: CargoRate[] = []; + + readOnlyFields: any = { + lastChangedDate: null, + lastChangedBy: null + }; + + carnetTypes = [ + { label: 'Original', value: 'ORIGINAL' }, + { label: 'Re-order', value: 'REORDER' }, + { label: 'Replacement', value: 'REPLACE' } + ]; + + @Input() isEditMode = false; + @Input() spid: number = 0; + @Input() userPreferences!: UserPreferences; + @Output() hasCargoRates = new EventEmitter(); + + private fb = inject(FormBuilder); + private cargoRateService = inject(CargoRateService); + private notificationService = inject(NotificationService); + private errorHandler = inject(ApiErrorHandlerService); + + constructor() { + this.cargoRateForm = this.fb.group({ + carnetType: ['ORIGINAL', Validators.required], + startSets: ['', [ + Validators.required, + Validators.pattern('^[0-9]*$'), + Validators.min(1) + ]], + endSets: ['', [ + Validators.required, + Validators.pattern('^[0-9]*$'), + Validators.min(1) + ]], + rate: ['', [ + Validators.required, + Validators.pattern(/^\d+\.?\d{0,2}$/), + Validators.min(0) + ]], + effectiveDate: ['', Validators.required] + }, { validator: this.validateSetsRange }); + } + + ngOnInit(): void { + this.loadCargoRates(); + } + + ngAfterViewInit() { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + + private validateSetsRange(group: FormGroup): { [key: string]: any } | null { + const start = +group.get('startSets')?.value; + const end = +group.get('endSets')?.value; + return start && end && start >= end ? { invalidRange: true } : null; + } + + loadCargoRates(): void { + if (!this.spid) return; + + this.isLoading = true; + this.cargoRateService.getCargoRates(this.spid).pipe(finalize(() => { + this.isLoading = false; + })) + .subscribe({ + next: ( + cargoRates: CargoRate[]) => { + this.cargoRates = cargoRates; + this.dataSource.data = this.cargoRates; + this.renderRecods(); + }, + error: (error: any) => { + let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load cargo rates'); + this.notificationService.showError(errorMessage); + console.error('Error loading cargo rates:', error); + } + }); + } + + toggleShowExpiredRecords(): void { + this.showExpiredRecords = !this.showExpiredRecords; + this.renderRecods(); + } + + renderRecods(): void { + if (this.showExpiredRecords) { + this.dataSource.data = this.cargoRates.filter(record => record.expired); + } else { + this.dataSource.data = this.cargoRates.filter(record => !record.expired); + } + } + + // applyFilter(event: Event): void { + // const filterValue = (event.target as HTMLInputElement).value; + // this.dataSource.filter = filterValue.trim().toLowerCase(); + + // if (this.dataSource.paginator) { + // this.dataSource.paginator.firstPage(); + // } + // } + + addNewCargoRate(): void { + this.showForm = true; + this.isEditing = false; + this.currentCargoRateId = null; + this.cargoRateForm.reset({ + carnetType: 'ORIGINAL' + }); + + this.cargoRateForm.get('carnetType')?.enable(); + this.cargoRateForm.get('startSets')?.enable(); + this.cargoRateForm.get('endSets')?.enable(); + } + + editCargoRate(cargoRate: any): void { + this.showForm = true; + this.isEditing = true; + this.currentCargoRateId = cargoRate.id; + this.cargoRateForm.patchValue({ + carnetType: cargoRate.carnetType, + startSets: cargoRate.startSets, + endSets: cargoRate.endSets, + rate: cargoRate.rate, + effectiveDate: new Date(cargoRate.effectiveDate) + }); + + this.readOnlyFields.lastChangedDate = cargoRate.dateCreated; + this.readOnlyFields.lastChangedBy = cargoRate.createdBy; + + this.cargoRateForm.get('carnetType')?.disable(); + this.cargoRateForm.get('startSets')?.disable(); + this.cargoRateForm.get('endSets')?.disable(); + } + + saveCargoRate(): void { + if (this.cargoRateForm.invalid) { + this.cargoRateForm.markAllAsTouched(); + return; + } + + const cargoRateData = { + ...this.cargoRateForm.value, + spid: this.spid + }; + + const saveObservable = this.isEditing && this.currentCargoRateId + ? this.cargoRateService.updateCargoRate(this.currentCargoRateId, cargoRateData) + : this.cargoRateService.addCargoRate(this.spid, cargoRateData); + + this.changeInProgress = true; + saveObservable.pipe(finalize(() => { + this.changeInProgress = false; + })).subscribe({ + next: () => { + this.notificationService.showSuccess(`Cargo Rate ${this.isEditing ? 'updated' : 'added'} successfully`); + this.loadCargoRates(); + this.cancelEdit(); + this.hasCargoRates.emit(true); + }, + error: (error) => { + let errorMessage = this.errorHandler.handleApiError(error, `Failed to ${this.isEditing ? 'update' : 'add'} cargo rate`); + this.notificationService.showError(errorMessage); + console.error('Error saving cargo rate:', error); + } + }); + } + + // deleteCargoRate(cargoRateId: string): void { + // const dialogRef = this.dialog.open(ConfirmDialogComponent, { + // width: '350px', + // data: { + // title: 'Confirm Delete', + // message: 'Are you sure you want to delete this cargoRate setup?', + // confirmText: 'Delete', + // cancelText: 'Cancel' + // } + // }); + + // dialogRef.afterClosed().subscribe(result => { + // if (result) { + // this.cargoRateService.deleteCargoRate(cargoRateId).subscribe({ + // next: () => { + // this.notificationService.showSuccess('CargoRate deleted successfully'); + // this.loadCargoRates(); + // }, + // error: (error) => { + // this.notificationService.showError('Failed to delete cargoRate'); + // } + // }); + // } + // }); + // } + + cancelEdit(): void { + this.showForm = false; + this.isEditing = false; + this.currentCargoRateId = null; + this.cargoRateForm.reset({ + carnetType: 'ORIGINAL' + }); + } + + getOptionLabel(options: any[], value: string): string { + return options.find(opt => opt.value === value)?.label || value; + } +} \ No newline at end of file diff --git a/src/app/service-provider/edit/edit-service-provider.component.html b/src/app/service-provider/edit/edit-service-provider.component.html index 5a5a958..1b444c4 100644 --- a/src/app/service-provider/edit/edit-service-provider.component.html +++ b/src/app/service-provider/edit/edit-service-provider.component.html @@ -73,4 +73,12 @@ + + + + Cargo Rate Setup + + + + \ No newline at end of file diff --git a/src/app/service-provider/edit/edit-service-provider.component.ts b/src/app/service-provider/edit/edit-service-provider.component.ts index ea44f38..6f8c720 100644 --- a/src/app/service-provider/edit/edit-service-provider.component.ts +++ b/src/app/service-provider/edit/edit-service-provider.component.ts @@ -14,10 +14,11 @@ import { SecurityDepositComponent } from "../security-deposit/security-deposit.c import { UserPreferences } from '../../core/models/user-preference'; import { CommonModule } from '@angular/common'; import { UserPreferencesService } from '../../core/services/user-preference.service'; +import { CargoRateComponent } from '../cargo-rate/cargo-rate.component'; @Component({ selector: 'app-edit-service-provider', - imports: [AngularMaterialModule, BasicDetailsComponent, ContactsComponent, CarnetSequenceComponent, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule], + imports: [AngularMaterialModule, BasicDetailsComponent, ContactsComponent, CarnetSequenceComponent, CarnetFeeComponent, BasicFeeComponent, CounterfoilFeeComponent, ContinuationSheetFeeComponent, ExpeditedFeeComponent, SecurityDepositComponent, CommonModule, CargoRateComponent], templateUrl: './edit-service-provider.component.html', styleUrl: './edit-service-provider.component.scss' }) diff --git a/src/app/service-provider/security-deposit/security-deposit.component.html b/src/app/service-provider/security-deposit/security-deposit.component.html index f086d3a..aacb563 100644 --- a/src/app/service-provider/security-deposit/security-deposit.component.html +++ b/src/app/service-provider/security-deposit/security-deposit.component.html @@ -48,6 +48,12 @@ {{ deposit.rate | currency }} + + + Rate In Percentage + {{ deposit.rateInPercentage | percent }} + + Effective Date @@ -97,7 +103,7 @@ Holder Type - {{ type.label }} + {{ type.name }} @@ -147,6 +153,18 @@ + + Rate % + + + + Rate % is required + + + Rate % must be positive + + + Effective Date diff --git a/src/app/service-provider/security-deposit/security-deposit.component.scss b/src/app/service-provider/security-deposit/security-deposit.component.scss index b9fa0d1..6847309 100644 --- a/src/app/service-provider/security-deposit/security-deposit.component.scss +++ b/src/app/service-provider/security-deposit/security-deposit.component.scss @@ -12,7 +12,7 @@ transform: scale(0.8); margin-left: -0.5rem; } - + button { float: right; } diff --git a/src/app/service-provider/security-deposit/security-deposit.component.ts b/src/app/service-provider/security-deposit/security-deposit.component.ts index d6cf92b..f6c5541 100644 --- a/src/app/service-provider/security-deposit/security-deposit.component.ts +++ b/src/app/service-provider/security-deposit/security-deposit.component.ts @@ -14,6 +14,7 @@ import { CommonService } from '../../core/services/common/common.service'; import { NotificationService } from '../../core/services/common/notification.service'; import { SecurityDepositService } from '../../core/services/service-provider/security-deposit.service'; import { finalize } from 'rxjs'; +import { HolderType } from '../../core/models/holder-type'; @Component({ selector: 'app-security-deposit', @@ -26,7 +27,7 @@ export class SecurityDepositComponent implements OnInit { @ViewChild(MatPaginator) paginator!: MatPaginator; @ViewChild(MatSort) sort!: MatSort; - displayedColumns: string[] = ['holderType', 'uscibMember', 'specialCommodity', 'specialCountry', 'rate', 'effectiveDate', 'actions']; + displayedColumns: string[] = ['holderType', 'uscibMember', 'specialCommodity', 'specialCountry', 'rate', 'rateInPercentage', 'effectiveDate', 'actions']; dataSource = new MatTableDataSource(); depositForm: FormGroup; isEditing = false; @@ -43,18 +44,13 @@ export class SecurityDepositComponent implements OnInit { }; countries: Country[] = []; + holderTypes: HolderType[] = []; @Input() isEditMode = false; @Input() spid: number = 0; @Input() userPreferences!: UserPreferences; @Output() hasSecurityDeposits = new EventEmitter(); - holderTypes = [ - { value: 'CORP', label: 'Corporation' }, - { value: 'INDIVIDUAL', label: 'Individual' }, - { value: 'GOVERNMENT', label: 'Government Agency' } - ]; - yesNoOptions = [ { value: 'Y', label: 'Yes' }, { value: 'N', label: 'No' } @@ -73,6 +69,7 @@ export class SecurityDepositComponent implements OnInit { specialCommodity: [''], specialCountry: [''], rate: [0, [Validators.required, Validators.min(0)]], + rateInPercentage: [0, [Validators.required, Validators.min(0)]], effectiveDate: ['', Validators.required] }); } @@ -80,6 +77,7 @@ export class SecurityDepositComponent implements OnInit { ngOnInit(): void { this.loadSecurityDeposits(); this.loadCountries(); + this.loadHolderTypes(); } ngAfterViewInit() { @@ -129,6 +127,16 @@ export class SecurityDepositComponent implements OnInit { }); } + loadHolderTypes(): void { + this.commonService.getHolderTypes().subscribe({ + next: (holderTypes) => { + this.holderTypes = holderTypes; + }, + error: (error) => { + console.error('Error loading holder types:', error); + } + }); + } // applyFilter(event: Event): void { // const filterValue = (event.target as HTMLInputElement).value; // this.dataSource.filter = filterValue.trim().toLowerCase(); @@ -147,7 +155,7 @@ export class SecurityDepositComponent implements OnInit { uscibMember: 'N', specialCountry: '', }); - this.depositForm.patchValue({ rate: 0 }); + this.depositForm.patchValue({ rate: 0, rateInPercentage: 0 }); this.depositForm.get('holderType')?.enable(); this.depositForm.get('uscibMember')?.enable(); @@ -165,6 +173,7 @@ export class SecurityDepositComponent implements OnInit { specialCommodity: deposit.specialCommodity, specialCountry: deposit.specialCountry, rate: deposit.rate, + rateInPercentage: deposit.rateInPercentage, effectiveDate: deposit.effectiveDate }); @@ -251,7 +260,7 @@ export class SecurityDepositComponent implements OnInit { getHolderTypeLabel(value: string): string { const type = this.holderTypes.find(t => t.value === value); - return type ? type.label : value; + return type ? type.name : value; } getCountryName(code: string): string {