From 80eb0f0a9f00b7f0b1150707fa3aa8998d9a6eb8 Mon Sep 17 00:00:00 2001 From: Guillaume Heurtier <guillaume.heurtier@maarch.org> Date: Wed, 2 Sep 2020 19:24:06 +0200 Subject: [PATCH] FEAT #14004 TIME 2:30 fix ar reception after cr --- migration/20.10/2010.sql | 6 ++ .../controllers/RegisteredMailController.php | 10 ++- .../acknowledgement-reception.component.html | 51 ++++++++++--- .../acknowledgement-reception.component.ts | 71 +++++++++++++------ src/lang/lang-en.json | 4 +- src/lang/lang-fr.json | 4 +- 6 files changed, 112 insertions(+), 34 deletions(-) diff --git a/migration/20.10/2010.sql b/migration/20.10/2010.sql index dfaca3d864e..39ef9d2c959 100755 --- a/migration/20.10/2010.sql +++ b/migration/20.10/2010.sql @@ -251,10 +251,16 @@ CREATE TABLE IF NOT EXISTS registered_mail_resources ( DELETE FROM parameters WHERE id = 'last_deposit_id'; INSERT INTO parameters (id, param_value_int) VALUES ('last_deposit_id', 0); +DELETE FROM parameters WHERE id = 'registeredMailNotDistributedStatus'; +INSERT INTO parameters (id, param_value_string) VALUES ('registeredMailNotDistributedStatus', 'PND'); +DELETE FROM parameters WHERE id = 'registeredMailDistributedStatus'; +INSERT INTO parameters (id, param_value_string) VALUES ('registeredMailDistributedStatus', 'DSTRIBUTED'); DELETE FROM parameters WHERE id = 'traffic_record_summary_sheet'; INSERT INTO parameters (id, description, param_value_string) VALUES ('traffic_record_summary_sheet', 'Module circulation pour la fiche de liaison', ''); +-- TODO statuses ar reception + /* RE CREATE VIEWS */ CREATE OR REPLACE VIEW res_view_letterbox AS SELECT r.res_id, diff --git a/src/app/registeredMail/controllers/RegisteredMailController.php b/src/app/registeredMail/controllers/RegisteredMailController.php index 3446eb4a240..4c3b3ba9386 100644 --- a/src/app/registeredMail/controllers/RegisteredMailController.php +++ b/src/app/registeredMail/controllers/RegisteredMailController.php @@ -14,6 +14,7 @@ namespace RegisteredMail\controllers; use Com\Tecnick\Barcode\Barcode; +use Group\controllers\PrivilegeController; use Parameter\models\ParameterModel; use Contact\controllers\ContactController; use Contact\models\ContactModel; @@ -120,6 +121,10 @@ class RegisteredMailController public function receiveAcknowledgement(Request $request, Response $response) { + if (!PrivilegeController::hasPrivilege(['privilegeId' => 'registered_mail_receive_ar', 'userId' => $GLOBALS['id']])) { + return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']); + } + $body = $request->getParsedBody(); if (!Validator::stringType()->notEmpty()->validate($body['type']) && !in_array($body['type'], ['distributed', 'notDistributed'])) { @@ -134,7 +139,7 @@ class RegisteredMailController $number = str_replace(' ', '', $number); $registeredMail = RegisteredMailModel::get([ - 'select' => ['id', 'res_id'], + 'select' => ['id', 'res_id', 'received_date'], 'where' => ['number = ?'], 'data' => [$number] ]); @@ -142,6 +147,9 @@ class RegisteredMailController return $response->withStatus(400)->withJson(['errors' => 'Registered mail number not found']); } $registeredMail = $registeredMail[0]; + if (!empty($registeredMail['received_date'])) { + return $response->withStatus(400)->withJson(['errors' => 'Registered mail was already received', 'lang' => 'arAlreadyReceived']); + } if ($body['type'] == 'distributed') { $set = ['received_date' => 'CURRENT_TIMESTAMP']; diff --git a/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.html b/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.html index be00b52049c..5b47fa3ecfa 100644 --- a/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.html +++ b/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.html @@ -21,17 +21,12 @@ <form style="display: contents;" [formGroup]="adminFormGroup"> <div> <mat-form-field> - <mat-select [(ngModel)]="type" required placeholder="{{'lang.returnType' | translate}}" formControlName="type"> + <mat-select [(ngModel)]="type" (ngModelChange)="changeType($event)" placeholder="{{'lang.returnType' | translate}}" formControlName="type"> <mat-option [value]="'distributed'">{{'lang.registeredMailDistributed' | translate}}</mat-option> <mat-option [value]="'notDistributed'">{{'lang.registeredMailNotDistributed' | translate}}</mat-option> </mat-select> </mat-form-field> - <mat-form-field> - <mat-label>{{'lang.registeredMailNumber' | translate}}</mat-label> - <input type="text" matInput required (change)="receiveAcknowledgement()" [(ngModel)]="number" formControlName="number"> - </mat-form-field> - <mat-form-field *ngIf="type === 'notDistributed'" (click)="picker.open()" appearance="outline" style="cursor:pointer;margin-top: 10px;"> <mat-label>{{'lang.registeredMailReceivedDate' | translate}}</mat-label> <input matInput [(ngModel)]="receivedDate" [matDatepicker]="picker" @@ -47,11 +42,9 @@ </mat-form-field> <mat-form-field *ngIf="type === 'notDistributed'" > + <!-- sort --> <mat-select [(ngModel)]="reason" formControlName="returnReason" placeholder="{{'lang.returnReason' | translate}}" required> - <mat-option value="{{'lang.returnReasonCannotAccess' | translate}}">{{'lang.returnReasonCannotAccess' | translate}}</mat-option> - <mat-option value="{{'lang.returnReasonNotClaimed' | translate}}">{{'lang.returnReasonNotClaimed' | translate}}</mat-option> - <mat-option value="{{'lang.returnReasonRejected' | translate}}">{{'lang.returnReasonRejected' | translate}}</mat-option> - <mat-option value="{{'lang.returnReasonUnknown' | translate}}">{{'lang.returnReasonUnknown' | translate}}</mat-option> + <mat-option *ngFor="let reason of returnReasons" [value]="reason">{{reason}}</mat-option> <mat-option value="{{'lang.others' | translate}}">{{'lang.others' | translate}}</mat-option> </mat-select> </mat-form-field> @@ -59,8 +52,46 @@ <mat-label>{{'lang.precise' | translate}}</mat-label> <input matInput name="returnReasonOther" formControlName="returnReasonOther" [(ngModel)]="reasonOther"> </mat-form-field> + + <mat-form-field> + <mat-label>{{'lang.registeredMailNumber' | translate}}</mat-label> + <input #numberInput type="text" matInput required (change)="receiveAcknowledgement()" [(ngModel)]="number" formControlName="number"> + </mat-form-field> + + <div style="text-align:center;"> + <button mat-raised-button color="primary" type="button" (click)="receiveAcknowledgement()" + [disabled]="!adminFormGroup.valid">{{'lang.validate' | translate}}</button> + </div> </div> </form> + + <mat-table #table [dataSource]="dataSource"> + <ng-container matColumnDef="type"> + <mat-header-cell *matHeaderCellDef>{{'lang.returnType' | translate}}</mat-header-cell> + <mat-cell *matCellDef="let element"> + {{(element.type === 'distributed' ? ('lang.registeredMailDistributed' | translate) : ('lang.registeredMailNotDistributed' | translate))}} + </mat-cell> + </ng-container> + <ng-container matColumnDef="number"> + <mat-header-cell *matHeaderCellDef>{{'lang.registeredMailNumber' | translate}}</mat-header-cell> + <mat-cell *matCellDef="let element"> {{element.number}} </mat-cell> + </ng-container> + <ng-container matColumnDef="receivedDate"> + <mat-header-cell *matHeaderCellDef>{{'lang.registeredMailReceivedDate' | translate}}</mat-header-cell> + <mat-cell *matCellDef="let element"> {{element.receivedDate}} </mat-cell> + </ng-container> + <ng-container matColumnDef="returnReason"> + <mat-header-cell *matHeaderCellDef>{{'lang.returnReason' | translate}}</mat-header-cell> + <mat-cell *matCellDef="let element">{{element.returnReason}} </mat-cell> + </ng-container> + <ng-container matColumnDef="returnReasonOther"> + <mat-header-cell *matHeaderCellDef>{{'lang.others' | translate}}</mat-header-cell> + <mat-cell *matCellDef="let element">{{element.returnReasonOther}} </mat-cell> + </ng-container> + + <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> + <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> + </mat-table> </mat-card> </div> </div> diff --git a/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.ts b/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.ts index 7db3e6e2b12..ceb2533de50 100644 --- a/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.ts +++ b/src/frontend/app/registeredMails/acknowledgement-reception/acknowledgement-reception.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import { HttpClient } from '@angular/common/http'; import {FormBuilder, FormGroup, ValidatorFn, Validators} from '@angular/forms'; import {catchError, tap} from 'rxjs/operators'; @@ -8,7 +8,7 @@ import { HeaderService } from '../../../service/header.service'; import { FunctionsService } from '../../../service/functions.service'; import {AppService} from '../../../service/app.service'; import {TranslateService} from '@ngx-translate/core'; -import {ActivatedRoute} from '@angular/router'; +import {MatTableDataSource} from '@angular/material/table'; @Component({ selector: 'app-acknowledgement-reception', @@ -19,16 +19,29 @@ export class AcknowledgementReceptionComponent implements OnInit { loading: boolean = false; + today: Date = new Date(); + type: any; number: any; - receivedDate: any; + receivedDate: any = this.today; reason: any; - reasonOther: any; - today: Date = new Date(); + reasonOther: any; adminFormGroup: FormGroup; + dataSource: MatTableDataSource<any>; + displayedColumns = ['type', 'number', 'receivedDate', 'returnReason', 'returnReasonOther']; + + returnReasons = [ + this.translate.instant('lang.returnReasonCannotAccess'), + this.translate.instant('lang.returnReasonNotClaimed'), + this.translate.instant('lang.returnReasonRejected'), + this.translate.instant('lang.returnReasonUnknown') + ]; + + @ViewChild('numberInput', { static: false }) numberInput: ElementRef; + constructor( public http: HttpClient, private notify: NotificationService, @@ -36,32 +49,31 @@ export class AcknowledgementReceptionComponent implements OnInit { public functions: FunctionsService, public appService: AppService, public translate: TranslateService, - private _formBuilder: FormBuilder, - private route: ActivatedRoute + private _formBuilder: FormBuilder ) { } ngOnInit() { - this.route.params.subscribe(async () => { - this.headerService.setHeader(this.translate.instant('lang.arReception')); - const validatorNumber: ValidatorFn[] = [Validators.pattern(/(2C|2D|RW) ([0-9]{3} [0-9]{3} [0-9]{4}) ([0-9])/), Validators.required]; - this.adminFormGroup = this._formBuilder.group({ - type: ['', Validators.required], - number: ['', validatorNumber], - receivedDate: ['', Validators.required], - returnReason: ['', Validators.required], - returnReasonOther: ['', Validators.required] - }); - this.loading = false; + this.headerService.setHeader(this.translate.instant('lang.arReception')); + const validatorNumber: ValidatorFn[] = [Validators.pattern(/(2C|2D|RW) ([0-9]{3} [0-9]{3} [0-9]{4}) ([0-9])/), Validators.required]; + this.adminFormGroup = this._formBuilder.group({ + type: ['', Validators.required], + number: ['', validatorNumber], + receivedDate: ['', Validators.required], + returnReason: ['', Validators.required], + returnReasonOther: [''] }); + this.loading = false; + this.dataSource = new MatTableDataSource([]); + this.returnReasons.sort(); } receiveAcknowledgement() { const data = { type: this.type, number: this.number, - receivedDate: this.receivedDate, + receivedDate: this.functions.formatDateObjectToDateString(this.receivedDate), returnReason: this.reason, returnReasonOther: this.reasonOther }; @@ -76,13 +88,22 @@ export class AcknowledgementReceptionComponent implements OnInit { this.notify.error(this.translate.instant('lang.fieldsNotValid')); return; } + if (this.reason === this.translate.instant('lang.others') && this.functions.empty(this.reasonOther)) { + this.notify.error(this.translate.instant('lang.fieldsNotValid')); + return; + } } this.http.put('../rest/registeredMails/acknowledgement', data).pipe( tap(() => { - this.type = ''; + this.notify.success(this.translate.instant('lang.arReceived')); + + const receivedList = this.dataSource.data; + receivedList.unshift(data); + this.dataSource.data = receivedList; + this.number = ''; - this.receivedDate = ''; + this.receivedDate = this.today; this.reason = ''; this.reasonOther = ''; }), @@ -92,4 +113,12 @@ export class AcknowledgementReceptionComponent implements OnInit { }) ).subscribe(); } + + changeType(type: any) { + setTimeout(() => { + if (type === 'distributed') { + this.numberInput.nativeElement.focus(); + } + }, 0); + } } diff --git a/src/lang/lang-en.json b/src/lang/lang-en.json index fe8b7d10136..38fca883245 100644 --- a/src/lang/lang-en.json +++ b/src/lang/lang-en.json @@ -1933,5 +1933,7 @@ "returnReasonCannotAccess": "Access or address error", "returnReasonNotClaimed": "Mail not claimed", "returnReasonRejected": "Mail rejected by recipient", - "returnReasonUnknown": "Recipient unknown at this address" + "returnReasonUnknown": "Recipient unknown at this address", + "arReceived": "AR received", + "arAlreadyReceived": "This AR has already been received" } diff --git a/src/lang/lang-fr.json b/src/lang/lang-fr.json index 880f8278008..26f4d47718e 100644 --- a/src/lang/lang-fr.json +++ b/src/lang/lang-fr.json @@ -1971,5 +1971,7 @@ "maileva": "Maileva", "acknowlegdmentReceipt": "Accusé de réception", "externalSignatoryBook": "Parapheur externe", - "dispositListGeneratedMsg": "Le recommandé a été imprimé dans un <b>descriptif de pli</b>, vous ne pouvez pas modifier les données." + "dispositListGeneratedMsg": "Le recommandé a été imprimé dans un <b>descriptif de pli</b>, vous ne pouvez pas modifier les données.", + "arReceived": "AR réceptionné", + "arAlreadyReceived": "Cet AR a déjà été reçu" } -- GitLab