Employee - Daily Timesheetdetails

In order to develop the functionality that allows a user in the Employee role to complete his/her timesheet for each day of a Timesheet period, we need to develop a new screen.

The image below shows this screen, named Day View

As can be screen from the screen above, an employee can select the tasks assigned to him/her by the Admin and enter the hours worked for that day on these tasks. Additionally, the employee can also enter hours for time-off.

When the employee clicks the Save button on this screen, if a Timesheet entity does not exist for the time period that includes the current day, it is created. Secondly, for the hours entered for each task or time-off type, a Timesheetdetails entity is created. These entities are then associated with the existing or newly created Timesheet entity.

Below, we describe the changes we need to make to the generated Timesheet application in order to implement the above functionality:

Back-end Changes

  1. com.fastcode.timesheetapp1.restcontrollers.extended.TimesheetControllerExtended.java

The method findTimesheetByDate shown below is used to get, if it exists, the Timesheet for a specific period based on a date specified within the period. We also add a permission READ_TIMESHEET_WITH_DETAILS to secure the method findTimesheetByDate shown below.

@RequestMapping(value = "/getTimesheet", method = RequestMethod.GET, consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<TimesheetOutput> findTimesheetByDate(@RequestParam("date") String date, @RequestParam("includeDetails") Boolean includeDetails, @RequestParam(value="userId", required=false) Long userId,HttpServletRequest request) throws Exception
  1. com.fastcode.timesheetapp1.restcontrollers.extended.TimesheetDetailsControllerExtended.java

The method createMultipleDetails shown below is a bulk create/update method that is called with all the Timesheetdetails for the day for creation or update.

The method findTimesheetdetailsByWorkDate shown below gets all the Timesheetdetails for a particular calendar day. This data is then displayed in the Day View screen.

We also add two permissions, CREATE_TIMESHEETDETAILS_BULK to secure the method createMultipleDetails, and FIND_BY_DATE_TIMESHEETDETAILS to secure the method findTimesheetdetailsByWorkDate.

@RequestMapping(value="/timesheetdetails", method = RequestMethod.POST, consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<Map<String,String>> createMultipleDetails(@RequestBody @Valid List<TimesheetdetailsInput> inputList) 

  
@RequestMapping(value = "/timesheetdetails", method = RequestMethod.GET, consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<List<TimesheetdetailsOutput>> findTimesheetdetailsByWorkDate(@RequestParam("workDate") String workDate)
  1. com.fastcode.timesheetapp1.restcontrollers.extended.UserTaskControllerExtended.java

The method getTaskAgainstUser shown below fetches the Tasks assigned to each employee. It is used by employees to select a task to assign hours to create Timesheetdetails entities.

@RequestMapping(value = "/taskList", method = RequestMethod.GET, consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<List<UsertaskOutput>> getTaskAgainstUser()

NOTE: In the code change above, we have only provided the changes related to the ReST Controllers. We leave it to you to look at the source code of the final Timesheet application to review the methods called by these ReST controllers in the Application and Domain layers.

Front-end Changes

  1. Create the timesheet module and routing files in src/app/extended/timesheet-module/ directory.

timesheet.module.ts
timesheet.routing.ts

  1. To fetch tasks assigned to the user, add the following code to src\app\extended\entities\usertask\usertask.service.ts
public getTasks(): Observable<ITaskModel[]> {
    return this.http.get<ITaskModel[]>(this.url + "/taskList").pipe(map((response: any) => {
      return response;
    }), catchError(this.handleError));
  }
  1. Create the Timesheet angular component

Create the Timesheet angular component under src\app\extended\timesheet-module. This component represents the Day View that allows a user to enter the Timesheetdetails for each day.

(i) timesheet\timesheet.component.html
(ii) timesheet\timesheet.component.scss
(iii) timesheet\timesheet.component.ts

  1. Add the component's entry in entities array in timesheet.module.ts file:
import { TimesheetComponent } from 'src/app/extended/timesheet-module/timesheet/timesheet.component';

const entities = [TimesheetComponent]
  1. Add the component's entry in the routes array in timesheet.routing.ts file:
import { TimesheetComponent } from 'src/app/extended/timesheet-module/timesheet/timesheet.component';

const routes: Routes = [
{ path: "timesheet", component: TimesheetComponent , canActivate: [ AuthGuard ] }];
  1. Create the methods getTimesheetDetails and createTimesheetDetails in the file src/app/extended/entities/timesheetdetails/timesheetdetails.service.ts
getTimesheetDetails(workDate: Date): Observable<ITimesheetdetails[]> {
let date = moment(workDate).format('DD-MM-YYYY')
return this.http.get<ITimesheetdetails[]>(`${this.url}/timesheetdetails/?workDate=${date}`).pipe(catchError(this.handleError));
}


createTimesheetDetails(items: ITimesheetdetails[]): Observable<any> {
    return this.http.post(this.url + '/timesheetdetails', items).pipe(catchError(this.handleError));
  }
  1. Add the method getByDate to get the Timesheet based on Date in the file src/app/extended/entities/timesheet/timesheet.service.ts**
getByDate(workDate: Date, includeDetails?: boolean, userId?: number): Observable<any> {
let params: any = {
date: moment(workDate).format('DD-MM-YYYY'),
includeDetails: includeDetails? 'true' : 'false'
}
if(userId) {
params['userId'] = userId.toString();
}
return this.http.get(`${this.url}/getTimesheet`, {params: params}).pipe(catchError(this.handleError));
}
  1. Add a link in main-navbar HTML file

The code should be added in src/app/extended/core/main-nav/main-nav.component.html inside tag.

<a mat-list-item class="sidenav-list-item" routerLink="timesheet" *ngIf="permissions['CREATE_TIMESHEETDETAILS_BULK']">
        <i class="material-icons">
          access_time
        </i> &nbsp; {{'TIMESHEET.DAY_VIEW' | translate}}</a>
  1. Add a link in main-navbar TS file

Add CREATE_TIMESHEETDETAILS_BULK permission in perm array in setPermission method in the file src/app/extended/core/main-nav/main-nav.component.ts.

setPermissions() {
        …….
        let perms = ["CREATE_TIMESHEETDETAILS_BULK"]
}
  1. Add a link in main-navbar HTML file

The code should be added in src/app/extended/core/main-nav/main-nav.component.html inside tag.

<a mat-list-item class="sidenav-list-item" routerLink="timesheet-details" *ngIf="permissions['READ_TIMESHEET_WITH_DETAILS']">
        <i class="material-icons">
          access_time
        </i> &nbsp; {{'TIMESHEET.TIMESHEET_VIEW' | translate}}</a>
  1. Add a link in main-navbar TS file

Add READ_TIMESHEET_WITH_DETAILS permission in perm array in setPermission method in the file src/app/extended/core/main-nav/main-nav.component.ts.

setPermissions() {
  …….
  let perms = ["READ_TIMESHEET_WITH_DETAILS"]
}