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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -5
- data/Gemfile +2 -0
- data/README.md +60 -6
- data/Rakefile +3 -2
- data/agpl-3.0.txt +661 -0
- data/exe/bcrypt_pw +10 -0
- data/exe/rawbotz_abort_orders +28 -0
- data/exe/rawbotz_process_order_queue +12 -8
- data/exe/rawbotz_stock_update +10 -1
- data/exe/rawbotz_update_local_products +11 -3
- data/exe/rawbotz_update_remote_products +27 -4
- data/lib/rawbotz.rb +13 -5
- data/lib/rawbotz/app.rb +36 -2
- data/lib/rawbotz/cli/order_result_table.rb +13 -0
- data/lib/rawbotz/helpers/format_helper.rb +14 -0
- data/lib/rawbotz/helpers/icon_helper.rb +108 -22
- data/lib/rawbotz/helpers/order_item_color_helper.rb +17 -0
- data/lib/rawbotz/helpers/resource_link_helper.rb +3 -0
- data/lib/rawbotz/mail_template.rb +42 -7
- data/lib/rawbotz/models/sales.rb +21 -0
- data/lib/rawbotz/models/stock.rb +25 -0
- data/lib/rawbotz/models/stock_product.rb +146 -0
- data/lib/rawbotz/models/stock_product_factory.rb +64 -0
- data/lib/rawbotz/processors/order_linker.rb +50 -0
- data/lib/rawbotz/{order_processor.rb → processors/order_processor.rb} +14 -3
- data/lib/rawbotz/processors/organic_product_deliveries_csv.rb +47 -0
- data/lib/rawbotz/{product_updater.rb → processors/product_updater.rb} +71 -6
- data/lib/rawbotz/processors/stock_processor.rb +67 -0
- data/lib/rawbotz/public/rawbotz.css +35 -1
- data/lib/rawbotz/public/rawbotz.js +0 -1
- data/lib/rawbotz/remote_shop.rb +3 -0
- data/lib/rawbotz/routes.rb +3 -0
- data/lib/rawbotz/routes/non_remote_orders.rb +129 -29
- data/lib/rawbotz/routes/orders.rb +55 -4
- data/lib/rawbotz/routes/orders/stock.rb +75 -0
- data/lib/rawbotz/routes/product_links.rb +1 -1
- data/lib/rawbotz/routes/products.rb +19 -22
- data/lib/rawbotz/routes/remote_shop.rb +1 -1
- data/lib/rawbotz/routes/stock.rb +58 -0
- data/lib/rawbotz/routes/suppliers.rb +9 -4
- data/lib/rawbotz/sales_data.rb +13 -0
- data/lib/rawbotz/version.rb +1 -1
- data/lib/rawbotz/views/_hide_unhide_button.haml +1 -1
- data/lib/rawbotz/views/_menu.haml +9 -0
- data/lib/rawbotz/views/index.haml +1 -1
- data/lib/rawbotz/views/layout.haml +0 -1
- data/lib/rawbotz/views/order/_head.haml +64 -19
- data/lib/rawbotz/views/order/_item_table.haml +19 -3
- data/lib/rawbotz/views/order/_order_actions.haml +26 -0
- data/lib/rawbotz/views/order/link_to_remote.haml +30 -0
- data/lib/rawbotz/views/order/non_remote.haml +120 -26
- data/lib/rawbotz/views/order/packlist.haml +62 -5
- data/lib/rawbotz/views/order/packlist.pdf.haml +35 -0
- data/lib/rawbotz/views/order/stock.haml +116 -0
- data/lib/rawbotz/views/order/view.haml +41 -21
- data/lib/rawbotz/views/orders/_order_table.haml +82 -0
- data/lib/rawbotz/views/orders/index.haml +41 -28
- data/lib/rawbotz/views/orders/menu.haml +2 -2
- data/lib/rawbotz/views/orders/non_remotes.haml +14 -3
- data/lib/rawbotz/views/pdf_layout.haml +44 -0
- data/lib/rawbotz/views/product/view.haml +64 -11
- data/lib/rawbotz/views/products/index.haml +1 -1
- data/lib/rawbotz/views/products/table.haml +5 -1
- data/lib/rawbotz/views/remote_cart/index.haml +10 -0
- data/lib/rawbotz/views/remote_order/view.haml +6 -4
- data/lib/rawbotz/views/remote_orders/index.haml +16 -13
- data/lib/rawbotz/views/stock/index.haml +119 -0
- data/lib/rawbotz/views/stock/menu.haml +20 -0
- data/lib/rawbotz/views/stock_product/_value_table_line.haml +22 -0
- data/lib/rawbotz/views/stock_product/value_table.haml +28 -0
- data/lib/rawbotz/views/stockexplorer/stockexplorer.haml +157 -0
- data/lib/rawbotz/views/supplier/orders/table.haml +26 -0
- data/lib/rawbotz/views/supplier/view.haml +56 -10
- data/rawbotz.gemspec +13 -9
- metadata +86 -17
- data/lib/rawbotz/views/order/new.haml +0 -22
@@ -1,24 +1,69 @@
|
|
1
1
|
%h2 General
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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%;"
|
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%;"
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
22
|
-
|
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
|
-
- @
|
27
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
%
|
56
|
-
|
57
|
-
|
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
|
-
|
82
|
-
%
|
83
|
-
%
|
84
|
-
|
85
|
-
%
|
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
|
-
|
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
|
7
|
-
|
8
|
-
|
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
|
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
|