diff --git a/README.md b/README.md index 191eb6a..a3b1af0 100644 --- a/README.md +++ b/README.md @@ -601,7 +601,7 @@ Successful response for users without saved contacts: ``` #### Create a contact with required and optional fields. -New contacts require a unique first and last name. All other fields are optional. +***New contacts require a unique first and last name. All other fields are optional.*** Request: ``` @@ -644,6 +644,45 @@ Status: 201 created } ``` +#### Create a contact with a company name from the dropdown box +***New contacts with company name require a unique first and last name, and company ID in the URI. All other fields are optional.*** + +Request: +``` +POST api/v1/users/:user_id/companies/:company_id/contacts + +Authorization: Bearer Token - put in token for user + +raw json body with all fields: + +{ + "data": [ + { + "id": "1", + "type": "contacts", + "attributes": { + "first_name": "Jane", + "last_name": "Doe", + "company_id": 2, + "email": "", + "phone_number": "", + "notes": "", + "user_id": 2, + "company": { + "id": 2, + "name": "Future Designs LLC", + "website": "https://futuredesigns.com", + "street_address": "456 Future Blvd", + "city": "Austin", + "state": "TX", + "zip_code": "73301", + "notes": "Submitted application for the UI Designer role." + } + } + } + ] + }, + ``` #### Contact Errors 401 Error Response if no token provided: diff --git a/app/controllers/api/v1/contacts_controller.rb b/app/controllers/api/v1/contacts_controller.rb index 708af18..febdb90 100644 --- a/app/controllers/api/v1/contacts_controller.rb +++ b/app/controllers/api/v1/contacts_controller.rb @@ -26,33 +26,31 @@ def index end end - def show - company = @current_user.companies.find_by(id: params[:id]) - authorize company - - if company - contacts = company.contacts - render json: { company: CompanySerializer.new(company), contacts: ContactSerializer.new(contacts) } + def create + authorize Contact + if params[:company_id] + company = @current_user.companies.find_by(id: params[:company_id]) + if company + contact = company.contacts.new(contact_params.merge(user_id: @current_user.id)) + else + return render json: { error: "Company not found" }, status: :not_found + end else - render json: { error: "Company not found or unauthorized access" }, status: :not_found + contact = @current_user.contacts.new(contact_params) + end + + if contact.save + render json: ContactsSerializer.new(contact), status: :created + else + render json: { error: contact.errors.full_messages.to_sentence }, status: :unprocessable_entity end end - def create - authorize Contact - contact = @current_user.contacts.new(contact_params) - if contact.save - render json: ContactsSerializer.new(contact), status: :created - else - render json: { error: contact.errors.full_messages.to_sentence }, status: :unprocessable_entity - end - end + private - private - - def contact_params - params.require(:contact).permit(:first_name, :last_name, :company_id, :email, :phone_number, :notes) - end + def contact_params + params.require(:contact).permit(:first_name, :last_name, :company_id, :email, :phone_number, :notes) + end end end end diff --git a/app/serializers/contacts_serializer.rb b/app/serializers/contacts_serializer.rb index 19e0f80..d87ad14 100644 --- a/app/serializers/contacts_serializer.rb +++ b/app/serializers/contacts_serializer.rb @@ -1,4 +1,22 @@ class ContactsSerializer include JSONAPI::Serializer attributes :first_name, :last_name, :company_id, :email, :phone_number, :notes, :user_id + + attribute :company do |object| + company = object.company + if company + { + id: company.id, + name: company.name, + website: company.website, + street_address: company.street_address, + city: company.city, + state: company.state, + zip_code: company.zip_code, + notes: company.notes + } + else + nil + end + end end diff --git a/config/routes.rb b/config/routes.rb index b7c0b08..f0fc3d1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,11 +10,12 @@ namespace :api do namespace :v1 do resources :users, only: [:create, :index, :show, :update] do - resources :contacts, only: [:create, :index] + resources :job_applications, only: [:create, :index, :show] - resources :companies, only: [:create, :index, :show] do - resources :contacts, only: [:index] + resources :companies, only: [:create, :index] do + resources :contacts, only: [:create, :index] end + resources :contacts, only: [:index, :create] resource :dashboard, only: :show end @@ -22,3 +23,4 @@ end end end + diff --git a/spec/requests/api/v1/contacts/create_spec.rb b/spec/requests/api/v1/contacts/create_spec.rb index 685aab7..80e47a5 100644 --- a/spec/requests/api/v1/contacts/create_spec.rb +++ b/spec/requests/api/v1/contacts/create_spec.rb @@ -81,6 +81,18 @@ expect(json[:attributes][:last_name]).to eq("Smith") expect(json[:attributes][:phone_number]).to eq("123-555-6789") end + + it 'creates a contact when given the company ID, returns a 201' do + minimal_params = { contact: {first_name: "John", last_name: "Smith" } } + post api_v1_user_company_contacts_path(user_id: @user1.id, company_id: @company.id), params: minimal_params , headers: { "Authorization" => "Bearer #{@token}" }, as: :json + + expect(response).to have_http_status(:created) + json = JSON.parse(response.body, symbolize_names: true)[:data] + + expect(json[:attributes][:first_name]).to eq("John") + expect(json[:attributes][:last_name]).to eq("Smith") + expect(json[:attributes][:company][:name]).to eq("Turing") + end end context "when the request is invalid - Sad Paths" do @@ -154,6 +166,16 @@ json = JSON.parse(response.body, symbolize_names: true) expect(json[:error]).to eq("Phone number must be in the format '555-555-5555'") end + + it 'returns a 404 error when a company is not found by ID number' do + minimal_params = { contact: {first_name: "John", last_name: "Smith" } } + post api_v1_user_company_contacts_path(user_id: @user1.id, company_id: 99999), params: minimal_params , headers: { "Authorization" => "Bearer #{@token}" }, as: :json + + expect(response).to have_http_status(:not_found) + json = JSON.parse(response.body, symbolize_names: true) + + expect(json[:error]).to eq("Company not found") + end end context "edge cases - Sad Paths" do diff --git a/spec/requests/api/v1/contacts/index_spec.rb b/spec/requests/api/v1/contacts/index_spec.rb index ca4a07e..2982bdd 100644 --- a/spec/requests/api/v1/contacts/index_spec.rb +++ b/spec/requests/api/v1/contacts/index_spec.rb @@ -40,11 +40,27 @@ expect(json[:data]).to eq([]) expect(json[:message]).to eq("No contacts found") end + + it "should return 200 and all contacts associated with a company" do + get api_v1_user_company_contacts_path(user_id: @user.id, company_id: @company.id), headers: { "Authorization" => "Bearer #{@token}" }, as: :json + + expect(response).to be_successful + expect(response).to have_http_status(:ok) + json = JSON.parse(response.body, symbolize_names: true) + + expect(json[:company][:data][:attributes][:name]).to eq("Turing") + expect(json[:contacts][:data][0][:attributes][:last_name]).to eq("Smith") + + end end context "Sad Paths" do before(:each) do @user = User.create!(name: "Me", email: "its_me", password: "reallyGoodPass") + @company = Company.create!(name: "Turing", website: "www.turing.com", street_address: "123 Main St", city: "Denver", state: "CO", zip_code: "80218", user_id: @user.id) + user_params = { email: "its_me", password: "reallyGoodPass" } + post api_v1_sessions_path, params: user_params, as: :json + @token = JSON.parse(response.body)["token"] end it "returns a 403 and an error message if no token is provided" do @@ -76,6 +92,16 @@ expect(json[:error]).to eq("Not authenticated") end + + it "returns a 404 and an error message if company ID is not found" do + get api_v1_user_company_contacts_path(user_id: @user.id, company_id: 99999), headers: { "Authorization" => "Bearer #{@token}" }, as: :json + + expect(response).to_not be_successful + expect(response).to have_http_status(:not_found) + json = JSON.parse(response.body, symbolize_names: true) + + expect(json[:error]).to eq("Company not found or unauthorized access") + end end end end \ No newline at end of file