From b5bce36ac65a23e5d3c123876cfb93dae370c7a1 Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Wed, 4 Aug 2021 17:16:28 +0100 Subject: [PATCH 01/19] Update govuk-frontend-2.5.0.min.css --- .../lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css b/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css index 97f12fb2c3..c4d29e3955 100755 --- a/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css +++ b/src/Provider/Provider.Web/wwwroot/lib/govuk-frontend/dist/govuk-frontend-2.5.0.min.css @@ -1,3 +1,3 @@ -@charset "UTF-8";.govuk-link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} +@charset "UTF-8";.govuk-link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} -/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-f38ad40456-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-458f8ea81c-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-a2452cb66f-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-f38c792ac2-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-851b10ccdd-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-62cc6f0a28-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-b89238d840-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-784c21afb8-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@media print{.govuk-link{font-family:sans-serif}}.govuk-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-link:link{color:#005ea5}.govuk-link:visited{color:#4c2c92}.govuk-link:active,.govuk-link:hover{color:#2b8cc4}.govuk-link:focus{color:#0b0c0c}@media print{.govuk-link[href^="/"]:after,.govuk-link[href^="http://"]:after,.govuk-link[href^="https://"]:after{content:" (" attr(href) ")";font-size:90%;word-wrap:break-word}}.govuk-link--muted:active,.govuk-link--muted:hover,.govuk-link--muted:link,.govuk-link--muted:visited{color:#6f777b}.govuk-link--muted:focus,.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#0b0c0c}@media print{.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#000}}.govuk-link--no-visited-state:link,.govuk-link--no-visited-state:visited{color:#005ea5}.govuk-link--no-visited-state:active,.govuk-link--no-visited-state:hover{color:#2b8cc4}.govuk-link--no-visited-state:focus,.govuk-list{color:#0b0c0c}.govuk-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px;padding-left:0;list-style-type:none}@media print{.govuk-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-list{margin-bottom:20px}}.govuk-list .govuk-list{margin-top:10px}.govuk-list>li{margin-bottom:5px}.govuk-list--bullet{padding-left:20px;list-style-type:disc}.govuk-list--number{padding-left:20px;list-style-type:decimal}.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:0}@media (min-width:40.0625em){.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:5px}}.govuk-template{background-color:#dee0e2}.govuk-template__body{margin:0;background-color:#fff}.govuk-heading-xl{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;display:block;margin-top:0;margin-bottom:30px}@media print{.govuk-heading-xl{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-heading-xl{font-size:32pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-xl{margin-bottom:50px}}.govuk-heading-l{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;display:block;margin-top:0;margin-bottom:20px}@media print{.govuk-heading-l{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-heading-l{font-size:24pt;line-height:1.05}}@media (min-width:40.0625em){.govuk-heading-l{margin-bottom:30px}}.govuk-heading-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-heading-m{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-m{margin-bottom:20px}}.govuk-heading-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-heading-s{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-s{margin-bottom:20px}}.govuk-caption-xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-xl{font-size:27px;font-size:1.6875rem;line-height:1.11111}}@media print{.govuk-caption-xl{font-size:18pt;line-height:1.15}}.govuk-caption-l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-l{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-caption-l{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-caption-l{margin-bottom:0}}.govuk-caption-m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;color:#6f777b}@media print{.govuk-caption-m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-caption-m{font-size:14pt;line-height:1.15}}.govuk-body-l,.govuk-body-lead{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:20px}@media print{.govuk-body-l,.govuk-body-lead{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-body-l,.govuk-body-lead{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{margin-bottom:30px}}.govuk-body,.govuk-body-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body,.govuk-body-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-body,.govuk-body-m{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{margin-bottom:20px}}.govuk-body-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;margin-top:0;margin-bottom:15px}@media print{.govuk-body-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-s{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-body-s{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-s{margin-bottom:20px}}.govuk-body-xs{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:12px;font-size:.75rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body-xs{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-xs{font-size:14px;font-size:.875rem;line-height:1.42857}}@media print{.govuk-body-xs{font-size:12pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-xs{margin-bottom:20px}}.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:5px}@media (min-width:40.0625em){.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:10px}}.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:15px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:20px}}.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:5px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:10px}}.govuk-section-break{margin:0;border:0}.govuk-section-break--xl{margin-top:30px;margin-bottom:30px}@media (min-width:40.0625em){.govuk-section-break--xl{margin-top:50px;margin-bottom:50px}}.govuk-section-break--l{margin-top:20px;margin-bottom:20px}@media (min-width:40.0625em){.govuk-section-break--l{margin-top:30px;margin-bottom:30px}}.govuk-section-break--m{margin-top:15px;margin-bottom:15px}@media (min-width:40.0625em){.govuk-section-break--m{margin-top:20px;margin-bottom:20px}}.govuk-section-break--visible{border-bottom:1px solid #bfc1c3}.govuk-form-group{margin-bottom:20px}@media (min-width:40.0625em){.govuk-form-group{margin-bottom:30px}}.govuk-form-group .govuk-form-group:last-of-type{margin-bottom:0}.govuk-form-group--error{padding-left:15px;border-left:5px solid #b10e1e}.govuk-form-group--error .govuk-form-group{padding:0;border:0}.govuk-grid-row{margin-right:-15px;margin-left:-15px}.govuk-grid-row:after{content:"";display:block;clear:both}.govuk-grid-column-one-quarter{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-quarter{width:25%;float:left}}.govuk-grid-column-one-third{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-third{width:33.3333%;float:left}}.govuk-grid-column-one-half{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-half{width:50%;float:left}}.govuk-grid-column-two-thirds{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-two-thirds{width:66.6666%;float:left}}.govuk-grid-column-three-quarters{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-three-quarters{width:75%;float:left}}.govuk-grid-column-full{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-full{width:100%;float:left}}.govuk-grid-column-one-quarter-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-quarter-from-desktop{width:25%;float:left}}.govuk-grid-column-one-third-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-third-from-desktop{width:33.3333%;float:left}}.govuk-grid-column-one-half-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-half-from-desktop{width:50%;float:left}}.govuk-grid-column-two-thirds-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-two-thirds-from-desktop{width:66.6666%;float:left}}.govuk-grid-column-three-quarters-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-three-quarters-from-desktop{width:75%;float:left}}.govuk-grid-column-full-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-full-from-desktop{width:100%;float:left}}.govuk-main-wrapper{padding-top:20px;padding-bottom:20px;display:block}@media (min-width:40.0625em){.govuk-main-wrapper{padding-top:30px;padding-bottom:30px}}.govuk-main-wrapper--l{padding-top:30px}@media (min-width:40.0625em){.govuk-main-wrapper--l{padding-top:50px}}.govuk-width-container{max-width:960px;margin:0 15px}@media (min-width:40.0625em){.govuk-width-container{margin:0 30px}}@media (min-width:1020px){.govuk-width-container{margin:0 auto}}.govuk-accordion{margin-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-accordion{margin-bottom:30px}}.govuk-accordion__section{border-top:1px solid #bfc1c3}.govuk-accordion__section-header{padding-bottom:15px}.govuk-accordion__section-heading{margin-top:0;margin-bottom:0}.govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:0;padding-top:15px}@media print{.govuk-accordion__section-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-accordion__section-button{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-accordion__section-button{font-size:18pt;line-height:1.15}}.govuk-accordion__section-summary{margin-top:10px;margin-bottom:0}.js-enabled .govuk-accordion__section-content{display:none;padding-top:15px;padding-bottom:15px}@media (min-width:40.0625em){.js-enabled .govuk-accordion__section-content{padding-top:15px;padding-bottom:15px}}.js-enabled .govuk-accordion__section-content>:last-child{margin-bottom:0}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-content{display:block}.js-enabled .govuk-accordion__open-all{font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline;border-width:0;color:#005ea5;background:none;cursor:pointer}@media (min-width:40.0625em){.js-enabled .govuk-accordion__open-all{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.js-enabled .govuk-accordion__open-all{font-size:14pt;line-height:1.2;font-family:sans-serif}}.js-enabled .govuk-accordion__open-all:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;background:none}.js-enabled .govuk-accordion__section-header{position:relative;padding-right:40px;cursor:pointer}.js-enabled .govuk-accordion__section-header:hover{background-color:#f8f8f8}.js-enabled .govuk-accordion__section-header--focused{outline:3px solid #ffbf47;outline-offset:0}.js-enabled .govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100%;margin-top:0;margin-bottom:0;margin-left:0;padding-top:15px;padding-bottom:0;padding-left:0;border-width:0;color:#005ea5;background:none;text-align:left;cursor:pointer}@media print{.js-enabled .govuk-accordion__section-button{font-family:sans-serif}}.js-enabled .govuk-accordion__section-button:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;outline:none;background:none}.js-enabled .govuk-accordion__section-button:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.js-enabled .govuk-accordion__controls{text-align:right}.js-enabled .govuk-accordion__icon{position:absolute;top:50%;right:15px;width:16px;height:16px;margin-top:-8px}.js-enabled .govuk-accordion__icon:after,.js-enabled .govuk-accordion__icon:before{content:"";box-sizing:border-box;position:absolute;top:0;right:0;bottom:0;left:0;width:25%;height:25%;margin:auto;border:2px solid rgba(0,0,0,0);background-color:#0b0c0c}.js-enabled .govuk-accordion__icon:before{width:100%}.js-enabled .govuk-accordion__icon:after{height:100%}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__icon:after{content:" ";display:none}.govuk-back-link{font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;position:relative;margin-top:15px;margin-bottom:15px;padding-left:14px;border-bottom:1px solid #0b0c0c;text-decoration:none}@media (min-width:40.0625em){.govuk-back-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-back-link{font-size:14pt;line-height:1.2;font-family:sans-serif}}.govuk-back-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#0b0c0c}@media print{.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#000}}.govuk-back-link:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 50%,100% 100%,100% 0);clip-path:polygon(0 50%,100% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:5px 6px 5px 0;border-right-color:inherit;content:"";position:absolute;left:0;margin:auto}.govuk-back-link:before{top:-1px;bottom:1px}.govuk-breadcrumbs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;margin-top:15px;margin-bottom:10px}@media print{.govuk-breadcrumbs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-breadcrumbs{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-breadcrumbs{font-size:14pt;line-height:1.2;color:#000}}.govuk-breadcrumbs__list{margin:0;padding:0;list-style-type:none}.govuk-breadcrumbs__list:after{content:"";display:block;clear:both}.govuk-breadcrumbs__list-item{display:inline-block;position:relative;margin-bottom:5px;margin-left:10px;padding-left:15.655px;float:left}.govuk-breadcrumbs__list-item:before{content:"";display:block;position:absolute;top:-1px;bottom:1px;left:-3.31px;width:7px;height:7px;margin:auto 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);border:solid;border-width:1px 1px 0 0;border-color:#6f777b}.govuk-breadcrumbs__list-item:first-child{margin-left:0;padding-left:0}.govuk-breadcrumbs__list-item:first-child:before{content:none;display:none}.govuk-breadcrumbs__link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media print{.govuk-breadcrumbs__link{font-family:sans-serif}}.govuk-breadcrumbs__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#0b0c0c}@media print{.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#000}}.govuk-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.1875;box-sizing:border-box;display:inline-block;position:relative;width:100%;margin-top:0;margin-bottom:22px;padding:7px 10px;border:2px solid rgba(0,0,0,0);border-radius:0;color:#fff;background-color:#00823b;box-shadow:0 2px 0 #003618;text-align:center;vertical-align:top;cursor:pointer;-webkit-appearance:none}@media print{.govuk-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-button{font-size:19px;font-size:1.1875rem;line-height:1}}@media print{.govuk-button{font-size:14pt;line-height:19px}}.govuk-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-button{margin-bottom:32px;width:auto}}.govuk-button:active,.govuk-button:hover,.govuk-button:link,.govuk-button:visited{color:#fff;text-decoration:none}.govuk-button::-moz-focus-inner{padding:0;border:0}.govuk-button:focus,.govuk-button:hover{background-color:#00692f}.govuk-button:active{top:2px;box-shadow:none}.govuk-button:before{content:"";display:block;position:absolute;top:-2px;right:-2px;bottom:-4px;left:-2px;background:rgba(0,0,0,0)}.govuk-button:active:before{top:-4px}.govuk-button--disabled,.govuk-button[disabled=disabled],.govuk-button[disabled]{opacity:.5;background:#00823b}.govuk-button--disabled:hover,.govuk-button[disabled=disabled]:hover,.govuk-button[disabled]:hover{background-color:#00823b;cursor:default}.govuk-button--disabled:focus,.govuk-button[disabled=disabled]:focus,.govuk-button[disabled]:focus{outline:none}.govuk-button--disabled:active,.govuk-button[disabled=disabled]:active,.govuk-button[disabled]:active{top:0;box-shadow:0 2px 0 #003618}.govuk-button--start{font-weight:700;font-size:18px;font-size:1.125rem;line-height:1;min-height:auto;padding:8px 40px 8px 15px;background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer.png);background-repeat:no-repeat;background-position:100% 50%}@media (min-width:40.0625em){.govuk-button--start{font-size:24px;font-size:1.5rem;line-height:1}}@media print{.govuk-button--start{font-size:18pt;line-height:1}}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-button--start{background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer-2x.png);background-size:30px 19px}}.govuk-button,.govuk-button--start{padding-top:9px;padding-bottom:6px}.govuk-error-message{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;clear:both;color:#b10e1e}@media print{.govuk-error-message{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-message{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-message{font-size:14pt;line-height:1.15}}.govuk-fieldset{margin:0;padding:0;border:0}.govuk-fieldset:after{content:"";display:block;clear:both}.govuk-fieldset__legend{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;box-sizing:border-box;display:table;max-width:100%;margin-bottom:10px;padding:0;overflow:hidden;white-space:normal}@media print{.govuk-fieldset__legend{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend{font-size:14pt;line-height:1.15;color:#000}}.govuk-fieldset__legend--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-fieldset__legend--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-fieldset__legend--xl{font-size:32pt;line-height:1.15}}.govuk-fieldset__legend--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-fieldset__legend--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-fieldset__legend--l{font-size:24pt;line-height:1.05}}.govuk-fieldset__legend--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:15px}@media print{.govuk-fieldset__legend--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-fieldset__legend--m{font-size:18pt;line-height:1.15}}.govuk-fieldset__legend--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-fieldset__legend--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend--s{font-size:14pt;line-height:1.15}}.govuk-fieldset__heading{margin:0;font-size:inherit;font-weight:inherit}.govuk-hint{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;color:#6f777b}@media print{.govuk-hint{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-hint{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-hint{font-size:14pt;line-height:1.15}}.govuk-label:not(.govuk-label--m):not(.govuk-label--l):not(.govuk-label--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend:not(.govuk-fieldset__legend--m):not(.govuk-fieldset__legend--l):not(.govuk-fieldset__legend--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend+.govuk-hint{margin-top:-5px}.govuk-label{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;display:block;margin-bottom:5px}@media print{.govuk-label{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label{font-size:14pt;line-height:1.15;color:#000}}.govuk-label--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-label--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-label--xl{font-size:32pt;line-height:1.15}}.govuk-label--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-label--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-label--l{font-size:24pt;line-height:1.05}}.govuk-label--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:10px}@media print{.govuk-label--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-label--m{font-size:18pt;line-height:1.15}}.govuk-label--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-label--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label--s{font-size:14pt;line-height:1.15}}.govuk-label-wrapper{margin:0}.govuk-checkboxes__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-checkboxes__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-checkboxes__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-checkboxes__item{font-size:14pt;line-height:1.15}}.govuk-checkboxes__item:last-child,.govuk-checkboxes__item:last-of-type{margin-bottom:0}.govuk-checkboxes__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-checkboxes__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-checkboxes__hint{display:block;padding-right:15px;padding-left:15px}.govuk-checkboxes__input+.govuk-checkboxes__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;background:rgba(0,0,0,0)}.govuk-checkboxes__input+.govuk-checkboxes__label:after{content:"";position:absolute;top:11px;left:9px;width:18px;height:7px;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);border:solid;border-width:0 0 5px 5px;border-top-color:rgba(0,0,0,0);opacity:0;background:rgba(0,0,0,0)}.govuk-checkboxes__input:focus+.govuk-checkboxes__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 3px #ffbf47}.govuk-checkboxes__input:checked+.govuk-checkboxes__label:after{opacity:1}.govuk-checkboxes__input:disabled,.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{cursor:default}.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{opacity:.5}.govuk-checkboxes__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-checkboxes__conditional{margin-bottom:20px}}.js-enabled .govuk-checkboxes__conditional--hidden{display:none}.govuk-checkboxes__conditional>:last-child{margin-bottom:0}.govuk-character-count{margin-bottom:20px}@media (min-width:40.0625em){.govuk-character-count{margin-bottom:30px}}.govuk-character-count .govuk-form-group,.govuk-character-count .govuk-textarea{margin-bottom:5px}.govuk-character-count .govuk-textarea--error{padding:3px}.govuk-character-count__message{margin-top:0;margin-bottom:0}.govuk-character-count__message--disabled{visibility:hidden}.govuk-summary-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin:0 0 20px}@media print{.govuk-summary-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-summary-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-summary-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-summary-list{display:table;width:100%;margin-bottom:30px}}@media (max-width:40.0525em){.govuk-summary-list__row{margin-bottom:15px;border-bottom:1px solid #bfc1c3}}@media (min-width:40.0625em){.govuk-summary-list__row{display:table-row}}.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{margin:0}@media (min-width:40.0625em){.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{display:table-cell;padding-right:20px;padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}}.govuk-summary-list__actions{margin-bottom:15px}@media (min-width:40.0625em){.govuk-summary-list__actions{padding-right:0}}.govuk-summary-list__key{margin-bottom:5px;font-weight:700;word-break:break-word}@media (min-width:40.0625em){.govuk-summary-list__key{width:30%}}@media (max-width:40.0525em){.govuk-summary-list__value{margin-bottom:15px}}.govuk-summary-list__value>p{margin-bottom:10px}.govuk-summary-list__value>:last-child{margin-bottom:0}.govuk-summary-list__actions-list{width:100%;margin:0;padding:0}@media (min-width:40.0625em){.govuk-summary-list__actions-list{text-align:right}}.govuk-summary-list__actions-list-item{display:inline;margin-right:10px;padding-right:10px}.govuk-summary-list__actions-list-item:not(:last-child){border-right:1px solid #bfc1c3}.govuk-summary-list__actions-list-item:last-child{margin-right:0;padding-right:0;border:0}.govuk-summary-list--no-border .govuk-summary-list__actions,.govuk-summary-list--no-border .govuk-summary-list__key,.govuk-summary-list--no-border .govuk-summary-list__row,.govuk-summary-list--no-border .govuk-summary-list__value{border:0}.govuk-input{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;width:100%;height:40px;margin-top:0;padding:5px;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media print{.govuk-input{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-input{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-input{font-size:14pt;line-height:1.15}}.govuk-input:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-input::-webkit-inner-spin-button,.govuk-input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.govuk-input[type=number]{-moz-appearance:textfield}.govuk-input--error{border:4px solid #b10e1e}.govuk-input--width-30{max-width:59ex}.govuk-input--width-20{max-width:41ex}.govuk-input--width-10{max-width:23ex}.govuk-input--width-5{max-width:10.8ex}.govuk-input--width-4{max-width:9ex}.govuk-input--width-3{max-width:7.2ex}.govuk-input--width-2{max-width:5.4ex}.govuk-date-input{font-size:0}.govuk-date-input:after{content:"";display:block;clear:both}.govuk-date-input__item{display:inline-block;margin-right:20px;margin-bottom:0}.govuk-date-input__label{display:block}.govuk-date-input__input{margin-bottom:0}.govuk-details{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-bottom:20px;display:block}@media print{.govuk-details{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-details{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-details{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-details{margin-bottom:30px}}.govuk-details__summary{display:inline-block;position:relative;margin-bottom:5px;padding-left:25px;color:#005ea5;cursor:pointer}.govuk-details__summary-text{text-decoration:underline}.govuk-details__summary:hover{color:#2b8cc4}.govuk-details__summary:focus{outline:4px solid #ffbf47;outline-offset:-1px;color:#0b0c0c;background:#ffbf47}.govuk-details__summary::-webkit-details-marker{display:none}.govuk-details__summary:before{content:"";position:absolute;top:0;bottom:0;left:0;margin:auto;display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,100% 50%,0 100%);clip-path:polygon(0 0,100% 50%,0 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:7px 0 7px 12.124px;border-left-color:inherit}.govuk-details[open]>.govuk-details__summary:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:12.124px 7px 0;border-top-color:inherit}.govuk-details__text{padding:15px 15px 15px 20px;border-left:5px solid #bfc1c3}.govuk-details__text p{margin-top:0;margin-bottom:20px}.govuk-details__text>:last-child{margin-bottom:0}.govuk-error-summary{color:#0b0c0c;padding:15px;margin-bottom:30px;border:4px solid #b10e1e}@media print{.govuk-error-summary{color:#000}}@media (min-width:40.0625em){.govuk-error-summary{padding:20px;margin-bottom:50px}}.govuk-error-summary:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-error-summary{border:5px solid #b10e1e}}.govuk-error-summary__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:15px}@media print{.govuk-error-summary__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__title{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-error-summary__title{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-error-summary__title{margin-bottom:20px}}.govuk-error-summary__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-error-summary__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__body{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-summary__body{font-size:14pt;line-height:1.15}}.govuk-error-summary__body p{margin-top:0;margin-bottom:15px}@media (min-width:40.0625em){.govuk-error-summary__body p{margin-bottom:20px}}.govuk-error-summary__list{margin-top:0;margin-bottom:0}.govuk-error-summary__list a{font-weight:700}.govuk-error-summary__list a:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-error-summary__list a:active,.govuk-error-summary__list a:hover,.govuk-error-summary__list a:link,.govuk-error-summary__list a:visited{color:#b10e1e}.govuk-error-summary__list a:focus{color:#0b0c0c}.govuk-file-upload{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c}@media print{.govuk-file-upload{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-file-upload{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-file-upload{font-size:14pt;line-height:1.15;color:#000}}.govuk-file-upload:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-file-upload--error{border:4px solid #b10e1e}.govuk-footer{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;padding-top:25px;padding-bottom:15px;border-top:1px solid #a1acb2;color:#454a4c;background:#dee0e2}@media print{.govuk-footer{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-footer{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-footer{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-footer{padding-top:40px;padding-bottom:25px}}.govuk-footer__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-footer__link:link,.govuk-footer__link:visited{color:#454a4c}.govuk-footer__link:active,.govuk-footer__link:hover{color:#171819}.govuk-footer__link:focus{color:#0b0c0c}.govuk-footer__section-break{margin:0 0 30px;border:0;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__section-break{margin-bottom:50px}}.govuk-footer__meta{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:end;-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.govuk-footer__meta-item{margin-right:15px;margin-bottom:25px;margin-left:15px}.govuk-footer__meta-item--grow{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}@media (max-width:40.0525em){.govuk-footer__meta-item--grow{-webkit-flex-basis:320px;-ms-flex-preferred-size:320px;flex-basis:320px}}.govuk-footer__licence-logo{display:inline-block;margin-right:10px;vertical-align:top}@media (max-width:48.0525em){.govuk-footer__licence-logo{margin-bottom:15px}}.govuk-footer__licence-description{display:inline-block}.govuk-footer__copyright-logo{display:inline-block;min-width:125px;padding-top:112px;background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest.png);background-repeat:no-repeat;background-position:50% 0;background-size:125px 102px;text-align:center;text-decoration:none;white-space:nowrap}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-footer__copyright-logo{background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest-2x.png)}}.govuk-footer__inline-list{margin-top:0;margin-bottom:15px;padding:0}.govuk-footer__meta-custom{margin-bottom:20px}.govuk-footer__inline-list-item{display:inline-block;margin-right:15px;margin-bottom:5px}.govuk-footer__heading{margin-bottom:25px;padding-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__heading{margin-bottom:40px}}@media (max-width:40.0525em){.govuk-footer__heading{padding-bottom:10px}}.govuk-footer__navigation{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.govuk-footer__section{display:inline-block;margin-right:15px;margin-bottom:30px;margin-left:15px;vertical-align:top;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}@media (max-width:48.0525em){.govuk-footer__section{-webkit-flex-basis:200px;-ms-flex-preferred-size:200px;flex-basis:200px}}@media (min-width:48.0625em){.govuk-footer__section:first-child{-webkit-box-flex:2;-webkit-flex-grow:2;-ms-flex-positive:2;flex-grow:2}}.govuk-footer__list{margin:0;padding:0;list-style:none;-webkit-column-gap:30px;column-gap:30px}@media (min-width:48.0625em){.govuk-footer__list--columns-2{-webkit-column-count:2;column-count:2}.govuk-footer__list--columns-3{-webkit-column-count:3;column-count:3}}.govuk-footer__list-item{margin-bottom:15px}@media (min-width:40.0625em){.govuk-footer__list-item{margin-bottom:20px}}.govuk-footer__list-item:last-child{margin-bottom:0}.govuk-header{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;border-bottom:10px solid #fff;color:#fff;background:#0b0c0c}@media print{.govuk-header{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header{font-size:14pt;line-height:1.2}}.govuk-header__container--full-width{padding:0 15px;border-color:#005ea5}.govuk-header__container--full-width .govuk-header__menu-button{right:15px}.govuk-header__container{position:relative;margin-bottom:-10px;padding-top:10px;border-bottom:10px solid #005ea5}.govuk-header__container:after{content:"";display:block;clear:both}.govuk-header__logotype{margin-right:5px}.govuk-header__logotype-crown{margin-right:1px;fill:currentColor;vertical-align:middle}.govuk-header__logotype-crown-fallback-image{width:36px;height:32px;border:0;vertical-align:middle}.govuk-header__product-name{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:inline-table;padding-right:10px}@media print{.govuk-header__product-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__product-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__product-name{font-size:18pt;line-height:1.15}}.govuk-header__link{text-decoration:none}.govuk-header__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-header__link:link,.govuk-header__link:visited{color:#fff}.govuk-header__link:hover{text-decoration:underline}.govuk-header__link:focus{color:#0b0c0c}.govuk-header__link--homepage{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;font-size:30px;line-height:30px}@media print{.govuk-header__link--homepage{font-family:sans-serif}}.govuk-header__link--homepage:link,.govuk-header__link--homepage:visited{text-decoration:none}.govuk-header__link--homepage:active,.govuk-header__link--homepage:hover{margin-bottom:-1px;border-bottom:1px solid}.govuk-header__link--service-name{display:inline-block;margin-bottom:10px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111}@media print{.govuk-header__link--service-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__link--service-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__link--service-name{font-size:18pt;line-height:1.15}}.govuk-header__logo{margin-bottom:10px;padding-right:50px}@media (min-width:40.0625em){.govuk-header__logo{margin-bottom:10px}}@media (min-width:48.0625em){.govuk-header__logo{width:33.33%;padding-right:0;float:left;vertical-align:top}}@media (min-width:48.0625em){.govuk-header__content{width:66.66%;float:left}}.govuk-header__menu-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;display:none;position:absolute;top:20px;right:0;margin:0;padding:0;border:0;color:#fff;background:none}@media print{.govuk-header__menu-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__menu-button{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__menu-button{font-size:14pt;line-height:1.2}}.govuk-header__menu-button:hover{text-decoration:underline}.govuk-header__menu-button:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:8.66px 5px 0;border-top-color:inherit;content:"";margin-left:5px}.govuk-header__menu-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-header__menu-button{top:15px}}.govuk-header__menu-button--open:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(50% 0,0 100%,100% 100%);clip-path:polygon(50% 0,0 100%,100% 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:0 5px 8.66px;border-bottom-color:inherit}.govuk-header__navigation{display:block;margin:0;padding:0;list-style:none}@media (min-width:40.0625em){.govuk-header__navigation{margin-bottom:10px}}.js-enabled .govuk-header__menu-button{display:block}@media (min-width:48.0625em){.js-enabled .govuk-header__menu-button{display:none}}.js-enabled .govuk-header__navigation{display:none}@media (min-width:48.0625em){.js-enabled .govuk-header__navigation{display:block}}.js-enabled .govuk-header__navigation--open{display:block}@media (min-width:48.0625em){.govuk-header__navigation--end{margin:0;padding:5px 0;text-align:right}}.govuk-header__navigation--no-service-name{padding-top:40px}.govuk-header__navigation-item{padding:10px 0;border-bottom:1px solid #2e3133}@media (min-width:48.0625em){.govuk-header__navigation-item{display:inline-block;margin-right:15px;padding:5px 0;border:0}}.govuk-header__navigation-item a{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.14286;white-space:nowrap}@media print{.govuk-header__navigation-item a{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__navigation-item a{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__navigation-item a{font-size:14pt;line-height:1.2}}.govuk-header__navigation-item--active a:hover,.govuk-header__navigation-item--active a:link,.govuk-header__navigation-item--active a:visited{color:#1d8feb}.govuk-header__navigation-item--active a:focus{color:#0b0c0c}.govuk-header__navigation-item:last-child{margin-right:0}@media print{.govuk-header{border-bottom-width:0;color:#0b0c0c;background:rgba(0,0,0,0)}.govuk-header__logotype-crown-fallback-image{display:none}.govuk-header__link:link,.govuk-header__link:visited{color:#0b0c0c}.govuk-header__link:after{display:none}}.govuk-header__logotype-crown,.govuk-header__logotype-crown-fallback-image{position:relative;top:-4px}.govuk-header{padding-top:3px}.govuk-inset-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;padding:15px;margin-top:20px;margin-bottom:20px;clear:both;border-left:10px solid #bfc1c3}@media print{.govuk-inset-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-inset-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-inset-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-inset-text{margin-top:30px;margin-bottom:30px}}.govuk-inset-text :first-child{margin-top:0}.govuk-inset-text :last-child,.govuk-inset-text :only-child{margin-bottom:0}.govuk-panel{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;margin-bottom:15px;padding:35px;border:5px solid rgba(0,0,0,0);text-align:center}@media print{.govuk-panel{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-panel{font-size:14pt;line-height:1.15}}@media (max-width:40.0525em){.govuk-panel{padding:25px}}.govuk-panel--confirmation{color:#fff;background:#28a197}.govuk-panel__title{margin-top:0;margin-bottom:30px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375}@media print{.govuk-panel__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__title{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-panel__title{font-size:32pt;line-height:1.15}}.govuk-panel__title:last-child{margin-bottom:0}.govuk-panel__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:24px;font-size:1.5rem;line-height:1.04167}@media print{.govuk-panel__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__body{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-panel__body{font-size:24pt;line-height:1.05}}.govuk-tag{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.25;display:inline-block;padding:4px 8px 1px;outline:2px solid rgba(0,0,0,0);outline-offset:-2px;color:#fff;background-color:#005ea5;letter-spacing:1px;text-decoration:none;text-transform:uppercase}@media print{.govuk-tag{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tag{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-tag{font-size:14pt;line-height:1.25}}.govuk-tag--inactive{background-color:#6f777b}.govuk-phase-banner{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}.govuk-phase-banner__content{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;display:table;margin:0}@media print{.govuk-phase-banner__content{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-phase-banner__content{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-phase-banner__content{font-size:14pt;line-height:1.2;color:#000}}.govuk-phase-banner__content__tag{margin-right:10px}.govuk-phase-banner__text{display:table-cell;vertical-align:baseline}.govuk-tabs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-top:5px;margin-bottom:20px}@media print{.govuk-tabs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-tabs{margin-top:5px;margin-bottom:30px}}.govuk-tabs__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-bottom:5px}@media print{.govuk-tabs__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__title{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__title{font-size:14pt;line-height:1.15}}.govuk-tabs__list{margin:0;padding:0;list-style:none}@media (max-width:40.0525em){.govuk-tabs__list{margin-bottom:20px}}@media (max-width:40.0525em) and (min-width:40.0625em){.govuk-tabs__list{margin-bottom:30px}}.govuk-tabs__list-item{margin-left:25px}.govuk-tabs__list-item:before{content:"— ";margin-left:-25px;padding-right:5px}.govuk-tabs__tab{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:inline-block;padding-top:10px;padding-bottom:10px}.govuk-tabs__tab:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-tabs__tab:link{color:#005ea5}.govuk-tabs__tab:visited{color:#4c2c92}.govuk-tabs__tab:active,.govuk-tabs__tab:hover{color:#2b8cc4}.govuk-tabs__tab:focus{color:#0b0c0c}@media print{.govuk-tabs__tab{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__tab{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__tab{font-size:14pt;line-height:1.15}}.govuk-tabs__tab[aria-current=true]{color:#0b0c0c;text-decoration:none}.govuk-tabs__panel{margin-bottom:30px}@media (min-width:40.0625em){.govuk-tabs__panel{margin-bottom:50px}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__list{border-bottom:1px solid #bfc1c3}.js-enabled .govuk-tabs__list:after{content:"";display:block;clear:both}.js-enabled .govuk-tabs__list-item{margin-left:0}.js-enabled .govuk-tabs__list-item:before{content:none}.js-enabled .govuk-tabs__title{display:none}.js-enabled .govuk-tabs__tab{margin-right:5px;padding-right:20px;padding-left:20px;float:left;color:#0b0c0c;background-color:#f8f8f8;text-align:center;text-decoration:none}.js-enabled .govuk-tabs__tab--selected{margin-top:-5px;margin-bottom:-1px;padding:14px 19px 16px;border:1px solid #bfc1c3;border-bottom:0;color:#0b0c0c;background-color:#fff}.js-enabled .govuk-tabs__tab--selected:focus{background-color:rgba(0,0,0,0)}.js-enabled .govuk-tabs__panel{margin-bottom:0;padding:30px 20px;border:1px solid #bfc1c3;border-top:0}}@media (min-width:40.0625em) and (min-width:40.0625em){.js-enabled .govuk-tabs__panel{margin-bottom:0}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__panel--hidden{display:none}.js-enabled .govuk-tabs__panel>:last-child{margin-bottom:0}}.govuk-radios__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-radios__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__item{font-size:14pt;line-height:1.15}}.govuk-radios__item:last-child,.govuk-radios__item:last-of-type{margin-bottom:0}.govuk-radios__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-radios__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-radios__hint{display:block;padding-right:15px;padding-left:15px}.govuk-radios__input+.govuk-radios__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;border-radius:50%;background:rgba(0,0,0,0)}.govuk-radios__input+.govuk-radios__label:after{content:"";position:absolute;top:10px;left:10px;width:0;height:0;border:10px solid;border-radius:50%;opacity:0;background:currentColor}.govuk-radios__input:focus+.govuk-radios__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 4px #ffbf47}.govuk-radios__input:checked+.govuk-radios__label:after{opacity:1}.govuk-radios__input:disabled,.govuk-radios__input:disabled+.govuk-radios__label{cursor:default}.govuk-radios__input:disabled+.govuk-radios__label{opacity:.5}@media (min-width:40.0625em){.govuk-radios--inline:after{content:"";display:block;clear:both}.govuk-radios--inline .govuk-radios__item{margin-right:20px;float:left;clear:none}}.govuk-radios--inline.govuk-radios--conditional .govuk-radios__item{margin-right:0;float:none}.govuk-radios__divider{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:40px;margin-bottom:10px;text-align:center}@media print{.govuk-radios__divider{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__divider{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__divider{font-size:14pt;line-height:1.15;color:#000}}.govuk-radios__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-radios__conditional{margin-bottom:20px}}.js-enabled .govuk-radios__conditional--hidden{display:none}.govuk-radios__conditional>:last-child{margin-bottom:0}.govuk-select{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;max-width:100%;height:40px;padding:5px;border:2px solid #0b0c0c}@media print{.govuk-select{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-select{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-select{font-size:14pt;line-height:1.25}}.govuk-select:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-select:focus::-ms-value,.govuk-select option:active,.govuk-select option:checked{color:#fff;background-color:#005ea5}.govuk-select--error{border:4px solid #b10e1e}.govuk-skip-link{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:14px;font-size:.875rem;line-height:1.14286;display:block;padding:10px 15px}.govuk-skip-link:active,.govuk-skip-link:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}@media print{.govuk-skip-link{font-family:sans-serif}}.govuk-skip-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#0b0c0c}@media print{.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#000}}@media (min-width:40.0625em){.govuk-skip-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-skip-link{font-size:14pt;line-height:1.2}}.govuk-table{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:100%;margin-bottom:20px;border-spacing:0;border-collapse:collapse}@media print{.govuk-table{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-table{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-table{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-table{margin-bottom:30px}}.govuk-table__header{font-weight:700}.govuk-table__cell,.govuk-table__header{padding:10px 20px 10px 0;border-bottom:1px solid #bfc1c3;text-align:left}.govuk-table__cell--numeric{font-family:ntatabularnumbers,nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400}@media print{.govuk-table__cell--numeric{font-family:sans-serif}}.govuk-table__cell--numeric,.govuk-table__header--numeric{text-align:right}.govuk-table__cell:last-child,.govuk-table__header:last-child{padding-right:0}.govuk-table__caption{font-weight:700;display:table-caption;text-align:left}.govuk-textarea{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;display:block;width:100%;min-height:40px;margin-bottom:20px;padding:5px;resize:vertical;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none}@media print{.govuk-textarea{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-textarea{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-textarea{font-size:14pt;line-height:1.25}}.govuk-textarea:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-textarea{margin-bottom:30px}}.govuk-textarea--error{border:4px solid #b10e1e}.govuk-warning-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;position:relative;margin-bottom:20px;padding:10px 0}@media print{.govuk-warning-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-warning-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-warning-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-warning-text{margin-bottom:30px}}.govuk-warning-text__assistive{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;padding:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;border:0!important;white-space:nowrap!important}.govuk-warning-text__icon{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;position:absolute;top:50%;left:0;min-width:32px;min-height:29px;margin-top:-20px;padding-top:3px;border:3px solid #0b0c0c;border-radius:50%;color:#fff;background:#0b0c0c;font-size:1.6em;line-height:29px;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media print{.govuk-warning-text__icon{font-family:sans-serif}}.govuk-warning-text__text{display:block;padding-left:50px}.govuk-clearfix:after{content:"";display:block;clear:both}.govuk-visually-hidden{padding:0!important;border:0!important}.govuk-visually-hidden,.govuk-visually-hidden-focusable{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important}.govuk-visually-hidden-focusable:active,.govuk-visually-hidden-focusable:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}.govuk-\!-display-inline{display:inline!important}.govuk-\!-display-inline-block{display:inline-block!important}.govuk-\!-display-block{display:block!important}.govuk-\!-margin-0{margin:0!important}@media (min-width:40.0625em){.govuk-\!-margin-0{margin:0!important}}.govuk-\!-margin-top-0{margin-top:0!important}@media (min-width:40.0625em){.govuk-\!-margin-top-0{margin-top:0!important}}.govuk-\!-margin-right-0{margin-right:0!important}@media (min-width:40.0625em){.govuk-\!-margin-right-0{margin-right:0!important}}.govuk-\!-margin-bottom-0{margin-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-0{margin-bottom:0!important}}.govuk-\!-margin-left-0{margin-left:0!important}@media (min-width:40.0625em){.govuk-\!-margin-left-0{margin-left:0!important}}.govuk-\!-margin-1{margin:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-1{margin:5px!important}}.govuk-\!-margin-top-1{margin-top:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-1{margin-top:5px!important}}.govuk-\!-margin-right-1{margin-right:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-1{margin-right:5px!important}}.govuk-\!-margin-bottom-1{margin-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-1{margin-bottom:5px!important}}.govuk-\!-margin-left-1{margin-left:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-1{margin-left:5px!important}}.govuk-\!-margin-2{margin:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-2{margin:10px!important}}.govuk-\!-margin-top-2{margin-top:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-2{margin-top:10px!important}}.govuk-\!-margin-right-2{margin-right:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-2{margin-right:10px!important}}.govuk-\!-margin-bottom-2{margin-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-2{margin-bottom:10px!important}}.govuk-\!-margin-left-2{margin-left:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-2{margin-left:10px!important}}.govuk-\!-margin-3{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-3{margin:15px!important}}.govuk-\!-margin-top-3{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-3{margin-top:15px!important}}.govuk-\!-margin-right-3{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-3{margin-right:15px!important}}.govuk-\!-margin-bottom-3{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-3{margin-bottom:15px!important}}.govuk-\!-margin-left-3{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-3{margin-left:15px!important}}.govuk-\!-margin-4{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-4{margin:20px!important}}.govuk-\!-margin-top-4{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-4{margin-top:20px!important}}.govuk-\!-margin-right-4{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-4{margin-right:20px!important}}.govuk-\!-margin-bottom-4{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-4{margin-bottom:20px!important}}.govuk-\!-margin-left-4{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-4{margin-left:20px!important}}.govuk-\!-margin-5{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-5{margin:25px!important}}.govuk-\!-margin-top-5{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-5{margin-top:25px!important}}.govuk-\!-margin-right-5{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-5{margin-right:25px!important}}.govuk-\!-margin-bottom-5{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-5{margin-bottom:25px!important}}.govuk-\!-margin-left-5{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-5{margin-left:25px!important}}.govuk-\!-margin-6{margin:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-6{margin:30px!important}}.govuk-\!-margin-top-6{margin-top:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-6{margin-top:30px!important}}.govuk-\!-margin-right-6{margin-right:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-6{margin-right:30px!important}}.govuk-\!-margin-bottom-6{margin-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-6{margin-bottom:30px!important}}.govuk-\!-margin-left-6{margin-left:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-6{margin-left:30px!important}}.govuk-\!-margin-7{margin:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-7{margin:40px!important}}.govuk-\!-margin-top-7{margin-top:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-7{margin-top:40px!important}}.govuk-\!-margin-right-7{margin-right:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-7{margin-right:40px!important}}.govuk-\!-margin-bottom-7{margin-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-7{margin-bottom:40px!important}}.govuk-\!-margin-left-7{margin-left:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-7{margin-left:40px!important}}.govuk-\!-margin-8{margin:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-8{margin:50px!important}}.govuk-\!-margin-top-8{margin-top:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-8{margin-top:50px!important}}.govuk-\!-margin-right-8{margin-right:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-8{margin-right:50px!important}}.govuk-\!-margin-bottom-8{margin-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-8{margin-bottom:50px!important}}.govuk-\!-margin-left-8{margin-left:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-8{margin-left:50px!important}}.govuk-\!-margin-9{margin:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-9{margin:60px!important}}.govuk-\!-margin-top-9{margin-top:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-9{margin-top:60px!important}}.govuk-\!-margin-right-9{margin-right:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-9{margin-right:60px!important}}.govuk-\!-margin-bottom-9{margin-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-9{margin-bottom:60px!important}}.govuk-\!-margin-left-9{margin-left:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-9{margin-left:60px!important}}.govuk-\!-padding-0{padding:0!important}@media (min-width:40.0625em){.govuk-\!-padding-0{padding:0!important}}.govuk-\!-padding-top-0{padding-top:0!important}@media (min-width:40.0625em){.govuk-\!-padding-top-0{padding-top:0!important}}.govuk-\!-padding-right-0{padding-right:0!important}@media (min-width:40.0625em){.govuk-\!-padding-right-0{padding-right:0!important}}.govuk-\!-padding-bottom-0{padding-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-0{padding-bottom:0!important}}.govuk-\!-padding-left-0{padding-left:0!important}@media (min-width:40.0625em){.govuk-\!-padding-left-0{padding-left:0!important}}.govuk-\!-padding-1{padding:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-1{padding:5px!important}}.govuk-\!-padding-top-1{padding-top:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-1{padding-top:5px!important}}.govuk-\!-padding-right-1{padding-right:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-1{padding-right:5px!important}}.govuk-\!-padding-bottom-1{padding-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-1{padding-bottom:5px!important}}.govuk-\!-padding-left-1{padding-left:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-1{padding-left:5px!important}}.govuk-\!-padding-2{padding:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-2{padding:10px!important}}.govuk-\!-padding-top-2{padding-top:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-2{padding-top:10px!important}}.govuk-\!-padding-right-2{padding-right:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-2{padding-right:10px!important}}.govuk-\!-padding-bottom-2{padding-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-2{padding-bottom:10px!important}}.govuk-\!-padding-left-2{padding-left:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-2{padding-left:10px!important}}.govuk-\!-padding-3{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-3{padding:15px!important}}.govuk-\!-padding-top-3{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-3{padding-top:15px!important}}.govuk-\!-padding-right-3{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-3{padding-right:15px!important}}.govuk-\!-padding-bottom-3{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-3{padding-bottom:15px!important}}.govuk-\!-padding-left-3{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-3{padding-left:15px!important}}.govuk-\!-padding-4{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-4{padding:20px!important}}.govuk-\!-padding-top-4{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-4{padding-top:20px!important}}.govuk-\!-padding-right-4{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-4{padding-right:20px!important}}.govuk-\!-padding-bottom-4{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-4{padding-bottom:20px!important}}.govuk-\!-padding-left-4{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-4{padding-left:20px!important}}.govuk-\!-padding-5{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-5{padding:25px!important}}.govuk-\!-padding-top-5{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-5{padding-top:25px!important}}.govuk-\!-padding-right-5{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-5{padding-right:25px!important}}.govuk-\!-padding-bottom-5{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-5{padding-bottom:25px!important}}.govuk-\!-padding-left-5{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-5{padding-left:25px!important}}.govuk-\!-padding-6{padding:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-6{padding:30px!important}}.govuk-\!-padding-top-6{padding-top:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-6{padding-top:30px!important}}.govuk-\!-padding-right-6{padding-right:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-6{padding-right:30px!important}}.govuk-\!-padding-bottom-6{padding-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-6{padding-bottom:30px!important}}.govuk-\!-padding-left-6{padding-left:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-6{padding-left:30px!important}}.govuk-\!-padding-7{padding:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-7{padding:40px!important}}.govuk-\!-padding-top-7{padding-top:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-7{padding-top:40px!important}}.govuk-\!-padding-right-7{padding-right:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-7{padding-right:40px!important}}.govuk-\!-padding-bottom-7{padding-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-7{padding-bottom:40px!important}}.govuk-\!-padding-left-7{padding-left:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-7{padding-left:40px!important}}.govuk-\!-padding-8{padding:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-8{padding:50px!important}}.govuk-\!-padding-top-8{padding-top:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-8{padding-top:50px!important}}.govuk-\!-padding-right-8{padding-right:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-8{padding-right:50px!important}}.govuk-\!-padding-bottom-8{padding-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-8{padding-bottom:50px!important}}.govuk-\!-padding-left-8{padding-left:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-8{padding-left:50px!important}}.govuk-\!-padding-9{padding:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-9{padding:60px!important}}.govuk-\!-padding-top-9{padding-top:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-9{padding-top:60px!important}}.govuk-\!-padding-right-9{padding-right:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-9{padding-right:60px!important}}.govuk-\!-padding-bottom-9{padding-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-9{padding-bottom:60px!important}}.govuk-\!-padding-left-9{padding-left:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-9{padding-left:60px!important}}.govuk-\!-font-size-80{font-size:53px!important;font-size:3.3125rem!important;line-height:1.03774!important}@media (min-width:40.0625em){.govuk-\!-font-size-80{font-size:80px!important;font-size:5rem!important;line-height:1!important}}@media print{.govuk-\!-font-size-80{font-size:53pt!important;line-height:1.1!important}}.govuk-\!-font-size-48{font-size:32px!important;font-size:2rem!important;line-height:1.09375!important}@media (min-width:40.0625em){.govuk-\!-font-size-48{font-size:48px!important;font-size:3rem!important;line-height:1.04167!important}}@media print{.govuk-\!-font-size-48{font-size:32pt!important;line-height:1.15!important}}.govuk-\!-font-size-36{font-size:24px!important;font-size:1.5rem!important;line-height:1.04167!important}@media (min-width:40.0625em){.govuk-\!-font-size-36{font-size:36px!important;font-size:2.25rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-36{font-size:24pt!important;line-height:1.05!important}}.govuk-\!-font-size-27{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-27{font-size:27px!important;font-size:1.6875rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-27{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-24{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-24{font-size:24px!important;font-size:1.5rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-24{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-19{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-19{font-size:19px!important;font-size:1.1875rem!important;line-height:1.31579!important}}@media print{.govuk-\!-font-size-19{font-size:14pt!important;line-height:1.15!important}}.govuk-\!-font-size-16{font-size:14px!important;font-size:.875rem!important;line-height:1.14286!important}@media (min-width:40.0625em){.govuk-\!-font-size-16{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-16{font-size:14pt!important;line-height:1.2!important}}.govuk-\!-font-size-14{font-size:12px!important;font-size:.75rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-14{font-size:14px!important;font-size:.875rem!important;line-height:1.42857!important}}@media print{.govuk-\!-font-size-14{font-size:12pt!important;line-height:1.2!important}}.govuk-\!-font-weight-regular{font-weight:400!important}.govuk-\!-font-weight-bold{font-weight:700!important}.govuk-\!-width-full,.govuk-\!-width-three-quarters{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-three-quarters{width:75%!important}}.govuk-\!-width-two-thirds{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-two-thirds{width:66.66%!important}}.govuk-\!-width-one-half{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-half{width:50%!important}}.govuk-\!-width-one-third{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-third{width:33.33%!important}}.govuk-\!-width-one-quarter{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-quarter{width:25%!important}} \ No newline at end of file +/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-2c037cf7e1-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-f38ad40456-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-458f8ea81c-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:nta;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-fb2676462a-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-a2452cb66f-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-f38c792ac2-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-498ea8ffe2-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-851b10ccdd-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/light-tabular-62cc6f0a28-v1.woff) format("woff");font-weight:400;font-style:normal;font-display:fallback}@font-face{font-family:ntatabularnumbers;src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot);src:url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-357fdfbcc3-v1.eot?#iefix) format("embedded-opentype"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-b89238d840-v1.woff2) format("woff2"),url(/lib/govuk-frontend/dist/assets/fonts/bold-tabular-784c21afb8-v1.woff) format("woff");font-weight:700;font-style:normal;font-display:fallback}@media print{.govuk-link{font-family:sans-serif}}.govuk-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-link:link{color:#005ea5}.govuk-link:visited{color:#4c2c92}.govuk-link:active,.govuk-link:hover{color:#2b8cc4}.govuk-link:focus{color:#0b0c0c}@media print{.govuk-link[href^="/"]:after,.govuk-link[href^="http://"]:after,.govuk-link[href^="https://"]:after{content:" (" attr(href) ")";font-size:90%;word-wrap:break-word}}.govuk-link--muted:active,.govuk-link--muted:hover,.govuk-link--muted:link,.govuk-link--muted:visited{color:#6f777b}.govuk-link--muted:focus,.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#0b0c0c}@media print{.govuk-link--text-colour:active,.govuk-link--text-colour:focus,.govuk-link--text-colour:hover,.govuk-link--text-colour:link,.govuk-link--text-colour:visited{color:#000}}.govuk-link--no-visited-state:link,.govuk-link--no-visited-state:visited{color:#005ea5}.govuk-link--no-visited-state:active,.govuk-link--no-visited-state:hover{color:#2b8cc4}.govuk-link--no-visited-state:focus,.govuk-list{color:#0b0c0c}.govuk-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px;padding-left:0;list-style-type:none}@media print{.govuk-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-list{margin-bottom:20px}}.govuk-list .govuk-list{margin-top:10px}.govuk-list>li{margin-bottom:5px}.govuk-list--bullet{padding-left:20px;list-style-type:disc}.govuk-list--number{padding-left:20px;list-style-type:decimal}.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:0}@media (min-width:40.0625em){.govuk-list--bullet>li,.govuk-list--number>li{margin-bottom:5px}}.govuk-template{background-color:#dee0e2}.govuk-template__body{margin:0;background-color:#fff}.govuk-heading-xl{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;display:block;margin-top:0;margin-bottom:30px}@media print{.govuk-heading-xl{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-heading-xl{font-size:32pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-xl{margin-bottom:50px}}.govuk-heading-l{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;display:block;margin-top:0;margin-bottom:20px}@media print{.govuk-heading-l{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-heading-l{font-size:24pt;line-height:1.05}}@media (min-width:40.0625em){.govuk-heading-l{margin-bottom:30px}}.govuk-heading-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-heading-m{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-m{margin-bottom:20px}}.govuk-heading-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-top:0;margin-bottom:15px}@media print{.govuk-heading-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-heading-s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-heading-s{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-heading-s{margin-bottom:20px}}.govuk-caption-xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-xl{font-size:27px;font-size:1.6875rem;line-height:1.11111}}@media print{.govuk-caption-xl{font-size:18pt;line-height:1.15}}.govuk-caption-l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:block;margin-bottom:5px;color:#6f777b}@media print{.govuk-caption-l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-l{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-caption-l{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-caption-l{margin-bottom:0}}.govuk-caption-m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;color:#6f777b}@media print{.govuk-caption-m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-caption-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-caption-m{font-size:14pt;line-height:1.15}}.govuk-body-l,.govuk-body-lead{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:20px}@media print{.govuk-body-l,.govuk-body-lead{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-body-l,.govuk-body-lead{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body-l,.govuk-body-lead{margin-bottom:30px}}.govuk-body,.govuk-body-m{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body,.govuk-body-m{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-body,.govuk-body-m{font-size:14pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-body,.govuk-body-m{margin-bottom:20px}}.govuk-body-s{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;margin-top:0;margin-bottom:15px}@media print{.govuk-body-s{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-s{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-body-s{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-s{margin-bottom:20px}}.govuk-body-xs{color:#0b0c0c;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:12px;font-size:.75rem;line-height:1.25;margin-top:0;margin-bottom:15px}@media print{.govuk-body-xs{color:#000;font-family:sans-serif}}@media (min-width:40.0625em){.govuk-body-xs{font-size:14px;font-size:.875rem;line-height:1.42857}}@media print{.govuk-body-xs{font-size:12pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-body-xs{margin-bottom:20px}}.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:5px}@media (min-width:40.0625em){.govuk-body-l+.govuk-heading-l,.govuk-body-lead+.govuk-heading-l{padding-top:10px}}.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:15px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-l,.govuk-body-m+.govuk-heading-l,.govuk-body-s+.govuk-heading-l,.govuk-list+.govuk-heading-l{padding-top:20px}}.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:5px}@media (min-width:40.0625em){.govuk-body+.govuk-heading-m,.govuk-body+.govuk-heading-s,.govuk-body-m+.govuk-heading-m,.govuk-body-m+.govuk-heading-s,.govuk-body-s+.govuk-heading-m,.govuk-body-s+.govuk-heading-s,.govuk-list+.govuk-heading-m,.govuk-list+.govuk-heading-s{padding-top:10px}}.govuk-section-break{margin:0;border:0}.govuk-section-break--xl{margin-top:30px;margin-bottom:30px}@media (min-width:40.0625em){.govuk-section-break--xl{margin-top:50px;margin-bottom:50px}}.govuk-section-break--l{margin-top:20px;margin-bottom:20px}@media (min-width:40.0625em){.govuk-section-break--l{margin-top:30px;margin-bottom:30px}}.govuk-section-break--m{margin-top:15px;margin-bottom:15px}@media (min-width:40.0625em){.govuk-section-break--m{margin-top:20px;margin-bottom:20px}}.govuk-section-break--visible{border-bottom:1px solid #bfc1c3}.govuk-form-group{margin-bottom:20px}@media (min-width:40.0625em){.govuk-form-group{margin-bottom:30px}}.govuk-form-group .govuk-form-group:last-of-type{margin-bottom:0}.govuk-form-group--error{padding-left:15px;border-left:5px solid #b10e1e}.govuk-form-group--error .govuk-form-group{padding:0;border:0}.govuk-grid-row{margin-right:-15px;margin-left:-15px}.govuk-grid-row:after{content:"";display:block;clear:both}.govuk-grid-column-one-quarter{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-quarter{width:25%;float:left}}.govuk-grid-column-one-third{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-third{width:33.3333%;float:left}}.govuk-grid-column-one-half{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-one-half{width:50%;float:left}}.govuk-grid-column-two-thirds{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-two-thirds{width:66.6666%;float:left}}.govuk-grid-column-three-quarters{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-three-quarters{width:75%;float:left}}.govuk-grid-column-full{box-sizing:border-box;width:100%;padding:0 15px}@media (min-width:40.0625em){.govuk-grid-column-full{width:100%;float:left}}.govuk-grid-column-one-quarter-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-quarter-from-desktop{width:25%;float:left}}.govuk-grid-column-one-third-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-third-from-desktop{width:33.3333%;float:left}}.govuk-grid-column-one-half-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-one-half-from-desktop{width:50%;float:left}}.govuk-grid-column-two-thirds-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-two-thirds-from-desktop{width:66.6666%;float:left}}.govuk-grid-column-three-quarters-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-three-quarters-from-desktop{width:75%;float:left}}.govuk-grid-column-full-from-desktop{box-sizing:border-box;padding:0 15px}@media (min-width:48.0625em){.govuk-grid-column-full-from-desktop{width:100%;float:left}}.govuk-main-wrapper{padding-top:20px;padding-bottom:20px;display:block}@media (min-width:40.0625em){.govuk-main-wrapper{padding-top:30px;padding-bottom:30px}}.govuk-main-wrapper--l{padding-top:30px}@media (min-width:40.0625em){.govuk-main-wrapper--l{padding-top:50px}}.govuk-width-container{max-width:960px;margin:0 15px}@media (min-width:40.0625em){.govuk-width-container{margin:0 30px}}@media (min-width:1020px){.govuk-width-container{margin:0 auto}}.govuk-accordion{margin-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-accordion{margin-bottom:30px}}.govuk-accordion__section{border-top:1px solid #bfc1c3}.govuk-accordion__section-header{padding-bottom:15px}.govuk-accordion__section-heading{margin-top:0;margin-bottom:0}.govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:0;padding-top:15px}@media print{.govuk-accordion__section-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-accordion__section-button{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-accordion__section-button{font-size:18pt;line-height:1.15}}.govuk-accordion__section-summary{margin-top:10px;margin-bottom:0}.js-enabled .govuk-accordion__section-content{display:none;padding-top:15px;padding-bottom:15px}@media (min-width:40.0625em){.js-enabled .govuk-accordion__section-content{padding-top:15px;padding-bottom:15px}}.js-enabled .govuk-accordion__section-content>:last-child{margin-bottom:0}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-content{display:block}.js-enabled .govuk-accordion__open-all{font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline;border-width:0;color:#005ea5;background:none;cursor:pointer}@media (min-width:40.0625em){.js-enabled .govuk-accordion__open-all{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.js-enabled .govuk-accordion__open-all{font-size:14pt;line-height:1.2;font-family:sans-serif}}.js-enabled .govuk-accordion__open-all:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;background:none}.js-enabled .govuk-accordion__section-header{position:relative;padding-right:40px;cursor:pointer}.js-enabled .govuk-accordion__section-header:hover{background-color:#f8f8f8}.js-enabled .govuk-accordion__section-header--focused{outline:3px solid #ffbf47;outline-offset:0}.js-enabled .govuk-accordion__section-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100%;margin-top:0;margin-bottom:0;margin-left:0;padding-top:15px;padding-bottom:0;padding-left:0;border-width:0;color:#005ea5;background:none;text-align:left;cursor:pointer}@media print{.js-enabled .govuk-accordion__section-button{font-family:sans-serif}}.js-enabled .govuk-accordion__section-button:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47;outline:none;background:none}.js-enabled .govuk-accordion__section-button:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.js-enabled .govuk-accordion__controls{text-align:right}.js-enabled .govuk-accordion__icon{position:absolute;top:50%;right:15px;width:16px;height:16px;margin-top:-8px}.js-enabled .govuk-accordion__icon:after,.js-enabled .govuk-accordion__icon:before{content:"";box-sizing:border-box;position:absolute;top:0;right:0;bottom:0;left:0;width:25%;height:25%;margin:auto;border:2px solid rgba(0,0,0,0);background-color:#0b0c0c}.js-enabled .govuk-accordion__icon:before{width:100%}.js-enabled .govuk-accordion__icon:after{height:100%}.js-enabled .govuk-accordion__section--expanded .govuk-accordion__icon:after{content:" ";display:none}.govuk-back-link{font-size:14px;font-size:.875rem;line-height:1.14286;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;position:relative;margin-top:15px;margin-bottom:15px;padding-left:14px;border-bottom:1px solid #0b0c0c;text-decoration:none}@media (min-width:40.0625em){.govuk-back-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-back-link{font-size:14pt;line-height:1.2;font-family:sans-serif}}.govuk-back-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#0b0c0c}@media print{.govuk-back-link:active,.govuk-back-link:focus,.govuk-back-link:hover,.govuk-back-link:link,.govuk-back-link:visited{color:#000}}.govuk-back-link:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 50%,100% 100%,100% 0);clip-path:polygon(0 50%,100% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:5px 6px 5px 0;border-right-color:inherit;content:"";position:absolute;left:0;margin:auto}.govuk-back-link:before{top:-1px;bottom:1px}.govuk-breadcrumbs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;margin-top:15px;margin-bottom:10px}@media print{.govuk-breadcrumbs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-breadcrumbs{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-breadcrumbs{font-size:14pt;line-height:1.2;color:#000}}.govuk-breadcrumbs__list{margin:0;padding:0;list-style-type:none}.govuk-breadcrumbs__list:after{content:"";display:block;clear:both}.govuk-breadcrumbs__list-item{display:inline-block;position:relative;margin-bottom:5px;margin-left:10px;padding-left:15.655px;float:left}.govuk-breadcrumbs__list-item:before{content:"";display:block;position:absolute;top:-1px;bottom:1px;left:-3.31px;width:7px;height:7px;margin:auto 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);border:solid;border-width:1px 1px 0 0;border-color:#6f777b}.govuk-breadcrumbs__list-item:first-child{margin-left:0;padding-left:0}.govuk-breadcrumbs__list-item:first-child:before{content:none;display:none}.govuk-breadcrumbs__link{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media print{.govuk-breadcrumbs__link{font-family:sans-serif}}.govuk-breadcrumbs__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#0b0c0c}@media print{.govuk-breadcrumbs__link:active,.govuk-breadcrumbs__link:focus,.govuk-breadcrumbs__link:hover,.govuk-breadcrumbs__link:link,.govuk-breadcrumbs__link:visited{color:#000}}.govuk-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.1875;box-sizing:border-box;display:inline-block;position:relative;width:100%;margin-top:0;margin-bottom:22px;padding:7px 10px;border:2px solid rgba(0,0,0,0);border-radius:0;color:#fff;background-color:#00823b;box-shadow:0 2px 0 #003618;text-align:center;vertical-align:top;cursor:pointer;-webkit-appearance:none}@media print{.govuk-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-button{font-size:19px;font-size:1.1875rem;line-height:1}}@media print{.govuk-button{font-size:14pt;line-height:19px}}.govuk-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-button{margin-bottom:32px;width:auto}}.govuk-button:active,.govuk-button:hover,.govuk-button:link,.govuk-button:visited{color:#fff;text-decoration:none}.govuk-button::-moz-focus-inner{padding:0;border:0}.govuk-button:focus,.govuk-button:hover{background-color:#00692f}.govuk-button:active{top:2px;box-shadow:none}.govuk-button:before{content:"";display:block;position:absolute;top:-2px;right:-2px;bottom:-4px;left:-2px;background:rgba(0,0,0,0)}.govuk-button:active:before{top:-4px}.govuk-button--disabled,.govuk-button[disabled=disabled],.govuk-button[disabled]{opacity:.5;background:#00823b}.govuk-button--disabled:hover,.govuk-button[disabled=disabled]:hover,.govuk-button[disabled]:hover{background-color:#00823b;cursor:default}.govuk-button--disabled:focus,.govuk-button[disabled=disabled]:focus,.govuk-button[disabled]:focus{outline:none}.govuk-button--disabled:active,.govuk-button[disabled=disabled]:active,.govuk-button[disabled]:active{top:0;box-shadow:0 2px 0 #003618}.govuk-button--start{font-weight:700;font-size:18px;font-size:1.125rem;line-height:1;min-height:auto;padding:8px 40px 8px 15px;background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer.png);background-repeat:no-repeat;background-position:100% 50%}@media (min-width:40.0625em){.govuk-button--start{font-size:24px;font-size:1.5rem;line-height:1}}@media print{.govuk-button--start{font-size:18pt;line-height:1}}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-button--start{background-image:url(/lib/govuk-frontend/dist/assets/images/icon-pointer-2x.png);background-size:30px 19px}}.govuk-button,.govuk-button--start{padding-top:9px;padding-bottom:6px}.govuk-error-message{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;clear:both;color:#b10e1e}@media print{.govuk-error-message{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-message{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-message{font-size:14pt;line-height:1.15}}.govuk-fieldset{margin:0;padding:0;border:0}.govuk-fieldset:after{content:"";display:block;clear:both}.govuk-fieldset__legend{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;box-sizing:border-box;display:table;max-width:100%;margin-bottom:10px;padding:0;overflow:hidden;white-space:normal}@media print{.govuk-fieldset__legend{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend{font-size:14pt;line-height:1.15;color:#000}}.govuk-fieldset__legend--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-fieldset__legend--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-fieldset__legend--xl{font-size:32pt;line-height:1.15}}.govuk-fieldset__legend--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-fieldset__legend--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-fieldset__legend--l{font-size:24pt;line-height:1.05}}.govuk-fieldset__legend--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:15px}@media print{.govuk-fieldset__legend--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-fieldset__legend--m{font-size:18pt;line-height:1.15}}.govuk-fieldset__legend--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-fieldset__legend--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-fieldset__legend--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-fieldset__legend--s{font-size:14pt;line-height:1.15}}.govuk-fieldset__heading{margin:0;font-size:inherit;font-weight:inherit}.govuk-hint{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;margin-bottom:15px;color:#6f777b}@media print{.govuk-hint{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-hint{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-hint{font-size:14pt;line-height:1.15}}.govuk-label:not(.govuk-label--m):not(.govuk-label--l):not(.govuk-label--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend:not(.govuk-fieldset__legend--m):not(.govuk-fieldset__legend--l):not(.govuk-fieldset__legend--xl)+.govuk-hint{margin-bottom:10px}.govuk-fieldset__legend+.govuk-hint{margin-top:-5px}.govuk-label{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;display:block;margin-bottom:5px}@media print{.govuk-label{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label{font-size:14pt;line-height:1.15;color:#000}}.govuk-label--xl{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375;margin-bottom:15px}@media print{.govuk-label--xl{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--xl{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-label--xl{font-size:32pt;line-height:1.15}}.govuk-label--l{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:24px;font-size:1.5rem;line-height:1.04167;margin-bottom:15px}@media print{.govuk-label--l{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--l{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-label--l{font-size:24pt;line-height:1.05}}.govuk-label--m{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-bottom:10px}@media print{.govuk-label--m{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--m{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-label--m{font-size:18pt;line-height:1.15}}.govuk-label--s{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-label--s{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-label--s{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-label--s{font-size:14pt;line-height:1.15}}.govuk-label-wrapper{margin:0}.govuk-checkboxes__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-checkboxes__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-checkboxes__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-checkboxes__item{font-size:14pt;line-height:1.15}}.govuk-checkboxes__item:last-child,.govuk-checkboxes__item:last-of-type{margin-bottom:0}.govuk-checkboxes__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-checkboxes__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-checkboxes__hint{display:block;padding-right:15px;padding-left:15px}.govuk-checkboxes__input+.govuk-checkboxes__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;background:rgba(0,0,0,0)}.govuk-checkboxes__input+.govuk-checkboxes__label:after{content:"";position:absolute;top:11px;left:9px;width:18px;height:7px;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);border:solid;border-width:0 0 5px 5px;border-top-color:rgba(0,0,0,0);opacity:0;background:rgba(0,0,0,0)}.govuk-checkboxes__input:focus+.govuk-checkboxes__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 3px #ffbf47}.govuk-checkboxes__input:checked+.govuk-checkboxes__label:after{opacity:1}.govuk-checkboxes__input:disabled,.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{cursor:default}.govuk-checkboxes__input:disabled+.govuk-checkboxes__label{opacity:.5}.govuk-checkboxes__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-checkboxes__conditional{margin-bottom:20px}}.js-enabled .govuk-checkboxes__conditional--hidden{display:none}.govuk-checkboxes__conditional>:last-child{margin-bottom:0}.govuk-character-count{margin-bottom:20px}@media (min-width:40.0625em){.govuk-character-count{margin-bottom:30px}}.govuk-character-count .govuk-form-group,.govuk-character-count .govuk-textarea{margin-bottom:5px}.govuk-character-count .govuk-textarea--error{padding:3px}.govuk-character-count__message{margin-top:0;margin-bottom:0}.govuk-character-count__message--disabled{visibility:hidden}.govuk-summary-list{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin:0 0 20px}@media print{.govuk-summary-list{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-summary-list{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-summary-list{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-summary-list{display:table;width:100%;margin-bottom:30px}}@media (max-width:40.0525em){.govuk-summary-list__row{margin-bottom:15px;border-bottom:1px solid #bfc1c3}}@media (min-width:40.0625em){.govuk-summary-list__row{display:table-row}}.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{margin:0}@media (min-width:40.0625em){.govuk-summary-list__actions,.govuk-summary-list__key,.govuk-summary-list__value{display:table-cell;padding-right:20px;padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}}.govuk-summary-list__actions{margin-bottom:15px}@media (min-width:40.0625em){.govuk-summary-list__actions{padding-right:0}}.govuk-summary-list__key{margin-bottom:5px;font-weight:700;word-break:break-word}@media (min-width:40.0625em){.govuk-summary-list__key{width:30%}}@media (max-width:40.0525em){.govuk-summary-list__value{margin-bottom:15px}}.govuk-summary-list__value>p{margin-bottom:10px}.govuk-summary-list__value>:last-child{margin-bottom:0}.govuk-summary-list__actions-list{width:100%;margin:0;padding:0}@media (min-width:40.0625em){.govuk-summary-list__actions-list{text-align:right}}.govuk-summary-list__actions-list-item{display:inline;margin-right:10px;padding-right:10px}.govuk-summary-list__actions-list-item:not(:last-child){border-right:1px solid #bfc1c3}.govuk-summary-list__actions-list-item:last-child{margin-right:0;padding-right:0;border:0}.govuk-summary-list--no-border .govuk-summary-list__actions,.govuk-summary-list--no-border .govuk-summary-list__key,.govuk-summary-list--no-border .govuk-summary-list__row,.govuk-summary-list--no-border .govuk-summary-list__value{border:0}.govuk-input{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;width:100%;height:40px;margin-top:0;padding:5px;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media print{.govuk-input{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-input{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-input{font-size:14pt;line-height:1.15}}.govuk-input:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-input::-webkit-inner-spin-button,.govuk-input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.govuk-input[type=number]{-moz-appearance:textfield}.govuk-input--error{border:4px solid #b10e1e}.govuk-input--width-30{max-width:59ex}.govuk-input--width-20{max-width:41ex}.govuk-input--width-10{max-width:23ex}.govuk-input--width-5{max-width:10.8ex}.govuk-input--width-4{max-width:9ex}.govuk-input--width-3{max-width:7.2ex}.govuk-input--width-2{max-width:5.4ex}.govuk-date-input{font-size:0}.govuk-date-input:after{content:"";display:block;clear:both}.govuk-date-input__item{display:inline-block;margin-right:20px;margin-bottom:0}.govuk-date-input__label{display:block}.govuk-date-input__input{margin-bottom:0}.govuk-details{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-bottom:20px;display:block}@media print{.govuk-details{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-details{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-details{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-details{margin-bottom:30px}}.govuk-details__summary{display:inline-block;position:relative;margin-bottom:5px;padding-left:25px;color:#005ea5;cursor:pointer}.govuk-details__summary-text{text-decoration:underline}.govuk-details__summary:hover{color:#2b8cc4}.govuk-details__summary:focus{outline:4px solid #ffbf47;outline-offset:-1px;color:#0b0c0c;background:#ffbf47}.govuk-details__summary::-webkit-details-marker{display:none}.govuk-details__summary:before{content:"";position:absolute;top:0;bottom:0;left:0;margin:auto;display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,100% 50%,0 100%);clip-path:polygon(0 0,100% 50%,0 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:7px 0 7px 12.124px;border-left-color:inherit}.govuk-details[open]>.govuk-details__summary:before{display:block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:12.124px 7px 0;border-top-color:inherit}.govuk-details__text{padding:15px 15px 15px 20px;border-left:5px solid #bfc1c3}.govuk-details__text p{margin-top:0;margin-bottom:20px}.govuk-details__text>:last-child{margin-bottom:0}.govuk-error-summary{color:#0b0c0c;padding:15px;margin-bottom:30px;border:4px solid #b10e1e}@media print{.govuk-error-summary{color:#000}}@media (min-width:40.0625em){.govuk-error-summary{padding:20px;margin-bottom:50px}}.govuk-error-summary:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-error-summary{border:5px solid #b10e1e}}.govuk-error-summary__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111;margin-top:0;margin-bottom:15px}@media print{.govuk-error-summary__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__title{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-error-summary__title{font-size:18pt;line-height:1.15}}@media (min-width:40.0625em){.govuk-error-summary__title{margin-bottom:20px}}.govuk-error-summary__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25}@media print{.govuk-error-summary__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-error-summary__body{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-error-summary__body{font-size:14pt;line-height:1.15}}.govuk-error-summary__body p{margin-top:0;margin-bottom:15px}@media (min-width:40.0625em){.govuk-error-summary__body p{margin-bottom:20px}}.govuk-error-summary__list{margin-top:0;margin-bottom:0}.govuk-error-summary__list a{font-weight:700}.govuk-error-summary__list a:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-error-summary__list a:active,.govuk-error-summary__list a:hover,.govuk-error-summary__list a:link,.govuk-error-summary__list a:visited{color:#b10e1e}.govuk-error-summary__list a:focus{color:#0b0c0c}.govuk-file-upload{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c}@media print{.govuk-file-upload{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-file-upload{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-file-upload{font-size:14pt;line-height:1.15;color:#000}}.govuk-file-upload:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-file-upload--error{border:4px solid #b10e1e}.govuk-footer{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;padding-top:25px;padding-bottom:15px;border-top:1px solid #a1acb2;color:#454a4c;background:#dee0e2}@media print{.govuk-footer{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-footer{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-footer{font-size:14pt;line-height:1.2}}@media (min-width:40.0625em){.govuk-footer{padding-top:40px;padding-bottom:25px}}.govuk-footer__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-footer__link:link,.govuk-footer__link:visited{color:#454a4c}.govuk-footer__link:active,.govuk-footer__link:hover{color:#171819}.govuk-footer__link:focus{color:#0b0c0c}.govuk-footer__section-break{margin:0 0 30px;border:0;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__section-break{margin-bottom:50px}}.govuk-footer__meta{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:end;-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.govuk-footer__meta-item{margin-right:15px;margin-bottom:25px;margin-left:15px}.govuk-footer__meta-item--grow{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}@media (max-width:40.0525em){.govuk-footer__meta-item--grow{-webkit-flex-basis:320px;-ms-flex-preferred-size:320px;flex-basis:320px}}.govuk-footer__licence-logo{display:inline-block;margin-right:10px;vertical-align:top}@media (max-width:48.0525em){.govuk-footer__licence-logo{margin-bottom:15px}}.govuk-footer__licence-description{display:inline-block}.govuk-footer__copyright-logo{display:inline-block;min-width:125px;padding-top:112px;background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest.png);background-repeat:no-repeat;background-position:50% 0;background-size:125px 102px;text-align:center;text-decoration:none;white-space:nowrap}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.govuk-footer__copyright-logo{background-image:url(/lib/govuk-frontend/dist/assets/images/govuk-crest-2x.png)}}.govuk-footer__inline-list{margin-top:0;margin-bottom:15px;padding:0}.govuk-footer__meta-custom{margin-bottom:20px}.govuk-footer__inline-list-item{display:inline-block;margin-right:15px;margin-bottom:5px}.govuk-footer__heading{margin-bottom:25px;padding-bottom:20px;border-bottom:1px solid #bfc1c3}@media (min-width:40.0625em){.govuk-footer__heading{margin-bottom:40px}}@media (max-width:40.0525em){.govuk-footer__heading{padding-bottom:10px}}.govuk-footer__navigation{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:-15px;margin-left:-15px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.govuk-footer__section{display:inline-block;margin-right:15px;margin-bottom:30px;margin-left:15px;vertical-align:top;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}@media (max-width:48.0525em){.govuk-footer__section{-webkit-flex-basis:200px;-ms-flex-preferred-size:200px;flex-basis:200px}}@media (min-width:48.0625em){.govuk-footer__section:first-child{-webkit-box-flex:2;-webkit-flex-grow:2;-ms-flex-positive:2;flex-grow:2}}.govuk-footer__list{margin:0;padding:0;list-style:none;-webkit-column-gap:30px;column-gap:30px}@media (min-width:48.0625em){.govuk-footer__list--columns-2{-webkit-column-count:2;column-count:2}.govuk-footer__list--columns-3{-webkit-column-count:3;column-count:3}}.govuk-footer__list-item{margin-bottom:15px}@media (min-width:40.0625em){.govuk-footer__list-item{margin-bottom:20px}}.govuk-footer__list-item:last-child{margin-bottom:0}.govuk-header{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;border-bottom:10px solid #fff;color:#fff;background:#0b0c0c}@media print{.govuk-header{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header{font-size:14pt;line-height:1.2}}.govuk-header__container--full-width{padding:0 15px;border-color:#005ea5}.govuk-header__container--full-width .govuk-header__menu-button{right:15px}.govuk-header__container{position:relative;margin-bottom:-10px;padding-top:10px;border-bottom:10px solid #005ea5}.govuk-header__container:after{content:"";display:block;clear:both}.govuk-header__logotype{margin-right:5px}.govuk-header__logotype-crown{margin-right:1px;fill:currentColor;vertical-align:middle}.govuk-header__logotype-crown-fallback-image{width:36px;height:32px;border:0;vertical-align:middle}.govuk-header__product-name{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:18px;font-size:1.125rem;line-height:1.11111;display:inline-table;padding-right:10px}@media print{.govuk-header__product-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__product-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__product-name{font-size:18pt;line-height:1.15}}.govuk-header__link{text-decoration:none}.govuk-header__link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-header__link:link,.govuk-header__link:visited{color:#fff}.govuk-header__link:hover{text-decoration:underline}.govuk-header__link:focus{color:#0b0c0c}.govuk-header__link--homepage{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;font-size:30px;line-height:30px}@media print{.govuk-header__link--homepage{font-family:sans-serif}}.govuk-header__link--homepage:link,.govuk-header__link--homepage:visited{text-decoration:none}.govuk-header__link--homepage:active,.govuk-header__link--homepage:hover{margin-bottom:-1px;border-bottom:1px solid}.govuk-header__link--service-name{display:inline-block;margin-bottom:10px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:18px;font-size:1.125rem;line-height:1.11111}@media print{.govuk-header__link--service-name{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__link--service-name{font-size:24px;font-size:1.5rem;line-height:1.25}}@media print{.govuk-header__link--service-name{font-size:18pt;line-height:1.15}}.govuk-header__logo{margin-bottom:10px;padding-right:50px}@media (min-width:40.0625em){.govuk-header__logo{margin-bottom:10px}}@media (min-width:48.0625em){.govuk-header__logo{width:33.33%;padding-right:0;float:left;vertical-align:top}}@media (min-width:48.0625em){.govuk-header__content{width:66.66%;float:left}}.govuk-header__menu-button{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;display:none;position:absolute;top:20px;right:0;margin:0;padding:0;border:0;color:#fff;background:none}@media print{.govuk-header__menu-button{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__menu-button{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__menu-button{font-size:14pt;line-height:1.2}}.govuk-header__menu-button:hover{text-decoration:underline}.govuk-header__menu-button:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);border-color:rgba(0,0,0,0);border-style:solid;border-width:8.66px 5px 0;border-top-color:inherit;content:"";margin-left:5px}.govuk-header__menu-button:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-header__menu-button{top:15px}}.govuk-header__menu-button--open:after{display:inline-block;width:0;height:0;-webkit-clip-path:polygon(50% 0,0 100%,100% 100%);clip-path:polygon(50% 0,0 100%,100% 100%);border-color:rgba(0,0,0,0);border-style:solid;border-width:0 5px 8.66px;border-bottom-color:inherit}.govuk-header__navigation{display:block;margin:0;padding:0;list-style:none}@media (min-width:40.0625em){.govuk-header__navigation{margin-bottom:10px}}.js-enabled .govuk-header__menu-button{display:block}@media (min-width:48.0625em){.js-enabled .govuk-header__menu-button{display:none}}.js-enabled .govuk-header__navigation{display:none}@media (min-width:48.0625em){.js-enabled .govuk-header__navigation{display:block}}.js-enabled .govuk-header__navigation--open{display:block}@media (min-width:48.0625em){.govuk-header__navigation--end{margin:0;padding:5px 0;text-align:right}}.govuk-header__navigation--no-service-name{padding-top:40px}.govuk-header__navigation-item{padding:10px 0;border-bottom:1px solid #2e3133}@media (min-width:48.0625em){.govuk-header__navigation-item{display:inline-block;margin-right:15px;padding:5px 0;border:0}}.govuk-header__navigation-item a{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.14286;white-space:nowrap}@media print{.govuk-header__navigation-item a{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-header__navigation-item a{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-header__navigation-item a{font-size:14pt;line-height:1.2}}.govuk-header__navigation-item--active a:hover,.govuk-header__navigation-item--active a:link,.govuk-header__navigation-item--active a:visited{color:#1d8feb}.govuk-header__navigation-item--active a:focus{color:#0b0c0c}.govuk-header__navigation-item:last-child{margin-right:0}@media print{.govuk-header{border-bottom-width:0;color:#0b0c0c;background:rgba(0,0,0,0)}.govuk-header__logotype-crown-fallback-image{display:none}.govuk-header__link:link,.govuk-header__link:visited{color:#0b0c0c}.govuk-header__link:after{display:none}}.govuk-header__logotype-crown,.govuk-header__logotype-crown-fallback-image{position:relative;top:-4px}.govuk-header{padding-top:3px}.govuk-inset-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;padding:15px;margin-top:20px;margin-bottom:20px;clear:both;border-left:10px solid #bfc1c3}@media print{.govuk-inset-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-inset-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-inset-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-inset-text{margin-top:30px;margin-bottom:30px}}.govuk-inset-text :first-child{margin-top:0}.govuk-inset-text :last-child,.govuk-inset-text :only-child{margin-bottom:0}.govuk-panel{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;margin-bottom:15px;padding:35px;border:5px solid rgba(0,0,0,0);text-align:center}@media print{.govuk-panel{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-panel{font-size:14pt;line-height:1.15}}@media (max-width:40.0525em){.govuk-panel{padding:25px}}.govuk-panel--confirmation{color:#fff;background:#00692f}.govuk-panel__title{margin-top:0;margin-bottom:30px;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:32px;font-size:2rem;line-height:1.09375}@media print{.govuk-panel__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__title{font-size:48px;font-size:3rem;line-height:1.04167}}@media print{.govuk-panel__title{font-size:32pt;line-height:1.15}}.govuk-panel__title:last-child{margin-bottom:0}.govuk-panel__body{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:24px;font-size:1.5rem;line-height:1.04167}@media print{.govuk-panel__body{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-panel__body{font-size:36px;font-size:2.25rem;line-height:1.11111}}@media print{.govuk-panel__body{font-size:24pt;line-height:1.05}}.govuk-tag{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:14px;font-size:.875rem;line-height:1.25;display:inline-block;padding:4px 8px 1px;outline:2px solid rgba(0,0,0,0);outline-offset:-2px;color:#fff;background-color:#005ea5;letter-spacing:1px;text-decoration:none;text-transform:uppercase}@media print{.govuk-tag{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tag{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-tag{font-size:14pt;line-height:1.25}}.govuk-tag--inactive{background-color:#6f777b}.govuk-phase-banner{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #bfc1c3}.govuk-phase-banner__content{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:14px;font-size:.875rem;line-height:1.14286;color:#0b0c0c;display:table;margin:0}@media print{.govuk-phase-banner__content{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-phase-banner__content{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-phase-banner__content{font-size:14pt;line-height:1.2;color:#000}}.govuk-phase-banner__content__tag{margin-right:10px}.govuk-phase-banner__text{display:table-cell;vertical-align:baseline}.govuk-tabs{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;margin-top:5px;margin-bottom:20px}@media print{.govuk-tabs{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-tabs{margin-top:5px;margin-bottom:30px}}.govuk-tabs__title{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;margin-bottom:5px}@media print{.govuk-tabs__title{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__title{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__title{font-size:14pt;line-height:1.15}}.govuk-tabs__list{margin:0;padding:0;list-style:none}@media (max-width:40.0525em){.govuk-tabs__list{margin-bottom:20px}}@media (max-width:40.0525em) and (min-width:40.0625em){.govuk-tabs__list{margin-bottom:30px}}.govuk-tabs__list-item{margin-left:25px}.govuk-tabs__list-item:before{content:"— ";margin-left:-25px;padding-right:5px}.govuk-tabs__tab{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:inline-block;padding-top:10px;padding-bottom:10px}.govuk-tabs__tab:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-tabs__tab:link{color:#005ea5}.govuk-tabs__tab:visited{color:#4c2c92}.govuk-tabs__tab:active,.govuk-tabs__tab:hover{color:#2b8cc4}.govuk-tabs__tab:focus{color:#0b0c0c}@media print{.govuk-tabs__tab{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-tabs__tab{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-tabs__tab{font-size:14pt;line-height:1.15}}.govuk-tabs__tab[aria-current=true]{color:#0b0c0c;text-decoration:none}.govuk-tabs__panel{margin-bottom:30px}@media (min-width:40.0625em){.govuk-tabs__panel{margin-bottom:50px}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__list{border-bottom:1px solid #bfc1c3}.js-enabled .govuk-tabs__list:after{content:"";display:block;clear:both}.js-enabled .govuk-tabs__list-item{margin-left:0}.js-enabled .govuk-tabs__list-item:before{content:none}.js-enabled .govuk-tabs__title{display:none}.js-enabled .govuk-tabs__tab{margin-right:5px;padding-right:20px;padding-left:20px;float:left;color:#0b0c0c;background-color:#f8f8f8;text-align:center;text-decoration:none}.js-enabled .govuk-tabs__tab--selected{margin-top:-5px;margin-bottom:-1px;padding:14px 19px 16px;border:1px solid #bfc1c3;border-bottom:0;color:#0b0c0c;background-color:#fff}.js-enabled .govuk-tabs__tab--selected:focus{background-color:rgba(0,0,0,0)}.js-enabled .govuk-tabs__panel{margin-bottom:0;padding:30px 20px;border:1px solid #bfc1c3;border-top:0}}@media (min-width:40.0625em) and (min-width:40.0625em){.js-enabled .govuk-tabs__panel{margin-bottom:0}}@media (min-width:40.0625em){.js-enabled .govuk-tabs__panel--hidden{display:none}.js-enabled .govuk-tabs__panel>:last-child{margin-bottom:0}}.govuk-radios__item{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;display:block;position:relative;min-height:40px;margin-bottom:10px;padding:0 0 0 40px;clear:left}@media print{.govuk-radios__item{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__item{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__item{font-size:14pt;line-height:1.15}}.govuk-radios__item:last-child,.govuk-radios__item:last-of-type{margin-bottom:0}.govuk-radios__input{position:absolute;z-index:1;top:0;left:0;width:40px;height:40px;cursor:pointer;margin:0;opacity:0}.govuk-radios__label{display:inline-block;margin-bottom:0;padding:8px 15px 5px;cursor:pointer;-ms-touch-action:manipulation;touch-action:manipulation}.govuk-radios__hint{display:block;padding-right:15px;padding-left:15px}.govuk-radios__input+.govuk-radios__label:before{content:"";box-sizing:border-box;position:absolute;top:0;left:0;width:40px;height:40px;border:2px solid;border-radius:50%;background:rgba(0,0,0,0)}.govuk-radios__input+.govuk-radios__label:after{content:"";position:absolute;top:10px;left:10px;width:0;height:0;border:10px solid;border-radius:50%;opacity:0;background:currentColor}.govuk-radios__input:focus+.govuk-radios__label:before{outline:3px solid rgba(0,0,0,0);outline-offset:3px;box-shadow:0 0 0 4px #ffbf47}.govuk-radios__input:checked+.govuk-radios__label:after{opacity:1}.govuk-radios__input:disabled,.govuk-radios__input:disabled+.govuk-radios__label{cursor:default}.govuk-radios__input:disabled+.govuk-radios__label{opacity:.5}@media (min-width:40.0625em){.govuk-radios--inline:after{content:"";display:block;clear:both}.govuk-radios--inline .govuk-radios__item{margin-right:20px;float:left;clear:none}}.govuk-radios--inline.govuk-radios--conditional .govuk-radios__item{margin-right:0;float:none}.govuk-radios__divider{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:40px;margin-bottom:10px;text-align:center}@media print{.govuk-radios__divider{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-radios__divider{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-radios__divider{font-size:14pt;line-height:1.15;color:#000}}.govuk-radios__conditional{margin-bottom:15px;margin-left:18px;padding-left:33px;border-left:4px solid #bfc1c3}@media (min-width:40.0625em){.govuk-radios__conditional{margin-bottom:20px}}.js-enabled .govuk-radios__conditional--hidden{display:none}.govuk-radios__conditional>:last-child{margin-bottom:0}.govuk-select{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;max-width:100%;height:40px;padding:5px;border:2px solid #0b0c0c}@media print{.govuk-select{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-select{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-select{font-size:14pt;line-height:1.25}}.govuk-select:focus{outline:3px solid #ffbf47;outline-offset:0}.govuk-select:focus::-ms-value,.govuk-select option:active,.govuk-select option:checked{color:#fff;background-color:#005ea5}.govuk-select--error{border:4px solid #b10e1e}.govuk-skip-link{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important;font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:14px;font-size:.875rem;line-height:1.14286;display:block;padding:10px 15px}.govuk-skip-link:active,.govuk-skip-link:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}@media print{.govuk-skip-link{font-family:sans-serif}}.govuk-skip-link:focus{outline:3px solid #ffbf47;outline-offset:0;background-color:#ffbf47}.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#0b0c0c}@media print{.govuk-skip-link:active,.govuk-skip-link:focus,.govuk-skip-link:hover,.govuk-skip-link:link,.govuk-skip-link:visited{color:#000}}@media (min-width:40.0625em){.govuk-skip-link{font-size:16px;font-size:1rem;line-height:1.25}}@media print{.govuk-skip-link{font-size:14pt;line-height:1.2}}.govuk-table{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;width:100%;margin-bottom:20px;border-spacing:0;border-collapse:collapse}@media print{.govuk-table{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-table{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-table{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-table{margin-bottom:30px}}.govuk-table__header{font-weight:700}.govuk-table__cell,.govuk-table__header{padding:10px 20px 10px 0;border-bottom:1px solid #bfc1c3;text-align:left}.govuk-table__cell--numeric{font-family:ntatabularnumbers,nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400}@media print{.govuk-table__cell--numeric{font-family:sans-serif}}.govuk-table__cell--numeric,.govuk-table__header--numeric{text-align:right}.govuk-table__cell:last-child,.govuk-table__header:last-child{padding-right:0}.govuk-table__caption{font-weight:700;display:table-caption;text-align:left}.govuk-textarea{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;box-sizing:border-box;display:block;width:100%;min-height:40px;margin-bottom:20px;padding:5px;resize:vertical;border:2px solid #0b0c0c;border-radius:0;-webkit-appearance:none}@media print{.govuk-textarea{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-textarea{font-size:19px;font-size:1.1875rem;line-height:1.25}}@media print{.govuk-textarea{font-size:14pt;line-height:1.25}}.govuk-textarea:focus{outline:3px solid #ffbf47;outline-offset:0}@media (min-width:40.0625em){.govuk-textarea{margin-bottom:30px}}.govuk-textarea--error{border:4px solid #b10e1e}.govuk-warning-text{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c;position:relative;margin-bottom:20px;padding:10px 0}@media print{.govuk-warning-text{font-family:sans-serif}}@media (min-width:40.0625em){.govuk-warning-text{font-size:19px;font-size:1.1875rem;line-height:1.31579}}@media print{.govuk-warning-text{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.govuk-warning-text{margin-bottom:30px}}.govuk-warning-text__assistive{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;padding:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;border:0!important;white-space:nowrap!important}.govuk-warning-text__icon{font-family:nta,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;display:inline-block;position:absolute;top:50%;left:0;min-width:32px;min-height:29px;margin-top:-20px;padding-top:3px;border:3px solid #0b0c0c;border-radius:50%;color:#fff;background:#0b0c0c;font-size:1.6em;line-height:29px;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media print{.govuk-warning-text__icon{font-family:sans-serif}}.govuk-warning-text__text{display:block;padding-left:50px}.govuk-clearfix:after{content:"";display:block;clear:both}.govuk-visually-hidden{padding:0!important;border:0!important}.govuk-visually-hidden,.govuk-visually-hidden-focusable{position:absolute!important;width:1px!important;height:1px!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important;white-space:nowrap!important}.govuk-visually-hidden-focusable:active,.govuk-visually-hidden-focusable:focus{position:static!important;width:auto!important;height:auto!important;margin:inherit!important;overflow:visible!important;clip:auto!important;-webkit-clip-path:none!important;clip-path:none!important;white-space:inherit!important}.govuk-\!-display-inline{display:inline!important}.govuk-\!-display-inline-block{display:inline-block!important}.govuk-\!-display-block{display:block!important}.govuk-\!-margin-0{margin:0!important}@media (min-width:40.0625em){.govuk-\!-margin-0{margin:0!important}}.govuk-\!-margin-top-0{margin-top:0!important}@media (min-width:40.0625em){.govuk-\!-margin-top-0{margin-top:0!important}}.govuk-\!-margin-right-0{margin-right:0!important}@media (min-width:40.0625em){.govuk-\!-margin-right-0{margin-right:0!important}}.govuk-\!-margin-bottom-0{margin-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-0{margin-bottom:0!important}}.govuk-\!-margin-left-0{margin-left:0!important}@media (min-width:40.0625em){.govuk-\!-margin-left-0{margin-left:0!important}}.govuk-\!-margin-1{margin:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-1{margin:5px!important}}.govuk-\!-margin-top-1{margin-top:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-1{margin-top:5px!important}}.govuk-\!-margin-right-1{margin-right:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-1{margin-right:5px!important}}.govuk-\!-margin-bottom-1{margin-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-1{margin-bottom:5px!important}}.govuk-\!-margin-left-1{margin-left:5px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-1{margin-left:5px!important}}.govuk-\!-margin-2{margin:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-2{margin:10px!important}}.govuk-\!-margin-top-2{margin-top:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-2{margin-top:10px!important}}.govuk-\!-margin-right-2{margin-right:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-2{margin-right:10px!important}}.govuk-\!-margin-bottom-2{margin-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-2{margin-bottom:10px!important}}.govuk-\!-margin-left-2{margin-left:10px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-2{margin-left:10px!important}}.govuk-\!-margin-3{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-3{margin:15px!important}}.govuk-\!-margin-top-3{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-3{margin-top:15px!important}}.govuk-\!-margin-right-3{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-3{margin-right:15px!important}}.govuk-\!-margin-bottom-3{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-3{margin-bottom:15px!important}}.govuk-\!-margin-left-3{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-3{margin-left:15px!important}}.govuk-\!-margin-4{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-4{margin:20px!important}}.govuk-\!-margin-top-4{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-4{margin-top:20px!important}}.govuk-\!-margin-right-4{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-4{margin-right:20px!important}}.govuk-\!-margin-bottom-4{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-4{margin-bottom:20px!important}}.govuk-\!-margin-left-4{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-4{margin-left:20px!important}}.govuk-\!-margin-5{margin:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-5{margin:25px!important}}.govuk-\!-margin-top-5{margin-top:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-5{margin-top:25px!important}}.govuk-\!-margin-right-5{margin-right:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-5{margin-right:25px!important}}.govuk-\!-margin-bottom-5{margin-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-5{margin-bottom:25px!important}}.govuk-\!-margin-left-5{margin-left:15px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-5{margin-left:25px!important}}.govuk-\!-margin-6{margin:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-6{margin:30px!important}}.govuk-\!-margin-top-6{margin-top:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-6{margin-top:30px!important}}.govuk-\!-margin-right-6{margin-right:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-6{margin-right:30px!important}}.govuk-\!-margin-bottom-6{margin-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-6{margin-bottom:30px!important}}.govuk-\!-margin-left-6{margin-left:20px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-6{margin-left:30px!important}}.govuk-\!-margin-7{margin:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-7{margin:40px!important}}.govuk-\!-margin-top-7{margin-top:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-7{margin-top:40px!important}}.govuk-\!-margin-right-7{margin-right:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-7{margin-right:40px!important}}.govuk-\!-margin-bottom-7{margin-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-7{margin-bottom:40px!important}}.govuk-\!-margin-left-7{margin-left:25px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-7{margin-left:40px!important}}.govuk-\!-margin-8{margin:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-8{margin:50px!important}}.govuk-\!-margin-top-8{margin-top:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-8{margin-top:50px!important}}.govuk-\!-margin-right-8{margin-right:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-8{margin-right:50px!important}}.govuk-\!-margin-bottom-8{margin-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-8{margin-bottom:50px!important}}.govuk-\!-margin-left-8{margin-left:30px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-8{margin-left:50px!important}}.govuk-\!-margin-9{margin:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-9{margin:60px!important}}.govuk-\!-margin-top-9{margin-top:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-top-9{margin-top:60px!important}}.govuk-\!-margin-right-9{margin-right:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-right-9{margin-right:60px!important}}.govuk-\!-margin-bottom-9{margin-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-bottom-9{margin-bottom:60px!important}}.govuk-\!-margin-left-9{margin-left:40px!important}@media (min-width:40.0625em){.govuk-\!-margin-left-9{margin-left:60px!important}}.govuk-\!-padding-0{padding:0!important}@media (min-width:40.0625em){.govuk-\!-padding-0{padding:0!important}}.govuk-\!-padding-top-0{padding-top:0!important}@media (min-width:40.0625em){.govuk-\!-padding-top-0{padding-top:0!important}}.govuk-\!-padding-right-0{padding-right:0!important}@media (min-width:40.0625em){.govuk-\!-padding-right-0{padding-right:0!important}}.govuk-\!-padding-bottom-0{padding-bottom:0!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-0{padding-bottom:0!important}}.govuk-\!-padding-left-0{padding-left:0!important}@media (min-width:40.0625em){.govuk-\!-padding-left-0{padding-left:0!important}}.govuk-\!-padding-1{padding:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-1{padding:5px!important}}.govuk-\!-padding-top-1{padding-top:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-1{padding-top:5px!important}}.govuk-\!-padding-right-1{padding-right:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-1{padding-right:5px!important}}.govuk-\!-padding-bottom-1{padding-bottom:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-1{padding-bottom:5px!important}}.govuk-\!-padding-left-1{padding-left:5px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-1{padding-left:5px!important}}.govuk-\!-padding-2{padding:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-2{padding:10px!important}}.govuk-\!-padding-top-2{padding-top:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-2{padding-top:10px!important}}.govuk-\!-padding-right-2{padding-right:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-2{padding-right:10px!important}}.govuk-\!-padding-bottom-2{padding-bottom:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-2{padding-bottom:10px!important}}.govuk-\!-padding-left-2{padding-left:10px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-2{padding-left:10px!important}}.govuk-\!-padding-3{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-3{padding:15px!important}}.govuk-\!-padding-top-3{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-3{padding-top:15px!important}}.govuk-\!-padding-right-3{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-3{padding-right:15px!important}}.govuk-\!-padding-bottom-3{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-3{padding-bottom:15px!important}}.govuk-\!-padding-left-3{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-3{padding-left:15px!important}}.govuk-\!-padding-4{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-4{padding:20px!important}}.govuk-\!-padding-top-4{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-4{padding-top:20px!important}}.govuk-\!-padding-right-4{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-4{padding-right:20px!important}}.govuk-\!-padding-bottom-4{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-4{padding-bottom:20px!important}}.govuk-\!-padding-left-4{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-4{padding-left:20px!important}}.govuk-\!-padding-5{padding:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-5{padding:25px!important}}.govuk-\!-padding-top-5{padding-top:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-5{padding-top:25px!important}}.govuk-\!-padding-right-5{padding-right:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-5{padding-right:25px!important}}.govuk-\!-padding-bottom-5{padding-bottom:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-5{padding-bottom:25px!important}}.govuk-\!-padding-left-5{padding-left:15px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-5{padding-left:25px!important}}.govuk-\!-padding-6{padding:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-6{padding:30px!important}}.govuk-\!-padding-top-6{padding-top:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-6{padding-top:30px!important}}.govuk-\!-padding-right-6{padding-right:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-6{padding-right:30px!important}}.govuk-\!-padding-bottom-6{padding-bottom:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-6{padding-bottom:30px!important}}.govuk-\!-padding-left-6{padding-left:20px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-6{padding-left:30px!important}}.govuk-\!-padding-7{padding:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-7{padding:40px!important}}.govuk-\!-padding-top-7{padding-top:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-7{padding-top:40px!important}}.govuk-\!-padding-right-7{padding-right:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-7{padding-right:40px!important}}.govuk-\!-padding-bottom-7{padding-bottom:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-7{padding-bottom:40px!important}}.govuk-\!-padding-left-7{padding-left:25px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-7{padding-left:40px!important}}.govuk-\!-padding-8{padding:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-8{padding:50px!important}}.govuk-\!-padding-top-8{padding-top:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-8{padding-top:50px!important}}.govuk-\!-padding-right-8{padding-right:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-8{padding-right:50px!important}}.govuk-\!-padding-bottom-8{padding-bottom:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-8{padding-bottom:50px!important}}.govuk-\!-padding-left-8{padding-left:30px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-8{padding-left:50px!important}}.govuk-\!-padding-9{padding:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-9{padding:60px!important}}.govuk-\!-padding-top-9{padding-top:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-top-9{padding-top:60px!important}}.govuk-\!-padding-right-9{padding-right:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-right-9{padding-right:60px!important}}.govuk-\!-padding-bottom-9{padding-bottom:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-bottom-9{padding-bottom:60px!important}}.govuk-\!-padding-left-9{padding-left:40px!important}@media (min-width:40.0625em){.govuk-\!-padding-left-9{padding-left:60px!important}}.govuk-\!-font-size-80{font-size:53px!important;font-size:3.3125rem!important;line-height:1.03774!important}@media (min-width:40.0625em){.govuk-\!-font-size-80{font-size:80px!important;font-size:5rem!important;line-height:1!important}}@media print{.govuk-\!-font-size-80{font-size:53pt!important;line-height:1.1!important}}.govuk-\!-font-size-48{font-size:32px!important;font-size:2rem!important;line-height:1.09375!important}@media (min-width:40.0625em){.govuk-\!-font-size-48{font-size:48px!important;font-size:3rem!important;line-height:1.04167!important}}@media print{.govuk-\!-font-size-48{font-size:32pt!important;line-height:1.15!important}}.govuk-\!-font-size-36{font-size:24px!important;font-size:1.5rem!important;line-height:1.04167!important}@media (min-width:40.0625em){.govuk-\!-font-size-36{font-size:36px!important;font-size:2.25rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-36{font-size:24pt!important;line-height:1.05!important}}.govuk-\!-font-size-27{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-27{font-size:27px!important;font-size:1.6875rem!important;line-height:1.11111!important}}@media print{.govuk-\!-font-size-27{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-24{font-size:18px!important;font-size:1.125rem!important;line-height:1.11111!important}@media (min-width:40.0625em){.govuk-\!-font-size-24{font-size:24px!important;font-size:1.5rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-24{font-size:18pt!important;line-height:1.15!important}}.govuk-\!-font-size-19{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-19{font-size:19px!important;font-size:1.1875rem!important;line-height:1.31579!important}}@media print{.govuk-\!-font-size-19{font-size:14pt!important;line-height:1.15!important}}.govuk-\!-font-size-16{font-size:14px!important;font-size:.875rem!important;line-height:1.14286!important}@media (min-width:40.0625em){.govuk-\!-font-size-16{font-size:16px!important;font-size:1rem!important;line-height:1.25!important}}@media print{.govuk-\!-font-size-16{font-size:14pt!important;line-height:1.2!important}}.govuk-\!-font-size-14{font-size:12px!important;font-size:.75rem!important;line-height:1.25!important}@media (min-width:40.0625em){.govuk-\!-font-size-14{font-size:14px!important;font-size:.875rem!important;line-height:1.42857!important}}@media print{.govuk-\!-font-size-14{font-size:12pt!important;line-height:1.2!important}}.govuk-\!-font-weight-regular{font-weight:400!important}.govuk-\!-font-weight-bold{font-weight:700!important}.govuk-\!-width-full,.govuk-\!-width-three-quarters{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-three-quarters{width:75%!important}}.govuk-\!-width-two-thirds{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-two-thirds{width:66.66%!important}}.govuk-\!-width-one-half{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-half{width:50%!important}}.govuk-\!-width-one-third{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-third{width:33.33%!important}}.govuk-\!-width-one-quarter{width:100%!important}@media (min-width:40.0625em){.govuk-\!-width-one-quarter{width:25%!important}} \ No newline at end of file From 166f3fa41c6752b411cbe2ac7a43014151a54f2a Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Thu, 5 Aug 2021 15:48:07 +0100 Subject: [PATCH 02/19] Updated orchestrators --- .../Provider.Web/Orchestrators/ReviewedOrchestrator.cs | 4 +++- .../Provider.Web/Orchestrators/SubmittedOrchestrator.cs | 3 ++- .../Reviewed/VacancyReviewedConfirmationViewModel.cs | 1 + .../Submitted/VacancySubmittedConfirmationViewModel.cs | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs b/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs index a915f0cf68..701905d09e 100644 --- a/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs +++ b/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs @@ -25,6 +25,7 @@ public async Task GetVacancyReviewedOrches { var vacancy = await Utility.GetAuthorisedVacancyAsync(_client, _vacancyClient, vrm, RouteNames.Reviewed_Index_Get); var employer = await _client.GetProviderEmployerVacancyDataAsync(vrm.Ukprn, vacancy.EmployerAccountId); + var preferences = await _vacancyClient.GetUserNotificationPreferencesAsync(vacancyUser.UserId); if (vacancy.Status != VacancyStatus.Review) throw new InvalidStateException(string.Format(ErrorMessages.VacancyNotReviewedSuccessfully, vacancy.Title)); @@ -34,7 +35,8 @@ public async Task GetVacancyReviewedOrches Title = vacancy.Title, VacancyReference = vacancy.VacancyReference?.ToString(), EmployerName = employer.Name, - IsResubmit = vacancy.ReviewDate.HasValue + IsResubmit = vacancy.ReviewDate.HasValue, + IsVacancyRejectedByEmployerNotificationSelected = preferences.NotificationTypes.HasFlag(NotificationTypes.VacancyRejectedByEmployer) }; return vm; diff --git a/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs b/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs index 6d924037a1..cddf434b65 100644 --- a/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs +++ b/src/Provider/Provider.Web/Orchestrators/SubmittedOrchestrator.cs @@ -43,7 +43,8 @@ public async Task GetVacancySubmittedConf Title = vacancy.Title, VacancyReference = vacancy.VacancyReference?.ToString(), IsResubmit = isResubmit, - HasNotificationsSet = preferences != null && preferences.NotificationTypes > NotificationTypes.None + HasNotificationsSet = preferences != null && preferences.NotificationTypes > NotificationTypes.None, + IsVacancyRejectedByESFANotificationSelected = preferences.NotificationTypes.HasFlag(NotificationTypes.VacancyRejected) }; return vm; diff --git a/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs b/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs index 6b08c26d47..589ac1b293 100644 --- a/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs +++ b/src/Provider/Provider.Web/ViewModels/Reviewed/VacancyReviewedConfirmationViewModel.cs @@ -8,5 +8,6 @@ public class VacancyReviewedConfirmationViewModel public bool HasVacancyReference => !string.IsNullOrEmpty(VacancyReference); public string EmployerName { get; set; } public bool IsResubmit { get; set; } + public bool IsVacancyRejectedByEmployerNotificationSelected { get; set; } } } diff --git a/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs b/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs index e96d2577bd..559d3c59c6 100644 --- a/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs +++ b/src/Provider/Provider.Web/ViewModels/Submitted/VacancySubmittedConfirmationViewModel.cs @@ -8,5 +8,6 @@ public class VacancySubmittedConfirmationViewModel public bool HasVacancyReference => !string.IsNullOrEmpty(VacancyReference); public bool HasNotificationsSet { get; set; } + public bool IsVacancyRejectedByESFANotificationSelected { get; set; } } } From 0138c28d44592d0914d439640fe406561f94972f Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Thu, 5 Aug 2021 16:33:16 +0100 Subject: [PATCH 03/19] Updated views --- .../Views/Reviewed/Confirmation.cshtml | 29 ++++++--- .../Views/Submitted/Confirmation.cshtml | 62 +++++++++++-------- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml index 8e79d6ef14..aac800e0a5 100644 --- a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml @@ -20,25 +20,38 @@

- +

What happens next

@Model.EmployerName needs to approve the vacancy.

- +

- If they approve the vacancy, we’ll do a final review and then post it on ‘Find an apprenticeship’. + If @Model.EmployerName approve the vacancy, the ESFA will do a final review and then post it on 'Find an apprenticeship'.

- + + @if (Model.IsVacancyRejectedByEmployerNotificationSelected) + { +

+ If @Model.EmployerName reject the vacancy, it will come back to you to edit and resubmit. We will let you know by email if you need to make any edits. +

+ } + else + { +

+ If the vacancy is rejected by either @Model.EmployerName or the ESFA and you need to make edits, they will tell you in the rejected vacancies of your Recruitment dashboard. +

+ } +

- If they reject the vacancy, it will come back to you to edit and resubmit. + Manage the frequency of your recruitment emails

- +

- Return to recruitment dashboard + Return to recruitment

- +

Create another vacancy

diff --git a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml index 0636b8c569..7e601dc427 100644 --- a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml @@ -4,42 +4,52 @@ ViewBag.GaData.Vpv = "/recruitment/provider/page-vacancy-submitted-for-approval"; } -

@Model.Title

-
-
-

- Vacancy submitted for approval +
+

+ Vacancy submitted to ESFA +

+

+ Vacancy resubmitted to ESFA

- The vacancy reference number is
+ Your reference number
VAC@(Model.VacancyReference)

-
-

- Vacancy resubmitted for approval -

-
-

Next steps

-
-

We’ll check the vacancy and let you know by email within one working day if you need to make any edits. Manage your recruitment emails.

-

When the vacancy is approved, it will appear on the Find an apprenticeship service.

-
-
-

We’ll check the vacancy and tell you within one working day on the dashboard if you need to make any edits. Visit Manage your recruitment emails if you’d also like to get an email.

-

When the vacancy is approved, it will appear on the Find an apprenticeship service.

-
+

What happens next

+ + @if (Model.IsVacancyRejectedByESFANotificationSelected) + { +

+ The ESFA will check the vacancy and will tell you within one working day, on the Recruitment dashboard within rejected vacancies, if you need to make any edits. +

+ } + else + { +

+ The ESFA will check the vacancy and let you know by email, within one working day, if you need to make and edits. +

+ } - +

+ Manage the frequency of your recruitment emails +

+ +

+ When the vacancy is approved, it will appear on Find an apprenticeship. +

+ +

+ Return to recruitment +

+ +

+ Create another vacancy +

\ No newline at end of file From b3906c8cf92a11d0956ffe9a96b260d1e371f23d Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Thu, 5 Aug 2021 17:06:13 +0100 Subject: [PATCH 04/19] Update Confirmation.cshtml --- .../Provider.Web/Views/Submitted/Confirmation.cshtml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml index 7e601dc427..e87dba1c5a 100644 --- a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml @@ -22,24 +22,24 @@

What happens next

- + @if (Model.IsVacancyRejectedByESFANotificationSelected) {

- The ESFA will check the vacancy and will tell you within one working day, on the Recruitment dashboard within rejected vacancies, if you need to make any edits. + The ESFA will check the vacancy and let you know by email, within one working day, if you need to make and edits.

} else {

- The ESFA will check the vacancy and let you know by email, within one working day, if you need to make and edits. + The ESFA will check the vacancy and will tell you within one working day, on the Recruitment dashboard within rejected vacancies, if you need to make any edits.

}

Manage the frequency of your recruitment emails

- +

When the vacancy is approved, it will appear on Find an apprenticeship.

From e2d3584f45973d3575e4d901b614d225fb7b74c6 Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Fri, 13 Aug 2021 17:24:48 +0100 Subject: [PATCH 05/19] Added employer review and rejection reason --- .../Controllers/VacancyPreviewController.cs | 19 +- .../Orchestrators/Part1/DatesOrchestrator.cs | 35 ++- .../Part1/DurationOrchestrator.cs | 44 +++- .../Part1/LocationOrchestrator.cs | 56 +++- .../Part1/NumberofPositionsOrchestrator.cs | 15 +- .../Orchestrators/Part1/TitleOrchestrator.cs | 13 +- .../Part1/TrainingOrchestrator.cs | 14 +- .../Part1/TrainingProviderOrchestrator.cs | 13 +- .../Orchestrators/Part1/WageOrchestrator.cs | 34 ++- .../Part2/AboutEmployerOrchestrator.cs | 16 +- .../Part2/ApplicationProcessOrchestrator.cs | 23 +- .../Part2/ConsiderationsOrchestrator.cs | 11 +- .../EmployerContactDetailsOrchestrator.cs | 29 ++- .../Part2/QualificationsOrchestrator.cs | 43 ++- .../Part2/ShortDescriptionOrchestrator.cs | 12 +- .../Orchestrators/Part2/SkillsOrchestrator.cs | 20 +- .../Part2/VacancyDescriptionOrchestrator.cs | 27 +- .../VacancyPreviewOrchestrator.cs | 26 +- .../VacancyValidatingOrchestrator.cs | 62 +++++ .../RejectJobAdvertViewModel.cs | 1 + .../VacancyPreview/SubmitReviewModel.cs | 26 +- .../VacancyPreview/VacancyPreviewViewModel.cs | 3 + .../ConfirmationJobAdvert.cshtml | 2 +- .../VacancyPreview/RejectJobAdvert.cshtml | 18 +- .../VacancyPreview/VacancyPreview.cshtml | 16 +- .../HardMocks/VacancyOrchestratorTestData.cs | 8 + .../Part2/AboutEmployerOrchestratorTests.cs | 129 +++++++++ .../ApplicationProcessOrchestratorTests.cs | 244 +++++++++++++++--- .../Part2/ConsiderationsOrchestratorTests.cs | 119 +++++++++ .../Entities/EmployerReviewFieldIndicator.cs | 8 + .../Domain/Entities/Vacancy.cs | 2 + 31 files changed, 960 insertions(+), 128 deletions(-) create mode 100644 src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs create mode 100644 src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs diff --git a/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs b/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs index 0840b4bb23..0dd7f31111 100644 --- a/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs +++ b/src/Employer/Employer.Web/Controllers/VacancyPreviewController.cs @@ -30,14 +30,14 @@ public VacancyPreviewController(VacancyPreviewOrchestrator orchestrator) } [HttpGet("preview", Name = RouteNames.Vacancy_Preview_Get)] - public async Task VacancyPreview(VacancyRouteModel vrm, string selection = null) + public async Task VacancyPreview(VacancyRouteModel vrm, bool? submitToEfsa = null) { var viewModel = await _orchestrator.GetVacancyPreviewViewModelAsync(vrm); AddSoftValidationErrorsToModelState(viewModel); SetSectionStates(viewModel); viewModel.CanHideValidationSummary = true; - ViewBag.Selection = selection; + viewModel.SubmitToEsfa = submitToEfsa; if (TempData.ContainsKey(TempDataKeys.VacancyClonedInfoMessage)) viewModel.VacancyClonedInfoMessage = TempData[TempDataKeys.VacancyClonedInfoMessage].ToString(); @@ -50,6 +50,15 @@ public async Task Review(SubmitReviewModel m) { if (ModelState.IsValid) { + if(m.SubmitToEsfa.Value) + { + await _orchestrator.ClearRejectedVacancyReason(m, User.ToVacancyUser()); + } + else + { + await _orchestrator.UpdateRejectedVacancyReason(m, User.ToVacancyUser()); + } + return RedirectToRoute(m.SubmitToEsfa.GetValueOrDefault() ? RouteNames.ApproveJobAdvert_Get : RouteNames.RejectJobAdvert_Get); @@ -57,6 +66,8 @@ public async Task Review(SubmitReviewModel m) var viewModel = await _orchestrator.GetVacancyPreviewViewModelAsync(m); viewModel.SoftValidationErrors = null; + viewModel.SubmitToEsfa = m.SubmitToEsfa; + viewModel.RejectedReason = m.RejectedReason; SetSectionStates(viewModel); return View(ViewNames.VacancyPreview, viewModel); @@ -125,7 +136,7 @@ public async Task ApproveJobAdvert(ApproveJobAdvertViewModel vm) } else { - return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, Selection = "Approve" }); + return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, SubmitToEfsa = true }); } var viewModel = await _orchestrator.GetVacancyPreviewViewModelAsync(vm); @@ -167,7 +178,7 @@ public async Task RejectJobAdvert(RejectJobAdvertViewModel vm) } } - return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, Selection = "Reject" }); + return RedirectToRoute(RouteNames.Vacancy_Preview_Get, new { VacancyId = vm.VacancyId, SubmitToEfsa = false }); } [HttpGet("confirmation-advert", Name = RouteNames.JobAdvertConfirmation_Get)] diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs index c21c04985c..93d3caa47c 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/DatesOrchestrator.cs @@ -7,6 +7,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Domain.Extensions; @@ -15,7 +16,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class DatesOrchestrator : EntityValidatingOrchestrator + public class DatesOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ClosingDate | VacancyRuleSet.StartDate | VacancyRuleSet.StartDateEndDate | VacancyRuleSet.TrainingExpiryDate; private readonly IEmployerVacancyClient _client; @@ -99,11 +100,33 @@ public async Task PostDatesEditModelAsync(DatesEditModel m { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.Dates_Post); - vacancy.ClosingDate = m.ClosingDate.AsDateTimeUk()?.ToUniversalTime(); - vacancy.StartDate = m.StartDate.AsDateTimeUk()?.ToUniversalTime(); - - vacancy.DisabilityConfident = m.IsDisabilityConfident ? DisabilityConfident.Yes : DisabilityConfident.No; - + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ClosingDate, + FieldIdResolver.ToFieldId(v => v.ClosingDate), + vacancy, + (v) => + { + return v.ClosingDate = m.ClosingDate.AsDateTimeUk()?.ToUniversalTime(); + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.StartDate, + FieldIdResolver.ToFieldId(v => v.StartDate), + vacancy, + (v) => + { + return v.StartDate = m.StartDate.AsDateTimeUk()?.ToUniversalTime(); + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.DisabilityConfident, + FieldIdResolver.ToFieldId(v => v.DisabilityConfident), + vacancy, + (v) => + { + return v.DisabilityConfident = m.IsDisabilityConfident ? DisabilityConfident.Yes : DisabilityConfident.No; + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs index 9f0eb29a7d..123bfc6e3c 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/DurationOrchestrator.cs @@ -6,6 +6,7 @@ using Esfa.Recruit.Shared.Web.Extensions; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -13,7 +14,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class DurationOrchestrator : EntityValidatingOrchestrator + public class DurationOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Duration | VacancyRuleSet.WorkingWeekDescription | VacancyRuleSet.WeeklyHours; private readonly IEmployerVacancyClient _client; @@ -72,11 +73,42 @@ public async Task PostDurationEditModelAsync(DurationEditM if(vacancy.Wage == null) vacancy.Wage = new Wage(); - vacancy.Wage.Duration = int.TryParse(m.Duration, out int duration) ? duration : default(int?); - vacancy.Wage.DurationUnit = m.DurationUnit; - vacancy.Wage.WorkingWeekDescription = m.WorkingWeekDescription; - vacancy.Wage.WeeklyHours = m.WeeklyHours.AsDecimal(2); - + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.Duration, + FieldIdResolver.ToFieldId(v => v.Wage.Duration), + vacancy, + (v) => + { + return v.Wage.Duration = int.TryParse(m.Duration, out int duration) ? duration : default(int?); + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.DurationUnit, + FieldIdResolver.ToFieldId(v => v.Wage.DurationUnit), + vacancy, + (v) => + { + return v.Wage.DurationUnit = m.DurationUnit; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WorkingWeekDescription, + FieldIdResolver.ToFieldId(v => v.Wage.WorkingWeekDescription), + vacancy, + (v) => + { + return v.Wage.WorkingWeekDescription = m.WorkingWeekDescription; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WeeklyHours, + FieldIdResolver.ToFieldId(v => v.Wage.WeeklyHours), + vacancy, + (v) => + { + return v.Wage.WeeklyHours = m.WeeklyHours.AsDecimal(2); + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs index 312511c11f..ca87fbed5e 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs @@ -16,10 +16,11 @@ using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Employer.Web.Mappings; using Esfa.Recruit.Shared.Web.Models; +using Esfa.Recruit.Vacancies.Client.Application.Services; namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class LocationOrchestrator : EntityValidatingOrchestrator + public class LocationOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerAddress; private readonly IEmployerVacancyClient _employerVacancyClient; @@ -140,9 +141,57 @@ public async Task PostLocationEditModelAsync( var matchingAddress = GetMatchingAddress(newLocation, allLocations); - vacancy.EmployerLocation = matchingAddress != null ? matchingAddress : ConvertToDomainAddress(locationEditModel); + var employerLocation = matchingAddress != null ? matchingAddress : ConvertToDomainAddress(locationEditModel); - //if cookie is found then update legal entity and name option from cookie + // this has diverged from the usual pattern because the individual properties are review fields + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine1, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine1), + vacancy, + (v) => + { + return employerLocation.AddressLine1; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine2, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine2), + vacancy, + (v) => + { + return employerLocation.AddressLine2; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine3, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine3), + vacancy, + (v) => + { + return employerLocation.AddressLine3; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.AddressLine4, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.AddressLine4), + vacancy, + (v) => + { + return employerLocation.AddressLine4; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerLocation?.Postcode, + FieldIdResolver.ToFieldId(v => v.EmployerLocation.Postcode), + vacancy, + (v) => + { + return employerLocation.Postcode; + }); + + vacancy.EmployerLocation = employerLocation; + + // if cookie is found then update legal entity and name option from cookie if (employerInfoModel != null) { vacancy.LegalEntityName = selectedOrganisation.Name; @@ -161,6 +210,7 @@ public async Task PostLocationEditModelAsync( await UpdateEmployerProfile(employerInfoModel, employerProfile, matchingAddress == null ? vacancy.EmployerLocation : null, user); }); } + private Address GetMatchingAddress(string locationToMatch, IEnumerable
allLocations) { var matchingLocation = diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs index a7caee7c55..51b6d131ae 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/NumberofPositionsOrchestrator.cs @@ -6,6 +6,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part1.NumberOfPositions; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -13,7 +14,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class NumberOfPositionsOrchestrator : EntityValidatingOrchestrator + public class NumberOfPositionsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.NumberOfPositions; private readonly IEmployerVacancyClient _client; @@ -58,9 +59,17 @@ public async Task GetNumberOfPositionsViewModelAsync public async Task> PostNumberOfPositionsEditModelAsync(NumberOfPositionsEditModel m, VacancyUser user) { - var numberOfPositions = int.TryParse(m.NumberOfPositions, out var n)? n : default(int?); var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient,m, RouteNames.NumberOfPositions_Post); - vacancy.NumberOfPositions = numberOfPositions; + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.NumberOfPositions, + FieldIdResolver.ToFieldId(v => v.NumberOfPositions), + vacancy, + (v) => + { + return v.NumberOfPositions = int.TryParse(m.NumberOfPositions, out var n) ? n : default(int?); + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs index b9dba9443d..d3ad72baea 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs @@ -8,6 +8,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Shared.Web.ViewModels; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -16,7 +17,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class TitleOrchestrator : EntityValidatingOrchestrator + public class TitleOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Title; private readonly IEmployerVacancyClient _client; @@ -83,7 +84,6 @@ public async Task GetTitleViewModelAsync(TitleEditModel m) return vm; } - public async Task> PostTitleEditModelAsync(TitleEditModel m, VacancyUser user) { TrainingProvider provider = null; @@ -111,7 +111,14 @@ public async Task> PostTitleEditModelAsync(TitleEditM var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, new VacancyRouteModel{EmployerAccountId = m.EmployerAccountId, VacancyId = m.VacancyId.Value}, RouteNames.Title_Post); - vacancy.Title = m.Title; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Title, + FieldIdResolver.ToFieldId(v => v.Title), + vacancy, + (v) => + { + return v.Title = m.Title; + }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs index 1606d236df..ecbbfa3c92 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingOrchestrator.cs @@ -8,6 +8,7 @@ using Esfa.Recruit.Shared.Web.Helpers; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Domain.Extensions; @@ -16,7 +17,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class TrainingOrchestrator : EntityValidatingOrchestrator + public class TrainingOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProgramme; private readonly IEmployerVacancyClient _client; @@ -104,8 +105,15 @@ public async Task GetConfirmTrainingViewModelAsync(Vac public async Task PostConfirmTrainingEditModelAsync(ConfirmTrainingEditModel m, VacancyUser user) { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.Training_Confirm_Post); - - vacancy.ProgrammeId = m.ProgrammeId; + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ProgrammeId, + FieldIdResolver.ToFieldId(v => v.ProgrammeId), + vacancy, + (v) => + { + return v.ProgrammeId = m.ProgrammeId; + }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs index 793269c0db..787b1589fc 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestrator.cs @@ -11,6 +11,7 @@ using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Configuration; using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -19,7 +20,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class TrainingProviderOrchestrator : EntityValidatingOrchestrator + public class TrainingProviderOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProvider; private readonly IEmployerVacancyClient _client; @@ -148,6 +149,16 @@ public async Task PostConfirmEditModelAsync(ConfirmTrainin var vacancy = vacancyTask.Result; var provider = providerTask.Result; + // this has diverged from the usual pattern because only a single individual property is a review field + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.TrainingProvider?.Ukprn, + FieldIdResolver.ToFieldId(v => v.TrainingProvider.Ukprn), + vacancy, + (v) => + { + return provider.Ukprn; + }); + vacancy.TrainingProvider = provider; return await ValidateAndExecute( diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs index 648609a3d7..9570297dd9 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/WageOrchestrator.cs @@ -8,6 +8,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Domain.Extensions; @@ -18,7 +19,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part1 { - public class WageOrchestrator : EntityValidatingOrchestrator + public class WageOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Wage | VacancyRuleSet.MinimumWage; private readonly IEmployerVacancyClient _client; @@ -82,10 +83,33 @@ public async Task PostWageEditModelAsync(WageEditModel m, if(vacancy.Wage == null) vacancy.Wage = new Wage(); - vacancy.Wage.WageType = m.WageType; - vacancy.Wage.FixedWageYearlyAmount = (m.WageType == WageType.FixedWage) ? m.FixedWageYearlyAmount?.AsMoney() : null; - vacancy.Wage.WageAdditionalInformation = m.WageAdditionalInformation; - + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WageType, + FieldIdResolver.ToFieldId(v => v.Wage.WageType), + vacancy, + (v) => + { + return v.Wage.WageType = m.WageType; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.FixedWageYearlyAmount, + FieldIdResolver.ToFieldId(v => v.Wage.FixedWageYearlyAmount), + vacancy, + (v) => + { + return v.Wage.FixedWageYearlyAmount = (m.WageType == WageType.FixedWage) ? m.FixedWageYearlyAmount?.AsMoney() : null; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Wage.WageAdditionalInformation, + FieldIdResolver.ToFieldId(v => v.Wage.WageAdditionalInformation), + vacancy, + (v) => + { + return v.Wage.WageAdditionalInformation = m.WageAdditionalInformation; + }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValidationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs index 2d9aa7cdb3..dfd86bb683 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestrator.cs @@ -7,6 +7,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.AboutEmployer; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -14,7 +15,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class AboutEmployerOrchestrator : EntityValidatingOrchestrator + public class AboutEmployerOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerDescription | VacancyRuleSet.EmployerWebsiteUrl; private readonly IEmployerVacancyClient _client; @@ -64,8 +65,17 @@ public async Task PostAboutEmployerEditModelAsync(AboutEmp { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.AboutEmployer_Post); - vacancy.EmployerDescription = m.EmployerDescription; - vacancy.EmployerWebsiteUrl = m.EmployerWebsiteUrl; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerDescription, + FieldIdResolver.ToFieldId(v => v.EmployerDescription), + vacancy, + (v) => { return v.EmployerDescription = m.EmployerDescription; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerWebsiteUrl, + FieldIdResolver.ToFieldId(v => v.EmployerWebsiteUrl), + vacancy, + (v) => { return v.EmployerWebsiteUrl = m.EmployerWebsiteUrl; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs index f3df55cf04..5077012da6 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestrator.cs @@ -6,6 +6,7 @@ using Esfa.Recruit.Employer.Web.ViewModels; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -14,7 +15,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class ApplicationProcessOrchestrator : EntityValidatingOrchestrator + public class ApplicationProcessOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ApplicationMethod; private readonly IEmployerVacancyClient _client; @@ -70,11 +71,25 @@ public async Task PostApplicationProcessEditModelAsync(App { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.ApplicationProcess_Post); + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ApplicationMethod, + FieldIdResolver.ToFieldId(v => v.ApplicationMethod), + vacancy, + (v) => { return v.ApplicationMethod = m.ApplicationMethod; }); + var hasSelectedApplyThroughFaa = m.ApplicationMethod == ApplicationMethod.ThroughFindAnApprenticeship; - vacancy.ApplicationMethod = m.ApplicationMethod; - vacancy.ApplicationInstructions = hasSelectedApplyThroughFaa ? null : m.ApplicationInstructions; - vacancy.ApplicationUrl = hasSelectedApplyThroughFaa ? null : m.ApplicationUrl; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ApplicationInstructions, + FieldIdResolver.ToFieldId(v => v.ApplicationInstructions), + vacancy, + (v) => { return v.ApplicationInstructions = hasSelectedApplyThroughFaa ? null : m.ApplicationInstructions; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ApplicationUrl, + FieldIdResolver.ToFieldId(v => v.ApplicationUrl), + vacancy, + (v) => { return v.ApplicationUrl = hasSelectedApplyThroughFaa ? null : m.ApplicationUrl; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs index e4eeaa5a00..7ef06649a7 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class ConsiderationsOrchestrator : EntityValidatingOrchestrator + public class ConsiderationsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ThingsToConsider; private readonly IEmployerVacancyClient _client; @@ -57,8 +58,12 @@ public async Task GetConsiderationsViewModelAsync(Consi public async Task PostConsiderationsEditModelAsync(ConsiderationsEditModel m, VacancyUser user) { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.Considerations_Post); - - vacancy.ThingsToConsider = m.ThingsToConsider; + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ThingsToConsider, + FieldIdResolver.ToFieldId(v => v.ThingsToConsider), + vacancy, + (v) => { return v.ThingsToConsider = m.ThingsToConsider; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs index 57509cf30d..fd770f165f 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class EmployerContactDetailsOrchestrator : EntityValidatingOrchestrator + public class EmployerContactDetailsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerContactDetails; private readonly IEmployerVacancyClient _client; @@ -63,12 +64,26 @@ public async Task PostEmployerContactDetailsEditModelAsync { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.EmployerContactDetails_Post); - vacancy.EmployerContact = new ContactDetail - { - Name = m.EmployerContactName, - Email = m.EmployerContactEmail, - Phone = m.EmployerContactPhone - }; + if (vacancy.EmployerContact == null) + vacancy.EmployerContact = new ContactDetail(); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerContact.Name, + FieldIdResolver.ToFieldId(v => v.EmployerContact.Name), + vacancy, + (v) => { return v.EmployerContact.Name = m.EmployerContactName; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerContact.Email, + FieldIdResolver.ToFieldId(v => v.EmployerContact.Email), + vacancy, + (v) => { return v.EmployerContact.Email = m.EmployerContactEmail; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerContact.Phone, + FieldIdResolver.ToFieldId(v => v.EmployerContact.Phone), + vacancy, + (v) => { return v.EmployerContact.Phone = m.EmployerContactPhone; }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs index 9737f1eaf3..708c988428 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs @@ -10,6 +10,7 @@ using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Shared.Web.ViewModels.Qualifications; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -17,7 +18,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class QualificationsOrchestrator : EntityValidatingOrchestrator + public class QualificationsOrchestrator : VacancyValidatingOrchestrator { private readonly IEmployerVacancyClient _client; private readonly IRecruitVacancyClient _vacancyClient; @@ -118,10 +119,10 @@ public async Task PostQualificationEditModelForAddAsync(Va if (vacancy.Qualifications == null) vacancy.Qualifications = new List(); - var qualification = new Qualification(); + var qualification = new Qualification(); vacancy.Qualifications.Add(qualification); - return await UpdateVacancyWithQualificationAsync(vacancy, qualification, m, user); + return await UpdateVacancyWithQualificationAsync(vacancy, null, qualification, m, user); } public async Task PostQualificationEditModelForEditAsync(VacancyRouteModel vrm, QualificationEditModel m, VacancyUser user, int index) @@ -129,8 +130,15 @@ public async Task PostQualificationEditModelForEditAsync(V var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, vrm, RouteNames.Qualification_Edit_Post); var qualification = vacancy.Qualifications[index]; + var currentQualification = new Qualification + { + QualificationType = qualification.QualificationType, + Grade = qualification.Grade, + Subject = qualification.Subject, + Weighting = qualification.Weighting, + }; - return await UpdateVacancyWithQualificationAsync(vacancy, qualification, m, user); + return await UpdateVacancyWithQualificationAsync(vacancy, currentQualification, qualification, m, user); } public async Task DeleteQualificationAsync(VacancyRouteModel vrm, int index, VacancyUser user) @@ -140,7 +148,15 @@ public async Task DeleteQualificationAsync(VacancyRouteModel vrm, int index, Vac if (vacancy.Qualifications == null) return; - vacancy.Qualifications.RemoveAt(index); + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Qualifications[index], + FieldIdResolver.ToFieldId(v => v.Qualifications), + vacancy, + (v) => + { + vacancy.Qualifications.RemoveAt(index); + return null; + }); await _vacancyClient.UpdateDraftVacancyAsync(vacancy, user); } @@ -199,12 +215,19 @@ private void SetQualificationViewModelFromEditModel(QualificationViewModel vm, Q vm.Weighting = m.Weighting; } - private async Task UpdateVacancyWithQualificationAsync(Vacancy vacancy, Qualification qualification, QualificationEditModel m, VacancyUser user) + private async Task UpdateVacancyWithQualificationAsync(Vacancy vacancy, Qualification currentQualification, Qualification qualification, QualificationEditModel m, VacancyUser user) { - qualification.QualificationType = m.QualificationType; - qualification.Grade = m.Grade; - qualification.Subject = m.Subject; - qualification.Weighting = m.Weighting; + SetVacancyWithEmployerReviewFieldIndicators( + currentQualification, + FieldIdResolver.ToFieldId(v => v.Qualifications), + vacancy, + (v) => { + qualification.QualificationType = m.QualificationType; + qualification.Grade = m.Grade; + qualification.Subject = m.Subject; + qualification.Weighting = m.Weighting; + return qualification; + }); var allQualifications = await _vacancyClient.GetCandidateQualificationsAsync(); vacancy.Qualifications = vacancy.Qualifications.SortQualifications(allQualifications).ToList(); diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs index af42e2698a..002c203c3c 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part2.ShortDescription; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class ShortDescriptionOrchestrator : EntityValidatingOrchestrator + public class ShortDescriptionOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.ShortDescription; private readonly IEmployerVacancyClient _client; @@ -59,7 +60,14 @@ public async Task PostShortDescriptionEditModelAsync(Short { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.ShortDescription_Post); - vacancy.ShortDescription = m.ShortDescription; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.ShortDescription, + FieldIdResolver.ToFieldId(v => v.ShortDescription), + vacancy, + (v) => + { + return v.ShortDescription = m.ShortDescription; + }); return await ValidateAndExecute( vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs index ee53793ae3..eec2b98508 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs @@ -8,7 +8,7 @@ using Esfa.Recruit.Shared.Web.Extensions; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; -using Esfa.Recruit.Shared.Web.ViewModels.Skills; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -16,7 +16,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class SkillsOrchestrator : EntityValidatingOrchestrator + public class SkillsOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValidationRules = VacancyRuleSet.Skills; private readonly IEmployerVacancyClient _client; @@ -79,9 +79,21 @@ public async Task PostSkillsEditModelAsync(VacancyRouteMod m.Skills = new List(); } - _skillsHelper.SetVacancyFromEditModel(vacancy, m); + var currentSkills = new List(); + currentSkills.AddRange(vacancy.Skills); - //if we are adding/removing a skill then just validate and don't persist + SetVacancyWithEmployerReviewFieldIndicators( + currentSkills, + FieldIdResolver.ToFieldId(v => v.Skills), + vacancy, + (v) => + { + _skillsHelper.SetVacancyFromEditModel(v, m); + return v.Skills; + }); + + // when adding a custom skill the vacancy is not saved immediately, the new custom skill is + // validated but all the updates are saved later in a single operation var validateOnly = m.IsAddingCustomSkill; return await ValidateAndExecute(vacancy, diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs index cc485af2d4..366c86d8af 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part2.VacancyDescription; using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; @@ -12,7 +13,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { - public class VacancyDescriptionOrchestrator : EntityValidatingOrchestrator + public class VacancyDescriptionOrchestrator : VacancyValidatingOrchestrator { private const VacancyRuleSet ValdationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; private readonly IEmployerVacancyClient _client; @@ -65,11 +66,25 @@ public async Task GetVacancyDescriptionViewModelAsy public async Task PostVacancyDescriptionEditModelAsync(VacancyDescriptionEditModel m, VacancyUser user) { var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, m, RouteNames.VacancyDescription_Index_Post); - - vacancy.Description = m.VacancyDescription; - vacancy.TrainingDescription = m.TrainingDescription; - vacancy.OutcomeDescription = m.OutcomeDescription; - + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.Description, + FieldIdResolver.ToFieldId(v => v.Description), + vacancy, + (v) => { return v.Description = m.VacancyDescription; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.TrainingDescription, + FieldIdResolver.ToFieldId(v => v.TrainingDescription), + vacancy, + (v) => { return v.TrainingDescription = m.TrainingDescription; }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.OutcomeDescription, + FieldIdResolver.ToFieldId(v => v.OutcomeDescription), + vacancy, + (v) => { return v.OutcomeDescription = m.OutcomeDescription; }); + return await ValidateAndExecute( vacancy, v => _vacancyClient.Validate(v, ValdationRules), diff --git a/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs index 0be15ac525..70eb29ec40 100644 --- a/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/VacancyPreviewOrchestrator.cs @@ -68,7 +68,8 @@ public async Task GetVacancyPreviewViewModelAsync(Vacan var vm = new VacancyPreviewViewModel(); await _vacancyDisplayMapper.MapFromVacancyAsync(vm, vacancy); - + + vm.RejectedReason = vacancy.EmployerRejectedReason; vm.HasProgramme = vacancy.ProgrammeId != null; vm.HasWage = vacancy.Wage != null; vm.CanShowReference = vacancy.Status != VacancyStatus.Draft; @@ -144,7 +145,25 @@ private async Task RejectActionAsync(Vacancy vacancy, Vac await _messaging.SendCommandAsync(command); - return new RejectVacancyResponse { IsRejected = true }; + return new RejectVacancyResponse { IsRejected = true }; + } + + public async Task ClearRejectedVacancyReason(SubmitReviewModel m, VacancyUser user) + { + var vacancy = await Utility.GetAuthorisedVacancyAsync(_vacancyClient, m, RouteNames.ApproveJobAdvert_Post); + + vacancy.EmployerRejectedReason = null; + + await _vacancyClient.UpdateDraftVacancyAsync(vacancy, user); + } + + public async Task UpdateRejectedVacancyReason(SubmitReviewModel m, VacancyUser user) + { + var vacancy = await Utility.GetAuthorisedVacancyAsync(_vacancyClient, m, RouteNames.ApproveJobAdvert_Post); + + vacancy.EmployerRejectedReason = m.RejectedReason; + + await _vacancyClient.UpdateDraftVacancyAsync(vacancy, user); } public async Task> ApproveJobAdvertAsync(ApproveJobAdvertViewModel m, VacancyUser user) @@ -205,7 +224,8 @@ public async Task GetVacancyRejectJobAdvertAsync(Vacan var vacancy = await _vacancyClient.GetVacancyAsync(vrm.VacancyId); var vm = new RejectJobAdvertViewModel - { + { + RejectionReason = vacancy.EmployerRejectedReason, TrainingProviderName = vacancy.TrainingProvider.Name }; diff --git a/src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs new file mode 100644 index 0000000000..2beca6b849 --- /dev/null +++ b/src/Employer/Employer.Web/Orchestrators/VacancyValidatingOrchestrator.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Esfa.Recruit.Employer.Web.Mappings; +using Esfa.Recruit.Shared.Web.Orchestrators; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace Esfa.Recruit.Employer.Web.Orchestrators +{ + public abstract class VacancyValidatingOrchestrator : EntityValidatingOrchestrator + { + protected VacancyValidatingOrchestrator(ILogger logger) + : base(logger) + { + } + + protected void SetVacancyWithEmployerReviewFieldIndicators(T currentValue, + string fieldId, + Vacancy vacancy, + Func setFunc + ) + { + PopulateEmployerReviewFieldIndicators(vacancy); + + var newValue = setFunc(vacancy); + if (!JsonConvert.SerializeObject(currentValue).Equals(JsonConvert.SerializeObject(newValue))) + { + foreach (var fieldIdentifier in ReviewFieldMappingLookups.GetPreviewReviewFieldIndicators().VacancyPropertyMappingsLookup[fieldId]) + { + var changedIndicator = vacancy.EmployerReviewFieldIndicators.Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault(); + if (changedIndicator != null) + { + changedIndicator.IsChangeRequested = true; + } + } + } + } + + private void PopulateEmployerReviewFieldIndicators(Vacancy vacancy) + { + var employerReviewFieldIndicators = vacancy.EmployerReviewFieldIndicators ?? new List(); + + // add field indicators which are missing + var missingIndicators = + ReviewFieldMappingLookups + .GetPreviewReviewFieldIndicators().FieldIdentifiersForPage + .Select(p => new EmployerReviewFieldIndicator { FieldIdentifier = p.ReviewFieldIdentifier, IsChangeRequested = false }) + .Where(p => !employerReviewFieldIndicators.Any(v => v.FieldIdentifier == p.FieldIdentifier)); + + if (missingIndicators.Any()) + { + employerReviewFieldIndicators + .AddRange(missingIndicators); + + vacancy.EmployerReviewFieldIndicators = employerReviewFieldIndicators + .OrderBy(p => p.FieldIdentifier).ToList(); + } + } + } +} diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs index c304694052..ce0600b970 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/RejectJobAdvertViewModel.cs @@ -7,6 +7,7 @@ public class RejectJobAdvertViewModel : VacancyRouteModel { [Required(ErrorMessage = "Select if you want to reject this job advert")] public bool? RejectJobAdvert { get; set; } + public string RejectionReason { get; set; } public string TrainingProviderName { get; set; } } diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs index 48fe7ed7d2..13efefbed4 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs @@ -1,11 +1,33 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using Esfa.Recruit.Employer.Web.RouteModel; namespace Esfa.Recruit.Employer.Web.ViewModels.Preview { - public class SubmitReviewModel : VacancyRouteModel + public class SubmitReviewModel : VacancyRouteModel, IValidatableObject { + private const int RejectedReasonMaxCharacters = 200; + [Required(ErrorMessage = "You need to submit or reject the advert")] public bool? SubmitToEsfa { get; set; } + + public string RejectedReason { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + var property = new[] { nameof(RejectedReason) }; + + if(SubmitToEsfa.HasValue && SubmitToEsfa.Value == false) + { + if (string.IsNullOrEmpty(RejectedReason)) + { + yield return new ValidationResult("Enter details of why you are rejecting this advert", property); + } + else if (RejectedReason.Length > RejectedReasonMaxCharacters) + { + yield return new ValidationResult($"You have {RejectedReason.Length- RejectedReasonMaxCharacters} character too many", property); + } + } + } } } diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs index 1904afcd82..52a21e2dd8 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/VacancyPreviewViewModel.cs @@ -66,6 +66,9 @@ public class VacancyPreviewViewModel : DisplayVacancyViewModel public bool HasSoftValidationErrors => SoftValidationErrors?.HasErrors == true; + public string RejectedReason { get; set; } + public bool? SubmitToEsfa { get; set; } + public bool ShowIncompleteSections => ((HasIncompleteMandatorySections || HasIncompleteOptionalSections) && !Review.HasBeenReviewed) || HasSoftValidationErrors; public ReviewSummaryViewModel Review { get; set; } = new ReviewSummaryViewModel(); public string SubmitButtonText => Review.HasBeenReviewed ? "Resubmit advert" : "Submit advert"; diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml index b9ad6cb4a6..0b71b57030 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/ConfirmationJobAdvert.cshtml @@ -29,7 +29,7 @@

When we approve your advert, it will appear on the Find an apprenticeship service (opens in a new tab or window).

-

This job advert has gone back to @Model.TrainingProviderName. You may want to tell them why you've rejected it.

+

This job advert has gone back to @Model.TrainingProviderName.

diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml index b7ff56176d..e4289d2125 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/RejectJobAdvert.cshtml @@ -3,18 +3,22 @@ @{ ViewBag.Vpv = "/recruitment/employer/reject-job-advert"; ViewBag.Title = "Are you sure you want to reject this job advert?"; } -Back +Back

- Are you sure you want to reject this job advert? -

-
-

This job advert will go back to @Model.TrainingProviderName. You may want to tell them why you're rejecting it.

-
+ Are you sure you want to reject this job advert? + +
+

This job advert will go back to @Model.TrainingProviderName.

+
+

Rejection reason

+

@Model.RejectionReason

+
+
@@ -33,6 +37,6 @@ ViewBag.Title = "Are you sure you want to reject this job advert?"; }
- +
\ No newline at end of file diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml index 3b781599c7..43f022a0ad 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml @@ -507,19 +507,29 @@ Error: @Html.ValidationMessage("SubmitToEsfa") -
+
- +
- +
+
+ +
+ + + You have + 200 + characters remaining +
+
diff --git a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs index 227ad7ac94..8050b9dbcb 100644 --- a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs +++ b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs @@ -32,5 +32,13 @@ internal static VacancyUser GetVacancyUser() UserId = "scott" }; } + + internal static EmployerProfile GetEmployerProfile() + { + return new EmployerProfile + { + EmployerAccountId = "EMPLOYER ACCOUNT ID" + }; + } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs new file mode 100644 index 0000000000..7951efaa1d --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs @@ -0,0 +1,129 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class AboutEmployerOrchestratorTests + { + private AboutEmployerOrchestratorTestsFixture _fixture; + + public AboutEmployerOrchestratorTests() + { + _fixture = new AboutEmployerOrchestratorTestsFixture(); + } + + [Fact] + public async Task WhenEmployerDescriptionIsUpdated_ShouldFlagEmployerDescriptionFieldIndicator() + { + _fixture + .WithEmployerDescription("has a value") + .WithEmployerWebsiteUrl("has a value") + .Setup(); + + var aboutEmployerEditModel = new AboutEmployerEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerDescription = "has a new value", + EmployerWebsiteUrl = "has a value" + }; + + await _fixture.PostAboutEmployerEditModelAsync(aboutEmployerEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerDescription, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerWebsiteUrl, false); + } + + [Fact] + public async Task WhenEmployerWebsiteUrlIsUpdated_ShouldFlagEmployerWebsiteUrlFieldIndicator() + { + _fixture + .WithEmployerDescription("has a value") + .WithEmployerWebsiteUrl("has a value") + .Setup(); + + var aboutEmployerEditModel = new AboutEmployerEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerDescription = "has a value", + EmployerWebsiteUrl = "has a new value" + }; + + await _fixture.PostAboutEmployerEditModelAsync(aboutEmployerEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerDescription, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerWebsiteUrl, true); + } + + public class AboutEmployerOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerDescription | VacancyRuleSet.EmployerWebsiteUrl; + public VacancyUser User { get; } + public EmployerProfile EmployerProfile { get; } + public Vacancy Vacancy { get; } + public AboutEmployerOrchestrator Sut {get; private set;} + + public AboutEmployerOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + EmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public AboutEmployerOrchestratorTestsFixture WithEmployerDescription(string employerDescription) + { + Vacancy.EmployerDescription = employerDescription; + return this; + } + + public AboutEmployerOrchestratorTestsFixture WithEmployerWebsiteUrl(string employerWebsiteUrl) + { + Vacancy.EmployerWebsiteUrl = employerWebsiteUrl; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, Vacancy.AccountLegalEntityPublicHashedId)).ReturnsAsync(EmployerProfile); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new AboutEmployerOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostAboutEmployerEditModelAsync(AboutEmployerEditModel model) + { + await Sut.PostAboutEmployerEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs index f56934f819..eb6b74dc3c 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs @@ -1,7 +1,11 @@ -using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; using Esfa.Recruit.Employer.Web.Configuration; using Esfa.Recruit.Employer.Web.Orchestrators.Part2; using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; @@ -16,73 +20,235 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 { public class ApplicationProcessOrchestratorTests { - private readonly Mock _mockClient; - private readonly Mock _mockVacancyClient; + private ApplicationProcessOrchestratorTestsFixture _fixture; public ApplicationProcessOrchestratorTests() { - _mockClient = new Mock(); - _mockVacancyClient = new Mock(); + _fixture = new ApplicationProcessOrchestratorTestsFixture(); } [Fact] - public void WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationUrlAsNull() + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldCallUpdateDraftVacancy() { - var user = VacancyOrchestratorTestData.GetVacancyUser(); - var vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(vacancy.Id)) - .ReturnsAsync(vacancy); - _mockVacancyClient.Setup(x => x.Validate(vacancy, VacancyRuleSet.ApplicationMethod)) - .Returns(new EntityValidationResult()); - _mockVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), user)); + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, + ApplicationInstructions = "has a value", + }; + + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); - var sut = new ApplicationProcessOrchestrator(_mockClient.Object, _mockVacancyClient.Object, Options.Create(new ExternalLinksConfiguration()), Mock.Of>(), Mock.Of()); + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationUrlAsNull() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); var applicationProcessEditModel = new ApplicationProcessEditModel { - EmployerAccountId = vacancy.EmployerAccountId, - VacancyId = vacancy.Id, + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, - ApplicationUrl = "www.google.com" + ApplicationUrl = "has a value" }; - var result = sut.PostApplicationProcessEditModelAsync(applicationProcessEditModel, user); + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); - vacancy.ApplicationMethod.HasValue.Should().BeTrue(); - vacancy.ApplicationMethod.Value.Should().Be(ApplicationMethod.ThroughFindAnApprenticeship); - vacancy.ApplicationUrl.Should().BeNull(); - _mockVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(vacancy, user), Times.Once); + _fixture.VerifyApplicationMethod(ApplicationMethod.ThroughFindAnApprenticeship); + _fixture.VerifyOverwriteApplicationUrlAsNull(); } [Fact] - public void WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationInstructionsAsNull() + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldOverwriteApplicationInstructionsAsNull() { - var user = VacancyOrchestratorTestData.GetVacancyUser(); - var vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(vacancy.Id)) - .ReturnsAsync(vacancy); - _mockVacancyClient.Setup(x => x.Validate(vacancy, VacancyRuleSet.ApplicationMethod)) - .Returns(new EntityValidationResult()); - _mockVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), user)); + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, + ApplicationInstructions = "has a value", + }; - var sut = new ApplicationProcessOrchestrator(_mockClient.Object, _mockVacancyClient.Object, Options.Create(new ExternalLinksConfiguration()), Mock.Of>(), Mock.Of()); + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyApplicationMethod(ApplicationMethod.ThroughFindAnApprenticeship); + _fixture.VerifyOverwriteApplicationInstructionsAsNull(); + } + + [Fact] + public async Task WhenApplicationMethodIsThroughFaaVacancy_ShouldFlagAllApplicationFieldIndicators() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); var applicationProcessEditModel = new ApplicationProcessEditModel { - EmployerAccountId = vacancy.EmployerAccountId, - VacancyId = vacancy.Id, + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, ApplicationMethod = ApplicationMethod.ThroughFindAnApprenticeship, - ApplicationInstructions = "just do it" + ApplicationInstructions = "has a value", + ApplicationUrl = "has a value" + }; + + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationMethod, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationInstructions, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationUrl, true); + } + + [Fact] + public async Task WhenApplicationInstructionsIsUpdated_ShouldFlagApplicationInstructionsFieldIndicator() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); + + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughExternalApplicationSite, + ApplicationInstructions = "has a new value", + ApplicationUrl = "has a value" }; - var result = sut.PostApplicationProcessEditModelAsync(applicationProcessEditModel, user); + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationMethod, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationInstructions, true); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationUrl, false); + } + + [Fact] + public async Task WhenApplicationUrlIsUpdated_ShouldFlagApplicationInstructionsFieldIndicator() + { + _fixture + .WithApplicationMethod(ApplicationMethod.ThroughExternalApplicationSite) + .WithApplicationInstructions("has a value") + .WithApplicationUrl("has a value") + .Setup(); + + var applicationProcessEditModel = new ApplicationProcessEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ApplicationMethod = ApplicationMethod.ThroughExternalApplicationSite, + ApplicationInstructions = "has a value", + ApplicationUrl = "has a new value" + }; + + await _fixture.PostApplicationProcessEditModelAsync(applicationProcessEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationMethod, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationInstructions, false); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ApplicationUrl, true); + } + + public class ApplicationProcessOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ApplicationMethod; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public ApplicationProcessOrchestrator Sut { get; private set; } + + public ApplicationProcessOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public ApplicationProcessOrchestratorTestsFixture WithApplicationMethod(ApplicationMethod applicationMethod) + { + Vacancy.ApplicationMethod = applicationMethod; + return this; + } + + public ApplicationProcessOrchestratorTestsFixture WithApplicationInstructions(string applicationInstructions) + { + Vacancy.ApplicationInstructions = applicationInstructions; + return this; + } + + public ApplicationProcessOrchestratorTestsFixture WithApplicationUrl(string applicationUrl) + { + Vacancy.ApplicationUrl = applicationUrl; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new ApplicationProcessOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Options.Create(new ExternalLinksConfiguration()), Mock.Of>(), Mock.Of()); + } + + public async Task PostApplicationProcessEditModelAsync(ApplicationProcessEditModel model) + { + await Sut.PostApplicationProcessEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyApplicationMethod(ApplicationMethod applicationMethod) + { + Vacancy.ApplicationMethod.HasValue.Should().BeTrue(); + Vacancy.ApplicationMethod.Value.Should().Be(applicationMethod); + } + + public void VerifyOverwriteApplicationInstructionsAsNull() + { + Vacancy.ApplicationInstructions.Should().BeNull(); + } + + public void VerifyOverwriteApplicationUrlAsNull() + { + Vacancy.ApplicationUrl.Should().BeNull(); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } - vacancy.ApplicationMethod.HasValue.Should().BeTrue(); - vacancy.ApplicationMethod.Value.Should().Be(ApplicationMethod.ThroughFindAnApprenticeship); - vacancy.ApplicationInstructions.Should().BeNull(); - _mockVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(vacancy, user), Times.Once); + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs new file mode 100644 index 0000000000..765f92c52b --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs @@ -0,0 +1,119 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class ConsiderationsOrchestratorTests + { + private ConsiderationsOrchestratorTestsFixture _fixture; + + public ConsiderationsOrchestratorTests() + { + _fixture = new ConsiderationsOrchestratorTestsFixture(); + } + + [Fact] + public async Task WhenThingsToConsiderIsUpdated__ShouldCallUpdateDraftVacancy() + { + _fixture + .WithThingsToConsider("has a value") + .Setup(); + + var thingsToConsiderEditModel = new ConsiderationsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ThingsToConsider = "has a new value" + }; + + await _fixture.PostConsiderationsEditModelAsync(thingsToConsiderEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenThingsToConsiderIsUpdated_ShouldFlagEmployerDescriptionFieldIndicator() + { + _fixture + .WithThingsToConsider("has a value") + .Setup(); + + var thingsToConsiderEditModel = new ConsiderationsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ThingsToConsider = "has a new value" + }; + + await _fixture.PostConsiderationsEditModelAsync(thingsToConsiderEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ThingsToConsider, true); + } + + public class ConsiderationsOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ThingsToConsider; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public ConsiderationsOrchestrator Sut {get; private set;} + + public ConsiderationsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public ConsiderationsOrchestratorTestsFixture WithThingsToConsider(string thingsToConsider) + { + Vacancy.ThingsToConsider = thingsToConsider; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new ConsiderationsOrchestrator(Mock.Of>(), MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of()); + } + + public async Task PostConsiderationsEditModelAsync(ConsiderationsEditModel model) + { + await Sut.PostConsiderationsEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs new file mode 100644 index 0000000000..151d549850 --- /dev/null +++ b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/EmployerReviewFieldIndicator.cs @@ -0,0 +1,8 @@ +namespace Esfa.Recruit.Vacancies.Client.Domain.Entities +{ + public class EmployerReviewFieldIndicator + { + public string FieldIdentifier { get; set; } + public bool IsChangeRequested { get; set; } + } +} diff --git a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs index ee7f9495ac..200c029774 100644 --- a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs +++ b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs @@ -41,6 +41,8 @@ public class Vacancy public Address EmployerLocation { get; set; } public string EmployerName { get; set; } public EmployerNameOption? EmployerNameOption { get; set; } + public List EmployerReviewFieldIndicators { get; set; } + public string EmployerRejectedReason { get; set; } public string LegalEntityName { get; set; } public string EmployerWebsiteUrl { get; set; } public GeoCodeMethod? GeoCodeMethod { get; set; } From 3dbbaadd7e699a60aa173c4aa4b4af1e6bd090ec Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Wed, 18 Aug 2021 17:33:23 +0100 Subject: [PATCH 06/19] Added more part 2 tests --- .../Part2/QualificationsOrchestrator.cs | 4 +- .../Part2/VacancyDescriptionOrchestrator.cs | 4 +- .../Part2/AboutEmployerOrchestratorTests.cs | 51 +-- .../ApplicationProcessOrchestratorTests.cs | 2 +- .../Part2/ConsiderationsOrchestratorTests.cs | 4 +- ...EmployerContactDetailsOrchestratorTests.cs | 156 +++++++ .../Part2/QualificationsOrchestratorTests.cs | 381 ++++++++++++++++++ .../ShortDescriptionOrchestratorTests.cs | 120 ++++++ .../Part2/SkillOrchestratorTests.cs | 381 +++++++++++------- .../VacancyDescriptionOrchestratorTests.cs | 163 ++++++++ 10 files changed, 1088 insertions(+), 178 deletions(-) create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs index 708c988428..e5dea21242 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/QualificationsOrchestrator.cs @@ -229,8 +229,8 @@ private async Task UpdateVacancyWithQualificationAsync(Vac return qualification; }); - var allQualifications = await _vacancyClient.GetCandidateQualificationsAsync(); - vacancy.Qualifications = vacancy.Qualifications.SortQualifications(allQualifications).ToList(); + var qualificationTypes = await _vacancyClient.GetCandidateQualificationsAsync(); + vacancy.Qualifications = vacancy.Qualifications.SortQualifications(qualificationTypes).ToList(); return await ValidateAndExecute(vacancy, v => diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs index 366c86d8af..74e62b4035 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestrator.cs @@ -15,7 +15,7 @@ namespace Esfa.Recruit.Employer.Web.Orchestrators.Part2 { public class VacancyDescriptionOrchestrator : VacancyValidatingOrchestrator { - private const VacancyRuleSet ValdationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; private readonly IEmployerVacancyClient _client; private readonly IRecruitVacancyClient _vacancyClient; private readonly IReviewSummaryService _reviewSummaryService; @@ -87,7 +87,7 @@ public async Task PostVacancyDescriptionEditModelAsync(Vac return await ValidateAndExecute( vacancy, - v => _vacancyClient.Validate(v, ValdationRules), + v => _vacancyClient.Validate(v, ValidationRules), v => _vacancyClient.UpdateDraftVacancyAsync(vacancy, user) ); } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs index 7951efaa1d..7a4e4db970 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs @@ -24,8 +24,11 @@ public AboutEmployerOrchestratorTests() _fixture = new AboutEmployerOrchestratorTestsFixture(); } - [Fact] - public async Task WhenEmployerDescriptionIsUpdated_ShouldFlagEmployerDescriptionFieldIndicator() + [Theory] + [InlineData("has a new value", "has a value", new string[] { FieldIdentifiers.EmployerDescription }, new string[] { FieldIdentifiers.EmployerWebsiteUrl})] + [InlineData("has a value", "has a new value", new string[] { FieldIdentifiers.EmployerWebsiteUrl }, new string[] { FieldIdentifiers.EmployerDescription })] + [InlineData("has a new value", "has a new value", new string[] { FieldIdentifiers.EmployerDescription, FieldIdentifiers.EmployerWebsiteUrl }, new string[] { })] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string employerDescription, string employerWebSiteUrl, string[] setFieldIdentifers, string [] unsetFieldIdentifiers) { _fixture .WithEmployerDescription("has a value") @@ -36,36 +39,13 @@ public async Task WhenEmployerDescriptionIsUpdated_ShouldFlagEmployerDescription { EmployerAccountId = _fixture.Vacancy.EmployerAccountId, VacancyId = _fixture.Vacancy.Id, - EmployerDescription = "has a new value", - EmployerWebsiteUrl = "has a value" + EmployerDescription = employerDescription, + EmployerWebsiteUrl = employerWebSiteUrl }; await _fixture.PostAboutEmployerEditModelAsync(aboutEmployerEditModel); - _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerDescription, true); - _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerWebsiteUrl, false); - } - - [Fact] - public async Task WhenEmployerWebsiteUrlIsUpdated_ShouldFlagEmployerWebsiteUrlFieldIndicator() - { - _fixture - .WithEmployerDescription("has a value") - .WithEmployerWebsiteUrl("has a value") - .Setup(); - - var aboutEmployerEditModel = new AboutEmployerEditModel - { - EmployerAccountId = _fixture.Vacancy.EmployerAccountId, - VacancyId = _fixture.Vacancy.Id, - EmployerDescription = "has a value", - EmployerWebsiteUrl = "has a new value" - }; - - await _fixture.PostAboutEmployerEditModelAsync(aboutEmployerEditModel); - - _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerDescription, false); - _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerWebsiteUrl, true); + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIdentifers, unsetFieldIdentifiers); } public class AboutEmployerOrchestratorTestsFixture @@ -114,10 +94,23 @@ public async Task PostAboutEmployerEditModelAsync(AboutEmployerEditModel model) await Sut.PostAboutEmployerEditModelAsync(model, User); } + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) { Vacancy.EmployerReviewFieldIndicators - .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() .Should().NotBeNull().And .Match((x) => x.IsChangeRequested == value); } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs index eb6b74dc3c..6a9f661e1c 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ApplicationProcessOrchestratorTests.cs @@ -221,7 +221,7 @@ public async Task PostApplicationProcessEditModelAsync(ApplicationProcessEditMod public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) { Vacancy.EmployerReviewFieldIndicators - .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() .Should().NotBeNull().And .Match((x) => x.IsChangeRequested == value); } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs index 765f92c52b..ca8b3d89f0 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ConsiderationsOrchestratorTests.cs @@ -25,7 +25,7 @@ public ConsiderationsOrchestratorTests() } [Fact] - public async Task WhenThingsToConsiderIsUpdated__ShouldCallUpdateDraftVacancy() + public async Task WhenUpdated__ShouldCallUpdateDraftVacancy() { _fixture .WithThingsToConsider("has a value") @@ -44,7 +44,7 @@ public async Task WhenThingsToConsiderIsUpdated__ShouldCallUpdateDraftVacancy() } [Fact] - public async Task WhenThingsToConsiderIsUpdated_ShouldFlagEmployerDescriptionFieldIndicator() + public async Task WhenThingsToConsiderIsUpdated_ShouldFlagThingsToConsiderFieldIndicator() { _fixture .WithThingsToConsider("has a value") diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs new file mode 100644 index 0000000000..4a0e38c96f --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/EmployerContactDetailsOrchestratorTests.cs @@ -0,0 +1,156 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class EmployerContactDetailsOrchestratorTests + { + private EmployerContactDetailsOrchestratorTestsFixture _fixture; + + public EmployerContactDetailsOrchestratorTests() + { + _fixture = new EmployerContactDetailsOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value")] + [InlineData("has a value", "has a new value", "has a value")] + [InlineData("has a value", "has a value", "has a new value")] + [InlineData("has a new value", "has a new value", "has a new value")] + public async Task WhenEmployerContactNameIsUpdated__ShouldCallUpdateDraftVacancy(string employerContactName, string employerContactEmail, string employerContactPhone) + { + _fixture + .WithEmployerContactName("has a value") + .WithEmployerContactEmail("has a value") + .WithEmployerContactPhone("has a value") + .Setup(); + + var employerContactDetailsEditModel = new EmployerContactDetailsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerContactName = employerContactName, + EmployerContactEmail = employerContactEmail, + EmployerContactPhone = employerContactPhone + }; + + await _fixture.PostEmployerContactDetailsEditModelAsync(employerContactDetailsEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value")] + [InlineData("has a value", "has a new value", "has a value")] + [InlineData("has a value", "has a value", "has a new value")] + [InlineData("has a new value", "has a new value", "has a new value")] + public async Task WhenEmployerContactNameIsUpdated_ShouldFlagEmployerContactFieldIndicator(string employerContactName, string employerContactEmail, string employerContactPhone) + { + _fixture + .WithEmployerContactName("has a value") + .WithEmployerContactEmail("has a value") + .WithEmployerContactPhone("has a value") + .Setup(); + + var employerContactDetailsEditModel = new EmployerContactDetailsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + EmployerContactName = employerContactName, + EmployerContactEmail = employerContactEmail, + EmployerContactPhone = employerContactPhone + }; + + await _fixture.PostEmployerContactDetailsEditModelAsync(employerContactDetailsEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerContact, true); + } + + public class EmployerContactDetailsOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerContactDetails; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public EmployerContactDetailsOrchestrator Sut {get; private set;} + + public EmployerContactDetailsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public EmployerContactDetailsOrchestratorTestsFixture WithEmployerContactName(string employerContactName) + { + if (Vacancy.EmployerContact == null) + Vacancy.EmployerContact = new ContactDetail(); + + Vacancy.EmployerContact.Name = employerContactName; + return this; + } + + public EmployerContactDetailsOrchestratorTestsFixture WithEmployerContactEmail(string employerContactEmail) + { + if (Vacancy.EmployerContact == null) + Vacancy.EmployerContact = new ContactDetail(); + + Vacancy.EmployerContact.Email = employerContactEmail; + return this; + } + + public EmployerContactDetailsOrchestratorTestsFixture WithEmployerContactPhone(string employerContactPhone) + { + if (Vacancy.EmployerContact == null) + Vacancy.EmployerContact = new ContactDetail(); + + Vacancy.EmployerContact.Phone = employerContactPhone; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new EmployerContactDetailsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostEmployerContactDetailsEditModelAsync(EmployerContactDetailsEditModel model) + { + await Sut.PostEmployerContactDetailsEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs new file mode 100644 index 0000000000..67da323bc5 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/QualificationsOrchestratorTests.cs @@ -0,0 +1,381 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.RouteModel; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Shared.Web.ViewModels.Qualifications; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Newtonsoft.Json; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class QualificationsOrchestratorTests + { + public QualificationsOrchestratorTests() + { + } + + [Fact] + public async Task WhenQualificationIsAdded_ShouldAddQualificationToDraftVacancy() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "A", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Essential + }; + + await fixture.PostQualificationEditModelForAddAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification)); + + fixture.VerifyAddQualificationToDraftVacancy(2, qualification); + } + + [Fact] + public async Task WhenQualificationIsAdded_ShouldCallUpdateDraftVacancyAsync() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "A", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Essential + }; + + await fixture.PostQualificationEditModelForAddAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification)); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenQualificationIsAdded_ShouldFlagQualificationsFieldIndicator() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "A", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Essential + }; + + await fixture.PostQualificationEditModelForAddAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification)); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Qualifications, true); + } + + [Fact] + public async Task WhenQualificationIsUpdated_ShouldUpdateQualificationForDraftVacancy() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.PostQualificationEditModelForEditAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification), + index: 1); + + fixture.VerifyUpdateQualificationForDraftVacancy(qualification); + } + + [Fact] + public async Task WhenQualificationIsUpdated_ShouldCallUpdateDraftVacancyAsync() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.PostQualificationEditModelForEditAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification), + index: 1); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenQualificationIsUpdated_ShouldFlagQualificationsFieldIndicator() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.PostQualificationEditModelForEditAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + FromQualification(qualification), + index: 1); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Qualifications, true); + } + + [Fact] + public async Task WhenQualificationIsDeleted_ShouldRemoveQualificationFromDraftVacancy() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + var qualification = new Qualification + { + Subject = "English", + Grade = "C", + QualificationType = "GCSE", + Weighting = QualificationWeighting.Desired + }; + + await fixture.DeleteQualificationAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + index: 1); + + fixture.VerifyRemoveQualificationFromDraftVacancy(qualification); + } + + [Fact] + public async Task WhenQualificationIsDeleted_ShouldCallUpdateDraftVacancyAsync() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + await fixture.DeleteQualificationAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + index: 1); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenQualificationIsDeleted_ShouldFlagQualificationsFieldIndicator() + { + var fixture = new QualificationsOrchestratorTestsFixture(); + fixture + .WithQualfication("Mathematics", "A", "GCSE", QualificationWeighting.Desired) + .WithQualfication("English", "B", "GCSE", QualificationWeighting.Essential) + .WithQualfication("Science", "C", "GCSE", QualificationWeighting.Essential) + .Setup(); + + await fixture.DeleteQualificationAsync( + new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }, + index: 1); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Qualifications, true); + } + + private QualificationEditModel FromQualification(Qualification qualification) + { + return new QualificationEditModel + { + Subject = qualification.Subject, + Grade = qualification.Grade, + QualificationType = qualification.QualificationType, + Weighting = qualification.Weighting + }; + } + + public class QualificationsOrchestratorTestsFixture + { + public VacancyUser User { get; } + public Vacancy Vacancy { get; private set; } + public QualificationsOrchestrator Sut {get; private set;} + + public QualificationsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public QualificationsOrchestratorTestsFixture WithQualfication(string subject, string grade, string qualificationType, QualificationWeighting weighting) + { + if ((Vacancy.Qualifications == null)) + Vacancy.Qualifications = new List(); + + Vacancy.Qualifications.Add(new Qualification + { + Subject = subject, + Grade = grade, + QualificationType = qualificationType, + Weighting = weighting + }); + + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetCandidateQualificationsAsync()).ReturnsAsync(new List() { "GCSE", "A-LEVEL" }); + MockRecruitVacancyClient.Setup(x => x.ValidateQualification(It.IsAny())).Returns(new EntityValidationResult()); + + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)) + .Callback((vacancy, user) => { Vacancy = vacancy; }) + .Returns(Task.FromResult(0)); + + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new QualificationsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostQualificationEditModelForAddAsync(VacancyRouteModel vacancyRouteModel, QualificationEditModel model) + { + await Sut.PostQualificationEditModelForAddAsync(vacancyRouteModel, model, User); + } + + public async Task PostQualificationEditModelForEditAsync(VacancyRouteModel vacancyRouteModel, QualificationEditModel model, int index) + { + await Sut.PostQualificationEditModelForEditAsync(vacancyRouteModel, model, User, index); + } + + public async Task DeleteQualificationAsync(VacancyRouteModel vacancyRouteModel, int index) + { + await Sut.DeleteQualificationAsync(vacancyRouteModel, index, User); + } + + public void VerifyAddQualificationToDraftVacancy(int count, Qualification qualification) + { + Vacancy.Qualifications.Should().HaveCount(count); + ContainEquivalentOf(Vacancy.Qualifications, qualification).Should().BeTrue(); + } + + public void VerifyUpdateQualificationForDraftVacancy(Qualification qualification) + { + ContainEquivalentOf(Vacancy.Qualifications, qualification).Should().BeTrue(); + } + + public void VerifyRemoveQualificationFromDraftVacancy(Qualification qualification) + { + ContainEquivalentOf(Vacancy.Qualifications, qualification).Should().BeFalse(); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + private bool ContainEquivalentOf(List collection, T expected) + { + // the FluentAssertions ContainEquivalentOf does not have a negated equivalent + return collection.Any(p => JsonConvert.SerializeObject(p).Equals(JsonConvert.SerializeObject(expected))); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs new file mode 100644 index 0000000000..06a6cd99ed --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/ShortDescriptionOrchestratorTests.cs @@ -0,0 +1,120 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.ShortDescription; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class ShortDescriptionOrchestratorTests + { + private ShortDescriptionOrchestratorTestsFixture _fixture; + + public ShortDescriptionOrchestratorTests() + { + _fixture = new ShortDescriptionOrchestratorTestsFixture(); + } + + [Fact] + public async Task WhenUpdated__ShouldCallUpdateDraftVacancy() + { + _fixture + .WithShortDescription("has a value") + .Setup(); + + var shortDescriptionEditModel = new ShortDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ShortDescription = "has a new value" + }; + + await _fixture.PostShortDescriptionEditModelAsync(shortDescriptionEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Fact] + public async Task WhenShortDescriptionIsUpdated_ShouldFlagThingsToConsiderFieldIndicator() + { + _fixture + .WithShortDescription("has a value") + .Setup(); + + var shortDescriptionEditModel = new ShortDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ShortDescription = "has a new value" + }; + + await _fixture.PostShortDescriptionEditModelAsync(shortDescriptionEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.ShortDescription, true); + } + + public class ShortDescriptionOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ShortDescription; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public ShortDescriptionOrchestrator Sut {get; private set;} + + public ShortDescriptionOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public ShortDescriptionOrchestratorTestsFixture WithShortDescription(string shortDescription) + { + Vacancy.ShortDescription = shortDescription; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new ShortDescriptionOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostShortDescriptionEditModelAsync(ShortDescriptionEditModel model) + { + await Sut.PostShortDescriptionEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).FirstOrDefault() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs index 217eaeeaac..71adcd625b 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs @@ -1,14 +1,14 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; using Esfa.Recruit.Employer.Web.Orchestrators.Part2; using Esfa.Recruit.Employer.Web.RouteModel; -using Esfa.Recruit.Employer.Web.Services; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.Skills; using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; -using Esfa.Recruit.Vacancies.Client.Infrastructure.ReferenceData.Skills; using FluentAssertions; using Microsoft.Extensions.Logging; using Moq; @@ -18,216 +18,313 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 { public class SkillOrchestratorTests { - private const string TestEmployerAccountId = "ABC"; - private readonly Mock _mockClient; - private readonly Mock _mockVacancyClient; - - private readonly SkillsOrchestrator _orchestrator; - private readonly Vacancy _testVacancy; - private readonly VacancyRouteModel _testRouteModel = new VacancyRouteModel { EmployerAccountId = TestEmployerAccountId, VacancyId = Guid.NewGuid() }; - - public SkillOrchestratorTests() - { - var mockLogger = new Mock>(); - var candidateSkills = GetBaseSkills(); - _mockClient = new Mock(); - _mockVacancyClient = new Mock(); - _orchestrator = new SkillsOrchestrator(_mockClient.Object, _mockVacancyClient.Object, mockLogger.Object, Mock.Of()); - _testVacancy = GetTestVacancy(); - - _mockVacancyClient.Setup(x => x.GetCandidateSkillsAsync()).ReturnsAsync(candidateSkills); - } - [Fact] public async Task WhenNoSkillsSaved_ShouldReturnListOfAllBasicSkillsUnchecked() { - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .Setup(); - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); - - // Count that all 18 base skills are there - result.Column1Checkboxes.Count(x => x.Selected == false).Should().Be(9); - result.Column2Checkboxes.Count(x => x.Selected == false).Should().Be(8); - } - - [Fact] - public async Task WhenSingleBaseSkillSaved_ShouldReturnListOfAllBasicSkillsWithSkillSelected() - { - _testVacancy.Skills = new List { "Logical" }; // Set the saved skill - - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - var allCheckboxes = result.Column1Checkboxes.Union(result.Column2Checkboxes); - allCheckboxes.Where(x => x.Selected).Should().HaveCount(1); + fixture.VerifyAllBasicSkillsAreUnchecked(skillsViewModel); } - [Fact] - public async Task WhenMultipleBaseSkillsSaved_ShouldReturnListOfAllBasicSkillsWithSkillsSelected() + [Theory] + [InlineData(new string[] { "Logical" }, 1)] + [InlineData(new string[] { "Logical", "Patience" }, 2)] + public async Task WhenBaseSkillSaved_ShouldReturnListOfAllBasicSkillsWithSkillsSelected(string[] selectedSkills, int selectedCount) { - _testVacancy.Skills = new List { "Logical", "Patience" }; // Set the saved skill + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .WithSelectedSkills(selectedSkills) + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - var allCheckboxes = result.Column1Checkboxes.Union(result.Column2Checkboxes); - allCheckboxes.Where(x => x.Selected).Should().HaveCount(2); + fixture.VerifySelectedSkillsCount(skillsViewModel, selectedCount); } [Fact] public async Task WhenCustomSkillHasBeenSaved_ShouldReturnCustomSkillsSelectedInLastItemInSecondColumn() { - _testVacancy.Skills = new List { "Custom1" }; // Set the saved skill - - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var fixture = new SkillsOrchestratorTestsFixture(); + + var customSkill = "Custom1"; + fixture + .WithSelectedSkills(new string[] { customSkill }) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); - var lastCol2Item = result.Column2Checkboxes.Last(); - lastCol2Item.Name.Should().Be("Custom1"); - lastCol2Item.Selected.Should().BeTrue(); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, customSkill, 8); } [Fact] public async Task WhenMultipleCustomSkillsSaved_ShouldReturnTheCustomSkillsInAlternateColumnsStaringWithColumn2() { - _testVacancy.Skills = new List { "Custom1", "Custom2", "Custom3" }; // Set the saved skill + var fixture = new SkillsOrchestratorTestsFixture(); + + var customSkill1 = "Custom1"; + var customSkill2 = "Custom2"; + var customSkill3 = "Custom3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { customSkill1, customSkill2, customSkill3 }) + .Setup(); - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - result.Column2Checkboxes.FindIndex(x => x.Name == "Custom1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Custom2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Custom3").Should().Be(9); // 10th item in list + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel); + + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, customSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, customSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, customSkill3, 9); } [Fact] public async Task WhenCustomDraftSkillHasBeenAdded_ShouldBeAddedToColumn2() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "1-Draft1" }; + var draftSkill = "Draft1"; + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, new string[] { "1-" + draftSkill}); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill, 8); } [Fact] public async Task WhenCustomeDraftSkillsAdded_ShouldBeAddedToAlternateColumnsStartingWithColumn2() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "1-Draft1", "2-Draft2", "3-Draft3" }; + var draftSkill1 = "Draft1"; + var draftSkill2 = "Draft2"; + var draftSkill3 = "Draft3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, + new string[] { "1-" + draftSkill1, "2-" + draftSkill2, "3-" + draftSkill3 }); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Draft2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft3").Should().Be(9); // 10th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, draftSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } [Fact] public async Task WhenCustomDraftSkillsAddedAndBaseSkillSelected_ShouldBeAddedToAlternateColumnsStartingWithColumn2() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "1-Draft1", "Patience", "2-Draft2", "3-Draft3" }; + var draftSkill1 = "Draft1"; + var draftSkill2 = "Draft2"; + var draftSkill3 = "Draft3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, + new string[] { "1-" + draftSkill1, "Patience", "2-" + draftSkill2, "3-" + draftSkill3 }); - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Draft2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft3").Should().Be(9); // 10th item in list + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, draftSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } - + [Fact] - public async Task WhenCustomDraftSkillsAdded_ShouldIncludeIndicatorOfItsOrder() + public async Task WhenCustomDraftSkillsHaveBeenAdded_ShouldBeOrderedByTheirPrefix() { - _testVacancy.Skills = new List(); // No selected skills already persisted + var fixture = new SkillsOrchestratorTestsFixture(); - var draftSkills = new [] { "2-Draft2", "3-Draft3", "1-Draft1" }; + var draftSkill1 = "Draft1"; + var draftSkill2 = "Draft2"; + var draftSkill3 = "Draft3"; - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + fixture + .WithSelectedSkills(new string[] { }) + .Setup(); - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsViewModel = await fixture.GetSkillsViewModelAsync(vacancyRouteModel, + new string[] { "2-" + draftSkill2, "3-" + draftSkill3, "1-" + draftSkill1 }); - result.Column2Checkboxes.Single(x => x.Name == "Draft1").Value.Should().Be("1-Draft1"); - result.Column1Checkboxes.Single(x => x.Name == "Draft2").Value.Should().Be("2-Draft2"); - result.Column2Checkboxes.Single(x => x.Name == "Draft3").Value.Should().Be("3-Draft3"); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill1, 8); + fixture.VerifyColumn1CheckboxesItemSelected(skillsViewModel, draftSkill2, 9); + fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } - - [Fact] - public async Task WhenCustomDraftSkillsHaveBeenAdded_ShouldBeOrderedByTheirPrefix() + + public class SkillsOrchestratorTestsFixture { - _testVacancy.Skills = new List(); // No selected skills already persisted + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public SkillsOrchestrator Sut { get; private set; } - var draftSkills = new [] { "2-Draft2", "3-Draft3", "1-Draft1" }; + public SkillsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); - _mockVacancyClient.Setup(x => x.GetVacancyAsync(It.IsAny())).ReturnsAsync(_testVacancy); + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } - var result = await _orchestrator.GetSkillsViewModelAsync(_testRouteModel, draftSkills); + public SkillsOrchestratorTestsFixture WithSelectedSkills(string[] selectedSkills) + { + Vacancy.Skills = selectedSkills.ToList(); + return this; + } - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft1").Should().Be(8); // 9th item in list - result.Column1Checkboxes.FindIndex(x => x.Name == "Draft2").Should().Be(9); // 10th item in list - result.Column2Checkboxes.FindIndex(x => x.Name == "Draft3").Should().Be(9); // 10th item in list - } + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetCandidateSkillsAsync()).ReturnsAsync(GetBasicSkills()); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new SkillsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task GetSkillsViewModelAsync(VacancyRouteModel vacancyRouteModel, string[] draftSkills = null) + { + return await Sut.GetSkillsViewModelAsync(vacancyRouteModel, draftSkills); + } - private static Vacancy GetTestVacancy() - { - return new Vacancy + public async Task PostSkillsEditModelAsync(VacancyRouteModel vacancyRouteModel, SkillsEditModel model) + { + await Sut.PostSkillsEditModelAsync(vacancyRouteModel, model, User); + } + + public void VerifyAllBasicSkillsAreUnchecked(SkillsViewModel skillsViewModel) + { + var allCheckboxes = skillsViewModel.Column1Checkboxes.Union(skillsViewModel.Column2Checkboxes); + allCheckboxes.Where(x => x.Selected == false).Should().HaveCount(GetBasicSkills().Count); + } + + internal void VerifySelectedSkillsCount(SkillsViewModel skillsViewModel, int count) { - EmployerAccountId = TestEmployerAccountId, - Title = "Test Title", - NumberOfPositions = 1, - ShortDescription = "Test Short Description", - EmployerLocation = new Address + var allCheckboxes = skillsViewModel.Column1Checkboxes.Union(skillsViewModel.Column2Checkboxes); + allCheckboxes.Where(x => x.Selected).Should().HaveCount(count); + } + + public SkillsOrchestratorTestsFixture VerifyColumn2CheckboxesItemSelected(SkillsViewModel skillsViewModel, string customSkill, int index) + { + skillsViewModel.Column2Checkboxes.FindIndex(x => x.Name == customSkill && x.Selected).Should().Be(index); + return this; + } + + public SkillsOrchestratorTestsFixture VerifyColumn1CheckboxesItemSelected(SkillsViewModel skillsViewModel, string customSkill, int index) + { + skillsViewModel.Column1Checkboxes.FindIndex(x => x.Name == customSkill && x.Selected).Should().Be(index); + return this; + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) { - Postcode = "AB1 2XZ" - }, - ProgrammeId = "2", - Wage = new Wage + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) { - Duration = 1, - WageType = WageType.NationalMinimumWage - }, - LegalEntityName = "legal name", - EmployerNameOption = EmployerNameOption.RegisteredName, - StartDate = DateTime.Now - }; - } + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } - private static List GetBaseSkills() - { - return new List - { - "Communication skills", - "IT skills", - "Attention to detail", - "Organisation skills", - "Customer care skills", - "Problem solving skills", - "Presentation skills", - "Administrative skills", - "Number skills", - "Analytical skills", - "Logical", - "Team working", - "Creative", - "Initiative", - "Non judgemental", - "Patience", - "Physical fitness" - }; + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + private static List GetBasicSkills() + { + return new List + { + "Communication skills", + "IT skills", + "Attention to detail", + "Organisation skills", + "Customer care skills", + "Problem solving skills", + "Presentation skills", + "Administrative skills", + "Number skills", + "Analytical skills", + "Logical", + "Team working", + "Creative", + "Initiative", + "Non judgemental", + "Patience", + "Physical fitness" + }; + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs new file mode 100644 index 0000000000..dea2af123e --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/VacancyDescriptionOrchestratorTests.cs @@ -0,0 +1,163 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part2; +using Esfa.Recruit.Employer.Web.ViewModels; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.ShortDescription; +using Esfa.Recruit.Employer.Web.ViewModels.Part2.VacancyDescription; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part2 +{ + public class VacancyDescriptionOrchestratorTests + { + private VacancyDescriptionOrchestratorTestsFixture _fixture; + + public VacancyDescriptionOrchestratorTests() + { + _fixture = new VacancyDescriptionOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value")] + [InlineData("has a value", "has a new value", "has a value")] + [InlineData("has a value", "has a value", "has a new value")] + [InlineData("has a new value", "has a new value", "has a new value")] + public async Task WhenUpdated__ShouldCallUpdateDraftVacancy(string description, string trainingDescription, string outcomeDescription) + { + _fixture + .WithDescription("has a value") + .WithTrainingDescription("has a value") + .WithOutcomeDescription("has a value") + .Setup(); + + var vacancyDescriptionEditModel = new VacancyDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + VacancyDescription = description, + TrainingDescription = trainingDescription, + OutcomeDescription = outcomeDescription + }; + + await _fixture.PostVacancyDescriptionEditModelAsync(vacancyDescriptionEditModel); + + _fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + + [Theory] + [InlineData("has a new value", "has a value", "has a value", new string[] { FieldIdentifiers.VacancyDescription }, new string[] { FieldIdentifiers.TrainingDescription, FieldIdentifiers.OutcomeDescription })] + [InlineData("has a value", "has a new value", "has a value", new string[] { FieldIdentifiers.TrainingDescription }, new string[] { FieldIdentifiers.VacancyDescription, FieldIdentifiers.OutcomeDescription })] + [InlineData("has a value", "has a value", "has a new value", new string[] { FieldIdentifiers.OutcomeDescription }, new string[] { FieldIdentifiers.VacancyDescription, FieldIdentifiers.Training})] + [InlineData("has a new value", "has a new value", "has a new value", new string[] { FieldIdentifiers.VacancyDescription, FieldIdentifiers.TrainingDescription , FieldIdentifiers.OutcomeDescription }, new string[] { })] + public async Task WhenShortDescriptionIsUpdated_ShouldFlagFieldIndicators(string description, string trainingDescription, string outcomeDescription, string[] setFieldIndicators, string[] unsetFieldIndicators) + { + _fixture + .WithDescription("has a value") + .WithTrainingDescription("has a value") + .WithOutcomeDescription("has a value") + .Setup(); + + var vacancyDescriptionEditModel = new VacancyDescriptionEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + VacancyDescription = description, + TrainingDescription = trainingDescription, + OutcomeDescription = outcomeDescription + }; + + await _fixture.PostVacancyDescriptionEditModelAsync(vacancyDescriptionEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIndicators, unsetFieldIndicators); + } + + public class VacancyDescriptionOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public VacancyDescriptionOrchestrator Sut {get; private set;} + + public VacancyDescriptionOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public VacancyDescriptionOrchestratorTestsFixture WithDescription(string description) + { + Vacancy.Description = description; + return this; + } + + public VacancyDescriptionOrchestratorTestsFixture WithTrainingDescription(string trainingDescription) + { + Vacancy.TrainingDescription = trainingDescription; + return this; + } + + public VacancyDescriptionOrchestratorTestsFixture WithOutcomeDescription(string outcomeDescription) + { + Vacancy.OutcomeDescription = outcomeDescription; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new VacancyDescriptionOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), Mock.Of()); + } + + public async Task PostVacancyDescriptionEditModelAsync(VacancyDescriptionEditModel model) + { + await Sut.PostVacancyDescriptionEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} From b8542bbac1db6ccbd8a0c73d63d1be1780541fc3 Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Thu, 19 Aug 2021 17:57:58 +0100 Subject: [PATCH 07/19] Added more part1 orchestrator tests for field indicators --- .../Orchestrators/Part1/TitleOrchestrator.cs | 6 +- .../HardMocks/VacancyOrchestratorTestData.cs | 35 ++- .../Part1/DatesOrchestratorTests.cs | 137 ++++++++ .../Part1/DurationOrchestratorTests.cs | 143 +++++++++ .../Part1/LocationOrchestratorTests.cs | 169 ++++++++++ .../NumberOfPositionsOrchestratorTests.cs | 97 ++++++ .../Part1/TitleOrchestratorTests.cs | 99 ++++++ .../Part1/TrainingOrchestratorTests.cs | 101 ++++++ .../TrainingProviderOrchestratorTests.cs | 297 ++++++++++++------ .../Part1/WageOrchestratorTests.cs | 131 ++++++++ .../Part2/SkillOrchestratorTests.cs | 76 ++++- 11 files changed, 1177 insertions(+), 114 deletions(-) create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs create mode 100644 src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs index d3ad72baea..661d5306c2 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/TitleOrchestrator.cs @@ -23,15 +23,13 @@ public class TitleOrchestrator : VacancyValidatingOrchestrator private readonly IEmployerVacancyClient _client; private readonly IRecruitVacancyClient _vacancyClient; private readonly IReviewSummaryService _reviewSummaryService; - private readonly IEmployerVacancyClient _employerVacancyClient; private readonly ITrainingProviderService _trainingProviderService; - public TitleOrchestrator(IEmployerVacancyClient client, IRecruitVacancyClient vacancyClient, ILogger logger, IReviewSummaryService reviewSummaryService, IEmployerVacancyClient employerVacancyClient, ITrainingProviderService trainingProviderService) : base(logger) + public TitleOrchestrator(IEmployerVacancyClient client, IRecruitVacancyClient vacancyClient, ILogger logger, IReviewSummaryService reviewSummaryService, ITrainingProviderService trainingProviderService) : base(logger) { _client = client; _vacancyClient = vacancyClient; _reviewSummaryService = reviewSummaryService; - _employerVacancyClient = employerVacancyClient; _trainingProviderService = trainingProviderService; } @@ -46,7 +44,7 @@ public TitleViewModel GetTitleViewModel() public async Task GetTitleViewModelAsync(VacancyRouteModel vrm) { - var dashboard = await _employerVacancyClient.GetDashboardAsync(vrm.EmployerAccountId); + var dashboard = await _client.GetDashboardAsync(vrm.EmployerAccountId); var vacancy = await Utility.GetAuthorisedVacancyForEditAsync(_client, _vacancyClient, vrm, RouteNames.Title_Get); var vm = new TitleViewModel diff --git a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs index 8050b9dbcb..9ea1c8588d 100644 --- a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs +++ b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs @@ -1,15 +1,21 @@ -using Esfa.Recruit.Vacancies.Client.Domain.Entities; -using System; +using System; +using System.Collections.Generic; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo; +using Address = Esfa.Recruit.Vacancies.Client.Domain.Entities.Address; namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks { internal class VacancyOrchestratorTestData { + private const string AccountLegalEntityPublicHashedId = "ABC123"; + internal static Vacancy GetPart1CompleteVacancy() { return new Vacancy { EmployerAccountId = "EMPLOYER ACCOUNT ID", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId, Id = Guid.Parse("84af954e-5baf-4942-897d-d00180a0839e"), Title = "has a value", NumberOfPositions = 1, @@ -37,7 +43,30 @@ internal static EmployerProfile GetEmployerProfile() { return new EmployerProfile { - EmployerAccountId = "EMPLOYER ACCOUNT ID" + EmployerAccountId = "EMPLOYER ACCOUNT ID", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId + }; + } + + internal static EmployerEditVacancyInfo GetEmployerEditVacancyInfo() + { + return new EmployerEditVacancyInfo + { + LegalEntities = new List + { + new LegalEntity + { + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId, + Address = new Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo.Address + { + AddressLine1 = "this is a value", + AddressLine2 = "this is a value", + AddressLine3 = "this is a value", + AddressLine4 = "this is a value", + Postcode = "this is a value" + } + } + } }; } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs new file mode 100644 index 0000000000..9aeaaaf80e --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs @@ -0,0 +1,137 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Dates; +using Esfa.Recruit.Shared.Web.Extensions; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class DatesOrchestratorTests + { + private DatesOrchestratorTestsFixture _fixture; + + public DatesOrchestratorTests() + { + _fixture = new DatesOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("31/12/2021", "01/01/2001", false, new string[] { FieldIdentifiers.ClosingDate }, new string[] { FieldIdentifiers.PossibleStartDate, FieldIdentifiers.DisabilityConfident})] + [InlineData("01/01/2001", "31/12/2021", false, new string[] { FieldIdentifiers.PossibleStartDate }, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.DisabilityConfident })] + [InlineData("01/01/2001", "01/01/2001", true, new string[] { FieldIdentifiers.DisabilityConfident }, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.PossibleStartDate })] + [InlineData("01/01/2001", "01/01/2001", false, new string[] { }, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.PossibleStartDate, FieldIdentifiers.DisabilityConfident })] + [InlineData("31/12/2021", "31/12/2021", true, new string[] { FieldIdentifiers.ClosingDate, FieldIdentifiers.PossibleStartDate, FieldIdentifiers.DisabilityConfident }, new string[] { })] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string closingDate, string startDate, bool isDisablityConfident, string[] setFieldIdentifers, string [] unsetFieldIdentifiers) + { + _fixture + .WithClosingDate("01/01/2001") + .WithStartDate("01/01/2001") + .WithDisabilityConfident(false) + .Setup(); + + var datesEditModel = new DatesEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ClosingDay = DateTime.Parse(closingDate).Day.ToString(), + ClosingMonth = DateTime.Parse(closingDate).Month.ToString(), + ClosingYear = DateTime.Parse(closingDate).Year.ToString(), + StartDay = DateTime.Parse(startDate).Day.ToString(), + StartMonth = DateTime.Parse(startDate).Month.ToString(), + StartYear = DateTime.Parse(startDate).Year.ToString(), + IsDisabilityConfident = isDisablityConfident + }; + + await _fixture.PostDatesEditModelAsync(datesEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIdentifers, unsetFieldIdentifiers); + } + + public class DatesOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.ClosingDate | VacancyRuleSet.StartDate | VacancyRuleSet.StartDateEndDate | VacancyRuleSet.TrainingExpiryDate; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public DatesOrchestrator Sut {get; private set;} + + public DatesOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public DatesOrchestratorTestsFixture WithClosingDate(string closingDate) + { + Vacancy.ClosingDate = closingDate.AsDateTimeUk()?.ToUniversalTime(); + return this; + } + + public DatesOrchestratorTestsFixture WithStartDate(string startDate) + { + Vacancy.StartDate = startDate.AsDateTimeUk()?.ToUniversalTime(); + return this; + } + + public DatesOrchestratorTestsFixture WithDisabilityConfident(bool isDisablityConfident) + { + Vacancy.DisabilityConfident = isDisablityConfident ? DisabilityConfident.Yes : DisabilityConfident.No; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new DatesOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(),Mock.Of(), Mock.Of()); + } + + public async Task PostDatesEditModelAsync(DatesEditModel model) + { + await Sut.PostDatesEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs new file mode 100644 index 0000000000..75bb42e784 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DurationOrchestratorTests.cs @@ -0,0 +1,143 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Dates; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Duration; +using Esfa.Recruit.Shared.Web.Extensions; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class DurationOrchestratorTests + { + private DurationOrchestratorTestsFixture _fixture; + + public DurationOrchestratorTests() + { + _fixture = new DurationOrchestratorTestsFixture(); + } + + [Theory] + [InlineData(24, DurationUnit.Month, 37.0, "this is a value", new string[] { }, new string[] { FieldIdentifiers.ExpectedDuration, FieldIdentifiers.WorkingWeek })] + [InlineData(12, DurationUnit.Month, 37.0, "this is a value", new string[] { FieldIdentifiers.ExpectedDuration }, new string[] { FieldIdentifiers.WorkingWeek })] + [InlineData(24, DurationUnit.Year, 37.0, "this is a value", new string[] { FieldIdentifiers.ExpectedDuration }, new string[] { FieldIdentifiers.WorkingWeek })] + [InlineData(24, DurationUnit.Month, 35.0, "this is a value", new string[] { FieldIdentifiers.WorkingWeek }, new string[] { FieldIdentifiers.ExpectedDuration })] + [InlineData(24, DurationUnit.Month, 37.0, "this is a new value", new string[] { FieldIdentifiers.WorkingWeek }, new string[] { FieldIdentifiers.ExpectedDuration })] + [InlineData(1, DurationUnit.Year, 35.0, "this is a new value", new string[] { FieldIdentifiers.ExpectedDuration, FieldIdentifiers.WorkingWeek }, new string[] { })] + public async Task WhenUpdated_ShouldFlagFieldIndicators(int duration, DurationUnit durationUnit, decimal weeklyHours, string workingWeekDescription, string[] setFieldIdentifers, string [] unsetFieldIdentifiers) + { + _fixture + .WithDuration(24) + .WithDurationUnit(DurationUnit.Month) + .WithWeeklyHours(37) + .WithWorkingWeekDescription("this is a value") + .Setup(); + + var durationEditModel = new DurationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + Duration = duration.ToString(), + DurationUnit = durationUnit, + WeeklyHours = weeklyHours.ToString(), + WorkingWeekDescription = workingWeekDescription + }; + + await _fixture.PostDurationEditModelAsync(durationEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(setFieldIdentifers, unsetFieldIdentifiers); + } + + public class DurationOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Duration | VacancyRuleSet.WorkingWeekDescription | VacancyRuleSet.WeeklyHours; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public DurationOrchestrator Sut {get; private set;} + + public DurationOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public DurationOrchestratorTestsFixture WithDuration(int duration) + { + Vacancy.Wage.Duration = duration; + return this; + } + + public DurationOrchestratorTestsFixture WithDurationUnit(DurationUnit durationUnit) + { + Vacancy.Wage.DurationUnit = durationUnit; + return this; + } + + public DurationOrchestratorTestsFixture WithWeeklyHours(decimal weeklyHours) + { + Vacancy.Wage.WeeklyHours = weeklyHours; + return this; + } + + public DurationOrchestratorTestsFixture WithWorkingWeekDescription(string workingWeekDescription) + { + Vacancy.Wage.WorkingWeekDescription = workingWeekDescription; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new DurationOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostDurationEditModelAsync(DurationEditModel model) + { + await Sut.PostDurationEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs new file mode 100644 index 0000000000..831af15e6f --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs @@ -0,0 +1,169 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Models; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Duration; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Location; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Wage; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using Esfa.Recruit.Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; +using Address = Esfa.Recruit.Vacancies.Client.Domain.Entities.Address; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class LocationOrchestratorTests + { + private LocationOrchestratorTestsFixture _fixture; + + public LocationOrchestratorTests() + { + _fixture = new LocationOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("this is a value", "this is a value", "this is a value", "this is a value", "this is a value", false)] + [InlineData("this is a new value", "this is a value", "this is a value", "this is a value", "this is a value", true)] + [InlineData("this is a value", "this is a new value", "this is a value", "this is a value", "this is a value", true)] + [InlineData("this is a value", "this is a value", "this is a new value", "this is a value", "this is a value", true)] + [InlineData("this is a value", "this is a value", "this is a value", "this is a new value", "this is a value", true)] + [InlineData("this is a value", "this is a value", "this is a value", "this is a value", "this is a new value", true)] + [InlineData("this is a new value", "this is a new value", "this is a new value", "this is a new value", "this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string addressLine1, string addressLine2, string addressLine3, string addressLine4, string postcode, bool fieldIndicatorSet) + { + _fixture + .WithAddressLine1("this is a value") + .WithAddressLine2("this is a value") + .WithAddresLine3("this is a value") + .WithAddresLine4("this is a value") + .WithPostcode("this is a value") + .Setup(); + + var locationEditModel = new LocationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + AddressLine1 = addressLine1, + AddressLine2 = addressLine2, + AddressLine3 = addressLine3, + AddressLine4 = addressLine4, + Postcode = postcode, + SelectedLocation = LocationViewModel.UseOtherLocationConst + }; + + await _fixture.PostLocationEditModelAsync(locationEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerAddress, fieldIndicatorSet); + } + + public class LocationOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerAddress; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public EmployerEditVacancyInfo EmployerEditVacancyInfo { get; } + public EmployerProfile EmployerProfile { get; } + public LocationOrchestrator Sut {get; private set;} + + public LocationOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + EmployerEditVacancyInfo = VacancyOrchestratorTestData.GetEmployerEditVacancyInfo(); + EmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(); + } + + public LocationOrchestratorTestsFixture WithAddressLine1(string addressLine1) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine1 = addressLine1; + return this; + } + + public LocationOrchestratorTestsFixture WithAddressLine2(string addressLine2) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine2 = addressLine2; + return this; + } + + public LocationOrchestratorTestsFixture WithAddresLine3(string addressLine3) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine3 = addressLine3; + return this; + } + + public LocationOrchestratorTestsFixture WithAddresLine4(string addressLine4) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.AddressLine4 = addressLine4; + return this; + } + + public LocationOrchestratorTestsFixture WithPostcode(string postcode) + { + if (Vacancy.EmployerLocation == null) + Vacancy.EmployerLocation = new Address(); + + Vacancy.EmployerLocation.Postcode = postcode; + return this; + } + + public void Setup() + { + MockClient.Setup(x => x.GetEditVacancyInfoAsync(Vacancy.EmployerAccountId)).ReturnsAsync(EmployerEditVacancyInfo); + + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, Vacancy.AccountLegalEntityPublicHashedId)).ReturnsAsync(EmployerProfile); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new LocationOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostLocationEditModelAsync(LocationEditModel model) + { + await Sut.PostLocationEditModelAsync(model, + new VacancyEmployerInfoModel + { + VacancyId = Vacancy.Id + }, + User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs new file mode 100644 index 0000000000..038f7f6b06 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/NumberOfPositionsOrchestratorTests.cs @@ -0,0 +1,97 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.NumberOfPositions; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class NumberofPositionsOrchestratorTests + { + private NumberofPositionsOrchestratorTestsFixture _fixture; + + public NumberofPositionsOrchestratorTests() + { + _fixture = new NumberofPositionsOrchestratorTestsFixture(); + } + + [Theory] + [InlineData(1, false)] + [InlineData(2, true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(int numberOfPositions, bool fieldIndicatorSet) + { + _fixture + .WithNumberOfPositions(1) + .Setup(); + + var numberOfPositionsEditModel = new NumberOfPositionsEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + NumberOfPositions = numberOfPositions.ToString() + }; + + await _fixture.PostNumberOfPositionsEditModelAsync(numberOfPositionsEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.NumberOfPositions, fieldIndicatorSet); + } + + public class NumberofPositionsOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.NumberOfPositions; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public NumberOfPositionsOrchestrator Sut {get; private set;} + + public NumberofPositionsOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public NumberofPositionsOrchestratorTestsFixture WithNumberOfPositions(int numberOfPositions) + { + Vacancy.NumberOfPositions = numberOfPositions; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new NumberOfPositionsOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostNumberOfPositionsEditModelAsync(NumberOfPositionsEditModel model) + { + await Sut.PostNumberOfPositionsEditModelAsync(model, User); + } + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs new file mode 100644 index 0000000000..0c2a3d1cdd --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TitleOrchestratorTests.cs @@ -0,0 +1,99 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Title; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Services.TrainingProvider; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class TitleOrchestratorTests + { + private TitleOrchestratorTestsFixture _fixture; + + public TitleOrchestratorTests() + { + _fixture = new TitleOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("this is a value", false)] + [InlineData("this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string title, bool fieldIndicatorSet) + { + _fixture + .WithTitle("this is a value") + .Setup(); + + var titleEditModel = new TitleEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + Title = title + }; + + await _fixture.PostTitleEditModelAsync(titleEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Title, fieldIndicatorSet); + } + + public class TitleOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Title; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public TitleOrchestrator Sut {get; private set;} + + public TitleOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public TitleOrchestratorTestsFixture WithTitle(string title) + { + Vacancy.Title = title; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new TitleOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(), Mock.Of()); + } + + public async Task PostTitleEditModelAsync(TitleEditModel model) + { + await Sut.PostTitleEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs new file mode 100644 index 0000000000..6c60e54a78 --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingOrchestratorTests.cs @@ -0,0 +1,101 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Title; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Training; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Services.TrainingProvider; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class TrainingOrchestratorTests + { + private TrainingOrchestratorTestsFixture _fixture; + + public TrainingOrchestratorTests() + { + _fixture = new TrainingOrchestratorTestsFixture(); + } + + [Theory] + [InlineData("this is a value", false)] + [InlineData("this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(string programmeId, bool fieldIndicatorSet) + { + _fixture + .WithProgrammeId("this is a value") + .Setup(); + + var confirmTrainingEditModel = new ConfirmTrainingEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + ProgrammeId = programmeId + }; + + await _fixture.PostConfirmTrainingEditModelAsync(confirmTrainingEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.TrainingLevel, fieldIndicatorSet); + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Training, fieldIndicatorSet); + } + + public class TrainingOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProgramme; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public TrainingOrchestrator Sut {get; private set;} + + public TrainingOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public TrainingOrchestratorTestsFixture WithProgrammeId(string programmeId) + { + Vacancy.ProgrammeId = programmeId; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new TrainingOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of()); + } + + public async Task PostConfirmTrainingEditModelAsync(ConfirmTrainingEditModel model) + { + await Sut.PostConfirmTrainingEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs index ff888ff7c5..03db0c04cd 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/TrainingProviderOrchestratorTests.cs @@ -1,8 +1,13 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Models; using Esfa.Recruit.Employer.Web.Orchestrators.Part1; using Esfa.Recruit.Employer.Web.ViewModels.Part1.TrainingProvider; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Orchestrators; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; using Esfa.Recruit.Vacancies.Client.Application.Validation; @@ -17,158 +22,264 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 { public class TrainingProviderOrchestratorTests - { - private const string EmployerAccountId = "EMPLOYERACCOUNTID"; - private readonly Guid VacancyId = Guid.Parse("0a8e54c9-e284-4023-b688-14b9d841fcd7"); - + { [Fact] public async Task PostSelectTrainingProviderAsync_WhenNotChoosingThenRemoveExistingTrainingProvider() { - var vacancy = new Vacancy - { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" - }; - - var orch = GetTrainingProviderOrchestrator(vacancy); + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var m = new SelectTrainingProviderEditModel + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { - IsTrainingProviderSelected = false, - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, + IsTrainingProviderSelected = false }; - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); - vacancy.TrainingProvider.Should().BeNull(); - result.Data.FoundTrainingProviderUkprn.Should().BeNull(); + fixture.VerifyTrainingProviderNotSet(); + fixture.VerifyNotFoundTrainingProviderUkprn(result); } [Theory] [InlineData("This search won't match a single provider")] - [InlineData("88888")] //will match multiple providers + [InlineData("88888")] // will match multiple providers public async Task PostSelectTrainingProviderAsync_TrainingProviderSearch_WhenNoSingleProviderFoundShouldNotReturnFoundProvider(string trainingProviderSearch) { - var vacancy = new Vacancy - { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" - }; + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var orch = GetTrainingProviderOrchestrator(vacancy); - - var m = new SelectTrainingProviderEditModel + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, IsTrainingProviderSelected = true, SelectionType = TrainingProviderSelectionType.TrainingProviderSearch, - TrainingProviderSearch = trainingProviderSearch, - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + TrainingProviderSearch = trainingProviderSearch }; - - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); - result.Data.FoundTrainingProviderUkprn.Should().BeNull(); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); + + fixture.VerifyNotFoundTrainingProviderUkprn(result); } [Fact] public async Task PostSelectTrainingProviderAsync_TrainingProviderSearch_WhenSingleProviderFoundShouldReturnFoundProvider() { - var vacancy = new Vacancy - { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" - }; + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var orch = GetTrainingProviderOrchestrator(vacancy); - - var m = new SelectTrainingProviderEditModel + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, IsTrainingProviderSelected = true, SelectionType = TrainingProviderSelectionType.TrainingProviderSearch, - TrainingProviderSearch = "MR EGG 88888888", - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + TrainingProviderSearch = "FIRST TRAINING PROVIDER 88888888", }; - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); - result.Data.FoundTrainingProviderUkprn.Should().Be(88888888); + fixture.VerifyFoundTrainingProviderUkprn(result, fixture.TrainingProviderOne.Ukprn.Value); } [Fact] public async Task PostSelectTrainingProviderAsync_UKPRN_WhenSingleProviderFoundShouldReturnFoundProvider() { - var vacancy = new Vacancy + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); + + var selectTrainingProviderEditModel = new SelectTrainingProviderEditModel { - Id = VacancyId, - EmployerAccountId = EmployerAccountId, - TrainingProvider = new TrainingProvider(), - Title = "specified for route validation", - ProgrammeId = "specified for route validation" + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, + IsTrainingProviderSelected = true, + SelectionType = TrainingProviderSelectionType.Ukprn, + Ukprn = fixture.TrainingProviderOne.Ukprn.ToString() }; - var orch = GetTrainingProviderOrchestrator(vacancy); + var result = await fixture.PostSelectTrainingProviderAsync(selectTrainingProviderEditModel); + + fixture.VerifyFoundTrainingProviderUkprn(result, fixture.TrainingProviderOne.Ukprn.Value); + } + + [Theory] + [InlineData(88888888)] + [InlineData(88888889)] + public async Task PostConfirmEditModelAsync_ShouldFlagProviderFieldIndicator(long ukprn) + { + var fixture = new TrainingProviderOrchestratorTestsFixture(); + fixture + .WithVacacny( + new Vacancy + { + Id = fixture.VacancyId, + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + TrainingProvider = new TrainingProvider(), + Title = "specified for route validation", + ProgrammeId = "specified for route validation" + }) + .Setup(); - var m = new SelectTrainingProviderEditModel + var confirmTrainingProviderEditModel = new ConfirmTrainingProviderEditModel { - IsTrainingProviderSelected = true, - SelectionType = TrainingProviderSelectionType.Ukprn, - Ukprn = "88888888", - EmployerAccountId = EmployerAccountId, - VacancyId = VacancyId + EmployerAccountId = TrainingProviderOrchestratorTestsFixture.EmployerAccountId, + VacancyId = fixture.Vacancy.Id, + Ukprn = ukprn.ToString() }; - var result = await orch.PostSelectTrainingProviderAsync(m, new VacancyUser()); + await fixture.PostConfirmEditModelAsync(confirmTrainingProviderEditModel); - result.Data.FoundTrainingProviderUkprn.Should().Be(88888888); + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Provider, true); } - private TrainingProviderOrchestrator GetTrainingProviderOrchestrator(Vacancy vacancy) + public class TrainingProviderOrchestratorTestsFixture { - var mockClient = new Mock(); + private const VacancyRuleSet ValidationRules = VacancyRuleSet.TrainingProvider; + public TrainingProvider TrainingProviderOne { get; set; } + public TrainingProvider TrainingProviderTwo { get; set; } + public TrainingProviderSummary TrainingProviderSummaryOne { get; set; } + public TrainingProviderSummary TrainingProviderSummaryTwo { get; set; } + public VacancyUser User { get; } + public Vacancy Vacancy { get; private set; } + public TrainingProviderOrchestrator Sut { get; private set; } + + public const string EmployerAccountId = "EmployerAccountId"; + public readonly Guid VacancyId = Guid.NewGuid(); + + public TrainingProviderOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + MockTrainingProviderSummaryProvider = new Mock(); + MockTrainingProviderService = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + + TrainingProviderOne = new TrainingProvider { Ukprn = 88888888 }; + TrainingProviderTwo = new TrainingProvider { Ukprn = 88888889 }; + TrainingProviderSummaryOne = new TrainingProviderSummary { ProviderName = "First Training Provider", Ukprn = TrainingProviderOne.Ukprn.Value }; + TrainingProviderSummaryTwo = new TrainingProviderSummary { ProviderName = "Second Training Provider", Ukprn = TrainingProviderTwo.Ukprn.Value }; + } + + public TrainingProviderOrchestratorTestsFixture WithVacacny(Vacancy vacancy) + { + Vacancy = vacancy; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + MockTrainingProviderSummaryProvider.Setup(p => p.FindAllAsync()).ReturnsAsync(new List + { + TrainingProviderSummaryOne, + TrainingProviderSummaryTwo + }); - var mockTrainingProviderService = new Mock(); - mockTrainingProviderService.Setup(t => t.GetProviderAsync(88888888)) - .ReturnsAsync(new TrainingProvider {Ukprn = 88888888}); + MockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(TrainingProviderSummaryOne.Ukprn)) + .ReturnsAsync(TrainingProviderSummaryOne); - var mockRecruitClient = new Mock(); - mockRecruitClient.Setup(c => c.GetVacancyAsync(VacancyId)).ReturnsAsync(vacancy); + MockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(TrainingProviderSummaryTwo.Ukprn)) + .ReturnsAsync(TrainingProviderSummaryTwo); - var mockTrainingProviderSummaryProvider = new Mock(); + MockTrainingProviderService.Setup(t => t.GetProviderAsync(TrainingProviderOne.Ukprn.Value)) + .ReturnsAsync(TrainingProviderOne); - var mrEggTrainingProvider = new TrainingProviderSummary { ProviderName = "MR EGG", Ukprn = 88888888 }; - var mrsEggTrainingProvider = new TrainingProviderSummary { ProviderName = "MRS EGG", Ukprn = 88888889 }; + MockTrainingProviderService.Setup(t => t.GetProviderAsync(TrainingProviderTwo.Ukprn.Value)) + .ReturnsAsync(TrainingProviderTwo); - mockTrainingProviderSummaryProvider.Setup(p => p.FindAllAsync()).ReturnsAsync(new List + Sut = new TrainingProviderOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(), MockTrainingProviderSummaryProvider.Object, MockTrainingProviderService.Object); + } + + public async Task> PostSelectTrainingProviderAsync(SelectTrainingProviderEditModel model) { - mrEggTrainingProvider, - mrsEggTrainingProvider - }); + return await Sut.PostSelectTrainingProviderAsync(model, User); + } - mockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(88888888)) - .ReturnsAsync(mrEggTrainingProvider); + public async Task PostConfirmEditModelAsync(ConfirmTrainingProviderEditModel model) + { + return await Sut.PostConfirmEditModelAsync(model, User); + } - mockTrainingProviderSummaryProvider.Setup(p => p.GetAsync(88888889)) - .ReturnsAsync(mrsEggTrainingProvider); + public void VerifyFoundTrainingProviderUkprn(OrchestratorResponse result, long value) + { + result.Data.FoundTrainingProviderUkprn.Should().Be(value); + } - mockRecruitClient.Setup(c => c.Validate(It.IsAny(), VacancyRuleSet.TrainingProvider)) - .Returns(new EntityValidationResult()); + public void VerifyNotFoundTrainingProviderUkprn(OrchestratorResponse result) + { + result.Data.FoundTrainingProviderUkprn.Should().BeNull(); + } - var mockLog = new Mock>(); - var mockReview = new Mock(); + public void VerifyTrainingProviderNotSet() + { + Vacancy.TrainingProvider.Should().BeNull(); + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public void VerifyUpdateDraftVacancyAsyncIsCalled() + { + MockRecruitVacancyClient.Verify(x => x.UpdateDraftVacancyAsync(Vacancy, User), Times.Once); + } - return new TrainingProviderOrchestrator(mockClient.Object, mockRecruitClient.Object, mockLog.Object, mockReview.Object, mockTrainingProviderSummaryProvider.Object, mockTrainingProviderService.Object); + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + public Mock MockTrainingProviderSummaryProvider { get; set; } + public Mock MockTrainingProviderService { get; set; } } } } diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs new file mode 100644 index 0000000000..e9e12c553f --- /dev/null +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/WageOrchestratorTests.cs @@ -0,0 +1,131 @@ +using System.Linq; +using System.Threading.Tasks; +using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; +using Esfa.Recruit.Employer.Web.Orchestrators.Part1; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Duration; +using Esfa.Recruit.Employer.Web.ViewModels.Part1.Wage; +using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Services; +using Esfa.Recruit.Vacancies.Client.Application.Providers; +using Esfa.Recruit.Vacancies.Client.Application.Validation; +using Esfa.Recruit.Vacancies.Client.Domain.Entities; +using Esfa.Recruit.Vacancies.Client.Infrastructure.Client; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.Orchestrators.Part1 +{ + public class WageOrchestratorTests + { + private WageOrchestratorTestsFixture _fixture; + + public WageOrchestratorTests() + { + _fixture = new WageOrchestratorTestsFixture(); + } + + [Theory] + [InlineData(WageType.FixedWage, 10000, "this is a value", false)] + [InlineData(WageType.NationalMinimumWage, 10000, "this is a value", true)] + [InlineData(WageType.FixedWage, 11000, "this is a value", true)] + [InlineData(WageType.FixedWage, 10000, "this is a new value", true)] + public async Task WhenUpdated_ShouldFlagFieldIndicators(WageType wageType, decimal fixedWageYearlyAmmount, string wageAddtionalInformation, bool fieldIndicatorSet) + { + _fixture + .WithWageType(WageType.FixedWage) + .WithFixedWageYearlyAmount(10000) + .WithWageAdditionalInformation("this is a value") + .Setup(); + + var wageEditModel = new WageEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + WageType = wageType, + FixedWageYearlyAmount = fixedWageYearlyAmmount.ToString(), + WageAdditionalInformation = wageAddtionalInformation + }; + + await _fixture.PostWageEditModelAsync(wageEditModel); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Wage, fieldIndicatorSet); + } + + public class WageOrchestratorTestsFixture + { + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Wage | VacancyRuleSet.MinimumWage; + public VacancyUser User { get; } + public Vacancy Vacancy { get; } + public WageOrchestrator Sut {get; private set;} + + public WageOrchestratorTestsFixture() + { + MockClient = new Mock(); + MockRecruitVacancyClient = new Mock(); + + User = VacancyOrchestratorTestData.GetVacancyUser(); + Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + } + + public WageOrchestratorTestsFixture WithWageType(WageType wageType) + { + Vacancy.Wage.WageType = wageType; + return this; + } + + public WageOrchestratorTestsFixture WithFixedWageYearlyAmount(decimal fixedWageYearlyAmmount) + { + Vacancy.Wage.FixedWageYearlyAmount = fixedWageYearlyAmmount; + return this; + } + + public WageOrchestratorTestsFixture WithWageAdditionalInformation(string wageAdditionalInformation) + { + Vacancy.Wage.WageAdditionalInformation = wageAdditionalInformation; + return this; + } + + public void Setup() + { + MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); + MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); + MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); + MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); + + Sut = new WageOrchestrator(MockClient.Object, MockRecruitVacancyClient.Object, Mock.Of>(), + Mock.Of(), Mock.Of()); + } + + public async Task PostWageEditModelAsync(WageEditModel model) + { + await Sut.PostWageEditModelAsync(model, User); + } + + public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) + { + foreach (var fieldIdentifier in setFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); + } + + foreach (var fieldIdentifier in unsetFieldIdentifiers) + { + VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); + } + } + + public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) + { + Vacancy.EmployerReviewFieldIndicators + .Where(p => p.FieldIdentifier == fieldIdentifier).Single() + .Should().NotBeNull().And + .Match((x) => x.IsChangeRequested == value); + } + + public Mock MockClient { get; set; } + public Mock MockRecruitVacancyClient { get; set; } + } + } +} diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs index 71adcd625b..c2c4df1e87 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/SkillOrchestratorTests.cs @@ -5,6 +5,7 @@ using Esfa.Recruit.Employer.Web.Orchestrators.Part2; using Esfa.Recruit.Employer.Web.RouteModel; using Esfa.Recruit.Employer.Web.ViewModels.Part2.Skills; +using Esfa.Recruit.Shared.Web.Mappers; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Validation; using Esfa.Recruit.Vacancies.Client.Domain.Entities; @@ -206,9 +207,69 @@ public async Task WhenCustomDraftSkillsHaveBeenAdded_ShouldBeOrderedByTheirPrefi fixture.VerifyColumn2CheckboxesItemSelected(skillsViewModel, draftSkill3, 9); } + [Theory] + [InlineData(new string[] { }, new string[] { }, false)] + [InlineData(new string[] { }, new string[] { "Organisation skills" }, true)] + [InlineData(new string[] { "Organisation skills" }, new string[] { "Organisation skills" }, false)] + [InlineData(new string[] { "Organisation skills" }, new string[] { }, true)] + public async Task WhenSkillsAreUpdated_ShouldFlagSkillsFieldIndicator(string[] currentlySelectedSkills, string[] newSelectedSkills, bool fieldIndicatorSet) + { + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .WithSelectedSkills(currentlySelectedSkills) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsEditModel = new SkillsEditModel + { + Skills = newSelectedSkills.ToList(), + AddCustomSkillAction = null, + AddCustomSkillName = null + }; + + await fixture.PostSkillsEditModelAsync(vacancyRouteModel, skillsEditModel); + + fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.Skills, fieldIndicatorSet); + } + + [Theory] + [InlineData(new string[] { }, new string[] { })] + [InlineData(new string[] { }, new string[] { "Organisation skills" })] + [InlineData(new string[] { "Organisation skills" }, new string[] { "Organisation skills" })] + [InlineData(new string[] { "Organisation skills" }, new string[] { })] + public async Task WhenSkillsAreUpdated_ShouldCallUpdateDraftVacancyAsync(string[] currentlySelectedSkills, string[] newSelectedSkills) + { + var fixture = new SkillsOrchestratorTestsFixture(); + fixture + .WithSelectedSkills(currentlySelectedSkills) + .Setup(); + + var vacancyRouteModel = new VacancyRouteModel + { + EmployerAccountId = fixture.Vacancy.EmployerAccountId, + VacancyId = fixture.Vacancy.Id + }; + + var skillsEditModel = new SkillsEditModel + { + Skills = newSelectedSkills.ToList(), + AddCustomSkillAction = null, + AddCustomSkillName = null + }; + + await fixture.PostSkillsEditModelAsync(vacancyRouteModel, skillsEditModel); + + fixture.VerifyUpdateDraftVacancyAsyncIsCalled(); + } + public class SkillsOrchestratorTestsFixture { - private const VacancyRuleSet ValidationRules = VacancyRuleSet.Description | VacancyRuleSet.TrainingDescription | VacancyRuleSet.OutcomeDescription; + private const VacancyRuleSet ValidationRules = VacancyRuleSet.Skills; public VacancyUser User { get; } public Vacancy Vacancy { get; } public SkillsOrchestrator Sut { get; private set; } @@ -273,19 +334,6 @@ public SkillsOrchestratorTestsFixture VerifyColumn1CheckboxesItemSelected(Skills return this; } - public void VerifyEmployerReviewFieldIndicators(string[] setFieldIdentifiers, string[] unsetFieldIdentifiers) - { - foreach (var fieldIdentifier in setFieldIdentifiers) - { - VerifyEmployerReviewFieldIndicators(fieldIdentifier, true); - } - - foreach (var fieldIdentifier in unsetFieldIdentifiers) - { - VerifyEmployerReviewFieldIndicators(fieldIdentifier, false); - } - } - public void VerifyEmployerReviewFieldIndicators(string fieldIdentifier, bool value) { Vacancy.EmployerReviewFieldIndicators From 2bfa12d4239af61b19b1d4bce0bd8d95afd743e1 Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Fri, 20 Aug 2021 14:25:41 +0100 Subject: [PATCH 08/19] Added employer review indicators for employer name and tests --- .../Part1/LocationOrchestrator.cs | 35 +++++++- .../HardMocks/VacancyOrchestratorTestData.cs | 27 ++++-- .../Part1/LocationOrchestratorTests.cs | 88 +++++++++++++++++-- .../Part2/AboutEmployerOrchestratorTests.cs | 2 +- 4 files changed, 133 insertions(+), 19 deletions(-) diff --git a/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs index ca87fbed5e..a2cee6bd02 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part1/LocationOrchestrator.cs @@ -194,9 +194,38 @@ public async Task PostLocationEditModelAsync( // if cookie is found then update legal entity and name option from cookie if (employerInfoModel != null) { - vacancy.LegalEntityName = selectedOrganisation.Name; + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.LegalEntityName, + FieldIdResolver.ToFieldId(v => v.EmployerName), + vacancy, + (v) => + { + return v.LegalEntityName = selectedOrganisation.Name; + }); + + SetVacancyWithEmployerReviewFieldIndicators( + vacancy.EmployerNameOption, + FieldIdResolver.ToFieldId(v => v.EmployerName), + vacancy, + (v) => + { + return v.EmployerNameOption = employerInfoModel.EmployerIdentityOption?.ConvertToDomainOption(); + }); + + if (employerInfoModel.EmployerIdentityOption == EmployerIdentityOption.NewTradingName) + { + SetVacancyWithEmployerReviewFieldIndicators( + employerProfile.TradingName, + FieldIdResolver.ToFieldId(v => v.EmployerName), + vacancy, + (e) => + { + // the indicator will be set for the vacancy when the employer profile will change to the new trading name + return employerInfoModel.NewTradingName; + }); + } + vacancy.AccountLegalEntityPublicHashedId = selectedOrganisation.AccountLegalEntityPublicHashedId; - vacancy.EmployerNameOption = employerInfoModel.EmployerIdentityOption?.ConvertToDomainOption(); vacancy.AnonymousReason = vacancy.IsAnonymous ? employerInfoModel.AnonymousReason : null; vacancy.EmployerName = vacancy.IsAnonymous ? employerInfoModel.AnonymousName : null; } @@ -256,8 +285,6 @@ private async Task UpdateEmployerProfile(VacancyEmployerInfoModel employerInfoMo } } - - private async Task> GetAllAvailableLocationsAsync(EmployerProfile employerProfile) { var employerData = await _employerVacancyClient.GetEditVacancyInfoAsync(employerProfile.EmployerAccountId); diff --git a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs index 9ea1c8588d..0f41e6c359 100644 --- a/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs +++ b/src/Employer/UnitTests/Employer.Web/HardMocks/VacancyOrchestratorTestData.cs @@ -8,14 +8,15 @@ namespace Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks { internal class VacancyOrchestratorTestData { - private const string AccountLegalEntityPublicHashedId = "ABC123"; + public const string AccountLegalEntityPublicHashedId123 = "ABC123"; + public const string AccountLegalEntityPublicHashedId456 = "ABC456"; internal static Vacancy GetPart1CompleteVacancy() { return new Vacancy { EmployerAccountId = "EMPLOYER ACCOUNT ID", - AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId, + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId123, Id = Guid.Parse("84af954e-5baf-4942-897d-d00180a0839e"), Title = "has a value", NumberOfPositions = 1, @@ -23,7 +24,7 @@ internal static Vacancy GetPart1CompleteVacancy() ShortDescription = "has a value", ProgrammeId = "has a value", Wage = new Wage {Duration = 1, WageType = WageType.FixedWage }, - LegalEntityName = "legal name", + LegalEntityName = "LEGAL ENTITY NAME 123", EmployerNameOption = EmployerNameOption.RegisteredName, StartDate = DateTime.Now }; @@ -39,12 +40,12 @@ internal static VacancyUser GetVacancyUser() }; } - internal static EmployerProfile GetEmployerProfile() + internal static EmployerProfile GetEmployerProfile(string accountLegalEntityPublicHashedId123) { return new EmployerProfile { EmployerAccountId = "EMPLOYER ACCOUNT ID", - AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId + AccountLegalEntityPublicHashedId = accountLegalEntityPublicHashedId123 }; } @@ -56,7 +57,21 @@ internal static EmployerEditVacancyInfo GetEmployerEditVacancyInfo() { new LegalEntity { - AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId, + Name = "LEGAL ENTITY NAME 123", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId123, + Address = new Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo.Address + { + AddressLine1 = "this is a value", + AddressLine2 = "this is a value", + AddressLine3 = "this is a value", + AddressLine4 = "this is a value", + Postcode = "this is a value" + } + }, + new LegalEntity + { + Name = "LEGAL ENTITY NAME 456", + AccountLegalEntityPublicHashedId = AccountLegalEntityPublicHashedId456, Address = new Vacancies.Client.Infrastructure.QueryStore.Projections.EditVacancyInfo.Address { AddressLine1 = "this is a value", diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs index 831af15e6f..97ee8b8d5d 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/LocationOrchestratorTests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Threading.Tasks; using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; using Esfa.Recruit.Employer.Web.Models; @@ -7,6 +8,7 @@ using Esfa.Recruit.Employer.Web.ViewModels.Part1.Location; using Esfa.Recruit.Employer.Web.ViewModels.Part1.Wage; using Esfa.Recruit.Shared.Web.Mappers; +using Esfa.Recruit.Shared.Web.Models; using Esfa.Recruit.Shared.Web.Services; using Esfa.Recruit.Vacancies.Client.Application.Providers; using Esfa.Recruit.Vacancies.Client.Application.Validation; @@ -38,7 +40,7 @@ public LocationOrchestratorTests() [InlineData("this is a value", "this is a value", "this is a value", "this is a new value", "this is a value", true)] [InlineData("this is a value", "this is a value", "this is a value", "this is a value", "this is a new value", true)] [InlineData("this is a new value", "this is a new value", "this is a new value", "this is a new value", "this is a new value", true)] - public async Task WhenUpdated_ShouldFlagFieldIndicators(string addressLine1, string addressLine2, string addressLine3, string addressLine4, string postcode, bool fieldIndicatorSet) + public async Task WhenAddressUpdated_ShouldFlagFieldIndicators(string addressLine1, string addressLine2, string addressLine3, string addressLine4, string postcode, bool fieldIndicatorSet) { _fixture .WithAddressLine1("this is a value") @@ -65,13 +67,69 @@ public async Task WhenUpdated_ShouldFlagFieldIndicators(string addressLine1, str _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerAddress, fieldIndicatorSet); } + [Fact] + public async Task WhenEmployerLegalEntityUpdated_ShouldFlagEmployerNameFieldIndicator() + { + _fixture + .WithEmployerNameOption(EmployerNameOption.RegisteredName) + .Setup(); + + var locationEditModel = new LocationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + SelectedLocation = LocationViewModel.UseOtherLocationConst + }; + + await _fixture.PostLocationEditModelAsync(locationEditModel, new VacancyEmployerInfoModel + { + EmployerIdentityOption = EmployerIdentityOption.RegisteredName, + AccountLegalEntityPublicHashedId = VacancyOrchestratorTestData.AccountLegalEntityPublicHashedId456 + }); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerName, true); + } + + [Theory] + [InlineData(EmployerNameOption.RegisteredName, EmployerIdentityOption.ExistingTradingName, null, true)] + [InlineData(EmployerNameOption.RegisteredName, EmployerIdentityOption.NewTradingName, "this is a new value", true)] + [InlineData(EmployerNameOption.TradingName, EmployerIdentityOption.NewTradingName, "this is a new value", true)] + [InlineData(EmployerNameOption.TradingName, EmployerIdentityOption.ExistingTradingName, null, false)] + [InlineData(EmployerNameOption.RegisteredName, EmployerIdentityOption.RegisteredName, null, false)] + public async Task WhenEmployerNameOptionUpdated_ShouldFlagEmployerNameFieldIndicator(EmployerNameOption employerNameOption, EmployerIdentityOption employerIdentityOption, string newTradingName, bool shouldFlagIndicator) + { + _fixture + .WithEmployerNameOption(employerNameOption) + .WithTradingName(employerNameOption == EmployerNameOption.TradingName + ? "this is a value" + : null) + .Setup(); + + var locationEditModel = new LocationEditModel + { + EmployerAccountId = _fixture.Vacancy.EmployerAccountId, + VacancyId = _fixture.Vacancy.Id, + SelectedLocation = LocationViewModel.UseOtherLocationConst + }; + + await _fixture.PostLocationEditModelAsync(locationEditModel, new VacancyEmployerInfoModel + { + EmployerIdentityOption = employerIdentityOption, + NewTradingName = newTradingName, + AccountLegalEntityPublicHashedId = _fixture.Vacancy.AccountLegalEntityPublicHashedId + }); + + _fixture.VerifyEmployerReviewFieldIndicators(FieldIdentifiers.EmployerName, shouldFlagIndicator); + } + public class LocationOrchestratorTestsFixture { private const VacancyRuleSet ValidationRules = VacancyRuleSet.EmployerAddress; public VacancyUser User { get; } public Vacancy Vacancy { get; } public EmployerEditVacancyInfo EmployerEditVacancyInfo { get; } - public EmployerProfile EmployerProfile { get; } + public EmployerProfile VacancyEmployerProfile { get; } + public EmployerProfile AlternateEmployerProfile { get; } public LocationOrchestrator Sut {get; private set;} public LocationOrchestratorTestsFixture() @@ -81,8 +139,9 @@ public LocationOrchestratorTestsFixture() User = VacancyOrchestratorTestData.GetVacancyUser(); Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + VacancyEmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(Vacancy.AccountLegalEntityPublicHashedId); + AlternateEmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(VacancyOrchestratorTestData.AccountLegalEntityPublicHashedId456); EmployerEditVacancyInfo = VacancyOrchestratorTestData.GetEmployerEditVacancyInfo(); - EmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(); } public LocationOrchestratorTestsFixture WithAddressLine1(string addressLine1) @@ -130,12 +189,25 @@ public LocationOrchestratorTestsFixture WithPostcode(string postcode) return this; } + public LocationOrchestratorTestsFixture WithEmployerNameOption(EmployerNameOption employerNameOption) + { + Vacancy.EmployerNameOption = employerNameOption; + return this; + } + + public LocationOrchestratorTestsFixture WithTradingName(string tradingName) + { + VacancyEmployerProfile.TradingName = tradingName; + return this; + } + public void Setup() { MockClient.Setup(x => x.GetEditVacancyInfoAsync(Vacancy.EmployerAccountId)).ReturnsAsync(EmployerEditVacancyInfo); MockRecruitVacancyClient.Setup(x => x.GetVacancyAsync(Vacancy.Id)).ReturnsAsync(Vacancy); - MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, Vacancy.AccountLegalEntityPublicHashedId)).ReturnsAsync(EmployerProfile); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, Vacancy.AccountLegalEntityPublicHashedId)).ReturnsAsync(VacancyEmployerProfile); + MockRecruitVacancyClient.Setup(x => x.GetEmployerProfileAsync(Vacancy.EmployerAccountId, AlternateEmployerProfile.AccountLegalEntityPublicHashedId)).ReturnsAsync(AlternateEmployerProfile); MockRecruitVacancyClient.Setup(x => x.Validate(Vacancy, ValidationRules)).Returns(new EntityValidationResult()); MockRecruitVacancyClient.Setup(x => x.UpdateDraftVacancyAsync(It.IsAny(), User)); MockRecruitVacancyClient.Setup(x => x.UpdateEmployerProfileAsync(It.IsAny(), User)); @@ -144,10 +216,10 @@ public void Setup() Mock.Of()); } - public async Task PostLocationEditModelAsync(LocationEditModel model) + public async Task PostLocationEditModelAsync(LocationEditModel model, VacancyEmployerInfoModel vacancyEmployerInfoModel = null) { - await Sut.PostLocationEditModelAsync(model, - new VacancyEmployerInfoModel + await Sut.PostLocationEditModelAsync(model, + vacancyEmployerInfoModel ?? new VacancyEmployerInfoModel { VacancyId = Vacancy.Id }, diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs index 7a4e4db970..80a79ea1a7 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part2/AboutEmployerOrchestratorTests.cs @@ -62,8 +62,8 @@ public AboutEmployerOrchestratorTestsFixture() MockRecruitVacancyClient = new Mock(); User = VacancyOrchestratorTestData.GetVacancyUser(); - EmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(); Vacancy = VacancyOrchestratorTestData.GetPart1CompleteVacancy(); + EmployerProfile = VacancyOrchestratorTestData.GetEmployerProfile(Vacancy.AccountLegalEntityPublicHashedId); } public AboutEmployerOrchestratorTestsFixture WithEmployerDescription(string employerDescription) From e8878f0715987741d65c0ddce3a2aba6d7b744e3 Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Fri, 20 Aug 2021 15:47:41 +0100 Subject: [PATCH 09/19] Remove employer review and rejection reason when cloning --- .../Application/CommandHandlers/CloneVacancyCommandHandler.cs | 2 ++ .../CommandHandlers/CloneVacancyCommandHandlerTests.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs index 667843d291..fc6836cf06 100644 --- a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs +++ b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs @@ -90,6 +90,8 @@ private Vacancy CreateClone(CloneVacancyCommand message, Vacancy vacancy) clone.TransferInfo = null; clone.ReviewByUser = null; clone.ReviewDate = null; + clone.EmployerReviewFieldIndicators = null; + clone.EmployerRejectedReason = null; return clone; } diff --git a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs index f7745aced0..26472f85ac 100644 --- a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs +++ b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs @@ -150,6 +150,8 @@ private static void AssertKnownProperties(Vacancy original, Vacancy clone) {nameof(Vacancy.EmployerLocation), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.EmployerName), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.EmployerNameOption), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, + {nameof(Vacancy.EmployerReviewFieldIndicators), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, + {nameof(Vacancy.EmployerRejectedReason), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.LegalEntityName), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.EmployerWebsiteUrl), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, {nameof(Vacancy.GeoCodeMethod), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Cloned)}, From 19300b9152efa539a23aa1f4b7e6332a57634802 Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Fri, 20 Aug 2021 16:07:02 +0100 Subject: [PATCH 10/19] Fix for culture specific dates --- .../Part1/DatesOrchestratorTests.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs index 9aeaaaf80e..39e9f7398a 100644 --- a/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs +++ b/src/Employer/UnitTests/Employer.Web/Orchestrators/Part1/DatesOrchestratorTests.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Esfa.Recruit.Employer.UnitTests.Employer.Web.HardMocks; @@ -41,16 +42,19 @@ public async Task WhenUpdated_ShouldFlagFieldIndicators(string closingDate, stri .WithDisabilityConfident(false) .Setup(); + var closingDateTime = DateTime.ParseExact(closingDate, "dd/MM/yyyy", CultureInfo.InvariantCulture); + var startDateTime = DateTime.ParseExact(startDate, "dd/MM/yyyy", CultureInfo.InvariantCulture); + var datesEditModel = new DatesEditModel { EmployerAccountId = _fixture.Vacancy.EmployerAccountId, VacancyId = _fixture.Vacancy.Id, - ClosingDay = DateTime.Parse(closingDate).Day.ToString(), - ClosingMonth = DateTime.Parse(closingDate).Month.ToString(), - ClosingYear = DateTime.Parse(closingDate).Year.ToString(), - StartDay = DateTime.Parse(startDate).Day.ToString(), - StartMonth = DateTime.Parse(startDate).Month.ToString(), - StartYear = DateTime.Parse(startDate).Year.ToString(), + ClosingDay = closingDateTime.Day.ToString(), + ClosingMonth = closingDateTime.Month.ToString(), + ClosingYear = closingDateTime.Year.ToString(), + StartDay = startDateTime.Day.ToString(), + StartMonth = startDateTime.Month.ToString(), + StartYear = startDateTime.Year.ToString(), IsDisabilityConfident = isDisablityConfident }; From 3203c7472b410207811b09a6ae2f87c1597a2794 Mon Sep 17 00:00:00 2001 From: James King Date: Tue, 24 Aug 2021 10:18:34 +0100 Subject: [PATCH 11/19] CSS to display latest GDS notification banner and additional tag colour options --- .../Provider.Web/wwwroot/css/application.css | 138 +++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/src/Provider/Provider.Web/wwwroot/css/application.css b/src/Provider/Provider.Web/wwwroot/css/application.css index 99595cf653..7d55311c0e 100644 --- a/src/Provider/Provider.Web/wwwroot/css/application.css +++ b/src/Provider/Provider.Web/wwwroot/css/application.css @@ -1227,4 +1227,140 @@ a[rel="external"]:hover:after { display: none; } -/*** End of cookie banner ***/ \ No newline at end of file +/*** End of cookie banner ***/ + + +/* GDS notification banner */ + +.govuk-notification-banner { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + line-height: 1.25; + margin-bottom: 30px; + border: 5px solid #1d70b8; + background-color: #1d70b8; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner { + margin-bottom: 50px; + } +} + +.govuk-notification-banner__header { + padding: 2px 15px 5px; + border-bottom: 1px solid transparent; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__header { + padding: 2px 20px 5px; + } +} + +.govuk-notification-banner__title { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + line-height: 1.25; + margin: 0; + padding: 0; + color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__title { + font-size: 19px; + line-height: 1.35; + } +} + +.govuk-notification-banner__content { + color: #0b0c0c; + padding: 15px; + background-color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__content { + padding: 20px; + } +} + +.govuk-notification-banner__content > * { + max-width: 605px; +} + +.govuk-notification-banner__content>:last-child { + margin-bottom: 0; +} + +.govuk-notification-banner__heading { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + line-height: 1.1; + margin: 0 0 15px 0; + padding: 0; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__heading { + font-size: 24px; + line-height: 1.25; + } +} + +.govuk-notification-banner__link { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + color: #1d70b8; +} + +.govuk-notification-banner__link:link { + color: #1d70b8; +} + +.govuk-notification-banner__link:hover { + color: #003078; +} + +.govuk-notification-banner__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #fd0; + -webkit-box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + text-decoration: none; +} + +/* Additional GDS tag colours */ + +.govuk-tag--purple { + color: #3d2375; + background: #dbd5e9; +} + +.govuk-tag--red { + color: #942514; + background: #f6d7d2; +} + +.govuk-tag--blue { + color: #144e81; + background: #d2e2f1; +} + +.govuk-tag--green { + color: #005a30; + background: #cce2d8; +} \ No newline at end of file From 6f81051c86c723a7b035a7f5c27bd0483a605d08 Mon Sep 17 00:00:00 2001 From: James King Date: Tue, 24 Aug 2021 10:29:32 +0100 Subject: [PATCH 12/19] Additional styles options in the Employer side as well --- .../Employer.Web/wwwroot/css/application.css | 140 ++++++++++++++++++ .../Provider.Web/wwwroot/css/application.css | 9 +- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/src/Employer/Employer.Web/wwwroot/css/application.css b/src/Employer/Employer.Web/wwwroot/css/application.css index 87ad83fa0e..a205e1b138 100644 --- a/src/Employer/Employer.Web/wwwroot/css/application.css +++ b/src/Employer/Employer.Web/wwwroot/css/application.css @@ -1417,4 +1417,144 @@ a[rel="external"]:hover:after { /*** govuk confirmation panel ***/ .govuk-panel--confirmation { background: #00703c; +} + +/* govuk notification banner */ + +.govuk-notification-banner { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + line-height: 1.25; + margin-bottom: 30px; + border: 5px solid #1d70b8; + background-color: #1d70b8; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner { + margin-bottom: 50px; + } +} + +.govuk-notification-banner__header { + padding: 2px 15px 5px; + border-bottom: 1px solid transparent; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__header { + padding: 2px 20px 5px; + } +} + +.govuk-notification-banner__title { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + line-height: 1.25; + margin: 0; + padding: 0; + color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__title { + font-size: 19px; + line-height: 1.35; + } +} + +.govuk-notification-banner__content { + color: #0b0c0c; + padding: 15px; + background-color: #fff; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__content { + padding: 20px; + } +} + +.govuk-notification-banner__content > * { + max-width: 605px; +} + +.govuk-notification-banner__content>:last-child { + margin-bottom: 0; +} + +.govuk-notification-banner__heading { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + line-height: 1.1; + margin: 0 0 15px 0; + padding: 0; +} + +@media (min-width: 48.0625em) { + .govuk-notification-banner__heading { + font-size: 24px; + line-height: 1.25; + } +} + +.govuk-notification-banner__link { + font-family: "nta", Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + color: #1d70b8; +} + +.govuk-notification-banner__link:link { + color: #1d70b8; +} + +.govuk-notification-banner__link:hover { + color: #003078; +} + +.govuk-notification-banner__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #fd0; + -webkit-box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + box-shadow: 0 -2px #fd0, 0 4px #0b0c0c; + text-decoration: none; +} + +/* Additional govuk tag colours */ + +.govuk-tag--purple { + color: #3d2375; + background: #dbd5e9; +} + +.govuk-tag--red { + color: #942514; + background: #f6d7d2; +} + +.govuk-tag--blue { + color: #144e81; + background: #d2e2f1; +} + +.govuk-tag--green { + color: #005a30; + background: #cce2d8; +} + +.govuk-tag--orange { + color: #6e3619; + background: #fcd6c3; } \ No newline at end of file diff --git a/src/Provider/Provider.Web/wwwroot/css/application.css b/src/Provider/Provider.Web/wwwroot/css/application.css index 7d55311c0e..ab6fb494c9 100644 --- a/src/Provider/Provider.Web/wwwroot/css/application.css +++ b/src/Provider/Provider.Web/wwwroot/css/application.css @@ -1230,7 +1230,7 @@ a[rel="external"]:hover:after { /*** End of cookie banner ***/ -/* GDS notification banner */ +/* govuk notification banner */ .govuk-notification-banner { font-family: "nta", Arial, sans-serif; @@ -1343,7 +1343,7 @@ a[rel="external"]:hover:after { text-decoration: none; } -/* Additional GDS tag colours */ +/* Additional govuk tag colours */ .govuk-tag--purple { color: #3d2375; @@ -1363,4 +1363,9 @@ a[rel="external"]:hover:after { .govuk-tag--green { color: #005a30; background: #cce2d8; +} + +.govuk-tag--orange { + color: #6e3619; + background: #fcd6c3; } \ No newline at end of file From 8bbad03ae3d3915ee3ae23288dbd7f2e7672595e Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Tue, 24 Aug 2021 11:47:09 +0100 Subject: [PATCH 13/19] Correct spelling --- .../Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml b/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml index 43f022a0ad..fcee3a2063 100644 --- a/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml +++ b/src/Employer/Employer.Web/Views/VacancyPreview/VacancyPreview.cshtml @@ -521,7 +521,7 @@
- +
From 55fee3a52b9322771818d7767227de788be6c50b Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Tue, 24 Aug 2021 16:06:17 +0100 Subject: [PATCH 14/19] Added review count --- src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs | 2 +- .../Application/CommandHandlers/CloneVacancyCommandHandler.cs | 1 + .../Application/CommandHandlers/ReviewVacancyCommandHandler.cs | 1 + src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs | 1 + .../CommandHandlers/CloneVacancyCommandHandlerTests.cs | 1 + .../CommandHandlers/ReviewVacancyCommandHandlerTests.cs | 2 ++ 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs b/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs index 701905d09e..eddeb54bc3 100644 --- a/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs +++ b/src/Provider/Provider.Web/Orchestrators/ReviewedOrchestrator.cs @@ -35,7 +35,7 @@ public async Task GetVacancyReviewedOrches Title = vacancy.Title, VacancyReference = vacancy.VacancyReference?.ToString(), EmployerName = employer.Name, - IsResubmit = vacancy.ReviewDate.HasValue, + IsResubmit = vacancy.ReviewCount > 1, IsVacancyRejectedByEmployerNotificationSelected = preferences.NotificationTypes.HasFlag(NotificationTypes.VacancyRejectedByEmployer) }; diff --git a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs index 667843d291..c73cbe7602 100644 --- a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs +++ b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandler.cs @@ -90,6 +90,7 @@ private Vacancy CreateClone(CloneVacancyCommand message, Vacancy vacancy) clone.TransferInfo = null; clone.ReviewByUser = null; clone.ReviewDate = null; + clone.ReviewCount = 0; return clone; } diff --git a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs index 66598d1f08..61eba47e83 100644 --- a/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs +++ b/src/Shared/Recruit.Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandler.cs @@ -66,6 +66,7 @@ public async Task Handle(ReviewVacancyCommand message, CancellationToken cancell vacancy.Status = VacancyStatus.Review; vacancy.ReviewDate = now; + vacancy.ReviewCount += 1; vacancy.ReviewByUser = message.User; vacancy.LastUpdatedDate = now; vacancy.LastUpdatedByUser = message.User; diff --git a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs index ee7f9495ac..2473432cec 100644 --- a/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs +++ b/src/Shared/Recruit.Vacancies.Client/Domain/Entities/Vacancy.cs @@ -21,6 +21,7 @@ public class Vacancy public VacancyUser SubmittedByUser { get; set; } public DateTime? ReviewDate { get; set; } public VacancyUser ReviewByUser { get; set; } + public int ReviewCount { get; set; } public DateTime? ApprovedDate { get; set; } public DateTime? LiveDate { get; set; } diff --git a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs index f7745aced0..a697e5d380 100644 --- a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs +++ b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/CloneVacancyCommandHandlerTests.cs @@ -130,6 +130,7 @@ private static void AssertKnownProperties(Vacancy original, Vacancy clone) {nameof(Vacancy.SubmittedDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.SubmittedByUser), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.ReviewDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, + {nameof(Vacancy.ReviewCount), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.Ignore)}, {nameof(Vacancy.ReviewByUser), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.ApprovedDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, {nameof(Vacancy.LiveDate), (o, c, s) => AssertProperty(o, c, s, CloneAssertType.IsNull)}, diff --git a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs index 3124756e9e..4f2c07ec8a 100644 --- a/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs +++ b/src/Shared/UnitTests/Vacancies.Client/Application/CommandHandlers/ReviewVacancyCommandHandlerTests.cs @@ -45,6 +45,7 @@ public async Task GivenEmployerDescription_ThenShouldUpdateVacancyWithThatDescri vacancy.Status.Should().Be(VacancyStatus.Review); vacancy.ReviewDate.Should().Be(now); vacancy.ReviewByUser.Should().Be(user); + vacancy.ReviewCount.Should().Be(1); vacancy.LastUpdatedDate.Should().Be(now); vacancy.LastUpdatedByUser.Should().Be(user); vacancy.EmployerDescription.Should().Be(expectedDescription); @@ -77,6 +78,7 @@ public async Task ShouldNotChangeEmployerDescriptionIfNotSpecifiedInCommand() vacancy.Status.Should().Be(VacancyStatus.Review); vacancy.ReviewDate.Should().Be(now); vacancy.ReviewByUser.Should().Be(user); + vacancy.ReviewCount.Should().Be(1); vacancy.LastUpdatedDate.Should().Be(now); vacancy.LastUpdatedByUser.Should().Be(user); vacancy.EmployerDescription.Should().Be(expectedDescription); From 91f0e4578a81ddc7d1890fb4903e4693b8df0ab4 Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Wed, 25 Aug 2021 11:36:57 +0100 Subject: [PATCH 15/19] Update error message for preview page --- .../Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs b/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs index 13efefbed4..af127ad960 100644 --- a/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs +++ b/src/Employer/Employer.Web/ViewModels/VacancyPreview/SubmitReviewModel.cs @@ -8,7 +8,7 @@ public class SubmitReviewModel : VacancyRouteModel, IValidatableObject { private const int RejectedReasonMaxCharacters = 200; - [Required(ErrorMessage = "You need to submit or reject the advert")] + [Required(ErrorMessage = "Confirm if you want to submit or reject this advert ")] public bool? SubmitToEsfa { get; set; } public string RejectedReason { get; set; } From 4f57a80c469a138554b4f4e445a41bfe9dc9b841 Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Wed, 25 Aug 2021 15:39:00 +0100 Subject: [PATCH 16/19] Changed link --- src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml | 2 +- src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml index aac800e0a5..555b8095d3 100644 --- a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml @@ -49,7 +49,7 @@

- Return to recruitment + Return to recruitment

diff --git a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml index e87dba1c5a..cdc76bf8e7 100644 --- a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml @@ -45,7 +45,7 @@

- Return to recruitment + Return to recruitment

From aef9bae3d638565885123a8da57ed87c4a9c5c93 Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Thu, 26 Aug 2021 13:37:58 +0100 Subject: [PATCH 17/19] Update Confirmation.cshtml --- src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml index 555b8095d3..3b9d6009f6 100644 --- a/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Reviewed/Confirmation.cshtml @@ -28,7 +28,7 @@

- If @Model.EmployerName approve the vacancy, the ESFA will do a final review and then post it on 'Find an apprenticeship'. + If @Model.EmployerName approves the vacancy, the ESFA will do a final review and then post it on 'Find an apprenticeship'.

@if (Model.IsVacancyRejectedByEmployerNotificationSelected) From 0a5cb589901ff9c434286e06ae99c4373c7da99a Mon Sep 17 00:00:00 2001 From: Paul Howes Date: Thu, 26 Aug 2021 13:47:45 +0100 Subject: [PATCH 18/19] Update Confirmation.cshtml --- src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml index cdc76bf8e7..bd9b152f3e 100644 --- a/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml +++ b/src/Provider/Provider.Web/Views/Submitted/Confirmation.cshtml @@ -26,7 +26,7 @@ @if (Model.IsVacancyRejectedByESFANotificationSelected) {

- The ESFA will check the vacancy and let you know by email, within one working day, if you need to make and edits. + The ESFA will check the vacancy and let you know by email, within one working day, if you need to make any edits.

} else From 901e924bc1f2ca987bc52af1d09e94104b6db43d Mon Sep 17 00:00:00 2001 From: Chris Woodcock Date: Wed, 1 Sep 2021 16:38:49 +0100 Subject: [PATCH 19/19] Fix bug with entering initial skills --- .../Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs b/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs index eec2b98508..c7e44a01ce 100644 --- a/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs +++ b/src/Employer/Employer.Web/Orchestrators/Part2/SkillsOrchestrator.cs @@ -80,7 +80,8 @@ public async Task PostSkillsEditModelAsync(VacancyRouteMod } var currentSkills = new List(); - currentSkills.AddRange(vacancy.Skills); + if (vacancy.Skills != null) + currentSkills.AddRange(vacancy.Skills); SetVacancyWithEmployerReviewFieldIndicators( currentSkills,