rawbotz 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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