Module: Legion::Extensions::Rfp::Analytics::Runners::Metrics
- Extended by:
- Helpers::Client
- Includes:
- Helpers::Lex
- Included in:
- Client
- Defined in:
- lib/legion/extensions/rfp/analytics/runners/metrics.rb
Instance Method Summary collapse
- #record_outcome(proposal_id:, outcome:, revenue: nil, feedback: nil) ⇒ Object
- #record_proposal(proposal_id:, rfp_source:, submitted_at: nil, sections: 0, word_count: 0) ⇒ Object
- #response_time_stats(proposals:) ⇒ Object
- #summary(proposals:) ⇒ Object
Methods included from Helpers::Client
Instance Method Details
#record_outcome(proposal_id:, outcome:, revenue: nil, feedback: nil) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/legion/extensions/rfp/analytics/runners/metrics.rb', line 23 def record_outcome(proposal_id:, outcome:, revenue: nil, feedback: nil, **) valid_outcomes = %i[won lost no_decision pending] outcome_sym = outcome.to_sym return { result: nil, error: "Invalid outcome: #{outcome}. Valid: #{valid_outcomes.join(', ')}" } unless valid_outcomes.include?(outcome_sym) { result: { proposal_id: proposal_id, outcome: outcome_sym, revenue: revenue, feedback: feedback, recorded_at: Time.now.iso8601 } } end |
#record_proposal(proposal_id:, rfp_source:, submitted_at: nil, sections: 0, word_count: 0) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/legion/extensions/rfp/analytics/runners/metrics.rb', line 11 def record_proposal(proposal_id:, rfp_source:, submitted_at: nil, sections: 0, word_count: 0, **) metric = { proposal_id: proposal_id, rfp_source: rfp_source, submitted_at: submitted_at || Time.now.iso8601, sections: sections, word_count: word_count, recorded_at: Time.now.iso8601 } { result: metric } end |
#response_time_stats(proposals:) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/legion/extensions/rfp/analytics/runners/metrics.rb', line 58 def response_time_stats(proposals:, **) times = proposals.filter_map do |p| next unless p[:created_at] && p[:submitted_at] created = Time.parse(p[:created_at]) submitted = Time.parse(p[:submitted_at]) (submitted - created).to_f end return { result: { count: 0 } } if times.empty? { result: { count: times.length, avg: (times.sum / times.length).round(2), min: times.min.round(2), max: times.max.round(2), median: times.sort[times.length / 2].round(2) } } end |
#summary(proposals:) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/legion/extensions/rfp/analytics/runners/metrics.rb', line 39 def summary(proposals:, **) total = proposals.length won = proposals.count { |p| p[:outcome] == :won } lost = proposals.count { |p| p[:outcome] == :lost } pending = proposals.count { |p| p[:outcome] == :pending || p[:outcome].nil? } total_revenue = proposals.select { |p| p[:outcome] == :won }.sum { |p| p[:revenue].to_f } { result: { total_proposals: total, won: won, lost: lost, pending: pending, win_rate: total.positive? ? (won.to_f / (won + lost)).round(4) : 0.0, total_revenue: total_revenue } } end |