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

137 lines
4.2 KiB
Ruby

class Warehouse::BatchesController < BaseBatchesController
before_action :set_allowed_templates, only: %i[ new create ]
# GET /warehouse/batches or /warehouse/batches.json
def index
authorize Warehouse::Batch
@batches = policy_scope(Warehouse::Batch).order(created_at: :desc)
end
# GET /warehouse/batches/1 or /warehouse/batches/1.json
def show
authorize @batch
end
# GET /warehouse/batches/new
def new
authorize Warehouse::Batch
@batch = Warehouse::Batch.new
end
# GET /warehouse/batches/1/edit
def edit
authorize @batch
end
# POST /warehouse/batches or /warehouse/batches.json
def create
authorize Warehouse::Batch
@batch = Warehouse::Batch.new(batch_params.merge(user: current_user))
if @batch.save
@batch.aasm_state = :awaiting_field_mapping
@batch.save!
redirect_to map_fields_warehouse_batch_path(@batch), notice: "Please map your CSV fields to address fields."
else
render :new, status: :unprocessable_entity
end
end
# PATCH/PUT /warehouse/batches/1 or /warehouse/batches/1.json
def update
authorize @batch
if @batch.update(batch_params)
# If template changed and batch hasn't been processed, recreate orders
if @batch.may_mark_processed? && @batch.saved_change_to_warehouse_template_id?
# Delete existing orders
@batch.orders.destroy_all
# Recreate orders from addresses with new template
@batch.addresses.each do |address|
Warehouse::Order.from_template(
@batch.warehouse_template,
batch: @batch,
recipient_email: address.email,
address: address,
user: @batch.user,
idempotency_key: "batch_#{@batch.id}_address_#{address.id}",
user_facing_title: @batch.warehouse_user_facing_title,
tags: @batch.tags,
).save!
end
end
# Always update tags and user facing title on orders
@batch.orders.update_all(
tags: @batch.tags,
user_facing_title: @batch.warehouse_user_facing_title,
)
redirect_to warehouse_batch_path(@batch), notice: "Batch was successfully updated."
else
render :edit, status: :unprocessable_entity
end
end
def destroy
authorize @batch
@batch.destroy
redirect_to warehouse_batches_path, notice: "Batch was successfully destroyed."
end
def process_form
authorize @batch, :process_form?
render :process_warehouse
end
def process_batch
authorize @batch, :process_batch?
if @batch.process!
redirect_to warehouse_batch_path(@batch), notice: "Batch was successfully processed."
else
render :process_form, status: :unprocessable_entity
end
end
def set_mapping
authorize @batch, :set_mapping?
mapping = mapping_params.to_h
# Invert the mapping to get from CSV columns to address fields
inverted_mapping = mapping.invert
# Validate required fields
missing_fields = REQUIRED_FIELDS.reject { |field| inverted_mapping[field].present? }
if missing_fields.any?
flash.now[:error] = "Please map the following required fields: #{missing_fields.join(", ")}"
render :map_fields, status: :unprocessable_entity
return
end
if @batch.update!(field_mapping: inverted_mapping)
begin
@batch.run_map!
rescue StandardError => e
Rails.logger.warn(e)
event_id = Sentry.capture_exception(e)&.event_id
redirect_to warehouse_batch_path(@batch), flash: { alert: "Error mapping fields! #{e.message} (error: #{event_id})" }
return
end
redirect_to process_confirm_warehouse_batch_path(@batch), notice: "Field mapping saved. Please review and process your batch."
else
flash.now[:error] = "Failed to save field mapping. #{@batch.errors.full_messages.join(", ")}"
render :map_fields, status: :unprocessable_entity
end
end
private
def batch_params
params.require(:batch).permit(:warehouse_template_id, :warehouse_user_facing_title, :csv, tags: [])
end
def set_allowed_templates
@allowed_templates = Warehouse::Template.where(public: true).or(Warehouse::Template.where(user: current_user))
end
end