diff --git a/app/graphql/mutations/dossier_envoyer_message.rb b/app/graphql/mutations/dossier_envoyer_message.rb new file mode 100644 index 000000000..601e448de --- /dev/null +++ b/app/graphql/mutations/dossier_envoyer_message.rb @@ -0,0 +1,27 @@ +module Mutations + class DossierEnvoyerMessage < Mutations::BaseMutation + description "Envoyer un message à l'usager du dossier." + + argument :dossier_id, ID, required: true, loads: Types::DossierType + argument :instructeur_id, ID, required: true, loads: Types::ProfileType + argument :body, String, required: true + argument :attachment, ID, required: false + + field :message, Types::MessageType, null: true + field :errors, [Types::ValidationErrorType], null: true + + def resolve(dossier:, instructeur:, body:, attachment: nil) + message = CommentaireService.build(instructeur, dossier, body: body, piece_jointe: attachment) + + if message.save + { message: message } + else + { errors: message.errors.full_messages } + end + end + + def authorized?(dossier:, instructeur:, body:) + instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) + end + end +end diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index d43003eb3..b60fc03ae 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -352,6 +352,33 @@ type DossierEdge { node: Dossier } +""" +Autogenerated input type of DossierEnvoyerMessage +""" +input DossierEnvoyerMessageInput { + attachment: ID + body: String! + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + dossierId: ID! + instructeurId: ID! +} + +""" +Autogenerated return type of DossierEnvoyerMessage +""" +type DossierEnvoyerMessagePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + errors: [ValidationError!] + message: Message +} + type DossierLinkChamp implements Champ { dossier: Dossier id: ID! @@ -495,6 +522,11 @@ type Mutation { File information required to prepare a direct upload """ createDirectUpload(input: CreateDirectUploadInput!): CreateDirectUploadPayload + + """ + Envoyer un message à l'usager du dossier. + """ + dossierEnvoyerMessage(input: DossierEnvoyerMessageInput!): DossierEnvoyerMessagePayload } enum Order { @@ -806,4 +838,14 @@ enum TypeDeChamp { """ A valid URL, transported as a string """ -scalar URL \ No newline at end of file +scalar URL + +""" +Éreur de validation +""" +type ValidationError { + """ + A description of the error + """ + message: String! +} \ No newline at end of file diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index bbdb5021e..92da07a80 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -1,5 +1,7 @@ module Types class MutationType < Types::BaseObject field :create_direct_upload, mutation: Mutations::CreateDirectUpload + + field :dossier_envoyer_message, mutation: Mutations::DossierEnvoyerMessage end end diff --git a/app/graphql/types/validation_error_type.rb b/app/graphql/types/validation_error_type.rb new file mode 100644 index 000000000..7df3a6fb4 --- /dev/null +++ b/app/graphql/types/validation_error_type.rb @@ -0,0 +1,11 @@ +module Types + class ValidationErrorType < Types::BaseObject + description "Éreur de validation" + + field :message, String, "A description of the error", null: false + + def message + object + end + end +end diff --git a/app/models/commentaire.rb b/app/models/commentaire.rb index 5f7c4f11c..9a93319d4 100644 --- a/app/models/commentaire.rb +++ b/app/models/commentaire.rb @@ -10,7 +10,7 @@ class Commentaire < ApplicationRecord has_one_attached :piece_jointe - validates :body, presence: { message: "Votre message ne peut être vide" } + validates :body, presence: { message: "ne peut être vide" } default_scope { order(created_at: :asc) } scope :updated_since?, -> (date) { where('commentaires.updated_at > ?', date) } diff --git a/config/locales/models/commentaire/fr.yml b/config/locales/models/commentaire/fr.yml index 16b77c012..71ed7e25e 100644 --- a/config/locales/models/commentaire/fr.yml +++ b/config/locales/models/commentaire/fr.yml @@ -2,4 +2,5 @@ fr: activerecord: attributes: commentaire: + body: 'Votre message' file: fichier diff --git a/spec/controllers/api/v2/graphql_controller_spec.rb b/spec/controllers/api/v2/graphql_controller_spec.rb index 3d499d8e5..eb2721145 100644 --- a/spec/controllers/api/v2/graphql_controller_spec.rb +++ b/spec/controllers/api/v2/graphql_controller_spec.rb @@ -216,6 +216,81 @@ describe API::V2::GraphqlController do end context "mutations" do + describe 'dossierEnvoyerMessage' do + context 'success' do + let(:query) do + "mutation { + dossierEnvoyerMessage(input: { + dossierId: \"#{dossier.to_typed_id}\", + instructeurId: \"#{instructeur.to_typed_id}\", + body: \"Bonjour\" + }) { + message { + body + } + } + }" + end + + it "should post a message" do + expect(gql_errors).to eq(nil) + + expect(gql_data).to eq(dossierEnvoyerMessage: { + message: { + body: "Bonjour" + } + }) + end + end + + context 'schema error' do + let(:query) do + "mutation { + dossierEnvoyerMessage(input: { + dossierId: \"#{dossier.to_typed_id}\", + instructeurId: \"#{instructeur.to_typed_id}\" + }) { + message { + body + } + } + }" + end + + it "should fail" do + expect(gql_data).to eq(nil) + expect(gql_errors).not_to eq(nil) + end + end + + context 'validation error' do + let(:query) do + "mutation { + dossierEnvoyerMessage(input: { + dossierId: \"#{dossier.to_typed_id}\", + instructeurId: \"#{instructeur.to_typed_id}\", + body: \"\" + }) { + message { + body + } + errors { + message + } + } + }" + end + + it "should fail" do + expect(gql_errors).to eq(nil) + expect(gql_data).to eq(dossierEnvoyerMessage: { + errors: [{ message: "Votre message ne peut être vide" }], + message: nil + }) + end + end + end + context 'createDirectUpload' do let(:query) do "mutation { @@ -263,5 +338,26 @@ describe API::V2::GraphqlController do expect(gql_errors).not_to eq(nil) end end + + context "mutation" do + let(:query) do + "mutation { + dossierEnvoyerMessage(input: { + dossierId: \"#{dossier.to_typed_id}\", + instructeurId: \"#{instructeur.to_typed_id}\", + body: \"Bonjour\" + }) { + message { + body + } + } + }" + end + + it "should return error" do + expect(gql_data[:dossierEnvoyerMessage]).to eq(nil) + expect(gql_errors).not_to eq(nil) + end + end end end