Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG. Co-authored-by: Cursor <cursoragent@cursor.com>
109 lines
3.6 KiB
Ruby
109 lines
3.6 KiB
Ruby
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
|