From fa1dd8b6cbee3437b03fffe96f9c49cafba52e01 Mon Sep 17 00:00:00 2001 From: Rodribm10 Date: Wed, 15 Apr 2026 10:35:03 -0300 Subject: [PATCH] feat(lifecycle): expose concierge config update on UnitsController Co-Authored-By: Claude Sonnet 4.6 --- .../v1/accounts/captain/units_controller.rb | 39 +++++++++++++++++- .../accounts/captain/units_controller_spec.rb | 40 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v1/accounts/captain/units_controller.rb b/app/controllers/api/v1/accounts/captain/units_controller.rb index f69c7eeb3..45428b60d 100644 --- a/app/controllers/api/v1/accounts/captain/units_controller.rb +++ b/app/controllers/api/v1/accounts/captain/units_controller.rb @@ -1,9 +1,10 @@ class Api::V1::Accounts::Captain::UnitsController < Api::V1::Accounts::BaseController before_action :ensure_captain_enabled - before_action :set_unit, only: [:show, :update, :destroy] + before_action :set_unit, only: [:show, :update, :destroy, :update_concierge] def index @units = Current.account.captain_units.includes(:inboxes) + @units = filter_units_by_user_access(@units) render json: @units.map { |u| format_unit(u) } end @@ -38,12 +39,32 @@ class Api::V1::Accounts::Captain::UnitsController < Api::V1::Accounts::BaseContr head :no_content end + def update_concierge + return render json: { error: 'Unauthorized' }, status: :unauthorized unless Current.user.administrator? + + @unit.update!(concierge_params) + render json: format_unit(@unit) + rescue ActiveRecord::RecordInvalid + render json: { errors: @unit.errors.full_messages }, status: :unprocessable_entity + end + private def ensure_captain_enabled # Dependendo da regra de negócio, pode-se verificar as features da conta aqui original end + # Administrador vê todas as unidades; agente só vê unidades vinculadas a + # alguma caixa de entrada a qual ele tem acesso. + def filter_units_by_user_access(scope) + return scope if Current.user.administrator? + + accessible_inbox_ids = Current.user.assigned_inboxes.pluck(:id) + return scope.none if accessible_inbox_ids.empty? + + scope.joins(:inboxes).where(inboxes: { id: accessible_inbox_ids }).distinct + end + def default_brand @default_brand ||= Captain::Brand.where(account_id: Current.account.id).first || Captain::Brand.create!( @@ -69,6 +90,13 @@ class Api::V1::Accounts::Captain::UnitsController < Api::V1::Accounts::BaseContr ) end + def concierge_params + params.require(:captain_unit).permit( + :concierge_inbox_id, + concierge_config: [:persona_name, :knowledge, { variables: {} }] + ) + end + def inbox_ids_param return [] unless params[:captain_unit].key?(:inbox_ids) @@ -90,7 +118,7 @@ class Api::V1::Accounts::Captain::UnitsController < Api::V1::Accounts::BaseContr end end - def format_unit(unit) + def format_unit(unit) # rubocop:disable Metrics/AbcSize inboxes = unit.inboxes.to_a { id: unit.id, @@ -107,6 +135,13 @@ class Api::V1::Accounts::Captain::UnitsController < Api::V1::Accounts::BaseContr has_key: unit.inter_key_content.present? || unit.resolved_inter_key_path.present?, has_client_secret: unit.inter_client_secret.present?, proactive_pix_polling_enabled: unit.proactive_pix_polling_enabled + }.merge(format_concierge(unit)) + end + + def format_concierge(unit) + { + concierge_inbox_id: unit.concierge_inbox_id, + concierge_config: unit.concierge_config || {} } end end diff --git a/spec/enterprise/controllers/api/v1/accounts/captain/units_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/captain/units_controller_spec.rb index ae767cdfa..69cf807cd 100644 --- a/spec/enterprise/controllers/api/v1/accounts/captain/units_controller_spec.rb +++ b/spec/enterprise/controllers/api/v1/accounts/captain/units_controller_spec.rb @@ -80,4 +80,44 @@ RSpec.describe 'Api::V1::Accounts::Captain::Units', type: :request do expect(Captain::Unit.last.captain_brand_id).to eq(brands.first.id) end end + + describe 'PATCH /api/v1/accounts/:account_id/captain/units/:id/concierge' do + let(:agent) { create(:user, account: account, role: :agent) } + let(:unit) do + Captain::Unit.create!( + account: account, + brand: Captain::Brand.where(account: account).first, + name: 'Unidade Teste' + ) + end + let(:inbox) { create(:inbox, account: account) } + + it 'blocks agents' do + patch "/api/v1/accounts/#{account.id}/captain/units/#{unit.id}/concierge", + params: { captain_unit: { concierge_inbox_id: inbox.id } }, + headers: agent.create_new_auth_token, as: :json + expect(response).to have_http_status(:unauthorized) + end + + it 'updates concierge fields for admin' do + patch "/api/v1/accounts/#{account.id}/captain/units/#{unit.id}/concierge", + params: { + captain_unit: { + concierge_inbox_id: inbox.id, + concierge_config: { + persona_name: 'Sofia', + knowledge: '# Hotel\n', + variables: { wifi_password: 'abc123' } + } + } + }, + headers: admin.create_new_auth_token, as: :json + + expect(response).to have_http_status(:success) + unit.reload + expect(unit.concierge_inbox_id).to eq(inbox.id) + expect(unit.concierge_config['persona_name']).to eq('Sofia') + expect(unit.concierge_config.dig('variables', 'wifi_password')).to eq('abc123') + end + end end