PageSourceSearch

https://apps.elfi.com/seb/webapp/src_app_discount_discount_module_ts.e720b6f91bedea19.js

js elfi.com collected 2026-09-24 12:07:47 UTC 19,215 bytes, 1 lines download raw bytes

1(self.webpackChunkfinstudentweb=self.webpackChunkfinstudentweb||[]).push([["src_app_discount_discount_module_ts"],{1330(m,v,c){"use strict";c.d(v,{DiscountModule:()=>f});var u=c(6089),i=c(9417),d=c(3049),T=c(7244);var x=c(6530),P=c.n(x),y=c(9832),D=c(1425),h=c(6354);let p=class{constructor(t,r,e){this.fb=t,this.executorService=r,this.sharedService=e,this.partnerOptions=[],this.productOptions=[],this.interestTypeOptions=[],this.loanTermOptions=[],this.partnerDiscounts=[],this.sortColumn="effectiveDate",this.sortDirection="desc",this.loadingDiscounts=!1,this.submitting=!1,this.responseMessage="",this.responseType=""}ngOnInit(){this.initializeForm(),this.loadPartnerOptions(),this.loadProductOptions(),this.interestTypeOptions=["ALL"],this.loanTermOptions=["ALL"]}loadProductOptions(){this.executorService.query("/admin/partner-discounts/sub-products","GET",{},null).pipe((0,h.T)(t=>(Array.isArray(t)?t:Array.isArray(t&&t.data)?t.data:Array.isArray(t&&t.result)?t.result:[]).map(e=>({subProductId:e&&(e.id??e.subProductId??e.value),name:e&&(e.name??e.productName??e.label??"")})).filter(e=>null!=e.subProductId&&e.name))).subscribe({next:t=>{this.productOptions=t,this.loadPartnerDiscounts()},error:()=>{this.productOptions=[],this.responseType="error",this.responseMessage="Unable to load product options.",this.loadPartnerDiscounts()}})}loadPartnerOptions(){this.executorService.query("/users/partners","GET",{},null).pipe((0,h.T)(t=>this.extractPartners(t))).subscribe({next:t=>{this.partnerOptions=t},error:()=>{this.partnerOptions=[],this.responseType="error",this.responseMessage="Unable to load partner options."}})}extractPartners(t){return(Array.isArray(t)?t:Array.isArray(t&&t.data)?t.data:Array.isArray(t&&t.result)?t.result:[]).map(e=>({value:e&&null!=(e.name??e.partnerName??e.id??e.value)?e.name??e.partnerName??e.id??e.value:null,label:e&&(e.name??e.partnerName??e.label)?e.name??e.partnerName??e.label:""})).filter(e=>null!=e.value&&!!e.label)}initializeForm(){this.discountForm=this.fb.group({partnerName:["",i.k0.required],productName:["",i.k0.required],interestType:["",i.k0.required],loanTerm:["",i.k0.required],discountRate:["0.00",i.k0.compose([i.k0.required,i.k0.pattern(/^(?:100(?:\.0{1,2})?|(?:\d{1,2})(?:\.\d{1,2})?)$/)])],effectiveDate:["",i.k0.required],expirationDate:["",i.k0.required]},{validator:t=>{const r=t.controls.effectiveDate.value,e=t.controls.expirationDate.value,s=t.controls.expirationDate;if(!s)return null;const n=s.errors||{};if(r&&e&&new Date(r)>new Date(e))return s.setErrors({...n,invalidDateRange:!0}),{invalidDateRange:!0};if(n&&n.invalidDateRange){const{invalidDateRange:o,...a}=n,b=Object.keys(a).length>0;s.setErrors(b?a:null)}return null}})}loadPartnerDiscounts(){this.loadingDiscounts=!0,this.executorService.query("/admin/partner-discounts","GET",{},null).pipe((0,h.T)(t=>(Array.isArray(t)?t:Array.isArray(t&&t.data)?t.data:[]).map(e=>{const s=e&&null!=e.subProductId&&this.productOptions.find(n=>Number(n.subProductId)===Number(e.subProductId))||null;return{partnerName:e&&e.partnerName?e.partnerName:"-",productName:s?s.name:"-",discountRate:e&&null!=e.discountRate?Number(e.discountRate):0,isActive:!(!e||!e.isActive),effectiveDate:e&&e.effectiveDate?e.effectiveDate:"",expirationDate:e&&e.expirationDate?e.expirationDate:"",interestType:e&&e.interestType?e.interestType:"ALL",loanTermMonths:e&&null!=e.loanTermMonths?Number(e.loanTermMonths):0}}))).subscribe({next:t=>{this.partnerDiscounts=t,this.applySort(),this.loadingDiscounts=!1},error:()=>{this.partnerDiscounts=[],this.loadingDiscounts=!1,this.responseType="error",this.responseMessage="Unable to load partner discounts."}})}sortBy(t){this.sortColumn===t?this.sortDirection="asc"===this.sortDirection?"desc":"asc":(this.sortColumn=t,this.sortDirection="asc"),this.applySort()}applySort(){const t="asc"===this.sortDirection?1:-1;this.partnerDiscounts=[...this.partnerDiscounts].sort((r,e)=>{const s=this.getSortableValue(r,this.sortColumn),n=this.getSortableValue(e,this.sortColumn);return s<n?-1*t:s>n?1*t:0})}getSortableValue(t,r){switch(r){case"partnerName":case"productName":case"interestType":return(t[r]||"").toString().toLowerCase();case"discountRate":case"loanTermMonths":return Number(t[r])||0;case"isActive":return t[r]?1:0;case"effectiveDate":case"expirationDate":return t[r]||"";default:return t[r]}}getSortIndicator(t){return this.sortColumn!==t?"":"asc"===this.sortDirection?"\u2191":"\u2193"}onProductChange(){this.discountForm.patchValue({interestType:"",loanTerm:""})}onDiscountRateInput(t){let r=(t&&t.target&&t.target.value?t.target.value:"").trim();r=r.replace(/[^\d.]/g,"");const e=r.indexOf(".");-1!==e&&(r=r.substring(0,e+1)+r.substring(e+1).replace(/\./g,""));let s=r,n="";const o=r.split(".");2===o.length&&(s=o[0],n=o[1].substring(0,2)),s.length>1&&(s=s.replace(/^0+(?=\d)/,"")),r.startsWith(".")&&(s="0"),r=2===o.length?s+"."+n:s,""!==r&&!isNaN(Number(r))&&Number(r)>100&&(r="100"),t.target.value=r,this.discountForm.patchValue({discountRate:r},{emitEvent:!1})}
1onApply(){if(this.discountForm.invalid)return this.discountForm.markAllAsTouched(),this.responseType="error",void(this.responseMessage="Please fill all required fields before applying.");const t=this.discountForm.value,r=Number(t.productName),e=(this.productOptions||[]).find(g=>Number(g.subProductId)===r);(this.partnerOptions||[]).find(g=>String(g.value)===String(t.partnerName));if(!e||!r||r<=0)return this.responseType="error",void(this.responseMessage="Unable to apply partner discount: valid sub-product mapping not found.");const n="Fixed"===t.interestType?"FIXED":"Variable"===t.interestType?"VARIABLE":"ALL",o="ALL"===t.loanTerm?0:Number(t.loanTerm);if("ALL"!==t.loanTerm&&(Number.isNaN(o)||o<=0))return this.responseType="error",void(this.responseMessage="Please select a valid numeric loan term.");const a=Number(t.discountRate);if(Number.isNaN(a)||a<=0)return this.responseType="error",void(this.responseMessage="Discount rate must be greater than 0.");const b={partnerName:t.partnerName,subProductId:r,interestType:n,loanTermMonths:o,discountRate:a,effectiveDate:t.effectiveDate,expirationDate:t.expirationDate,confirmOverlap:!1};this.submitDiscount(b)}submitDiscount(t){this.submitting=!0,this.responseMessage="",this.responseType="",this.executorService.query("/admin/partner-discounts","POST",t).subscribe({next:()=>{this.submitting=!1,this.responseType="success",this.responseMessage="Partner discount applied successfully.",this.loadPartnerDiscounts()},error:r=>{this.submitting=!1,this.handleSubmitError(r,t)}})}handleSubmitError(t,r){const e=t&&t.error?t.error:{};if("PD_DATE_OVERLAP_DETECTED"===e.code&&!0===e.promptMessage&&!r.confirmOverlap)return void this.sharedService.showConfirm({title:"Confirm Overwrite",message:e.data||"Date overlap detected for this discount combination. Do you want to overwrite?",uid:"MODAL_PARTNER_DISCOUNT_OVERLAP",confirmCB:()=>{const a={...r,confirmOverlap:!0};this.submitDiscount(a)},cancelCB:()=>{this.responseType="error",this.responseMessage="Discount apply cancelled."}});const n=e.message||e.error||e.data,o=e.code;this.responseType="error",this.responseMessage=n?"Unable to apply partner discount: "+n:o?"Unable to apply partner discount. Server error code: "+o:"Unable to apply partner discount. Please try again."}static{this.ctorParameters=()=>[{type:i.ok},{type:y.n},{type:D.d}]}};p=function(l,t,r,e){var o,s=arguments.length,n=s<3?t:null===e?e=Object.getOwnPropertyDescriptor(t,r):e;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(l,t,r,e);else for(var a=l.length-1;a>=0;a--)(o=l[a])&&(n=(s<3?o(n):s>3?o(t,r,n):o(t,r))||n);return s>3&&n&&Object.defineProperty(t,r,n),n}([(0,u.uAl)({selector:"partner-discount",template:'<div class="discount-page">\r\n    <div class="col-lg-12">\r\n        <div class="pt-1 pb-2">\r\n            <h4 class="my-2">Partners Discount</h4>\r\n        </div>\r\n\r\n        <div class="discount-card">\r\n            <form [formGroup]="discountForm" (ngSubmit)="onApply()" autocomplete="off">\r\n                <div class="row align-items-end">\r\n                    <div class="col-lg-2 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Partner Name</label>\r\n                            <select class="form-control b-input-box" formControlName="partnerName"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'partnerName\').invalid && discountForm.get(\'partnerName\').touched}">\r\n                                <option value="">Please Select</option>\r\n                                <option *ngFor="let partner of partnerOptions" [ngValue]="partner.value">{{partner.label}}</option>\r\n                            </select>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-3 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Product Name</label>\r\n                            <select class="form-control b-input-box" formControlName="productName" (change)="onProductChange()"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'productName\').invalid && discountForm.get(\'productName\').touched}">\r\n                                <option value="">Please Select</option>\r\n                                <option *ngFor="let product of productOptions" [ngValue]="product.subProductId">{{product.name}}</option>\r\n                            </select>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-2 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Interest Type</label>\r\n                            <select class="form-control b-input-box" formControlName="interestType"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'interestType\').invalid && discountForm.get(\'interestType\').touched}">\r\n                                <option value="">Please Select</option>\r\n                                <option *ngFor="let interestType of interestTypeOptions" [ngValue]="interestType">{{interestType}}</option>\r\n                            </select>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-2 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Loan Term</label>\r\n                            <select class="form-control b-input-box" formControlName="loanTerm"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'loanTerm\').invalid && discountForm.get(\'loanTerm\').touched}">\r\n                                <option value="">Please Select</option>\r\n                                <option *ngFor="let loanTerm of loanTermOptions" [ngValue]="loanTerm">{{loanTerm}}</option>\r\n                            </select>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-2 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Discount Rate (%)</label>\r\n                            <input type="text" class="form-control b-input-box" formControlName="discountRate" maxlength="6"\r\n                                (input)="onDiscountRateInput($event)"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'discountRate\').invalid && discountForm.get(\'discountRate\').touched}">\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-2 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Effective Date</label>\r\n                            <input type="date" class="form-control b-input-box" formControlName="effectiveDate"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'effectiveDate\').invalid && discountForm.get(\'effectiveDate\').touched}">\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-2 col-md-6 col-12">\r\n                        <div class="form-group ld-form-cus">\r\n                            <label class="borrower-labels">Expiration Date</label>\r\n                            <input type="date" class="form-control b-input-box" formControlName="expirationDate"\r\n                                [ngClass]="{\'has-error\': discountForm.get(\'expirationDate\').invalid && discountForm.get(\'expirationDate\').touched}">\r\n                        </div>\r\n                    </div>\r\n\r\n                    <div class="col-lg-2 col-md-6 col-12 text-right discount-apply-btn-wrap">\r\n                        <button type="submit" class="button-new-css upload-btn-cus mob-mar-0 w-100" [disabled]="submitting">\r\n                            {{submitting ? \'Applying...\' : \'Apply\'}}\r\n                        </button>\r\n                    </div>\r\n                </div>\r\n            </form>\r\n\r\n            <div class="row" *ngIf="discountForm.get(\'expirationDate\').hasError(\'invalidDateRange\') && discountForm.get(\'expirationDate\').touched">\r\n                <div class="col-12">\r\n                    <div class="cus-common-err-msg mt-2">Expiration date should be greater than or equal to effective date.</div>\r\n                </div>\r\n            </div>\r\n\r\n            <div class="row" *ngIf="responseMessage">\r\n                <div class="col-12">\r\n                    <div class="mt-2" [ngClass]="responseType === \'success\' ? \'discount-success-msg\' : \'cus-common-err-msg\'">{{responseMessage}}</div>\r\n                </div>\r\n            </div>\r\n\r\n            <div class="partner-discount-table-wrap mt-3">\r\n                <h5 class="mb-2">Partner Discount List</h5>\r\n\r\n                <div *ngIf="loadingDiscounts" class="discount-table-state">Loading partner discounts...</div>\r\n\r\n                <div *ngIf="!loadingDiscounts" class="table-responsive">\r\n                    <table class="table table-sm table-bordered table-hover discount-table mb-0" *ngIf="partnerDiscounts.length; else noDiscountRows">\r\n                        <thead>\r\n                            <tr>\r\n                                <th (click)="sortBy(\'partnerName\')" class="sortable">Partner Name <span class="sort-indicator">{{getSortIndicator(\'partnerName\')}}</span></th>\r\n                                <th (click)="sortBy(\'productName\')" class="sortable">Product Name <span class="sort-indicator">{{getSortIndicator(\'productName\')}}</span></th>\r\n                                <th (click)="sortBy(\'discountRate\')" class="sortable">Discount Rate <span class="sort-indicator">{{getSortIndicator(\'discountRate\')}}</span></th>\r\n                                <th (click)="sortBy(\'isActive\')" class="sortable">Is Active <span class="sort-indicator">{{getSortIndicator(\'isActive\')}}</span></th>\r\n                                <th (click)="sortBy(\'effectiveDate\')" class="sortable">Effective Date <span class="sort-indicator">{{getSortIndicator(\'effectiveDate\')}}</span></th>\r\n                                <th (click)="sortBy(\'expirationDate\')" class="sortable">Expiration Date <span class="sort-indicator">{{getSortIndicator(\'expirationDate\')}}</span></th>\r\n                                <th (click)="sortBy(\'interestType\')" class="sortable">Interest Type <span class="sort-indicator">{{getSortIndicator(\'interestType\')}}</span></th>\r\n                                <th (click)="sortBy(\'loanTermMonths\')" class="sortable">Loan Term Months <span class="sort-indicator">{{getSortIndicator(\'loanTermMonths\')}}</span></th>\r\n                            </tr>\r\n                        </thead>\r\n                        <tbody>\r\n                            <tr *ngFor="let item of partnerDiscounts">\r\n                                <td>{{item.partnerName}}</td>\r\n                                <td>{{item.productName}}</td>\r\n                                <td>{{item.discountRate | number:\'1.2-2\'}}</td>\r\n                                <td>{{item.isActive ? \'Yes\' : \'No\'}}</td>\r\n                                <td>{{item.effectiveDate || \'-\'}}</td>\r\n                                <td>{{item.expirationDate || \'-\'}}</td>\r\n                                <td>{{item.interestType}}</td>\r\n                                <td>{{item.loanTermMonths === 0 ? \'ALL\' : item.loanTermMonths}}</td>\r\n                            </tr>\r\n                        </tbody>\r\n                    </table>\r\n\r\n                    <ng-template #noDiscountRows>\r\n                        <div class="discount-table-state">No partner discounts found.</div>\r\n                    </ng-template>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    </div>\r\n</div>\r\n\r\n',standalone:!1,styles:[P()]}),function(l,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(l,t)}("design:paramtypes",[i.ok,y.n,D.d])],p);const I=[{path:"",component:p,canActivate:[c(9318).q]}];let f=class{};f=function(l,t,r,e){var o,s=arguments.length,n=s<3?t:null===e?e=Object.getOwnPropertyDescriptor(t,r):e;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(l,t,r,e);else for(var a=l.length-1;a>=0;a--)(o=l[a])&&(n=(s<3?o(n):s>3?o(t,r,n):o(t,r))||n);return s>3&&n&&Object.defineProperty(t,r,n),n}([(0,u.UQu)({imports:[i.YN,i.X1,T.G,d.iI.forChild(I)],declarations:[p],exports:[d.iI]})],f)},6530(m,v,c){var u=c(8564),d=c(8557)(u);d.push([m.id,".discount-page {\n  margin-top: -8px;\n  padding: 8px 20px 20px;\n}\n.discount-page .discount-card {\n  background: #efefef;\n  border: 1px solid #d7d7d7;\n  border-radius: 4px;\n  padding: 16px;\n}\n.discount-page .discount-apply-btn-wrap {\n  align-self: flex-end;\n  margin-bottom: 1rem;\n}\n.discount-page .discount-success-msg {\n  color: #1a7f37;\n  font-size: 14px;\n}\n.discount-page .cus-common-err-msg {\n  color: #d32f2f;\n  font-size: 14px;\n}\n.discount-page .partner-discount-table-wrap .discount-table {\n  background: #fff;\n}\n.discount-page .partner-discount-table-wrap .discount-table th {\n  font-weight: 600;\n}\n.discount-page .partner-discount-table-wrap .discount-table td {\n  font-weight: 400;\n}\n.discount-page .partner-discount-table-wrap .sortable {\n  cursor: pointer;\n  -webkit-user-select: none;\n          user-select: none;\n  white-space: nowrap;\n}\n.discount-page .partner-discount-table-wrap .sort-indicator {\n  display: inline-block;\n  width: 12px;\n  text-align: center;\n}\n.discount-page .partner-discount-table-wrap .discount-table-state {\n  font-size: 14px;\n  color: #555;\n  padding: 8px 0;\n}",""]),m.exports=d.toString()}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.