rawbotz 0.1.5 → 0.2.0

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