/** * Gets the rate set filtered by agents rate ID and risk area * * @param int $agentRateID * @param int $riskArea * @return Model_Insurance_Rate */ public function getRateSet($agentRateID, $riskArea, $rateSetID) { $rateModel = new Model_Insurance_Rate(); if ($rateSetID == 0 || $rateSetID == -1) { $select = $this->select()->where('endDate >= NOW() OR endDate = "0000-00-00"')->where('agentsRateID = ?', $agentRateID)->where('riskarea = ?', $riskArea); } else { $select = $this->select()->where('rateSetID = ?', $rateSetID)->where('riskarea = ?', $riskArea); } $rate = $this->fetchRow($select); if (count($rate) > 0) { $rateModel->rateSetID = $rate->rateSetID; $rateModel->rateName = $rate->rateName; $rateModel->riskArea = $rate->riskarea; $rateModel->contentstpb = $rate->contentstpb; $rateModel->contentstpa_banda = $rate->contentstpa_banda; $rateModel->contentstpa_bandb = $rate->contentstpa_bandb; $rateModel->contentstpa_bandc = $rate->contentstpa_bandc; $rateModel->contentstpa_bandd = $rate->contentstpa_bandd; $rateModel->possessionsp_banda = $rate->possessionsp_banda; $rateModel->possessionsp_bandb = $rate->possessionsp_bandb; $rateModel->possessionsp_bandc = $rate->possessionsp_bandc; $rateModel->possessionsp_bandd = $rate->possessionsp_bandd; $rateModel->pedalcyclesp = $rate->pedalcyclesp; $rateModel->specpossessionsp = $rate->specpossessionsp; //The TCI+ rates were originally written for IPT at 5%, as this was something that hadn't //changed in over a thousand years. However, IPT suddenly started to change every few months, //switching restlessly between 5% and 6%, and so the best developers in the land were gathered //together to devise an engineering solution to accommodate this... $taxDatasource = new Datasource_Core_Tax(); $tax = $taxDatasource->getTaxbyType('ipt'); if ($tax['rate'] == 6) { //Behold repugnance: $fudge = 1.05 / 1.06; $rateModel->contentstpa_banda = round($rateModel->contentstpa_banda * $fudge, 4); $rateModel->contentstpa_bandb = round($rateModel->contentstpa_bandb * $fudge, 4); $rateModel->contentstpa_bandc = round($rateModel->contentstpa_bandc * $fudge, 4); $rateModel->contentstpa_bandd = round($rateModel->contentstpa_bandd * $fudge, 4); $rateModel->contentstpb = round($rateModel->contentstpb * $fudge, 6); $rateModel->possessionsp_banda = round($rateModel->possessionsp_banda * $fudge, 4); $rateModel->possessionsp_bandb = round($rateModel->possessionsp_bandb * $fudge, 4); $rateModel->possessionsp_bandc = round($rateModel->possessionsp_bandc * $fudge, 4); $rateModel->possessionsp_bandd = round($rateModel->possessionsp_bandd * $fudge, 4); $rateModel->pedalcyclesp = round($rateModel->pedalcyclesp * $fudge, 4); $rateModel->specpossessionsp = round($rateModel->specpossessionsp * $fudge, 4); } } else { // Can't find rates - log a warning Application_Core_Logger::log("Can't find rates in table {$this->_name} (agentsRateID = {$agentRateID}, riskarea = {$riskArea})", 'warning'); } return $rateModel; }
/** * Calculate the Premium * */ public function calculatePremiums() { Application_Core_Logger::log('Calculating Premiums', 'info'); // Split the sum insured amounts $amountsCovered = explode('|', $this->_quoteModel->amountsCovered); $contentsSumInsured = $amountsCovered[0]; $pedalCyclesSumInsured = $amountsCovered[1]; $specifiedPossessionsSumInsured = $amountsCovered[2]; $unspecifiedPossessionsSumInsured = $amountsCovered[3]; // Get IPT percentage unless we are doing just a quick quote if (isset($this->_quoteModel->ID)) { $propertiesDatasource = new Datasource_Insurance_Quote_Properties(); $properties = $propertiesDatasource->getByQuoteID($this->_quoteModel->ID); $postcode = $properties[0]['postcode']; $taxDatasource = new Datasource_Core_Tax(); $tax = $taxDatasource->getTaxbyTypeAndPostcode('ipt', $postcode); $ipt = 1 + $tax['rate'] / 100; } else { // We're just doing a quick quote so just get the regular ipt $taxDatasource = new Datasource_Core_Tax(); $tax = $taxDatasource->getTaxbyType('ipt'); $ipt = 1 + $tax['rate'] / 100; } // Zero the premium amounts $premiums = new Model_Insurance_TenantsContentsPlus_Premiums(); // TODO: This rating engine is flawed and produces un-rounded values. // Need to replace this with the landlords CORE rating engine which is currently unfinished. // Load the rates $ratesManager = new Manager_Insurance_TenantsContentsPlus_Rates($this->_quoteModel->agentRateSetID, $this->_quoteModel->riskArea, $this->_rateSetID); $ratesManager->setCoverAmounts($contentsSumInsured, $unspecifiedPossessionsSumInsured); // Fetch the rate set ID and store it in the object $this->_quoteModel->rateSetID = $ratesManager->getSetID(); // Now we have the rate set ID - let's get the rates $contentsRate = $ratesManager->getContentsRate(); $pedalCyclesRate = $ratesManager->getPedalCyclesRate(); $specifiedPossessionsRate = $ratesManager->getSpecifiedPossessionsRate(); $unspecifiedPossessionsRate = $ratesManager->getUnspecifiedPossessionsRate(); // Calculate premiums if ($contentsSumInsured > 0) { if ($contentsSumInsured > 15000) { $premiums->contents = $contentsRate * $ipt * ($contentsSumInsured / 1000); } else { $premiums->contents = $contentsRate * $ipt; } } if ($pedalCyclesSumInsured >= 200) { $premiums->pedalCycles = round($pedalCyclesRate * $pedalCyclesSumInsured / 100 * $ipt, 3); } else { $premiums->pedalCycles = 0; } if ($specifiedPossessionsSumInsured > 0) { $premiums->specifiedPossessions = round($specifiedPossessionsSumInsured / 100 * $specifiedPossessionsRate * $ipt, 3); } if ($unspecifiedPossessionsSumInsured > 0) { $premiums->unspecifiedPossessions = $unspecifiedPossessionsRate * $ipt; } // Calculate totals with Loadings $premiums->annualTotal = ($premiums->contents + $premiums->pedalCycles + $premiums->specifiedPossessions + $premiums->unspecifiedPossessions) * $this->_quoteModel->discountLoading * 12; $premiums->annualIptAmount = $premiums->annualTotal - $premiums->annualTotal / $ipt; $premiums->total = ($premiums->contents + $premiums->pedalCycles + $premiums->specifiedPossessions + $premiums->unspecifiedPossessions) * $this->_quoteModel->discountLoading; $premiums->iptAmount = $premiums->total - $premiums->total / $ipt; // Apply loadings to individual breakdowns $premiums->contents = $premiums->contents * $this->_quoteModel->discountLoading; $premiums->pedalCycles = $premiums->pedalCycles * $this->_quoteModel->discountLoading; $premiums->specifiedPossessions = $premiums->specifiedPossessions * $this->_quoteModel->discountLoading; $premiums->unspecifiedPossessions = $premiums->unspecifiedPossessions * $this->_quoteModel->discountLoading; // Update the optionpremiums field in the database // These are rounded to 2 decimal places and do not include IPT $optionPremiums = explode('|', $this->_quoteModel->optionPremiums); $optionPremiums[0] = round($premiums->contents / $ipt, 2); $optionPremiums[1] = round($premiums->pedalCycles / $ipt, 2); $optionPremiums[2] = round($premiums->specifiedPossessions / $ipt, 2); $optionPremiums[3] = round($premiums->unspecifiedPossessions / $ipt, 2); $optionPremiums[4] = 0; $optionPremiums = implode('|', $optionPremiums); // Calculate annual individual breakdowns $premiums->annualContents = $premiums->contents * $this->_quoteModel->discountLoading * 12; $premiums->annualPedalCycles = $premiums->pedalCycles * $this->_quoteModel->discountLoading * 12; $premiums->annualSpecifiedPossessions = $premiums->specifiedPossessions * $this->_quoteModel->discountLoading * 12; $premiums->annualUnspecifiedPossessions = $premiums->unspecifiedPossessions * $this->_quoteModel->discountLoading * 12; // Now that ALL calculations are done we can safely round to 2 decimal places $premiums->annualTotal = round($premiums->annualTotal, 2); $premiums->annualIptAmount = round($premiums->annualIptAmount, 2); $premiums->total = round($premiums->total, 2); $premiums->iptAmount = round($premiums->iptAmount, 2); $premiums->contents = round($premiums->contents, 2); $premiums->pedalCycles = round($premiums->pedalCycles, 2); $premiums->specifiedPossessions = round($premiums->specifiedPossessions, 2); $premiums->unspecifiedPossessions = round($premiums->unspecifiedPossessions, 2); $premiums->annualContents = round($premiums->annualContents, 2); $premiums->annualPedalCycles = round($premiums->annualPedalCycles, 2); $premiums->annualSpecifiedPossessions = round($premiums->annualSpecifiedPossessions, 2); $premiums->annualUnspecifiedPossessions = round($premiums->annualUnspecifiedPossessions, 2); if ($this->getPayBy() == "Annually") { $this->_quoteModel->premium = $premiums->annualTotal - $premiums->annualIptAmount; $this->_quoteModel->ipt = $premiums->annualIptAmount; $this->_quoteModel->quote = $premiums->annualTotal; } else { $this->_quoteModel->premium = $premiums->total - $premiums->iptAmount; $this->_quoteModel->ipt = $premiums->iptAmount; $this->_quoteModel->quote = $premiums->total; } $this->_quoteModel->optionPremiums = $optionPremiums; $amountsCovered[4] = "no"; $this->_quoteModel->amountsCovered = implode('|', $amountsCovered); $this->_save(); return $premiums; }