class OpportunitiesController < ApplicationController before_action :require_current_project! before_action :set_opportunity, only: %i[show edit update destroy update_stage] before_action :load_form_data, only: %i[new create edit update] def index @page_title = "Opportunità" scope = opportunities_for_current_project.includes(:organization, :assigned_user, :project).order(updated_at: :desc) scope = scope.where(pipeline_stage: params[:pipeline_stage]) if params[:pipeline_stage].present? scope = scope.where(assigned_user_id: params[:owner]) if params[:owner].present? @pagy, @opportunities = pagy(scope, items: 30) respond_to do |format| format.html format.csv { send_data CsvExport.opportunities(scope), filename: "opportunities-#{Date.current}.csv" } end end def show redirect_to @opportunity.organization end def new @page_title = "Nuova opportunità" @opportunity = Opportunity.new( organization_id: params[:organization_id], project: current_project, assigned_user: current_user, pipeline_stage: "to_contact", probability: 5 ) end def create @opportunity = Opportunity.new(opportunity_params) @opportunity.project ||= current_project if @opportunity.save redirect_to @opportunity.organization, notice: "Opportunità creata." else render :new, status: :unprocessable_entity end end def edit @page_title = "Modifica opportunità" end def update if @opportunity.update(opportunity_params) redirect_to @opportunity.organization, notice: "Opportunità aggiornata." else render :edit, status: :unprocessable_entity end end def destroy org = @opportunity.organization @opportunity.destroy! redirect_to org, notice: "Opportunità eliminata." end def update_stage stage_params = params.permit(:pipeline_stage, :lost_reason, :notes) new_stage = stage_params[:pipeline_stage].to_s unless Catalog::PIPELINE_STAGES.key?(new_stage) redirect_back fallback_location: pipeline_path, alert: "Stage non valido." and return end begin @opportunity.move_to_stage!( new_stage, lost_reason: stage_params[:lost_reason], notes: stage_params[:notes], user: current_user ) respond_to do |format| format.turbo_stream { render turbo_stream: turbo_stream.replace("flash", partial: "shared/flash", locals: { notice: "Stage aggiornato." }) } format.html { redirect_back fallback_location: pipeline_path, notice: "Stage aggiornato." } format.json { render json: { ok: true, stage: @opportunity.pipeline_stage } } end rescue ActiveRecord::RecordInvalid => e respond_to do |format| format.html { redirect_back fallback_location: pipeline_path, alert: e.record.errors.full_messages.to_sentence } format.json { render json: { ok: false, errors: e.record.errors.full_messages }, status: :unprocessable_entity } end end end private def set_opportunity @opportunity = Opportunity.find(params[:id]) end def load_form_data @organizations = organizations_for_current_project.order(:name) @users = User.active.order(:first_name) @products = Product.active.ordered @projects = available_projects end def opportunity_params params.require(:opportunity).permit( :organization_id, :project_id, :name, :pipeline_stage, :estimated_value, :probability, :expected_close_date, :product, :assigned_user_id, :lost_reason, :notes, :ab_variant, :send_status, :sent_on, :outcome, :demo_trial, :converted ) end end