mirror of
https://github.com/rickbarrette/redmine_qbo_calendar.git
synced 2026-10-03 20:40:43 -04:00
Add method to create issues from labor lines in QBO estimates
This commit is contained in:
1 parent
11bc1f1d57
commit
45fcdeebd7
1 file changed
+78
-1
@@ -28,6 +28,65 @@ class CustomerAppointment < ActiveRecord::Base
|
||||
Cancelled
|
||||
]
|
||||
|
||||
# Scans the QBO Estimate's InvoiceLineItems for "Labor" sales items
|
||||
# and generates a Redmine Issue for each matching line.
|
||||
#
|
||||
# @param project [Project] Target project (defaults to appointment's project)
|
||||
# @param author [User] Author for the new issues
|
||||
# @param tracker [Tracker] Target tracker (defaults to project's first tracker)
|
||||
# @return [Array<Issue>] Created issues
|
||||
def create_issues_from_labor_lines(project: self.project, author: User.current, tracker: nil)
|
||||
return [] if estimate.blank?
|
||||
|
||||
target_project = project || self.project || Project.first
|
||||
target_tracker = tracker || target_project&.trackers&.first
|
||||
return [] unless target_project && target_tracker
|
||||
|
||||
created_issues = []
|
||||
|
||||
# estimate.line_items returns array of Quickbooks::Model::InvoiceLineItem
|
||||
estimate.line_items.each do |line|
|
||||
detail = line.respond_to?(:sales_line_item_detail) ? line.sales_line_item_detail : nil
|
||||
next if detail.nil? || detail.item_ref.nil?
|
||||
|
||||
item_name = detail.item_ref.name.to_s.strip
|
||||
description = line.description.to_s.strip
|
||||
|
||||
# Match "Labor" (case-insensitive) and ensure description is present
|
||||
next unless item_name.casecmp('Labor').zero?
|
||||
next if description.blank?
|
||||
|
||||
# detail.quantity contains line quantity/hours; line.amount is total line cost fallback
|
||||
qty = detail.respond_to?(:quantity) ? detail.quantity.to_f : 0.0
|
||||
hours = qty.positive? ? qty : line.amount.to_f
|
||||
|
||||
issue = Issue.new(
|
||||
project: target_project,
|
||||
tracker: target_tracker,
|
||||
assigned_to_id: self.user&.id,
|
||||
author: author,
|
||||
subject: description.truncate(255),
|
||||
description: "The purpose of this work is to bill the time spent on this issue for Estimate ##{estimate.doc_number} for Appointment: #{subject}",
|
||||
estimated_hours: hours,
|
||||
start_date: self.start_date,
|
||||
due_date: self.due_date,
|
||||
vehicle: self.vehicle,
|
||||
estimate: self.estimate,
|
||||
customer: self.customer,
|
||||
created_on: Time.current,
|
||||
updated_on: Time.current
|
||||
)
|
||||
|
||||
if issue.save
|
||||
created_issues << issue
|
||||
else
|
||||
log "Failed to create issue for Estimate ##{estimate.id}: #{issue.errors.full_messages.join(', ')}"
|
||||
end
|
||||
end
|
||||
|
||||
created_issues
|
||||
end
|
||||
|
||||
# Cast datetime to Date for Redmine Calendar compatibility
|
||||
def start_date
|
||||
date&.to_date
|
||||
@@ -50,7 +109,25 @@ class CustomerAppointment < ActiveRecord::Base
|
||||
private
|
||||
|
||||
def log(msg)
|
||||
Rails.logger.info "[Event] #{msg}"
|
||||
Rails.logger.info "[CustomerAppointment] #{msg}"
|
||||
end
|
||||
|
||||
# Helper to parse item name across Quickbooks::Model::Line and Hash structures
|
||||
def extract_item_name(line)
|
||||
if line.respond_to?(:sales_line_item_detail) && line.sales_line_item_detail.present?
|
||||
line.sales_line_item_detail.item_ref&.name
|
||||
elsif line.is_a?(Hash)
|
||||
line[:item_name] || line.dig('sales_line_item_detail', 'item_ref', 'name')
|
||||
end
|
||||
end
|
||||
|
||||
# Helper to parse description across Quickbooks::Model::Line and Hash structures
|
||||
def extract_description(line)
|
||||
if line.respond_to?(:description)
|
||||
line.description
|
||||
elsif line.is_a?(Hash)
|
||||
line[:description] || line['description']
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Reference in new issue
Block a user