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.
- data/lib/bizLogic/VPMSHelper.rb +187 -0
- data/lib/bizLogic/applymta.rb +82 -0
- data/lib/bizLogic/continualQNB.rb +8 -0
- data/lib/bizLogic/diff.rb +39 -0
- data/lib/bizLogic/payment.rb +88 -0
- data/lib/bizLogic/search.rb +34 -0
- data/lib/bizLogic/xquery1 +28 -0
- data/lib/models/modbdbxml.rb +116 -0
- data/lib/models/modbdbxmlje.rb +135 -0
- data/lib/models/persist.rb +50 -0
- data/lib/processengine/HashEnhancement.rb +59 -0
- data/lib/processengine/communicator.rb +18 -0
- data/lib/processengine/engine.rb +171 -0
- data/lib/servicebroker/broker.rb +74 -0
- data/lib/servicebroker/mocks/CommercialCombinedQuoteNBRs.xml +2291 -0
- data/lib/servicebroker/mocks/RoadRisksQuoteNBRs.xml +469 -0
- data/lib/servicebroker/xsl/extractCode.xsl +11 -0
- data/lib/servicebroker/xsl/extractDescription.xsl +11 -0
- data/lib/servicebroker/xsl/extractPremium.xsl +52 -0
- data/lib/servicebroker/xsl/in_MotorTrade.xsl +561 -0
- metadata +98 -0
@@ -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
|