Skip to content

Instantly share code, notes, and snippets.

@epochwolf
Created May 22, 2012 21:35
Show Gist options
  • Save epochwolf/187d24af5fe3f7bc092c to your computer and use it in GitHub Desktop.
Save epochwolf/187d24af5fe3f7bc092c to your computer and use it in GitHub Desktop.
require 'active_support/builder' unless defined?(Builder)
class AcordWriter
def initialize(policy)
@xml_string = ""
builder = ::Builder::XmlMarkup.new(target:@xml_string, indent:4)
build_acord(builder, policy)
end
def to_xml
@xml_string
end
def build_acord(xml, policy)
ns = {
"xsi:noNamespaceSchemaLocation" => "acord-pcs-v1_20_0-nodoc-codes.xsd",
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"
}
xml.instruct!
xml.instruct!("ACORD", "ACORD" => "1.20.0")
xml.ACORD(ns){
build_sign_on_request(xml, policy)
build_service_request(xml, policy)
build_vpi_extension(xml, policy)
}
end
def build_sign_on_request(xml, policy)
xml.comment! "Sign On Request"
xml.SignonRq{
xml.SignonPswd{
xml.CustId{
xml.SPName "policyissuance.vertafore.com"
xml.CustLoginId "kevin_pga"
}
xml.CustPswd{
xml.EncryptionTypeCd "NONE"
xml.Pswd "138feeb3eed9f0eaa792156e217cad1b"
}
}
xml.ClientDt dt(Date.today)
xml.CustLangPref "en-US"
xml.ClientApp{
xml.Org "Vertafore"
xml.Name "PolicyBuilder"
xml.Version "0.1"
}
}
end
def build_service_request(xml, policy)
xml.comment! "Service Request"
xml.InsuranceSvcRq{
xml.RqUID String.uuid # always a new random value, app doesn't track requests.
xml.tag!(policy.service_request){
xml.RqUID String.uuid # always a new random value, app doesn't track requests.
xml.ItemIdInfo{
xml.SystemId policy.guid
xml.comment! "OtherIdentifier is Policy Builder's primary key for this policy"
xml.OtherIdentifier policy.id
}
xml.TransactionRequestDt dt(Date.today)
xml.CurCd "USD"
xml.BroadLOBCd "C" # Commercial lines
xml.ACORDStandardVersionCd "1120"
build_producers(xml, policy)
build_insured_or_principal(xml, policy)
build_pc_policy(xml, policy)
build_locations(xml, policy)
build_lob(xml, policy)
build_comml_sublocations(xml, policy)
build_remarks(xml, policy)
}
}
end
def build_producers(xml, policy)
xml.comment! "General Agent"
xml.Producer {
xml.ItemIdInfo {
#xml.AgencyId '' # Comes from AIM. Do I need this?
xml.InsurerId policy.carrier_ga_code
xml.SystemId policy.general_agent_id if policy.general_agent
}
build_general_party(xml, policy.general_agent) if policy.general_agent
xml.ProducerInfo {
# xml.ContractNumber '' # What does this do?
# xml.PlacingOffice '' # Name for the GA?
xml.ProducerRoleCd 'Intermediary'
# xml.FieldOfficeCd '' # Similar to PlacingOffice?
xml.License { xml.LicensePermitNumber policy.surplus_lines_license }
}
}
xml.comment! "Retail Agent"
if agent = policy.retail_agent
xml.Producer {
xml.ItemIdInfo {
#xml.AgencyId '' # Comes from AIM. Do I need this?
xml.InsurerId agent.agent_code
xml.SystemId agent.id
}
build_general_party(xml, agent)
xml.ProducerInfo {
xml.ProducerRoleCd 'Agency'
}
}
end
end
def build_insured_or_principal(xml, policy)
xml.comment! "Insured"
if insured = policy.insured
xml.InsuredOrPrincipal{
xml.ItemIdInfo {
xml.SystemId insured.id
}
build_general_party(xml, insured)
xml.InsuredOrPrincipalInfo {
xml.InsuredOrPrincipalRoleCd 'Insured'
xml.BusinessInfo {
xml.SICCd insured.sic_code
# xml.OperationsDesc '' # Old tag??? Does that mean don't use it?
}
}
}
end
end
def build_pc_policy(xml, policy)
xml.comment! "PcPolicy"
xml.tag!("CommlPolicy"){
xml.PolicyNumber policy.number
xml.CompanyProductCd policy.program_code
xml.LOBCd policy.lob_code
xml.NAICCd policy.carrier_naic
xml.ContractTerm{
xml.EffectiveDt dt policy.effective_at
xml.ExpirationDt dt policy.expires_at
}
xml.CurrentTermAmt{ xml.Amt policy.premium }
if policy.renewal_of_number.present?
xml.OtherOrPriorPolicy {
xml.PolicyCd "Prior"
xml.PolicyNumber policy.renewal_of_number
xml.LOBCd policy.lob_code
}
end
build_additional_interests(xml, policy.additional_interests.where(:building_id => nil))
xml.MinPremInd policy.minimum_premium.blank? ? 0 : 1
xml.MinPremAmt{ xml.Amt policy.minimum_premium } unless policy.minimum_premium.blank?
xml.CommlPolicySupplement{
xml.AuditInd policy.audit_code.blank? ? 0 : 1
xml.AuditFrequencyCd{ xml.Amt policy.audit_code } unless policy.audit_code.blank?
build_taxes_fees(xml, policy)
}
xml.CommlCoverage{
xml.CoverageCd policy.terrorism_code
xml.CurrentTermAmt{ xml.Amt policy.terrorism_premium } if policy.terrorism_premium.present?
}
}
end
def build_additional_interests(xml, interests)
xml.comment! "Additional Interests"
interests.each do |interest|
xml.AdditionalInterest {
xml.ItemIdInfo {
xml.SystemId interest.id
}
build_general_party(xml, interest)
xml.AdditionalInterestInfo {
xml.NatureInterestCd interest.role
}
}
end
end
def build_taxes_fees(xml, policy)
xml.comment! "Taxes / Fees"
policy.tax_fees.each do |fee|
xml.CreditOrSurcharge{
xml.CreditSurchargeCd fee.code
xml.CreditSurchargeAmtDesc fee.code_name
xml.NumericValue { xml.FormatCurrencyAmt{ xml.Amt fee.amount } }
xml.SecondaryCd fee.type_code if fee.type_code.present?
}
end
end
def build_locations(xml, policy)
xml.comment! "Locations"
policy.locations.each do |location|
xml.Location(id: location.acord_id){
xml.ItemIdInfo{
xml.AgencyId location.number
xml.SystemId location.id
}
build_address(xml, location.address)
location.buildings.each do |building|
xml.SubLocation(id: building.acord_id){
xml.ItemIdInfo{
xml.AgencyId building.number
xml.SystemId building.id
}
build_address(xml, location.address)
xml.SubLocationName building.name
build_additional_interests(xml, building.additional_interests)
}
end
xml.LocationName location.name
xml.LocationDesc location.description
}
end
end
def build_lob(xml, policy)
policy.gl? and build_gl(xml, policy)
policy.property? and build_property(xml, policy)
policy.crime? and build_crime(xml, policy)
policy.inland_marine? and build_inland_marine(xml, policy)
end
def build_gl(xml, policy)
xml.comment! "General Liability"
line = policy.lines_of_business.gl
xml.GeneralLiabilityLineBusiness{
xml.LOBCd line.lob_code
xml.NAICCd policy.carrier_naic
build_term xml, line.premium
xml.LiabilityInfo{
xml.CommlCoverage{
xml.CoverageCd 'GL'
xml.CoverageDesc 'Commercial General Liability'
xml.comment! "Deductible"
xml.Deductible { # TODO: Add GL Deductible
build_amt xml, policy.gl_deductible.try(:amount)
xml.DeductibleTypeCd policy.gl_deductible.try(:type_code)
xml.DeductibleAppliesToCd policy.gl_deductible.try(:applies_to_code)
}
}
xml.comment! "Limits"
policy.gl_limits.each do |limit|
xml.CommlCoverage{
xml.CoverageCd limit.code
xml.CoverageDesc limit.code_name
xml.Limit { build_amt xml, limit.amount }
}
end
xml.comment! "Classifications"
policy.gl_classifications.each do |cls|
xml.GeneralLiabilityClassification(building_ref(cls.building)){
xml.ItemIdInfo {
xml.SystemId cls.id
}
xml.CommlCoverage{
xml.CoverageCd "PREM"
build_term xml, cls.premises_premium
xml.Rate cls.premises_rate
xml.MinPremAmt cls.premises_minimum_premium
}
xml.CommlCoverage{
xml.CoverageCd "PRDCO"
build_term xml, cls.product_premium
xml.Rate cls.product_rate
xml.MinPremAmt cls.product_minimum_premium
}
xml.ClassCd cls.code
xml.ClassCdDesc cls.description
xml.Exposure cls.exposure
xml.PremiumBasisCd cls.basis
}
end
}
}
end
def build_crime(xml, policy)
xml.comment! "Crime"
line = policy.lines_of_business.crime
xml.CrimeLineBusiness {
xml.LOBCd line.lob_code
xml.NAICCd policy.carrier_naic
build_term xml, line.premium
policy.crime_coverages.each do |c|
loc = building_ref(c.building)
xml.CrimeCoverageInfo(loc){
xml.CrimePlanCd "PLAN1"
c.details_by_form_code.each do |form, details|
xml.CrimeCoverageDetails{
xml.CrimeCoverageFormCd form
details.each do |detail|
xml.CommlCoverage{
xml.CoverageCd detail.code
xml.CoverageDesc detail.description
xml.Limit{
build_amt xml, detail.limit
xml.LimitAppliesToCd detail.applies_to_code
}
xml.Deductible{
build_amt xml, detail.deductible
}
build_term xml, detail.premium
}
end
}
end
}
end
}
end
def build_property(xml, policy)
xml.comment! "Property"
line = policy.lines_of_business.property
xml.CommlPropertyLineBusiness {
xml.LOBCd line.lob_code
xml.NAICCd policy.carrier_naic
build_term xml, line.premium
xml.PropertyInfo {
policy.locations.map(&:buildings).flatten.each do |building|
detail = building.building_detail
coverages = building.property_coverages
next unless detail || !coverages.empty?
xml.CommlPropertyInfo(building_ref(building)){
if detail
xml.ItemValueAmt{ xml.Amt detail.value }
xml.ClassCd detail.class_code
end
coverages.each do |coverage|
xml.CommlCoverage{
xml.CoverageCd coverage.code
xml.CoverageDesc coverage.code_description
xml.Limit {
build_amt xml, coverage.limit
xml.ValuationCd coverage.valuation_code
}
xml.Deductible{
build_amt xml, coverage.deductible
}
xml.Deductible{
xml.DeductibleAppliesToCd 'EGK'
build_amt xml, coverage.earthquake_deductible
}
xml.Option {
xml.OptionCd coverage.indemnity_limit_code
}
build_term xml, coverage.premium
xml.Rate coverage.rate
xml.CommlCoverageSupplement{
xml.CoverageSubCd coverage.covered_cause_of_loss_code
xml.CoinsurancePct coverage.coinsurance_percent
}
}
end
}
end
}
}
end
def build_comml_sublocations(xml, policy)
return unless policy.property?
policy.building_details.each do |detail|
xml.CommlSubLocation(building_ref(detail.building)){
xml.InterestCd detail.interest_code
xml.Construction{
xml.ConstructionCd detail.construction_code
xml.SidingCd detail.siding_code
xml.YearBuilt detail.year_built
xml.BldgArea {
xml.NumUnits detail.square_footage
xml.UnitMeasurementCd "SQFT"
}
xml.NumStories detail.number_of_stories
xml.NumUnits detail.number_of_units
xml.RoofingMaterial{
xml.RoofMaterialCd detail.roofing_code
}
xml.GlassTypeCd detail.glass_type_code
}
xml.BldgProtection{
xml.ProtectionClassGradeCd detail.protection_grade_code
xml.SprinkleredPct detail.sprinklered_percent
}
xml.BldgOccupancy{
xml.VacantUnoccupiedCd 'VAC' if detail.occupancy_code == 'VAC'
xml.OccupiedPct detail.percent_occupied
xml.NatureBusinessCd detail.occupancy_code unless detail.occupancy_code == 'VAC'
}
xml.WindClassCd detail.wind_code
xml.SeacoastOrOtherBodyWaterProximityCd detail.water_proximity_code
}
end
end
def build_vpi_extension(xml, policy)
xml.comment! "Vertafore Extensions"
xml.VertaforeExtensions {
xml.VPI{
xml.Version '0001'
xml.SLANumber policy.sla_number if policy.sla_number.present?
xml.Custom ''
xml.Contracts ''
xml.ExternalServices{
xml.PromptingCancelUrl "http://localhost:3000/builder/#{policy.id}/summary?aborted=true"
xml.PromptingFinishUrl "http://localhost:3000/builder/#{policy.id}/finished"
}
}
}
end
def build_remarks(xml, policy)
#xml.Remark("This location doesn't exist.", "IdRef" => "a6de2b90-8a6a-11e1-b0c4-0800200c9a66")
end
def build_address(xml, address)
return unless address
xml.Addr{
xml.AddrTypeCd Address::TYPES[address.address_type]
xml.Addr1 address.address1
xml.Addr2 address.address2 if address.address2.present?
xml.City address.city
xml.StateProvCd address.state
xml.PostalCode address.zipcode
xml.ItemIdInfo {
xml.SystemId address.id
}
}
end
def build_phones(xml, object)
return unless object && [:fax, :phone, :email].any?{|s| object.send(s).present? }
xml.Communications {
if object.phone.present?
xml.PhoneInfo{
xml.PhoneTypeCd "Phone"
xml.PhoneNumber object.phone
}
end
if object.fax.present?
xml.PhoneInfo{
xml.PhoneTypeCd "Fax"
xml.PhoneNumber object.fax
}
end
if object.email.present?
xml.EmailInfo {
xml.EmailAddr object.email
}
end
}
end
def build_general_party(xml, object)
return unless object
xml.GeneralPartyInfo {
if object.name
xml.NameInfo {
xml.CommlName {
xml.CommercialName object.name
}
if object.respond_to?(:dba_name) && object.dba_name.present?
xml.SupplementaryNameInfo {
xml.SupplementaryNameCd 'DBA'
xml.SupplementaryName object.dba_name
}
end
xml.LegalEntityCd object.form_of_business if object.is_a? Insured
}
end
object.addresses.each do |address|
build_address(xml, address)
end
build_phones(xml, object)
}
end
def build_term(xml, amt)
xml.CurrentTermAmt { xml.Amt amt }
end
def build_amt(xml, amt)
xml.FormatCurrencyAmt { xml.Amt amt }
end
protected
def building_ref(building)
if building
{:LocationRef => building.location.acord_id, :SubLocationRef => building.acord_id}
else
{}
end
end
# don't want outside classes directly accessing the builder object.
def builder
@builder
end
# DateTime converter
def dt(date)
AcordConvert.acord_date date
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment