mirror of
https://github.com/rickbarrette/redmine_qbo_lineitems.git
synced 2026-10-04 01:20:43 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0d6b08a3d | ||
|
|
9a9efcbaf9 | ||
|
|
0acf5ffca4 | ||
|
|
5b1d98aa07 | ||
|
|
3ca45a457f | ||
|
|
c9d2a47a92 |
No files matched your search
@@ -45,11 +45,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button type="button"
|
|
||||||
class="icon icon-add"
|
<% if User.current.allowed_to?(:add_line_items, nil, global: true) %>
|
||||||
data-nested-form-add>
|
<button type="button"
|
||||||
<%= l(:button_add) %>
|
class="icon icon-add"
|
||||||
</button>
|
data-nested-form-add>
|
||||||
|
<%= l(:button_add) %>
|
||||||
|
</button>
|
||||||
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,57 @@
|
|||||||
<% if @issue.line_items.any? %>
|
<% if @issue.line_items.any? || @issue.descendant_line_items_total > 0%>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div>
|
<div>
|
||||||
<p><strong><%= t :label_line_items %></strong></p>
|
<p><strong><%= t :label_line_items %></strong></p>
|
||||||
|
|
||||||
<table class="list line-items-table">
|
<% total = 0 %>
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:70%;"><%= t :label_description %></th>
|
|
||||||
<th style="width:10%;"><%= t :label_qty %></th>
|
|
||||||
<th style="width:10%;"><%= t :label_price %></th>
|
|
||||||
<th style="width:10%;"><%= t :label_total %></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
<% if @issue.line_items.any?%>
|
||||||
<% total = 0 %>
|
|
||||||
|
|
||||||
<% @issue.line_items.each do |item| %>
|
|
||||||
<% line_total = item.quantity.to_f * item.unit_price.to_f %>
|
|
||||||
<% total += line_total %>
|
|
||||||
|
|
||||||
|
<table class="list line-items-table">
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= h item.description %></td>
|
<th style="width:70%;"><%= t :label_description %></th>
|
||||||
<td><%= item.quantity %></td>
|
<th style="width:10%;"><%= t :label_qty %></th>
|
||||||
<td><%= number_to_currency(item.unit_price) %></td>
|
<th style="width:10%;"><%= t :label_price %></th>
|
||||||
<td><%= number_to_currency(line_total) %></td>
|
<th style="width:10%;"><%= t :label_total %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<% @issue.line_items.each do |item| %>
|
||||||
|
<% line_total = item.quantity.to_f * item.unit_price.to_f %>
|
||||||
|
<% total += line_total %>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><%= h item.description %></td>
|
||||||
|
<td><%= item.quantity %></td>
|
||||||
|
<td><%= number_to_currency(item.unit_price) %></td>
|
||||||
|
<td><%= number_to_currency(line_total) %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<tfoot>
|
||||||
|
<% if @issue.line_items.any?%>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" style="text-align:right;"><strong><%= t :label_total %></strong></td>
|
||||||
|
<td>
|
||||||
|
<strong><%= number_to_currency(total) %></strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if @issue.descendant_line_items_total > 0 %>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" style="text-align:right;"><strong><%= t :label_running_total %></strong></td>
|
||||||
|
<td>
|
||||||
|
<strong>(<%= number_to_currency(@issue.descendant_line_items_total + total) %>)</strong>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
|
||||||
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td colspan="3" style="text-align:right;"><strong><%= t :label_total %></strong></td>
|
|
||||||
<td><strong><%= number_to_currency(total) %></strong></td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,13 +35,15 @@
|
|||||||
0.00
|
0.00
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<% unless readonly %>
|
<% if User.current.allowed_to?(:delete_line_items, nil, global: true) %>
|
||||||
<td class="actions">
|
<% unless readonly %>
|
||||||
<button type="button"
|
<td class="actions">
|
||||||
class="icon-only icon-del"
|
<button type="button"
|
||||||
title="<%= l(:label_remove) %>"
|
class="icon-only icon-del"
|
||||||
data-nested-form-remove>
|
title="<%= l(:label_remove) %>"
|
||||||
</button>
|
data-nested-form-remove>
|
||||||
</td>
|
</button>
|
||||||
|
</td>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -33,6 +33,7 @@ en:
|
|||||||
label_no: "No"
|
label_no: "No"
|
||||||
label_qty: "Quantity"
|
label_qty: "Quantity"
|
||||||
label_remove: "Remove"
|
label_remove: "Remove"
|
||||||
|
label_running_total: "Running Total"
|
||||||
label_sync_now_accounts: "Sync Accounts"
|
label_sync_now_accounts: "Sync Accounts"
|
||||||
label_sync_now_items: "Sync Items"
|
label_sync_now_items: "Sync Items"
|
||||||
label_type: "Type"
|
label_type: "Type"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Redmine::Plugin.register :redmine_qbo_lineitems do
|
|||||||
name 'Redmine QBO Line Items plugin'
|
name 'Redmine QBO Line Items plugin'
|
||||||
author 'Rick Barrette'
|
author 'Rick Barrette'
|
||||||
description 'A plugin for Redmine to extend the capabilitys of the Redmine QuickBooks Online plugin to attach billable line items to an isuue'
|
description 'A plugin for Redmine to extend the capabilitys of the Redmine QuickBooks Online plugin to attach billable line items to an isuue'
|
||||||
version '2026.4.0'
|
version '2026.9.0'
|
||||||
url 'https://github.com/rickbarrette/redmine_qbo_lineitems'
|
url 'https://github.com/rickbarrette/redmine_qbo_lineitems'
|
||||||
author_url 'https://barrettefabrication.com'
|
author_url 'https://barrettefabrication.com'
|
||||||
requires_redmine version_or_higher: '6.1.0'
|
requires_redmine version_or_higher: '6.1.0'
|
||||||
@@ -29,14 +29,12 @@ Redmine::Plugin.register :redmine_qbo_lineitems do
|
|||||||
|
|
||||||
# Add safe attributes for core models
|
# Add safe attributes for core models
|
||||||
Issue.safe_attributes :line_items_attributes
|
Issue.safe_attributes :line_items_attributes
|
||||||
end
|
|
||||||
|
|
||||||
# Administration menu extension
|
# Global Permissions
|
||||||
Redmine::MenuManager.map :admin_menu do |menu|
|
permission :view_line_items, { line_items: [:index, :show] }, global: true
|
||||||
menu.push :redmine_qbo_lineitems, { controller: 'items', action: 'index' },
|
permission :add_line_items, { line_items: [:new, :create] }, global: true
|
||||||
icon: 'list',
|
permission :edit_line_items, { line_items: [:edit, :update] }, global: true
|
||||||
caption: :label_items,
|
permission :delete_line_items, { line_items: [:destroy] }, global: true
|
||||||
html: { class: 'icon icon-list' }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
RedmineQboLineItems.setup
|
RedmineQboLineItems.setup
|
||||||
@@ -24,18 +24,18 @@ module LineItems
|
|||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Add the line items form to the issue edit page
|
||||||
def view_issues_edit_notes_bottom(context = {})
|
def view_issues_edit_notes_bottom(context = {})
|
||||||
return if context[:issue].closed?
|
return if context[:issue].closed?
|
||||||
context[:controller].send(:render_to_string, {
|
return unless User.current.allowed_to?(:edit_line_items, nil, global: true)
|
||||||
partial: 'line_items/issue_form',
|
context[:controller].send(:render_to_string, { partial: 'line_items/issue_form', locals: { f: context[:form] } })
|
||||||
locals: {
|
|
||||||
f: context[:form]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
render_on :view_issues_show_description_bottom , partial: 'line_items/issue_line_items'
|
# Add the line items to the issue view page
|
||||||
|
def view_issues_show_description_bottom (context = {})
|
||||||
|
return unless User.current.allowed_to?(:view_line_items, nil, global: true)
|
||||||
|
context[:controller].send(:render_to_string, { partial: 'line_items/issue_line_items', locals: { issue: context[:issue] } })
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,6 +16,30 @@ module LineItems
|
|||||||
has_many :line_items, dependent: :destroy
|
has_many :line_items, dependent: :destroy
|
||||||
accepts_nested_attributes_for :line_items, allow_destroy: true, reject_if: proc { |attrs| attrs['description'].blank? }
|
accepts_nested_attributes_for :line_items, allow_destroy: true, reject_if: proc { |attrs| attrs['description'].blank? }
|
||||||
|
|
||||||
|
# Returns line items for immediate children
|
||||||
|
def children_line_items
|
||||||
|
LineItem.where(issue_id: self.children.pluck(:id))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Calculates the total value of all child line items
|
||||||
|
def children_line_items_total
|
||||||
|
children_line_items.sum(:line_total)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns line items for the entire tree below this issue
|
||||||
|
def descendant_line_items
|
||||||
|
LineItem.where(issue_id: self.descendants.pluck(:id))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Calculates the total value of entire tree below this issue
|
||||||
|
def descendant_line_items_total
|
||||||
|
descendant_line_items.sum(:line_total)
|
||||||
|
end
|
||||||
|
|
||||||
|
def line_items_total
|
||||||
|
line_items.sum(:line_total)
|
||||||
|
end
|
||||||
|
|
||||||
def line_items_attributes=(attrs)
|
def line_items_attributes=(attrs)
|
||||||
attrs = attrs.stringify_keys
|
attrs = attrs.stringify_keys
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,18 @@ module RedmineQboLineItems
|
|||||||
|
|
||||||
def self.setup
|
def self.setup
|
||||||
unless Issue.ancestors.include?(LineItems::Patches::IssuePatch)
|
unless Issue.ancestors.include?(LineItems::Patches::IssuePatch)
|
||||||
|
# Patches
|
||||||
Issue.prepend LineItems::Patches::IssuePatch
|
Issue.prepend LineItems::Patches::IssuePatch
|
||||||
|
|
||||||
|
# Hooks
|
||||||
LineItems::Hooks::IssuesSaveHookListener
|
LineItems::Hooks::IssuesSaveHookListener
|
||||||
LineItems::Hooks::QboHookListener
|
LineItems::Hooks::QboHookListener
|
||||||
LineItems::Hooks::ViewHookListener
|
LineItems::Hooks::ViewHookListener
|
||||||
|
|
||||||
|
# Administration menu extension
|
||||||
|
Redmine::MenuManager.map :admin_menu do |menu|
|
||||||
|
menu.push :redmine_qbo_lineitems, { controller: 'items', action: 'index' }, icon: 'list', caption: :label_items, html: { class: 'icon icon-list' }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Reference in new issue
Block a user