rawbotz 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.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/CODE_OF_CONDUCT.md +49 -0
  4. data/Gemfile +9 -0
  5. data/README.md +185 -0
  6. data/Rakefile +29 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/config.ru +9 -0
  10. data/exe/debug/test_mail +15 -0
  11. data/exe/rawbotz +39 -0
  12. data/exe/rawbotz_import_links +74 -0
  13. data/exe/rawbotz_maintenance.sh +57 -0
  14. data/exe/rawbotz_process_order +86 -0
  15. data/exe/rawbotz_process_order_queue +80 -0
  16. data/exe/rawbotz_stock_update +84 -0
  17. data/exe/rawbotz_update_local_products +48 -0
  18. data/exe/rawbotz_update_remote_products +160 -0
  19. data/lib/rawbotz/app.rb +84 -0
  20. data/lib/rawbotz/cli/order_result_table.rb +57 -0
  21. data/lib/rawbotz/datapolate.rb +42 -0
  22. data/lib/rawbotz/helpers/flash_helper.rb +13 -0
  23. data/lib/rawbotz/helpers/icon_helper.rb +40 -0
  24. data/lib/rawbotz/helpers/resource_link_helper.rb +45 -0
  25. data/lib/rawbotz/local_shop.rb +12 -0
  26. data/lib/rawbotz/mail_template.rb +29 -0
  27. data/lib/rawbotz/option_parser.rb +37 -0
  28. data/lib/rawbotz/order_processor.rb +92 -0
  29. data/lib/rawbotz/product_updater.rb +89 -0
  30. data/lib/rawbotz/public/Chart.min.js +14 -0
  31. data/lib/rawbotz/public/font-awesome-4.5.0/HELP-US-OUT.txt +7 -0
  32. data/lib/rawbotz/public/font-awesome-4.5.0/css/font-awesome.css +2086 -0
  33. data/lib/rawbotz/public/font-awesome-4.5.0/css/font-awesome.min.css +4 -0
  34. data/lib/rawbotz/public/font-awesome-4.5.0/fonts/FontAwesome.otf +0 -0
  35. data/lib/rawbotz/public/font-awesome-4.5.0/fonts/fontawesome-webfont.eot +0 -0
  36. data/lib/rawbotz/public/font-awesome-4.5.0/fonts/fontawesome-webfont.svg +655 -0
  37. data/lib/rawbotz/public/font-awesome-4.5.0/fonts/fontawesome-webfont.ttf +0 -0
  38. data/lib/rawbotz/public/font-awesome-4.5.0/fonts/fontawesome-webfont.woff +0 -0
  39. data/lib/rawbotz/public/font-awesome-4.5.0/fonts/fontawesome-webfont.woff2 +0 -0
  40. data/lib/rawbotz/public/font-awesome-4.5.0/less/animated.less +34 -0
  41. data/lib/rawbotz/public/font-awesome-4.5.0/less/bordered-pulled.less +25 -0
  42. data/lib/rawbotz/public/font-awesome-4.5.0/less/core.less +12 -0
  43. data/lib/rawbotz/public/font-awesome-4.5.0/less/fixed-width.less +6 -0
  44. data/lib/rawbotz/public/font-awesome-4.5.0/less/font-awesome.less +17 -0
  45. data/lib/rawbotz/public/font-awesome-4.5.0/less/icons.less +697 -0
  46. data/lib/rawbotz/public/font-awesome-4.5.0/less/larger.less +13 -0
  47. data/lib/rawbotz/public/font-awesome-4.5.0/less/list.less +19 -0
  48. data/lib/rawbotz/public/font-awesome-4.5.0/less/mixins.less +26 -0
  49. data/lib/rawbotz/public/font-awesome-4.5.0/less/path.less +15 -0
  50. data/lib/rawbotz/public/font-awesome-4.5.0/less/rotated-flipped.less +20 -0
  51. data/lib/rawbotz/public/font-awesome-4.5.0/less/stacked.less +20 -0
  52. data/lib/rawbotz/public/font-awesome-4.5.0/less/variables.less +708 -0
  53. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_animated.scss +34 -0
  54. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_bordered-pulled.scss +25 -0
  55. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_core.scss +12 -0
  56. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_fixed-width.scss +6 -0
  57. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_icons.scss +697 -0
  58. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_larger.scss +13 -0
  59. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_list.scss +19 -0
  60. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_mixins.scss +26 -0
  61. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_path.scss +15 -0
  62. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_rotated-flipped.scss +20 -0
  63. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_stacked.scss +20 -0
  64. data/lib/rawbotz/public/font-awesome-4.5.0/scss/_variables.scss +708 -0
  65. data/lib/rawbotz/public/font-awesome-4.5.0/scss/font-awesome.scss +17 -0
  66. data/lib/rawbotz/public/jquery-2.2.0.min.js +4 -0
  67. data/lib/rawbotz/public/jui/external/jquery/jquery.js +9789 -0
  68. data/lib/rawbotz/public/jui/images/ui-icons_444444_256x240.png +0 -0
  69. data/lib/rawbotz/public/jui/images/ui-icons_555555_256x240.png +0 -0
  70. data/lib/rawbotz/public/jui/images/ui-icons_777620_256x240.png +0 -0
  71. data/lib/rawbotz/public/jui/images/ui-icons_777777_256x240.png +0 -0
  72. data/lib/rawbotz/public/jui/images/ui-icons_cc0000_256x240.png +0 -0
  73. data/lib/rawbotz/public/jui/images/ui-icons_ffffff_256x240.png +0 -0
  74. data/lib/rawbotz/public/jui/index.html +513 -0
  75. data/lib/rawbotz/public/jui/jquery-ui.css +1225 -0
  76. data/lib/rawbotz/public/jui/jquery-ui.js +16617 -0
  77. data/lib/rawbotz/public/jui/jquery-ui.min.css +7 -0
  78. data/lib/rawbotz/public/jui/jquery-ui.min.js +13 -0
  79. data/lib/rawbotz/public/jui/jquery-ui.structure.css +833 -0
  80. data/lib/rawbotz/public/jui/jquery-ui.structure.min.css +5 -0
  81. data/lib/rawbotz/public/jui/jquery-ui.theme.css +410 -0
  82. data/lib/rawbotz/public/jui/jquery-ui.theme.min.css +5 -0
  83. data/lib/rawbotz/public/pure-min.css +11 -0
  84. data/lib/rawbotz/public/rawbotz.css +60 -0
  85. data/lib/rawbotz/public/rawbotz.js +96 -0
  86. data/lib/rawbotz/public/rawbotz_ajax_product_link.js +64 -0
  87. data/lib/rawbotz/remote_shop.rb +21 -0
  88. data/lib/rawbotz/routes/non_remote_orders.rb +45 -0
  89. data/lib/rawbotz/routes/orders.rb +76 -0
  90. data/lib/rawbotz/routes/product_links.rb +68 -0
  91. data/lib/rawbotz/routes/products.rb +104 -0
  92. data/lib/rawbotz/routes/remote_shop.rb +37 -0
  93. data/lib/rawbotz/routes/suppliers.rb +36 -0
  94. data/lib/rawbotz/routes.rb +9 -0
  95. data/lib/rawbotz/version.rb +3 -0
  96. data/lib/rawbotz/views/_hide_unhide_button.haml +11 -0
  97. data/lib/rawbotz/views/_menu.haml +20 -0
  98. data/lib/rawbotz/views/index.haml +1 -0
  99. data/lib/rawbotz/views/layout.haml +55 -0
  100. data/lib/rawbotz/views/maintenance/menu.haml +25 -0
  101. data/lib/rawbotz/views/maintenance.haml +150 -0
  102. data/lib/rawbotz/views/order/_head.haml +24 -0
  103. data/lib/rawbotz/views/order/_item_table.haml +44 -0
  104. data/lib/rawbotz/views/order/new.haml +22 -0
  105. data/lib/rawbotz/views/order/non_remote.haml +42 -0
  106. data/lib/rawbotz/views/order/packlist.haml +14 -0
  107. data/lib/rawbotz/views/order/view.haml +79 -0
  108. data/lib/rawbotz/views/orders/index.haml +40 -0
  109. data/lib/rawbotz/views/orders/menu.haml +24 -0
  110. data/lib/rawbotz/views/orders/non_remotes.haml +8 -0
  111. data/lib/rawbotz/views/product/_stock_sales_plot.haml +60 -0
  112. data/lib/rawbotz/views/product/link_to.haml +29 -0
  113. data/lib/rawbotz/views/product/view.haml +64 -0
  114. data/lib/rawbotz/views/products/_link_table.haml +38 -0
  115. data/lib/rawbotz/views/products/index.haml +36 -0
  116. data/lib/rawbotz/views/products/link_wizard.haml +48 -0
  117. data/lib/rawbotz/views/products/links.haml +65 -0
  118. data/lib/rawbotz/views/products/menu.haml +27 -0
  119. data/lib/rawbotz/views/products/table.haml +20 -0
  120. data/lib/rawbotz/views/products/table_with_linking.haml +30 -0
  121. data/lib/rawbotz/views/remote_cart/index.haml +30 -0
  122. data/lib/rawbotz/views/remote_order/view.haml +35 -0
  123. data/lib/rawbotz/views/remote_orders/index.haml +20 -0
  124. data/lib/rawbotz/views/remote_product/view.haml +90 -0
  125. data/lib/rawbotz/views/remote_products/_table.haml +15 -0
  126. data/lib/rawbotz/views/remote_products/index.haml +30 -0
  127. data/lib/rawbotz/views/supplier/view.haml +63 -0
  128. data/lib/rawbotz/views/suppliers/index.haml +13 -0
  129. data/lib/rawbotz/views/thin_layout.haml +32 -0
  130. data/lib/rawbotz/views/widgets/_ajax_link.haml +5 -0
  131. data/lib/rawbotz/views/widgets/_link.haml +6 -0
  132. data/lib/rawbotz/views/widgets/_link_line.haml +15 -0
  133. data/lib/rawbotz.rb +77 -0
  134. data/rawbotz.gemspec +33 -0
  135. metadata +327 -0
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'date'
4
+
5
+ require "rawbotz"
6
+
7
+ require 'optparse'
8
+
9
+ options = {config: RawgentoModels::CONF_FILE}
10
+
11
+ optparse = OptionParser.new do |opts|
12
+ opts.banner = "Usage: #{$PROGRAM_NAME} [OPTIONS]"
13
+ opts.separator ""
14
+
15
+ opts.separator "RawgentoDB configuration file (MySQL options)"
16
+ opts.on("-c", "--config FILE", 'file path to rawgento-db YAML config file.') do |c|
17
+ if !File.exist? c
18
+ STDERR.puts "Cannot load conf file #{c}"
19
+ exit 2
20
+ end
21
+
22
+ options[:config] = c
23
+ end
24
+
25
+ opts.separator ""
26
+ opts.separator "Output options"
27
+ opts.on("-v", "--verbose", 'print debug output (WARNING: including PASSWORD)') do |v|
28
+ $stdout.sync = true
29
+ options[:verbose] = true
30
+ end
31
+
32
+ opts.separator ""
33
+ opts.separator "General"
34
+ opts.on_tail('--version', 'Show version.') do
35
+ puts "#{$PROGRAM_NAME} #{Rawbotz::VERSION}"
36
+ exit 0
37
+ end
38
+ opts.on('-h', '--help', 'Show this help.') do
39
+ puts opts
40
+ exit 0
41
+ end
42
+ end
43
+ optparse.parse!
44
+
45
+ include RawgentoModels
46
+
47
+ def main options
48
+ logger = Logger.new(STDOUT)
49
+ logger.level = options[:verbose] ? Logger::DEBUG : Logger::INFO
50
+
51
+ logger.debug "#{$PROGRAM_NAME} #{Rawbotz::VERSION}"
52
+
53
+ if !File.exist? options[:config]
54
+ logger.warn "Cannot load conf file #{options[:config]}"
55
+ exit 2
56
+ end
57
+
58
+ RawgentoModels.establish_connection options[:config]
59
+
60
+ begin
61
+ result = RawgentoDB::Query.stock(RawgentoDB.settings(options[:config]))
62
+ rescue Mysql2::Error => e
63
+ logger.error "Problems accessing MySQL database #{e.inspect}"
64
+ exit 2
65
+ end
66
+
67
+ now = DateTime.now
68
+
69
+ logger.info("Starting stock update")
70
+
71
+ result.each do |s|
72
+ product = RawgentoModels::LocalProduct.find_by(product_id: s.product_id)
73
+ if product.nil?
74
+ logger.info("No such product #{s.product_id}")
75
+ else
76
+ product.stock_items.create(qty: s.qty, date: now)
77
+ logger.info("Updated stock for #{s.product_id}")
78
+ end
79
+ end
80
+
81
+ logger.info("Finished with stock update")
82
+ end
83
+
84
+ main options
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rawbotz"
4
+ require "rawbotz/option_parser"
5
+
6
+ optparse = Rawbotz::OptionParser.new do |opts, options|
7
+ opts.banner = "Usage: #{$PROGRAM_NAME} [OPTIONS]"
8
+ opts.separator ""
9
+
10
+ opts.on("-m", "--[no-]mail",
11
+ "send mail with result") do |v|
12
+ options[:mail] = v
13
+ end
14
+ end
15
+ optparse.parse!
16
+ options = optparse.options
17
+
18
+ logger = Logger.new(STDOUT)
19
+ logger.level = optparse.options[:verbose] ? Logger::DEBUG : Logger::INFO
20
+
21
+ logger.debug "#{$PROGRAM_NAME} #{Rawbotz::VERSION}"
22
+
23
+ logger.info("Fetching and updating local products from MySQL database")
24
+
25
+ begin
26
+ products = RawgentoDB::Query.products
27
+ rescue
28
+ logger.error "Could not connect to MySQL database or other error"
29
+ #logger.error "$!.inspect" $@ -> backtrace
30
+ exit 1
31
+ end
32
+
33
+ product_count = RawgentoModels::LocalProduct.unscoped.count
34
+
35
+ updater = Rawbotz::ProductUpdater.new logger
36
+ updater.sync
37
+
38
+ logger.info("Finished updating local products.")
39
+
40
+ logger.info("Found #{RawgentoModels::LocalProduct.unscoped.count - product_count} new products")
41
+
42
+ if options[:mail]
43
+ logger.debug("Sending mail")
44
+ Rawbotz::mail("rawbotz local product update",
45
+ "Found #{RawgentoModels::LocalProduct.unscoped.count - product_count} new local products")
46
+ end
47
+
48
+ exit 0
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rawbotz"
4
+
5
+ require 'magento_remote'
6
+
7
+ require 'optparse'
8
+
9
+ options = { sleep_time: 1,
10
+ start_pid: 0,
11
+ limit: nil,
12
+ check_new: false,
13
+ max_dead: 100,
14
+ conf_file: 'remote-shop.yml'}
15
+ def options.print_default(sym); "(default: #{self[sym]})" end
16
+
17
+ program_name = File.basename __FILE__
18
+ $program_name = program_name
19
+
20
+ optparse = OptionParser.new do |opts|
21
+ opts.banner = "Usage: #{program_name} [OPTIONS]"
22
+ opts.separator ""
23
+ opts.separator "Scrapes remote shop and 'imports' products from it."
24
+ opts.separator ""
25
+
26
+ opts.separator "Will read remote shop conf from config file."
27
+
28
+ opts.separator ""
29
+ opts.separator "Configuration file (remote shop info, local db info)"
30
+ opts.on("-c", "--config FILE", 'file path to YAML config file.') do |c|
31
+ options[:config] = c
32
+ end
33
+ opts.separator ""
34
+ opts.separator "Parsing/scraping options"
35
+ opts.on("-s", "--start-pid PRODUCT_ID", Integer,
36
+ "start at product_id PRODUCT_ID #{options.print_default(:start_pid)}") do |v|
37
+ options[:start_pid] = v
38
+ end
39
+ opts.on("-w", "--wait SECONDS", Float,
40
+ "sleep SECONDS between two requests #{options.print_default(:sleep_time)}") do |v|
41
+ options[:sleep_time] = v
42
+ end
43
+ opts.on("-b", "--batches NUMBER", Integer,
44
+ "try NUMBER batches before assuming no further hits #{options.print_default(:max_dead)}") do |v|
45
+ options[:max_dead] = v
46
+ end
47
+ opts.on("-m", "--[no-]mail",
48
+ "send mail with result") do |v|
49
+ options[:mail] = v
50
+ end
51
+ opts.on("-l", "--limit LIMIT", Integer,
52
+ "try LIMIT products #{options.print_default(:limit)}") do |v|
53
+ options[:limit] = v
54
+ end
55
+ opts.on("-n", "--check-new", Integer,
56
+ "check only for new products") do |v|
57
+ options[:check_new] = true
58
+ end
59
+
60
+ opts.separator ""
61
+ opts.separator "Output options"
62
+ opts.on("-v", "--verbose", 'print debug output (WARNING: including PASSWORD)') do |v|
63
+ $stdout.sync = true
64
+ options[:verbose] = true
65
+ end
66
+
67
+ opts.separator ""
68
+ opts.separator "General"
69
+ opts.on_tail('--version', 'Show version.') do
70
+ puts "#{program_name} #{Rawbotz::VERSION}"
71
+ exit 0
72
+ end
73
+ opts.on_tail('-h', '--help', 'Show this help.') do
74
+ puts opts
75
+ exit 0
76
+ end
77
+ end
78
+ optparse.parse!
79
+
80
+ if options[:check_new] && options[:start_pid] != 0
81
+ STDERR.puts "Cannot define both check-new and start-pid options"
82
+ exit 1
83
+ end
84
+
85
+ def main options
86
+ STDOUT.sync = true
87
+ logger = Logger.new(STDOUT)
88
+ logger.level = options[:verbose] ? Logger::DEBUG : Logger::INFO
89
+
90
+ logger.debug "#{$program_name} #{Rawbotz::VERSION}"
91
+
92
+ mech_config = (YAML.load_file options[:config])["remote_shop"]
93
+ logger.debug(mech_config)
94
+ mech = MagentoMech.from_config(mech_config)
95
+ mech.log_to! logger
96
+
97
+ RawgentoModels.establish_connection options[:config]
98
+ logger.debug("Established connection to rawbotz database.")
99
+
100
+ supplier_name = mech_config["supplier_name"]
101
+ supplier = RawgentoModels::Supplier.find_or_create_by(name: supplier_name)
102
+ logger.debug("Supplier is #{supplier.name}")
103
+
104
+ number_dead = 0
105
+ product_count = RawgentoModels::RemoteProduct.count
106
+
107
+
108
+ current_pid = options[:start_pid]
109
+ if options[:check_new]
110
+
111
+ # max (product_id)
112
+ last_product_id = RawgentoModels::RemoteProduct.unscoped.where(supplier: supplier).order(product_id: :desc).first.product_id rescue 0
113
+ logger.debug "Nr Remote Products: #{RawgentoModels::RemoteProduct.where(supplier: supplier).count}"
114
+ current_pid = last_product_id
115
+ options[:start_pid] = last_product_id
116
+ logger.info "Check for new products (last found product_id was #{last_product_id})"
117
+ end
118
+
119
+ while true do
120
+ p = mech.scrape_products(current_pid, 1, options[:sleep_time])
121
+ if !p.empty?
122
+ logger.info "Found #{p[0].inspect}"
123
+ product_db = RawgentoModels::RemoteProduct.find_or_initialize_by(product_id: p[0][1].to_i, supplier: supplier)
124
+ product_db.update!(name: p[0][0], product_id: p[0][1].to_i, supplier: supplier)
125
+ product_db.save!
126
+ number_dead = 0
127
+ else
128
+ extra = options[:limit] ? "#{current_pid - (options[:start_pid] + options[:limit])}" : ""
129
+ extra += " #{options[:max_dead] - number_dead}"
130
+ logger.info "None at #{current_pid} - try #{extra} more"
131
+ number_dead += 1
132
+ end
133
+ current_pid += 1
134
+ if options[:limit] && current_pid > options[:start_pid] + options[:limit]
135
+ logger.info "reached limit"
136
+ break
137
+ end
138
+ if number_dead > options[:max_dead]
139
+ logger.info "reached max dead"
140
+ break
141
+ end
142
+ end
143
+
144
+ if RawgentoModels::RemoteProduct.any?
145
+ logger.info "Last at #{RawgentoModels::RemoteProduct.unscoped.where(supplier: supplier).order(product_id: :desc).first.product_id}"
146
+ logger.info "Found #{RawgentoModels::RemoteProduct.count - product_count} remote products"
147
+ else
148
+ logger.warn "No remote products found!"
149
+ end
150
+
151
+ if options[:mail]
152
+ logger.debug("Sending mail")
153
+ Rawbotz::mail("rawbotz remote product update",
154
+ "Found #{RawgentoModels::RemoteProduct.count - product_count} remote products")
155
+ end
156
+ end
157
+
158
+
159
+ main options
160
+ exit 0
@@ -0,0 +1,84 @@
1
+ require 'sinatra/base'
2
+ require 'action_view' # Workaround https://github.com/haml/haml/issues/695
3
+ require 'haml'
4
+ require 'rawbotz/helpers/icon_helper'
5
+ require 'rawbotz/helpers/flash_helper'
6
+ require 'rawbotz/helpers/resource_link_helper'
7
+ require 'tilt/haml'
8
+
9
+ class RawbotzApp < Sinatra::Base
10
+ include RawgentoModels
11
+
12
+ enable :sessions
13
+
14
+ configure do
15
+ # Setup local rawbotz database
16
+ if Rawbotz.conf_file_path
17
+ RawgentoModels.establish_connection Rawbotz.conf_file_path
18
+ else
19
+ RawgentoModels.establish_connection
20
+ end
21
+
22
+ # Configure local mysql database
23
+ RawgentoDB.settings(Rawbotz.conf_file_path)
24
+
25
+ # And RemoteShop
26
+ conf = YAML.load_file(Rawbotz.conf_file_path)
27
+ set :supplier_name, conf["supplier_name"]
28
+ set :supplier, Supplier.find_by(name:
29
+ conf["supplier_name"])
30
+ set :conf, conf
31
+ end
32
+
33
+ helpers do ; end
34
+ helpers Rawbotz::Helpers::IconHelper
35
+ helpers Rawbotz::Helpers::FlashHelper
36
+ helpers Rawbotz::Helpers::ResourceLinkHelper
37
+
38
+ get '/' do
39
+ haml :index
40
+ end
41
+
42
+ # get '/orders'
43
+ # get '/order/new'
44
+ # get '/order/:id'
45
+ # post '/order/:id/'
46
+ # get '/order/:id/packlist'
47
+ register Rawbotz::RawbotzApp::Routing::Orders
48
+
49
+ # get '/products'
50
+ # post '/products/search'
51
+ # get '/product/:id'
52
+ # get '/product/:id/stock_sales_plot'
53
+ # post '/product/:id/hide'
54
+ # post '/product/:id/unhide'
55
+ # get '/remote_products'
56
+ # post '/remote_products/search'
57
+ # get '/remote_product/id'
58
+ register Rawbotz::RawbotzApp::Routing::Products
59
+
60
+ # get '/products/links'
61
+ # get '/products/link_wizard'
62
+ # get '/products/link_wizard/:idx'
63
+ # get '/product/:id/link'
64
+ # post '/product/:id/link'
65
+ register Rawbotz::RawbotzApp::Routing::ProductLinks
66
+
67
+ # get '/remote_cart'
68
+ # get '/remote_orders'
69
+ # get '/remote_order/:id'
70
+ register Rawbotz::RawbotzApp::Routing::RemoteShop
71
+
72
+ # get '/supplier/:id'
73
+ # post '/supplier/:id'
74
+ register Rawbotz::RawbotzApp::Routing::Suppliers
75
+
76
+ # get '/orders/non_remote'
77
+ # get '/order/non_remote/:supplier_id'
78
+ # post '/order/non_remote/:supplier_id'
79
+ register Rawbotz::RawbotzApp::Routing::NonRemoteOrders
80
+
81
+ get '/maintenance' do
82
+ haml :maintenance
83
+ end
84
+ end
@@ -0,0 +1,57 @@
1
+ module Rawbotz::CLI
2
+ module OrderResultTable
3
+ def self.tables diffs
4
+ out = ""
5
+ if !diffs[:perfect].empty?
6
+ perfect_items = diffs[:perfect].map do |p, q|
7
+ [p.local_product.remote_product.name[0..35], q]
8
+ end
9
+ out << Terminal::Table.new(title: "Perfect",
10
+ headings: ['Product', 'In Cart'],
11
+ rows: perfect_items,
12
+ style: {width: 60}).to_s
13
+ out << "\n\n"
14
+ end
15
+
16
+ if !diffs[:modified].empty?
17
+ modified_items = diffs[:modified].map do |p,q|
18
+ [p.local_product.remote_product.name[0..35], p.num_wished, q]
19
+ end
20
+ out << Terminal::Table.new(title: "Modified",
21
+ headings: ['Product', 'Wished', 'In Cart'],
22
+ rows: modified_items,
23
+ style: {width:60}).to_s
24
+ out << "\n\n"
25
+ end
26
+
27
+ if !diffs[:miss].empty?
28
+ missing_items = diffs[:miss].map do |p,q|
29
+ [p.local_product.remote_product.name[0..35], q]
30
+ end
31
+ out << Terminal::Table.new(title: "Missing (?)",
32
+ headings: ['Product', 'In Cart'],
33
+ rows: missing_items,
34
+ style: {width:60}).to_s
35
+ out << "\n\n"
36
+ end
37
+
38
+ if !diffs[:under_avail].empty?
39
+ under_avail_items = diffs[:under_avail].map do |p,q|
40
+ [p.local_product.remote_product.name[0..35], p.num_wished, q]
41
+ end
42
+ out << Terminal::Table.new(title: "Not available as such",
43
+ headings: ['Product', 'Wanted', 'In Cart'],
44
+ rows: under_avail_items,
45
+ style: {width:60}).to_s
46
+ out << "\n\n"
47
+ end
48
+
49
+ if !diffs[:extra].empty?
50
+ out << Terminal::Table.new(title: "Extra (not in rawbotz)",
51
+ headings: ['Product', 'In Cart'],
52
+ rows: diffs[:extra],
53
+ style: {width:60}).to_s
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,42 @@
1
+ module Rawbotz
2
+ module Datapolate
3
+ def self.date_minmax sales, stock
4
+ #sales.each{|sale| sale[0] = Date.strptime(sale[0])}
5
+ sales_first, sales_last = sales.minmax_by{|s| s[0]}
6
+ stock_first, stock_last = stock.minmax_by{|s| s.date}
7
+ first_dates = []
8
+ first_dates << sales_first[0] if !sales_first.nil?
9
+ first_dates << stock_first.date.to_date if !stock_first.nil?
10
+
11
+ last_dates = []
12
+ last_dates << sales_last[0] if !sales_last.nil?
13
+ last_dates << stock_last.date.to_date if !stock_last.nil?
14
+
15
+ [first_dates.min, last_dates.max]
16
+ end
17
+
18
+ def self.explode_days min_date, max_date
19
+ (min_date.to_date..max_date.to_date).to_a
20
+ end
21
+
22
+ def self.create_data sales, stock
23
+ # from [date, sales] and [date, stock] create realistic list
24
+ from_date, to_date = date_minmax sales, stock
25
+ days = explode_days from_date, to_date
26
+
27
+ stock_data = Hash.new(nil)
28
+ stock.each{|s| stock_data[s.date.to_date] = s.qty}
29
+ sales_data = Hash.new(nil)
30
+ sales.each{|s| sales_data[s[0].to_date] = s.fetch(1)}
31
+
32
+ data = {}
33
+ days.each do |day|
34
+ data[day] = {label: day.to_date,
35
+ stock: stock_data[day],
36
+ sales: sales_data[day]
37
+ }
38
+ end
39
+ data
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module Rawbotz
2
+ module Helpers
3
+ module FlashHelper
4
+ def flash
5
+ @flash = session[:flash]# || {}
6
+ end
7
+ def add_flash kind, msg
8
+ session[:flash] ||= {}
9
+ (session[:flash][kind] ||= []) << msg
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module Rawbotz
2
+ module Helpers
3
+ module IconHelper
4
+ def error_icon
5
+ '<i class="fa fa-flash"></i>'
6
+ end
7
+ def index_icon
8
+ '<i class="fa fa-th-list"></i>'
9
+ end
10
+ def info_icon
11
+ '<i class="fa fa-info-circle"></i>'
12
+ end
13
+ def link_icon
14
+ '<i class="fa fa-link"></i>'
15
+ end
16
+ def order_icon
17
+ '<i class="fa fa-shopping-cart"></i>'
18
+ end
19
+ def product_icon
20
+ '<i class="fa fa-cube"></i>'
21
+ end
22
+ def products_icon
23
+ '<i class="fa fa-cubes"></i>'
24
+ end
25
+ def remote_icon
26
+ '<i class="fa fa-globe"></i>'
27
+ end
28
+ def settings_icon
29
+ '<i class="fa fa-wrench"></i>'
30
+ end
31
+ def success_icon
32
+ '<i class="fa fa-smile-o"></i>'
33
+ end
34
+ def warning_icon
35
+ '<i class="fa fa-warning"></i>'
36
+ end
37
+ end
38
+ end
39
+ # briefcase clone gift shopping-bag truck
40
+ end
@@ -0,0 +1,45 @@
1
+ module Rawbotz
2
+ module Helpers
3
+ module ResourceLinkHelper
4
+ include RawgentoModels
5
+
6
+ def local_product_link product
7
+ if product.present?
8
+ if product.name.empty?
9
+ "<a href=\"/product/#{product.id}\">[no product name!]</a>"
10
+ else
11
+ "<a href=\"/product/#{product.id}\">#{product.name}</a>"
12
+ end
13
+ else
14
+ "Product not in database"
15
+ end
16
+ end
17
+ def remote_product_link product
18
+ if product.is_a? LocalProduct
19
+ remote_product_link product.remote_product
20
+ elsif product.try(:id)
21
+ "<a href=\"/remote_product/#{product.id}\">"\
22
+ "<i class=\"fa fa-globe\"></i>#{product.name}</a>"
23
+ elsif product.name
24
+ # Used in RemoteOrder view.
25
+ "#{product.name}"
26
+ else
27
+ "not linked"
28
+ end
29
+ end
30
+ def product_link product
31
+ return local_product_link(product) if product.is_a?(LocalProduct)
32
+ return remote_product_link(product) if product.is_a?(RemoteProduct)
33
+ "no product"
34
+ end
35
+ def supplier_link supplier
36
+ if supplier.to_s != ""
37
+ "<a href=\"/supplier/#{supplier.id}\">#{supplier.name}</a>"
38
+ else
39
+ "[no supplier]"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,12 @@
1
+ module Rawbotz
2
+ module LocalShop
3
+ def self.product_page_frontend(product, settings)
4
+ # TODO settings could be memoized
5
+ "#{settings['local_shop']['base_uri']}catalog/product/view/id/#{product.product_id}"
6
+ end
7
+ def self.product_page_backend(product, settings)
8
+ # TODO settings could be memoized
9
+ "#{settings['local_shop']['base_uri']}index.php/rawadmin/catalog_product/edit/id/#{product.product_id}"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ module Rawbotz
2
+ module MailTemplate
3
+ # Substitute certain patterns in template
4
+ def self.consume template, order
5
+ result = ""
6
+ result = template.gsub(/SUPPLIERNAME/, order[:supplier][:name])
7
+
8
+ lines = result.split("\n")
9
+ subject, lines = lines.partition{|l| l.start_with?("SUBJECT=")}
10
+ product_line = lines.detect{|l| l.start_with?("* ")}
11
+ order_lines = order[:order_items].map do |oi|
12
+ next if product_line.nil?
13
+ order_item_line = product_line[2..-1]
14
+ order_item_line.gsub!(/PRODUCTCODE/, '')
15
+ order_item_line.gsub!(/QTY/, oi[:num_wished].to_s)
16
+ if oi[:local_product][:packsize].to_s != ""
17
+ order_item_line.gsub!(/NUM_PACKS/, (oi[:num_wished] / oi[:local_product][:packsize].to_f).to_s)
18
+ else
19
+ order_item_line.gsub!(/NUM_PACKS/, '')
20
+ end
21
+ order_item_line.gsub!(/PACKSIZE/, oi[:local_product][:packsize].to_s)
22
+ order_item_line.gsub!(/PRODUCTNAME/, oi[:local_product][:name].to_s)
23
+ order_item_line
24
+ end
25
+ lines[lines.find_index(product_line)] = order_lines
26
+ lines.flatten.join("\n")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ require 'optparse'
2
+
3
+ module Rawbotz
4
+ class OptionParser < ::OptionParser
5
+ attr_accessor :options
6
+
7
+ def initialize(*args)
8
+ @options = {}
9
+ super *args
10
+ default_options!
11
+ yield(self, @options) if block_given?
12
+ end
13
+
14
+ private
15
+
16
+ def default_options!
17
+ separator "Output Options"
18
+ on("-v", "--[no-]verbose", 'Run verbosely') do |c|
19
+ @options[:verbose] = c
20
+ end
21
+ separator "Configuration file"
22
+ on("-c", "--config FILE", 'File path to YAML config file.') do |c|
23
+ Rawbotz.conf_file_path = c
24
+ Rawbotz.configure!
25
+ end
26
+ separator "General"
27
+ on_tail('--version', 'Show version and exit.') do
28
+ puts "part of rawbotz #{Rawbotz::VERSION}"
29
+ exit 0
30
+ end
31
+ on('-h', '--help', 'Show this help and exit.') do
32
+ puts self
33
+ exit 0
34
+ end
35
+ end
36
+ end
37
+ end