Merge branch 'master' into hooks

This commit is contained in:
2023-12-30 23:40:08 -05:00
8 changed files with 157 additions and 126 deletions

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -20,10 +20,13 @@ class InvoiceController < ApplicationController
#
def show
begin
base = Invoice.get_base
invoice = base.fetch_by_id(params[:id])
@pdf = base.pdf(invoice)
send_data @pdf, filename: "invoice #{invoice.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
qbo = Qbo.first
qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
invoice = service.fetch_by_id(params[:id])
@pdf = service.pdf(invoice)
send_data @pdf, filename: "invoice #{invoice.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
end
rescue
redirect_to :back, :flash => { :error => "Invoice not found" }
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -142,17 +142,14 @@ class Customer < ActiveRecord::Base
# proforms a bruteforce sync operation
# This needs to be simplified
def self.sync
service = Qbo.get_base(:customer)
# Sync ALL customers if the database is empty
#if count == 0
customers = service.all
#else
# last = Qbo.first.last_sync
# query = "Select Id, DisplayName From Customer"
# query << " Where Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
# customers = service.query(query)
#end
qbo = Qbo.first
customers = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
service.all
end
return unless customers
customers.each do |c|
logger.info "Processing customer #{c.id}"
@@ -180,9 +177,14 @@ class Customer < ActiveRecord::Base
# proforms a bruteforce sync operation
# This needs to be simplified
def self.sync_by_id(id)
service = Qbo.get_base(:customer)
qbo = Qbo.first
customer = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
service.fetch_by_id(id)
end
return unless customer
customer = service.fetch_by_id(id)
customer = Customer.find_or_create_by(id: customer.id)
if customer.active?
if not customer.name.eql? customer.display_name
@@ -200,7 +202,11 @@ class Customer < ActiveRecord::Base
# Push the updates
def save_with_push
begin
@details = Qbo.get_base(:customer).update(@details)
qbo = Qbo.first
@details = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
serivce.update(@details)
end
#raise "QBO Fault" if @details.fault?
self.id = @details.id
rescue Exception => e
@@ -218,7 +224,11 @@ class Customer < ActiveRecord::Base
def pull
begin
raise Exception unless self.id
@details = Qbo.get_base(:customer).fetch_by_id(self.id)
qbo = Qbo.first
@details = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
service.fetch_by_id(self.id)
end
rescue Exception => e
@details = Quickbooks::Model::Customer.new
end

View File

@@ -13,12 +13,14 @@ class Employee < ActiveRecord::Base
has_many :users
validates_presence_of :id, :name
def self.get_base
Qbo.get_base(:employee)
end
def self.sync
employees = get_base.all
qbo = Qbo.first
employees = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Employee.new(:company_id => qbo.realm_id, :access_token => access_token)
service.all
end
return unless employees
transaction do
# Update the item table
@@ -33,7 +35,13 @@ class Employee < ActiveRecord::Base
end
def self.sync_by_id(id)
employee = get_base.fetch_by_id(id)
qbo = Qbo.first
employee = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Employee.new(:company_id => qbo.realm_id, :access_token => access_token)
service.fetch_by_id(id)
end
return unless employee
employee = find_or_create_by(id: employee.id)
employee.name = employee.display_name
employee.id = employee.id

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -16,15 +16,17 @@ class Estimate < ActiveRecord::Base
validates_presence_of :doc_number, :id
self.primary_key = :id
# return the QBO Estimate service
def self.get_base
Qbo.get_base(:estimate)
end
# sync all estimates
def self.sync
logger.debug "Syncing ALL estimates"
estimates = get_base.all
qbo = Qbo.first
estimates = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
service.all
end
return unless estimates
estimates.each { |estimate|
process_estimate(estimate)
}
@@ -36,17 +38,28 @@ class Estimate < ActiveRecord::Base
# sync only one estimate
def self.sync_by_id(id)
logger.debug "Syncing estimate #{id}"
process_estimate(get_base.fetch_by_id(id))
qbo = Qbo.first
qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
process_estimate(service.fetch_by_id(id))
end
end
# update an estimate
def self.update(id)
# Update the item table
estimate = get_base.fetch_by_id(id)
estimate = find_or_create_by(id: id)
estimate.doc_number = estimate.doc_number
estimate.txn_date = estimate.txn_date
estimate.save!
qbo = Qbo.first
estimate = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
service.fetch_by_id(id)
end
return unless estimate
e = find_or_create_by(id: id)
e.doc_number = estimate.doc_number
e.txn_date = estimate.txn_date
e.save!
end
# process an estimate into the database
@@ -62,9 +75,12 @@ class Estimate < ActiveRecord::Base
# download the pdf from quickbooks
def pdf
base = Estimate.get_base
estimate = base.fetch_by_id(id)
return base.pdf(estimate)
qbo = Qbo.first
qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
estimate = service.fetch_by_id(id)
service.pdf(estimate)
end
end
# Magic Method
@@ -91,7 +107,11 @@ class Estimate < ActiveRecord::Base
def pull
begin
raise Exception unless self.id
@details = Qbo.get_base(:estimate).fetch_by_id(self.id)
qbo = Qbo.first
@details = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
service(:estimate).fetch_by_id(self.id)
end
rescue Exception => e
@details = Quickbooks::Model::Estimate.new
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -15,11 +15,6 @@ class Invoice < ActiveRecord::Base
validates_presence_of :doc_number, :id, :customer_id, :txn_date
self.primary_key = :id
# Get the quickbooks-ruby base for invoice
def self.get_base
Qbo.get_base(:invoice)
end
# sync ALL the invoices
def self.sync
logger.debug "Syncing all invoices"
@@ -30,11 +25,13 @@ class Invoice < ActiveRecord::Base
# TODO actually do something with the above query
# .all() is never called since count is never initialized
if count == 0
invoices = get_base.all
else
invoices = get_base.query()
qbo = Qbo.first
invoices = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
service.all
end
return unless invoices
invoices.each { | invoice |
process_invoice invoice
@@ -44,8 +41,12 @@ class Invoice < ActiveRecord::Base
#sync by invoice ID
def self.sync_by_id(id)
logger.debug "Syncing invoice #{id}"
invoice = get_base.fetch_by_id(id)
process_invoice invoice
qbo = Qbo.first
qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
invoice = service.fetch_by_id(id)
process_invoice invoice
end
end
private
@@ -140,7 +141,11 @@ class Invoice < ActiveRecord::Base
# Push updates
begin
logger.debug "Trying to update invoice"
get_base.update(invoice) if is_changed
qbo = Qbo.first
qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
service.update(invoice) if is_changed
end
rescue
# Do nothing, probaly custome field sync confict on the invoice.
# This is a problem with how it's billed
@@ -172,7 +177,11 @@ class Invoice < ActiveRecord::Base
def pull
begin
raise Exception unless self.id
@details = Qbo.get_base(:invoice).fetch_by_id(self.id)
qbo = Qbo.first
@details = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
service.fetch_by_id(self.id)
end
rescue Exception => e
@details = Quickbooks::Model::Invoice.new
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -12,34 +12,6 @@ class Qbo < ActiveRecord::Base
unloadable
include QuickbooksOauth
#
# Get a quickbooks base service object for type
# @params type of base
#
def self.get_base(type)
qbo = self.first
qbo.perform_authenticated_request do |access_token|
# build the reqiested service
case type
when :time_activity
return Quickbooks::Service::TimeActivity.new(:company_id => qbo.realm_id, :access_token => access_token)
when :customer
return Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
when :invoice
return Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
when :estimate
return Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
when :employee
return Quickbooks::Service::Employee.new(:company_id => qbo.realm_id, :access_token => access_token)
when :item
return Quickbooks::Service::Item.new(:company_id => qbo.realm_id, :access_token => access_token)
else
return nil
end
end
end
# Updates last sync time stamp
def self.update_time_stamp

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -26,7 +26,13 @@ class AddTxnDates < ActiveRecord::Migration[5.1]
say "Sync Invoices"
invoices = QboInvoice.get_base.all
qbo = Qbo.first
invoices = qbo.perform_authenticated_request do |access_token|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
service.all
end
return unless invoices
invoices.each { |invoice|
# Load the invoice into the database

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 rick barrette
#Copyright (c) 2023 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
@@ -52,46 +52,49 @@ module IssuePatch
if spent_hours > 0 then
# Prepare to create a new Time Activity
time_service = Qbo.get_base(:time_activity)
item_service = Qbo.get_base(:item)
time_entry = Quickbooks::Model::TimeActivity.new
qbo = Qbo.first
qbo.perform_authenticated_request do |access_token|
time_service = Quickbooks::Service::TimeActivity.new(:company_id => qbo.realm_id, :access_token => access_token)
item_service = Quickbooks::Service::Item.new(:company_id => qbo.realm_id, :access_token => access_token)
time_entry = Quickbooks::Model::TimeActivity.new
# Lets total up each activity before billing.
# This will simpify the invoicing with a single billable time entry per time activity
h = Hash.new(0)
spent_time.each do |entry|
h[entry.activity.name] += entry.hours
# update time entries billed status
entry.billed = true
entry.save
end
# Now letes upload our totals for each activity as their own billable time entry
h.each do |key, val|
# Lets total up each activity before billing.
# This will simpify the invoicing with a single billable time entry per time activity
h = Hash.new(0)
spent_time.each do |entry|
h[entry.activity.name] += entry.hours
# update time entries billed status
entry.billed = true
entry.save
end
# Convert float spent time to hours and minutes
hours = val.to_i
minutesDecimal = (( val - hours) * 60)
minutes = minutesDecimal.to_i
# Now letes upload our totals for each activity as their own billable time entry
h.each do |key, val|
# Convert float spent time to hours and minutes
hours = val.to_i
minutesDecimal = (( val - hours) * 60)
minutes = minutesDecimal.to_i
# Lets match the activity to an qbo item
item = item_service.query("SELECT * FROM Item WHERE Name = '#{key}' ").first
next if item.nil?
# Create the new billable time entry and upload it
time_entry.description = "#{tracker} ##{id}: #{subject} #{"(Partial @ #{done_ratio}%)" if not closed?}"
time_entry.employee_id = assigned_to.employee_id
time_entry.customer_id = customer_id
time_entry.billable_status = "Billable"
time_entry.hours = hours
time_entry.minutes = minutes
time_entry.name_of = "Employee"
time_entry.txn_date = Date.today
time_entry.hourly_rate = item.unit_price
time_entry.item_id = item.id
time_entry.start_time = start_date
time_entry.end_time = Time.now
time_service.create(time_entry)
# Lets match the activity to an qbo item
item = item_service.query("SELECT * FROM Item WHERE Name = '#{key}' ").first
next if item.nil?
# Create the new billable time entry and upload it
time_entry.description = "#{tracker} ##{id}: #{subject} #{"(Partial @ #{done_ratio}%)" if not closed?}"
time_entry.employee_id = assigned_to.employee_id
time_entry.customer_id = customer_id
time_entry.billable_status = "Billable"
time_entry.hours = hours
time_entry.minutes = minutes
time_entry.name_of = "Employee"
time_entry.txn_date = Date.today
time_entry.hourly_rate = item.unit_price
time_entry.item_id = item.id
time_entry.start_time = start_date
time_entry.end_time = Time.now
time_service.create(time_entry)
end
end
end
end