iab-InsuranceBizLogic 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,187 @@
1
+ # Copyright (c) 2007-2008 Orangery Technology Limited
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+ module VPMSHelper
5
+ include REXML
6
+
7
+ def mergeIntoXMLDoc(xml,premiums)
8
+ doc = Document.new(xml)
9
+ #premiums is a named value pair array
10
+ premiums.each do |singleResult|
11
+ value = singleResult.pop
12
+ path = Array.new
13
+ insertionNode = nil
14
+ found_where_to_insert = false
15
+ singleResult.each do |a|
16
+ path.push("/#{a}")
17
+ nodes = XPath.match(doc,"/#{path}")
18
+ if (a != singleResult.last)
19
+ if nodes.length <= 0
20
+ path.pop
21
+ insertionNode = XPath.first(doc,"/#{path}")
22
+ insertionNode.insert_after insertionNode,Element.new(a)
23
+ path.push("/#{a}")
24
+ insertionNode = XPath.first(doc,"/#{path}")
25
+ elsif (nodes.length == 1)
26
+ insertionNode = nodes[0]
27
+ end
28
+ else
29
+ if nodes.length > 0
30
+ #leaf node already there and maybe with an old value from previous page
31
+ else
32
+ path.pop
33
+ e = Element.new(a)
34
+ e.text = value
35
+ insertionNode.insert_after insertionNode,e
36
+ end
37
+ end
38
+ end
39
+ end
40
+ doc.to_s
41
+ end
42
+
43
+ def parseVPMSresponse(response,product)
44
+ @premiums = Array.new
45
+ doc = Document.new(response)
46
+ nodes = XPath.match(doc,"//multiRef[returnCode=0]")
47
+ nodes.each do |node|
48
+ extractPremiums(node,product)
49
+ end
50
+ #display any VPMS issues
51
+ #probably won't result in runtime issue since IAB currently asks for more than VPMS will understand
52
+ #because VPMS schema built on product view of library and VPMS message is built from full library def of coverage
53
+ #at the mo
54
+ nodes = XPath.match(doc,"//multiRef[returnCode!=0]")
55
+ nodes.each do |node|
56
+ viewPremiumComputeErrors(node,product)
57
+ end
58
+ end
59
+
60
+ def viewPremiumComputeErrors(node,product) #:nodoc
61
+ value = ""
62
+ node.each_child do |child|
63
+ case child.node_type
64
+ when :element
65
+ key, value = child.expanded_name, extractPremiums(child,product)
66
+ #put out 'error' message text
67
+ puts "#{value}" if key == "message"
68
+ when :text
69
+ key, value = '$', unescape(child.to_s).strip
70
+ end
71
+ end
72
+ value
73
+ end
74
+
75
+ def extractPremiums(node,product) #:nodoc
76
+ #vpms will return the following nodes of interest
77
+ #message, name, reffield, returncode, value
78
+ #like this
79
+ #key=message,value=
80
+ #key=name,value=F_CommercialProperty_#{product}_ContentsCover_CoverDetail_PremiumQuoteBreakdown_GrossAmount
81
+ #key=refField,value=
82
+ #key=returnCode,value=0
83
+ #key=value,value=125.55
84
+ value = ""
85
+ node.each_child do |child|
86
+ case child.node_type
87
+ when :element
88
+ key, value = child.expanded_name, extractPremiums(child,product)
89
+ @premiums.push(value.gsub("F_CommercialProperty_","").gsub('CommercialProperty',product).split("_")) if (key == "name")
90
+ if (key == "value")
91
+ name = @premiums.pop
92
+ name.push(value)
93
+ @premiums.push(name)
94
+ end
95
+ when :text
96
+ key, value = '$', unescape(child.to_s).strip
97
+ end
98
+ end
99
+ value
100
+ end
101
+
102
+ def callVPMS(nvpxml)
103
+ headers = {
104
+ 'Content-Type' => 'text/xml',
105
+ 'SoapAction' => ""
106
+ }
107
+ Net::HTTP.start(APP_CONFIG['vpms_ip'], 8080) do |http|
108
+ response = http.post('/jvpms/services/ProductRequestProcessor',nvpxml,headers)
109
+ response.body
110
+ end
111
+ end
112
+
113
+ def buildVPMSMessage(product,package,brand,params)
114
+ @instructionBlock = ""
115
+
116
+ nvpxml = '<?xml version="1.0" encoding="utf-8"?>
117
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
118
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
119
+ xmlns:tns="http://com/csc/dip/webservice/core/"
120
+ xmlns:types="http://com/csc/dip/webservice/core/encodedTypes"
121
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
122
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
123
+ xmlns:q1="http://core.webservice.dip.csc.com">
124
+ <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
125
+ <tns:process>
126
+ <in0 href="#id1"/>
127
+ </tns:process>
128
+ <soapenc:Array id="id1" soapenc:arrayType="q1:ProductRequest[1]">
129
+ <Item href="#id3"/>
130
+ </soapenc:Array>
131
+ <q1:ProductRequest id="id3" xsi:type="q1:ProductRequest">
132
+ <productName xsi:type="xsd:string">CommercialPropertyProduct</productName>
133
+ <store xsi:type="xsd:boolean">false</store>
134
+ <traceMode xsi:type="xsd:boolean">false</traceMode>
135
+ <useUI xsi:type="xsd:boolean">false</useUI>
136
+ <actions href="#id5"/>
137
+ </q1:ProductRequest>'
138
+
139
+ @id=7
140
+ @instructionBlock << "<Item href=\"#id#{@id += 1}\"/>"
141
+ nvpxml << "<q1:SetAction id=\"id#{@id}\" xsi:type=\"q1:SetAction\">
142
+ <useUI xsi:type=\"xsd:boolean\">false</useUI>
143
+ <name xsi:type=\"xsd:string\">A_CommercialProperty_#{package}_Brand</name>
144
+ <value xsi:type=\"xsd:string\">#{brand}</value>
145
+ </q1:SetAction>"
146
+ @instructionBlock << "<Item href=\"#id#{@id += 1}\"/>"
147
+ nvpxml << "<q1:SetAction id=\"id#{@id}\" xsi:type=\"q1:SetAction\">
148
+ <useUI xsi:type=\"xsd:boolean\">false</useUI>
149
+ <name xsi:type=\"xsd:string\">A_CommercialProperty_#{package}_Package</name>
150
+ <value xsi:type=\"xsd:string\">#{product}</value>
151
+ </q1:SetAction>"
152
+
153
+
154
+ nvpxml << createXMLMessage(product,params,true) do |k,v|
155
+
156
+ @instructionBlock << "<Item href=\"#id#{@id += 1}\"/>"
157
+
158
+ "<q1:SetAction id=\"id#{@id}\" xsi:type=\"q1:SetAction\">
159
+ <useUI xsi:type=\"xsd:boolean\">false</useUI>
160
+ <name xsi:type=\"xsd:string\">A_CommercialProperty_#{package}_#{k}</name>
161
+ <value xsi:type=\"xsd:string\">#{v}</value>
162
+ </q1:SetAction>"
163
+ end
164
+
165
+ nvpxml << deriveComputes(package)
166
+ @instructionBlock << "<Item href=\"#id#{@id}\"/>"
167
+
168
+ nvpxml << "<soapenc:Array id=\"id5\" soapenc:arrayType=\"q1:VpmsAction[1]\">
169
+ #{@instructionBlock}
170
+ </soapenc:Array>"
171
+
172
+ nvpxml << "</soap:Body></soap:Envelope>"
173
+ nvpxml
174
+ end
175
+
176
+ def deriveComputes(package)
177
+ nvpxml = ""
178
+ @pqbNodes.each do |n|
179
+ nvpxml << "<q1:ComputeAction id=\"id#{@id += 1}\" xsi:type=\"q1:ComputeAction\">
180
+ <useUI xsi:type=\"xsd:boolean\">false</useUI>
181
+ <name xsi:type=\"xsd:string\">F_CommercialProperty_#{package}_#{n}</name>
182
+ </q1:ComputeAction>"
183
+ @instructionBlock << "<Item href=\"#id#{@id}\"/>"
184
+ end
185
+ nvpxml
186
+ end
187
+ end
@@ -0,0 +1,82 @@
1
+ # Copyright (c) 2007-2008 Orangery Technology Limited
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+ module ApplyMTA
5
+ def applyMTA(startDateTime,endDateTime,policyKey,origImage,newImage)
6
+ appliedDateTime = Time.now.strftime('%Y-%m-%d') #TODO: add time into this
7
+ appliedDateTimeEpoch = Time.now.to_i
8
+
9
+ xmldiff = determineDiff(origImage,newImage)
10
+
11
+ doc = REXML::Document.new xmldiff
12
+
13
+ #remove the diff records of no interest to us
14
+ doc.elements.delete_all('//xupdate:append')
15
+ doc.elements.delete_all('//xupdate:remove')
16
+ doc.elements.delete_all('//xupdate:insert-after')
17
+ doc.elements.delete_all('//xupdate:insert-before')
18
+ doc.elements.delete_all('//xupdate:rename')
19
+
20
+ #the reduced doc
21
+ #puts doc.to_s
22
+
23
+ persist = Persist.instance
24
+ #add the MTA diff doc to the data store
25
+ key = persist.put('UUID',doc.to_s)
26
+ #puts "MTA diff doc key is #{key}"
27
+
28
+ #get the doc that holds the relationship between the policy and
29
+ #any MTA diff docs
30
+ #if it does not exist then get! will create it
31
+ mtas = persist.get!("#{policyKey}MTAS","<MTAS></MTAS>")
32
+ doc = REXML::Document.new mtas
33
+ mtasNode = REXML::XPath.first(doc, '//MTAS')
34
+
35
+ #check to see if any MTAs exist that start later than this one
36
+ #if so mark them as rolled back and store them in a
37
+ #reapply->hash
38
+ reapply = []
39
+
40
+ elems = doc.root.get_elements('//MTAS/MTA[@startDateTime]')
41
+ sorted = elems.map { |s| s.attributes["startDateTime"].to_s}.sort
42
+ #puts "This new MTA starting on #{startDateTime} yields out-of-sequence node(s):"
43
+ count = 0
44
+ sorted.each do |sd|
45
+ if (sd > startDateTime)
46
+ #roll these back
47
+ xpath = '//MTAS/MTA[@startDateTime = '+'"'+sd+'"]'
48
+ node = REXML::XPath.first(doc, xpath)
49
+ #puts node
50
+ #put into reapply-array providing of course not already rolled back
51
+ rb = node.attributes["rolledBack"]
52
+ if (rb != "true") then
53
+ reapply[count] = node.deep_clone
54
+ count = count + 1
55
+ #set current node to rolledBack
56
+ node.attributes["rolledBack"] = true
57
+ end
58
+ end
59
+ end
60
+ #puts "No nodes qualified." unless count > 0
61
+ #puts "\n"
62
+
63
+ #get first node and add element with meta data relating to the MTA diff doc added above
64
+ #meta data includes the key of the diff doc
65
+ mtasNode.add_element('MTA',{'key' => key , 'appliedDateTimeEpoch' => appliedDateTimeEpoch, 'appliedDateTime' => appliedDateTime, 'startDateTime' => startDateTime, 'endDateTime' => endDateTime, 'rolledBack' => false})
66
+
67
+ #check the reapply->array
68
+ #create new entries for any in the reapply->hash with new appliedDateTime attribute values appliedDateTime = Time.now.strftime('%Y-%m-%d') #TODO: add time into this
69
+ reapply.each do |n|
70
+ appliedDateTimeEpoch = appliedDateTimeEpoch + 1
71
+ n.attributes["appliedDateTime"] = appliedDateTime
72
+ n.attributes["appliedDateTimeEpoch"] = appliedDateTimeEpoch
73
+ n.attributes["rolledBack"] = false
74
+ mtasNode.add_element(n)
75
+ end
76
+ #puts "Final state of MTA meta data doc:"+doc.to_s
77
+
78
+ mtaKey = persist.put("#{policyKey}MTAS",doc.to_s)
79
+ #puts "MTAS key is still:#{mtaKey}"
80
+ doc.to_s
81
+ end
82
+ end
@@ -0,0 +1,8 @@
1
+ module RefineQuote
2
+ def integrateData(session,origData,newData)
3
+ #this piece of logica takes two xml documents that need to be merge, there will be new nodes
4
+ #and overlapping nodes as question answers for the quote are made available
5
+ result = origData.gsub("</#{session[:product]}>","")+newData.gsub("<#{session[:product]}>","")
6
+ result
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2007-2008 Orangery Technology Limited
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+
5
+ module XMLDiff
6
+ def runCommand(cmd, inp='')
7
+ IO.popen(cmd, 'r+') do |io|
8
+ begin
9
+ io.write inp
10
+ io.close_write
11
+ return io.read
12
+ rescue Exception => e
13
+ e.message
14
+ end
15
+ end
16
+ end
17
+
18
+ def determineDiff(origImage,newImage)
19
+ before, after, result = nil, nil, nil
20
+ begin
21
+ before = Tempfile.new('iab')
22
+ before << origImage
23
+ before.close
24
+ after = Tempfile.new('iab')
25
+ after << newImage
26
+ after.close
27
+ result = Tempfile.new('iab')
28
+ cmd = "#{APP_CONFIG['python_xmldiff_path']} -x #{before.path} #{after.path} > #{result.path}"
29
+ runCommand(cmd)
30
+ xmlDiff = result.read
31
+ #identify only the update nodes - we do not need to know about nodes that have moved sequence
32
+ return xmlDiff
33
+ ensure
34
+ before.delete unless before == nil
35
+ after.delete unless after == nil
36
+ result.delete unless result == nil
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2007-2008 Orangery Technology Limited
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+ # See doc/paypal_developer_info.txt
5
+ # See www.codyfauser.com
6
+
7
+ require 'active_merchant'
8
+
9
+ module Payment
10
+
11
+ include ActiveMerchant::Billing
12
+
13
+ # returns a url
14
+ def setup_payment(params)
15
+ amount = params[:payment_amount].to_i
16
+ if amount < 1
17
+ return params[:cancel_return_url]
18
+ else
19
+ setup_response = payment_gateway.setup_purchase(amount, :ip => params[:ip], :return_url => params[:return_url], :cancel_return_url => params[:cancel_return_url])
20
+ return payment_gateway.redirect_url_for(setup_response.token)
21
+ end
22
+ end
23
+
24
+ # returns a PaymentDetails
25
+ def get_gateway_payment_details(params)
26
+ details_response = payment_gateway.details_for(params[:token])
27
+ return PaymentDetails.new(details_response.success?, details_response.message, details_response.address)
28
+ end
29
+
30
+ class PaymentDetails
31
+ attr_reader :error_message, :address
32
+ def initialize(success, error_message, address)
33
+ @success = success
34
+ @error_message = error_message
35
+ @address = address
36
+ end
37
+ def success?
38
+ @success
39
+ end
40
+ end
41
+
42
+ # returns a PurchaseDetails
43
+ def complete_payment(params)
44
+ amount = params[:payment_amount].to_i
45
+ if amount < 1
46
+ #TODO localise error message
47
+ return PurchaseDetails.new(false, "Amount to pay must be greater than 0")
48
+ else
49
+ purchase = payment_gateway.purchase(amount, :ip => params[:ip], :payer_id => params[:payer_id], :token => params[:token])
50
+ return PurchaseDetails.new(purchase.success?, purchase.message)
51
+ end
52
+ end
53
+
54
+ class PurchaseDetails
55
+ attr_reader :error_message
56
+ def initialize(success, error_message)
57
+ @success = success
58
+ @error_message = error_message
59
+ end
60
+ def success?
61
+ @success
62
+ end
63
+ end
64
+
65
+ # private
66
+ # TODO this is the test paypal account, needs to come from configuration
67
+ def payment_gateway
68
+ @payment_gateway ||= @@gateway_creator.call
69
+ end
70
+
71
+ def self.gateway_creator=(creator)
72
+ @@gateway_creator = creator
73
+ end
74
+
75
+ end
76
+
77
+
78
+ #TODO THIS BELONGS IN A CONFIGURATION INCLUDE SOMEWHERE (which is why it looks funny here)
79
+
80
+ # Put ActiveMerchant in test mode
81
+ ActiveMerchant::Billing::Base.mode = :test
82
+
83
+ # Use the ActiveMerchant Paypal Express gateway with these sandbox account details
84
+ Payment.gateway_creator = lambda { ActiveMerchant::Billing::PaypalExpressGateway.new(
85
+ :login => 'kuboid_1208170947_biz_api1.gmail.com',
86
+ :password => '1208170953',
87
+ :signature => 'AMVR2Do.R-utyMm2sFyqPkqVzWDzAn4yKS9xT07kyzoyj5DFPG-wh53q'
88
+ ) }
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2007-2008 Orangery Technology Limited
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+ module Search
5
+ def executeSearch(product,params)
6
+
7
+ mypredicate = ""
8
+ params.each do |k,v|
9
+ if (v.class.name == 'HashWithIndifferentAccess')
10
+ mypredicate << explodeHash(v)
11
+ end
12
+ end
13
+
14
+ open("#{File.dirname(__FILE__)}/xquery1") {|f| @query = f.read }
15
+ @query = @query.gsub("PRODUCT","#{product}").gsub("PREDICATE",mypredicate[0..-5])
16
+
17
+ persist = Persist.instance
18
+ result = persist.find(@query)
19
+ end
20
+
21
+ def explodeHash(h)
22
+ predicate = ""
23
+ h.each do |k,v|
24
+ if (v.class.name == 'HashWithIndifferentAccess')
25
+ predicate << explodeHash(v)
26
+ elsif (v.class.name == "String")
27
+ if (v.length > 0)
28
+ predicate << "$result//#{k} =\"#{v}\" and "
29
+ end
30
+ end
31
+ end
32
+ predicate
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ declare namespace xupdate="http://www.xmldb.org/xupdate";
2
+ for $result in collection("quotes.dbxml")/PRODUCT
3
+ where PREDICATE
4
+ return
5
+ (
6
+ concat(
7
+ "@rowHash = {",
8
+ "'companyname' => '",$result//Insured[1]//CompanyName/string(),"',",
9
+ "'postcode' => '",$result//Insured[1]//Postcode/string(),"',",
10
+ "'key' => '", $result/dbxml:metadata("dbxml:name"),"',"),
11
+ "'mtas' => [",
12
+ for $mtas in collection("quotes.dbxml")/MTAS/MTA,
13
+ $mta in collection("quotes.dbxml")
14
+ where $mtas/dbxml:metadata("dbxml:name") = concat($result/dbxml:metadata("dbxml:name"),"MTAS")
15
+ and $mta/dbxml:metadata("dbxml:name") = $mtas/@key
16
+ return (
17
+ concat(
18
+ "{",
19
+ "'AD' => '",$mtas/@appliedDateTime/string(),"',",
20
+ "'SD' => '",$mtas/@startDateTime/string(),"',",
21
+ "'ED' => '",$mtas/@endDateTime/string(),"',",
22
+ "'RB' => '",$mtas/@rolledBack/string(),"',",
23
+ "'Changes' => '",$mta//xupdate:update/@select," -to- ",$mta//xupdate:update/string(),"'",
24
+ "},"
25
+ )
26
+ ),
27
+ "]}"
28
+ )
@@ -0,0 +1,116 @@
1
+ require 'bdbxml'
2
+ module BDBXML
3
+ #setup DB_ROOT to point to IABDB location
4
+ unless defined?(DB_ROOT)
5
+ db_path = APP_CONFIG['dbpath']
6
+ require 'pathname'
7
+ db_path = Pathname.new(db_path).cleanpath(true).to_s
8
+ DB_ROOT = db_path
9
+ DB_NAME = APP_CONFIG['dbcontainer']
10
+ end
11
+
12
+ def setup_env
13
+ puts "VERSION of BDB is #{BDB::VERSION}\n"
14
+ puts "VERSION of BDB::XML is #{BDB::XML::VERSION}\n"
15
+ puts "Database path is #{File.expand_path(DB_ROOT)}\n"
16
+
17
+ #setup UUID state file
18
+ UUID.config(:state_file => "#{DB_ROOT}/uuid.state",
19
+ :sequence => rand(0x100000000),
20
+ :mac_addr => '00:19:e3:36:60:f5')
21
+
22
+ @flag = BDB::INIT_TRANSACTION
23
+ @flag ||= BDB::INIT_LOMP
24
+ $env = BDB::Env.new(DB_ROOT, BDB::CREATE | @flag)
25
+ $man = $env.manager
26
+ if (!File.exist?("#{DB_ROOT}/#{DB_NAME}"))
27
+ if (@flag & BDB::INIT_TXN) != 0
28
+ $con = $man.create_container(DB_NAME, BDB::XML::TRANSACTIONAL)
29
+ else
30
+ $con = $man.create_container(DB_NAME)
31
+ end
32
+ else
33
+ if (@flag & BDB::INIT_TXN) != 0
34
+ $con = $man.open_container(DB_NAME, BDB::XML::TRANSACTIONAL)
35
+ else
36
+ $con = $man.open_container(DB_NAME)
37
+ end
38
+ end
39
+ $base = "."
40
+ end
41
+
42
+ def clean_env
43
+ puts "\nVERSION of BDB is #{BDB::VERSION}\n"
44
+ puts "\nVERSION of BDB::XML is #{BDB::XML::VERSION}\n"
45
+ puts "Cleaning #{DB_ROOT}/#{DB_NAME}\n"
46
+
47
+ Dir.foreach(DB_ROOT) do |x|
48
+ if FileTest.file?(DB_ROOT+"/#{x}")
49
+ File.unlink(DB_ROOT+"/#{x}")
50
+ end
51
+ end
52
+ end
53
+
54
+ def close_env
55
+ $man.close
56
+ $env.close
57
+ end
58
+
59
+ def create_key_and_doc(msg)
60
+ key = UUID.new
61
+ create_doc(msg,key)
62
+ key
63
+ end
64
+
65
+ def read_doc(key)
66
+ $con.get(key).content
67
+ end
68
+
69
+ def create_doc(msg,key)
70
+ $man.begin($con) do |txn, con|
71
+ a = $man.create_document
72
+ a.content = msg
73
+ con[key] = a
74
+ txn.commit
75
+ end
76
+ end
77
+
78
+ def replace_doc(msg,key)
79
+ $man.begin($con) do |txn, con|
80
+ a = $con.get(key)
81
+ a.content = msg
82
+ $con.update(a)
83
+ txn.commit
84
+ end
85
+ end
86
+
87
+ def find(query)
88
+ cxt = $man.create_query_context()
89
+ results = $man.query(query, cxt)
90
+ if (results.size == 0) then
91
+ return nil
92
+ end
93
+ #results is essentially an array of result lines
94
+ #a single result will span a number of output lines, e.g. outer joined
95
+ #MTA info will appear with a CRLF separator
96
+ #the following code makes up single logical result rows based on the lines between
97
+ #successive pairs of {} braces
98
+ #
99
+ #it should be noted that the result set from the xqueries is intended to be
100
+ #a valid ruby block
101
+ #this allows the result to be used to instantiate an active record object
102
+ #with no further manipulation required
103
+ rows = []
104
+ i = 0
105
+ results.each do |r|
106
+ if rows[i] == nil
107
+ rows[i] = ""
108
+ end
109
+ rows[i] << r.chomp
110
+ if (r.match(']}'))
111
+ i = i + 1
112
+ end
113
+ end
114
+ rows
115
+ end
116
+ end