mirror of
https://github.com/rickbarrette/redmine_qbo.git
synced 2026-04-04 09:11:58 -04:00
Compare commits
9 Commits
9f9810686f
...
2026.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
| c4c02f8d27 | |||
| 00b1baa1f3 | |||
| 2520892e2c | |||
| b96678a2e9 | |||
| bccfcd9dbc | |||
| 8ba99b7db2 | |||
| aff7d0c48e | |||
| e9b3b1c838 | |||
| 2fc2f94cd1 |
@@ -80,16 +80,31 @@ class CustomersController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
@customer = Customer.find_by_id(params[:id])
|
@customer = Customer.find_by_id(params[:id])
|
||||||
return render_404 unless @customer
|
return render_404 unless @customer
|
||||||
@issues = @customer.issues&.order(id: :desc)
|
|
||||||
@billing_address = address_to_s(@customer.billing_address)
|
@open_issues = @customer.issues
|
||||||
@shipping_address = address_to_s(@customer.shipping_address)
|
.joins(:status)
|
||||||
@closed_issues = (@issues - @issues.open)
|
.includes(:status, :project, :tracker, :priority)
|
||||||
@hours = 0
|
.where(issue_statuses: { is_closed: false })
|
||||||
@closed_hours = 0
|
.order(id: :desc)
|
||||||
@issues.open.each { |i| @hours+= i.total_spent_hours }
|
|
||||||
@closed_issues.each { |i| @closed_hours+= i.total_spent_hours }
|
@closed_issues = @customer.issues
|
||||||
|
.joins(:status)
|
||||||
|
.includes(:status, :project, :tracker, :priority)
|
||||||
|
.where(issue_statuses: { is_closed: true })
|
||||||
|
.order(id: :desc)
|
||||||
|
|
||||||
|
@hours = TimeEntry
|
||||||
|
.joins(:issue)
|
||||||
|
.where(issues: { id: @open_issues.select(:id) })
|
||||||
|
.sum(:hours)
|
||||||
|
|
||||||
|
@closed_hours = TimeEntry
|
||||||
|
.joins(:issue)
|
||||||
|
.where(issues: { id: @closed_issues.select(:id) })
|
||||||
|
.sum(:hours)
|
||||||
|
|
||||||
rescue => e
|
rescue => e
|
||||||
log "Failed to load customer ##{params[:id]}: #{e.message}"
|
Rails.logger.error "Failed to load customer ##{params[:id]}: #{e.message}\n#{e.backtrace.join("\n")}"
|
||||||
flash[:error] = e.message
|
flash[:error] = e.message
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,7 +35,20 @@ class Customer < ActiveRecord::Base
|
|||||||
|
|
||||||
# Returns the details of the customer. If the details have already been fetched, it returns the cached version. Otherwise, it fetches the details from QuickBooks Online and caches them for future use. This method is used to access the customer's information in a way that minimizes unnecessary API calls to QBO, improving performance and reducing latency.
|
# Returns the details of the customer. If the details have already been fetched, it returns the cached version. Otherwise, it fetches the details from QuickBooks Online and caches them for future use. This method is used to access the customer's information in a way that minimizes unnecessary API calls to QBO, improving performance and reducing latency.
|
||||||
def details
|
def details
|
||||||
@details ||= fetch_details
|
return (@details ||= Quickbooks::Model::Customer.new) if new_record?
|
||||||
|
|
||||||
|
@details ||= begin
|
||||||
|
xml = Rails.cache.fetch(details_cache_key, expires_in: 10.minutes) do
|
||||||
|
fetch_details.to_xml_ns
|
||||||
|
end
|
||||||
|
|
||||||
|
Quickbooks::Model::Customer.from_xml(xml)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates a unique cache key for storing this customer's QBO details.
|
||||||
|
def details_cache_key
|
||||||
|
"customer:#{id}:qbo_details:#{updated_at.to_i}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the customer's email address
|
# Returns the customer's email address
|
||||||
@@ -50,6 +63,7 @@ class Customer < ActiveRecord::Base
|
|||||||
@details.email_address = s
|
@details.email_address = s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Returns the last sync time formatted for display. If no sync has occurred, returns a default message.
|
# Returns the last sync time formatted for display. If no sync has occurred, returns a default message.
|
||||||
def self.last_sync
|
def self.last_sync
|
||||||
return I18n.t(:label_qbo_never_synced) unless maximum(:updated_at)
|
return I18n.t(:label_qbo_never_synced) unless maximum(:updated_at)
|
||||||
@@ -167,6 +181,7 @@ class Customer < ActiveRecord::Base
|
|||||||
log "Starting push for customer ##{self.id}..."
|
log "Starting push for customer ##{self.id}..."
|
||||||
qbo = QboConnectionService.current!
|
qbo = QboConnectionService.current!
|
||||||
CustomerService.new(qbo: qbo, customer: self).push()
|
CustomerService.new(qbo: qbo, customer: self).push()
|
||||||
|
Rails.cache.delete(details_cache_key)
|
||||||
save_without_push
|
save_without_push
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<h3><%=@issues.open.count%> <%=t(:label_open_issues)%> - <%=@hours.round(1)%> <%=t(:label_hours)%></h3>
|
<h3><%=@open_issues.count%> <%=t(:label_open_issues)%> - <%=@hours.round(1)%> <%=t(:label_hours)%></h3>
|
||||||
<%= render partial: 'issues/list_simple', locals: {issues: @issues.open} %>
|
<%= render partial: 'issues/list_simple', locals: {issues: @open_issues.open} %>
|
||||||
|
|
||||||
<h3><%=@closed_issues.count%> <%=t(:label_closed_issues)%> - <%= @closed_hours.round(1)%> <%=t(:label_hours)%></h3>
|
<h3><%=@closed_issues.count%> <%=t(:label_closed_issues)%> - <%= @closed_hours.round(1)%> <%=t(:label_hours)%></h3>
|
||||||
<%= render partial: 'issues/list_simple', locals: {issues: @closed_issues} %>
|
<%= render partial: 'issues/list_simple', locals: {issues: @closed_issues} %>
|
||||||
|
|||||||
2
init.rb
2
init.rb
@@ -14,7 +14,7 @@ Redmine::Plugin.register :redmine_qbo do
|
|||||||
name 'Redmine QBO plugin'
|
name 'Redmine QBO plugin'
|
||||||
author 'Rick Barrette'
|
author 'Rick Barrette'
|
||||||
description 'A pluging for Redmine to connect with QuickBooks Online to create Time Activity Entries for billable hours logged when an Issue is closed'
|
description 'A pluging for Redmine to connect with QuickBooks Online to create Time Activity Entries for billable hours logged when an Issue is closed'
|
||||||
version '2026.3.0'
|
version '2026.3.2'
|
||||||
url 'https://github.com/rickbarrette/redmine_qbo'
|
url 'https://github.com/rickbarrette/redmine_qbo'
|
||||||
author_url 'https://barrettefabrication.com'
|
author_url 'https://barrettefabrication.com'
|
||||||
settings default: {empty: true}, partial: 'qbo/settings'
|
settings default: {empty: true}, partial: 'qbo/settings'
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ module RedmineQbo
|
|||||||
f = context[:form]
|
f = context[:form]
|
||||||
issue = context[:issue]
|
issue = context[:issue]
|
||||||
project = context[:project]
|
project = context[:project]
|
||||||
log issue.inspect
|
|
||||||
log project.inspect
|
|
||||||
|
|
||||||
# Customer Name Text Box with database backed autocomplete
|
# Customer Name Text Box with database backed autocomplete
|
||||||
# onchange event will update the hidden customer_id field
|
# onchange event will update the hidden customer_id field
|
||||||
|
|||||||
@@ -260,8 +260,9 @@ module RedmineQbo
|
|||||||
|
|
||||||
# Check to see if there is an estimate attached, then combine them
|
# Check to see if there is an estimate attached, then combine them
|
||||||
if issue.estimate
|
if issue.estimate
|
||||||
|
e_pdf, ref = EstimatePdfService.new(qbo: QboConnectionService.current!).fetch_pdf(doc_ids: [issue.estimate.id])
|
||||||
pdf = CombinePDF.parse(pdf.output, allow_optional_content: true)
|
pdf = CombinePDF.parse(pdf.output, allow_optional_content: true)
|
||||||
pdf << CombinePDF.parse(issue.estimate.pdf)
|
pdf << CombinePDF.parse(e_pdf)
|
||||||
return pdf.to_pdf
|
return pdf.to_pdf
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user