smerp-quotation-engine 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +10 -0
- data/app/assets/config/smerp_quotation_engine_manifest.js +1 -0
- data/app/assets/stylesheets/smerp/quotation/engine/application.css +15 -0
- data/app/controllers/smerp/quotation/engine/application_controller.rb +9 -0
- data/app/controllers/smerp/quotation/engine/quotation_item_groups_controller.rb +70 -0
- data/app/controllers/smerp/quotation/engine/quotation_items_controller.rb +237 -0
- data/app/controllers/smerp/quotation/engine/quotation_product_categories_controller.rb +60 -0
- data/app/controllers/smerp/quotation/engine/quotation_products_controller.rb +60 -0
- data/app/controllers/smerp/quotation/engine/quotations_controller.rb +192 -0
- data/app/helpers/smerp/quotation/engine/application_helper.rb +29 -0
- data/app/helpers/smerp/quotation/engine/quotation_item_groups_helper.rb +4 -0
- data/app/helpers/smerp/quotation/engine/quotation_items_helper.rb +4 -0
- data/app/helpers/smerp/quotation/engine/quotation_product_categories_helper.rb +4 -0
- data/app/helpers/smerp/quotation/engine/quotation_products_helper.rb +4 -0
- data/app/helpers/smerp/quotation/engine/quotations_helper.rb +81 -0
- data/app/jobs/smerp/quotation/engine/application_job.rb +8 -0
- data/app/mailers/smerp/quotation/engine/application_mailer.rb +10 -0
- data/app/models/smerp/quotation/engine/application_record.rb +9 -0
- data/app/models/smerp/quotation/engine/quotation.rb +11 -0
- data/app/models/smerp/quotation/engine/quotation_item.rb +34 -0
- data/app/models/smerp/quotation/engine/quotation_item_group.rb +10 -0
- data/app/models/smerp/quotation/engine/quotation_product.rb +30 -0
- data/app/models/smerp/quotation/engine/quotation_product_category.rb +11 -0
- data/app/views/layouts/smerp/quotation/engine/application.html.erb +15 -0
- data/app/views/smerp/quotation/engine/_new_quotation_item_form.html.erb +48 -0
- data/app/views/smerp/quotation/engine/extended_calculators/extended_calculators.html.erb +36 -0
- data/app/views/smerp/quotation/engine/quotation_item_groups/_form.html.erb +17 -0
- data/app/views/smerp/quotation/engine/quotation_item_groups/_quotation_item_group.html.erb +2 -0
- data/app/views/smerp/quotation/engine/quotation_item_groups/edit.html.erb +10 -0
- data/app/views/smerp/quotation/engine/quotation_item_groups/index.html.erb +14 -0
- data/app/views/smerp/quotation/engine/quotation_item_groups/new.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotation_item_groups/show.html.erb +10 -0
- data/app/views/smerp/quotation/engine/quotation_items/_form.html.erb +53 -0
- data/app/views/smerp/quotation/engine/quotation_items/_product_item_form.html.erb +47 -0
- data/app/views/smerp/quotation/engine/quotation_items/_quotation_item.html.erb +17 -0
- data/app/views/smerp/quotation/engine/quotation_items/edit.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotation_items/index.html.erb +14 -0
- data/app/views/smerp/quotation/engine/quotation_items/new.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotation_items/new_product_item.html.erb +7 -0
- data/app/views/smerp/quotation/engine/quotation_items/show.html.erb +76 -0
- data/app/views/smerp/quotation/engine/quotation_product_categories/_form.html.erb +33 -0
- data/app/views/smerp/quotation/engine/quotation_product_categories/_quotation_product_category.html.erb +17 -0
- data/app/views/smerp/quotation/engine/quotation_product_categories/edit.html.erb +10 -0
- data/app/views/smerp/quotation/engine/quotation_product_categories/index.html.erb +14 -0
- data/app/views/smerp/quotation/engine/quotation_product_categories/new.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotation_product_categories/show.html.erb +10 -0
- data/app/views/smerp/quotation/engine/quotation_products/_form.html.erb +41 -0
- data/app/views/smerp/quotation/engine/quotation_products/_quotation_product.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotation_products/edit.html.erb +10 -0
- data/app/views/smerp/quotation/engine/quotation_products/index.html.erb +19 -0
- data/app/views/smerp/quotation/engine/quotation_products/new.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotation_products/show.html.erb +32 -0
- data/app/views/smerp/quotation/engine/quotations/_form.html.erb +49 -0
- data/app/views/smerp/quotation/engine/quotations/_new_group_form.html.erb +24 -0
- data/app/views/smerp/quotation/engine/quotations/_product_item_form.html.erb +47 -0
- data/app/views/smerp/quotation/engine/quotations/_quotation.html.erb +10 -0
- data/app/views/smerp/quotation/engine/quotations/_quotation_item.html.erb +96 -0
- data/app/views/smerp/quotation/engine/quotations/edit.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotations/extended_calculators.html.erb +36 -0
- data/app/views/smerp/quotation/engine/quotations/index.html.erb +21 -0
- data/app/views/smerp/quotation/engine/quotations/new.html.erb +9 -0
- data/app/views/smerp/quotation/engine/quotations/new_extended_calculator.html.erb +65 -0
- data/app/views/smerp/quotation/engine/quotations/new_product_item.html.erb +7 -0
- data/app/views/smerp/quotation/engine/quotations/show.html.erb +151 -0
- data/config/routes.rb +50 -0
- data/db/migrate/20220929020407_create_smerp_quotation_engine_quotation_products.rb +16 -0
- data/db/migrate/20220929041715_create_smerp_quotation_engine_quotation_product_categories.rb +12 -0
- data/db/migrate/20220929074438_link_product_to_item.rb +5 -0
- data/db/seeds.rb +36 -0
- data/lib/smerp/quotation/engine/engine.rb +40 -0
- data/lib/smerp/quotation/engine/version.rb +7 -0
- data/lib/smerp/quotation/engine.rb +10 -0
- data/lib/tasks/smerp/quotation/engine_tasks.rake +4 -0
- metadata +216 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<div id="<%= dom_id quotation_item %>">
|
|
2
|
+
|
|
3
|
+
<tr style="background-color: <%= level_marker(level) %>">
|
|
4
|
+
<td>
|
|
5
|
+
<%= (" * " * level).html_safe %>
|
|
6
|
+
<%= index+1 %>.
|
|
7
|
+
<%= link_to quotation_item.name, quotation_quotation_item_path(@quotation, quotation_item) %>
|
|
8
|
+
<%#= link_to "Add Sub Item", add_sub_item_quotation_item_url(quotation_item) %>
|
|
9
|
+
<%= link_to image_tag('add.png', size: "20x20"), add_sub_item_quotation_item_url(quotation_item) %>
|
|
10
|
+
<%= link_to image_tag('add-product_item.png', size: "20x20"), new_product_item_quotation_item_url(quotation_item) %>
|
|
11
|
+
<% if quotation_item.children.length > 0 %>
|
|
12
|
+
<% if is_children_hidden?(quotation_item.id) %>
|
|
13
|
+
<%= link_to image_tag('show.png'), show_children_quotation_item_url(quotation_item), data: { turbo_method: :post } %>
|
|
14
|
+
<% else %>
|
|
15
|
+
<%= link_to image_tag('icon-hide.png', size: "20x20"), hide_children_quotation_item_url(quotation_item), data: { turbo_method: :post } %>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% end %>
|
|
18
|
+
</td>
|
|
19
|
+
<td class="text-center"><%= quotation_item.quantity %></td>
|
|
20
|
+
<td class="text-first"><%= quotation_item.unit %></td>
|
|
21
|
+
<td class="text-end">
|
|
22
|
+
<%= currency(quotation_item.unit_price) %>
|
|
23
|
+
<div class="collapse" id="dist<%= quotation_item.id %>">
|
|
24
|
+
<%= form_for(:quotation_item, url: apply_discount_quotation_item_path(quotation_item), method: :post) do |f| %>
|
|
25
|
+
<%= f.hidden_field :discount_on, value: :unit_price %>
|
|
26
|
+
<table class="table">
|
|
27
|
+
<tr>
|
|
28
|
+
<td width="28px"><%= f.text_field :discount, class: "form-control text-end" %></td>
|
|
29
|
+
</tr>
|
|
30
|
+
<tr>
|
|
31
|
+
<td><%= f.submit "Apply", class: "btn btn-primary form-control" %></td>
|
|
32
|
+
</tr>
|
|
33
|
+
</table>
|
|
34
|
+
<% end %>
|
|
35
|
+
</div>
|
|
36
|
+
</td>
|
|
37
|
+
<td class="text-end">
|
|
38
|
+
<%= currency(quotation_item.line_total) %>
|
|
39
|
+
<div class="collapse" id="dist<%= quotation_item.id %>">
|
|
40
|
+
<%= form_for(:quotation_item, url: apply_discount_quotation_item_path(quotation_item), method: :post) do |f| %>
|
|
41
|
+
<%= f.hidden_field :discount_on, value: :line_total %>
|
|
42
|
+
<% eExtCal = quotation_item.get_item_discount(:line_total) %>
|
|
43
|
+
<% if not eExtCal.nil? %>
|
|
44
|
+
<%= f.hidden_field :ecid, value: eExtCal.ecid %>
|
|
45
|
+
<% end %>
|
|
46
|
+
<table class="table">
|
|
47
|
+
<tr>
|
|
48
|
+
<td width="28px">
|
|
49
|
+
<%= f.text_field :discount, value: eExtCal.nil? ? "" : extended_calculator_value_code(eExtCal), class: "form-control text-center" %>
|
|
50
|
+
</td>
|
|
51
|
+
</tr>
|
|
52
|
+
<tr>
|
|
53
|
+
<td><%= f.submit "Apply", class: "btn btn-primary form-control" %></td>
|
|
54
|
+
</tr>
|
|
55
|
+
</table>
|
|
56
|
+
<% end %>
|
|
57
|
+
</div>
|
|
58
|
+
</td>
|
|
59
|
+
<td class="text-end">
|
|
60
|
+
<%= link_to currency(quotation_item.discount), "#dist#{quotation_item.id}", "data-bs-toggle" => "collapse", "aria-expanded" => "false", "aria-controls" => "dist#{quotation_item.id}", role: "button" %>
|
|
61
|
+
</td>
|
|
62
|
+
<td>(<%= quotation_item.discount.percent_of(quotation_item.line_total,2) %>%)</td>
|
|
63
|
+
<td class="text-end"><%= currency(quotation_item.line_total_after_discount) %></td>
|
|
64
|
+
<td class="text-end">
|
|
65
|
+
<%= link_to currency(quotation_item.tax), "#tax#{quotation_item.id}", "data-bs-toggle" => "collapse", "aria-expanded" => "false", "aria-controls" => "tax#{quotation_item.id}", role: "button" %>
|
|
66
|
+
<div class="collapse" id="tax<%= quotation_item.id %>">
|
|
67
|
+
<%= form_for(:quotation_item, url: apply_tax_quotation_item_path(quotation_item), method: :post) do |f| %>
|
|
68
|
+
<% eExtCal = quotation_item.get_item_tax %>
|
|
69
|
+
<% if not eExtCal.nil? %>
|
|
70
|
+
<%= f.hidden_field :ecid, value: eExtCal.ecid %>
|
|
71
|
+
<% end %>
|
|
72
|
+
<table class="table">
|
|
73
|
+
<tr>
|
|
74
|
+
<td width="28px">
|
|
75
|
+
<%= f.text_field :tax, value: eExtCal.nil? ? "" : extended_calculator_value_code(eExtCal), class: "form-control text-center" %>
|
|
76
|
+
</td>
|
|
77
|
+
</tr>
|
|
78
|
+
<tr>
|
|
79
|
+
<td><%= f.submit "Apply", class: "btn btn-primary form-control" %></td>
|
|
80
|
+
</tr>
|
|
81
|
+
</table>
|
|
82
|
+
<% end %>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
</td>
|
|
86
|
+
<td><%= link_to image_tag('taxfree.png', size: "22x22"), remove_tax_quotation_item_path(quotation_item), data: { turbo_method: "post" } %></td>
|
|
87
|
+
<td class="text-end"><%= currency(quotation_item.line_total_with_tax) %></td>
|
|
88
|
+
<td>
|
|
89
|
+
<%= link_to image_tag('edit.png'), edit_quotation_quotation_item_path(quotation_item.quotation, quotation_item) %>
|
|
90
|
+
<%= link_to image_tag('Delete.png'), quotation_item_path(quotation_item), dataz: { turbo_method: :delete, turbo_confirm: "Delete this item?" } %>
|
|
91
|
+
</td>
|
|
92
|
+
</tr>
|
|
93
|
+
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
<h2>Extended Calculator for Quotation</h2>
|
|
3
|
+
|
|
4
|
+
<table class="table">
|
|
5
|
+
|
|
6
|
+
<tr>
|
|
7
|
+
<th>Calculator Type</th>
|
|
8
|
+
<th>Calculator Applicability</th>
|
|
9
|
+
<th>Value</th>
|
|
10
|
+
<th></th>
|
|
11
|
+
</tr>
|
|
12
|
+
|
|
13
|
+
<% @privExtCals.each do |ec| %>
|
|
14
|
+
<tr>
|
|
15
|
+
<td><%= extended_calculator_name(ec) %></td>
|
|
16
|
+
<td>Quotation</td>
|
|
17
|
+
<td><%= extended_calculator_value_name(ec) %></td>
|
|
18
|
+
<td><%= link_edit edit_extended_calculator_quotation_path(@quotation, ecid: ec.ecid) %></td>
|
|
19
|
+
</tr>
|
|
20
|
+
<% end %>
|
|
21
|
+
|
|
22
|
+
<% @extCals.each do |ec| %>
|
|
23
|
+
<tr>
|
|
24
|
+
<td><%= extended_calculator_name(ec) %></td>
|
|
25
|
+
<td>Quotation Items</td>
|
|
26
|
+
<td><%= extended_calculator_value_name(ec) %></td>
|
|
27
|
+
<td><%= link_edit edit_extended_calculator_quotation_path(@quotation, ecid: ec.ecid) %></td>
|
|
28
|
+
</tr>
|
|
29
|
+
<% end %>
|
|
30
|
+
|
|
31
|
+
</table>
|
|
32
|
+
|
|
33
|
+
<%= link_to "Back", @quotation, class: "btn btn-secondary" %>
|
|
34
|
+
<%= link_to "Add Calculator", new_extended_calculator_quotation_path(@quotation), class: "btn btn-primary" %>
|
|
35
|
+
|
|
36
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<p style="color: green"><%= notice %></p>
|
|
2
|
+
|
|
3
|
+
<h1>Quotations</h1>
|
|
4
|
+
|
|
5
|
+
<div id="quotations">
|
|
6
|
+
<table class="table">
|
|
7
|
+
<tr>
|
|
8
|
+
<th>Quotation ID</th>
|
|
9
|
+
<th>Customer</th>
|
|
10
|
+
<th>Quotation Date</th>
|
|
11
|
+
<th>Status</th>
|
|
12
|
+
</tr>
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
<% @quotations.each do |quotation| %>
|
|
16
|
+
<%= render quotation %>
|
|
17
|
+
<% end %>
|
|
18
|
+
</table>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<%= link_to "New quotation", new_quotation_path, class: "btn btn-primary" %>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<h3>Extended Calculator</h3>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
//function load_applicability() {
|
|
7
|
+
// cType = document.getElementById('calculator_cal_type');
|
|
8
|
+
// tfield = document.getElementById('input_field_for_type');
|
|
9
|
+
// alert(cType.value)
|
|
10
|
+
// //return true;
|
|
11
|
+
// return new Promise(function(resolv, reject) {
|
|
12
|
+
// var xhr = new XMLHttpRequest();
|
|
13
|
+
// xhr.open('POST',"<%#= extcal_input_field_filter_quotations_path %>");
|
|
14
|
+
// xhr.setRequestHeader('X-CSRF-Token',document.querySelector('meta[name="csrf-token"]').content);
|
|
15
|
+
// xhr.onload = function() {
|
|
16
|
+
// if(this.status >= 200 && this.status < 300) {
|
|
17
|
+
// //alert(xhr.response);
|
|
18
|
+
// tfield.innerHTML = xhr.response;
|
|
19
|
+
// }
|
|
20
|
+
// else
|
|
21
|
+
// {
|
|
22
|
+
// reject({ status: this.status, statusText: xhr.statusText });
|
|
23
|
+
// }
|
|
24
|
+
// };
|
|
25
|
+
|
|
26
|
+
// xhr.onerror = function() {
|
|
27
|
+
// reject({ status: this.status, statusText: xhr.statusText });
|
|
28
|
+
// };
|
|
29
|
+
|
|
30
|
+
// xhr.send({ ctype: cType });
|
|
31
|
+
|
|
32
|
+
// });
|
|
33
|
+
//}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<table class="table">
|
|
37
|
+
<%= form_for :calculator, url: create_calculator_quotation_path(@quotation) do |f| %>
|
|
38
|
+
<%= f.hidden_field :quotation_id, value: @quotation.id %>
|
|
39
|
+
<div class="row">
|
|
40
|
+
<div class="col">Calculator Type</div>
|
|
41
|
+
<div class="col">Applicable</div>
|
|
42
|
+
<div class="col">Value</div>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="row">
|
|
45
|
+
<div class="col"><%= f.select :cal_type, [["Discount", :discount],["Tax",:tax]], { }, onchange: "load_applicability();", class: "form-control" %></div>
|
|
46
|
+
<!--
|
|
47
|
+
<div class="col" id="input_field_for_type"> </div>
|
|
48
|
+
-->
|
|
49
|
+
<div class="col"><%= f.select :applicability, [["Quotation Only", :quotation],["Quotation Items", :items]], { }, class: "form-control" %></div>
|
|
50
|
+
<div class="col"><%= f.text_field :value, class: "form-control" %></div>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div class="row pt-2">
|
|
54
|
+
<div class="col">
|
|
55
|
+
<%= link_to "Back", extended_calculators_quotation_path(@quotation), class: "btn btn-secondary" %>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="col">
|
|
58
|
+
</div>
|
|
59
|
+
<div class="col text-end">
|
|
60
|
+
<%= f.submit "Save Calculator", class: "btn btn-primary" %>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<% end %>
|
|
65
|
+
</table>
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<h2>Quotation</h2>
|
|
4
|
+
|
|
5
|
+
<table class="table">
|
|
6
|
+
<tr>
|
|
7
|
+
<th>Quotation ID</th>
|
|
8
|
+
<td><%= @quotation.qid %></td>
|
|
9
|
+
<th>Date</th>
|
|
10
|
+
<td><%= @quotation.qdate.nil? ? "" : @quotation.qdate.strftime("%d-%m-%Y (%a)") %></td>
|
|
11
|
+
</tr>
|
|
12
|
+
|
|
13
|
+
<tr>
|
|
14
|
+
<th>Name</th>
|
|
15
|
+
<td><%= @quotation.name %></td>
|
|
16
|
+
<th>Status</th>
|
|
17
|
+
<td><%= @quotation.state.to_s.titleize %></td>
|
|
18
|
+
</tr>
|
|
19
|
+
|
|
20
|
+
<tr>
|
|
21
|
+
<th>Address</th>
|
|
22
|
+
<td colspan="3"><%= @quotation.address %></td>
|
|
23
|
+
</tr>
|
|
24
|
+
|
|
25
|
+
<tr>
|
|
26
|
+
<th>Attention To</th>
|
|
27
|
+
<td><%= @quotation.attention_to %></td>
|
|
28
|
+
</tr>
|
|
29
|
+
</table>
|
|
30
|
+
|
|
31
|
+
<%= link_to "Back", quotations_path, class: "btn btn-secondary" %>
|
|
32
|
+
<%= link_to "Edit", edit_quotation_path(@quotation), class: "btn btn-warning" %>
|
|
33
|
+
<%= link_to "Add/Edit Extended Calculator", extended_calculators_quotation_path(@quotation), class: "btn btn-info" %>
|
|
34
|
+
|
|
35
|
+
<table class="table">
|
|
36
|
+
|
|
37
|
+
<tr>
|
|
38
|
+
<th>Calculator Type</th>
|
|
39
|
+
<th>Calculator Applicability</th>
|
|
40
|
+
<th>Value</th>
|
|
41
|
+
</tr>
|
|
42
|
+
|
|
43
|
+
<% @privExtCals.each do |ec| %>
|
|
44
|
+
<tr>
|
|
45
|
+
<td><%= extended_calculator_name(ec) %></td>
|
|
46
|
+
<td>Quotation</td>
|
|
47
|
+
<td><%= extended_calculator_value_name(ec) %></td>
|
|
48
|
+
</tr>
|
|
49
|
+
<% end %>
|
|
50
|
+
|
|
51
|
+
<% @extCals.each do |ec| %>
|
|
52
|
+
<tr>
|
|
53
|
+
<td><%= extended_calculator_name(ec) %></td>
|
|
54
|
+
<td>Quotation Items</td>
|
|
55
|
+
<td><%= extended_calculator_value_name(ec) %></td>
|
|
56
|
+
</tr>
|
|
57
|
+
<% end %>
|
|
58
|
+
|
|
59
|
+
</table>
|
|
60
|
+
|
|
61
|
+
<hr>
|
|
62
|
+
|
|
63
|
+
<h3>Details</h3>
|
|
64
|
+
|
|
65
|
+
<% if not notice.nil? %>
|
|
66
|
+
<div class="alert alert-success text-center w-100" role="alert">
|
|
67
|
+
<%= notice %>
|
|
68
|
+
</div>
|
|
69
|
+
<% end %>
|
|
70
|
+
|
|
71
|
+
<table class="table" id="details">
|
|
72
|
+
|
|
73
|
+
<tr>
|
|
74
|
+
<th width="38%">Name</th>
|
|
75
|
+
<th class="text-center">Quantity</th>
|
|
76
|
+
<th class="text-center">Unit</th>
|
|
77
|
+
<th class="text-end">Unit Price</th>
|
|
78
|
+
<th class="text-end">Line Total</th>
|
|
79
|
+
<th class="text-center" colspan="2">Discount</th>
|
|
80
|
+
<th class="text-end">Total After Discount</th>
|
|
81
|
+
<th class="text-center" colspan="2">Tax</th>
|
|
82
|
+
<th class="text-end">Total with Tax</th>
|
|
83
|
+
<th> </th>
|
|
84
|
+
</tr>
|
|
85
|
+
|
|
86
|
+
<% @quotation.quotation_item_groups.each do |g| %>
|
|
87
|
+
<tr>
|
|
88
|
+
<td>
|
|
89
|
+
<%= g.name %>
|
|
90
|
+
</td>
|
|
91
|
+
<td> </td>
|
|
92
|
+
<td> </td>
|
|
93
|
+
<td> </td>
|
|
94
|
+
<td> </td>
|
|
95
|
+
<td> </td>
|
|
96
|
+
<td> </td>
|
|
97
|
+
<td> </td>
|
|
98
|
+
<td> </td>
|
|
99
|
+
<td> </td>
|
|
100
|
+
<td> </td>
|
|
101
|
+
<td> </td>
|
|
102
|
+
</tr>
|
|
103
|
+
|
|
104
|
+
<% g.quotation_items.each do |i| %>
|
|
105
|
+
<%= render "quotation_item", quotation_item: i, level: 1 %>
|
|
106
|
+
<%= render_item_tree_table(i, 1).join.html_safe %>
|
|
107
|
+
<% end %>
|
|
108
|
+
|
|
109
|
+
<% end %>
|
|
110
|
+
|
|
111
|
+
<% indx = 0 %>
|
|
112
|
+
<% @quotation.quotation_items.where(["parent_id is null"]).each do |i| %>
|
|
113
|
+
|
|
114
|
+
<%= render "quotation_item", quotation_item: i, level: 0, index: indx %>
|
|
115
|
+
|
|
116
|
+
<% indx += 1 %>
|
|
117
|
+
|
|
118
|
+
<% if session[:hide_children_parent_id].nil? or not session[:hide_children_parent_id].include?(i.id) %>
|
|
119
|
+
<% iindx = 0 %>
|
|
120
|
+
<% i.children.each do |c| %>
|
|
121
|
+
<%= render "quotation_item", quotation_item: c, level: 1, index: iindx %>
|
|
122
|
+
<% iindx += 1 %>
|
|
123
|
+
<%= render_item_tree_table(c, 1, iindx).join.html_safe %>
|
|
124
|
+
<% end %>
|
|
125
|
+
|
|
126
|
+
<% end %>
|
|
127
|
+
|
|
128
|
+
<% end %>
|
|
129
|
+
|
|
130
|
+
<tr style="background-color: #acf8ff">
|
|
131
|
+
<td></td>
|
|
132
|
+
<td></td>
|
|
133
|
+
<td></td>
|
|
134
|
+
<th>Grand Total</th>
|
|
135
|
+
<th class="text-end"><%= currency(@quotation.total) %></th>
|
|
136
|
+
<th class="text-end"><%= currency(@quotation.total_discount) %></th>
|
|
137
|
+
<td>(<%= @quotation.total_discount.percent_of(@quotation.total, 1) %>%)</td>
|
|
138
|
+
<th class="text-end"><%= currency(@quotation.total_after_discount) %></th>
|
|
139
|
+
<th class="text-end"><%= currency(@quotation.total_tax) %></th>
|
|
140
|
+
<th></th>
|
|
141
|
+
<th class="text-end"><%= currency(@quotation.total_with_tax) %></th>
|
|
142
|
+
<td></td>
|
|
143
|
+
</tr>
|
|
144
|
+
|
|
145
|
+
</table>
|
|
146
|
+
|
|
147
|
+
<%= link_to 'New Open Item', new_quotation_quotation_item_path(@quotation), class: "btn btn-primary" %>
|
|
148
|
+
<%= link_to 'New Product Item', new_product_item_quotation_path(@quotation), class: "btn btn-primary" %>
|
|
149
|
+
<%#= link_to 'New Group', new_quotation_quotation_item_group_path(@quotation), class: "btn btn-primary" %>
|
|
150
|
+
|
|
151
|
+
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Smerp::Quotation::Engine::Engine.routes.draw do
|
|
2
|
+
resources :quotation_product_categories
|
|
3
|
+
resources :quotation_products
|
|
4
|
+
|
|
5
|
+
resources :quotations do
|
|
6
|
+
resources :quotation_item_groups do
|
|
7
|
+
resources :quotation_items
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
resources :quotation_items
|
|
11
|
+
|
|
12
|
+
# quotation member
|
|
13
|
+
member do
|
|
14
|
+
get :extended_calculators
|
|
15
|
+
|
|
16
|
+
get :new_extended_calculator
|
|
17
|
+
post :create_calculator
|
|
18
|
+
|
|
19
|
+
get :edit_extended_calculator
|
|
20
|
+
post :update_calculator
|
|
21
|
+
|
|
22
|
+
delete :delete_extended_calculator
|
|
23
|
+
|
|
24
|
+
get :new_product_item
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end # quotations
|
|
29
|
+
|
|
30
|
+
resources :quotation_items do
|
|
31
|
+
member do
|
|
32
|
+
post :apply_discount
|
|
33
|
+
post :apply_tax
|
|
34
|
+
post :remove_tax
|
|
35
|
+
|
|
36
|
+
get :add_sub_item
|
|
37
|
+
post :create_sub_item
|
|
38
|
+
|
|
39
|
+
get :new_product_item
|
|
40
|
+
post :create_product_product_item
|
|
41
|
+
|
|
42
|
+
post :hide_children
|
|
43
|
+
post :show_children
|
|
44
|
+
end
|
|
45
|
+
end # quotation_items
|
|
46
|
+
|
|
47
|
+
resources :quotation_item_groups do
|
|
48
|
+
resources :quotation_items
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class CreateSmerpQuotationEngineQuotationProducts < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :smerp_quotation_engine_quotation_products do |t|
|
|
4
|
+
|
|
5
|
+
t.string :qpid
|
|
6
|
+
t.string :name
|
|
7
|
+
t.text :notes
|
|
8
|
+
t.integer :quotation_product_category_id, default: 0
|
|
9
|
+
t.string :state, default: 'active'
|
|
10
|
+
t.string :unit, default: "Unit"
|
|
11
|
+
t.decimal :unit_price, default: 0.0
|
|
12
|
+
|
|
13
|
+
t.timestamps
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateSmerpQuotationEngineQuotationProductCategories < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :smerp_quotation_engine_quotation_product_categories do |t|
|
|
4
|
+
t.string :name
|
|
5
|
+
t.text :notes
|
|
6
|
+
t.string :state, default: "active"
|
|
7
|
+
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
12
|
+
end
|
data/db/seeds.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
Smerp::Quotation::Engine::QuotationProductCategory.create!([
|
|
4
|
+
{
|
|
5
|
+
name: "Resources",
|
|
6
|
+
notes: "Resources in man days",
|
|
7
|
+
state: "active"
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
name: "Services",
|
|
12
|
+
notes: "Standard services such as installation etc.",
|
|
13
|
+
state: "active"
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
name: "Hardware",
|
|
18
|
+
notes: "Hardware products such as servers etc.",
|
|
19
|
+
state: "active"
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
name: "License",
|
|
24
|
+
notes: "License such as software licenses",
|
|
25
|
+
state: "active"
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
name: "Others",
|
|
30
|
+
notes: "Category others than the rest",
|
|
31
|
+
state: "active"
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
])
|
|
36
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
require 'ca/data_store/ar'
|
|
3
|
+
|
|
4
|
+
module Smerp
|
|
5
|
+
module Quotation
|
|
6
|
+
module Engine
|
|
7
|
+
class Engine < ::Rails::Engine
|
|
8
|
+
isolate_namespace Smerp::Quotation::Engine
|
|
9
|
+
|
|
10
|
+
puts "root : #{Rails.root}"
|
|
11
|
+
Ca::DataStore::Ar.root = Rails.root
|
|
12
|
+
|
|
13
|
+
initializer :append_migrations do |app|
|
|
14
|
+
unless app.root.to_s.match root.to_s
|
|
15
|
+
|
|
16
|
+
#p app.config.paths.keys
|
|
17
|
+
|
|
18
|
+
puts "appending migration : #{Smerp::Quotation.migration_path}"
|
|
19
|
+
app.config.paths["db/migrate"].unshift(Smerp::Quotation.migration_path) #<< Smerp::Quotation.migration_path
|
|
20
|
+
|
|
21
|
+
puts "Appending engine migration : #{File.join(File.dirname(__FILE__),"..","..","..","db","migrate")}"
|
|
22
|
+
app.config.paths["db/migrate"] << File.join(File.dirname(__FILE__),"..","..","..","..","db","migrate")
|
|
23
|
+
|
|
24
|
+
app.config.paths["db/seeds.rb"] << File.join(File.dirname(__FILE__),"..","..","..","..","db","seeds.rb")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
#config.paths["db/migrate"].expanded.each do |expanded_path|
|
|
28
|
+
# app.config.paths["db/migrate"] << expanded_path
|
|
29
|
+
#end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
initializer "smerp_quotation_engine.assets.precompile" do |app|
|
|
34
|
+
app.config.assets.precompile << "smerp_quotation_engine_manifest.js"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|