package gw.lob.cp.rating.dtobased uses entity.PolicyLine uses entity.windowed.CPBuildingCovCostVersionList uses entity.windowed.CPBuildingCovVersionList uses entity.windowed.CPBuildingVersionList uses gw.api.productmodel.Offering uses gw.api.profiler.PCProfilerTag uses gw.api.rating.dtobased.accessors.cp.CPLineDAO uses gw.api.rating.dtobased.data.CoverageDTO uses gw.api.rating.dtobased.data.EffDatedDTO uses gw.api.rating.dtobased.data.cp.CPBuildingCovDTO uses gw.api.rating.dtobased.data.cp.CPLineDTO uses gw.api.rating.dtobased.data.cp.CPLocationDTO uses gw.job.RenewalProcess uses gw.lob.cp.rating.* uses gw.rating.CostData uses gw.rating.RateFlowLogger uses gw.rating.dtobased.AbstractDTOParallelRatingEngine /** * In the base configuration, CPDTORatingEngine extends AbstractDTOParallelRatingEngine and rates the CPLocationDTOs in parallel. * Implementing parallelization in a child of AbstractParallelRatingEngine requires the following: *
    *
  1. * Steps of setup and cleanup. * In method {@link #rateSlice(CPLine)} you must call method {@link #preRateStep} before the rating code and * {@link #postRateStep} after the rating code. *
  2. *
  3. * Replace the loop of CPLocationDTOs with a call to method {@link #rateInParallel}. * In method rateSlice, the loop of CPLocationDTOs is replaced by a call to rateInParallel. The contents of the loop * becomes a code block which is passed to method rateInParallel as the second argument. The collection of CPLocationDTOs * is passed to method rateInParallel as the first argument. *
  4. *
  5. * Call {@link #handleFutures(List)} on all the Futures returned from rateInParallel. * Do this immediately following the rateInParallel method. *
  6. *
*/ @Export class CPDTORatingEngine extends AbstractDTOParallelRatingEngine { static var _rfLogger = RateFlowLogger.Logger var _baseRatingDate : Date var _jurisdiction : Jurisdiction var _minimumRatingLevel : RateBookStatus var _renewal : boolean var _uwCompany : UWCompany var _offering : Offering var _linePatternCode : String construct(line : CPLine) { this(line, RateBookStatus.TC_ACTIVE) } construct(line : CPLine, minimumRatingLevel : RateBookStatus) { super(line) _minimumRatingLevel = minimumRatingLevel // Populate most of the instance vars from line _jurisdiction = line.BaseState _baseRatingDate = line.Branch.RateAsOfDate _renewal = line.Branch.JobProcess typeis RenewalProcess _uwCompany = line.Branch.UWCompany _offering = line.Branch.Offering _linePatternCode = line.PolicyLine.PatternCode } // CP is rated on a 365-day term override protected property get NumDaysInCoverageRatedTerm() : int { return 365 } override protected function existingSliceModeCosts() : Iterable { return PolicyLine.Costs.whereTypeIs(CPBuildingCovCost) } // Used by the extractCostDatasFromExistingCosts method. Must be implemented if that method is going to be called override protected function createCostDataForCost(c : Cost) : CPCostData { switch(typeof c) { case CPBuildingCovBroadCost: return new CPBuildingCovBroadCostData(c, RateCache) case CPBuildingCovGrp1Cost: return new CPBuildingCovGroup1CostData(c, RateCache) case CPBuildingCovGrp2Cost: return new CPBuildingCovGroup2CostData(c, RateCache) case CPBuildingCovSpecCost: return new CPBuildingCovSpecialCostData(c, RateCache) default: throw "Unexpected cost type ${c.DisplayName}" } } override function preLoadCostArrays() { PolicyLine.VersionList.CPLocations.arrays("Buildings") .arrays("Coverages") .arrays("Costs") } //=========================================================================== // Rate Flow //=========================================================================== protected override function rateWindow(lineVersion : CPLine) { var cpBuildingCovCostDatas = CostDatas as List var basesMap = cpBuildingCovCostDatas.partition(\ c -> c.State).mapValues(\ l -> l.sum(\ c -> c.ActualAmountBilling.Amount)) for (st in basesMap.Keys) { var subtotal = basesMap.get(st) if (subtotal == 0) { continue } var costData = new CPStateTaxCostData(lineVersion.Branch.PeriodStart, lineVersion.Branch.PeriodEnd,TaxRatingCurrency, RateCache, st) costData.Overridable = false costData.NumDaysInRatedTerm = lineVersion.Branch.NumDaysInPeriod var rateRoutineParameterMap : Map = {TC_POLICYLINE ->PolicyLine, TC_TAXABLEBASIS ->subtotal, TC_STATE ->st} var refDate = Branch.PeriodStart //This will return a CP ratebook that has generic rateBook in its hierarchy var genericRateBook = getRateBook(refDate, lineVersion.Branch.Offering.PublicID, _linePatternCode) costData.RateBook = genericRateBook genericRateBook.executeCalcRoutine("gx_state_tax_rr", costData, costData, rateRoutineParameterMap) costData.StandardAmount = costData.StandardTermAmount costData.copyStandardColumnsToActualColumns() // no overrides addCost(costData) if (_rfLogger.DebugEnabled) { logDebugRatedCost(costData) } } } protected override function rateSlice(lineVersion : CPLine) { PolicyLine = lineVersion // This also sets the PolicyLineDTO if (PolicyLineDTO.CanceledSlice) { if (_rfLogger.DebugEnabled) { _rfLogger.debug("Not rating " + PolicyLineDTO + " " + PolicyLineDTO.SliceDate + " version because it is in the cancelled period of time.") } } else { _rfLogger.info("Rating " + PolicyLineDTO + " " + PolicyLineDTO.SliceDate + " version...") preRateStep(lineVersion) var buildingLocations = PolicyLineDTO.CPLocations.where(\location -> location.Buildings.HasElements) try { var futures = rateInParallel(buildingLocations.toList(), \location -> { //Signature for rateInParallel() takes doRating(item : E) where E is EffDated... var cpLocationDTO = location as CPLocationDTO //... so we call rateLocation() after type casting location from EffDated to CPLocationDTO using(PCProfilerTag.RATE_CP_LOCATION) { rateLocation(cpLocationDTO) } }) handleFutures(futures) _rfLogger.info("Rating " + PolicyLineDTO + " " + PolicyLineDTO.SliceDate + " version...Done") } finally { // Apply staged cost data. Shutdown the thread pool when all threads are done rating or when the first // exception occurs. End the worksheet container processing which will update the worksheet container if // running in parallel postRateStep() } } } /** * Rate the location. This function is passed into the rateInParallel method in the rateSlice * method. It will be executed in parallel if the engine is configured to run in parallel, otherwise it will run * single threaded. * @param location the location that will be rated. */ private function rateLocation(location : CPLocationDTO) { /* * Within rateInParallel, each bean (in this case location) is looked up in the child thread's bundle. So * we use the CPLine from this location in the child thread */ var lineVersion = location.CPLine if (_rfLogger.DebugEnabled) { _rfLogger.debug("Rating " + location + "...") } for (building in location.Buildings) { if (Thread.currentThread().isInterrupted()) { // Stop rating the rest of the buildings if the thread has already been interrupted (most likely due to timeout). _rfLogger.info("Rating " + location + "...Interrupted") return } if (_rfLogger.DebugEnabled) { _rfLogger.debug("Rating " + building + "...") } // All coverages on CP are referenced to the Coverable reference date. If this were not so, we would // want to loop over the coverages, and call ReferenceDatePlugin.getCoverageReferenceDate() for each one. using (PCProfilerTag.RATE_CP_BUILDING) { var rateBook : RateBook using (PCProfilerTag.GET_CP_BUILDING_RATE_BOOK) { rateBook = getCPRateBook(building.CoverableReferenceDate, lineVersion.Branch.OfferingCode) } for (cov in building.Coverages) { // not including cost datas that have a zero term amount var costs = rateCPBuildingCov(cov, rateBook) addStagedCosts(costs.where(\c -> c.StandardTermAmount != 0)) } } if (_rfLogger.DebugEnabled) { _rfLogger.debug("Rating " + building + "...") } } if (_rfLogger.DebugEnabled) { _rfLogger.debug("Rating " + location + "...Done") } } private function rateCPBuildingCov(cov : CPBuildingCovDTO, rateBook : RateBook) : List { var costs = new LinkedList() return rateCPBuildingCov(cov, costs, rateBook, cov.CauseOfLoss) } private function rateCPBuildingCov(cov : CPBuildingCovDTO, costs: List, rateBook : RateBook, causeOfLoss : CPCauseOfLoss) : List { var routineName = getRateRoutineName(cov) var params = createParamMap(cov, "cpDeductGrp1") costs.add(executeCPRateRoutine(cov, createCostData(cov, "cpDeductGrp1"), rateBook, params, routineName)) updateDeductFactor(params, "cpDeductGrp2") costs.add(executeCPRateRoutine(cov, createCostData(cov, "cpDeductGrp2"), rateBook, params, routineName)) if (causeOfLoss == TC_BROAD or causeOfLoss == TC_SPECIAL) { updateDeductFactor(params, "cpDeductBroad") costs.add(executeCPRateRoutine(cov, createCostData(cov, "cpDeductBroad"), rateBook, params, routineName)) } if (causeOfLoss == TC_SPECIAL) { updateDeductFactor(params, "cpDeductSpecial") costs.add(executeCPRateRoutine(cov, createCostData(cov, "cpDeductSpecial"), rateBook, params, routineName)) } return costs } private function executeCPRateRoutine (cov: CPBuildingCovDTO, data: CPBuildingCovCostData, rateBook : RateBook, rateRoutineParameterMap: Map, rateRoutineName: String) : CPBuildingCovCostData { data.NumDaysInRatedTerm = this.NumDaysInCoverageRatedTerm data.Basis = 1 data.RateBook = rateBook rateBook.executeCalcRoutine(rateRoutineName, data, data, rateRoutineParameterMap) if (_rfLogger.DebugEnabled) { _rfLogger.debug("Rate " + cov.PatternCode) _rfLogger.debug(" Standard Base Rate: ${data.StandardBaseRate}") _rfLogger.debug(" Standard Adjusted Rate: ${data.StandardAdjRate}") _rfLogger.debug(" Standard Term Amount: ${data.StandardTermAmount}") } return data } protected override function initializeCostWrappers(lineVersion : PolicyLine) { var costs = lineVersion.CostVLs.allVersions(true) costs.Keys.where(\VL -> costs[VL].first() typeis CPBuildingCovCost).forEach(\costVL -> { var cost = costVL.getVersionAsOf(lineVersion.SliceDate) as CPBuildingCovCost if (cost != null) { addCostWrapper(cost, cost.Coverage.FixedId) } }) } //=========================================================================== // Utility Functions //=========================================================================== private function createCostData(cov: CPBuildingCovDTO, deductFactorName: String): CPBuildingCovCostData { var start = cov.SliceDate var end = getNextSliceDateAfter(start) var state = cov.CPBuilding.Jurisdiction // This code is simplified vs. the entity rating engine var cpCostData : CPBuildingCovCostData switch (deductFactorName) { case ("cpDeductGrp1") : cpCostData = new CPBuildingCovGroup1CostData(start, end, cov.Currency, RateCache, cov.FixedId, state) break case ("cpDeductGrp2") : cpCostData = new CPBuildingCovGroup2CostData(start, end, cov.Currency, RateCache, cov.FixedId, state) break case ("cpDeductBroad") : cpCostData = new CPBuildingCovBroadCostData(start, end, cov.Currency, RateCache, cov.FixedId, state) break case ("cpDeductSpecial") : cpCostData = new CPBuildingCovSpecialCostData(start, end, cov.Currency, RateCache, cov.FixedId, state) break default: throw "Unknown Deductible Factor Name" } cpCostData.init(getCostWrapper(cov.FixedId, cpCostData), PolicyLineDTO.QuoteRoundingLevel, PolicyLineDTO.QuoteRoundingMode) return cpCostData } private function getCPRateBook( refDate : Date, offeringCode : String ) : RateBook { return getRateBook(refDate, offeringCode, _linePatternCode) } private function getGenericRateBook( refDate : Date, offeringCode : String ) : RateBook { return getRateBook(refDate, offeringCode, null) } private function getRateBook(refDate : Date, offeringCode : String, linePatternCode : String ) : RateBook { return RateBook.selectRateBook(refDate, _baseRatingDate, linePatternCode, _jurisdiction, _minimumRatingLevel, _renewal, offeringCode, _uwCompany) } private function getRateRoutineName(cov: CoverageDTO) : String { switch (cov.PatternCode) { case "CPBldgCov": case "CPBPPCov": return "cp_cov_premium_rr_dto" default: throw "No rate routine defined for " + cov.PatternCode + " coverage" } } private function updateDeductFactor(params : Map, factorName : String) { params.put(TC_CPDEDUCTFACTORNAME, factorName) } private function createParamMap(cov: CPBuildingCovDTO, deductFactorName: String) : Map { switch (cov.PatternCode) { case "CPBldgCov": case "CPBPPCov": return {TC_POLICYLINE->PolicyLineDTO, TC_BUILDING ->cov.CPBuilding, TC_COVERAGE -> cov, TC_CPDEDUCTFACTORNAME -> deductFactorName} default: throw "No rate routine param set defined for " + typeof cov + " coverage" } } private function logDebugRatedCost(costData : CostData) { logDebugRatedCost("Rated", costData) } private function logDebugRatedCost(preMsg : String, costData : CostData) { if (_rfLogger.DebugEnabled) { _rfLogger.debug(preMsg + " " + costData.debugString() + " for " + costData) } } protected override function createPolicyLineDTO(line: CPLine): CPLineDTO { return new CPLineDAO(line).DTO } }