rawbotz 0.1.5 → 0.2.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -5
  3. data/Gemfile +2 -0
  4. data/README.md +60 -6
  5. data/Rakefile +3 -2
  6. data/agpl-3.0.txt +661 -0
  7. data/exe/bcrypt_pw +10 -0
  8. data/exe/rawbotz_abort_orders +28 -0
  9. data/exe/rawbotz_process_order_queue +12 -8
  10. data/exe/rawbotz_stock_update +10 -1
  11. data/exe/rawbotz_update_local_products +11 -3
  12. data/exe/rawbotz_update_remote_products +27 -4
  13. data/lib/rawbotz.rb +13 -5
  14. data/lib/rawbotz/app.rb +36 -2
  15. data/lib/rawbotz/cli/order_result_table.rb +13 -0
  16. data/lib/rawbotz/helpers/format_helper.rb +14 -0
  17. data/lib/rawbotz/helpers/icon_helper.rb +108 -22
  18. data/lib/rawbotz/helpers/order_item_color_helper.rb +17 -0
  19. data/lib/rawbotz/helpers/resource_link_helper.rb +3 -0
  20. data/lib/rawbotz/mail_template.rb +42 -7
  21. data/lib/rawbotz/models/sales.rb +21 -0
  22. data/lib/rawbotz/models/stock.rb +25 -0
  23. data/lib/rawbotz/models/stock_product.rb +146 -0
  24. data/lib/rawbotz/models/stock_product_factory.rb +64 -0
  25. data/lib/rawbotz/processors/order_linker.rb +50 -0
  26. data/lib/rawbotz/{order_processor.rb → processors/order_processor.rb} +14 -3
  27. data/lib/rawbotz/processors/organic_product_deliveries_csv.rb +47 -0
  28. data/lib/rawbotz/{product_updater.rb → processors/product_updater.rb} +71 -6
  29. data/lib/rawbotz/processors/stock_processor.rb +67 -0
  30. data/lib/rawbotz/public/rawbotz.css +35 -1
  31. data/lib/rawbotz/public/rawbotz.js +0 -1
  32. data/lib/rawbotz/remote_shop.rb +3 -0
  33. data/lib/rawbotz/routes.rb +3 -0
  34. data/lib/rawbotz/routes/non_remote_orders.rb +129 -29
  35. data/lib/rawbotz/routes/orders.rb +55 -4
  36. data/lib/rawbotz/routes/orders/stock.rb +75 -0
  37. data/lib/rawbotz/routes/product_links.rb +1 -1
  38. data/lib/rawbotz/routes/products.rb +19 -22
  39. data/lib/rawbotz/routes/remote_shop.rb +1 -1
  40. data/lib/rawbotz/routes/stock.rb +58 -0
  41. data/lib/rawbotz/routes/suppliers.rb +9 -4
  42. data/lib/rawbotz/sales_data.rb +13 -0
  43. data/lib/rawbotz/version.rb +1 -1
  44. data/lib/rawbotz/views/_hide_unhide_button.haml +1 -1
  45. data/lib/rawbotz/views/_menu.haml +9 -0
  46. data/lib/rawbotz/views/index.haml +1 -1
  47. data/lib/rawbotz/views/layout.haml +0 -1
  48. data/lib/rawbotz/views/order/_head.haml +64 -19
  49. data/lib/rawbotz/views/order/_item_table.haml +19 -3
  50. data/lib/rawbotz/views/order/_order_actions.haml +26 -0
  51. data/lib/rawbotz/views/order/link_to_remote.haml +30 -0
  52. data/lib/rawbotz/views/order/non_remote.haml +120 -26
  53. data/lib/rawbotz/views/order/packlist.haml +62 -5
  54. data/lib/rawbotz/views/order/packlist.pdf.haml +35 -0
  55. data/lib/rawbotz/views/order/stock.haml +116 -0
  56. data/lib/rawbotz/views/order/view.haml +41 -21
  57. data/lib/rawbotz/views/orders/_order_table.haml +82 -0
  58. data/lib/rawbotz/views/orders/index.haml +41 -28
  59. data/lib/rawbotz/views/orders/menu.haml +2 -2
  60. data/lib/rawbotz/views/orders/non_remotes.haml +14 -3
  61. data/lib/rawbotz/views/pdf_layout.haml +44 -0
  62. data/lib/rawbotz/views/product/view.haml +64 -11
  63. data/lib/rawbotz/views/products/index.haml +1 -1
  64. data/lib/rawbotz/views/products/table.haml +5 -1
  65. data/lib/rawbotz/views/remote_cart/index.haml +10 -0
  66. data/lib/rawbotz/views/remote_order/view.haml +6 -4
  67. data/lib/rawbotz/views/remote_orders/index.haml +16 -13
  68. data/lib/rawbotz/views/stock/index.haml +119 -0
  69. data/lib/rawbotz/views/stock/menu.haml +20 -0
  70. data/lib/rawbotz/views/stock_product/_value_table_line.haml +22 -0
  71. data/lib/rawbotz/views/stock_product/value_table.haml +28 -0
  72. data/lib/rawbotz/views/stockexplorer/stockexplorer.haml +157 -0
  73. data/lib/rawbotz/views/supplier/orders/table.haml +26 -0
  74. data/lib/rawbotz/views/supplier/view.haml +56 -10
  75. data/rawbotz.gemspec +13 -9
  76. metadata +86 -17
  77. data/lib/rawbotz/views/order/new.haml +0 -22
@@ -38,7 +38,6 @@
38
38
  = msg.join(" | ")
39
39
  -# Consume the remainder
40
40
  - if flash.length > 0
41
- = flash.inspect
42
41
  #flash.ui-state-highlight
43
42
  - flash.each do |f|
44
43
  = error_icon
@@ -1,24 +1,69 @@
1
1
  %h2 General
2
- %dl
3
- %dt
4
- Supplier
5
- %dd
6
- = order.supplier.try(:name)
7
- %dt
8
- Created at
9
- %dd
10
- = order.created_at
11
- %dt
12
- Updated at
13
- %dd
14
- = order.updated_at
15
- %dt
16
- State
17
- %dd
18
- = order.state
2
+
3
+ .pure-g
4
+ .pure-u-1-2
5
+ %dl
6
+ %dt
7
+ Supplier
8
+ %dd
9
+ = order.supplier.try(:name)
10
+ %dt
11
+ Created at
12
+ %dd
13
+ = order.created_at
14
+ %dt
15
+ Updated at
16
+ %dd
17
+ = order.updated_at
18
+ .pure-u-1-2
19
+ %dl
20
+ %dt
21
+ State
22
+ %dd
23
+ = order_state_icon order
24
+ = order.state
25
+ - if order.supplier.minimum_order_value.present?
26
+ %dt
27
+ Supplier minimum order value
28
+ %dd
29
+ %b
30
+ = order.supplier.minimum_order_value
31
+ - if order.supplier.order_info.present?
32
+ %dt
33
+ Supplier Order Info
34
+ %dd
35
+ %b
36
+ = order.supplier.order_info
37
+ - if order.supplier.delivery_time_days.present?
38
+ %dt
39
+ Supplier Delivery time (days)
40
+ %dd
41
+ %b
42
+ = order.supplier.delivery_time_days
43
+ - if order.remote_order_id.present?
44
+ %dt
45
+ Remote Order ID
46
+ %dd
47
+ = order.remote_order_id
48
+ - if order.remote_order_link
49
+ %dt
50
+ Remote Order Link
51
+ %dd
52
+ %a(href="#{order.remote_order_link}" target="remote_shop")
53
+ = external_link_icon
54
+ = order.remote_order_link
55
+ %br
56
+ %a(href="/remote_order/#{order.remote_order_link.split('/').last}")
57
+ in rawbotz
58
+ - if order.internal_comment.present?
59
+ .internal_comment
60
+ %h3 Internal Comment
61
+ = order.internal_comment
62
+ - if order.public_comment.present?
63
+ .public_comment
64
+ %h3 Public Comment
65
+ = order.public_comment
19
66
 
20
67
  %h2 Content
21
68
  = order.order_items.count
22
69
  Items.
23
-
24
-
@@ -1,16 +1,26 @@
1
+ :javascript
2
+ $( function() {
3
+ $( document ).tooltip();
4
+ });
1
5
 
2
6
  %table.pure-table.pure-table-bordered
3
7
  %thead
4
8
  %tr
5
9
  %th(style="width: 5%;") Product ID
6
10
  %th(style="width: 50%;") Product Name
7
- %th(style="width: 10%;") Stock (at order- time) / min stock
11
+ %th(style="width: 10%;" title="Stock (at order- time!) / Minimum stock warning value")
12
+ = stock_icon
13
+ \/
14
+ = stock_full_icon
8
15
  %th(style="width: 20%;") Order
9
- %th(style="width: 5%;")
16
+ %th(style="width: 5%;" title="Packsize")
10
17
  %i.fa.fa-cube
11
- %th(style="width: 10%;") Stock/ Sales history
18
+ %th(style="width: 10%;" title="Stock and Sales history")
19
+ = sales_icon
20
+ %i.fa.fa-line-chart
12
21
  %tbody
13
22
  - order_items.each do |order_item|
23
+ -# purchase price, order info!
14
24
  %tr
15
25
  %td
16
26
  - if order_item.local_product
@@ -19,6 +29,12 @@
19
29
  No local product!
20
30
  %td
21
31
  = local_product_link order_item.local_product
32
+ - if order_item.local_product.order_info.present?
33
+ %br
34
+ #flash.ui-state-highlight
35
+ = info_icon
36
+ = order_item.local_product.order_info
37
+
22
38
  %td
23
39
  = order_item.current_stock
24
40
  \/
@@ -0,0 +1,26 @@
1
+ %center
2
+ %h2 Actions
3
+ - if order.state == "new"
4
+ %button.pure-button.pure-button-secondary(name="action" value="save")
5
+ = save_icon
6
+ Save
7
+ - if order.state == "new"
8
+ %button.pure-button.pure-button-primary(name="action" value="order")
9
+ = order_icon
10
+ Order!
11
+ - if !["new", "deleted"].include? order.state
12
+ %a.pure-button(href="/order/#{order.id}/packlist")
13
+ = view_icon
14
+ = packlist_icon
15
+ Packlist
16
+ %a.pure-button(href="/order/#{order.id}/packlist/pdf")
17
+ %i.fa.fa-file-pdf-o
18
+ Download Packlist
19
+ - if !["stocked", "deleted", "new"].include? order.state
20
+ %a.pure-button(href="/order/#{order.id}/stock")
21
+ = stock_icon
22
+ Stock
23
+ - if order.state != "deleted"
24
+ %button.pure-button.pure-button-primary(name="action" value="delete")
25
+ = delete_icon
26
+ Delete
@@ -0,0 +1,30 @@
1
+ = haml "orders/menu".to_sym
2
+
3
+ %h1 Link order from #{@order.updated_at} to a remote order
4
+
5
+ %center
6
+ %table.pure-table.pure-table-striped
7
+ %thead
8
+ %tr
9
+ %th Date
10
+ %th Volume
11
+ %th Order ID
12
+ %th State
13
+ %th Action
14
+ %tbody
15
+ - @last_orders.each do |remote_order|
16
+ %form.pure-form(method="post")
17
+ %input(type="hidden" name="remote_order_link" value="#{remote_order[2]}")
18
+ %input(type="hidden" name="remote_order_id" value="#{remote_order[3]}")
19
+ %tr
20
+ %td=remote_order[0]
21
+ %td=remote_order[1]
22
+ %td=remote_order[3]
23
+ %td=remote_order[4]
24
+ %td
25
+ %a(href="#{remote_order[2]}" target="remote_shop")
26
+ Visit remote shop
27
+ %br
28
+ %button.pure-button.pure-button-primary(type="submit" href="/remote_order/#{remote_order[2][/\d+/]}")
29
+ = add_icon
30
+ Link to this order
@@ -1,30 +1,58 @@
1
1
  = haml "orders/menu".to_sym
2
2
 
3
+ :javascript
4
+ $( function() {
5
+ $( document ).tooltip();
6
+ });
7
+
3
8
  %h1 Non-Remote Order for supplier #{@supplier.name}
4
9
 
5
10
  #modal-plot.modal-plot
6
11
 
7
- - if @mail_preview.to_s != ""
8
- %h2 Mail preview
9
- %pre~ @mail_preview
10
- %a{:href => "mailto:#{@supplier.email}?Subject=Order&body=%s" % URI::escape(@mail_preview).gsub(/&/,'%26')} Open mail
11
- %br
12
+ #supplier_info
13
+ - if @supplier.order_info.present?
14
+ #flash.ui-state-highlight
15
+ = info_icon
16
+ %b Delivery info:
17
+ = @supplier.order_info
18
+
19
+ - if @supplier.delivery_time_days
20
+ #flash.ui-state-highlight
21
+ = info_icon
22
+ %b Delivery Time (in days):
23
+ = @supplier.delivery_time_days
24
+
25
+ - if @supplier.minimum_order_value
26
+ #flash.ui-state-highlight
27
+ = info_icon
28
+ %b Minimum Order Value
29
+ = @supplier.minimum_order_value
30
+
31
+
32
+ - if @supplier.order_info.present? || @supplier.delivery_time_days || @supplier.minimum_order_value
33
+ %br
12
34
 
13
35
  %center
14
36
  %form#non_remote_order.pure-form(action="" method="post")
15
37
  %input(name="supplier_id" type="hidden" value="#{@supplier.id}")
16
- %table.pure-table
38
+ %table.pure-table.pure-table-striped
17
39
  %thead
18
40
  %tr
19
41
  %th Name
20
42
  %th Qty
21
- %th Packsize
22
- %th Rough Avg. sales/ m
43
+ %th(title="Packsize")
44
+ = packsize_icon
45
+ %th Avg. sales / m
23
46
  %th Stock
47
+ %th Missing
48
+ %th Purchase Price
24
49
  %th Chart
25
50
  %tbody
26
- - @products.find_each do |product|
27
- %tr
51
+ - @order.order_items.find_each do |order_item|
52
+ - product = order_item.local_product
53
+ - product_monthly_sales = @monthly_sales && @monthly_sales[product.product_id]
54
+ - product_stock = @stock[product.product_id]
55
+ %tr(title="Complete sales info")
28
56
  %td
29
57
  = product_link product
30
58
  - if product.supplier_prod_name
@@ -32,29 +60,78 @@
32
60
  %small
33
61
  = product.supplier_sku
34
62
  = product.supplier_prod_name
35
- %td
36
- = haml "widgets/_qty_wished_input".to_sym, locals: {product: product, input_id_num: product.id}
37
- %td
63
+ - if product.order_info.present?
64
+ #flash.ui-state-highlight
65
+ = error_icon
66
+ = product.order_info
67
+ %td(title="Quantity to order")
68
+ - if @order.state == "new"
69
+ = haml "widgets/_qty_wished_input".to_sym, locals: {product: product, input_id_num: product.id, num_wished: order_item.num_wished}
70
+ - else
71
+ %input.qty{readonly: true, value: order_item.num_wished, size: 2}
72
+ %td(title="Packsize of product")
38
73
  - if product.packsize.present?
39
74
  = product.packsize
40
75
  - else
41
76
  %i.fa.fa-ban
42
- %td
43
- - if @monthly_sales
44
- = @monthly_sales[product.product_id]
45
- %td
46
- = @stock[product.product_id]
77
+ %td(title="Monthly sales of product")
78
+ = product_monthly_sales
79
+ %td(title="Product Stock")
80
+ = product_stock
81
+ %td(title="Predicted quantity missing to stock for 30 days")
82
+ - if product_stock && product_monthly_sales
83
+ -# red/yellow/green
84
+ -# if negative, put button
85
+ = product_stock - product_monthly_sales
86
+ %td(title="Purchase Price")
87
+ - if product.purchase_price
88
+ = product.purchase_price
89
+
47
90
  %td
48
91
  - stock_url = "/product/#{product.id}/stock_sales_plot"
49
92
  %a.stock_show_action{:href => "", :data => {url: stock_url, product: product.name}}
50
93
  Stock/Sales
94
+ %br
95
+ %center
96
+ Total price (updates on 'Save' click):
97
+ %br
98
+ %b
99
+ = "%.2f" % @order.order_items.inject(0.0) {|acc, oi| acc += oi.num_wished.to_i * oi.local_product.purchase_price.to_f}
100
+
101
+ - if @order.order_items.detect{|oi| oi.num_wished.to_i > 0 && oi.local_product.purchase_price.present?}
102
+ \... plus products without purchase price
103
+ %br
51
104
 
105
+ .br
106
+ %table.pure-table.pure-table-bordered(width="100%")
107
+ %thead
108
+ %tr
109
+ %th
110
+ %label(for="internal_comment")
111
+ Internal Comment
112
+ %th
113
+ %label(for="public")
114
+ Public Comment
115
+ %tbody
116
+ %tr
117
+ %td
118
+ %textarea#internal_comment(name="internal_comment")~ @order.internal_comment
119
+ %td
120
+ %textarea#public_comment(name="public_comment")~ @order.public_comment
52
121
 
53
122
  %br
54
123
  %center
55
- %button.pure-button.pure-button-primary
56
- %i.fa.fa-envelope
57
- Show me the mail!
124
+ %h2 Actions
125
+ - if @order.state != "deleted" && @order.state != "mailed"
126
+ %button.pure-button.pure-button-primary(name="action" value="save")
127
+ = save_icon
128
+ Save
129
+ - if @order.state != "deleted" && @order.state != "mailed"
130
+ %button.pure-button.pure-button-secondary(name="action" value="fix")
131
+ Save and fix, mark as mailed
132
+ - if @order.state != "deleted"
133
+ %button.pure-button.pure-button-primary(name="action" value="delete")
134
+ Delete
58
135
  -#%button#ajax_mailto.pure-button.pure-button-secondary
59
136
  -# %i.fa.fa-envelope
60
137
  -# Open mail
@@ -78,8 +155,25 @@
78
155
  -#Edit supplier ...
79
156
 
80
157
  %br
81
- %h2 Mail template
82
- %pre~ @supplier.order_template
83
- %a.pure-button(href="/supplier/#{@supplier.id}")
84
- Edit template
85
- %br
158
+ - if @mail_preview_text.to_s != ""
159
+ %table.pure-table
160
+ %tr
161
+ %td
162
+ %h2 Mail preview
163
+ %pre~ "SUBJECT: #{@mail_preview_subject}"
164
+ %pre~ "TO: #{@supplier.email}"
165
+ %pre~ @mail_preview_text
166
+ %a{:href => @mailto_url, :target => 'rawbotz_mail_order'}
167
+ Open mail
168
+ %td
169
+ %h2 Mail template
170
+ %pre~ @supplier.order_template
171
+ %a.pure-button(href="/supplier/#{@supplier.id}#tab_order_settings")
172
+ Edit template
173
+ %br
174
+ - else
175
+ %h2 Mail template
176
+ %pre~ @supplier.order_template
177
+ %a.pure-button(href="/supplier/#{@supplier.id}#tab_order_settings")
178
+ Edit template
179
+ %br
@@ -1,14 +1,71 @@
1
- %h2 Order #{@order.supplier} from #{@order.created_at}
1
+ = haml "orders/menu".to_sym
2
+
3
+ %h2 Packlist for order #{@order.supplier.name} from #{@order.created_at}
4
+
5
+ - if @order.supplier == settings.supplier && !@order.remote_order_link.present?
6
+ .ui-state-error
7
+ = error_icon
8
+ This order is not linked up to a remote order, thus no refunds or extra items are shown.
9
+ %a.button.pure-button(href="/order/#{@order.id}/link_to_remote")
10
+ Link to a remote order
11
+
12
+ %center
13
+ Last changed #{@order.updated_at}
14
+
15
+ = haml "order/_head".to_sym, locals: {order: @order}
16
+ %br
2
17
 
3
18
  %table.pure-table.pure-table-striped
4
19
  %thead
5
20
  %tr
6
- %th Product
7
- %th Shelve
8
- %th Quantity
21
+ %th
22
+ = products_icon
23
+ Product
24
+ %th
25
+ = shelve_icon
26
+ Shelve
27
+ %th
28
+ = order_icon
29
+ Quantity Ordered
30
+ - if !@refunds.empty? || !@orphans.empty?
31
+ %th
32
+ %i.fa.fa-times-circle-o
33
+ Refunded
34
+ %th
35
+ = stock_icon
36
+ Quantity Stocked
9
37
  %tbody
10
38
  - @order.order_items.where("num_ordered > 0").sort_by{|i| i.local_product.name}.each do |p|
11
39
  %tr
12
40
  %td=p.local_product.name
13
41
  %td=p.local_product.shelve_nr
14
- %td=p.num_ordered
42
+ %td
43
+ = p.num_ordered
44
+ - if refund = @refunds[p.local_product.product_id]
45
+ (
46
+ = refund.qty_ordered
47
+ )
48
+ - if !@refunds.empty?
49
+ %td
50
+ - if remote_line = @refunds[p.local_product.product_id]
51
+ = @refunds[p.local_product.product_id].qty_refunded
52
+ %td=p.num_stocked
53
+ - if !@orphans.empty?
54
+ %tr
55
+ %td(colspan=4)
56
+ %center
57
+ %b
58
+ = error_icon
59
+ Orphans (not ordered via rawbotz):
60
+ = error_icon
61
+ - @orphans.each do |orphan|
62
+ %tr
63
+ %td
64
+ = orphan[0]
65
+ %td
66
+ %td(title="Quantity ordered")
67
+ = orphan[1]
68
+ %td(title="Quantity refunded")
69
+ = orphan[2]
70
+ %td
71
+ %br