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
@@ -0,0 +1,35 @@
1
+ %h2 Packlist #{@order.supplier.name} from #{@order.created_at}
2
+
3
+ %center
4
+ Last changed #{@order.updated_at}
5
+ - if @order.remote_order_id.present?
6
+ %br
7
+ Remote Order ID:
8
+ = @order.remote_order_id
9
+
10
+ = haml "order/_head".to_sym, locals: {order: @order}
11
+ %br
12
+
13
+ %table.pure-table.pure-table-striped
14
+ %thead
15
+ %tr
16
+ %th
17
+ = products_icon
18
+ Product
19
+ %th
20
+ = shelve_icon
21
+ Shelve
22
+ %th
23
+ = order_icon
24
+ Quantity Ordered
25
+ %th
26
+ = stock_icon
27
+ Quantity Stocked
28
+ %tbody
29
+ - @order.order_items.where("num_ordered > 0").sort_by{|i| i.local_product.name}.each do |p|
30
+ %tr
31
+ %td=p.local_product.name
32
+ %td=p.local_product.shelve_nr
33
+ %td=p.num_ordered
34
+ %td=p.num_stocked
35
+ %br
@@ -0,0 +1,116 @@
1
+ = haml "orders/menu".to_sym
2
+
3
+ :javascript
4
+ $( function() {
5
+ $( document ).tooltip();
6
+ });
7
+
8
+ -# order by name, and use a striped table
9
+ %h1 Stock Order from #{@order.supplier.name}
10
+
11
+
12
+ %form.pure-form(action="" method="post")
13
+ %fieldset
14
+ %legend
15
+ Remote Order Information
16
+ %dl
17
+ %dt
18
+ (Remote) Order ID
19
+ %dd
20
+ %input{value: @order.remote_order_id, name: "remote_order_id"}
21
+ - if @order.supplier == settings.supplier
22
+ %dt
23
+ (Remote) Order Link
24
+ %dd
25
+ %input{value: @order.remote_order_link, name: "remote_order_link"}
26
+ - if @order.remote_order_link.present?
27
+ %a(href="#{@order.remote_order_link}" target="remote_shop")
28
+ = external_link_icon
29
+ = @order.remote_order_link
30
+
31
+ = order_link @order
32
+ %br
33
+
34
+ %fieldset
35
+ %legend
36
+ Items to stock
37
+ %table.pure-table.pure-table-striped
38
+ %thead
39
+ %tr
40
+ %th Remote Name
41
+ %th Local Name
42
+ %th
43
+ = shelve_icon
44
+ Shelve
45
+ %th(title="Quantity wished")
46
+ %i.fa.fa-magic
47
+ %th(title="Quantity actually ordered")
48
+ = product_icon
49
+ %th(title="Packs ordered")
50
+ Packs ordered
51
+ - if @order.supplier == settings.supplier
52
+ %th In remote
53
+ %th Refund
54
+ -#%th
55
+ -# = supplier_icon
56
+ -# Qty delivered
57
+ %th
58
+ - if @order.state == "stocked"
59
+ Number stocked
60
+ - else
61
+ Number to stock
62
+ %tbody
63
+ - @order.order_items.where("num_ordered > ?", 0).find_each do |order_item|
64
+ %tr
65
+ %td
66
+ - if order_item.local_product.remote_product.present?
67
+ = remote_product_link order_item.local_product
68
+ - elsif order_item.local_product.supplier_prod_name.present?
69
+ = order_item.local_product.supplier_prod_name
70
+ - else
71
+ [none]
72
+ %td
73
+ = local_product_link order_item.local_product
74
+ %td= order_item.local_product.shelve_nr
75
+ %td(title="Quantity wished")
76
+ = order_item.num_wished
77
+ %td(title="Quantity actually ordered")
78
+ = order_item.num_ordered
79
+ %td(title="Packs ordered")
80
+ - if order_item.num_ordered && order_item.local_product.packsize.present?
81
+ = "%g" % (order_item.num_ordered / order_item.local_product.packsize)
82
+ = pack_icon
83
+ - if @order.supplier == settings.supplier
84
+ %td
85
+ = @refunds[order_item].try :qty_ordered
86
+ - if @refunds[order_item].nil?
87
+ = warning_icon
88
+ %td
89
+ = @refunds[order_item].try :qty_refunded
90
+ - if @refunds[order_item].nil?
91
+ = warning_icon
92
+ -#%td
93
+ %td
94
+ - if order_item.stocked?
95
+ stocked #{order_item.num_stocked}
96
+ - else
97
+ - qty = order_item.num_ordered
98
+ - if @refunds[order_item].present?
99
+ - qty = @refunds[order_item].qty_ordered.to_i - @refunds[order_item].qty_refunded.to_i
100
+ %input(name="qty_delivered_#{order_item.id}" value="#{qty}")
101
+ - if @orphans
102
+ %tr
103
+ %td(colspan=6)
104
+ %h3 'Extra' products
105
+ %b These products were not found in the original order, please take care of these by hand
106
+ - @orphans.each do |orphan|
107
+ %tr
108
+ %td(colspan=6)= orphan[0]
109
+ %td(title="Quantity ordered (in remote order)")= orphan[1]
110
+ %td(title="Quantity refunded (in remote order)")= orphan[2]
111
+ %td
112
+
113
+ - if @order.state != "stocked"
114
+ %button.pure-button
115
+ Add to Stock
116
+
@@ -1,5 +1,10 @@
1
1
  = haml "orders/menu".to_sym
2
2
 
3
+ :javascript
4
+ $( function() {
5
+ $( document ).tooltip();
6
+ });
7
+
3
8
  %h1 View Order
4
9
 
5
10
  #modal-plot.modal-plot
@@ -17,7 +22,8 @@
17
22
 
18
23
  #tabs
19
24
  - supplier_name = settings.supplier
20
- - understocked_items = @order.order_items.select{|i| i.local_product.supplier==supplier_name && i.num_wished.nil?}
25
+ -# Use scopes?
26
+ - understocked_items = @order.order_items.select{|i| i.local_product.present? && i.num_wished.nil?}
21
27
  - unordered_items = []
22
28
  - ordered_items = @order.order_items.select{|i| i.num_wished.present? && i.num_wished != 0}
23
29
  - ignored_items = @order.order_items.select{|i| i.local_product.supplier==supplier_name && i.num_wished == 0}
@@ -42,38 +48,52 @@
42
48
  %p
43
49
  Add another item?
44
50
  %br
45
- %h2 Action
46
- %center
47
- -#(Find remote order? Delete?)
48
- %button.pure-button.pure-button-secondary(name="action" value="save")
49
- Save
50
- %button.pure-button.pure-button-primary(name="action" value="order")
51
- Order!
52
- %button.pure-button.pure-button-primary(name="action" value="delete")
53
- Delete
51
+ %label(for="internal_comment")
52
+ Internal Comment
53
+ %textarea#internal_comment(name="internal_comment")~ @order.internal_comment
54
+ %br
55
+ = haml "order/_order_actions".to_sym, locals: {order: @order}
54
56
  - else
57
+ = haml "order/_order_actions".to_sym, locals: {order: @order}
58
+ %br
55
59
  %table.pure-table
56
60
  %thead
57
61
  %tr
58
62
  %th
59
63
  Item
60
- %th
61
- Wished Qty
62
- %th
63
- Ordered Qty
64
+ %th(title="Wished Qty")
65
+ %i.fa.fa-magic
66
+ %th(title="Ordered Qty")
67
+ %i.fa.fa-arrow-right
64
68
  %th
65
69
  Stock at time
70
+ %th
71
+ Stocked Qty
72
+ - if !@stock.empty?
73
+ %th Current Stock
66
74
  %tbody
67
75
  - @order.order_items.find_each do |item|
68
- %tr
76
+ %tr{:class => order_item_class(item)}
77
+ -# color when not avail, or less available than wished!
69
78
  %td
70
79
  = local_product_link item.local_product
71
- %td
80
+ %br
81
+ - if item.local_product.order_info.present?
82
+ %small= item.local_product.order_info
83
+ %td(title="Quantity wished")
84
+ - if item.state == "error"
85
+ = error_icon tooltip_text: "There was an error during ordering - does the product exist?"
72
86
  =item.num_wished
73
- %td
87
+ %td(title="Quantity ordered")
88
+ - if item.state == "error"
89
+ = error_icon tooltip_text: "There was an error during ordering - does the product exist?"
74
90
  =item.num_ordered
75
- %td
91
+ %td(title="Stock at that time")
76
92
  =item.current_stock
77
- -# %h2 Action
78
- -# (Find remote order? Delete?)
79
-
93
+ %td(title="Quantity stocked")
94
+ =item.num_stocked
95
+ - if !@stock.empty?
96
+ %td(title="Current Stock")
97
+ = @stock[item.local_product.product_id]
98
+ %br
99
+ = haml "order/_order_actions".to_sym, locals: {order: @order}
@@ -0,0 +1,82 @@
1
+ :javascript
2
+ $( function() {
3
+ $( document ).tooltip();
4
+ });
5
+
6
+ %table.pure-table
7
+ %thead
8
+ %tr
9
+ %th Date
10
+ %th
11
+ = supplier_icon
12
+ Supplier
13
+ %th Number of Items
14
+ %th Action
15
+ %th State
16
+ %tbody
17
+ - if supplier.present?
18
+ %tr
19
+ %td(colspan=5)
20
+ %center
21
+ - if supplier == settings.supplier
22
+ %a.pure-button(href="/order/new")
23
+ = add_icon
24
+ Create New Remote Order
25
+ - else
26
+ %a.pure-button(href="/order/non_remote/#{supplier.id}/new")
27
+ = add_icon
28
+ Create New Mail Order
29
+ -# find_each ignores order!
30
+ - orders.each do |order|
31
+ %tr
32
+ %td=order.created_at
33
+ %td
34
+ = supplier_link order.supplier
35
+ - if order.supplier == settings.supplier
36
+ (remote)
37
+ %td
38
+ = order.order_items.count
39
+ (
40
+ = order.order_items.processible.count
41
+ )
42
+ %td
43
+ - if order.supplier == settings.supplier
44
+ %a.pure-button(href="/order/#{order.id}")
45
+ = view_icon
46
+ View
47
+ - else
48
+ %a.pure-button(href="/order/non_remote/#{order.id}")
49
+ = view_icon
50
+ View
51
+
52
+ - if order.state == "ordered" || order.state == 'mailed' || order.state == "stocked"
53
+ - tooltip = "Packlist"
54
+ - if order.supplier == settings.supplier
55
+ - if order.remote_order_link.present?
56
+ - tooltip += " with real values from remote order"
57
+ - else
58
+ - tooltip += " without refunds, with rawbotz data only"
59
+ %a.pure-button(href="/order/#{order.id}/packlist" title="#{tooltip}")
60
+ - if order.supplier == settings.supplier
61
+ - if order.remote_order_link.present?
62
+ %i.fa.fa-thumbs-o-up
63
+ - else
64
+ %i.fa.fa-thumbs-o-down
65
+ = packlist_icon
66
+ Packlist
67
+ - if order.state == "ordered" || order.state == 'mailed'
68
+ %a.pure-button(href="/order/#{order.id}/stock")
69
+ %i.fa.fa-cart-arrow-down
70
+ Stock
71
+
72
+ %td
73
+ .state-label
74
+ = order_state_icon order
75
+ = order.state
76
+ - if order.state == 'processing'
77
+ = order.order_items.where("num_ordered > ?", 0).count
78
+ of
79
+ = order.order_items.where("num_wished > ?", 0).count
80
+ (
81
+ = "%.2f" % (order.order_items.where("num_ordered > ?", 0).count.to_f / order.order_items.where("num_wished > ?", 0).count)
82
+ \%)
@@ -2,6 +2,18 @@
2
2
 
3
3
  %h1 Orders
4
4
 
5
+ :javascript
6
+ $(document).ready(function() {
7
+ $( "#tabs" ).tabs();
8
+ });
9
+
10
+
11
+ - if Order.in_state('processing').present?
12
+ - current_processing = Order.in_state("processing").all[0]
13
+ = current_processing.order_items.where("num_ordered > ?", 0).count
14
+ of
15
+ = current_processing.order_items.where("num_wished > ?", 0).count
16
+
5
17
  - if Order.current.present?
6
18
  %a(href="/order/#{Order.current.id}")
7
19
  Current Order
@@ -9,32 +21,33 @@
9
21
  %a(href="/order/new") New Order
10
22
 
11
23
  %br
12
- - if @orders.count > 0
13
- %br
14
-
15
- %table.pure-table
16
- %thead
17
- %tr
18
- %th Date
19
- %th Number of Items
20
- %th Action
21
- %th State
22
- %tbody
23
- - @orders.each do |order|
24
- %tr
25
- %td=order.created_at
26
- %td
27
- = order.order_items.count
28
- (
29
- = order.order_items.processible.count
30
- )
31
- %td
32
- %a.pure-button(href="/order/#{order.id}")
33
- %i.fa.fa-eye
34
- View
35
- - if order.state == "ordered"
36
- %a.pure-button(href="/order/#{order.id}/packlist")
37
- %i.fa.fa-paper
38
- Packlist
39
24
 
40
- %td=order.state
25
+ #tabs
26
+ %ul
27
+ %li
28
+ %a(href="#tab_all_orders") All
29
+ - if @orders.in_state('ordered').present?
30
+ %li
31
+ %a(href="#tab_ordered_orders") Ordered
32
+ - if @orders.in_state('deleted').present?
33
+ %li
34
+ %a(href="#tab_deleted_orders") Deleted
35
+ - Supplier.find_each do |s|
36
+ - if s.orders.count != 0
37
+ %li
38
+ %a(href="#tab_by_supplier_#{s.id}") By Supplier: #{s.name}
39
+ - Supplier.find_each do |s|
40
+ - if s.orders.count != 0
41
+ %div(id="tab_by_supplier_#{s.id}")
42
+ = haml "orders/_order_table".to_sym, locals: {orders: s.orders.where.not(state: 'deleted').order(updated_at: :desc), supplier: s}
43
+ %br
44
+ %br
45
+ %a.pure-button.pure-button-primary(href="/order/non_remote/#{s.id}/new") New Order
46
+ #tab_all_orders
47
+ = haml "orders/_order_table".to_sym, locals: {orders: @orders.where.not(state: 'deleted'), supplier: nil}
48
+ - if @orders.in_state('ordered').present?
49
+ #tab_ordered_orders
50
+ = haml "orders/_order_table".to_sym, locals: {orders: @orders.in_state('ordered'), supplier: nil}
51
+ - if @orders.in_state('deleted').present?
52
+ #tab_deleted_orders
53
+ = haml "orders/_order_table".to_sym, locals: {orders: @orders.in_state('deleted'), supplier: nil}
@@ -12,11 +12,11 @@
12
12
  Orders
13
13
  %li.pure-menu-item
14
14
  %a.pure-menu-link(href="/order/new")
15
- %i(class="fa fa-plus")
15
+ = add_icon
16
16
  New or current
17
17
  %li.pure-menu-item
18
18
  %a.pure-menu-link(href="/orders/non_remote")
19
- %i(class="fa fa-envelope-o")
19
+ = mail_icon
20
20
  Other Suppliers
21
21
  %li.pure-menu-item
22
22
  %a.pure-menu-link(href="/remote_orders")
@@ -2,7 +2,18 @@
2
2
 
3
3
  %h1 Non-Remote Order
4
4
 
5
- - Supplier.find_each do |supplier|
6
- %a.supplier(href="/order/non_remote/#{supplier.id}")
7
- =supplier.name
5
+ %ul.float_ul
6
+ - @suppliers.each do |supplier|
7
+ %li
8
+ - if supplier.order_template.present?
9
+ %a.supplier(href="/order/non_remote/#{supplier.id}/new")
10
+ = supplier.name
11
+ - else
12
+ %a.supplier(href="/supplier/#{supplier.id}#tab_order_settings")
13
+ = supplier.name
14
+ (!)
15
+ -# - if supplier.mail temp...
16
+ -# %a(href="/order/non_remote/#{supplier.id}/new")
17
+ -# New Order
18
+ -# -# direct link to order? and also, show whether settings are needed
8
19
  %br
@@ -0,0 +1,44 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title Rawbotz
5
+ %meta{name: "pdfkit-page_size", content: "A4"}
6
+ %meta(name="viewport" content="width=device-width, initial-scale=1")
7
+ %meta(charset="utf-8")
8
+ -# CSS stuff will be inserted by pdfkit
9
+ %body
10
+ .pure-g
11
+ .pure-u-1#main
12
+ - if flash
13
+ - if msg = flash.delete(:error)
14
+ #flash.ui-state-error
15
+ = error_icon
16
+ = msg.join(" | ")
17
+ - if msg = flash.delete(:success)
18
+ #flash.ui-state-highlight
19
+ = success_icon
20
+ = msg.join(" | ")
21
+ - if msg = flash.delete(:failure)
22
+ #flash.ui-state-highlight
23
+ = error_icon
24
+ = msg.join(" | ")
25
+ - if msg = flash.delete(:info)
26
+ #flash.ui-state-highlight
27
+ = info_icon
28
+ = msg.join(" | ")
29
+ -# Consume the remainder
30
+ - if flash.length > 0
31
+ #flash.ui-state-highlight
32
+ - flash.each do |f|
33
+ = error_icon
34
+ = flash.delete(f[0]).join(" | ")
35
+
36
+ =yield
37
+ %br
38
+ .pure-u-1
39
+ .pure-menu.pure-menu-horizontal#menu
40
+ %small
41
+ %center
42
+ %ul.pure-menu-list
43
+ %li.pure-menu-item
44
+ Rawbotz #{Rawbotz::VERSION} 2016 (c) Felix Wolfsteller