theseus/app/controllers/letter/batches_controller.rb
2025-12-30 12:22:11 -05:00

256 lines
8.3 KiB
Ruby

class Letter::BatchesController < BaseBatchesController
# GET /letter/batches
def index
authorize Letter::Batch, policy_class: Letter::BatchPolicy
@batches = policy_scope(Letter::Batch, policy_scope_class: Letter::BatchPolicy::Scope).order(created_at: :desc)
end
# GET /letter/batches/new
def new
authorize Letter::Batch, policy_class: Letter::BatchPolicy
@batch = Letter::Batch.new
end
# GET /letter/batches/:id
def show
authorize @batch, policy_class: Letter::BatchPolicy
end
# GET /letter/batches/:id/edit
def edit
authorize @batch, policy_class: Letter::BatchPolicy
end
# POST /letter/batches
def create
authorize Letter::Batch, policy_class: Letter::BatchPolicy
@batch = Letter::Batch.new(batch_params.merge(user: current_user))
if @batch.save
redirect_to map_fields_letter_batch_path(@batch), notice: "Batch was successfully created."
else
render :new, status: :unprocessable_entity
end
end
# PATCH /letter/batches/:id
def update
authorize @batch, policy_class: Letter::BatchPolicy
if @batch.update(batch_params)
validate_postage_types
if @batch.errors.any?
render :edit, status: :unprocessable_entity
return
end
# Update associated letters if the batch hasn't been processed
if @batch.may_mark_processed?
@batch.letters.update_all(
height: @batch.letter_height,
width: @batch.letter_width,
weight: @batch.letter_weight,
mailing_date: @batch.letter_mailing_date,
usps_mailer_id_id: @batch.letter_mailer_id_id,
return_address_id: @batch.letter_return_address_id,
return_address_name: @batch.letter_return_address_name,
)
end
# Always update tags and user facing title on letters
@batch.letters.update_all(
tags: @batch.tags,
user_facing_title: @batch.user_facing_title,
)
redirect_to letter_batch_path(@batch), notice: "Batch was successfully updated."
else
render :edit, status: :unprocessable_entity
end
end
# DELETE /letter/batches/:id
def destroy
authorize @batch, policy_class: Letter::BatchPolicy
@batch.destroy
redirect_to letter_batches_path, notice: "Batch was successfully destroyed."
end
def process_form
authorize @batch, :process_form?, policy_class: Letter::BatchPolicy
render :process_letter
end
def process_batch
authorize @batch, :process_batch?, policy_class: Letter::BatchPolicy
@batch = Batch.find(params[:id])
if request.post?
if letter_batch_params[:letter_mailing_date].blank?
redirect_to process_letter_batch_path(@batch), alert: "Mailing date is required"
return
end
@batch.letter_mailing_date = letter_batch_params[:letter_mailing_date]
@batch.save! # Save the mailing date before processing
# Only require payment account if indicia is selected
if letter_batch_params[:us_postage_type] == "indicia" || letter_batch_params[:intl_postage_type] == "indicia"
authorize @batch, :process_batch_with_indicia?, policy_class: Letter::BatchPolicy
payment_account = USPS::PaymentAccount.find_by(id: letter_batch_params[:usps_payment_account_id])
if payment_account.nil?
redirect_to process_letter_batch_path(@batch), alert: "Please select a valid payment account when using indicia"
return
end
hcb_payment_account = current_user.hcb_payment_accounts.find_by(id: letter_batch_params[:hcb_payment_account_id])
if hcb_payment_account.nil?
redirect_to process_letter_batch_path(@batch), alert: "Please select an HCB payment account to purchase indicia"
return
end
else
hcb_payment_account = nil
end
begin
@batch.process!(
payment_account: payment_account,
hcb_payment_account: hcb_payment_account,
us_postage_type: letter_batch_params[:us_postage_type],
intl_postage_type: letter_batch_params[:intl_postage_type],
template_cycle: letter_batch_params[:template_cycle].to_s.split(",").compact_blank,
user_facing_title: letter_batch_params[:user_facing_title],
include_qr_code: letter_batch_params[:include_qr_code],
)
@batch.mark_processed! if @batch.may_mark_processed?
redirect_to letter_batch_path(@batch, print_now: letter_batch_params[:print_immediately]), notice: "Batch processed successfully"
rescue => e
event_id = Sentry.capture_exception(e)&.event_id
redirect_to process_letter_batch_path(@batch), alert: "Failed to process batch: #{e.message} (error: #{event_id})"
end
end
end
def mark_printed
authorize @batch, :mark_printed?, policy_class: Letter::BatchPolicy
if @batch.processed?
@batch.letters.each do |letter|
letter.mark_printed! if letter.may_mark_printed?
end
flash[:success] = "all letters have been marked as printed!"
redirect_to letter_batch_path(@batch)
else
flash[:alert] = "Cannot mark letters as printed. Batch must be processed."
redirect_to letter_batch_path(@batch)
end
end
def mark_mailed
authorize @batch, :mark_mailed?, policy_class: Letter::BatchPolicy
if @batch.processed?
@batch.letters.each do |letter|
letter.mark_mailed! if letter.may_mark_mailed?
end
User::UpdateTasksJob.perform_now(current_user)
redirect_to letter_batch_path(@batch), notice: "All letters have been marked as mailed."
else
redirect_to letter_batch_path(@batch), alert: "Cannot mark letters as mailed. Batch must be processed."
end
end
def update_costs
authorize @batch, :update_costs?, policy_class: Letter::BatchPolicy
# Calculate counts without saving
us_letters = @batch.letters.joins(:address).where(addresses: { country: "US" })
intl_letters = @batch.letters.joins(:address).where.not(addresses: { country: "US" })
cost_differences = @batch.postage_cost_difference(
us_postage_type: params[:us_postage_type],
intl_postage_type: params[:intl_postage_type],
)
render json: {
total_cost: @batch.postage_cost,
cost_difference: {
us: cost_differences[:us],
intl: cost_differences[:intl],
},
us_count: us_letters.count,
intl_count: intl_letters.count,
}
end
def regenerate_form
authorize @batch, :process_batch?, policy_class: Letter::BatchPolicy
render :regenerate_labels
end
def regenerate_labels
authorize @batch, :process_batch?, policy_class: Letter::BatchPolicy
@batch.regenerate_labels!(
template_cycle: letter_batch_params[:template_cycle].to_s.split(",").compact_blank,
include_qr_code: letter_batch_params[:include_qr_code],
)
redirect_to letter_batch_path(@batch), notice: "Labels regenerated successfully"
end
private
def batch_params
params.require(:letter_batch).permit(
:csv,
:letter_template_id,
:user_facing_title,
:letter_height,
:letter_width,
:letter_weight,
:letter_mailing_date,
:letter_mailer_id_id,
:letter_return_address_id,
:letter_return_address_name,
:letter_processing_category,
tags: [],
)
end
def letter_batch_params
params.require(:batch).permit(
:csv,
:letter_height,
:letter_width,
:user_facing_title,
:letter_weight,
:letter_mailing_date,
:letter_processing_category,
:letter_mailer_id_id,
:letter_return_address_id,
:letter_return_address_name,
:us_postage_type,
:intl_postage_type,
:usps_payment_account_id,
:hcb_payment_account_id,
:include_qr_code,
:print_immediately,
:template_cycle,
tags: [],
)
end
def validate_postage_types
return unless @batch.letter_return_address&.us?
us_postage_type = batch_params[:us_postage_type]
intl_postage_type = batch_params[:intl_postage_type]
if us_postage_type.present? && !%w[stamps indicia].include?(us_postage_type)
@batch.errors.add(:us_postage_type, "must be either 'stamps' or 'indicia'")
end
if intl_postage_type.present? && !%w[stamps indicia].include?(intl_postage_type)
@batch.errors.add(:intl_postage_type, "must be either 'stamps' or 'indicia'")
end
end
end