2019-11-12-01 (#4507)

2019-11-12-01
This commit is contained in:
Pierre de La Morinerie 2019-11-12 13:58:31 +01:00 committed by GitHub
commit b8a9e737a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 140 additions and 70 deletions

View file

@ -53,7 +53,7 @@ class API::V1::DossiersController < APIController
end
order = ORDER_DIRECTIONS.fetch(params[:order], :asc)
@dossiers = @procedure.dossiers.state_not_brouillon.order_for_api(order)
@dossiers = @procedure.dossiers.state_not_brouillon.order_by_created_at(order)
rescue ActiveRecord::RecordNotFound
render json: {}, status: :not_found

View file

@ -128,25 +128,35 @@ type Demarche {
"""
before: String
"""
Dossiers déposés depuis la date.
"""
createdSince: ISO8601DateTime
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Filtrer les dossiers par ID.
"""
ids: [ID!]
"""
Returns the last _n_ elements from the list.
"""
last: Int
"""
Dossiers crées depuis la date.
L'ordre des dossiers.
"""
since: ISO8601DateTime
order: Order = ASC
"""
Dossiers avec statut.
"""
state: DossierState
"""
Dossiers mis à jour depuis la date.
"""
updatedSince: ISO8601DateTime
): DossierConnection!
groupeInstructeurs: [GroupeInstructeur!]!
id: ID!
@ -401,6 +411,18 @@ type Mutation {
createDirectUpload(input: CreateDirectUploadInput!): CreateDirectUploadPayload
}
enum Order {
"""
Lordre ascendant.
"""
ASC
"""
Lordre descendant.
"""
DESC
}
"""
Information about pagination in a connection.
"""

View file

@ -21,8 +21,10 @@ module Types
field :groupe_instructeurs, [Types::GroupeInstructeurType], null: false
field :dossiers, Types::DossierType.connection_type, "Liste de tous les dossiers d'une démarche.", null: false do
argument :ids, [ID], required: false, description: "Filtrer les dossiers par ID."
argument :since, GraphQL::Types::ISO8601DateTime, required: false, description: "Dossiers crées depuis la date."
argument :order, Types::Order, default_value: :asc, required: false, description: "L'ordre des dossiers."
argument :created_since, GraphQL::Types::ISO8601DateTime, required: false, description: "Dossiers déposés depuis la date."
argument :updated_since, GraphQL::Types::ISO8601DateTime, required: false, description: "Dossiers mis à jour depuis la date."
argument :state, Types::DossierType::DossierState, required: false, description: "Dossiers avec statut."
end
field :champ_descriptors, [Types::ChampDescriptorType], null: false, method: :types_de_champ
@ -36,15 +38,21 @@ module Types
Loaders::Association.for(object.class, groupe_instructeurs: { procedure: [:administrateurs] }).load(object)
end
def dossiers(ids: nil, since: nil)
dossiers = object.dossiers.for_api_v2
def dossiers(updated_since: nil, created_since: nil, state: nil, order:)
dossiers = object.dossiers.state_not_brouillon.for_api_v2
if ids.present?
dossiers = dossiers.where(id: ids)
if state.present?
dossiers = dossiers.where(state: state)
end
if since.present?
dossiers = dossiers.since(since)
if updated_since.present?
dossiers = dossiers.updated_since(updated_since).order_by_updated_at(order)
else
if created_since.present?
dossiers = dossiers.created_since(created_since)
end
dossiers = dossiers.order_by_created_at(order)
end
dossiers

View file

@ -0,0 +1,6 @@
module Types
class Order < Types::BaseEnum
value('ASC', 'Lordre ascendant.', value: :asc)
value('DESC', 'Lordre descendant.', value: :desc)
end
end

View file

@ -0,0 +1,4 @@
module ActiveStorage
# activestorage-openstack uses ActiveStorage::FileNotFoundError which only exists in rails 6
class FileNotFoundError < StandardError; end
end

View file

@ -105,7 +105,9 @@ class Dossier < ApplicationRecord
scope :not_archived, -> { where(archived: false) }
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
scope :order_for_api, -> (order = :asc) { order(en_construction_at: order, created_at: order, id: order) }
scope :order_by_created_at, -> (order = :asc) { order(en_construction_at: order, created_at: order, id: order) }
scope :updated_since, -> (since) { where('dossiers.updated_at >= ?', since) }
scope :created_since, -> (since) { where('dossiers.en_construction_at >= ?', since) }
scope :all_state, -> { not_archived.state_not_brouillon }
scope :en_construction, -> { not_archived.state_en_construction }
@ -134,7 +136,6 @@ class Dossier < ApplicationRecord
scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) }
scope :with_champs, -> { includes(champs: :type_de_champ) }
scope :nearing_end_of_retention, -> (duration = '1 month') { joins(:procedure).where("en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - now() < interval ?", duration) }
scope :since, -> (since) { where('dossiers.en_construction_at >= ?', since) }
scope :for_api, -> {
includes(commentaires: { piece_jointe_attachment: :blob },
champs: [

View file

@ -444,7 +444,7 @@ class Procedure < ApplicationRecord
version = options.delete(:version)
if version == 'v2'
options.delete(:tables)
ProcedureExportV2Service.new(self, dossiers, **options.to_h.symbolize_keys)
ProcedureExportV2Service.new(self, dossiers)
else
ProcedureExportService.new(self, dossiers, **options.to_h.symbolize_keys)
end

View file

@ -49,7 +49,7 @@ class ProcedureExportService
:prenom
]
def initialize(procedure, dossiers, tables: [], ids: nil, since: nil, limit: nil)
def initialize(procedure, dossiers, tables: [])
@procedure = procedure
@attributes = ATTRIBUTES.dup
@ -59,15 +59,6 @@ class ProcedureExportService
end
@dossiers = dossiers.downloadable_sorted
if ids
@dossiers = @dossiers.where(id: ids)
end
if since
@dossiers = @dossiers.since(since)
end
if limit
@dossiers = @dossiers.limit(limit)
end
@dossiers = @dossiers.to_a
@tables = tables.map(&:to_sym)
end

View file

@ -1,18 +1,9 @@
class ProcedureExportV2Service
attr_reader :dossiers
def initialize(procedure, dossiers, ids: nil, since: nil, limit: nil)
def initialize(procedure, dossiers)
@procedure = procedure
@dossiers = dossiers.downloadable_sorted
if ids
@dossiers = @dossiers.where(id: ids)
end
if since
@dossiers = @dossiers.since(since)
end
if limit
@dossiers = @dossiers.limit(limit)
end
@tables = [:dossiers, :etablissements, :avis] + champs_repetables_options
end

View file

@ -1,9 +1,8 @@
Rails.application.config.content_security_policy do |policy|
# En cas de non respect d'une des règles, faire un POST sur cette URL
if Rails.env.production?
policy.report_uri "https://demarchessimplifieestest.report-uri.com/r/d/csp/reportOnly"
else
policy.report_uri "http://#{ENV['APP_HOST']}/csp/" # ne pas notifier report-uri en dev/test
if Rails.env.development?
# les CSP ne sont pas appliquées en dev: on notifie cependant une url quelconque de la violation
# pour détecter les erreurs lors de l'ajout d'une nouvelle brique externe durant le développement
policy.report_uri "http://#{ENV['APP_HOST']}/csp/"
end
# Whitelist image
policy.img_src :self, "*.openstreetmap.org", "static.demarches-simplifiees.fr", "*.cloud.ovh.net", "stats.data.gouv.fr", "*", :data

View file

@ -12,6 +12,15 @@ describe API::V2::GraphqlController do
create(:commentaire, dossier: dossier, email: 'test@test.com')
dossier
end
let(:dossier1) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: 1.day.ago) }
let(:dossier2) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: 3.days.ago) }
let!(:dossier_brouillon) { create(:dossier, procedure: procedure) }
let(:dossiers) { [dossier2, dossier1, dossier] }
let(:instructeur) { create(:instructeur, followed_dossiers: dossiers) }
before do
instructeur.assign_to_procedure(procedure)
end
let(:query) do
"{
@ -62,31 +71,65 @@ describe API::V2::GraphqlController do
request.env['HTTP_AUTHORIZATION'] = authorization_header
end
it "should return demarche" do
expect(gql_errors).to eq(nil)
expect(gql_data).to eq(demarche: {
id: procedure.to_typed_id,
number: procedure.id.to_s,
title: procedure.libelle,
description: procedure.description,
state: 'brouillon',
archivedAt: nil,
createdAt: procedure.created_at.iso8601,
updatedAt: procedure.updated_at.iso8601,
groupeInstructeurs: [{ instructeurs: [], label: "défaut" }],
champDescriptors: procedure.types_de_champ.map do |tdc|
{
id: tdc.to_typed_id,
label: tdc.libelle,
type: tdc.type_champ,
description: tdc.description,
required: tdc.mandatory?
context "demarche" do
it "should be returned" do
expect(gql_errors).to eq(nil)
expect(gql_data).to eq(demarche: {
id: procedure.to_typed_id,
number: procedure.id.to_s,
title: procedure.libelle,
description: procedure.description,
state: 'brouillon',
archivedAt: nil,
createdAt: procedure.created_at.iso8601,
updatedAt: procedure.updated_at.iso8601,
groupeInstructeurs: [
{
instructeurs: [{ email: instructeur.email }],
label: "défaut"
}
],
champDescriptors: procedure.types_de_champ.map do |tdc|
{
id: tdc.to_typed_id,
label: tdc.libelle,
type: tdc.type_champ,
description: tdc.description,
required: tdc.mandatory?
}
end,
dossiers: {
nodes: dossiers.map { |dossier| { id: dossier.to_typed_id } }
}
end,
dossiers: {
nodes: []
}
})
})
end
context "filter dossiers" do
let(:query) do
"{
demarche(number: #{procedure.id}) {
id
number
dossiers(createdSince: \"#{2.days.ago.iso8601}\") {
nodes {
id
}
}
}
}"
end
it "should be returned" do
expect(gql_errors).to eq(nil)
expect(gql_data).to eq(demarche: {
id: procedure.to_typed_id,
number: procedure.id.to_s,
dossiers: {
nodes: [{ id: dossier1.to_typed_id }, { id: dossier.to_typed_id }]
}
})
end
end
end
context "dossier" do
@ -130,7 +173,7 @@ describe API::V2::GraphqlController do
}"
end
it "should return dossier" do
it "should be returned" do
expect(gql_errors).to eq(nil)
expect(gql_data).to eq(dossier: {
id: dossier.to_typed_id,
@ -146,7 +189,12 @@ describe API::V2::GraphqlController do
id: dossier.user.to_typed_id,
email: dossier.user.email
},
instructeurs: [],
instructeurs: [
{
id: instructeur.to_typed_id,
email: instructeur.email
}
],
messages: dossier.commentaires.map do |commentaire|
{
body: commentaire.body,