Allinea il conteggio clienti della dashboard alle società, non ai deal vinti.
CI / scan_ruby (push) Failing after 14m57s
CI / scan_js (push) Successful in 11m7s
CI / lint (push) Failing after 12m34s

Neumarkt aveva due opportunità WON e gonfiava banner e card a 3, mentre la lista Solo clienti mostra 2 società.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 07:52:03 +02:00
co-authored by Cursor
parent 3f7794959e
commit 47c4308815
5 changed files with 34 additions and 5 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ class SalesGoal < ApplicationRecord
case metric
when "customers_acquired"
opps.won.where(won_at: start_date.beginning_of_day..end_date.end_of_day).count
opps.won.where(won_at: start_date.beginning_of_day..end_date.end_of_day).distinct.count(:organization_id)
when "won_value"
opps.won.where(won_at: start_date.beginning_of_day..end_date.end_of_day).sum(:estimated_value).to_f
when "trials"
+4
View File
@@ -15,6 +15,10 @@ class Dashboard::Metrics
organizations_scope.prospects.count
end
def customers_count
organizations_scope.customers.count
end
def open_pipeline_value
@scope.open_stage.sum(:estimated_value).to_f
end
+2 -2
View File
@@ -37,7 +37,7 @@
</section>
<section>
<p class="mb-3 text-sm text-slate-500">Conteggio per stage attuale: quante opportunità sono in quello stato ora.</p>
<p class="mb-3 text-sm text-slate-500">Prospect e clienti sono società. Gli altri numeri sono opportunità nello stage attuale.</p>
<div class="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-4">
<% [
["Prospect totali", @metrics.prospect_count],
@@ -48,7 +48,7 @@
["Demo/Trial", @stage_counts["demo_trial"]],
["Primo utilizzo", @stage_counts["first_use"]],
["Proposte", @stage_counts["proposal"]],
["Clienti acquisiti", @stage_counts["won"]],
["Clienti acquisiti", @metrics.customers_count],
["Persi", @stage_counts["lost"]],
["Valore WON", format_money(@metrics.won_value)],
["Pipeline aperta", format_money(@metrics.open_pipeline_value)],
@@ -7,7 +7,7 @@ class DashboardControllerTest < ActionDispatch::IntegrationTest
assert_response :success
assert_match(/Da contattare/, response.body)
assert_match(/Conteggio per stage attuale/, response.body)
assert_match(/Prospect e clienti sono società/, response.body)
assert_match(/da qui in poi/, response.body)
assert_match(/In trattativa senza next action/, response.body)
assert_match(/Senza attività in timeline/, response.body)
+26 -1
View File
@@ -82,12 +82,37 @@ class DashboardMetricsTest < ActiveSupport::TestCase
assert_equal 0, metrics.demo_to_won_conversion
end
test "customers acquired counts unique organizations not duplicate won deals" do
org = Organization.create!(
name: "Cliente doppio #{SecureRandom.hex(3)}",
status: "prospect",
organization_type: "societa_sportiva"
)
2.times { |i| add_opp("won", organization: org, name: "Deal #{i}") }
add_opp("won")
assert_equal 3, metrics.stage_counts["won"]
assert_equal 2, metrics.customers_count
end
test "goal progress" do
goal = sales_goals(:september)
assert_equal 0, goal.current_value
assert_equal 0, goal.progress_percentage
end
test "customers_acquired goal counts distinct organizations in the period" do
org = Organization.create!(
name: "Cliente goal #{SecureRandom.hex(3)}",
status: "prospect",
organization_type: "societa_sportiva"
)
2.times { |i| add_opp("won", organization: org, name: "Goal deal #{i}") }
add_opp("won")
assert_equal 2, sales_goals(:september).current_value
end
private
def metrics
@@ -95,7 +120,7 @@ class DashboardMetricsTest < ActiveSupport::TestCase
end
def add_opp(stage, **attrs)
org = Organization.create!(
org = attrs.delete(:organization) || Organization.create!(
name: "Soc #{stage} #{SecureRandom.hex(3)}",
status: "prospect",
organization_type: "societa_sportiva"