xmlconv2 2.0.0

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.
Files changed (108) hide show
  1. data/History.txt +6 -0
  2. data/LICENCE.txt +339 -0
  3. data/Manifest.txt +107 -0
  4. data/README.txt +25 -0
  5. data/Rakefile +28 -0
  6. data/bin/admin +65 -0
  7. data/bin/xmlconvd +19 -0
  8. data/data/grammar/i2.grammar +73 -0
  9. data/src/conversion/bdd_geh.rb +281 -0
  10. data/src/conversion/bdd_i2.rb +102 -0
  11. data/src/conversion/bdd_xml.rb +242 -0
  12. data/src/conversion/geh_bdd.rb +165 -0
  13. data/src/conversion/i2_bdd.rb +271 -0
  14. data/src/conversion/xml_bdd.rb +125 -0
  15. data/src/custom/lookandfeel.rb +47 -0
  16. data/src/i2/address.rb +33 -0
  17. data/src/i2/date.rb +37 -0
  18. data/src/i2/document.rb +26 -0
  19. data/src/i2/header.rb +24 -0
  20. data/src/i2/order.rb +44 -0
  21. data/src/i2/parser.rb +25 -0
  22. data/src/i2/position.rb +37 -0
  23. data/src/i2/record.rb +11 -0
  24. data/src/model/address.rb +20 -0
  25. data/src/model/agreement.rb +10 -0
  26. data/src/model/bdd.rb +26 -0
  27. data/src/model/bsr.rb +16 -0
  28. data/src/model/delivery.rb +15 -0
  29. data/src/model/delivery_item.rb +18 -0
  30. data/src/model/freetext_container.rb +26 -0
  31. data/src/model/id_container.rb +15 -0
  32. data/src/model/invoice.rb +18 -0
  33. data/src/model/invoice_item.rb +11 -0
  34. data/src/model/item.rb +19 -0
  35. data/src/model/item_container.rb +15 -0
  36. data/src/model/name.rb +27 -0
  37. data/src/model/part_info.rb +10 -0
  38. data/src/model/part_info_container.rb +15 -0
  39. data/src/model/party.rb +23 -0
  40. data/src/model/party_container.rb +20 -0
  41. data/src/model/price.rb +10 -0
  42. data/src/model/price_container.rb +18 -0
  43. data/src/model/transaction.rb +28 -0
  44. data/src/state/global.rb +28 -0
  45. data/src/state/global_predefine.rb +11 -0
  46. data/src/state/login.rb +38 -0
  47. data/src/state/transaction.rb +13 -0
  48. data/src/state/transactions.rb +130 -0
  49. data/src/util/application.rb +143 -0
  50. data/src/util/destination.rb +130 -0
  51. data/src/util/invoicer.rb +72 -0
  52. data/src/util/known_user.rb +16 -0
  53. data/src/util/polling_manager.rb +78 -0
  54. data/src/util/session.rb +23 -0
  55. data/src/util/transaction.rb +105 -0
  56. data/src/util/validator.rb +20 -0
  57. data/src/view/foot.rb +27 -0
  58. data/src/view/head.rb +13 -0
  59. data/src/view/login.rb +36 -0
  60. data/src/view/navigation.rb +30 -0
  61. data/src/view/navigationlink.rb +21 -0
  62. data/src/view/pager.rb +73 -0
  63. data/src/view/preformatted.rb +39 -0
  64. data/src/view/template.rb +17 -0
  65. data/src/view/transaction.rb +42 -0
  66. data/src/view/transactions.rb +90 -0
  67. data/test/mock.rb +149 -0
  68. data/test/suite.rb +16 -0
  69. data/test/test_conversion/bdd_geh.rb +533 -0
  70. data/test/test_conversion/bdd_i2.rb +314 -0
  71. data/test/test_conversion/bdd_xml.rb +556 -0
  72. data/test/test_conversion/geh_bdd.rb +372 -0
  73. data/test/test_conversion/i2_bdd.rb +804 -0
  74. data/test/test_conversion/xml_bdd.rb +203 -0
  75. data/test/test_i2/address.rb +88 -0
  76. data/test/test_i2/date.rb +49 -0
  77. data/test/test_i2/document.rb +62 -0
  78. data/test/test_i2/header.rb +39 -0
  79. data/test/test_i2/order.rb +94 -0
  80. data/test/test_i2/parser.rb +309 -0
  81. data/test/test_i2/position.rb +65 -0
  82. data/test/test_integration/geh_i2.rb +312 -0
  83. data/test/test_integration/i2_geh.rb +449 -0
  84. data/test/test_integration/i2_xml.rb +162 -0
  85. data/test/test_integration/xml_i2.rb +254 -0
  86. data/test/test_model/address.rb +35 -0
  87. data/test/test_model/agreement.rb +22 -0
  88. data/test/test_model/bdd.rb +55 -0
  89. data/test/test_model/bsr.rb +38 -0
  90. data/test/test_model/delivery.rb +79 -0
  91. data/test/test_model/delivery_item.rb +52 -0
  92. data/test/test_model/freetext_container.rb +45 -0
  93. data/test/test_model/invoice.rb +65 -0
  94. data/test/test_model/invoice_item.rb +41 -0
  95. data/test/test_model/name.rb +57 -0
  96. data/test/test_model/part_info.rb +24 -0
  97. data/test/test_model/party.rb +96 -0
  98. data/test/test_model/price.rb +24 -0
  99. data/test/test_util/application.rb +168 -0
  100. data/test/test_util/destination.rb +197 -0
  101. data/test/test_util/invoicer.rb +36 -0
  102. data/test/test_util/polling_manager.rb +111 -0
  103. data/test/test_util/transaction.rb +129 -0
  104. data/user-stories/UserStories_XmlConv2.txt +381 -0
  105. data/user-stories/doku/ABB.incoming.HTTP.invoice.xml +315 -0
  106. data/user-stories/doku/ABB.received.xml +259 -0
  107. data/user-stories/doku/BO_OrderProcessing.sxw +0 -0
  108. metadata +195 -0
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env ruby
2
+ # Destination -- xmlconv2 -- 08.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'fileutils'
5
+ require 'uri'
6
+ require 'odba'
7
+ require 'net/http'
8
+
9
+ module XmlConv
10
+ module Util
11
+ class Destination
12
+ include ODBA::Persistable
13
+ attr_accessor :path
14
+ attr_reader :uri, :status
15
+ STATUS_COMPARABLE = {
16
+ :pending_pickup => 10,
17
+ :picked_up => 20,
18
+ :http_ok => 20
19
+ }
20
+ def initialize
21
+ @status = :open
22
+ end
23
+ def deliver(delivery)
24
+ raise 'Abstract Method deliver called in Destination'
25
+ end
26
+ def update_status
27
+ end
28
+ def status_comparable
29
+ self::class::STATUS_COMPARABLE[@status].to_i
30
+ end
31
+ def forget_credentials!
32
+ end
33
+ end
34
+ class DestinationDir < Destination
35
+ attr_reader :filename
36
+ def deliver(delivery)
37
+ do_deliver(delivery)
38
+ @status = :pending_pickup
39
+ odba_store
40
+ end
41
+ def do_deliver(delivery)
42
+ if(delivery.is_a?(Array))
43
+ delivery.each { |part| do_deliver(part) }
44
+ else
45
+ FileUtils.mkdir_p(@path)
46
+ @filename = if(delivery.respond_to?(:filename))
47
+ delivery.filename
48
+ else
49
+ "%.5f.txt" % Time.now.to_f
50
+ end
51
+ path = File.expand_path(@filename, @path)
52
+ File.open(path, 'w') { |fh| fh << delivery.to_s }
53
+ end
54
+ end
55
+ def update_status
56
+ if(@status == :pending_pickup \
57
+ && !File.exist?(File.expand_path(@filename.to_s, @path)))
58
+ @status = :picked_up
59
+ odba_store
60
+ end
61
+ end
62
+ def uri
63
+ URI.parse("file:#{File.expand_path(@filename.to_s, @path)}")
64
+ end
65
+ end
66
+ class DestinationHttp < Destination
67
+ HTTP_CLASS = Net::HTTP # replaceable for testing purposes
68
+ HTTP_HEADERS = {
69
+ 'content-type' => 'text/xml',
70
+ }
71
+ def initialize
72
+ super
73
+ @uri = URI.parse('http:/')
74
+ end
75
+ def deliver(delivery)
76
+ do_deliver(delivery)
77
+ ensure
78
+ forget_credentials!
79
+ end
80
+ def do_deliver(delivery)
81
+ if(delivery.is_a?(Array))
82
+ worst_status = ''
83
+ delivery.each { |part|
84
+ do_deliver(part)
85
+ ## bogostatus: assume that the more information in the string,
86
+ ## the worse the status is (ok < not found)
87
+ ## rationale: DTSTTCPW
88
+ if(@status.to_s > worst_status.to_s)
89
+ worst_status = @status
90
+ end
91
+ }
92
+ @status = worst_status
93
+ else
94
+ self.class::HTTP_CLASS.start(@uri.host, @uri.port) { |http|
95
+ request = Net::HTTP::Post.new(@uri.path, HTTP_HEADERS)
96
+ if(@uri.user || @uri.password)
97
+ request.basic_auth(@uri.user, @uri.password)
98
+ end
99
+ response = http.request(request, delivery.to_s)
100
+ status_str = response.message.downcase.gsub(/\s+/, "_")
101
+ @status = "http_#{status_str}".intern
102
+ }
103
+ end
104
+ end
105
+ def forget_credentials!
106
+ @uri = URI::HTTP.new(@uri.scheme, nil, @uri.host, @uri.port,
107
+ @uri.registry, @uri.path, @uri.opaque, @uri.query, @uri.fragment)
108
+ end
109
+ def host
110
+ @uri.host
111
+ end
112
+ def host=(str)
113
+ @uri.host = str
114
+ end
115
+ def path
116
+ @uri.path if(@uri)
117
+ end
118
+ def path=(str)
119
+ @uri.path = str if(@uri)
120
+ end
121
+ def uri=(uri)
122
+ if(uri.is_a?(String))
123
+ @uri = URI.parse(uri)
124
+ else
125
+ @uri = uri
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::Invoicer -- xmlconv2 -- 03.08.2006 -- hwyss@ywesee.com
3
+
4
+ require 'ydim/config'
5
+ require 'ydim/client'
6
+ require 'openssl'
7
+
8
+ module XmlConv
9
+ module Util
10
+ class Invoicer
11
+ class << self
12
+ def create_invoice(time_range, groups, date, currency='CHF')
13
+ time = Time.now
14
+ format = "Umsatzbeteiligung %s\nCHF %1.2f Umsatz\naus %i Rechnungs-�bermittlungen"
15
+ ydim_connect { |client|
16
+ ydim_inv = client.create_invoice(YDIM_ID)
17
+ ydim_inv.description = sprintf("Umsatzbeteiligung %s-%s",
18
+ time_range.first.strftime("%d.%m.%Y"),
19
+ (time_range.last - 1).strftime("%d.%m.%Y"))
20
+ ydim_inv.date = date
21
+ ydim_inv.currency = currency
22
+ ydim_inv.payment_period = 30
23
+ item_data = groups.sort.collect { |group, bdds|
24
+ amount = 0
25
+ invoices = 0
26
+ bdds.each { |bdd|
27
+ amount += bdd.invoiced_amount
28
+ invoices += 1 unless(bdd.invoices.empty?)
29
+ }
30
+ {
31
+ :price => (amount * 1.5) / 1000.0,
32
+ :quantity => 1,
33
+ :text => sprintf(format, group.to_s, amount, invoices),
34
+ :time => Time.local(date.year, date.month, date.day),
35
+ :unit => "0.15%",
36
+ }
37
+ }
38
+ client.add_items(ydim_inv.unique_id, item_data)
39
+ ydim_inv
40
+ }
41
+ end
42
+ def group_by_partner(transactions)
43
+ groups = {}
44
+ transactions.each { |transaction|
45
+ (groups[transaction.partner] ||= []).push(transaction.model)
46
+ }
47
+ groups
48
+ end
49
+ def run(time_range, transactions, date)
50
+ unless(transactions.empty?)
51
+ invoice = create_invoice(time_range, group_by_partner(transactions),
52
+ date)
53
+ send_invoice(invoice.unique_id)
54
+ end
55
+ end
56
+ def send_invoice(invoice_id)
57
+ ydim_connect { |client| client.send_invoice(invoice_id) }
58
+ end
59
+ def ydim_connect(&block)
60
+ config = YDIM::Client::CONFIG
61
+ server = DRbObject.new(nil, config.server_url)
62
+ client = YDIM::Client.new(config)
63
+ key = OpenSSL::PKey::DSA.new(File.read(config.private_key))
64
+ client.login(server, key)
65
+ block.call(client)
66
+ ensure
67
+ client.logout if(client)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::KnownUser -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'sbsm/user'
5
+ require 'state/transactions'
6
+
7
+ module XmlConv
8
+ module Util
9
+ class KnownUser < SBSM::KnownUser
10
+ HOME = State::Transactions
11
+ NAVIGATION = [
12
+ :home, :logout
13
+ ]
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::PollingManager -- xmlconv2 -- 29.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'fileutils'
5
+ require 'uri'
6
+ require 'yaml'
7
+ require 'util/destination'
8
+ require 'util/transaction'
9
+
10
+ module XmlConv
11
+ module Util
12
+ class PollingMission
13
+ attr_accessor :directory, :reader, :writer, :destination,
14
+ :error_recipients, :debug_recipients, :backup_dir,
15
+ :glob_pattern, :partner
16
+ end
17
+ class PollingManager
18
+ PROJECT_ROOT = File.expand_path('../..', File.dirname(__FILE__))
19
+ CONFIG_PATH = File.expand_path('etc/polling.yaml', PROJECT_ROOT)
20
+ def initialize(system)
21
+ @system = system
22
+ end
23
+ def destination(str)
24
+ uri = URI.parse(str)
25
+ case uri
26
+ when URI::HTTP
27
+ dest = DestinationHttp.new
28
+ dest.uri = uri
29
+ dest
30
+ else
31
+ dest = DestinationDir.new
32
+ dest.path = str
33
+ dest
34
+ end
35
+ end
36
+ def load_sources(&block)
37
+ file = File.open(self::class::CONFIG_PATH)
38
+ YAML.load_documents(file) { |mission|
39
+ path = File.expand_path(mission.directory, PROJECT_ROOT)
40
+ mission.directory = path
41
+ block.call(mission)
42
+ }
43
+ ensure
44
+ file.close if(file)
45
+ end
46
+ def file_paths(dir_path, pattern=nil)
47
+ Dir.glob(File.expand_path(pattern || '*', dir_path)).collect { |entry|
48
+ File.expand_path(entry, dir_path)
49
+ }.compact
50
+ end
51
+ def poll(source)
52
+ file_paths(source.directory, source.glob_pattern).each { |path|
53
+ begin
54
+ transaction = XmlConv::Util::Transaction.new
55
+ transaction.input = File.read(path)
56
+ transaction.partner = source.partner
57
+ transaction.origin = 'file:' << path
58
+ transaction.reader = source.reader
59
+ transaction.writer = source.writer
60
+ transaction.destination = destination(source.destination)
61
+ transaction.debug_recipients = source.debug_recipients
62
+ transaction.error_recipients = source.error_recipients
63
+ @system.execute(transaction)
64
+ ensure
65
+ backup_dir = source.backup_dir
66
+ FileUtils.mkdir_p(backup_dir)
67
+ FileUtils.mv(path, backup_dir)
68
+ end
69
+ }
70
+ end
71
+ def poll_sources
72
+ load_sources { |source|
73
+ poll(source)
74
+ }
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # Session -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'sbsm/session'
5
+ require 'state/login'
6
+ require 'custom/lookandfeel'
7
+ require 'util/known_user'
8
+
9
+ module XmlConv
10
+ module Util
11
+ class Session < SBSM::Session
12
+ DEFAULT_LANGUAGE = 'de'
13
+ DEFAULT_STATE = State::Login
14
+ LOOKANDFEEL = Custom::Lookandfeel
15
+ def login
16
+ if((pass = user_input(:pass)) \
17
+ && (pass == "6646c9e7892ef147dbed611a00ea48e6"))
18
+ @user = Util::KnownUser.new
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::Transaction -- xmlconv2 -- 04.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'odba'
5
+ require 'conversion/bdd_geh'
6
+ require 'conversion/bdd_i2'
7
+ require 'conversion/bdd_xml'
8
+ require 'conversion/geh_bdd'
9
+ require 'conversion/i2_bdd'
10
+ require 'conversion/xml_bdd'
11
+ require 'util/destination'
12
+ require 'net/smtp'
13
+ require 'tmail'
14
+
15
+ module XmlConv
16
+ module Util
17
+ class Transaction
18
+ include ODBA::Persistable
19
+ MAIL_FROM = 'xmlconv@ywesee.com'
20
+ SMTP_HANDLER = Net::SMTP
21
+ attr_accessor :input, :reader, :writer, :destination, :origin,
22
+ :transaction_id, :partner, :error,
23
+ :error_recipients, :debug_recipients
24
+ attr_reader :output, :model, :start_time, :commit_time,
25
+ :input_model, :output_model, :status
26
+ def execute
27
+ reader_instance = Conversion.const_get(@reader)
28
+ writer_instance = Conversion.const_get(@writer)
29
+ @start_time = Time.now
30
+ input_model = reader_instance.parse(@input)
31
+ @model = reader_instance.convert(input_model)
32
+ output_model = writer_instance.convert(@model)
33
+ @output = output_model.to_s
34
+ @destination.deliver(output_model)
35
+ @commit_time = Time.now
36
+ @output
37
+ ensure
38
+ @destination.forget_credentials!
39
+ end
40
+ def notify
41
+ recipients = [@debug_recipients]
42
+ subject = 'XmlConv2 - Debug-Notification'
43
+ if(@error)
44
+ recipients.push(@error_recipients)
45
+ subject = 'XmlConv2 - Error-Notification'
46
+ end
47
+ recipients.flatten!
48
+ recipients.compact!
49
+ recipients.uniq!
50
+ return if(recipients.empty?)
51
+ mail = TMail::Mail.new
52
+ mail.set_content_type('text', 'plain', 'charset'=>'ISO-8859-1')
53
+ mail.body = <<-EOS
54
+ Date: #{@start_time.strftime("%d.%m.%Y")}
55
+ Time: #{@start_time.strftime("%H:%M:%S")}
56
+ Status: #{status}
57
+ Error: #{@error}
58
+ Link: http://janico.ywesee.com/de/transaction/transaction_id/#{@transaction_id}
59
+
60
+ Input:
61
+ # input start
62
+ #{@input}
63
+ # input end
64
+
65
+ Output:
66
+ # output start
67
+ #{@output}
68
+ # output end
69
+ EOS
70
+ mail.from = self::class::MAIL_FROM
71
+ mail.to = recipients
72
+ mail.subject = subject
73
+ mail.date = Time.now
74
+ mail['User-Agent'] = 'XmlConv::Util::Transaction'
75
+
76
+ self.class::SMTP_HANDLER.start('mail.ywesee.com') { |smtp|
77
+ smtp.sendmail(mail.encoded, self::class::MAIL_FROM, recipients)
78
+ }
79
+ end
80
+ def status
81
+ if(@error)
82
+ :error
83
+ elsif(@destination.respond_to?(:status))
84
+ @destination.status
85
+ end
86
+ end
87
+ def status_comparable
88
+ if(@destination.respond_to?(:status_comparable))
89
+ @destination.status_comparable
90
+ end
91
+ end
92
+ def update_status
93
+ if(@destination.respond_to?(:update_status))
94
+ @destination.update_status
95
+ end
96
+ end
97
+ def uri
98
+ @destination.uri if(@destination.respond_to?(:uri))
99
+ end
100
+ def uri_comparable
101
+ self.uri.to_s
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # Util::Validator -- xmlconv2 -- 09.06.2004 -- hwyss@ywesee.com
3
+
4
+ require 'sbsm/validator'
5
+
6
+ module XmlConv
7
+ module Util
8
+ class Validator < SBSM::Validator
9
+ EVENTS = [
10
+ :login, :logout, :sort, :transaction, :self, :home
11
+ ]
12
+ STRINGS = [
13
+ :sortvalue,
14
+ ]
15
+ NUMERIC = [
16
+ :transaction_id, :page
17
+ ]
18
+ end
19
+ end
20
+ end