jasper print speed refactor working

This commit is contained in:
Jason Jordan
2026-03-27 08:04:37 -04:00
parent a43c8bf6b5
commit 9f306d3150
33 changed files with 1015 additions and 168 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ inherit_gem:
rubocop-rails-omakase: rubocop.yml
AllCops:
TargetRubyVersion: 3.3.9
TargetRubyVersion: 3.4.8
TargetRailsVersion: 7.2.2
DisabledByDefault: true
Exclude:
+1 -1
View File
@@ -1 +1 @@
3.3.9
3.4.8
+1 -1
View File
@@ -83,9 +83,9 @@ gem 'devise'
gem 'pundit'
gem "tailwindcss-rails"
gem 'docx'
gem 'rubyzip'
gem 'httparty'
gem 'combine_pdf'
gem 'rails_icons'
gem 'fastimage'
gem 'rubyzip', require: 'zip'
gem "solid_queue"
+88 -103
View File
@@ -56,7 +56,7 @@ GEM
activemodel (= 7.2.3)
activesupport (= 7.2.3)
timeout (>= 0.4.0)
activerecord-sqlserver-adapter (7.2.8)
activerecord-sqlserver-adapter (7.2.9)
activerecord (~> 7.2.0)
tiny_tds
activestorage (7.2.3)
@@ -77,21 +77,21 @@ GEM
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
addressable (2.8.9)
public_suffix (>= 2.0.2, < 8.0)
ast (2.4.3)
base64 (0.3.0)
bcrypt (3.1.20)
bcrypt (3.1.22)
benchmark (0.5.0)
bigdecimal (3.3.1)
bigdecimal (4.0.1)
bindex (0.8.1)
bootsnap (1.18.6)
bootsnap (1.23.0)
msgpack (~> 1.2)
brakeman (7.1.1)
brakeman (8.0.4)
racc
builder (3.3.0)
bundler-audit (0.9.2)
bundler (>= 1.2.0, < 3)
bundler-audit (0.9.3)
bundler (>= 1.2.0)
thor (~> 1.0)
capybara (3.40.0)
addressable
@@ -102,20 +102,20 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
cgi (0.5.0)
cgi (0.5.1)
coderay (1.1.3)
combine_pdf (1.0.31)
matrix
ruby-rc4 (>= 0.1.5)
concurrent-ruby (1.3.5)
connection_pool (2.5.4)
concurrent-ruby (1.3.6)
connection_pool (3.0.2)
crass (1.0.6)
csv (3.3.5)
date (3.5.0)
devise (4.9.4)
date (3.5.1)
devise (5.0.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
railties (>= 7.0)
responders
warden (~> 1.2.3)
diff-lcs (1.6.2)
@@ -123,34 +123,42 @@ GEM
nokogiri (~> 1.13, >= 1.13.0)
rubyzip (>= 2.0, < 4)
drb (2.2.3)
erb (5.1.3)
erb (6.0.2)
erubi (1.13.1)
fastimage (2.4.0)
et-orbi (1.4.0)
tzinfo
fastimage (2.4.1)
fugit (1.12.1)
et-orbi (~> 1.4)
raabro (~> 1.4)
globalid (1.3.0)
activesupport (>= 6.1)
httparty (0.23.2)
httparty (0.24.2)
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.14.7)
i18n (1.14.8)
concurrent-ruby (~> 1.0)
importmap-rails (2.2.2)
icons (0.8.1)
nokogiri (~> 1.16, >= 1.16.4)
importmap-rails (2.2.3)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
io-console (0.8.1)
irb (1.15.3)
io-console (0.8.2)
irb (1.17.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jbuilder (2.14.1)
actionview (>= 7.0.0)
activesupport (>= 7.0.0)
json (2.15.2)
json (2.19.2)
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
logger (1.7.0)
loofah (2.24.1)
loofah (2.25.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.9.0)
@@ -163,11 +171,13 @@ GEM
matrix (0.4.3)
method_source (1.1.0)
mini_mime (1.1.5)
minitest (5.26.0)
minitest (6.0.2)
drb (~> 2.0)
prism (~> 1.5)
msgpack (1.8.0)
multi_xml (0.7.2)
bigdecimal (~> 3.1)
net-imap (0.5.12)
multi_xml (0.8.1)
bigdecimal (>= 3.1, < 5)
net-imap (0.6.3)
date
net-protocol
net-pop (0.1.2)
@@ -177,46 +187,34 @@ GEM
net-smtp (0.5.1)
net-protocol
nio4r (2.7.5)
nokogiri (1.18.10-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.10-aarch64-linux-musl)
racc (~> 1.4)
nokogiri (1.18.10-arm-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.10-arm-linux-musl)
racc (~> 1.4)
nokogiri (1.18.10-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.10-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-musl)
nokogiri (1.19.2-x86_64-linux-gnu)
racc (~> 1.4)
orm_adapter (0.5.0)
parallel (1.27.0)
parser (3.3.10.0)
parser (3.3.10.2)
ast (~> 2.4.1)
racc
pp (0.6.3)
prettyprint
prettyprint (0.2.0)
prism (1.6.0)
pry (0.15.2)
prism (1.9.0)
pry (0.16.0)
coderay (~> 1.1)
method_source (~> 1.0)
reline (>= 0.6.0)
pry-rails (0.3.11)
pry (>= 0.13.0)
psych (5.2.6)
psych (5.3.1)
date
stringio
public_suffix (6.0.2)
public_suffix (7.0.5)
puma (6.6.1)
nio4r (~> 2.0)
pundit (2.5.2)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
rack (3.2.4)
rack (3.2.5)
rack-mini-profiler (4.0.1)
rack (>= 1.2.0)
rack-session (2.1.1)
@@ -224,7 +222,7 @@ GEM
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.1)
rackup (2.3.1)
rack (>= 3)
rails (7.2.3)
actioncable (= 7.2.3)
@@ -244,11 +242,11 @@ GEM
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
rails-html-sanitizer (1.7.0)
loofah (~> 2.25)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails_icons (1.5.1)
nokogiri (~> 1.16, >= 1.16.4)
rails_icons (1.7.1)
icons (~> 0.8.1)
rails (>= 7.0)
railties (7.2.3)
actionpack (= 7.2.3)
@@ -262,12 +260,12 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.3.1)
rdoc (6.15.1)
rdoc (7.2.0)
erb
psych (>= 4.0.0)
tsort
regexp_parser (2.11.3)
reline (0.6.2)
reline (0.6.3)
io-console (~> 0.5)
responders (3.2.0)
actionpack (>= 7.0)
@@ -278,19 +276,19 @@ GEM
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.7)
rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (8.0.2)
rspec-rails (8.0.4)
actionpack (>= 7.2)
activesupport (>= 7.2)
railties (>= 7.2)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.6)
rubocop (1.81.7)
rspec-core (>= 3.13.0, < 5.0.0)
rspec-expectations (>= 3.13.0, < 5.0.0)
rspec-mocks (>= 3.13.0, < 5.0.0)
rspec-support (>= 3.13.0, < 5.0.0)
rspec-support (3.13.7)
rubocop (1.86.0)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@@ -298,17 +296,17 @@ GEM
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.47.1, < 2.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.47.1)
rubocop-ast (1.49.1)
parser (>= 3.3.7.2)
prism (~> 1.4)
prism (~> 1.7)
rubocop-performance (1.26.1)
lint_roller (~> 1.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.47.1, < 2.0)
rubocop-rails (2.33.4)
rubocop-rails (2.34.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
@@ -318,19 +316,26 @@ GEM
rubocop (>= 1.72)
rubocop-performance (>= 1.24)
rubocop-rails (>= 2.30)
rubocop-rspec (3.7.0)
rubocop-rspec (3.9.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop (~> 1.81)
ruby-progressbar (1.13.0)
ruby-rc4 (0.1.5)
rubyzip (3.2.2)
securerandom (0.4.1)
selenium-webdriver (4.38.0)
selenium-webdriver (4.41.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 4.0)
websocket (~> 1.0)
solid_queue (1.4.0)
activejob (>= 7.1)
activerecord (>= 7.1)
concurrent-ruby (>= 1.3.1)
fugit (~> 1.11)
railties (>= 7.1)
thor (>= 1.3.1)
sprockets (4.2.2)
concurrent-ruby (~> 1.0)
logger
@@ -341,38 +346,24 @@ GEM
sprockets (>= 3.0.0)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.7)
stringio (3.2.0)
tailwindcss-rails (4.4.0)
railties (>= 7.0.0)
tailwindcss-ruby (~> 4.0)
tailwindcss-ruby (4.1.16)
tailwindcss-ruby (4.1.16-aarch64-linux-gnu)
tailwindcss-ruby (4.1.16-aarch64-linux-musl)
tailwindcss-ruby (4.1.16-arm64-darwin)
tailwindcss-ruby (4.1.16-x86_64-darwin)
tailwindcss-ruby (4.1.16-x86_64-linux-gnu)
tailwindcss-ruby (4.1.16-x86_64-linux-musl)
thor (1.4.0)
timeout (0.4.4)
tiny_tds (3.3.0)
bigdecimal (~> 3)
tiny_tds (3.3.0-aarch64-linux-gnu)
bigdecimal (~> 3)
tiny_tds (3.3.0-aarch64-linux-musl)
bigdecimal (~> 3)
tiny_tds (3.3.0-x86_64-linux-gnu)
bigdecimal (~> 3)
tiny_tds (3.3.0-x86_64-linux-musl)
bigdecimal (~> 3)
tailwindcss-ruby (4.2.1-x86_64-linux-gnu)
thor (1.5.0)
timeout (0.6.1)
tiny_tds (3.4.0-x86_64-linux-gnu)
bigdecimal (>= 2.0.0)
tsort (0.2.0)
turbo-rails (2.0.20)
turbo-rails (2.0.23)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.1.0)
unicode-emoji (4.2.0)
useragent (0.16.11)
warden (1.2.9)
rack (>= 2.0.9)
@@ -388,17 +379,10 @@ GEM
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.3)
zeitwerk (2.7.5)
PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl
x86_64-linux
DEPENDENCIES
activerecord-sqlserver-adapter
@@ -425,6 +409,7 @@ DEPENDENCIES
rubocop-rspec
rubyzip
selenium-webdriver
solid_queue
sprockets-rails
stimulus-rails
tailwindcss-rails
@@ -437,4 +422,4 @@ RUBY VERSION
ruby 3.4.8p72
BUNDLED WITH
2.5.22
2.6.9
+1 -1
View File
@@ -72,7 +72,7 @@ class EmployersController < ApplicationController
def import
word_doc = params[:employer][:import_from_word]
if word_doc.present? && word_doc.is_a?(ActionDispatch::Http::UploadedFile)
@employer = WordDocProcessor.new(word_doc.tempfile).call
@employer = BenefitsWordDocService::WordDocProcessor.new(word_doc.tempfile).call
@employer.save
redirect_to employer_path(@employer.slug), notice: 'Employer Imported'
else
+1 -1
View File
@@ -70,7 +70,7 @@ module IdCard
slug = params[:id]
@employer = Employer.find_by(slug: slug)
end
cards_pdf = IdCardPrinterService::EmployerCardsGenerator.new(@employer, "PrintCard").call
cards_pdf = IdCardPrinterService::CardsGenerator.new(@employer.employer_member_keys, "PrintCard").call
send_data cards_pdf.to_pdf,
filename: "#{@employer.name.parameterize(separator: "_")}_print_cards_#{Date.today}.pdf",
+90
View File
@@ -0,0 +1,90 @@
class ProcessIdCardDataJob < ApplicationJob
queue_as :default
def perform(member_key, field_exception_ids, has_divisions = false)
member = Member.find_by(pb_entity_key: member_key)
effect_date = determine_eff_date(member)
if effect_date
member_card = @base_card.dup
member_attributes = {
full_name: member.id_card_display_name,
full_name_last_name_first: member.name,
primary_mb_member_key: member.pb_entity_key,
family_id: member.family_id,
plan_id: member.id_card_plan_id,
medical_eff_date: effect_date.strftime("%m/%d/%Y")
}
dependent_attributes = get_dependent_fields(member)
if dependent_attributes.present?
member_attributes.merge!(dependent_attributes)
end
if has_divisions
member_attributes.merge!({employer_name: member.division})
end
if field_exception_ids.present?
exceptions_attributes = {}
field_exceptions = IdCard::FieldException.where(id: field_exception_ids)
member_exception_values = member.id_card_field_exception_values
field_exceptions.each do |fe|
if member_exception_values[fe.field_type] == fe.field_value
fe.field_exception_items.each do |fei|
if fei.field_value.present?
exceptions_attributes[fei.field_name] = fei.field_value
elsif fei.provider_section_id.present?
provider_attributes = IdCard::ProviderSection.find(fei.provider_section_id).attributes.with_indifferent_access.slice(
:provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6,
:provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12,
:claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6,
:claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12
)
exceptions_attributes.merge!(provider_attributes)
elsif fei.network_logo_id.present?
exceptions_attributes.merge!(network_logo_id: fei.network_logo_id)
exceptions_attributes.merge!(network_logo_filename: fei.network_logo.filename)
end
end
end
end
member_attributes.merge!(exceptions_attributes)
end
member_card = IdCard::PrintData.find_by(pl_plan_key: member.pl_plan_key, plan_id: member.id_card_plan_id, primary_mb_member_key: nil).dup
member_card.assign_attributes(member_attributes)
member_card.save
end
true
# BatchProcess.increment_counter(:completed_jobs, batch_process_id)
end
private
def determine_eff_date(member)
participation = Vhcs::PbProductParticipation.joins('INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey"').where('"PBCoveredEntities"."PBEntityKey" = ?', member.pb_entity_key).last
in_effect = participation.in_effect
out_of_effect = participation.out_of_effect
if in_effect <= (Date.today + 90.days) && (out_of_effect - 1.day) > Date.today && out_of_effect > in_effect
in_effect
else
false
end
end
def get_dependent_fields(member)
dependent_attributes = {}
dependents = Vhcs::VwmbMember.where(pl_plan_key: member.pl_plan_key, family_id: member.family_id).where.not(pb_entity_key: member.pb_entity_key)
dependents.each do |dep|
dependent_name = dep.first_name + ' ' + dep.last_name
dependent_attributes["dependent_#{dep.sequence_number - 1}".to_sym] = dependent_name
end
dependent_attributes
end
end
+7
View File
@@ -46,6 +46,13 @@ class Employer < ApplicationRecord
false
end
def employer_member_keys
{
pl_plan_key: self.pl_plan_key,
member_keys: self.members.pluck(:pb_entity_key)
}
end
def name_to_logo_filename(extension)
self.employer_trim_name(self.name).titleize.gsub(/[^a-zA-Z]/, '').concat('Logo').concat(extension.downcase)
end
+4
View File
@@ -36,6 +36,10 @@ module IdCard
plan
end
def has_field_exceptions?
self.field_exceptions.present?
end
def self.permitted_params(params)
params.require(:id_card_setup).permit(
:print_name,
+11
View File
@@ -2,5 +2,16 @@ class Member < ApplicationRecord
belongs_to :id_card_plan, class_name: 'IdCard::Plan', optional: true
belongs_to :employer
def id_card_field_exception_values
address = Vhcs::PbEntityAddress.find_by(pb_entity_key: self.pb_entity_key)
{
zipcode: address.zip,
state: address.state,
family_id: self.family_id
}
end
end
+47
View File
@@ -0,0 +1,47 @@
module Vhcs
class PbEntityAddress < VhcsRecord
self.table_name = 'PBEntityAddress'
alias_attribute :pb_entity_address_key, :PBEntityAddressKey
alias_attribute :pb_entity_key, :PBEntityKey
alias_attribute :address_type_id, :AddressTypeID
alias_attribute :street_line_1, :StreetLine1
alias_attribute :street_line_2, :StreetLine2
alias_attribute :city, :City
alias_attribute :state, :State
alias_attribute :zip, :Zip
alias_attribute :country_code, :CountryCode
alias_attribute :county, :County
alias_attribute :override_pb_entity_address_key, :OverridePBEntityAddressKey
alias_attribute :when_last_changed, :WhenLastChanged
alias_attribute :who_last_changed, :WhoLastChanged
alias_attribute :full_address_to_use, :FullAddressToUse
alias_attribute :country_sub_div, :CountrySubDiv
alias_attribute :full_address, :FullAddress
def attributes
rails_like = {
pb_entity_address_key: self.pb_entity_address_key,
pb_entity_key: self.pb_entity_key,
address_type_id: self.address_type_id,
street_line_1: self.street_line_1,
street_line_2: self.street_line_2,
city: self.city,
state: self.state,
zip: self.zip,
country_code: self.country_code,
county: self.county,
override_pb_entity_address_key: self.override_pb_entity_address_key,
when_last_changed: self.when_last_changed,
who_last_changed: self.who_last_changed,
full_address_to_use: self.full_address_to_use,
country_sub_div: self.country_sub_div,
full_address: self.full_address,
}
super.merge(rails_like)
end
end
end
@@ -0,0 +1,180 @@
module IdCardPrinterService
class CardDataFormatter
def initialize(employers_member_keys)
# @employer = employer
@employers_member_keys = employers_member_keys
# @employer = Employer.includes(id_card_setup: [:provider_section, :rx_section]).find_by(pl_plan_key: pl_plan_key)
# @card_setup = @employer.id_card_setup
end
def call
# blank_card = IdCard::PrintData.new()
# @employer_cards = []
print_card_futures = []
@employers_member_keys.each do |emk|
pl_plan_key = emk[:pl_plan_key]
@member_keys = emk[:member_keys]
@employer = Employer.includes(id_card_setup: [:provider_section, :rx_section]).find_by(pl_plan_key: pl_plan_key)
@card_setup = @employer.id_card_setup
base_card = initialize_employer_base_card()
create_plan_base_cards(base_card)
employer_card_futures = create_member_cards_async()
print_card_futures << employer_card_futures
end
print_card_futures.flatten.map(&:value)
end
private
def initialize_employer_base_card
employer_attributes = {
pl_plan_key: @employer.pl_plan_key,
group_number: @employer.group_number,
rx_group: @card_setup.rx_group_number,
network_provider: @card_setup.network_provider,
network_logo_id: @card_setup.network_logo_id,
network_logo_filename: @card_setup.network_logo.filename,
employer_logo_filename: @card_setup.employer_logo.filename
}
unless @card_setup.has_divisions
employer_attributes.merge!({employer_name: @card_setup.print_name})
end
rx_attributes = @card_setup.rx_section.attributes.with_indifferent_access.slice(
:customer_service,
:web_url
)
provider_attributes = @card_setup.provider_section.attributes.with_indifferent_access.slice(
:provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6,
:provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12,
:claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6,
:claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12
)
selected_attributes = employer_attributes.merge(rx_attributes).merge(provider_attributes)
# blank_card.assign_attributes(selected_attributes)
IdCard::PrintData.new(selected_attributes)
end
def create_plan_base_cards(common_fields_card)
needed_plans_ids = @employer.members.where(pb_entity_key: @member_keys).distinct.pluck(:id_card_plan_id)
needed_plans = @card_setup.plans.where(id: needed_plans_ids)
needed_plans.each do |plan|
selected_attributes = { plan_id: plan.id }
plan.plan_benefits.each do |bene|
selected_attributes["benefit_desc_#{bene.sequence}".to_sym] = bene.benefit_desc
selected_attributes["benefit_#{bene.sequence}".to_sym] = bene.benefit
end
plan_base_card = common_fields_card.dup
plan_base_card.assign_attributes(selected_attributes)
plan_base_card.save
end
end
def create_member_cards_async
field_exceptions = @card_setup.field_exceptions.pluck(:id)
mmember_card_futures = @member_keys.map do |member_key|
Concurrent::Future.execute do
ActiveRecord::Base.connection_pool.with_connection do
ProcessIdCardDataJob.perform_now(member_key, field_exceptions, @card_setup.has_divisions)
end
end
end
mmember_card_futures
# batch_process = BatchProcess.create!(total_jobs: @member_keys.count)
# @member_keys.each do |member_key|
# ProcessIdCardDataJob.perform_later(member_key, @card_setup.has_divisions, batch_process.id)
# end
# @batch_id = batch_process.id
# @members.each do |me|
# effect_date = determine_eff_date(me)
# if effect_date
# member_card = @base_card.dup
# member_attributes = {
# full_name: me.id_card_display_name,
# full_name_last_name_first: me.name,
# primary_mb_member_key: me.pb_entity_key,
# family_id: me.family_id,
# plan_id: me.id_card_plan_id,
# medical_eff_date: effect_date.strftime("%m/%d/%Y")
# }
# if @card_setup.has_divisions
# member_attributes.merge!({employer_name: me.division})
# end
# dependent_attributes = get_dependent_fields(me)
# if dependent_attributes.present?
# selected_attributes = member_attributes.merge(dependent_attributes)
# else
# selected_attributes = member_attributes
# end
# member_card.assign_attributes(selected_attributes)
# @employer_cards.push(member_card)
# end
# end
end
# def set_network_fields
# selected_attributes = @employer.card_provider.attributes.with_indifferent_access.slice(
# :provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6,
# :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12,
# :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6,
# :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12
# )
# @employer_cards.all do |card|
# card.assign_attributes(selected_attributes)
# end
# end
# def set_rx_fields
# # fairos_information = Vhcs::HlrxCrosRef.where(pl_plan_key: 52).first
# selected_attributes = @employer.card_rx.attributes.with_indifferent_access.slice(
# :customer_service,
# :web_url
# )
# @employer_cards.all do |card|
# card.assign_attributes(selected_attributes)
# end
# end
def determine_eff_date(member)
participation = Vhcs::PbProductParticipation.joins('INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey"').where('"PBCoveredEntities"."PBEntityKey" = ?', member.pb_entity_key).last
in_effect = participation.in_effect
out_of_effect = participation.out_of_effect
if in_effect <= (Date.today + 90.days) && (out_of_effect - 1.day) > Date.today && out_of_effect > in_effect
in_effect
else
false
end
end
def get_dependent_fields(member)
dependent_attributes = {}
dependents = @group_dependents.where(family_id: member.family_id).where.not(pb_entity_key: member.pb_entity_key)
dependents.each do |dep|
dependent_name = dep.first_name + ' ' + dep.last_name
dependent_attributes["dependent_#{dep.sequence_number - 1}".to_sym] = dependent_name
end
dependent_attributes
end
end
end
@@ -0,0 +1,68 @@
module IdCardPrinterService
class CardsGenerator
def initialize(employers_member_keys, layout, zip=false)
@employers_member_keys = Array.wrap(employers_member_keys)
@layout = layout
@zip = zip
end
def call
pl_plan_keys = @employers_member_keys.map { |emk| emk[:pl_plan_key] }
IdCard::PrintData.where(pl_plan_key: pl_plan_keys).destroy_all
IdCardPrinterService::CardDataFormatter.new(@employers_member_keys).call
IdCard::PrintData.where(pl_plan_key: pl_plan_keys, primary_mb_member_key: nil).destroy_all
pdf_array = []
batches = break_into_batches(pl_plan_keys)
batches.each do |card_template, batch_pl_plan_keys|
jasper_batch_id = "#{batch_pl_plan_keys.join('_')}-#{Time.current.utc.to_i}"
batch = IdCard::PrintData.where(pl_plan_key: batch_pl_plan_keys)
batch.update!(jasper_batch_id: jasper_batch_id)
batch_pdf = IdCardPrinterService::PdfBatchProcessor.new(card_template, jasper_batch_id, @layout).call
pdf_array << batch_pdf
end
# @employers_member_keys.each do |emk|
# employer_jasper_batches = IdCard::PrintData.where(pl_plan_key: emk[:pl_plan_key]).pluck(:network_logo_id).uniq
# employer_jasper_batches.each do |batch_network_logo|
# jasper_batch_id = "#{emk[:pl_plan_key]}-#{Time.current.utc.to_i}"
# batch = IdCard::PrintData.where(pl_plan_key: emk[:pl_plan_key], network_logo_id: batch_network_logo)
# # batch = employer_card_data.where(network_logo_id: batch_network_logo)
# batch.update!(jasper_batch_id: jasper_batch_id)
# batch_pdf = IdCardPrinterService::PdfBatchProcessor.new(emk[:pl_plan_key], batch_network_logo, jasper_batch_id, @layout).call
# pdf_array << batch_pdf
# end
# end
group_pdfs = combine_pdfs(pdf_array)
group_pdfs
end
private
def break_into_batches(pl_plan_keys)
batches_by_card_template = IdCard::Setup.where(pl_plan_key: pl_plan_keys).group_by(&:card_template)
.transform_values { |setups| setups.map(&:pl_plan_key) }
.compact_blank
end
def combine_pdfs(pdf_array)
if @zip
group_cards_pdf = Zip::OutputStream.write_buffer do |zio|
pdf_array.each do |file|
zio.put_next_entry(file[:name])
zio.write(file[:data])
end
end
else
group_cards_pdf = CombinePDF.new
pdf_array.each { |pdf| group_cards_pdf << pdf }
end
group_cards_pdf
end
end
end
@@ -3,13 +3,36 @@ module IdCardPrinterService
def initialize(employer, layout, zip=false)
@employer = employer
@member_keys = @employer.members.pluck(:pb_entity_key)
@layout = layout
@zip = zip
end
def call
IdCard::PrintData.where(pl_plan_key: @employer.pl_plan_key).destroy_all
IdCardPrinterService::EmployerDataFormatter.new(@employer).call
IdCardPrinterService::EmployerDataFormatter.new(@employer.pl_plan_key, @member_keys).call
# card_futures.each(&:value)
# max_retries = 60
# retries = 0
# finished = false
# batch_process = BatchProcess.find(batch_id)
# until finished || retries > max_retries
# # Solid Queue stores finished jobs here if preserve_finished_jobs = true
# if batch_process.completed_jobs < batch_process.total_jobs
# sleep 0.5
# retries += 1
# else
# batch_process.destroy!
# finished = true
# end
# end
IdCard::PrintData.where(pl_plan_key: @employer.pl_plan_key, primary_mb_member_key: nil).destroy_all
pdf_array = IdCardPrinterService::PdfProcessor.new(@employer, @layout, @zip).call
@@ -1,37 +1,35 @@
module IdCardPrinterService
class EmployerDataFormatter
def initialize(employer, member_keys = nil)
@employer = employer
def initialize(pl_plan_key, member_keys)
# @employer = employer
@member_keys = member_keys
@employer = Employer.includes(id_card_setup: [:provider_section, :rx_section]).find_by(pl_plan_key: pl_plan_key)
@card_setup = @employer.id_card_setup
if member_keys
@members = @employer.members.where(pb_entity_key: member_keys).order(:name)
else
@members = @employer.members.order(:name)
end
@batch_id
end
def call
@base_card = IdCard::PrintData.new()
@employer_cards = []
# blank_card = IdCard::PrintData.new()
# @employer_cards = []
set_common_fields
set_member_fields
base_card = initialize_employer_base_card()
create_plan_base_cards(base_card)
card_futures = create_member_cards_async()
set_plan_fields
@employer_cards.each(&:save!)
card_futures
end
private
def set_common_fields
def initialize_employer_base_card
employer_attributes = {
pl_plan_key: @card_setup.pl_plan_key,
pl_plan_key: @employer.pl_plan_key,
group_number: @employer.group_number,
rx_group: @card_setup.rx_group_number,
network_provider: @card_setup.network_provider
@@ -53,52 +51,70 @@ module IdCardPrinterService
)
selected_attributes = employer_attributes.merge(rx_attributes).merge(provider_attributes)
@base_card.assign_attributes(selected_attributes)
# blank_card.assign_attributes(selected_attributes)
IdCard::PrintData.new(selected_attributes)
end
def set_plan_fields
@card_setup.plans.each do |plan|
selected_attributes = {}
def create_plan_base_cards(common_fields_card)
needed_plans_ids = @employer.members.where(pb_entity_key: @member_keys).distinct.pluck(:id_card_plan_id)
needed_plans = @card_setup.plans.where(id: needed_plans_ids)
needed_plans.each do |plan|
selected_attributes = { plan_id: plan.id }
plan.plan_benefits.each do |bene|
selected_attributes["benefit_desc_#{bene.sequence}".to_sym] = bene.benefit_desc
selected_attributes["benefit_#{bene.sequence}".to_sym] = bene.benefit
end
@employer_cards.find_all { |card| card.plan_id == plan.id.to_s }.each do |card|
card.assign_attributes(selected_attributes)
end
plan_base_card = common_fields_card.dup
plan_base_card.assign_attributes(selected_attributes)
plan_base_card.save
end
end
def set_member_fields
@group_dependents = Vhcs::VwmbMember.where(pl_plan_key: @employer.pl_plan_key)
@members.each do |me|
effect_date = determine_eff_date(me)
if effect_date
member_card = @base_card.dup
member_attributes = {
full_name: me.id_card_display_name,
full_name_last_name_first: me.name,
primary_mb_member_key: me.pb_entity_key,
family_id: me.family_id,
plan_id: me.id_card_plan_id,
medical_eff_date: effect_date.strftime("%m/%d/%Y")
}
def create_member_cards_async
if @card_setup.has_divisions
member_attributes.merge!({employer_name: me.division})
mmember_card_futures = @member_keys.map do |member_key|
Concurrent::Future.execute do
ActiveRecord::Base.connection_pool.with_connection do
ProcessIdCardDataJob.perform_now(member_key, @card_setup.has_divisions)
end
dependent_attributes = get_dependent_fields(me)
if dependent_attributes.present?
selected_attributes = member_attributes.merge(dependent_attributes)
else
selected_attributes = member_attributes
end
member_card.assign_attributes(selected_attributes)
@employer_cards.push(member_card)
end
end
mmember_card_futures
# batch_process = BatchProcess.create!(total_jobs: @member_keys.count)
# @member_keys.each do |member_key|
# ProcessIdCardDataJob.perform_later(member_key, @card_setup.has_divisions, batch_process.id)
# end
# @batch_id = batch_process.id
# @members.each do |me|
# effect_date = determine_eff_date(me)
# if effect_date
# member_card = @base_card.dup
# member_attributes = {
# full_name: me.id_card_display_name,
# full_name_last_name_first: me.name,
# primary_mb_member_key: me.pb_entity_key,
# family_id: me.family_id,
# plan_id: me.id_card_plan_id,
# medical_eff_date: effect_date.strftime("%m/%d/%Y")
# }
# if @card_setup.has_divisions
# member_attributes.merge!({employer_name: me.division})
# end
# dependent_attributes = get_dependent_fields(me)
# if dependent_attributes.present?
# selected_attributes = member_attributes.merge(dependent_attributes)
# else
# selected_attributes = member_attributes
# end
# member_card.assign_attributes(selected_attributes)
# @employer_cards.push(member_card)
# end
# end
end
# def set_network_fields
@@ -0,0 +1,40 @@
module IdCardPrinterService
class JasperBatchUrlGenerator
def initialize(card_template, jasper_batch_id, layout)
@card_template = card_template
@jasper_batch_id = jasper_batch_id
@layout = layout
end
def call
URI::HTTP.build(url_components)
end
private
# def determine_network_logo
# # if @network_logos.length > 1
# # member_geographic_info = Vhcs::PbEntityAddress.joins("INNER JOIN vwMBMember ON PBEntityAddress.PBEntityKey = vwMBMember.PBEntityKey AND PBEntityAddress.AddressTypeID = 1137").where("vwMBMember.FamilyID = ?", @family_id).first
# # @network_logos.where.not(default: true).each do |pnl|
# # if member_geographic_info[pnl.exception_type] == pnl.exception_value
# # return pnl.net_logo
# # end
# # end
# # end
# # @network_logos.find_by(default: true).net_logo
# IdCard::NetworkLogo.find(@network_logo_id).filename
# end
# http://localhost:8080/trunk/PdfServlet?reportConn=BrittonConnect&id=&reportName=FairosRxSampleIDCard-Half&family_id=Classic%202K&employer_logo=BryanPestControl.jpeg&network_logo=CignaLogo.png&reportDir=secure/Documents&SUBREPORT_DIR=/&ImageDir=secure/Documents&netToken=3a4a8b03f4dfb0e6e3fc82dd369f70ef&FileType=PDF
# http://localhost:8080/trunk/PdfServlet?reportConn=BrittonConnect&id=&reportName=FairosRxSampleIDCard-Half&family_id=Classic%202K&employer_logo=BryanPestControl.jpeg&network_logo=CignaLogo.png&reportDir=secure/Documents&SUBREPORT_DIR=/&ImageDir=secure/Documents&netToken=3a4a8b03f4dfb0e6e3fc82dd369f70ef&FileType=PDF
def url_components
{
host: '10.41.1.115',
port: 8080,
path: '/trunk/IdCardsServlet',
query: "reportConn=BrittonConnect&cardTemplate=#{@card_template}Batch&printType=Batch#{@layout}&jasper_batch_id=#{@jasper_batch_id}&FileType=PDF"
}
end
end
end
@@ -0,0 +1,36 @@
module IdCardPrinterService
class PdfBatchProcessor
def initialize(card_template, jasper_batch_id, layout)
@card_template = card_template
@jasper_batch_id = jasper_batch_id
@layout = layout
end
def call
# if @zip
# group_cards_pdf_array = []
# else
# group_cards_pdf = CombinePDF.new
# end
url = IdCardPrinterService::JasperBatchUrlGenerator.new(@card_template, @jasper_batch_id, @layout).call
puts url
batch_pdf = IdCardPrinterService::JasperPdfGenerator.new(url).call
# if @zip
# group_cards_pdf = Zip::OutputStream.write_buffer do |zio|
# group_cards_pdf_array.each do |file|
# zio.put_next_entry(file[:name])
# zio.write(file[:data])
# end
# end
# # else
# # todays_date = DateTime.current.strftime('%Y%m%d%H%M%S')
# # group_cards_pdf.save("tmp/#{@employer.name}_print_cards_#{todays_date}.pdf")
# end
batch_pdf
end
end
end
@@ -3,7 +3,6 @@ module IdCardPrinterService
def initialize(employer, layout, zip = false)
@employer = employer
@card_setup = @employer.id_card_setup
@layout = layout
@zip = zip
end
@@ -6,7 +6,7 @@ module IdCardPrinterService
end
def call
IdCard::PrintData.where(employer_name: @employer.name).destroy_all
IdCard::PrintData.where(employer_name: @employer.id_card_setup.print_name).destroy_all
IdCardPrinterService::SampleDataFormatter.new(@employer).call
IdCardPrinterService::SamplePdfProcessor.new(@employer).call
@@ -23,7 +23,7 @@ module IdCardPrinterService
def set_employer_fields
selected_attributes = {
employer_name: @employer.name,
employer_name: @card_setup.print_name,
group_number: @employer.group_number.present? ? @employer.group_number : "999999",
medical_eff_date: @employer.effective_date
}
@@ -8,7 +8,7 @@ module IdCardPrinterService
def call
group_cards_pdf = CombinePDF.new
IdCard::PrintData.where(employer_name: @employer.name).each do |card|
IdCard::PrintData.where(employer_name: @card_setup.print_name).each do |card|
url = IdCardPrinterService::SampleJasperUrlGenerator.new(@employer, card.sample_key, card.sample_plan_title).call
puts url
card_pdf = IdCardPrinterService::JasperPdfGenerator.new(url).call
@@ -10,7 +10,21 @@ module IdCardQueueService
end
def call
CallStoredProc.new('BrittonGetQueuedIdCardMemberKeysTPA', { PLPlanKeys: @employer_pl_plan_keys }).call.to_ary
raw_employers_member_keys = CallStoredProc.new('BrittonGetQueuedIdCardMemberKeysTPA', { PLPlanKeys: @employer_pl_plan_keys }).call.to_ary
format_employers_member_keys(raw_employers_member_keys)
end
private
def format_employers_member_keys(raw_employers_member_keys)
key_map = { "PlanKey" => :pl_plan_key, "MemberKeys" => :member_keys }
raw_employers_member_keys.map do |hash|
hash["PlanKey"] = hash["PlanKey"].to_s
hash["MemberKeys"] = hash["MemberKeys"].split(", ").map(&:to_i)
hash.transform_keys(key_map)
end
end
end
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
require_relative "../config/environment"
require "solid_queue/cli"
SolidQueue::Cli.start(ARGV)
+1
View File
@@ -40,5 +40,6 @@ module Baclight
# Don't generate system test files.
config.generators.system_tests = nil
config.active_job.queue_adapter = :solid_queue
end
end
+4
View File
@@ -81,4 +81,8 @@ Rails.application.configure do
# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
# config.generators.apply_rubocop_autocorrect_after_generate!
config.active_job.queue_adapter = :solid_queue
config.solid_queue.connects_to = { database: { writing: :baclight } }
# config.active_job.queue_adapter = :async
end
+3 -1
View File
@@ -71,7 +71,9 @@ Rails.application.configure do
# config.cache_store = :mem_cache_store
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
config.active_job.queue_adapter = :solid_queue
# config.solid_queue.connects_to = { database: { writing: :queue } }
# config.solid_queue.connects_to = { database: { writing: :queue } }
# config.active_job.queue_name_prefix = "railsondocker_production"
# Disable caching for Action Mailer templates even if Action Controller
+2
View File
@@ -29,6 +29,8 @@ port ENV.fetch("PORT", 3002)
# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
plugin :solid_queue if Rails.env.development?
# plugin :tailwindcss
# Only use a pidfile when requested
+18
View File
@@ -0,0 +1,18 @@
default: &default
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 3
processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
polling_interval: 0.1
development:
<<: *default
test:
<<: *default
production:
<<: *default
+15
View File
@@ -0,0 +1,15 @@
# examples:
# periodic_cleanup:
# class: CleanSoftDeletedRecordsJob
# queue: background
# args: [ 1000, { batch_size: 500 } ]
# schedule: every hour
# periodic_cleanup_with_command:
# command: "SoftDeletedRecord.due.delete_all"
# priority: 2
# schedule: at 5am every day
production:
clear_solid_queue_finished_jobs:
command: "SolidQueue::Job.clear_finished_in_batches(sleep_between_batches: 0.3)"
schedule: every hour at minute 12
@@ -74,9 +74,13 @@ class CreateIdCardPrintData < ActiveRecord::Migration[7.0]
t.string :benefit_13
t.string :benefit_desc_14
t.string :benefit_14
t.integer :network_logo_id
t.string :network_logo_filename
t.string :employer_logo_filename
t.boolean :sample, default: false
t.string :sample_key
t.string :sample_plan_title
t.string :jasper_batch_id
t.timestamps
end
@@ -0,0 +1,131 @@
class SolidQueueSetup < ActiveRecord::Migration[7.2]
def change
create_table "solid_queue_blocked_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "queue_name", null: false
t.integer "priority", default: 0, null: false
t.string "concurrency_key", null: false
t.datetime "expires_at", null: false
t.datetime "created_at", null: false
t.index [ "concurrency_key", "priority", "job_id" ], name: "index_solid_queue_blocked_executions_for_release"
t.index [ "expires_at", "concurrency_key" ], name: "index_solid_queue_blocked_executions_for_maintenance"
t.index [ "job_id" ], name: "index_solid_queue_blocked_executions_on_job_id", unique: true
end
create_table "solid_queue_claimed_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.bigint "process_id"
t.datetime "created_at", null: false
t.index [ "job_id" ], name: "index_solid_queue_claimed_executions_on_job_id", unique: true
t.index [ "process_id", "job_id" ], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id"
end
create_table "solid_queue_failed_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.text "error"
t.datetime "created_at", null: false
t.index [ "job_id" ], name: "index_solid_queue_failed_executions_on_job_id", unique: true
end
create_table "solid_queue_jobs", force: :cascade do |t|
t.string "queue_name", null: false
t.string "class_name", null: false
t.text "arguments"
t.integer "priority", default: 0, null: false
t.string "active_job_id"
t.datetime "scheduled_at"
t.datetime "finished_at"
t.string "concurrency_key"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index [ "active_job_id" ], name: "index_solid_queue_jobs_on_active_job_id"
t.index [ "class_name" ], name: "index_solid_queue_jobs_on_class_name"
t.index [ "finished_at" ], name: "index_solid_queue_jobs_on_finished_at"
t.index [ "queue_name", "finished_at" ], name: "index_solid_queue_jobs_for_filtering"
t.index [ "scheduled_at", "finished_at" ], name: "index_solid_queue_jobs_for_alerting"
end
create_table "solid_queue_pauses", force: :cascade do |t|
t.string "queue_name", null: false
t.datetime "created_at", null: false
t.index [ "queue_name" ], name: "index_solid_queue_pauses_on_queue_name", unique: true
end
create_table "solid_queue_processes", force: :cascade do |t|
t.string "kind", null: false
t.datetime "last_heartbeat_at", null: false
t.bigint "supervisor_id"
t.integer "pid", null: false
t.string "hostname"
t.text "metadata"
t.datetime "created_at", null: false
t.string "name", null: false
t.index [ "last_heartbeat_at" ], name: "index_solid_queue_processes_on_last_heartbeat_at"
t.index [ "name", "supervisor_id" ], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true
t.index [ "supervisor_id" ], name: "index_solid_queue_processes_on_supervisor_id"
end
create_table "solid_queue_ready_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "queue_name", null: false
t.integer "priority", default: 0, null: false
t.datetime "created_at", null: false
t.index [ "job_id" ], name: "index_solid_queue_ready_executions_on_job_id", unique: true
t.index [ "priority", "job_id" ], name: "index_solid_queue_poll_all"
t.index [ "queue_name", "priority", "job_id" ], name: "index_solid_queue_poll_by_queue"
end
create_table "solid_queue_recurring_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "task_key", null: false
t.datetime "run_at", null: false
t.datetime "created_at", null: false
t.index [ "job_id" ], name: "index_solid_queue_recurring_executions_on_job_id", unique: true
t.index [ "task_key", "run_at" ], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true
end
create_table "solid_queue_recurring_tasks", force: :cascade do |t|
t.string "key", null: false
t.string "schedule", null: false
t.string "command", limit: 2048
t.string "class_name"
t.text "arguments"
t.string "queue_name"
t.integer "priority", default: 0
t.boolean "static", default: true, null: false
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index [ "key" ], name: "index_solid_queue_recurring_tasks_on_key", unique: true
t.index [ "static" ], name: "index_solid_queue_recurring_tasks_on_static"
end
create_table "solid_queue_scheduled_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "queue_name", null: false
t.integer "priority", default: 0, null: false
t.datetime "scheduled_at", null: false
t.datetime "created_at", null: false
t.index [ "job_id" ], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true
t.index [ "scheduled_at", "priority", "job_id" ], name: "index_solid_queue_dispatch_all"
end
create_table "solid_queue_semaphores", force: :cascade do |t|
t.string "key", null: false
t.integer "value", default: 1, null: false
t.datetime "expires_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index [ "expires_at" ], name: "index_solid_queue_semaphores_on_expires_at"
t.index [ "key", "value" ], name: "index_solid_queue_semaphores_on_key_and_value"
t.index [ "key" ], name: "index_solid_queue_semaphores_on_key", unique: true
end
add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
end
end
+132 -1
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2026_01_16_182836) do
ActiveRecord::Schema[7.2].define(version: 2026_03_20_152726) do
create_table "employers", force: :cascade do |t|
t.string "name"
t.string "slug"
@@ -162,9 +162,13 @@ ActiveRecord::Schema[7.2].define(version: 2026_01_16_182836) do
t.string "benefit_13"
t.string "benefit_desc_14"
t.string "benefit_14"
t.integer "network_logo_id"
t.string "network_logo_filename"
t.string "employer_logo_filename"
t.boolean "sample", default: false
t.string "sample_key"
t.string "sample_plan_title"
t.string "jasper_batch_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
@@ -265,6 +269,127 @@ ActiveRecord::Schema[7.2].define(version: 2026_01_16_182836) do
t.index ["id_card_plan_id"], name: "index_members_on_id_card_plan_id"
end
create_table "solid_queue_blocked_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "queue_name", null: false
t.integer "priority", default: 0, null: false
t.string "concurrency_key", null: false
t.datetime "expires_at", null: false
t.datetime "created_at", null: false
t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release"
t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance"
t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true
end
create_table "solid_queue_claimed_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.bigint "process_id"
t.datetime "created_at", null: false
t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true
t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id"
end
create_table "solid_queue_failed_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.text "error"
t.datetime "created_at", null: false
t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true
end
create_table "solid_queue_jobs", force: :cascade do |t|
t.string "queue_name", null: false
t.string "class_name", null: false
t.text "arguments"
t.integer "priority", default: 0, null: false
t.string "active_job_id"
t.datetime "scheduled_at"
t.datetime "finished_at"
t.string "concurrency_key"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id"
t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name"
t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at"
t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering"
t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting"
end
create_table "solid_queue_pauses", force: :cascade do |t|
t.string "queue_name", null: false
t.datetime "created_at", null: false
t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true
end
create_table "solid_queue_processes", force: :cascade do |t|
t.string "kind", null: false
t.datetime "last_heartbeat_at", null: false
t.bigint "supervisor_id"
t.integer "pid", null: false
t.string "hostname"
t.text "metadata"
t.datetime "created_at", null: false
t.string "name", null: false
t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at"
t.index ["name", "supervisor_id"], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true
t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id"
end
create_table "solid_queue_ready_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "queue_name", null: false
t.integer "priority", default: 0, null: false
t.datetime "created_at", null: false
t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true
t.index ["priority", "job_id"], name: "index_solid_queue_poll_all"
t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue"
end
create_table "solid_queue_recurring_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "task_key", null: false
t.datetime "run_at", null: false
t.datetime "created_at", null: false
t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true
t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true
end
create_table "solid_queue_recurring_tasks", force: :cascade do |t|
t.string "key", null: false
t.string "schedule", null: false
t.string "command", limit: 2048
t.string "class_name"
t.text "arguments"
t.string "queue_name"
t.integer "priority", default: 0
t.boolean "static", default: true, null: false
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["key"], name: "index_solid_queue_recurring_tasks_on_key", unique: true
t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static"
end
create_table "solid_queue_scheduled_executions", force: :cascade do |t|
t.bigint "job_id", null: false
t.string "queue_name", null: false
t.integer "priority", default: 0, null: false
t.datetime "scheduled_at", null: false
t.datetime "created_at", null: false
t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true
t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all"
end
create_table "solid_queue_semaphores", force: :cascade do |t|
t.string "key", null: false
t.integer "value", default: 1, null: false
t.datetime "expires_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at"
t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value"
t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true
end
add_foreign_key "id_card_field_exception_items", "id_card_field_exceptions", column: "field_exception_id"
add_foreign_key "id_card_field_exception_items", "id_card_network_logos", column: "network_logo_id"
add_foreign_key "id_card_field_exception_items", "id_card_provider_sections", column: "provider_section_id"
@@ -278,4 +403,10 @@ ActiveRecord::Schema[7.2].define(version: 2026_01_16_182836) do
add_foreign_key "id_card_setups", "id_card_rx_sections", column: "rx_section_id"
add_foreign_key "members", "employers"
add_foreign_key "members", "id_card_plans"
add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
end
+15 -2
View File
@@ -1,7 +1,7 @@
# ----- Build Stage -----
# Using a specific Ruby version (e.g., 3.3) for stability
ARG RUBY_VERSION=3.4.8
FROM docker.io/library/ruby:$RUBY_VERSION-slim as base
FROM docker.io/library/ruby:3.4.8-slim as base
# Install production system dependencies
RUN --mount=type=cache,target=/var/cache/apt \
@@ -27,6 +27,8 @@ WORKDIR /usr/src/app
RUN gem install foreman
# RUN chmod +x /usr/src/app/bin/jobs
# Copy runtime Ruby dependencies and the precompiled assets from the builder stage
# COPY --from=builder /usr/local/bundle /usr/local/bundle
# COPY --from=builder /usr/src/app /usr/src/app
@@ -37,6 +39,17 @@ RUN gem install foreman
# && touch /usr/local/var/run/watchman/.not-empty \
# && chmod 2777 /usr/local/var/run/watchman
# COPY . .
# 1. Add bin/jobs script to container
COPY bin/jobs /usr/src/bin/jobs
# 2. Make the script executable
RUN chmod +x /usr/src/bin/jobs
# 3. Set it as the entrypoint
# ENTRYPOINT ["/usr/src/bin/jobs"]
# The entrypoint script is a good practice for handling Rails server startup
ENTRYPOINT ["./bin/docker-entrypoint-development"]
@@ -44,4 +57,4 @@ ENTRYPOINT ["./bin/docker-entrypoint-development"]
EXPOSE 3002
# Set the default command to run the Rails server
CMD ["./bin/dev"]
CMD ["./bin/dev", "bin/jobs start"]