Merge branch 'develop'
This commit is contained in:
commit
4a04c3f0d4
150 changed files with 2416 additions and 733 deletions
|
@ -64,7 +64,7 @@ jobs:
|
|||
- "0a:67:42:7d:7e:b7:e1:3c:48:8f:bf:68:10:51:a8:44"
|
||||
- deploy:
|
||||
command: |
|
||||
if [ "${CIRCLE_BRANCH}" == "staging" ]; then
|
||||
if [ "${CIRCLE_BRANCH}" == "develop" ]; then
|
||||
bundle exec rake deploy_ha
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
exclude: 'app/assets/stylesheets/reset.scss'
|
||||
exclude: 'app/assets/stylesheets/new_design/reset.scss'
|
||||
|
||||
linters:
|
||||
BangFormat:
|
||||
|
|
BIN
app/assets/images/mailer/gestionnaire_mailer/logo.png
Executable file
BIN
app/assets/images/mailer/gestionnaire_mailer/logo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
|
@ -3,5 +3,3 @@ $light-blue: #F2F6FA;
|
|||
|
||||
// Bootstrap constants
|
||||
$font-size-base: 16px;
|
||||
|
||||
$page-width: 1040px;
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
%horizontal-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
%horizontal-list-item {
|
||||
display: inline-block;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
|
@ -13,13 +13,8 @@
|
|||
// file per style scope.
|
||||
//
|
||||
// = require _card
|
||||
// = require _colors
|
||||
// = require _constants
|
||||
// = require _helpers
|
||||
// = require _mixins
|
||||
// = require _placeholders
|
||||
// = require _turbolinks
|
||||
// = require _typography
|
||||
// = require admin_procedures_modal
|
||||
// = require admin_type_de_champ
|
||||
// = require backoffice
|
||||
|
@ -31,9 +26,7 @@
|
|||
// = require dossier_show
|
||||
// = require dossiers
|
||||
// = require etapes
|
||||
// = require fonts
|
||||
// = require france_connect_particulier
|
||||
// = require landing
|
||||
// = require left_panel
|
||||
// = require login
|
||||
// = require main_container
|
||||
|
@ -47,7 +40,6 @@
|
|||
// = require recapitulatif
|
||||
// = require search
|
||||
// = require siret
|
||||
// = require stats
|
||||
// = require support_navigator_banner
|
||||
// = require switch_menu
|
||||
// = require typeahead
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
// = require reset
|
||||
// = require custom_reset
|
||||
// = require common
|
||||
// = require utils
|
||||
// = require fonts
|
||||
// = require new_alert
|
||||
// = require new_header
|
||||
// = require new_footer
|
||||
// = require landing
|
||||
// = require navbar
|
3
app/assets/stylesheets/new_design/_constants.scss
Normal file
3
app/assets/stylesheets/new_design/_constants.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
$page-width: 1040px;
|
||||
|
||||
$default-padding: 15px;
|
21
app/assets/stylesheets/new_design/_placeholders.scss
Normal file
21
app/assets/stylesheets/new_design/_placeholders.scss
Normal file
|
@ -0,0 +1,21 @@
|
|||
@import "constants";
|
||||
@import "mixins";
|
||||
|
||||
%horizontal-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
%horizontal-list-item {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
%page-width-container {
|
||||
@include horizontal-padding($default-padding);
|
||||
max-width: $page-width + 2 * $default-padding;
|
||||
margin: 0 auto;
|
||||
}
|
91
app/assets/stylesheets/new_design/avis_sign_up.scss
Normal file
91
app/assets/stylesheets/new_design/avis_sign_up.scss
Normal file
|
@ -0,0 +1,91 @@
|
|||
@import "typography";
|
||||
@import "colors";
|
||||
|
||||
.avis-sign-up {
|
||||
display: flex;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
width: 50%;
|
||||
padding: 60px 86px;
|
||||
}
|
||||
|
||||
.left {
|
||||
p {
|
||||
margin: auto;
|
||||
max-width: 410px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 30px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.dossier {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
background-color: $light-grey;
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
form {
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
label,
|
||||
input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
input {
|
||||
border: solid 1px $border-grey;
|
||||
border-radius: 4px;
|
||||
height: 56px;
|
||||
padding: 0 15px;
|
||||
font-family: Muli;
|
||||
font-size: 14px;
|
||||
|
||||
&:disabled {
|
||||
background-color: $border-grey;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-block;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
border: none;
|
||||
border-radius: 60px;
|
||||
background-color: $blue;
|
||||
color: #FFFFFF;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin: 55px 0;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
background-color: $light-blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
app/assets/stylesheets/new_design/beta.scss
Normal file
15
app/assets/stylesheets/new_design/beta.scss
Normal file
|
@ -0,0 +1,15 @@
|
|||
#beta {
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
position: fixed;
|
||||
bottom: 26px;
|
||||
right: -35px;
|
||||
transform: rotate(-45deg);
|
||||
width: 150px;
|
||||
background-color: #008CBA;
|
||||
color: #FFFFFF;
|
||||
padding: 5px;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
z-index: 10;
|
||||
}
|
|
@ -12,12 +12,30 @@
|
|||
}
|
||||
|
||||
.landing-panel-inner-content {
|
||||
width: $page-width;
|
||||
margin: 0 auto;
|
||||
@extend %page-width-container;
|
||||
}
|
||||
|
||||
$landing-breakpoint: 1040px;
|
||||
|
||||
.hero-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-text {
|
||||
max-width: 500px;
|
||||
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-tagline {
|
||||
width: 500px;
|
||||
font-size: 30px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
@ -29,12 +47,16 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hero-text {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.hero-illustration {
|
||||
width: 500px;
|
||||
max-width: 500px;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 1030px) {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-button {
|
||||
|
@ -69,6 +91,7 @@
|
|||
}
|
||||
|
||||
.landing-panel-title {
|
||||
width: 100%;
|
||||
font-size: 30px;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
|
@ -86,15 +109,22 @@
|
|||
|
||||
.features {
|
||||
@extend %horizontal-list;
|
||||
}
|
||||
width: 100%;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
|
||||
$feature-width: 320px;
|
||||
$features-count: 3;
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.feature {
|
||||
@extend %horizontal-list-item;
|
||||
width: $feature-width;
|
||||
margin-right: calc((#{$page-width} - (#{$feature-width} * #{$features-count})) / (#{$features-count} - 1));
|
||||
width: 320px;
|
||||
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
margin: 15px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-text {
|
||||
|
@ -116,18 +146,27 @@ $features-count: 3;
|
|||
|
||||
.quotes {
|
||||
@extend %horizontal-list;
|
||||
}
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
$quote-width: 500px;
|
||||
$quote-count: 2;
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.quote {
|
||||
@extend %horizontal-list-item;
|
||||
width: $quote-width;
|
||||
margin-right: calc((#{$page-width} - (#{$quote-width} * #{$quote-count}))/ (#{$quote-count} - 1));
|
||||
max-width: 500px;
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 4px 16px 0 rgba(153, 153, 153, 0.2);
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
margin: 15px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.quote-quotation-mark {
|
||||
|
@ -136,13 +175,16 @@ $quote-count: 2;
|
|||
|
||||
.quote-content {
|
||||
font-size: 18px;
|
||||
width: 388px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.quote-content-wrapper {
|
||||
margin-left: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.quote-author {
|
||||
font-size: 14px;
|
||||
margin-left: 64px;
|
||||
}
|
||||
|
||||
.quote-author-name {
|
||||
|
@ -155,16 +197,18 @@ $quote-count: 2;
|
|||
|
||||
.numbers {
|
||||
@extend %horizontal-list;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
$number-width: 320px;
|
||||
$number-count: 3;
|
||||
|
||||
.number {
|
||||
@extend %horizontal-list-item;
|
||||
width: $number-width;
|
||||
margin-right: calc((#{$page-width} - (#{$number-width} * #{$number-count}))/ (#{$number-count} - 1));
|
||||
width: 320px;
|
||||
text-align: center;
|
||||
|
||||
@media (max-width: $landing-breakpoint) {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.number-value {
|
||||
|
@ -178,25 +222,33 @@ $number-count: 3;
|
|||
font-size: 20px;
|
||||
}
|
||||
|
||||
$users-breakpoint: 950px;
|
||||
|
||||
.users {
|
||||
@extend %horizontal-list;
|
||||
}
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
$image-width: 170px;
|
||||
$images-total-width: $image-width * 5;
|
||||
$images-count: 5;
|
||||
@media (max-width: $users-breakpoint) {
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
|
||||
.user {
|
||||
@extend %horizontal-list-item;
|
||||
margin-right: calc((#{$page-width} - (#{$images-total-width}))/ (#{$images-count} - 1));
|
||||
width: 170px;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@media (max-width: $users-breakpoint) {
|
||||
margin: 0 15px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-image {
|
||||
width: $image-width;
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
.cta-panel {
|
||||
|
@ -204,6 +256,13 @@ $images-count: 5;
|
|||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.cta-panel-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cta-panel-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
|
@ -212,22 +271,21 @@ $images-count: 5;
|
|||
|
||||
.cta-panel-explanation {
|
||||
font-size: 24px;
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
$cta-panel-button-height: 60px;
|
||||
$cta-panel-button-border-size: 2px;
|
||||
|
||||
.cta-panel-button {
|
||||
@include horizontal-padding(30px);
|
||||
|
||||
display: block;
|
||||
height: $cta-panel-button-height;
|
||||
line-height: $cta-panel-button-height - (2 * $cta-panel-button-border-size);
|
||||
border-radius: $cta-panel-button-height;
|
||||
padding: 10px;
|
||||
border-radius: 100px;
|
||||
border: $cta-panel-button-border-size solid #FFFFFF;
|
||||
color: #FFFFFF;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
6
app/assets/stylesheets/new_design/new_application.scss
Normal file
6
app/assets/stylesheets/new_design/new_application.scss
Normal file
|
@ -0,0 +1,6 @@
|
|||
// = require ./reset
|
||||
// = require ./custom_reset
|
||||
// = require ./common
|
||||
// = require ./utils
|
||||
// = require ./fonts
|
||||
// = require_tree .
|
|
@ -10,23 +10,25 @@
|
|||
}
|
||||
|
||||
.footer-inner-content {
|
||||
width: $page-width;
|
||||
margin: 0 auto;
|
||||
@extend %page-width-container;
|
||||
}
|
||||
|
||||
.footer-columns {
|
||||
@extend %horizontal-list;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
$footer-column-width: 320px;
|
||||
$footer-column-count: 3;
|
||||
|
||||
.footer-column {
|
||||
@extend %horizontal-list-item;
|
||||
width: $footer-column-width;
|
||||
margin-right: calc((#{$page-width} - (#{$footer-column-width} * #{$footer-column-count})) / (#{$footer-column-count} - 1));
|
||||
font-size: 14px;
|
||||
vertical-align: top;
|
||||
flex-grow: 1;
|
||||
min-width: 320px;
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
width: 100%;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-logos,
|
|
@ -1,6 +1,7 @@
|
|||
@import "constants";
|
||||
@import "colors";
|
||||
@import "mixins";
|
||||
@import "placeholders";
|
||||
|
||||
// FIXME: Rename when the header is generalized
|
||||
.new-header {
|
||||
|
@ -13,8 +14,9 @@
|
|||
}
|
||||
|
||||
.header-inner-content {
|
||||
width: $page-width;
|
||||
margin: 0 auto;
|
||||
@extend %page-width-container;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header-logo {
|
|
@ -1,5 +1,3 @@
|
|||
@import "card";
|
||||
|
||||
$dark-grey: #333333;
|
||||
$light-grey: #999999;
|
||||
$blue: rgba(61, 149, 236, 1);
|
||||
|
@ -8,12 +6,23 @@ $blue-hover: rgba(61, 149, 236, 0.8);
|
|||
$default-space: 15px;
|
||||
|
||||
$new-h1-margin-bottom: 4 * $default-space;
|
||||
$new-h2-margin-bottom: 3 * $default-space;
|
||||
|
||||
.new-h1 {
|
||||
.new-h1,
|
||||
.new-h2 {
|
||||
color: $dark-grey;
|
||||
text-align: center;
|
||||
margin-top: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.new-h1 {
|
||||
margin-bottom: $new-h1-margin-bottom;
|
||||
font-size: 41px;
|
||||
}
|
||||
|
||||
.new-h2 {
|
||||
margin-bottom: $new-h2-margin-bottom;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
$statistiques-padding-top: $default-space * 2;
|
||||
|
@ -33,6 +42,7 @@ $statistiques-padding-top: $default-space * 2;
|
|||
$stat-card-margin-bottom: 3 * $default-space;
|
||||
|
||||
.stat-card {
|
||||
padding: 15px;
|
||||
margin-bottom: $stat-card-margin-bottom;
|
||||
border-radius: 5px;
|
||||
box-shadow: none;
|
||||
|
@ -49,7 +59,7 @@ $stat-card-half-horizontal-spacing: 4 * $default-space;
|
|||
.stat-card-title {
|
||||
color: $dark-grey;
|
||||
font-size: 26px;
|
||||
font-weight: 500;
|
||||
font-weight: bold;
|
||||
width: 200px;
|
||||
}
|
||||
|
|
@ -13,3 +13,7 @@
|
|||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
|
@ -2,29 +2,33 @@ class Admin::MailTemplatesController < AdminController
|
|||
before_action :retrieve_procedure
|
||||
|
||||
def index
|
||||
@mails = mails
|
||||
@mail_templates = mail_templates
|
||||
end
|
||||
|
||||
def edit
|
||||
@mail_template = find_the_right_mail params[:id]
|
||||
@mail_template_name = params[:id]
|
||||
@mail_template = find_mail_template_by_slug(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
mail_template = find_the_right_mail params[:id]
|
||||
mail_template = find_mail_template_by_slug(params[:id])
|
||||
mail_template.update_attributes(update_params)
|
||||
redirect_to admin_procedure_mail_templates_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mails
|
||||
%w(initiated received closed refused without_continuation)
|
||||
.map { |name| @procedure.send(name + "_mail") }
|
||||
def mail_templates
|
||||
[
|
||||
@procedure.initiated_mail_template,
|
||||
@procedure.received_mail_template,
|
||||
@procedure.closed_mail_template,
|
||||
@procedure.refused_mail_template,
|
||||
@procedure.without_continuation_mail_template
|
||||
]
|
||||
end
|
||||
|
||||
def find_the_right_mail type
|
||||
mails.find { |m| m.class.slug == type }
|
||||
def find_mail_template_by_slug(slug)
|
||||
mail_templates.find { |template| template.class.const_get(:SLUG) == slug }
|
||||
end
|
||||
|
||||
def update_params
|
||||
|
|
|
@ -10,9 +10,6 @@ class Admin::PrevisualisationsController < AdminController
|
|||
|
||||
@champs = @dossier.ordered_champs
|
||||
|
||||
@headers = @champs.inject([]) do |acc, champ|
|
||||
acc.push(champ) if champ.type_champ == 'header_section'
|
||||
acc
|
||||
end
|
||||
@headers = @champs.select { |champ| champ.type_champ == 'header_section' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class API::StatistiquesController < ApplicationController
|
||||
|
||||
def dossiers_stats
|
||||
render json: {
|
||||
total: total_dossiers,
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
class API::V1::DossiersController < APIController
|
||||
|
||||
api :GET, '/procedures/:procedure_id/dossiers/', 'Liste de tous les dossiers d\'une procédure'
|
||||
param :procedure_id, Integer, desc: "L'identifiant de la procédure", required: true
|
||||
param :token, String, desc: "Token administrateur", required: true
|
||||
error code: 401, desc: "Non authorisé"
|
||||
error code: 404, desc: "Procédure inconnue"
|
||||
|
||||
meta champs: {
|
||||
}
|
||||
|
||||
def index
|
||||
procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||
dossiers = procedure.dossiers.where.not(state: :draft).paginate(page: params[:page])
|
||||
|
@ -25,10 +21,6 @@ class API::V1::DossiersController < APIController
|
|||
error code: 401, desc: "Non authorisé"
|
||||
error code: 404, desc: "Procédure ou dossier inconnu"
|
||||
|
||||
meta champs: {
|
||||
|
||||
}
|
||||
|
||||
def show
|
||||
procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||
dossier = procedure.dossiers.find(params[:id])
|
||||
|
|
|
@ -5,10 +5,6 @@ class API::V1::ProceduresController < APIController
|
|||
error code: 401, desc: "Non authorisé"
|
||||
error code: 404, desc: "Procédure inconnue"
|
||||
|
||||
meta champs: {
|
||||
|
||||
}
|
||||
|
||||
def show
|
||||
procedure = current_administrateur.procedures.find(params[:id]).decorate
|
||||
|
||||
|
|
95
app/controllers/backoffice/avis_controller.rb
Normal file
95
app/controllers/backoffice/avis_controller.rb
Normal file
|
@ -0,0 +1,95 @@
|
|||
class Backoffice::AvisController < ApplicationController
|
||||
|
||||
before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire]
|
||||
before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
|
||||
before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire]
|
||||
|
||||
def create
|
||||
avis = Avis.new(create_params.merge(claimant: current_gestionnaire))
|
||||
avis.dossier = dossier
|
||||
|
||||
email = create_params[:email]
|
||||
gestionnaire = Gestionnaire.find_by(email: email)
|
||||
if gestionnaire
|
||||
avis.gestionnaire = gestionnaire
|
||||
avis.email = nil
|
||||
end
|
||||
|
||||
if avis.save
|
||||
flash[:notice] = "Votre demande d'avis a bien été envoyée à #{email}"
|
||||
end
|
||||
|
||||
redirect_to backoffice_dossier_path(dossier)
|
||||
end
|
||||
|
||||
def update
|
||||
if avis.update(update_params)
|
||||
NotificationService.new('avis', params[:dossier_id]).notify
|
||||
flash[:notice] = 'Merci, votre avis a été enregistré.'
|
||||
end
|
||||
|
||||
redirect_to backoffice_dossier_path(avis.dossier_id)
|
||||
end
|
||||
|
||||
def sign_up
|
||||
@email = params[:email]
|
||||
@dossier = Avis.includes(:dossier).find(params[:id]).dossier
|
||||
|
||||
render layout: 'new_application'
|
||||
end
|
||||
|
||||
def create_gestionnaire
|
||||
email = params[:email]
|
||||
password = params['gestionnaire']['password']
|
||||
|
||||
gestionnaire = Gestionnaire.new(email: email, password: password)
|
||||
|
||||
if gestionnaire.save
|
||||
sign_in(gestionnaire, scope: :gestionnaire)
|
||||
Avis.link_avis_to_gestionnaire(gestionnaire)
|
||||
avis = Avis.find(params[:id])
|
||||
redirect_to url_for(backoffice_dossier_path(avis.dossier_id))
|
||||
else
|
||||
flash[:alert] = gestionnaire.errors.full_messages.join('<br>')
|
||||
redirect_to url_for(avis_sign_up_path(params[:id], email))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def dossier
|
||||
current_gestionnaire.dossiers.find(params[:dossier_id])
|
||||
end
|
||||
|
||||
def avis
|
||||
current_gestionnaire.avis.find(params[:id])
|
||||
end
|
||||
|
||||
def create_params
|
||||
params.require(:avis).permit(:email, :introduction)
|
||||
end
|
||||
|
||||
def update_params
|
||||
params.require(:avis).permit(:answer)
|
||||
end
|
||||
|
||||
def redirect_if_no_sign_up_needed
|
||||
avis = Avis.find(params[:id])
|
||||
|
||||
if current_gestionnaire.present?
|
||||
# a gestionnaire is authenticated ... lets see if it can view the dossier
|
||||
|
||||
redirect_to backoffice_dossier_url(avis.dossier)
|
||||
elsif avis.gestionnaire.present? && avis.gestionnaire.email == params[:email]
|
||||
# the avis gestionnaire has already signed up and it sould sign in
|
||||
|
||||
redirect_to new_gestionnaire_session_url
|
||||
end
|
||||
end
|
||||
|
||||
def check_avis_exists_and_email_belongs_to_avis
|
||||
if !Avis.avis_exists_and_email_belongs_to_avis?(params[:id], params[:email])
|
||||
redirect_to url_for(root_path)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,4 @@
|
|||
class Backoffice::Dossiers::ProcedureController < Backoffice::DossiersListController
|
||||
|
||||
def index
|
||||
super
|
||||
|
||||
|
@ -22,4 +21,5 @@ class Backoffice::Dossiers::ProcedureController < Backoffice::DossiersListContro
|
|||
def retrieve_procedure
|
||||
current_gestionnaire.procedures.find params[:id]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
class Backoffice::DossiersController < Backoffice::DossiersListController
|
||||
respond_to :html, :xlsx, :ods, :csv
|
||||
|
||||
prepend_before_action :store_current_location, only: :show
|
||||
before_action :ensure_gestionnaire_is_authorized, only: :show
|
||||
|
||||
def index
|
||||
return redirect_to backoffice_invitations_path if current_gestionnaire.avis.any?
|
||||
|
||||
procedure = current_gestionnaire.procedure_filter
|
||||
|
||||
if procedure.nil?
|
||||
procedure_list = dossiers_list_facade.gestionnaire_procedures_name_and_id_list
|
||||
|
||||
if procedure_list.count == 0
|
||||
flash.alert = "Vous n'avez aucune procédure d'affectée."
|
||||
return redirect_to root_path
|
||||
|
@ -20,18 +24,22 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
end
|
||||
|
||||
def show
|
||||
create_dossier_facade params[:id]
|
||||
dossier_id = params[:id]
|
||||
create_dossier_facade dossier_id
|
||||
|
||||
unless @facade.nil?
|
||||
@champs_private = @facade.champs_private
|
||||
|
||||
@headers_private = @champs_private.inject([]) do |acc, champ|
|
||||
acc.push(champ) if champ.type_champ == 'header_section'
|
||||
acc
|
||||
end
|
||||
@headers_private = @champs_private.select { |champ| champ.type_champ == 'header_section' }
|
||||
end
|
||||
|
||||
Notification.where(dossier_id: params[:id].to_i).update_all already_read: true
|
||||
# if the current_gestionnaire does not own the dossier, it is here to give an advice
|
||||
# and it should not remove the notifications
|
||||
if current_gestionnaire.dossiers.find_by(id: dossier_id).present?
|
||||
Notification.where(dossier_id: dossier_id).update_all(already_read: true)
|
||||
end
|
||||
|
||||
@new_avis = Avis.new(introduction: "Bonjour, merci de me donner votre avis sur ce dossier.")
|
||||
end
|
||||
|
||||
def filter
|
||||
|
@ -92,8 +100,6 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
dossier.received!
|
||||
flash.notice = 'Dossier considéré comme reçu.'
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.received_mail).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
||||
|
@ -105,7 +111,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
dossier.next_step! 'gestionnaire', 'refuse'
|
||||
flash.notice = 'Dossier considéré comme refusé.'
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.refused_mail).deliver_now!
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.refused_mail_template).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
@ -118,7 +124,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
dossier.next_step! 'gestionnaire', 'without_continuation'
|
||||
flash.notice = 'Dossier considéré comme sans suite.'
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.without_continuation_mail).deliver_now!
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.without_continuation_mail_template).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
@ -131,7 +137,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
dossier.next_step! 'gestionnaire', 'close'
|
||||
flash.notice = 'Dossier traité avec succès.'
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.closed_mail).deliver_now!
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.closed_mail_template).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
@ -187,12 +193,17 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
|
||||
private
|
||||
|
||||
def ensure_gestionnaire_is_authorized
|
||||
current_gestionnaire.dossiers.find(params[:id])
|
||||
def store_current_location
|
||||
if !gestionnaire_signed_in?
|
||||
store_location_for(:gestionnaire, request.url)
|
||||
end
|
||||
end
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
flash.alert = t('errors.messages.dossier_not_found')
|
||||
redirect_to url_for(controller: '/backoffice')
|
||||
def ensure_gestionnaire_is_authorized
|
||||
unless current_gestionnaire.can_view_dossier?(params[:id])
|
||||
flash.alert = t('errors.messages.dossier_not_found')
|
||||
redirect_to url_for(controller: '/backoffice')
|
||||
end
|
||||
end
|
||||
|
||||
def create_dossier_facade dossier_id
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
class BackofficeController < ApplicationController
|
||||
include SmartListing::Helper::ControllerExtensions
|
||||
helper SmartListing::Helper
|
||||
|
||||
before_action :authenticate_gestionnaire!, only: [:invitations]
|
||||
|
||||
def index
|
||||
if !gestionnaire_signed_in?
|
||||
|
@ -7,4 +11,18 @@ class BackofficeController < ApplicationController
|
|||
redirect_to(:backoffice_dossiers)
|
||||
end
|
||||
end
|
||||
|
||||
def invitations
|
||||
pending_avis = current_gestionnaire.avis.without_answer.includes(dossier: [:procedure]).by_latest
|
||||
@pending_avis = smart_listing_create :pending_avis,
|
||||
pending_avis,
|
||||
partial: 'backoffice/dossiers/list_invitations',
|
||||
array: true
|
||||
|
||||
avis_with_answer = current_gestionnaire.avis.with_answer.includes(dossier: [:procedure]).by_latest
|
||||
@avis_with_answer = smart_listing_create :avis_with_answer,
|
||||
avis_with_answer,
|
||||
partial: 'backoffice/dossiers/list_invitations',
|
||||
array: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class FranceConnect::ParticulierController < ApplicationController
|
||||
|
||||
def login
|
||||
client = FranceConnectParticulierClient.new
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class PingController < ApplicationController
|
||||
|
||||
def index
|
||||
Rails.logger.silence do
|
||||
if (ActiveRecord::Base.connected?)
|
||||
|
@ -9,5 +8,4 @@ class PingController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
class RootController < ApplicationController
|
||||
def index
|
||||
|
||||
begin
|
||||
route = Rails.application.routes.recognize_path(request.referrer)
|
||||
rescue ActionController::RoutingError
|
||||
route = Rails.application.routes.recognize_path(new_user_session_path)
|
||||
end
|
||||
|
||||
if user_signed_in? && !route[:controller].match('users').nil?
|
||||
return redirect_to users_dossiers_path
|
||||
|
||||
elsif administrateur_signed_in? && !route[:controller].match('admin').nil?
|
||||
if administrateur_signed_in?
|
||||
return redirect_to admin_procedures_path
|
||||
|
||||
elsif gestionnaire_signed_in?
|
||||
return redirect_to backoffice_invitations_path if current_gestionnaire.avis.any?
|
||||
|
||||
procedure_id = current_gestionnaire.procedure_filter
|
||||
if procedure_id.nil?
|
||||
procedure_list = current_gestionnaire.procedures
|
||||
|
@ -30,15 +22,10 @@ class RootController < ApplicationController
|
|||
elsif user_signed_in?
|
||||
return redirect_to users_dossiers_path
|
||||
|
||||
elsif administrateur_signed_in?
|
||||
return redirect_to admin_procedures_path
|
||||
|
||||
elsif administration_signed_in?
|
||||
return redirect_to administrations_path
|
||||
end
|
||||
|
||||
@demo_environment_host = "https://tps-dev.apientreprise.fr" unless Rails.env.development?
|
||||
|
||||
render 'landing', :layout => 'new_application'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Sessions::SessionsController < Devise::SessionsController
|
||||
|
||||
before_action :before_sign_in, only: [:create]
|
||||
|
||||
def before_sign_in
|
||||
|
|
|
@ -1,45 +1,49 @@
|
|||
class StatsController < ApplicationController
|
||||
layout "new_application"
|
||||
|
||||
MEAN_NUMBER_OF_CHAMPS_IN_A_FORM = 24.0
|
||||
|
||||
def index
|
||||
procedures = Procedure.where(:published => true)
|
||||
dossiers = Dossier.where.not(:state => :draft)
|
||||
|
||||
@procedures_30_days_flow = thirty_days_flow_hash(procedures)
|
||||
@dossiers_30_days_flow = thirty_days_flow_hash(dossiers, :initiated_at)
|
||||
|
||||
@procedures_cumulative = cumulative_hash(procedures)
|
||||
@dossiers_cumulative = cumulative_hash(dossiers, :initiated_at)
|
||||
|
||||
@procedures_count = procedures.count
|
||||
@dossiers_count = dossiers.count
|
||||
|
||||
@procedures_cumulative = cumulative_hash(procedures)
|
||||
@procedures_in_the_last_4_months = last_four_months_hash(procedures)
|
||||
|
||||
@dossiers_cumulative = cumulative_hash(dossiers, :initiated_at)
|
||||
@dossiers_in_the_last_4_months = last_four_months_hash(dossiers, :initiated_at)
|
||||
|
||||
@procedures_count_per_administrateur = procedures_count_per_administrateur(procedures)
|
||||
|
||||
@dossier_instruction_mean_time = Rails.cache.fetch("dossier_instruction_mean_time", expires_in: 1.day) do
|
||||
dossier_instruction_mean_time(dossiers)
|
||||
end
|
||||
|
||||
@dossier_filling_mean_time = Rails.cache.fetch("dossier_filling_mean_time", expires_in: 1.day) do
|
||||
dossier_filling_mean_time(dossiers)
|
||||
end
|
||||
|
||||
@avis_usage = avis_usage
|
||||
@avis_average_answer_time = avis_average_answer_time
|
||||
@avis_answer_percentages = avis_answer_percentages
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def thirty_days_flow_hash(association, date_attribute = :created_at)
|
||||
min_date = 30.days.ago.to_date
|
||||
def last_four_months_hash(association, date_attribute = :created_at)
|
||||
min_date = 3.months.ago.beginning_of_month.to_date
|
||||
max_date = Time.now.to_date
|
||||
|
||||
thirty_days_flow_hash = association
|
||||
association
|
||||
.where(date_attribute => min_date..max_date)
|
||||
.group("date_trunc('day', #{date_attribute.to_s})")
|
||||
.group("DATE_TRUNC('month', #{date_attribute.to_s})")
|
||||
.count
|
||||
|
||||
clean_hash(thirty_days_flow_hash, min_date, max_date)
|
||||
end
|
||||
|
||||
def clean_hash(h, min_date, max_date)
|
||||
# Convert keys to date
|
||||
h = Hash[h.map { |(k, v)| [k.to_date, v] }]
|
||||
|
||||
# Add missing vales where count is 0
|
||||
(min_date..max_date).each do |date|
|
||||
if h[date].nil?
|
||||
h[date] = 0
|
||||
end
|
||||
end
|
||||
|
||||
h
|
||||
.to_a
|
||||
.sort{ |x, y| x[0] <=> y[0] }
|
||||
.map { |e| [I18n.l(e.first, format: "%B %Y"), e.last] }
|
||||
end
|
||||
|
||||
def cumulative_hash(association, date_attribute = :created_at)
|
||||
|
@ -53,4 +57,152 @@ class StatsController < ApplicationController
|
|||
.reduce({}, :merge)
|
||||
end
|
||||
|
||||
def procedures_count_per_administrateur(procedures)
|
||||
count_per_administrateur = procedures.group(:administrateur_id).count.values
|
||||
{
|
||||
'Une procédure' => count_per_administrateur.select { |count| count == 1 }.count,
|
||||
'Entre deux et cinq procédures' => count_per_administrateur.select { |count| 2 <= count && count <= 5 }.count,
|
||||
'Plus de cinq procédures' => count_per_administrateur.select { |count| 5 < count }.count
|
||||
}
|
||||
end
|
||||
|
||||
def mean(collection)
|
||||
(collection.sum.to_f / collection.size).round(2)
|
||||
end
|
||||
|
||||
def dossier_instruction_mean_time(dossiers)
|
||||
# In the 12 last months, we compute for each month
|
||||
# the average time it took to instruct a dossier
|
||||
# We compute monthly averages by first making an average per procedure
|
||||
# and then computing the average for all the procedures
|
||||
|
||||
min_date = 11.months.ago
|
||||
max_date = Time.now.to_date
|
||||
|
||||
processed_dossiers = dossiers
|
||||
.where(:processed_at => min_date..max_date)
|
||||
.pluck(:procedure_id, :initiated_at, :processed_at)
|
||||
|
||||
# Group dossiers by month
|
||||
processed_dossiers_by_month = processed_dossiers
|
||||
.group_by do |dossier|
|
||||
dossier[2].beginning_of_month.to_s
|
||||
end
|
||||
|
||||
processed_dossiers_by_month.map do |month, value|
|
||||
# Group the dossiers for this month by procedure
|
||||
dossiers_grouped_by_procedure = value.group_by { |dossier| dossier[0] }
|
||||
|
||||
# Compute the mean time for this procedure
|
||||
procedure_processing_times = dossiers_grouped_by_procedure.map do |procedure_id, procedure_dossiers|
|
||||
procedure_dossiers_processing_time = procedure_dossiers.map do |dossier|
|
||||
(dossier[2] - dossier[1]).to_f / (3600 * 24)
|
||||
end
|
||||
|
||||
mean(procedure_dossiers_processing_time)
|
||||
end
|
||||
|
||||
# Compute the average mean time for all the procedures of this month
|
||||
month_average = mean(procedure_processing_times)
|
||||
|
||||
[month, month_average]
|
||||
end.to_h
|
||||
end
|
||||
|
||||
def dossier_filling_mean_time(dossiers)
|
||||
# In the 12 last months, we compute for each month
|
||||
# the average time it took to fill a dossier
|
||||
# We compute monthly averages by first making an average per procedure
|
||||
# and then computing the average for all the procedures
|
||||
# For each procedure, we normalize the data: the time is calculated
|
||||
# for a 24 champs form (the current form mean length)
|
||||
|
||||
min_date = 11.months.ago
|
||||
max_date = Time.now.to_date
|
||||
|
||||
processed_dossiers = dossiers
|
||||
.where(:processed_at => min_date..max_date)
|
||||
.pluck(:procedure_id, :created_at, :initiated_at, :processed_at)
|
||||
|
||||
# Group dossiers by month
|
||||
processed_dossiers_by_month = processed_dossiers
|
||||
.group_by do |e|
|
||||
e[3].beginning_of_month.to_s
|
||||
end
|
||||
|
||||
processed_dossiers_by_month.map do |month, value|
|
||||
# Group the dossiers for this month by procedure
|
||||
dossiers_grouped_by_procedure = value.group_by { |dossier| dossier[0] }
|
||||
|
||||
# Compute the mean time for this procedure
|
||||
procedure_processing_times = dossiers_grouped_by_procedure.map do |procedure_id, procedure_dossiers|
|
||||
procedure_dossiers_processing_time = procedure_dossiers.map do |dossier|
|
||||
(dossier[2] - dossier[1]).to_f / 60
|
||||
end
|
||||
|
||||
procedure_mean = mean(procedure_dossiers_processing_time)
|
||||
|
||||
# We normalize the data for 24 fields
|
||||
procedure_fields_count = Procedure.find(procedure_id).types_de_champ.count
|
||||
procedure_mean * (MEAN_NUMBER_OF_CHAMPS_IN_A_FORM / procedure_fields_count)
|
||||
end
|
||||
|
||||
# Compute the average mean time for all the procedures of this month
|
||||
month_average = mean(procedure_processing_times)
|
||||
|
||||
[month, month_average]
|
||||
end.to_h
|
||||
end
|
||||
|
||||
def avis_usage
|
||||
[3.week.ago, 2.week.ago, 1.week.ago].map do |min_date|
|
||||
max_date = min_date + 1.week
|
||||
|
||||
weekly_dossiers = Dossier.includes(:avis).where(created_at: min_date..max_date).to_a
|
||||
|
||||
weekly_dossiers_count = weekly_dossiers.count
|
||||
|
||||
if weekly_dossiers_count == 0
|
||||
result = 0
|
||||
else
|
||||
weekly_dossier_with_avis_count = weekly_dossiers.select { |dossier| dossier.avis.present? }.count
|
||||
result = ((weekly_dossier_with_avis_count.to_f / weekly_dossiers_count) * 100).round(2)
|
||||
end
|
||||
|
||||
[min_date.to_i, result]
|
||||
end
|
||||
end
|
||||
|
||||
def avis_average_answer_time
|
||||
[3.week.ago, 2.week.ago, 1.week.ago].map do |min_date|
|
||||
max_date = min_date + 1.week
|
||||
|
||||
average = Avis.with_answer
|
||||
.where(created_at: min_date..max_date)
|
||||
.average("EXTRACT(EPOCH FROM updated_at - created_at) / 86400")
|
||||
|
||||
result = average ? average.to_f.round(2) : 0
|
||||
|
||||
[min_date.to_i, result]
|
||||
end
|
||||
end
|
||||
|
||||
def avis_answer_percentages
|
||||
[3.week.ago, 2.week.ago, 1.week.ago].map do |min_date|
|
||||
max_date = min_date + 1.week
|
||||
|
||||
weekly_avis = Avis.where(created_at: min_date..max_date)
|
||||
|
||||
weekly_avis_count = weekly_avis.count
|
||||
|
||||
if weekly_avis_count == 0
|
||||
[min_date.to_i, 0]
|
||||
else
|
||||
answered_weekly_avis_count = weekly_avis.with_answer.count
|
||||
result = ((answered_weekly_avis_count.to_f / weekly_avis_count) * 100).round(2)
|
||||
|
||||
[min_date.to_i, result]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Users::CarteController < UsersController
|
||||
|
||||
before_action only: [:show] do
|
||||
authorized_routes? self.class
|
||||
end
|
||||
|
|
|
@ -52,7 +52,7 @@ class Users::DescriptionController < UsersController
|
|||
else
|
||||
if dossier.draft?
|
||||
dossier.initiated!
|
||||
NotificationMailer.send_notification(dossier, procedure.initiated_mail).deliver_now!
|
||||
NotificationMailer.send_notification(dossier, procedure.initiated_mail_template).deliver_now!
|
||||
end
|
||||
flash.notice = 'Félicitations, votre demande a bien été enregistrée.'
|
||||
redirect_to url_for(controller: :recapitulatif, action: :show, dossier_id: dossier.id)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Users::Dossiers::InvitesController < UsersController
|
||||
|
||||
def authenticate_user!
|
||||
session["user_return_to"] = request.fullpath
|
||||
return redirect_to new_user_registration_path(user_email: params[:email]) if !params[:email].blank? && User.find_by_email(params[:email]).nil?
|
||||
|
|
|
@ -16,13 +16,13 @@ class Users::DossiersController < UsersController
|
|||
|
||||
@dossiers_filtered = case @liste
|
||||
when 'brouillon'
|
||||
@user_dossiers.brouillon.order_by_updated_at
|
||||
@user_dossiers.state_brouillon.order_by_updated_at
|
||||
when 'a_traiter'
|
||||
@user_dossiers.en_construction.order_by_updated_at
|
||||
@user_dossiers.state_en_construction.order_by_updated_at
|
||||
when 'en_instruction'
|
||||
@user_dossiers.en_instruction.order_by_updated_at
|
||||
@user_dossiers.state_en_instruction.order_by_updated_at
|
||||
when 'termine'
|
||||
@user_dossiers.termine.order_by_updated_at
|
||||
@user_dossiers.state_termine.order_by_updated_at
|
||||
when 'invite'
|
||||
current_user.invites
|
||||
else
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Users::RecapitulatifController < UsersController
|
||||
|
||||
before_action only: [:show] do
|
||||
authorized_routes? self.class
|
||||
end
|
||||
|
|
|
@ -33,7 +33,8 @@ class Users::SessionsController < Sessions::SessionsController
|
|||
if user_signed_in?
|
||||
redirect_to after_sign_in_path_for(:user)
|
||||
elsif gestionnaire_signed_in?
|
||||
redirect_to backoffice_path
|
||||
location = stored_location_for(:gestionnaire) || backoffice_path
|
||||
redirect_to location
|
||||
elsif administrateur_signed_in?
|
||||
redirect_to admin_path
|
||||
else
|
||||
|
|
|
@ -2,9 +2,15 @@ class ChampDecorator < Draper::Decorator
|
|||
delegate_all
|
||||
|
||||
def value
|
||||
return object.value == 'on' ? 'Oui' : 'Non' if type_champ == 'checkbox'
|
||||
return JSON.parse(object.value).join(', ') if type_champ == 'multiple_drop_down_list' && object.value.present?
|
||||
object.value
|
||||
if type_champ == "date" && object.value.present?
|
||||
Date.parse(object.value).strftime("%d/%m/%Y")
|
||||
elsif type_champ == 'checkbox'
|
||||
object.value == 'on' ? 'Oui' : 'Non'
|
||||
elsif type_champ == 'multiple_drop_down_list' && object.value.present?
|
||||
JSON.parse(object.value).join(', ')
|
||||
else
|
||||
object.value
|
||||
end
|
||||
end
|
||||
|
||||
def description_with_links
|
||||
|
|
9
app/mailers/avis_mailer.rb
Normal file
9
app/mailers/avis_mailer.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class AvisMailer < ApplicationMailer
|
||||
|
||||
def avis_invitation(avis)
|
||||
@avis = avis
|
||||
email = @avis.gestionnaire.try(:email) || @avis.email
|
||||
mail(to: email, subject: "Donnez votre avis sur le dossier nº #{@avis.dossier.id} (#{@avis.dossier.procedure.libelle})")
|
||||
end
|
||||
|
||||
end
|
|
@ -8,6 +8,11 @@ class GestionnaireMailer < ApplicationMailer
|
|||
send_mail email, email_admin, "Vous avez été assigné à un nouvel administrateur sur la plateforme TPS"
|
||||
end
|
||||
|
||||
def last_week_overview(gestionnaire, overview)
|
||||
headers['X-mailjet-campaign'] = 'last_week_overview'
|
||||
send_mail gestionnaire.email, overview, 'Résumé de la semaine'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def vars_mailer email, args
|
||||
|
|
|
@ -4,7 +4,7 @@ class NewAdminMailer < ApplicationMailer
|
|||
@admin = admin
|
||||
@password = password
|
||||
|
||||
mail(to: 'tech@apientreprise.fr',
|
||||
mail(to: 'tech@tps.apientreprise.fr',
|
||||
subject: "Création d'un compte Admin TPS")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,16 +3,16 @@ class NotificationMailer < ApplicationMailer
|
|||
|
||||
after_action :create_commentaire_for_notification, only: :send_notification
|
||||
|
||||
def send_notification dossier, mail_template
|
||||
def send_notification(dossier, mail_template)
|
||||
vars_mailer(dossier)
|
||||
|
||||
@obj = mail_template.object_for_dossier dossier
|
||||
@object = mail_template.object_for_dossier dossier
|
||||
@body = mail_template.body_for_dossier dossier
|
||||
|
||||
mail(subject: @obj) { |format| format.html { @body } }
|
||||
mail(subject: @object) { |format| format.html { @body } }
|
||||
end
|
||||
|
||||
def new_answer dossier
|
||||
def new_answer(dossier)
|
||||
send_mail dossier, "Nouveau message pour votre dossier TPS nº #{dossier.id}"
|
||||
end
|
||||
|
||||
|
@ -22,16 +22,16 @@ class NotificationMailer < ApplicationMailer
|
|||
Commentaire.create(
|
||||
dossier: @dossier,
|
||||
email: I18n.t("dynamics.contact_email"),
|
||||
body: ["[#{@obj}]", @body].join("<br><br>")
|
||||
body: ["[#{@object}]", @body].join("<br><br>")
|
||||
)
|
||||
end
|
||||
|
||||
def vars_mailer dossier
|
||||
def vars_mailer(dossier)
|
||||
@dossier = dossier
|
||||
@user = dossier.user
|
||||
end
|
||||
|
||||
def send_mail dossier, subject
|
||||
def send_mail(dossier, subject)
|
||||
vars_mailer dossier
|
||||
|
||||
mail(subject: subject)
|
||||
|
|
|
@ -27,5 +27,4 @@ class Administrateur < ActiveRecord::Base
|
|||
break token unless Administrateur.find_by(api_token: token)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
29
app/models/avis.rb
Normal file
29
app/models/avis.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
class Avis < ApplicationRecord
|
||||
belongs_to :dossier
|
||||
belongs_to :gestionnaire
|
||||
belongs_to :claimant, class_name: 'Gestionnaire'
|
||||
|
||||
after_create :notify_gestionnaire
|
||||
|
||||
scope :with_answer, -> { where.not(answer: nil) }
|
||||
scope :without_answer, -> { where(answer: nil) }
|
||||
scope :for_dossier, ->(dossier_id) { where(dossier_id: dossier_id) }
|
||||
scope :by_latest, -> { order(updated_at: :desc) }
|
||||
|
||||
def email_to_display
|
||||
gestionnaire.try(:email) || email
|
||||
end
|
||||
|
||||
def notify_gestionnaire
|
||||
AvisMailer.avis_invitation(self).deliver_now
|
||||
end
|
||||
|
||||
def self.link_avis_to_gestionnaire(gestionnaire)
|
||||
Avis.where(email: gestionnaire.email).update_all(email: nil, gestionnaire_id: gestionnaire.id)
|
||||
end
|
||||
|
||||
def self.avis_exists_and_email_belongs_to_avis?(avis_id, email)
|
||||
avis = Avis.find_by(id: avis_id)
|
||||
avis.present? && avis.email == email
|
||||
end
|
||||
end
|
|
@ -5,6 +5,7 @@ class Champ < ActiveRecord::Base
|
|||
|
||||
delegate :libelle, :type_champ, :order_place, :mandatory, :description, :drop_down_list, to: :type_de_champ
|
||||
|
||||
before_save :format_date_to_iso, if: Proc.new { type_champ == 'date' }
|
||||
after_save :internal_notification, if: Proc.new { !dossier.nil? }
|
||||
|
||||
def mandatory?
|
||||
|
@ -12,12 +13,12 @@ class Champ < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def data_provide
|
||||
return 'datepicker' if (type_champ == 'datetime' || type_champ == 'date') && !(BROWSER.value.chrome? || BROWSER.value.edge?)
|
||||
return 'datepicker' if (type_champ == 'datetime') && !(BROWSER.value.chrome? || BROWSER.value.edge?)
|
||||
return 'typeahead' if type_champ == 'address'
|
||||
end
|
||||
|
||||
def data_date_format
|
||||
('dd/mm/yyyy' if type_champ == 'datetime' || type_champ == 'date')
|
||||
('dd/mm/yyyy' if type_champ == 'datetime')
|
||||
end
|
||||
|
||||
def same_hour? num
|
||||
|
@ -55,6 +56,15 @@ class Champ < ActiveRecord::Base
|
|||
|
||||
private
|
||||
|
||||
def format_date_to_iso
|
||||
date = begin
|
||||
Date.parse(value).strftime("%F")
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
self.value = date
|
||||
end
|
||||
|
||||
def internal_notification
|
||||
unless dossier.state == 'draft'
|
||||
NotificationService.new('champs', self.dossier.id, self.libelle).notify
|
||||
|
|
|
@ -4,50 +4,23 @@ module MailTemplateConcern
|
|||
include Rails.application.routes.url_helpers
|
||||
include ActionView::Helpers::UrlHelper
|
||||
|
||||
TAGS = {
|
||||
numero_dossier: {
|
||||
description: "Permet d'afficher le numéro de dossier de l'utilisateur.",
|
||||
templates: [
|
||||
"initiated_mail",
|
||||
"received_mail",
|
||||
"closed_mail",
|
||||
"refused_mail",
|
||||
"without_continuation_mail"
|
||||
]
|
||||
},
|
||||
lien_dossier: {
|
||||
description: "Permet d'afficher un lien vers le dossier de l'utilisateur.",
|
||||
templates: [
|
||||
"initiated_mail",
|
||||
"received_mail",
|
||||
"closed_mail",
|
||||
"refused_mail",
|
||||
"without_continuation_mail"
|
||||
]
|
||||
},
|
||||
libelle_procedure: {
|
||||
description: "Permet d'afficher le libellé de la procédure.",
|
||||
templates: [
|
||||
"initiated_mail",
|
||||
"received_mail",
|
||||
"closed_mail",
|
||||
"refused_mail",
|
||||
"without_continuation_mail"
|
||||
]
|
||||
},
|
||||
date_de_decision: {
|
||||
description: "Permet d'afficher la date à laquelle la décision finale (acceptation, refus, classement sans suite) sur le dossier a été prise.",
|
||||
templates: [
|
||||
"closed_mail",
|
||||
"refused_mail",
|
||||
"without_continuation_mail"
|
||||
]
|
||||
}
|
||||
TAGS = []
|
||||
TAGS << TAG_NUMERO_DOSSIER = {
|
||||
name: "numero_dossier",
|
||||
description: "Permet d'afficher le numéro de dossier de l'utilisateur."
|
||||
}
|
||||
TAGS << TAG_LIEN_DOSSIER = {
|
||||
name: "lien_dossier",
|
||||
description: "Permet d'afficher un lien vers le dossier de l'utilisateur."
|
||||
}
|
||||
TAGS << TAG_LIBELLE_PROCEDURE = {
|
||||
name: "libelle_procedure",
|
||||
description: "Permet d'afficher le libellé de la procédure."
|
||||
}
|
||||
TAGS << TAG_DATE_DE_DECISION = {
|
||||
name: "date_de_decision",
|
||||
description: "Permet d'afficher la date à laquelle la décision finale (acceptation, refus, classement sans suite) sur le dossier a été prise."
|
||||
}
|
||||
|
||||
def self.tags_for_template(template)
|
||||
TAGS.select { |key, value| value[:templates].include?(template) }
|
||||
end
|
||||
|
||||
def object_for_dossier(dossier)
|
||||
replace_tags(object, dossier)
|
||||
|
@ -59,17 +32,13 @@ module MailTemplateConcern
|
|||
|
||||
def replace_tags(string, dossier)
|
||||
TAGS.inject(string) do |acc, tag|
|
||||
acc.gsub!("--#{tag.first}--", replace_tag(tag.first.to_sym, dossier)) || acc
|
||||
acc.gsub!("--#{tag[:name]}--", replace_tag(tag, dossier)) || acc
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def slug
|
||||
self.name.demodulize.underscore.parameterize
|
||||
end
|
||||
|
||||
def default
|
||||
body = ActionController::Base.new.render_to_string(template: self.name.underscore)
|
||||
body = ActionController::Base.new.render_to_string(template: self.const_get(:TEMPLATE_NAME))
|
||||
self.new(object: self.const_get(:DEFAULT_OBJECT), body: body)
|
||||
end
|
||||
end
|
||||
|
@ -78,13 +47,13 @@ module MailTemplateConcern
|
|||
|
||||
def replace_tag(tag, dossier)
|
||||
case tag
|
||||
when :numero_dossier
|
||||
when TAG_NUMERO_DOSSIER
|
||||
dossier.id.to_s
|
||||
when :lien_dossier
|
||||
when TAG_LIEN_DOSSIER
|
||||
link_to users_dossier_recapitulatif_url(dossier), users_dossier_recapitulatif_url(dossier), target: '_blank'
|
||||
when :libelle_procedure
|
||||
when TAG_LIBELLE_PROCEDURE
|
||||
dossier.procedure.libelle
|
||||
when :date_de_decision
|
||||
when TAG_DATE_DE_DECISION
|
||||
dossier.processed_at.present? ? dossier.processed_at.localtime.strftime("%d/%m/%Y") : ""
|
||||
else
|
||||
'--BALISE_NON_RECONNUE--'
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
class Dossier < ActiveRecord::Base
|
||||
enum state: {draft: 'draft',
|
||||
initiated: 'initiated',
|
||||
replied: 'replied', #action utilisateur demandé
|
||||
updated: 'updated', #etude par l'administration en cours
|
||||
received: 'received',
|
||||
closed: 'closed',
|
||||
refused: 'refused',
|
||||
without_continuation: 'without_continuation'
|
||||
}
|
||||
enum state: {
|
||||
draft: 'draft',
|
||||
initiated: 'initiated',
|
||||
replied: 'replied', # action utilisateur demandé
|
||||
updated: 'updated', # etude par l'administration en cours
|
||||
received: 'received',
|
||||
closed: 'closed',
|
||||
refused: 'refused',
|
||||
without_continuation: 'without_continuation'
|
||||
}
|
||||
|
||||
BROUILLON = %w(draft)
|
||||
NOUVEAUX = %w(initiated)
|
||||
OUVERT = %w(updated replied)
|
||||
WAITING_FOR_GESTIONNAIRE = %w(updated)
|
||||
WAITING_FOR_USER = %w(replied)
|
||||
EN_CONSTRUCTION = %w(initiated updated replied)
|
||||
EN_INSTRUCTION = %w(received)
|
||||
A_INSTRUIRE = %w(received)
|
||||
TERMINE = %w(closed refused without_continuation)
|
||||
|
||||
has_one :etablissement, dependent: :destroy
|
||||
has_one :entreprise, dependent: :destroy
|
||||
|
@ -25,10 +36,36 @@ class Dossier < ActiveRecord::Base
|
|||
has_many :invites_gestionnaires, class_name: 'InviteGestionnaire', dependent: :destroy
|
||||
has_many :follows
|
||||
has_many :notifications, dependent: :destroy
|
||||
has_many :avis, dependent: :destroy
|
||||
|
||||
belongs_to :procedure
|
||||
belongs_to :user
|
||||
|
||||
scope :state_brouillon, -> { where(state: BROUILLON) }
|
||||
scope :state_not_brouillon, -> { where.not(state: BROUILLON) }
|
||||
scope :state_nouveaux, -> { where(state: NOUVEAUX) }
|
||||
scope :state_ouvert, -> { where(state: OUVERT) }
|
||||
scope :state_waiting_for_gestionnaire, -> { where(state: WAITING_FOR_GESTIONNAIRE) }
|
||||
scope :state_waiting_for_user, -> { where(state: WAITING_FOR_USER) }
|
||||
scope :state_en_construction, -> { where(state: EN_CONSTRUCTION) }
|
||||
scope :state_en_instruction, -> { where(state: EN_INSTRUCTION) }
|
||||
scope :state_a_instruire, -> { where(state: A_INSTRUIRE) }
|
||||
scope :state_termine, -> { where(state: TERMINE) }
|
||||
|
||||
scope :archived, -> { where(archived: true) }
|
||||
scope :not_archived, -> { where(archived: false) }
|
||||
|
||||
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
|
||||
|
||||
scope :all_state, -> { not_archived.state_not_brouillon.order_by_updated_at(:asc) }
|
||||
scope :nouveaux, -> { not_archived.state_nouveaux.order_by_updated_at(:asc) }
|
||||
scope :ouvert, -> { not_archived.state_ouvert.order_by_updated_at(:asc) }
|
||||
scope :waiting_for_gestionnaire, -> { not_archived.state_waiting_for_gestionnaire.order_by_updated_at(:asc) }
|
||||
scope :waiting_for_user, -> { not_archived.state_waiting_for_user.order_by_updated_at(:asc) }
|
||||
scope :a_instruire, -> { not_archived.state_a_instruire.order_by_updated_at(:asc) }
|
||||
scope :termine, -> { not_archived.state_termine.order_by_updated_at(:asc) }
|
||||
scope :downloadable, -> { state_not_brouillon.order_by_updated_at(:asc) }
|
||||
|
||||
accepts_nested_attributes_for :individual
|
||||
|
||||
delegate :siren, to: :entreprise
|
||||
|
@ -41,20 +78,10 @@ class Dossier < ActiveRecord::Base
|
|||
|
||||
after_save :build_default_champs, if: Proc.new { procedure_id_changed? }
|
||||
after_save :build_default_individual, if: Proc.new { procedure.for_individual? }
|
||||
after_save :send_notification_email
|
||||
|
||||
validates :user, presence: true
|
||||
|
||||
BROUILLON = %w(draft)
|
||||
NOUVEAUX = %w(initiated)
|
||||
OUVERT = %w(updated replied)
|
||||
WAITING_FOR_GESTIONNAIRE = %w(updated)
|
||||
WAITING_FOR_USER = %w(replied)
|
||||
EN_CONSTRUCTION = %w(initiated updated replied)
|
||||
EN_INSTRUCTION = %w(received)
|
||||
A_INSTRUIRE = %w(received)
|
||||
TERMINE = %w(closed refused without_continuation)
|
||||
ALL_STATE = %w(initiated updated replied received closed refused without_continuation)
|
||||
|
||||
def unreaded_notifications
|
||||
@unreaded_notif ||= notifications.where(already_read: false)
|
||||
end
|
||||
|
@ -158,49 +185,10 @@ class Dossier < ActiveRecord::Base
|
|||
state
|
||||
end
|
||||
|
||||
def self.all_state order = 'ASC'
|
||||
where(state: ALL_STATE, archived: false).order("updated_at #{order}")
|
||||
end
|
||||
|
||||
def brouillon?
|
||||
BROUILLON.include?(state)
|
||||
end
|
||||
|
||||
scope :brouillon, -> { where(state: BROUILLON) }
|
||||
|
||||
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
|
||||
|
||||
def self.nouveaux order = 'ASC'
|
||||
where(state: NOUVEAUX, archived: false).order("updated_at #{order}")
|
||||
end
|
||||
|
||||
def self.waiting_for_gestionnaire order = 'ASC'
|
||||
where(state: WAITING_FOR_GESTIONNAIRE, archived: false).order("updated_at #{order}")
|
||||
end
|
||||
|
||||
def self.waiting_for_user order = 'ASC'
|
||||
where(state: WAITING_FOR_USER, archived: false).order("updated_at #{order}")
|
||||
end
|
||||
|
||||
scope :en_construction, -> { where(state: EN_CONSTRUCTION) }
|
||||
|
||||
def self.ouvert order = 'ASC'
|
||||
where(state: OUVERT, archived: false).order("updated_at #{order}")
|
||||
end
|
||||
|
||||
def self.a_instruire order = 'ASC'
|
||||
where(state: A_INSTRUIRE, archived: false).order("updated_at #{order}")
|
||||
end
|
||||
|
||||
scope :en_instruction, -> { where(state: EN_INSTRUCTION) }
|
||||
|
||||
scope :termine, -> { where(state: TERMINE) }
|
||||
|
||||
scope :archived, -> { where(archived: true) }
|
||||
scope :not_archived, -> { where(archived: false) }
|
||||
|
||||
scope :downloadable, -> { all_state }
|
||||
|
||||
def cerfa_available?
|
||||
procedure.cerfa_flag? && cerfa.size != 0
|
||||
end
|
||||
|
@ -315,4 +303,10 @@ class Dossier < ActiveRecord::Base
|
|||
def serialize_value_for_export(value)
|
||||
value.nil? || value.kind_of?(Time) ? value : value.to_s
|
||||
end
|
||||
|
||||
def send_notification_email
|
||||
if state_changed? && EN_INSTRUCTION.include?(state)
|
||||
NotificationMailer.send_notification(self, procedure.received_mail_template).deliver_now!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Entreprise < ActiveRecord::Base
|
||||
|
||||
belongs_to :dossier
|
||||
has_one :etablissement, dependent: :destroy
|
||||
has_one :rna_information, dependent: :destroy
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Etablissement < ActiveRecord::Base
|
||||
|
||||
belongs_to :dossier
|
||||
belongs_to :entreprise
|
||||
|
||||
|
|
|
@ -2,5 +2,4 @@ class Exercice < ActiveRecord::Base
|
|||
belongs_to :etablissement
|
||||
|
||||
validates :ca, presence: true, allow_blank: false, allow_nil: false
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class FranceConnectParticulierClient < OpenIDConnect::Client
|
||||
|
||||
def initialize params={}
|
||||
super(
|
||||
identifier: FRANCE_CONNECT.particulier_identifier,
|
||||
|
|
|
@ -12,6 +12,7 @@ class Gestionnaire < ActiveRecord::Base
|
|||
has_many :followed_dossiers, through: :follows, source: :dossier
|
||||
has_many :follows
|
||||
has_many :preference_list_dossiers
|
||||
has_many :avis
|
||||
|
||||
after_create :build_default_preferences_list_dossier
|
||||
after_create :build_default_preferences_smart_listing_page
|
||||
|
@ -24,6 +25,11 @@ class Gestionnaire < ActiveRecord::Base
|
|||
self[:procedure_filter]
|
||||
end
|
||||
|
||||
def can_view_dossier?(dossier_id)
|
||||
avis.where(dossier_id: dossier_id).any? ||
|
||||
dossiers.where(id: dossier_id).any?
|
||||
end
|
||||
|
||||
def toggle_follow_dossier dossier_id
|
||||
dossier = dossier_id
|
||||
dossier = Dossier.find(dossier_id) unless dossier_id.class == Dossier
|
||||
|
@ -41,6 +47,10 @@ class Gestionnaire < ActiveRecord::Base
|
|||
Follow.where(gestionnaire_id: id, dossier_id: dossier_id).any?
|
||||
end
|
||||
|
||||
def assigned_on_procedure?(procedure_id)
|
||||
procedures.find_by(id: procedure_id).present?
|
||||
end
|
||||
|
||||
def build_default_preferences_list_dossier procedure_id=nil
|
||||
|
||||
PreferenceListDossier.available_columns_for(procedure_id).each do |table|
|
||||
|
@ -92,6 +102,26 @@ class Gestionnaire < ActiveRecord::Base
|
|||
notifications.pluck(:dossier_id).uniq.count
|
||||
end
|
||||
|
||||
def last_week_overview
|
||||
start_date = DateTime.now.beginning_of_week
|
||||
|
||||
active_procedure_overviews = procedures
|
||||
.where(published: true)
|
||||
.all
|
||||
.map { |procedure| procedure.procedure_overview(start_date, dossiers_with_notifications_count_for_procedure(procedure)) }
|
||||
.select(&:had_some_activities?)
|
||||
|
||||
if active_procedure_overviews.count == 0 && notifications.count == 0
|
||||
nil
|
||||
else
|
||||
{
|
||||
start_date: start_date,
|
||||
procedure_overviews: active_procedure_overviews,
|
||||
notifications: notifications
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_couple_table_attr? table, column
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
module Mails
|
||||
class ClosedMail < ActiveRecord::Base
|
||||
class ClosedMail < ApplicationRecord
|
||||
include MailTemplateConcern
|
||||
|
||||
SLUG = "closed_mail"
|
||||
TEMPLATE_NAME = "mails/closed_mail"
|
||||
DISPLAYED_NAME = "Accusé d'acceptation"
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été accepté'
|
||||
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
module Mails
|
||||
class InitiatedMail < ActiveRecord::Base
|
||||
class InitiatedMail < ApplicationRecord
|
||||
include MailTemplateConcern
|
||||
|
||||
SLUG = "initiated_mail"
|
||||
TEMPLATE_NAME = "mails/initiated_mail"
|
||||
DISPLAYED_NAME = 'Accusé de réception'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été bien reçu'
|
||||
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
module Mails
|
||||
class ReceivedMail < ActiveRecord::Base
|
||||
class ReceivedMail < ApplicationRecord
|
||||
include MailTemplateConcern
|
||||
|
||||
SLUG = "received_mail"
|
||||
TEMPLATE_NAME = "mails/received_mail"
|
||||
DISPLAYED_NAME = 'Accusé de passage en instruction'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- va être instruit'
|
||||
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,10 @@ module Mails
|
|||
class RefusedMail < ApplicationRecord
|
||||
include MailTemplateConcern
|
||||
|
||||
SLUG = "refused_mail"
|
||||
TEMPLATE_NAME = "mails/refused_mail"
|
||||
DISPLAYED_NAME = 'Accusé de rejet du dossier'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été refusé'
|
||||
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,10 @@ module Mails
|
|||
class WithoutContinuationMail < ApplicationRecord
|
||||
include MailTemplateConcern
|
||||
|
||||
SLUG = "without_continuation"
|
||||
TEMPLATE_NAME = "mails/without_continuation_mail"
|
||||
DISPLAYED_NAME = 'Accusé de classement sans suite'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été classé sans suite'
|
||||
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
class Notification < ActiveRecord::Base
|
||||
belongs_to :dossier
|
||||
enum type_notif: {
|
||||
commentaire: 'commentaire',
|
||||
cerfa: 'cerfa',
|
||||
piece_justificative: 'piece_justificative',
|
||||
champs: 'champs',
|
||||
submitted: 'submitted'
|
||||
}
|
||||
commentaire: 'commentaire',
|
||||
cerfa: 'cerfa',
|
||||
piece_justificative: 'piece_justificative',
|
||||
champs: 'champs',
|
||||
submitted: 'submitted',
|
||||
avis: 'avis'
|
||||
}
|
||||
|
||||
belongs_to :dossier
|
||||
|
||||
scope :unread, -> { where(already_read: false) }
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@ class Procedure < ActiveRecord::Base
|
|||
has_many :types_de_champ, class_name: 'TypeDeChampPublic', dependent: :destroy
|
||||
has_many :types_de_champ_private, dependent: :destroy
|
||||
has_many :dossiers
|
||||
has_many :notifications, through: :dossiers
|
||||
|
||||
has_one :procedure_path, dependent: :destroy
|
||||
|
||||
|
@ -16,6 +15,12 @@ class Procedure < ActiveRecord::Base
|
|||
|
||||
has_many :preference_list_dossiers
|
||||
|
||||
has_one :initiated_mail, class_name: "Mails::InitiatedMail", dependent: :destroy
|
||||
has_one :received_mail, class_name: "Mails::ReceivedMail", dependent: :destroy
|
||||
has_one :closed_mail, class_name: "Mails::ClosedMail", dependent: :destroy
|
||||
has_one :refused_mail, class_name: "Mails::RefusedMail", dependent: :destroy
|
||||
has_one :without_continuation_mail, class_name: "Mails::WithoutContinuationMail", dependent: :destroy
|
||||
|
||||
delegate :use_api_carto, to: :module_api_carto
|
||||
|
||||
accepts_nested_attributes_for :types_de_champ, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
||||
|
@ -25,31 +30,11 @@ class Procedure < ActiveRecord::Base
|
|||
|
||||
mount_uploader :logo, ProcedureLogoUploader
|
||||
|
||||
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
||||
validates :description, presence: true, allow_blank: false, allow_nil: false
|
||||
|
||||
# for all those mails do
|
||||
# has_one :initiated_mail, class_name: 'Mails::InitiatedMail'
|
||||
#
|
||||
# add a method to return default mail if none is saved
|
||||
# def initiated_mail_with_override
|
||||
# self.initiated_mail_without_override || InitiatedMail.default
|
||||
# end
|
||||
# alias_method_chain :initiated_mail, :override
|
||||
|
||||
MAIL_TEMPLATE_TYPES = %w(InitiatedMail ReceivedMail ClosedMail RefusedMail WithoutContinuationMail)
|
||||
|
||||
MAIL_TEMPLATE_TYPES.each do |name|
|
||||
has_one "#{name.underscore}".to_sym, class_name: "Mails::#{name}", dependent: :destroy
|
||||
define_method("#{name.underscore}_with_override") do
|
||||
self.send("#{name.underscore}_without_override") || Object.const_get("Mails::#{name}").default
|
||||
end
|
||||
alias_method_chain "#{name.underscore.to_sym}".to_s, :override
|
||||
end
|
||||
|
||||
scope :not_archived, -> { where(archived: false) }
|
||||
scope :by_libelle, -> { order(libelle: :asc) }
|
||||
|
||||
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
||||
validates :description, presence: true, allow_blank: false, allow_nil: false
|
||||
|
||||
def path
|
||||
procedure_path.path unless procedure_path.nil?
|
||||
|
@ -68,7 +53,7 @@ class Procedure < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.active id
|
||||
Procedure.where(archived: false, published: true).find(id)
|
||||
not_archived.where(published: true).find(id)
|
||||
end
|
||||
|
||||
def switch_types_de_champ index_of_first_element
|
||||
|
@ -84,12 +69,17 @@ class Procedure < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def switch_list_order(list, index_of_first_element)
|
||||
return false if index_of_first_element < 0
|
||||
return false if index_of_first_element == list.count - 1
|
||||
return false if list.count < 1
|
||||
list[index_of_first_element].update_attributes(order_place: index_of_first_element + 1)
|
||||
list[index_of_first_element + 1].update_attributes(order_place: index_of_first_element)
|
||||
true
|
||||
if index_of_first_element < 0 ||
|
||||
index_of_first_element == list.count - 1 ||
|
||||
list.count < 1
|
||||
|
||||
false
|
||||
else
|
||||
list[index_of_first_element].update_attributes(order_place: index_of_first_element + 1)
|
||||
list[index_of_first_element + 1].update_attributes(order_place: index_of_first_element)
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def locked?
|
||||
|
@ -109,9 +99,11 @@ class Procedure < ActiveRecord::Base
|
|||
procedure.logo_secure_token = nil
|
||||
procedure.remote_logo_url = self.logo_url
|
||||
|
||||
MAIL_TEMPLATE_TYPES.each do |mtt|
|
||||
procedure.send("#{mtt.underscore}=", self.send("#{mtt.underscore}_without_override").try(:dup))
|
||||
end
|
||||
procedure.initiated_mail = initiated_mail.try(:dup)
|
||||
procedure.received_mail = received_mail.try(:dup)
|
||||
procedure.closed_mail = closed_mail.try(:dup)
|
||||
procedure.refused_mail = refused_mail.try(:dup)
|
||||
procedure.without_continuation_mail = without_continuation_mail.try(:dup)
|
||||
|
||||
return procedure if procedure.save
|
||||
end
|
||||
|
@ -141,4 +133,27 @@ class Procedure < ActiveRecord::Base
|
|||
}
|
||||
end
|
||||
|
||||
def procedure_overview(start_date, notifications_count)
|
||||
ProcedureOverview.new(self, start_date, notifications_count)
|
||||
end
|
||||
|
||||
def initiated_mail_template
|
||||
initiated_mail || Mails::InitiatedMail.default
|
||||
end
|
||||
|
||||
def received_mail_template
|
||||
received_mail || Mails::ReceivedMail.default
|
||||
end
|
||||
|
||||
def closed_mail_template
|
||||
closed_mail || Mails::ClosedMail.default
|
||||
end
|
||||
|
||||
def refused_mail_template
|
||||
refused_mail || Mails::RefusedMail.default
|
||||
end
|
||||
|
||||
def without_continuation_mail_template
|
||||
without_continuation_mail || Mails::WithoutContinuationMail.default
|
||||
end
|
||||
end
|
||||
|
|
82
app/models/procedure_overview.rb
Normal file
82
app/models/procedure_overview.rb
Normal file
|
@ -0,0 +1,82 @@
|
|||
class ProcedureOverview
|
||||
include Rails.application.routes.url_helpers
|
||||
attr_accessor :libelle, :notifications_count, :received_dossiers_count, :created_dossiers_count, :processed_dossiers_count, :date
|
||||
|
||||
def initialize(procedure, start_date, notifications_count)
|
||||
@libelle = procedure.libelle
|
||||
@procedure_url = backoffice_dossiers_procedure_url(procedure)
|
||||
@notifications_count = notifications_count
|
||||
|
||||
@received_dossiers_count = procedure.dossiers.where(state: :received).count
|
||||
@created_dossiers_count = procedure.dossiers
|
||||
.where(created_at: start_date..DateTime.now)
|
||||
.where.not(state: :draft)
|
||||
.count
|
||||
@processed_dossiers_count = procedure.dossiers.where(processed_at: start_date..DateTime.now).count
|
||||
end
|
||||
|
||||
def had_some_activities?
|
||||
[received_dossiers_count,
|
||||
created_dossiers_count,
|
||||
processed_dossiers_count,
|
||||
notifications_count].reduce(:+) > 0
|
||||
end
|
||||
|
||||
def to_html
|
||||
[libelle_description,
|
||||
dossiers_en_instruction_description,
|
||||
created_dossier_description,
|
||||
processed_dossier_description,
|
||||
notifications_description].compact.join('<br>')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def libelle_description
|
||||
"<a href='#{@procedure_url}'><strong>#{libelle}</strong></a>"
|
||||
end
|
||||
|
||||
def dossiers_en_instruction_description
|
||||
case received_dossiers_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
"1 dossier est en cours d'instruction"
|
||||
else
|
||||
"#{received_dossiers_count} dossiers sont en cours d'instruction"
|
||||
end
|
||||
end
|
||||
|
||||
def created_dossier_description
|
||||
case created_dossiers_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
'1 nouveau dossier a été déposé'
|
||||
else
|
||||
"#{created_dossiers_count} nouveaux dossiers ont été déposés"
|
||||
end
|
||||
end
|
||||
|
||||
def processed_dossier_description
|
||||
case processed_dossiers_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
'1 dossier a été instruit'
|
||||
else
|
||||
"#{processed_dossiers_count} dossiers ont été instruits"
|
||||
end
|
||||
end
|
||||
|
||||
def notifications_description
|
||||
case notifications_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
'1 notification en attente sur les dossiers que vous suivez'
|
||||
else
|
||||
"#{notifications_count} notifications en attente sur les dossiers que vous suivez"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,26 +1,26 @@
|
|||
class TypeDeChamp < ActiveRecord::Base
|
||||
enum type_champs: {
|
||||
text: 'text',
|
||||
textarea: 'textarea',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
number: 'number',
|
||||
checkbox: 'checkbox',
|
||||
civilite: 'civilite',
|
||||
email: 'email',
|
||||
phone: 'phone',
|
||||
address: 'address',
|
||||
yes_no: 'yes_no',
|
||||
drop_down_list: 'drop_down_list',
|
||||
multiple_drop_down_list: 'multiple_drop_down_list',
|
||||
pays: 'pays',
|
||||
regions: 'regions',
|
||||
departements: 'departements',
|
||||
engagement: 'engagement',
|
||||
header_section: 'header_section',
|
||||
explication: 'explication',
|
||||
dossier_link: 'dossier_link'
|
||||
}
|
||||
text: 'text',
|
||||
textarea: 'textarea',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
number: 'number',
|
||||
checkbox: 'checkbox',
|
||||
civilite: 'civilite',
|
||||
email: 'email',
|
||||
phone: 'phone',
|
||||
address: 'address',
|
||||
yes_no: 'yes_no',
|
||||
drop_down_list: 'drop_down_list',
|
||||
multiple_drop_down_list: 'multiple_drop_down_list',
|
||||
pays: 'pays',
|
||||
regions: 'regions',
|
||||
departements: 'departements',
|
||||
engagement: 'engagement',
|
||||
header_section: 'header_section',
|
||||
explication: 'explication',
|
||||
dossier_link: 'dossier_link'
|
||||
}
|
||||
|
||||
belongs_to :procedure
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class User < ActiveRecord::Base
|
||||
enum loged_in_with_france_connect: {particulier: 'particulier',
|
||||
entreprise: 'entreprise'}
|
||||
enum loged_in_with_france_connect: {
|
||||
particulier: 'particulier',
|
||||
entreprise: 'entreprise'
|
||||
}
|
||||
|
||||
# Include default devise modules. Others available are:
|
||||
# :confirmable, :lockable, :timeoutable and :omniauthable
|
||||
|
@ -35,5 +37,4 @@ class User < ActiveRecord::Base
|
|||
def invite? dossier_id
|
||||
invites.pluck(:dossier_id).include?(dossier_id.to_i)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -45,7 +45,7 @@ class DossiersListGestionnaireService
|
|||
end
|
||||
|
||||
def termine
|
||||
@termine ||= filter_dossiers.termine.not_archived
|
||||
@termine ||= filter_dossiers.termine
|
||||
end
|
||||
|
||||
def filter_dossiers
|
||||
|
|
|
@ -35,6 +35,8 @@ class NotificationService
|
|||
attribut
|
||||
when 'submitted'
|
||||
"Le dossier nº #{@dossier_id} a été déposé."
|
||||
when 'avis'
|
||||
'Un nouvel avis a été rendu'
|
||||
else
|
||||
'Notification par défaut'
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
= simple_form_for @mail_template,
|
||||
as: 'mail_template',
|
||||
url: admin_procedure_mail_template_path(@procedure, @mail_template.class.slug),
|
||||
url: admin_procedure_mail_template_path(@procedure, @mail_template.class.const_get(:SLUG)),
|
||||
method: :put do |f|
|
||||
.row
|
||||
.col-md-6
|
||||
|
@ -22,9 +22,9 @@
|
|||
Balise
|
||||
%th
|
||||
Description
|
||||
- MailTemplateConcern.tags_for_template(@mail_template_name).each do |balise|
|
||||
- @mail_template.class.const_get(:ALLOWED_TAGS).each do |tag|
|
||||
%tr
|
||||
%td.center
|
||||
= "--#{balise.first}--"
|
||||
= "--#{tag[:name]}--"
|
||||
%td
|
||||
= balise.second[:description]
|
||||
= tag[:description]
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
%tr
|
||||
%th{ colspan: 2 }
|
||||
Type d'email
|
||||
- @mails.each do |mail|
|
||||
- @mail_templates.each do |mail_template|
|
||||
%tr
|
||||
%td
|
||||
= mail.class.const_get(:DISPLAYED_NAME)
|
||||
= mail_template.class.const_get(:DISPLAYED_NAME)
|
||||
%td.text-right
|
||||
= link_to "Personnaliser l'e-mail", edit_admin_procedure_mail_template_path(@procedure, mail.class.slug)
|
||||
= link_to "Personnaliser l'e-mail", edit_admin_procedure_mail_template_path(@procedure, mail_template.class.const_get(:SLUG))
|
||||
|
|
28
app/views/avis_mailer/avis_invitation.html.haml
Normal file
28
app/views/avis_mailer/avis_invitation.html.haml
Normal file
|
@ -0,0 +1,28 @@
|
|||
%html
|
||||
%body
|
||||
%p
|
||||
Bonjour,
|
||||
%br
|
||||
= "Vous avez été invité par #{@avis.claimant.email} à donner votre avis sur le dossier nº #{@avis.dossier.id} de la procédure : #{@avis.dossier.procedure.libelle}."
|
||||
%br
|
||||
Message de votre interlocuteur :
|
||||
|
||||
%p{ style: 'border: 1px solid grey' }
|
||||
= @avis.introduction
|
||||
|
||||
- if @avis.gestionnaire.present?
|
||||
%p
|
||||
= link_to "Connectez-vous pour donner votre avis", backoffice_dossier_url(@avis.dossier)
|
||||
- else
|
||||
%p
|
||||
= link_to "Inscrivez-vous pour donner votre avis", avis_sign_up_url(@avis.id, @avis.email)
|
||||
|
||||
Bonne journée,
|
||||
%br
|
||||
%br
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
%br
|
||||
%br
|
||||
%hr
|
||||
%br
|
||||
Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme.
|
15
app/views/backoffice/avis/sign_up.html.haml
Normal file
15
app/views/backoffice/avis/sign_up.html.haml
Normal file
|
@ -0,0 +1,15 @@
|
|||
.avis-sign-up
|
||||
.left
|
||||
%p.description= @dossier.procedure.libelle
|
||||
%p.dossier Dossier nº #{@dossier.id}
|
||||
.right
|
||||
%h1 Créez-vous un compte
|
||||
|
||||
= form_for(Gestionnaire.new, url: { controller: 'backoffice/avis', action: :create_gestionnaire }, method: :post) do |f|
|
||||
= f.label :email, 'Email'
|
||||
= f.email_field :email, value: @email, disabled: true
|
||||
|
||||
= f.label :password, 'Mot de passe'
|
||||
= f.password_field :password, autofocus: true, required: true, placeholder: '8 caractères minimum'
|
||||
|
||||
%button Créer un compte
|
20
app/views/backoffice/dossiers/_list_invitations.html.haml
Normal file
20
app/views/backoffice/dossiers/_list_invitations.html.haml
Normal file
|
@ -0,0 +1,20 @@
|
|||
- if smart_listing.collection.any?
|
||||
%table#dossiers-list.table
|
||||
%thead
|
||||
%th
|
||||
Nº
|
||||
%th
|
||||
Procédure
|
||||
%th
|
||||
Invité le
|
||||
%tbody
|
||||
- smart_listing.collection.each do |avis|
|
||||
%tr.dossier-row{ id: "tr_dossier_#{avis.dossier.id}", 'data-dossier_url' => backoffice_dossier_url(id: avis.dossier.id) }
|
||||
%td= avis.dossier.id
|
||||
%td= avis.dossier.procedure.libelle
|
||||
%td= avis.created_at.strftime('%d/%m/%Y %H:%M')
|
||||
= smart_listing.paginate
|
||||
|
||||
- else
|
||||
.center{ colspan: 2 }
|
||||
%em Aucun dossier
|
22
app/views/backoffice/invitations.html.haml
Normal file
22
app/views/backoffice/invitations.html.haml
Normal file
|
@ -0,0 +1,22 @@
|
|||
.col-md-12
|
||||
.default-data-block.default_visible
|
||||
.row.show-block
|
||||
.header
|
||||
.title
|
||||
.carret-right
|
||||
.carret-down
|
||||
= "#{@pending_avis.count} avis à rendre"
|
||||
.body
|
||||
= smart_listing_render :pending_avis
|
||||
|
||||
%br
|
||||
|
||||
.default-data-block
|
||||
.row.show-block
|
||||
.header
|
||||
.title
|
||||
.carret-right
|
||||
.carret-down
|
||||
= "#{@avis_with_answer.count} avis #{"rendu".pluralize(@avis_with_answer.count)}"
|
||||
.body
|
||||
= smart_listing_render :avis_with_answer
|
4
app/views/backoffice/invitations.js.erb
Normal file
4
app/views/backoffice/invitations.js.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<%= smart_listing_update :pending_avis %>
|
||||
<%= smart_listing_update :avis_with_answer %>
|
||||
|
||||
link_init();
|
|
@ -1,4 +1,4 @@
|
|||
<p>Bonjour <%= @resource.email %>!</p>
|
||||
<p>Bonjour,</p>
|
||||
|
||||
<p>Vous avez demandé à regénérer votre mot de passe sur la plateforme TPS. Pour ceci, merci de suivre le lien suivant :</p>
|
||||
|
||||
|
@ -6,10 +6,6 @@
|
|||
|
||||
<p>Si vous n'avez pas effectué une telle demande, merci d'ignorer ce mail. Votre mot de passe ne sera pas changé.</p>
|
||||
|
||||
<p>Bonne journée</p>
|
||||
<p>Bonne journée,</p>
|
||||
|
||||
|
||||
<p>
|
||||
---
|
||||
<br>
|
||||
L'équipe Téléprocédures Simplifiées</p>
|
||||
<p>L'équipe Téléprocédures Simplifiées</p>
|
||||
|
|
56
app/views/dossiers/_avis.html.haml
Normal file
56
app/views/dossiers/_avis.html.haml
Normal file
|
@ -0,0 +1,56 @@
|
|||
- if current_gestionnaire && current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id)
|
||||
|
||||
.default-data-block.default_visible
|
||||
.row.show-block.infos
|
||||
.header
|
||||
.col-xs-12.title
|
||||
.carret-right
|
||||
.carret-down
|
||||
AVIS EXTERNES
|
||||
.body
|
||||
.display-block-on-print
|
||||
- dossier_facade.dossier.avis.by_latest.each do |avis|
|
||||
- if avis.answer
|
||||
.panel.panel-success
|
||||
.panel-heading
|
||||
%strong= avis.email_to_display
|
||||
a donné son avis le
|
||||
= avis.updated_at.localtime.strftime('%d/%m/%Y à %H:%M')
|
||||
.panel-body
|
||||
%strong Vous :
|
||||
= avis.introduction
|
||||
%hr
|
||||
%strong= "#{avis.email_to_display} :"
|
||||
= avis.answer
|
||||
- else
|
||||
.panel.panel-info
|
||||
.panel-heading
|
||||
Avis demandé à
|
||||
%strong= avis.email_to_display
|
||||
le
|
||||
= avis.created_at.localtime.strftime('%d/%m/%Y à %H:%M')
|
||||
.panel-body
|
||||
%strong Vous :
|
||||
= avis.introduction
|
||||
%hr
|
||||
.center
|
||||
%em Avis en attente
|
||||
|
||||
-# FIXME prevent bug when the user is also a gestionnaire on the procedure #375
|
||||
- if @new_avis.present?
|
||||
.hidden-print
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
Demander un avis externe
|
||||
.panel-body
|
||||
.help-block
|
||||
Invitez une personne externe à consulter le dossier et à vous donner un avis sur celui ci.
|
||||
%br
|
||||
Cette personne pourra également contribuer au fil de messagerie, mais ne pourra pas modifier le dossier.
|
||||
|
||||
= simple_form_for @new_avis, url: backoffice_dossier_avis_index_path(dossier_facade.dossier.object.id) do |f|
|
||||
|
||||
= f.input 'email', label: "Email de la personne qui doit donner un avis"
|
||||
= f.input 'introduction', label: "Message"
|
||||
|
||||
= f.submit "Envoyer la demande d'avis", class: 'btn btn-default'
|
|
@ -1,3 +1,5 @@
|
|||
= render partial: 'dossiers/edit_avis', locals: { dossier_facade: @facade }
|
||||
|
||||
= render partial: 'dossiers/messagerie', locals: { dossier_facade: @facade }
|
||||
|
||||
- if @facade.procedure.individual_with_siret
|
||||
|
@ -51,8 +53,7 @@
|
|||
= render partial: '/users/carte/map', locals: { dossier: @facade.dossier }
|
||||
= render partial: 'users/carte/init_carto', locals: { dossier: @facade.dossier }
|
||||
|
||||
|
||||
- if @current_gestionnaire && gestionnaire_signed_in? && @champs_private.count > 0
|
||||
- if @current_gestionnaire && gestionnaire_signed_in? && current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id) && @champs_private.count > 0
|
||||
.default-data-block.default_visible
|
||||
.row.show-block#private-fields
|
||||
.header
|
||||
|
@ -65,3 +66,5 @@
|
|||
= (private_fields_count == 1) ? "1 champ" : "#{private_fields_count} champs"
|
||||
.body
|
||||
= render partial: '/dossiers/infos_private_fields'
|
||||
|
||||
= render partial: 'dossiers/avis', locals: { dossier_facade: @facade }
|
||||
|
|
13
app/views/dossiers/_edit_avis.html.haml
Normal file
13
app/views/dossiers/_edit_avis.html.haml
Normal file
|
@ -0,0 +1,13 @@
|
|||
- if current_gestionnaire
|
||||
- avis_for_dossier = current_gestionnaire.avis.for_dossier(dossier_facade.dossier.id).by_latest
|
||||
- if avis_for_dossier.any?
|
||||
.panel.panel-default
|
||||
.panel-body
|
||||
%h4 Votre avis est sollicité sur le dossier :
|
||||
- avis_for_dossier.each do |avis|
|
||||
%hr
|
||||
%p= avis.introduction
|
||||
= simple_form_for avis, url: backoffice_dossier_avis_path(dossier_facade.dossier, avis) do |f|
|
||||
= f.input 'answer', label: "Votre avis"
|
||||
- submit_label = if avis.answer then "Modifier votre avis" else "Enregistrer votre avis" end
|
||||
= f.submit submit_label, class: 'btn btn-default'
|
26
app/views/gestionnaire_mailer/last_week_overview.html.haml
Normal file
26
app/views/gestionnaire_mailer/last_week_overview.html.haml
Normal file
|
@ -0,0 +1,26 @@
|
|||
%table{ align: 'center', border: '0', cellpadding: '0', cellspacing: '0', height: '100%', style: 'background-color: #fafafa', width: '100%' }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ align: 'center', style: 'height: 100%; margin: 0; padding: 30px; width: 100%; border-top: 0', valign: 'top' }
|
||||
%table{ border: '0', cellpadding: '0', cellspacing: '0', style: 'border-collapse: collapse; border: 0; max-width: 600px!important;', width: '100%' }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: 'background: #ffffff none no-repeat center/cover; background-color: #ffffff; background-image: none; background-repeat: no-repeat; background-position: center; background-size: cover; border-top: 0; padding-top: 0;', valign: 'top' }
|
||||
%table{ border: '0', cellpadding: '0', cellspacing: '0', style: 'min-width: 100%; border-collapse: collapse', width: '100%' }
|
||||
%tr
|
||||
%td{ style: 'padding: 0 30px; mso-line-height-rule: exactly; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; ', valign: 'top' }
|
||||
%img{ align: 'middle', alt: 'Logo TPS', src: image_url('mailer/gestionnaire_mailer/logo.png'), style: 'max-width: 125px; padding: 30px 0; display: inline !important; vertical-align: bottom; border: 0; height: auto; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;' }
|
||||
%tr
|
||||
%td{ style: 'padding: 0 30px 30px; word-break: break-word; color: #333333; font-family: Helvetica; font-size: 16px; line-height: 150%; text-align: left; border-bottom: 2px solid #4393F3;', valign: 'top' }
|
||||
Bonjour, voici votre résumé de l'activité de la semaine du #{l(@args[:start_date], format: '%d %B')} au #{l(DateTime.now, format: '%d %B')}.
|
||||
%br
|
||||
%br
|
||||
|
||||
- @args[:procedure_overviews].each do |procedure_overview|
|
||||
= procedure_overview.to_html.html_safe
|
||||
%br
|
||||
%br
|
||||
Bonne journée,
|
||||
%br
|
||||
%br
|
||||
L'équipe Téléprocédures Simplifiées
|
|
@ -1,4 +1,4 @@
|
|||
Bienvenue sur la plateforme TPS
|
||||
Bienvenue sur la plateforme TPS,
|
||||
|
||||
Vous venez d'être assigné à un administrateur sur la plateforme TPS. Voici quelques informations utiles :
|
||||
|
||||
|
@ -7,5 +7,4 @@ Vous venez d'être assigné à un administrateur sur la plateforme TPS. Voici qu
|
|||
|
||||
Bonne journée,
|
||||
|
||||
---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Bienvenue sur la plateforme TPS
|
||||
Bienvenue sur la plateforme TPS,
|
||||
|
||||
Vous venez d'être nommé accompagnateur sur la plateforme TPS. Pour mémoire, voici quelques informations utiles :
|
||||
|
||||
|
@ -8,5 +8,4 @@ Vous venez d'être nommé accompagnateur sur la plateforme TPS. Pour mémoire, v
|
|||
|
||||
Bonne journée,
|
||||
|
||||
---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
Bonjour <%= @invite.email %>
|
||||
Bonjour,
|
||||
|
||||
L'utilisateur <%= @invite.email_sender %> souhaite que vous participiez à l'élaboration d'un dossier sur la plateforme TPS.
|
||||
|
||||
Cette plateforme permet à ses utilisateurs d'établir des dossiers 100% en ligne et de dialoguer avec plusieurs interlocuteurs privilégiés avant d'instruire un dépot.
|
||||
Cette plateforme permet à ses utilisateurs d'établir des dossiers 100 % en ligne et de dialoguer avec plusieurs interlocuteurs privilégiés avant d'instruire un dépot.
|
||||
|
||||
Afin de répondre à cette invitation, merci de vous inscrit avec l'adresse email <%= @invite.email %> sur <%= users_dossiers_invite_url(@invite.id)+"?email=#{@invite.email}" %>.
|
||||
Afin de répondre à cette invitation, merci de vous inscrire avec l'adresse email <%= @invite.email %> sur <%= users_dossiers_invite_url(@invite.id)+"?email=#{@invite.email}" %>.
|
||||
|
||||
Bonne journée.
|
||||
Bonne journée,
|
||||
|
||||
---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
Bonjour <%= @invite.email %>
|
||||
Bonjour,
|
||||
|
||||
L'utilisateur <%= @invite.email_sender %> souhaite que vous participiez à l'élaboration d'un dossier sur la plateforme TPS.
|
||||
|
||||
Pour le consulter, merci de suivre ce lien : <%= users_dossiers_invite_url(@invite.id) %>
|
||||
|
||||
Bonne journée.
|
||||
Bonne journée,
|
||||
|
||||
---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
|
|
9
app/views/layouts/_google_analytics.html.haml
Normal file
9
app/views/layouts/_google_analytics.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
|||
- ua_id = Rails.env.production? ? 'UA-63927236-2' : 'UA-63927236-4'
|
||||
:javascript
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '#{ua_id}', 'auto');
|
||||
ga('send', 'pageview');
|
|
@ -1,7 +1,6 @@
|
|||
.new-header{ class: current_page?(root_path) ? nil : 'new-header-with-border' }
|
||||
.header-inner-content
|
||||
%img.header-logo.pull-left{ src: image_url("header/logo-tps.svg") }
|
||||
= link_to root_path do
|
||||
%img.header-logo{ src: image_url("header/logo-tps.svg") }
|
||||
|
||||
= link_to "Connexion", new_user_session_path, :class => "header-login-button pull-right"
|
||||
|
||||
.clear-fix
|
||||
= link_to "Connexion", new_user_session_path, class: "header-login-button"
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#infos-block
|
||||
.split-hr-left
|
||||
#procedure-list
|
||||
- if current_gestionnaire.avis.any?
|
||||
= link_to backoffice_invitations_path do
|
||||
.procedure-list-element{ class: ('active' if request.path == backoffice_invitations_path) }
|
||||
Invitations
|
||||
- current_gestionnaire.procedures.by_libelle.each do |procedure|
|
||||
= link_to backoffice_dossiers_procedure_path(procedure.id), { title: procedure.libelle } do
|
||||
.procedure-list-element{ class: ('active' if procedure.id.to_s == params[:id]) }
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
.infos
|
||||
#dossier_id= t('dynamics.dossiers.numéro') + @facade.dossier.id.to_s
|
||||
|
||||
#action-block
|
||||
- if gestionnaire_signed_in?
|
||||
- if current_gestionnaire && current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id)
|
||||
#action-block
|
||||
- if !@facade.dossier.read_only? || @facade.dossier.initiated?
|
||||
= link_to 'Passer en instruction', backoffice_dossier_receive_path(@facade.dossier), method: :post, class: 'btn btn-danger btn-block', data: { confirm: "Confirmer vous le passage en instruction de ce dossier ?" }
|
||||
|
||||
|
@ -51,12 +51,12 @@
|
|||
- if notification.liste.size > 1
|
||||
.type= "Plusieurs attributs ont été changés, dont: #{notification.liste.join(" ")}"
|
||||
- else
|
||||
.type= "Un attribut à été changé: #{notification.liste.last}"
|
||||
.type= "Un attribut a été changé: #{notification.liste.last}"
|
||||
- elsif ['piece_justificative'].include?(notification.type_notif)
|
||||
- if notification.liste.size > 1
|
||||
.type= "Plusieurs pièces jointes ont été changés, dont: #{notification.liste.join(" ")}"
|
||||
- else
|
||||
.type= "Une pièce jointe à été changée: #{notification.liste.last}"
|
||||
.type= "Une pièce jointe a été changée: #{notification.liste.last}"
|
||||
- else
|
||||
.type= notification.liste.last
|
||||
.split-hr
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'layouts/left_panels/left_panel_backoffice_dossierscontroller_index'
|
|
@ -15,25 +15,25 @@
|
|||
.procedure-list-element#brouillon{ class: ('active' if @liste == 'brouillon') }
|
||||
Brouillons
|
||||
.badge.progress-bar-default
|
||||
= @user_dossiers.brouillon.count
|
||||
= @user_dossiers.state_brouillon.count
|
||||
|
||||
%a{ :href => "#{url_for users_dossiers_path(liste: 'a_traiter')}", 'data-toggle' => :tooltip, title: 'Les dossiers qui requièrent une action de votre part.' }
|
||||
.procedure-list-element#a_traiter{ class: ('active' if @liste == 'a_traiter') }
|
||||
En construction
|
||||
.badge.progress-bar-danger
|
||||
= @user_dossiers.en_construction.count
|
||||
= @user_dossiers.state_en_construction.count
|
||||
|
||||
%a{ :href => "#{url_for users_dossiers_path(liste: 'en_instruction')}", 'data-toggle' => :tooltip, title: 'Les dossiers en cours d\'examen par l\'administration compétante.' }
|
||||
.procedure-list-element#en_instruction{ class: ('active' if @liste == 'en_instruction') }
|
||||
En instruction
|
||||
.badge.progress-bar-default
|
||||
= @user_dossiers.en_instruction.count
|
||||
= @user_dossiers.state_en_instruction.count
|
||||
|
||||
%a{ :href => "#{url_for users_dossiers_path(liste: 'termine')}", 'data-toggle' => :tooltip, title: 'Les dossiers cloturés qui peuvent être "Accepté", "Refusé" ou "Sans suite".' }
|
||||
.procedure-list-element#termine{ class: ('active' if @liste == 'termine') }
|
||||
Terminé
|
||||
.badge.progress-bar-success
|
||||
= @user_dossiers.termine.count
|
||||
= @user_dossiers.state_termine.count
|
||||
|
||||
%a{ :href => "#{url_for users_dossiers_path(liste: 'invite')}" }
|
||||
.procedure-list-element#invite{ class: ('active' if @liste == 'invite') }
|
||||
|
|
|
@ -1,40 +1,43 @@
|
|||
.col-xs-7.main-info
|
||||
= @facade.dossier.procedure.libelle
|
||||
.col-xs-3.options
|
||||
.row
|
||||
.col-xs-12
|
||||
- if current_gestionnaire.follow?(@facade.dossier.id)
|
||||
= link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), "data-method" => :put, class: "button-navbar-action", id: "suivre_dossier_#{@facade.dossier.id}" do
|
||||
%i.fa.fa-user-times
|
||||
Ne plus suivre
|
||||
- else
|
||||
= link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), 'data-method' => :put, class: 'button-navbar-action', id: "suivre_dossier_#{@facade.dossier.id}" do
|
||||
%i.fa.fa-user-plus
|
||||
Suivre le dossier
|
||||
.row
|
||||
.col-xs-12
|
||||
#invitations.dropdown-toggle{ 'data-toggle' => 'dropdown', 'aria-haspopup' => true, 'aria-expanded' => false }
|
||||
%i.fa.fa-user
|
||||
= t('utils.involved')
|
||||
.badge.progress-bar-info
|
||||
= @facade.dossier.invites.count
|
||||
.dropdown-menu.dropdown-menu-right.dropdown-pannel
|
||||
%h4= t('dynamics.dossiers.followers.title')
|
||||
%ul
|
||||
- unless @facade.followers.empty?
|
||||
- @facade.followers.each do |follower|
|
||||
%li= follower.email
|
||||
- else
|
||||
= t('dynamics.dossiers.followers.empty')
|
||||
%h4= t('dynamics.dossiers.invites.title')
|
||||
%ul
|
||||
- unless @facade.invites.empty?
|
||||
- @facade.invites.each do |invite|
|
||||
%li= invite.email
|
||||
- else
|
||||
= t('dynamics.dossiers.invites.empty')
|
||||
- if current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id)
|
||||
.row
|
||||
.col-xs-12
|
||||
- if current_gestionnaire.follow?(@facade.dossier.id)
|
||||
= link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), "data-method" => :put, class: "button-navbar-action", id: "suivre_dossier_#{@facade.dossier.id}" do
|
||||
%i.fa.fa-user-times
|
||||
Ne plus suivre
|
||||
- else
|
||||
= link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), 'data-method' => :put, class: 'button-navbar-action', id: "suivre_dossier_#{@facade.dossier.id}" do
|
||||
%i.fa.fa-user-plus
|
||||
Suivre le dossier
|
||||
.row
|
||||
.col-xs-12
|
||||
#invitations.dropdown-toggle{ 'data-toggle' => 'dropdown', 'aria-haspopup' => true, 'aria-expanded' => false }
|
||||
%i.fa.fa-user
|
||||
= t('utils.involved')
|
||||
.badge.progress-bar-info
|
||||
= @facade.dossier.invites.count
|
||||
.dropdown-menu.dropdown-menu-right.dropdown-pannel
|
||||
%h4= t('dynamics.dossiers.followers.title')
|
||||
%ul
|
||||
- unless @facade.followers.empty?
|
||||
- @facade.followers.each do |follower|
|
||||
%li= follower.email
|
||||
- else
|
||||
= t('dynamics.dossiers.followers.empty')
|
||||
%h4= t('dynamics.dossiers.invites.title')
|
||||
%p
|
||||
%b Attention, les invitations sur les dossiers vont disparaître en faveur des avis externes situés en bas de la page
|
||||
%ul
|
||||
- unless @facade.invites.empty?
|
||||
- @facade.invites.each do |invite|
|
||||
%li= invite.email
|
||||
- else
|
||||
= t('dynamics.dossiers.invites.empty')
|
||||
|
||||
%li
|
||||
= form_tag invites_dossier_path(dossier_id: @facade.dossier.id), method: :post, class: 'form-inline', id: 'send-invitation' do
|
||||
= text_field_tag :email, '', class: 'form-control', placeholder: 'Envoyer une invitation', id: 'invitation-email'
|
||||
= submit_tag 'Ajouter', class: 'btn btn-success', data: { confirm: "Envoyer l'invitation ?" }
|
||||
%li
|
||||
= form_tag invites_dossier_path(dossier_id: @facade.dossier.id), method: :post, class: 'form-inline', id: 'send-invitation' do
|
||||
= text_field_tag :email, '', class: 'form-control', placeholder: 'Envoyer une invitation', id: 'invitation-email'
|
||||
= submit_tag 'Ajouter', class: 'btn btn-success', data: { confirm: "Envoyer l'invitation ?" }
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
.col-xs-10.main-info
|
||||
INVITATIONS
|
|
@ -3,6 +3,7 @@
|
|||
%meta{ "http-equiv" => "Content-Type", :content => "text/html; charset=UTF-8" }
|
||||
%meta{ "http-equiv" => "X-UA-Compatible", :content => "IE=edge" }
|
||||
%meta{ :name => "turbolinks-cache-control", :content => "no-cache" }
|
||||
%meta{ name: "viewport", content: "width=device-width, initial-scale=1" }
|
||||
= csrf_meta_tags
|
||||
= action_cable_meta_tag
|
||||
|
||||
|
@ -13,7 +14,7 @@
|
|||
= favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32")
|
||||
= favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96")
|
||||
|
||||
= stylesheet_link_tag "new_application", :media => "all", "data-turbolinks-track" => true
|
||||
= stylesheet_link_tag "new_design/new_application", :media => "all", "data-turbolinks-track" => true
|
||||
= stylesheet_link_tag "print", :media => "print", "data-turbolinks-track" => true
|
||||
|
||||
%body
|
||||
|
@ -36,6 +37,7 @@
|
|||
= render partial: "layouts/mailjet_newsletter"
|
||||
|
||||
= javascript_include_tag "application", "data-turbolinks-track" => true
|
||||
= yield :charts_js
|
||||
- if Rails.env == "test"
|
||||
%script{ :type => "text/javascript" }
|
||||
(typeof jQuery !== "undefined") && (jQuery.fx.off = true);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Bonjour
|
||||
Bonjour,
|
||||
%br
|
||||
%br
|
||||
Votre dossier nº --numero_dossier-- a été accepté le --date_de_decision--.
|
||||
|
@ -7,11 +7,13 @@ Votre dossier nº --numero_dossier-- a été accepté le --date_de_decision--.
|
|||
A tout moment, vous pouvez consulter le contenu de vos dossiers et les éventuels commentaires de l'administration à cette adresse : --lien_dossier--
|
||||
%br
|
||||
%br
|
||||
Bonne journée
|
||||
Bonne journée,
|
||||
%br
|
||||
%br
|
||||
\---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
%br
|
||||
Merci de ne pas répondre à ce mail. Postez directement vos questions dans votre dossier sur la plateforme.
|
||||
%br
|
||||
\---
|
||||
—
|
||||
%br
|
||||
%br
|
||||
Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Bonjour
|
||||
Bonjour,
|
||||
%br
|
||||
%br
|
||||
Votre administration vous confirme la bonne réception de votre dossier nº --numero_dossier--.
|
||||
|
@ -7,11 +7,13 @@ Votre administration vous confirme la bonne réception de votre dossier nº --n
|
|||
A tout moment, vous pouvez consulter le contenu de vos dossiers et les éventuels commentaires de l'administration à cette adresse : --lien_dossier--
|
||||
%br
|
||||
%br
|
||||
Bonne journée
|
||||
Bonne journée,
|
||||
%br
|
||||
%br
|
||||
\---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
%br
|
||||
Merci de ne pas répondre à ce mail. Postez directement vos questions dans votre dossier sur la plateforme.
|
||||
%br
|
||||
\---
|
||||
—
|
||||
%br
|
||||
%br
|
||||
Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme.
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
Bonjour
|
||||
Bonjour,
|
||||
%br
|
||||
%br
|
||||
Votre administration vous confirme la bonne réception de votre dossier nº --numero_dossier--. Celui-ci sera instruit dans le délai légal déclaré par votre interlocuteur.
|
||||
%br
|
||||
%br
|
||||
Bonne journée
|
||||
Bonne journée,
|
||||
%br
|
||||
%br
|
||||
\---
|
||||
L'équipe Téléprocédures Simplifiées
|
||||
%br
|
||||
Merci de ne pas répondre à ce mail. Postez directement vos questions dans votre dossier sur la plateforme.
|
||||
%br
|
||||
\---
|
||||
—
|
||||
%br
|
||||
%br
|
||||
Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue