text:
<repo_name>javadev/pt-backend<file_sep>/src/test/java/com/osomapps/pt/programs/WorkoutItemSetResponseDTOTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutItemSetResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(
                new WorkoutItemSetResponseDTO(1, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        WorkoutItemSetResponseDTO workoutItemSetResponseDTO =
                new WorkoutItemSetResponseDTO()
                        .setRepetitions(null)
                        .setWeight(null)
                        .setBodyweight(null)
                        .setTime_in_sec(null)
                        .setSpeed(null)
                        .setIncline(null)
                        .setResistance(null);
        assertThat(workoutItemSetResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        WorkoutItemSetResponseDTO workoutItemSetResponseDTO = new WorkoutItemSetResponseDTO();
        workoutItemSetResponseDTO.getRepetitions();
        workoutItemSetResponseDTO.getWeight();
        workoutItemSetResponseDTO.getBodyweight();
        workoutItemSetResponseDTO.getTime_in_sec();
        workoutItemSetResponseDTO.getSpeed();
        workoutItemSetResponseDTO.getIncline();
        workoutItemSetResponseDTO.getResistance();
        assertThat(workoutItemSetResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserProgramRequestDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserProgramRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserProgramRequestDTO(null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        UserProgramRequestDTO userProgramRequestDTO = new UserProgramRequestDTO();
        userProgramRequestDTO.setName(null);
        userProgramRequestDTO.setType(null);
        userProgramRequestDTO.setWorkouts(null);
        assertThat(userProgramRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserProgramRequestDTO userProgramRequestDTO = new UserProgramRequestDTO();
        userProgramRequestDTO.getName();
        userProgramRequestDTO.getType();
        userProgramRequestDTO.getWorkouts();
        assertThat(userProgramRequestDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/ExerciseFileResponseDTO.java
package com.osomapps.pt.admin.exercise;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Builder
class ExerciseFileResponseDTO {
    Long id;
    String file_name;
    Long file_size;
    String file_type;
    String data_url;
}
<file_sep>/src/main/resources/db/migration/V4.39__add_in_workout_item_id_to_parse_workout_item_table.sql
ALTER TABLE ptcore.parse_workout_item ADD COLUMN in_workout_item_id BIGINT NULL;
<file_sep>/src/main/resources/db/migration/V4.61__change_value_type_for_in_user_goal_table.sql
ALTER TABLE ptcore.in_user_goal ALTER COLUMN goal_value TYPE VARCHAR(1000);
<file_sep>/src/main/java/com/osomapps/pt/user/UserLevelSerializer.java
package com.osomapps.pt.user;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class UserLevelSerializer extends JsonSerializer<UserLevel> {

    @Override
    public void serialize(UserLevel value, JsonGenerator gen, SerializerProvider serializers)
            throws IOException {
        if (value == null) {
            gen.writeNull();
        } else {
            gen.writeNumber(value.getLevel());
        }
    }
}
<file_sep>/src/main/resources/db/migration/V4.9__create_warmup_workout_item_table.sql
CREATE TABLE ptcore.in_warmup_workout_item (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_workout_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_id VARCHAR(45),
    d_exercise_name VARCHAR(45),
    speed INT,
    incline INT,
    time_in_min INT,
    FOREIGN KEY (in_workout_id) REFERENCES ptcore.in_workout (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/resources/db/migration/V4.3__add_translations_for_exercise_tables.sql
INSERT INTO ptcore.dictionary_data (dlanguage, dname, dkey, dvalue) VALUES
('nb', 'exercise_category_name', '10', 'Ben'),
('nb', 'exercise_category_name', '140', 'Rygg'),
('nb', 'exercise_category_name', '250', 'Bryst'),
('nb', 'exercise_category_name', '330', 'Skuldre'),
('nb', 'exercise_category_name', '430', 'Mage'),
('nb', 'exercise_category_name', '510', 'Armer'),
('nb', 'exercise_category_name', '520', 'Tricep'),
('nb', 'exercise_category_name', '590', 'Bicep');

INSERT INTO ptcore.dictionary_data (dlanguage, dname, dkey, dvalue) VALUES
('nb', 'exercise_name', '20', 'Knebøy'),
('nb', 'exercise_name', '30', 'Front knebøy'),
('nb', 'exercise_name', '40', 'Markløft'),
('nb', 'exercise_name', '50', 'Sumo Deadlift'),
('nb', 'exercise_name', '60', 'Utfall'),
('nb', 'exercise_name', '70', 'Bulgarsk utfall'),
('nb', 'exercise_name', '80', 'Nordic Hamstrings'),
('nb', 'exercise_name', '90', 'Hip-thrust'),
('nb', 'exercise_name', '100', 'Hip-thrust med ett ben'),
('nb', 'exercise_name', '110', 'Hyperekstensjon'),
('nb', 'exercise_name', '120', 'Benpress'),
('nb', 'exercise_name', '130', 'Tå-hev'),

('nb', 'exercise_name', '150', 'Pull-ups'),
('nb', 'exercise_name', '160', 'Chin-ups'),
('nb', 'exercise_name', '170', 'Foroverlent roing'),
('nb', 'exercise_name', '180', 'En-arms hantel-ro'),

('nb', 'exercise_name', '190', 'Strak-arms nedtrekk'),
('nb', 'exercise_name', '200', 'Nedtrekk'),
('nb', 'exercise_name', '210', 'Markløft'),
('nb', 'exercise_name', '220', 'Hyperekstensjon'),
('nb', 'exercise_name', '230', 'Face pull'),
('nb', 'exercise_name', '240', 'Face pull med slynge'),

('nb', 'exercise_name', '250', 'Bryst'),
('nb', 'exercise_name', '260', 'Benkpress'),
('nb', 'exercise_name', '270', 'Skrå benkpress'),
('nb', 'exercise_name', '280', 'Brystpress med hantler'),
('nb', 'exercise_name', '290', 'Skrå brystpress med hantler'),
('nb', 'exercise_name', '300', 'Push-uos'),
('nb', 'exercise_name', '310', 'Push-ups med slynge'),
('nb', 'exercise_name', '320', 'Brystpressmaskin'),

('nb', 'exercise_name', '330', 'Skuldre'),
('nb', 'exercise_name', '340', 'Skulderpress med stang'),
('nb', 'exercise_name', '350', 'Skulderpress med hantler'),
('nb', 'exercise_name', '360', 'Front-hev med hantler'),
('nb', 'exercise_name', '370', 'Front-hev med kabelmaskin'),
('nb', 'exercise_name', '380', 'Side-hev med hantler'),
('nb', 'exercise_name', '390', 'Side-hev med kabelmaskin'),
('nb', 'exercise_name', '400', 'Omvendt flys'),
('nb', 'exercise_name', '410', 'Face pull'),
('nb', 'exercise_name', '420', 'Face pull med slynge'),

('nb', 'exercise_name', '430', 'Mage'),
('nb', 'exercise_name', '440', 'Planke'),
('nb', 'exercise_name', '450', 'Planke på stor ball'),
('nb', 'exercise_name', '460', 'Båt'),
('nb', 'exercise_name', '470', 'Båt med rotasjon'),
('nb', 'exercise_name', '480', 'Benhev/knehev'),
('nb', 'exercise_name', '490', 'Hengende benhev/knehev'),
('nb', 'exercise_name', '500', 'Knetrekk i slynge'),

('nb', 'exercise_name', '510', 'Armer'),

('nb', 'exercise_name', '520', 'Tricep'),
('nb', 'exercise_name', '530', 'Dips'),
('nb', 'exercise_name', '540', 'Smal benkpress'),
('nb', 'exercise_name', '550', 'Liggende franskpress'),
('nb', 'exercise_name', '560', 'Hindu push-ups'),
('nb', 'exercise_name', '570', 'Smal push-ups'),
('nb', 'exercise_name', '580', 'Tricep-ekstensjon i kabelmaskin'),

('nb', 'exercise_name', '590', 'Bicep'),
('nb', 'exercise_name', '600', 'Bicep curl med stang'),
('nb', 'exercise_name', '610', 'Bicep curl med hantler'),
('nb', 'exercise_name', '620', 'Hammer curl med hantler'),
('nb', 'exercise_name', '630', 'Bicep curl med slynge'),
('nb', 'exercise_name', '640', 'Bicep curl i kabelmaskin'),
('nb', 'exercise_name', '650', 'Chin-ups');
<file_sep>/src/test/java/com/osomapps/pt/activecertificate/ActiveCertificateResponseDTOTest.java
package com.osomapps.pt.activecertificate;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ActiveCertificateResponseDTOTest {
    @Test
    public void setters() {
        ActiveCertificateResponseDTO activeCertificateResponseDTO =
                new ActiveCertificateResponseDTO();
        activeCertificateResponseDTO.setCode(null).setExpiration_date(null);
        assertThat(activeCertificateResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserWorkoutRequestDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserWorkoutRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserWorkoutRequestDTO(null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        UserWorkoutRequestDTO userWorkoutRequestDTO = new UserWorkoutRequestDTO();
        userWorkoutRequestDTO.setWarmup(null);
        assertThat(userWorkoutRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserWorkoutRequestDTO userWorkoutRequestDTO = new UserWorkoutRequestDTO();
        userWorkoutRequestDTO.getWarmup();
        assertThat(userWorkoutRequestDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.7__add_exercise_id_for_exercise_table.sql
ALTER TABLE ptcore.exercise ADD COLUMN exercise_id INT NOT NULL DEFAULT 0;

UPDATE ptcore.exercise SET exercise_id = CAST(d_exercise_name AS INT);
<file_sep>/src/main/resources/application-production.yml
spring:
    profiles:
        active: production

app:
    name: PT Production
    email:
        confirm:
            url: https://pt-backend-app.herokuapp.com/email/confirm/
        reset:
            url: https://pt-backend-app.herokuapp.com/email/reset/
<file_sep>/src/main/java/com/osomapps/pt/admin/goal/AdminGoalResource.java
package com.osomapps.pt.admin.goal;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/goal")
class AdminGoalResource {

    private final AdminGoalService adminGoalService;

    @Autowired
    AdminGoalResource(AdminGoalService adminGoalService) {
        this.adminGoalService = adminGoalService;
    }

    @GetMapping
    List<GoalResponseDTO> findAll() {
        return adminGoalService.findAll();
    }

    @GetMapping("{id}")
    GoalResponseDTO findOne(@PathVariable Long id) {
        return adminGoalService.findOne(id);
    }

    @PostMapping
    GoalResponseDTO create(@RequestBody GoalRequestDTO ptUserRequestDTO) {
        return adminGoalService.create(ptUserRequestDTO);
    }

    @PutMapping("{id}")
    GoalResponseDTO update(@PathVariable Long id, @RequestBody GoalRequestDTO ptUserRequestDTO) {
        return adminGoalService.update(id, ptUserRequestDTO);
    }

    @DeleteMapping("{id}")
    GoalResponseDTO delete(@PathVariable Long id) {
        return adminGoalService.delete(id);
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/AdminUserTypeResource.java
package com.osomapps.pt.admin.user;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/user-type")
class AdminUserTypeResource {

    private final AdminUserTypeService userTypeService;

    @Autowired
    AdminUserTypeResource(AdminUserTypeService userTypeService) {
        this.userTypeService = userTypeService;
    }

    @GetMapping
    List<UserTypeResponseDTO> findAll() {
        return userTypeService.findAll();
    }
}
<file_sep>/src/main/resources/db/migration/V4.5__create_workout_item_report_table.sql
CREATE TABLE ptcore.in_workout_item_report (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_workout_item_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    sets INT,
    repetitions INT,
    weight INT,
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    FOREIGN KEY (in_workout_item_id) REFERENCES ptcore.in_workout_item (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/test/java/com/osomapps/pt/email/EmailMessageTypeTest.java
package com.osomapps.pt.email;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class EmailMessageTypeTest {

    @Test
    public void allArgsConstructor() {
        assertThat(new EmailMessageType(null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        assertThat(new EmailMessageType().setId(null), notNullValue());
        assertThat(new EmailMessageType().setCreated(null), notNullValue());
        assertThat(new EmailMessageType().setName(null), notNullValue());
        assertThat(new EmailMessageType().setEmailMessageTemplates(null), notNullValue());
    }

    @Test
    public void getters() {
        assertThat(new EmailMessageType().getId(), nullValue());
        assertThat(new EmailMessageType().getCreated(), nullValue());
        assertThat(new EmailMessageType().getName(), nullValue());
        assertThat(new EmailMessageType().getEmailMessageTemplates(), nullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/AdminExerciseOutputService.java
package com.osomapps.pt.admin.exercise;

import com.osomapps.pt.exercises.ExerciseOutput;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

@Service
class AdminExerciseOutputService {

    private final ExerciseOutputRepository exerciseOutputRepository;

    AdminExerciseOutputService(ExerciseOutputRepository exerciseOutputRepository) {
        this.exerciseOutputRepository = exerciseOutputRepository;
    }

    List<ExerciseOutputResponseDTO> findAll() {
        return exerciseOutputRepository.findAll(sortByIdAsc()).stream()
                .map(AdminExerciseOutputService::exerciseOutputToDto)
                .collect(Collectors.toList());
    }

    private Sort sortByIdAsc() {
        return Sort.by(Sort.Direction.ASC, "id");
    }

    private static ExerciseOutputResponseDTO exerciseOutputToDto(ExerciseOutput output) {
        return ExerciseOutputResponseDTO.builder()
                .id(output.getId())
                .name(output.getName())
                .build();
    }
}
<file_sep>/src/main/resources/db/migration/V4.53__create_workout_item_set_table.sql
ALTER TABLE ptcore.in_workout_item DROP COLUMN sets;
ALTER TABLE ptcore.in_workout_item DROP COLUMN repetitions;
ALTER TABLE ptcore.in_workout_item DROP COLUMN weight;
ALTER TABLE ptcore.in_workout_item DROP COLUMN bodyweight;
ALTER TABLE ptcore.in_workout_item DROP COLUMN time_in_min;
ALTER TABLE ptcore.in_workout_item DROP COLUMN speed;
ALTER TABLE ptcore.in_workout_item DROP COLUMN resistance;
ALTER TABLE ptcore.in_workout_item DROP COLUMN incline;

CREATE TABLE ptcore.in_workout_item_set (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_workout_item_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    repetitions INT,
    repetitions_to_failure BOOLEAN NOT NULL DEFAULT FALSE,
    weight INT,
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    time_in_min INT,
    speed INT,
    incline INT,
    resistance INT,
    FOREIGN KEY (in_workout_item_id) REFERENCES ptcore.in_workout_item (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/java/com/osomapps/pt/admin/program/AdminProgramResource.java
package com.osomapps.pt.admin.program;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/program")
class AdminProgramResource {

    private final AdminProgramService programService;

    @Autowired
    AdminProgramResource(AdminProgramService programService) {
        this.programService = programService;
    }

    @GetMapping
    List<ProgramResponseDTO> findAll() {
        return programService.findAll();
    }

    @GetMapping("{id}")
    ProgramResponseDTO findOne(@PathVariable Long id) {
        return programService.findOne(id);
    }

    @PostMapping
    ProgramResponseDTO create(@RequestBody ProgramRequestDTO programRequestDTO) {
        return programService.create(programRequestDTO);
    }

    @PutMapping("{id}")
    ProgramResponseDTO update(
            @PathVariable Long id, @RequestBody ProgramRequestDTO exerciseRequestDTO) {
        return programService.update(id, exerciseRequestDTO);
    }

    @DeleteMapping("{id}")
    ProgramResponseDTO delete(@PathVariable Long id) {
        return programService.delete(id);
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/ptuser/AdminPtUserService.java
package com.osomapps.pt.admin.ptuser;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.UnauthorizedException;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

@Service
class AdminPtUserService {

    private final PtUserRepository ptUserRepository;
    private final PtRoleRepository ptRoleRepository;

    AdminPtUserService(PtUserRepository ptUserRepository, PtRoleRepository ptRoleRepository) {
        this.ptUserRepository = ptUserRepository;
        this.ptRoleRepository = ptRoleRepository;
    }

    private static PtUserResponseDTO ptUserToDto(PtUser ptUser) {
        return PtUserResponseDTO.builder()
                .id(ptUser.getId())
                .created(ptUser.getCreated())
                .login(ptUser.getLogin())
                .name(ptUser.getName())
                .activated(ptUser.getActivated())
                .is_blocked(ptUser.getIs_blocked())
                .is_blocked_date_set(ptUser.getIs_blocked_date_set())
                .blocked_comment(ptUser.getBlocked_comment())
                .blocked_start(ptUser.getBlocked_start())
                .blocked_finish(ptUser.getBlocked_finish())
                .deleted(ptUser.getDeleted())
                .deleted_comment(ptUser.getDeleted_comment())
                .is_deleted(ptUser.getIs_deleted())
                .is_default_password(ptUser.getIs_default_password())
                .description(ptUser.getDescription())
                .phone(ptUser.getPhone())
                .phone2(ptUser.getPhone2())
                .roles(
                        ptUser.getPtRoles().stream()
                                .map(
                                        role ->
                                                PtRoleResponseDTO.builder()
                                                        .id(role.getId())
                                                        .name(role.getName())
                                                        .build())
                                .collect(Collectors.toList()))
                .build();
    }

    List<PtUserResponseDTO> findAll() {
        return ptUserRepository.findAll().stream()
                .map(AdminPtUserService::ptUserToDto)
                .collect(Collectors.toList());
    }

    PtUserResponseDTO findOne(Long id) {
        final PtUser ptUser = ptUserRepository.findById(id).orElse(null);
        if (ptUser == null) {
            throw new ResourceNotFoundException("User with id " + id + " not found.");
        }
        return ptUserToDto(ptUser);
    }

    PtUserResponseDTO delete(Long id) {
        final PtUser ptUser = ptUserRepository.findById(id).orElse(null);
        if (ptUser == null) {
            throw new ResourceNotFoundException("User with id " + id + " not found.");
        }
        if (id == 1L) {
            throw new UnauthorizedException("Cannot delete user with id 1.");
        }
        final PtUserResponseDTO ptUserResponseDTO = ptUserToDto(ptUser);
        ptUserRepository.deleteById(id);
        return ptUserResponseDTO;
    }

    PtUserResponseDTO create(PtUserRequestDTO userRequestDTO) {
        final PtUser ptUser = dtoToPtUser(userRequestDTO, new PtUser());
        final PtUser savedPtUser = ptUserRepository.save(ptUser);
        return ptUserToDto(savedPtUser);
    }

    PtUserResponseDTO update(Long id, PtUserRequestDTO userRequestDTO) {
        final PtUser ptUser = ptUserRepository.findById(id).orElse(null);
        if (ptUser == null) {
            throw new ResourceNotFoundException("User with id " + id + " not found.");
        }
        if (id == 1L) {
            throw new UnauthorizedException("Cannot update user with id 1.");
        }
        final PtUser updatedPtUser = dtoToPtUser(userRequestDTO, ptUser);
        final PtUser savedPtUser = ptUserRepository.save(updatedPtUser);
        return ptUserToDto(savedPtUser);
    }

    private PtUser dtoToPtUser(PtUserRequestDTO userRequestDTO, PtUser ptUser) {
        return ptUser.setLogin(userRequestDTO.getLogin())
                .setPassword(<PASSWORD>RequestDTO.<PASSWORD>())
                .setName(userRequestDTO.getName())
                .setActivated(userRequestDTO.getActivated())
                .setIs_blocked(userRequestDTO.getIs_blocked())
                .setIs_blocked_date_set(userRequestDTO.getIs_blocked_date_set())
                .setBlocked_comment(userRequestDTO.getBlocked_comment())
                .setBlocked_start(userRequestDTO.getBlocked_start())
                .setBlocked_finish(userRequestDTO.getBlocked_finish())
                .setDeleted(userRequestDTO.getDeleted())
                .setDeleted_comment(userRequestDTO.getDeleted_comment())
                .setIs_deleted(userRequestDTO.getIs_deleted())
                .setIs_default_password(userRequestDTO.getIs_default_password())
                .setDescription(userRequestDTO.getDescription())
                .setPhone(userRequestDTO.getPhone())
                .setPhone2(userRequestDTO.getPhone2())
                .setPtRoles(
                        ptRoleRepository.findAllById(
                                userRequestDTO.getRoles().stream()
                                        .map(role -> role.getId())
                                        .collect(Collectors.toList())));
    }
}
<file_sep>/src/main/resources/static/scripts/views/goals.js
/*jshint browser: true*/
/*global define, console*/
define([
    'jquery',
    'underscore',
    'marionette',
    'app',
    'bootstrapTab',
    'bootstrapSelect'
],
function ($, _, Marionette, App) {
  'use strict';

  var EmptyView = Marionette.ItemView.extend({
        tagName: 'tr',
        template: _.template('<td colspan="7">There are no goals available.</td>')
  });

  var Goal = Marionette.ItemView.extend({
    tagName: 'tr',
    className: function() {
      return this.collection._modelId === this.model.get('id') ? 'selectedId' : '';
    },
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ titleEn }}',
      '</td>',
      '<td>',
        '{{ title2En }}',
      '</td>',
      '<td>',
        '{{ type == null ? "" : type.name }}',
      '</td>',
      '<td>',
        '{{ _.map(parameters, function(item) {return item.name;}).join(", ") }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-edit-value">',
          '<i class="glyphicon glyphicon-edit"></i>',
        '</button>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-delete-value">',
          '<i class="glyphicon glyphicon-remove"></i>',
        '</button>',
      '</td>'
    ].join('')),

    initialize: function(options) {
      this.collection = options.collection;
    },
    events: {
      'click .js-edit-value': 'editGoal',
      'click .js-delete-value': 'deleteGoal'
    },
    editGoal: function() {
      this.collection.trigger('goal:new', this.model);
    },
    deleteGoal: function(evt) {
      evt.preventDefault();
      var model = this.model;
      var collection = this.collection;
      this.model.destroy()
        .done(function() {
        })
        .fail(function (xhr) {
          App.vent.trigger('xhr:error', 'Goal ' + model.get('id') + ' delete was failed');
        })
        .always(function() {
          collection.fetch();
        });
    }
  });

  var Goals = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: Goal,
    emptyView: EmptyView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Goals </h3>',
      '</div>',
      '<button class="btn btn-primary js-new-goal" style="margin: 10px;">',
        'New goal',
      '</button>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Title</th>',
            '<th>Title2</th>',
            '<th>Type</th>',
            '<th>Parameters</th>',
            '<th></th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    collectionEvents: {
      'sync': 'render'
    },
    events: {
      'click .js-new-goal': 'newGoal'
    },
    newGoal: function() {
      this.collection.trigger('goal:new');
    }
  });

  var NewGoalLayout = Marionette.Layout.extend({
    template: _.template([
      '<div class="panel panel-primary">',
        '<div class="panel-heading">',
          '<h3 class="panel-title"> {{ getHeader() }} </h3>',
        '</div>',
        '<div id="buttons"/>',
        '<div id="inputForm"/>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getHeader: function () {
          return model.isNew() ? 'New goal' : 'Edit goal';
        }
      };
    },
    tagName: 'form',
    className: 'form-horizontal',
    regions: {
      buttons: '#buttons',
      inputForm: '#inputForm'
    },
    onShow: function() {
      this.buttons.show(new NewGoalButtons({model: this.model}));
      this.inputForm.show(new NewGoalInputForm({model: this.model}));
    }
  });

  var NewGoalButtons = Marionette.ItemView.extend({
    template: _.template([
      '<div class="btn-group">',
        '<button class="btn btn-default js-back" style="margin: 10px 0 0 10px;">',
          'Back',
        '</button>',
        '<button class="btn btn-danger js-save  {{ getSaveDisabled() }}" style="margin: 10px 0 0 0; min-width: 100px;">',
          'Save',
        '</button>',
        '<button class="btn btn-default js-discard" style="margin: 10px 0 0 0px;">',
          'Discard',
        '</button>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getSaveDisabled: function () {
          return view.model.isValid() ? '' : 'disabled';
        }
      };
    },
    events: {
      'click .js-back': 'back',
      'click .js-save': 'save',
      'click .js-discard': 'discard'
    },
    modelEvents: {
      'change': 'render'
    },
    initialize: function(options) {
      this._model = options.model.clone();
    },
    back: function(evt) {
      evt.preventDefault();
      this.model.trigger('goal:back', this.model.get('id'));
    },
    save: function(evt) {
      evt.preventDefault();
      var model = this.model;
      this.model.save().done(function(data) {
        model.trigger('goal:back', model.get('id'), data);
      })
      .fail(function (xhr) {
        App.vent.trigger('xhr:error', 'Goal save was failed');
      });
    },
    discard: function(evt) {
      evt.preventDefault();
      this.model.set(this._model.toJSON());
      this.model.trigger('sync');
    }
  });

  var NewGoalInputForm = Marionette.ItemView.extend({
    className: 'user-input-form',
    template: _.template([
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">ID</label>',
        '<div class="col-sm-8">',
          '<p class="form-control-static">',
            ' {{ id }}',
          '</p>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Type</label>',
        '<div class="col-sm-8">',
          '<select id="goal-type" class="selectpicker show-tick">',
            '{{ getTypes() }}',
          '</select>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Parameters</label>',
        '<div class="col-sm-8">',
          '<select id="goal-parameters" class="selectpicker show-tick" multiple>',
            '{{ getParameters() }}',
          '</select>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Title in English</label>',
        '<div class="col-sm-8">',
          '<textarea id="goal-titleEn" class="form-control" rows="3" placeholder="Please enter title in English" name="titleEn" required="true">',
            '{{ titleEn }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Title in Norwegian</label>',
        '<div class="col-sm-8">',
          '<textarea id="goal-titleNo" class="form-control" rows="3" placeholder="Please enter title in Norwegian" name="titleNo" required="true">',
            '{{ titleNo }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Title2 in English</label>',
        '<div class="col-sm-8">',
          '<textarea id="goal-title2En" class="form-control" rows="3" placeholder="Please enter title2 in English" name="title2En" required="true">',
            '{{ title2En }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Title2 in Norwegian</label>',
        '<div class="col-sm-8">',
          '<textarea id="goal-title2No" class="form-control" rows="3" placeholder="Please enter title2 in Norwegian" name="title2No" required="true">',
            '{{ title2No }}',
          '</textarea>',
        '</div>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getTypes: function() {
          var types = model._types || [];
          var result = _.map(types, function(item) {
            if (_.isNull(item.id)) {
              return '<option></option>';
            }
            return '<option value="' + item.id + '"' +
              (!!model.get('type') && model.get('type').id === item.id ? ' selected' : '') +
              '>' + item.name + '</option>';
          });
          return result;
        },
        getParameters: function() {
          var parameters = model._parameters || [];
          var modelParameters = _.map(model.get('parameters'), function(item) {
             return item.id;
          });
          var result = _.map(parameters, function(item) {
            if (_.isNull(item.id)) {
              return '<option data-hidden="true"></option>';
            }
            return '<option value="' + item.id + '"' +
              (_.contains(modelParameters, item.id) ? ' selected' : '') +
              '>' + item.name + '</option>';
          });
          return result;
        }
      };
    },
    modelEvents: {
      'sync': 'render'
    },
    events: {
      'input #goal-titleEn': 'inputTitleEn',
      'input #goal-titleNo': 'inputTitleNo',
      'input #goal-title2En': 'inputTitle2En',
      'input #goal-title2No': 'inputTitle2No'
    },
    ui: {
      goalType: '#goal-type',
      goalParameters: '#goal-parameters',
      titleEn: '#goal-titleEn',
      titleNo: '#goal-titleNo',
      title2En: '#goal-title2En',
      title2No: '#goal-title2No'
    },
    inputTitleEn: function() {
      this.model.set('titleEn', this.ui.titleEn.val());
    },
    inputTitleNo: function() {
      this.model.set('titleNo', this.ui.titleNo.val());
    },
    inputTitle2En: function() {
      this.model.set('title2En', this.ui.title2En.val());
    },
    inputTitle2No: function() {
      this.model.set('title2No', this.ui.title2No.val());
    },
    onShow: function() {
      this.onRender();
    },
    onRender: function() {
      var view = this;
      $('.selectpicker').selectpicker({
        style: 'btn-default',
        size: false
      });
      this.ui.goalType.on('changed.bs.select', function (e) {
        view.model.set('type', {id: parseInt(e.target.value, 10) });
      });
      this.ui.goalParameters.on('changed.bs.select', function (e) {
        var selectedParameters = _.map(e.target.selectedOptions, function(item) {
            return {id: parseInt(item.value, 10) };
        });
        view.model.set('parameters', selectedParameters);
      });
    }
  });

  return {
    Goals: Goals,
    NewGoalLayout: NewGoalLayout
  };

});
<file_sep>/src/test/java/com/osomapps/pt/admin/user/InUserGoalTypeTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class InUserGoalTypeTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new InUserGoalType(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        InUserGoalType inUserGoalType = new InUserGoalType();
        inUserGoalType.setId(null);
        inUserGoalType.setCreated(null);
        inUserGoalType.setD_user_goal_type(null);
        inUserGoalType.setInUserGoals(null);
        assertThat(inUserGoalType, notNullValue());
    }

    @Test
    public void getters() {
        InUserGoalType inUserGoalType = new InUserGoalType();
        inUserGoalType.getId();
        inUserGoalType.getCreated();
        inUserGoalType.getD_user_goal_type();
        inUserGoalType.getInUserGoals();
        assertThat(inUserGoalType, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/certificate/AdminCertificateResource.java
package com.osomapps.pt.admin.certificate;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/certificate")
class AdminCertificateResource {

    private final AdminCertificateService certificateService;

    @Autowired
    AdminCertificateResource(AdminCertificateService certificateService) {
        this.certificateService = certificateService;
    }

    @GetMapping
    List<CertificateResponseDTO> findAll() {
        return certificateService.findAll();
    }

    @GetMapping(value = "{id}")
    CertificateResponseDTO findOne(@PathVariable Long id) {
        return certificateService.findOne(id);
    }

    @PostMapping
    CertificateResponseDTO create(@RequestBody CertificateRequestDTO certificateRequestDTO) {
        return certificateService.create(certificateRequestDTO);
    }

    @PutMapping(value = "{id}")
    CertificateResponseDTO update(
            @PathVariable Long id, @RequestBody CertificateRequestDTO certificateRequestDTO) {
        return certificateService.update(id, certificateRequestDTO);
    }

    @DeleteMapping(value = "{id}")
    CertificateResponseDTO delete(@PathVariable Long id) {
        return certificateService.delete(id);
    }
}
<file_sep>/src/main/java/com/osomapps/pt/user/UserResponseDTO.java
package com.osomapps.pt.user;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.osomapps.pt.token.LocalDateSerializer;
import java.time.LocalDate;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class UserResponseDTO {
    Long id;
    String name;
    String email;
    String avatar;
    String avatar_dataurl;
    String gender;
    Long age;

    @JsonSerialize(using = LocalDateSerializer.class)
    LocalDate birthday;

    @JsonSerialize(using = UserLevelSerializer.class)
    UserLevel level;

    List<UserGoalResponseDTO> goals;
    Long height;
    Long weight;
}
<file_sep>/src/test/java/com/osomapps/pt/reportworkout/WorkoutItemReportResponseDTOTest.java
package com.osomapps.pt.reportworkout;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutItemReportResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new WorkoutItemReportResponseDTO(1L, null), notNullValue());
    }

    @Test
    public void setters() {
        WorkoutItemReportResponseDTO workoutItemReportResponseDTO =
                new WorkoutItemReportResponseDTO();
        workoutItemReportResponseDTO.setId(1L);
        workoutItemReportResponseDTO.setSets(null);
        assertThat(workoutItemReportResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        WorkoutItemReportResponseDTO workoutItemReportResponseDTO =
                new WorkoutItemReportResponseDTO();
        workoutItemReportResponseDTO.getId();
        workoutItemReportResponseDTO.getSets();
        assertThat(workoutItemReportResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.23__create_in_user_type_table.sql
CREATE TABLE ptcore.in_user_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_user_type VARCHAR(45) NOT NULL
);

INSERT INTO ptcore.in_user_type (d_user_type) VALUES
('10'),
('20');

INSERT INTO ptcore.dictionary_data (dlanguage, dname, dkey, dvalue) VALUES
('en', 'user_type', '10', 'Test'),
('en', 'user_type', '20', 'Premium'),
('nb', 'user_type', '10', 'Test'),
('nb', 'user_type', '20', 'Premium');

ALTER TABLE ptcore.in_user ADD COLUMN in_user_type_id BIGINT;

ALTER TABLE ptcore.in_user
  ADD CONSTRAINT in_user_type_id_fkey FOREIGN KEY (in_user_type_id)
      REFERENCES ptcore.in_user_type (id)
      ON UPDATE CASCADE ON DELETE CASCADE;
<file_sep>/src/test/java/com/osomapps/pt/admin/program/AdminProgramAssignServiceTest.java
package com.osomapps.pt.admin.program;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.dictionary.DictionaryName;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.exercises.Exercise;
import com.osomapps.pt.exercises.ExerciseRepository;
import com.osomapps.pt.exercises.ExerciseType;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InProgramRepository;
import com.osomapps.pt.programs.InWarmupWorkoutItemRepository;
import com.osomapps.pt.programs.InWorkout;
import com.osomapps.pt.programs.InWorkoutRepository;
import com.osomapps.pt.programs.ParseExercise;
import com.osomapps.pt.programs.ParseGoal;
import com.osomapps.pt.programs.ParsePart;
import com.osomapps.pt.programs.ParseProgram;
import com.osomapps.pt.programs.ParseProgramRepository;
import com.osomapps.pt.programs.ParseRound;
import com.osomapps.pt.programs.ParseUserGroup;
import com.osomapps.pt.programs.ParseWarmupWorkoutItem;
import com.osomapps.pt.programs.ParseWorkout;
import com.osomapps.pt.programs.ParseWorkoutItem;
import com.osomapps.pt.programs.ParseWorkoutItemSet;
import com.osomapps.pt.reportworkout.InWorkoutItemRepository;
import com.osomapps.pt.reportworkout.InWorkoutItemSetRepository;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserGoal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Sort;

@RunWith(MockitoJUnitRunner.class)
public class AdminProgramAssignServiceTest {

    @Mock private InProgramRepository inProgramRepository;
    @Mock private InWorkoutRepository inWorkoutRepository;
    @Mock private InWorkoutItemRepository inWorkoutItemRepository;
    @Mock private InWorkoutItemSetRepository inWorkoutItemSetRepository;
    @Mock private ParseProgramRepository parseProgramRepository;
    @Mock private InWarmupWorkoutItemRepository inWarmupWorkoutItemRepository;
    @Mock private DictionaryService dictionaryService;
    @Mock private ExerciseRepository exerciseRepository;

    @InjectMocks private AdminProgramAssignService adminProgramAssignService;

    @Test
    public void assign_user_group_1_two_goals() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        when(dictionaryService.getEnValue(eq(DictionaryName.goal_title), isNull(), isNull()))
                .thenReturn("Loose weight");
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("2")
                        .setD_sex("male")
                        .setInUserGoals(Arrays.asList(new InUserGoal(), new InUserGoal()))
                        .setInPrograms(
                                Arrays.asList(
                                        new InProgram()
                                                .setInWorkouts(Arrays.asList(new InWorkout())))));
        verify(inProgramRepository).save(any(InProgram.class));
    }

    @Test
    public void assign_empty_program() {
        when(parseProgramRepository.findAll(any(Sort.class))).thenReturn(Collections.emptyList());
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("3")
                        .setD_sex("male2")
                        .setInUserGoals(Arrays.asList(new InUserGoal())));
        verify(inProgramRepository, never()).save(any(InProgram.class));
    }

    @Test
    public void assign_user_unknown_gender() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("2")
                        .setD_sex("male2")
                        .setInUserGoals(Arrays.asList(new InUserGoal())));
        verify(inProgramRepository, never()).save(any(InProgram.class));
    }

    @Test
    public void assign_user_unknown_level() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("3")
                        .setD_sex("male")
                        .setInUserGoals(Arrays.asList(new InUserGoal())));
        verify(inProgramRepository, never()).save(any(InProgram.class));
    }

    @Test
    public void assign_user_unknown_level_and_gender() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("3")
                        .setD_sex("male2")
                        .setInUserGoals(Arrays.asList(new InUserGoal())));
        verify(inProgramRepository, never()).save(any(InProgram.class));
    }

    @Test
    public void assign_user_group_1() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        when(dictionaryService.getEnValue(eq(DictionaryName.goal_title), isNull(), isNull()))
                .thenReturn("Loose weight");
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("2")
                        .setD_sex("male")
                        .setInUserGoals(Arrays.asList(new InUserGoal()))
                        .setInPrograms(
                                Arrays.asList(
                                        new InProgram()
                                                .setCurrent_workout_index(0)
                                                .setInWorkouts(Arrays.asList(new InWorkout())))));
        verify(inProgramRepository).save(any(InProgram.class));
    }

    @Test
    public void assign_empty_goals() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("2")
                        .setD_sex("male")
                        .setInUserGoals(Collections.emptyList()));
        verify(inProgramRepository, never()).save(any(InProgram.class));
    }

    @Test
    public void assign_user_group_2() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        when(dictionaryService.getEnValue(eq(DictionaryName.goal_title), isNull(), isNull()))
                .thenReturn("Loose weight");
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("1")
                        .setD_sex("male")
                        .setInUserGoals(Arrays.asList(new InUserGoal()))
                        .setInPrograms(
                                Arrays.asList(
                                        new InProgram()
                                                .setCurrent_workout_index(0)
                                                .setInWorkouts(Arrays.asList(new InWorkout())))));

        verify(inProgramRepository).save(any(InProgram.class));
    }

    @Test
    public void assign_user_group_3() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        when(dictionaryService.getEnValue(eq(DictionaryName.goal_title), isNull(), isNull()))
                .thenReturn("Loose weight");
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("2")
                        .setD_sex("female")
                        .setInUserGoals(Arrays.asList(new InUserGoal()))
                        .setInPrograms(
                                Arrays.asList(
                                        new InProgram()
                                                .setCurrent_workout_index(0)
                                                .setInWorkouts(Arrays.asList(new InWorkout())))));
        verify(inProgramRepository).save(any(InProgram.class));
    }

    @Test
    public void assign_user_group_4() {
        when(parseProgramRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(getParseProgram()));
        when(dictionaryService.getEnValue(eq(DictionaryName.goal_title), isNull(), isNull()))
                .thenReturn("Loose weight");
        adminProgramAssignService.assign(
                new InUser()
                        .setD_level("1")
                        .setD_sex("female")
                        .setInUserGoals(Arrays.asList(new InUserGoal()))
                        .setInPrograms(
                                Arrays.asList(
                                        new InProgram()
                                                .setCurrent_workout_index(0)
                                                .setInWorkouts(Arrays.asList(new InWorkout())))));
        verify(inProgramRepository).save(any(InProgram.class));
    }

    @Test
    public void getCurrentWorkoutIndex_empty_programs() {
        assertThat(
                adminProgramAssignService.getCurrentWorkoutIndex(
                        new InUser().setInPrograms(Collections.emptyList()),
                        Collections.emptyList()),
                equalTo(0));
    }

    @Test
    public void getCurrentWorkoutIndex_empty_programs2() {
        assertThat(
                adminProgramAssignService.getCurrentWorkoutIndex(
                        new InUser().setInPrograms(null), Collections.emptyList()),
                equalTo(0));
    }

    @Test
    public void getCurrentWorkoutIndex_same_names() {
        assertThat(
                adminProgramAssignService.getCurrentWorkoutIndex(
                        new InUser()
                                .setInPrograms(
                                        Arrays.asList(
                                                new InProgram()
                                                        .setCurrent_workout_index(1)
                                                        .setInWorkouts(
                                                                Arrays.asList(
                                                                        new InWorkout()
                                                                                .setD_workout_name(
                                                                                "name1"),
                                                                        new InWorkout()
                                                                                .setD_workout_name(
                                                                                "name2"))))),
                        Arrays.asList(
                                new ParseWorkout().setName("name1"),
                                new ParseWorkout().setName("name2"))),
                equalTo(1));
    }

    private static ParseProgram getParseProgram() {
        return new ParseProgram()
                .setParseExercises(Arrays.asList(new ParseExercise()))
                .setParseGoals(
                        Arrays.asList(
                                new ParseGoal()
                                        .setName("Loose weight")
                                        .setParseUserGroups(
                                                Arrays.asList(
                                                        new ParseUserGroup()
                                                                .setName("1")
                                                                .setParseRounds(
                                                                        Arrays.asList(
                                                                                new ParseRound()
                                                                                .setParseUserGroup(
                                                                                new ParseUserGroup()
                                                                                .setParseGoal(
                                                                                new ParseGoal()))
                                                                                .setParseParts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParsePart()
                                                                                .setParseWorkouts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkout()
                                                                                .setName(
                                                                                "")
                                                                                .setParsePart(
                                                                                new ParsePart()
                                                                                .setParseRound(
                                                                                new ParseRound()
                                                                                .setParseUserGroup(
                                                                                new ParseUserGroup()
                                                                                .setParseGoal(
                                                                                new ParseGoal()))))
                                                                                .setParseWarmupWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWarmupWorkoutItem()))
                                                                                .setParseWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItem()
                                                                                .setParseWorkoutItemSets(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItemSet()
                                                                                .setParseWorkoutItem(
                                                                                new ParseWorkoutItem()
                                                                                .setParseWorkout(
                                                                                new ParseWorkout()
                                                                                .setParsePart(
                                                                                new ParsePart()
                                                                                .setParseRound(
                                                                                new ParseRound()
                                                                                .setParseUserGroup(
                                                                                new ParseUserGroup()
                                                                                .setName(
                                                                                "1"))))))))))))))))))));
    }

    @Test
    public void multiplyLists_one_element() {
        List<ParseRound> parseRounds1 = Arrays.asList(new ParseRound().setName("1_1"));
        List<ParseRound> result = adminProgramAssignService.multiplyLists(parseRounds1, 1);
        assertThat(result.size(), equalTo(1));
        assertThat(result.get(0).getName(), equalTo("1_1"));
    }

    @Test
    public void multiplyLists_one_element_loops_2() {
        List<ParseRound> parseRounds1 = Arrays.asList(new ParseRound().setName("1_1"));
        List<ParseRound> result = adminProgramAssignService.multiplyLists(parseRounds1, 2);
        assertThat(result.size(), equalTo(2));
        assertThat(result.get(0).getName(), equalTo("1_1"));
    }

    @Test
    public void multiplyLists_two_elements() {
        List<ParseRound> parseRounds1 =
                Arrays.asList(new ParseRound().setName("1_1"), new ParseRound().setName("1_2"));
        List<ParseRound> result = adminProgramAssignService.multiplyLists(parseRounds1, 1);
        assertThat(result.size(), equalTo(2));
        assertThat(result.get(0).getName(), equalTo("1_1"));
        assertThat(result.get(1).getName(), equalTo("1_2"));
    }

    @Test
    public void multiplyLists_two_elements_loops_2() {
        List<ParseRound> parseRounds1 =
                Arrays.asList(new ParseRound().setName("1_1"), new ParseRound().setName("1_2"));
        List<ParseRound> result = adminProgramAssignService.multiplyLists(parseRounds1, 2);
        assertThat(result.size(), equalTo(4));
        assertThat(result.get(0).getName(), equalTo("1_1"));
        assertThat(result.get(1).getName(), equalTo("1_1"));
        assertThat(result.get(2).getName(), equalTo("1_2"));
        assertThat(result.get(3).getName(), equalTo("1_2"));
    }

    @Test
    public void mergeLists_one_element() {
        List<ParseWorkout> parseWorkouts1 = Arrays.asList(new ParseWorkout().setName("1_1"));
        List<ParseWorkout> result =
                adminProgramAssignService.mergeLists(parseWorkouts1, Collections.emptyList());
        assertThat(result.size(), equalTo(1));
        assertThat(result.get(0).getName(), equalTo("1_1"));
    }

    @Test
    public void mergeLists_one_element2() {
        List<ParseWorkout> parseWorkouts2 = Arrays.asList(new ParseWorkout().setName("2_1"));
        List<ParseWorkout> result =
                adminProgramAssignService.mergeLists(Collections.emptyList(), parseWorkouts2);
        assertThat(result.size(), equalTo(1));
        assertThat(result.get(0).getName(), equalTo("2_1"));
    }

    @Test
    public void mergeLists_two_elements() {
        List<ParseWorkout> parseWorkouts1 = Arrays.asList(new ParseWorkout().setName("1_1"));
        List<ParseWorkout> parseWorkouts2 = Arrays.asList(new ParseWorkout().setName("2_1"));
        List<ParseWorkout> result =
                adminProgramAssignService.mergeLists(parseWorkouts1, parseWorkouts2);
        assertThat(result.size(), equalTo(2));
        assertThat(result.get(0).getName(), equalTo("1_1"));
        assertThat(result.get(1).getName(), equalTo("2_1"));
    }

    @Test
    public void mergeLists_five_elements() {
        List<ParseWorkout> parseWorkouts1 =
                Arrays.asList(new ParseWorkout().setName("1_1"), new ParseWorkout().setName("1_2"));
        List<ParseWorkout> parseWorkouts2 =
                Arrays.asList(
                        new ParseWorkout().setName("2_1"),
                        new ParseWorkout().setName("2_2"),
                        new ParseWorkout().setName("2_3"));
        List<ParseWorkout> result =
                adminProgramAssignService.mergeLists(parseWorkouts1, parseWorkouts2);
        assertThat(result.size(), equalTo(6));
        assertThat(result.get(0).getName(), equalTo("1_1"));
        assertThat(result.get(1).getName(), equalTo("2_1"));
        assertThat(result.get(2).getName(), equalTo("1_2"));
        assertThat(result.get(3).getName(), equalTo("2_2"));
        assertThat(result.get(4).getName(), equalTo("1_1"));
        assertThat(result.get(5).getName(), equalTo("2_3"));
    }

    @Test
    public void mergeLists_five_elements2() {
        List<ParseWorkout> parseWorkouts1 =
                Arrays.asList(
                        new ParseWorkout().setName("1_1"),
                        new ParseWorkout().setName("1_2"),
                        new ParseWorkout().setName("1_3"));
        List<ParseWorkout> parseWorkouts2 =
                Arrays.asList(new ParseWorkout().setName("2_1"), new ParseWorkout().setName("2_2"));
        List<ParseWorkout> result =
                adminProgramAssignService.mergeLists(parseWorkouts1, parseWorkouts2);
        assertThat(result.size(), equalTo(6));
        assertThat(result.get(0).getName(), equalTo("1_1"));
        assertThat(result.get(1).getName(), equalTo("2_1"));
        assertThat(result.get(2).getName(), equalTo("1_2"));
        assertThat(result.get(3).getName(), equalTo("2_2"));
        assertThat(result.get(4).getName(), equalTo("1_3"));
        assertThat(result.get(5).getName(), equalTo("2_1"));
    }

    @Test
    public void roundToEven_11() {
        assertThat(adminProgramAssignService.roundToEven(11F), equalTo(10F));
    }

    @Test
    public void roundToEven_12() {
        assertThat(adminProgramAssignService.roundToEven(12F), equalTo(12F));
    }

    @Test
    public void roundToEven_2_1() {
        assertThat(adminProgramAssignService.roundToEven(2.1F), equalTo(2F));
    }

    @Test
    public void getWeightForUserGroup_1_weight_80() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(80F, 1), equalTo(80F));
    }

    @Test
    public void getWeightForUserGroup_1_weight_120() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(120F, 1), equalTo(100F));
    }

    @Test
    public void getWeightForUserGroup_2_weight_80() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(80F, 2), equalTo(80F));
    }

    @Test
    public void getWeightForUserGroup_2_weight_120() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(120F, 2), equalTo(100F));
    }

    @Test
    public void getWeightForUserGroup_3_weight_60() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(60F, 3), equalTo(60F));
    }

    @Test
    public void getWeightForUserGroup_3_weight_90() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(90F, 3), equalTo(75F));
    }

    @Test
    public void getWeightForUserGroup_4_weight_60() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(60F, 4), equalTo(60F));
    }

    @Test
    public void getWeightForUserGroup_4_weight_90() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(90F, 4), equalTo(75F));
    }

    @Test
    public void getWeightForUserGroup_5_weight_60() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(60F, 5), equalTo(60F));
    }

    @Test
    public void getWeightForUserGroup_5_weight_90() {
        assertThat(adminProgramAssignService.getWeightForUserGroup(90F, 5), equalTo(90F));
    }

    @Test
    public void getExerciseType_size_1() {
        when(exerciseRepository.findByExerciseId(anyObject()))
                .thenReturn(
                        Arrays.asList(
                                new Exercise()
                                        .setExerciseTypes(
                                                Arrays.asList(
                                                        new ExerciseType().setName("test")))));
        assertThat(
                adminProgramAssignService.getExerciseType(new ParseWorkoutItem()), equalTo("test"));
    }

    @Test
    public void getExerciseType_size_2() {
        when(exerciseRepository.findByExerciseId(anyObject()))
                .thenReturn(
                        Arrays.asList(
                                new Exercise()
                                        .setExerciseTypes(
                                                Arrays.asList(
                                                        new ExerciseType().setName("test1"),
                                                        new ExerciseType().setName("test2")))));
        assertThat(
                adminProgramAssignService.getExerciseType(
                        new ParseWorkoutItem()
                                .setParseWorkoutItemSets(
                                        Arrays.asList(
                                                new ParseWorkoutItemSet().setTime_in_min(1F)))),
                equalTo("OnTime"));
    }

    @Test
    public void getExerciseType_size_2_with_null_time() {
        when(exerciseRepository.findByExerciseId(anyObject()))
                .thenReturn(
                        Arrays.asList(
                                new Exercise()
                                        .setExerciseTypes(
                                                Arrays.asList(
                                                        new ExerciseType().setName("test1"),
                                                        new ExerciseType().setName("test2")))));
        assertThat(
                adminProgramAssignService.getExerciseType(
                        new ParseWorkoutItem()
                                .setParseWorkoutItemSets(
                                        Arrays.asList(
                                                new ParseWorkoutItemSet().setTime_in_min(null)))),
                equalTo("OnRepetitions"));
    }
}
<file_sep>/src/main/java/com/osomapps/pt/token/InUserRepository.java
package com.osomapps.pt.token;

import org.springframework.data.jpa.repository.JpaRepository;

public interface InUserRepository extends JpaRepository<InUser, Long> {}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseBodypartServiceTest.java
package com.osomapps.pt.admin.exercise;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.exercises.ExerciseBodypart;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseBodypartServiceTest {

    @Mock private ExerciseBodypartRepository exerciseBodypartRepository;
    @Mock private DictionaryService dictionaryService;
    @InjectMocks private AdminExerciseBodypartService adminExerciseBodypartService;

    @Test
    public void findAll() {
        when(exerciseBodypartRepository.findAll())
                .thenReturn(Arrays.asList(new ExerciseBodypart()));
        List<ExerciseBodypartResponseDTO> responseDTOs = adminExerciseBodypartService.findAll();
        assertThat(responseDTOs.size(), equalTo(1));
    }
}
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExerciseImageService.java
package com.osomapps.pt.exercises;

import com.osomapps.pt.ResourceNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Base64;
import org.springframework.stereotype.Service;

@Service
class ExerciseImageService {
    private static final String BASE64_PREFIX = ";base64,";
    private static final int BASE64_PREFIX_LENGTH = 8;
    private final ExerciseFileRepository exerciseFileRepository;

    ExerciseImageService(ExerciseFileRepository exerciseFileRepository) {
        this.exerciseFileRepository = exerciseFileRepository;
    }

    ExerciseImageDTO findOne(Long id, String fileName, OutputStream outputStream)
            throws IOException {
        final ExerciseFile exerciseFile = exerciseFileRepository.findById(id).orElse(null);
        if (exerciseFile == null) {
            throw new ResourceNotFoundException("File with id " + id + " not found");
        }
        dataUrlToOutputStream(exerciseFile.getData_url(), outputStream);
        return new ExerciseImageDTO()
                .setId(exerciseFile.getId())
                .setFileName(exerciseFile.getFile_name())
                .setFileType(exerciseFile.getFile_type());
    }

    void dataUrlToOutputStream(String dataUrl, OutputStream outputStream) throws IOException {
        final String encodedString =
                dataUrl.substring(dataUrl.indexOf(BASE64_PREFIX) + BASE64_PREFIX_LENGTH);
        outputStream.write(Base64.getDecoder().decode(encodedString));
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/goal/AdminGoalParameterService.java
package com.osomapps.pt.admin.goal;

import com.osomapps.pt.goals.GoalParameter;
import com.osomapps.pt.goals.GoalParameterRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

@Service
class AdminGoalParameterService {

    private final GoalParameterRepository goalParameterRepository;

    AdminGoalParameterService(GoalParameterRepository goalParameterRepository) {
        this.goalParameterRepository = goalParameterRepository;
    }

    List<GoalParameterResponseDTO> findAll() {
        return goalParameterRepository.findAll().stream()
                .map(AdminGoalParameterService::goalParameterToDto)
                .collect(Collectors.toList());
    }

    private static GoalParameterResponseDTO goalParameterToDto(GoalParameter parameter) {
        return GoalParameterResponseDTO.builder()
                .id(parameter.getId())
                .name(parameter.getName())
                .build();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserProgramResponseDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserProgramResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new UserProgramResponseDTO(1L, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        UserProgramResponseDTO userProgramResponseDTO = new UserProgramResponseDTO();
        userProgramResponseDTO.setId(null);
        userProgramResponseDTO.setName(null);
        userProgramResponseDTO.setType(null);
        userProgramResponseDTO.setCreated(null);
        assertThat(userProgramResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserProgramResponseDTO userProgramResponseDTO = new UserProgramResponseDTO();
        userProgramResponseDTO.getId();
        userProgramResponseDTO.getName();
        userProgramResponseDTO.getType();
        userProgramResponseDTO.getCreated();
        assertThat(userProgramResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V3.4__add_birthday_for_in_user_facebook_and_in_user.sql
ALTER TABLE ptcore.in_user ADD COLUMN birthday TIMESTAMP WITHOUT TIME ZONE;
ALTER TABLE ptcore.in_user_facebook ADD COLUMN birthday TIMESTAMP WITHOUT TIME ZONE;

CREATE INDEX facebook_token_device_id_index ON ptcore.in_user_facebook (token, device_id);
<file_sep>/src/main/resources/db/migration/V4.42__add_avatar_dataurl_to_the_in_user_table.sql
ALTER TABLE ptcore.in_user ADD COLUMN avatar_dataurl TEXT NULL;
<file_sep>/src/main/java/com/osomapps/pt/package-info.java
/**
 *
 *
 * <h1>Personal Trainer api.</h1>
 *
 * <h2>Design guidelines</h2>
 *
 * <ul>
 *   <li>Use constructor based injection in Spring to increase testability
 *   <li>Create immutable objects when possible
 *   <li>Functions without side effects
 *   <li>Use Guava Optional, Functional collection utils, caching and argument checking
 * </ul>
 */
package com.osomapps.pt;
<file_sep>/src/main/resources/db/migration/V4.55__create_report_workout_item_set_table.sql
ALTER TABLE ptcore.parse_workout_item DROP COLUMN sets;
ALTER TABLE ptcore.parse_workout_item DROP COLUMN repetitions;
ALTER TABLE ptcore.parse_workout_item DROP COLUMN weight;
ALTER TABLE ptcore.parse_workout_item DROP COLUMN bodyweight;
ALTER TABLE ptcore.parse_workout_item DROP COLUMN time_in_min;
ALTER TABLE ptcore.parse_workout_item DROP COLUMN speed;
ALTER TABLE ptcore.parse_workout_item DROP COLUMN resistance;
ALTER TABLE ptcore.in_workout_item_set ALTER COLUMN weight TYPE DECIMAL(9,2);

CREATE TABLE ptcore.parse_workout_item_set (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_workout_item_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    repetitions INT,
    repetitions_to_failure BOOLEAN NOT NULL DEFAULT FALSE,
    weight DECIMAL(9,2),
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    time_in_min INT,
    speed INT,
    incline INT,
    resistance INT,
    FOREIGN KEY (parse_workout_item_id) REFERENCES ptcore.parse_workout_item (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/resources/db/migration/V4.26__remove_exercise_type_table.sql
DELETE FROM ptcore.dictionary_data where dkey = 'exercise_type_name';
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExerciseService.java
package com.osomapps.pt.exercises;

import com.osomapps.pt.dictionary.DictionaryName;
import com.osomapps.pt.dictionary.DictionaryService;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

@Service
class ExerciseService {
    private final ExerciseViewRepository exerciseViewRepository;
    private final DictionaryService dictionaryService;

    @Autowired
    ExerciseService(
            ExerciseViewRepository exerciseViewRepository, DictionaryService dictionaryService) {
        this.exerciseViewRepository = exerciseViewRepository;
        this.dictionaryService = dictionaryService;
    }

    List<ExerciseDTO> findAll() {
        List<ExerciseView> exercises =
                exerciseViewRepository.findAll(Sort.by(Sort.Direction.ASC, "exerciseId"));
        return exercises.stream()
                .map(
                        exercise -> {
                            ExerciseDTO exerciseDTO = new ExerciseDTO();
                            exerciseDTO.setId(exercise.getExerciseId());
                            exerciseDTO.setName(
                                    dictionaryService.getEnValue(
                                            DictionaryName.exercise_name,
                                            exercise.getDExerciseName(),
                                            ""));
                            exerciseDTO.setDescription(
                                    dictionaryService.getEnValue(
                                            DictionaryName.exercise_description,
                                            exercise.getDExerciseDescription(),
                                            null));
                            exerciseDTO.setCardio_percent(exercise.getCardio_percent());
                            exerciseDTO.setTypes(
                                    exercise.getExerciseTypes().stream()
                                            .map(type -> type.getName())
                                            .collect(Collectors.toList()));
                            exerciseDTO.setImages(
                                    exercise.getExerciseFiles().stream()
                                            .map(
                                                    file ->
                                                            "/api/v1/exercise-image/"
                                                                    + file.getId()
                                                                    + "/"
                                                                    + file.getFile_name())
                                            .collect(Collectors.toList()));
                            return exerciseDTO;
                        })
                .sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId()))
                .collect(Collectors.toList());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/auth/CustomUserDetails.java
package com.osomapps.pt.auth;

import com.osomapps.pt.admin.ptuser.PtUser;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;

class CustomUserDetails implements UserDetails {

    private final PtUser ptUser;

    CustomUserDetails(PtUser ptUser) {
        this.ptUser = ptUser;
    }

    public PtUser getPtUser() {
        return ptUser;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return AuthorityUtils.commaSeparatedStringToAuthorityList(
                ptUser.getPtRoles().stream()
                        .map(ptRole -> ptRole.getName())
                        .collect(Collectors.joining(",")));
    }

    @Override
    public String getPassword() {
        return <PASSWORD>();
    }

    @Override
    public String getUsername() {
        return ptUser.getName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return !ptUser.getIs_deleted();
    }
}
<file_sep>/src/main/java/com/osomapps/pt/email/EmailMessageTypeRepository.java
package com.osomapps.pt.email;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface EmailMessageTypeRepository extends JpaRepository<EmailMessageType, Long> {
    List<EmailMessageType> findByNameOrderByIdDesc(String name);
}
<file_sep>/src/main/resources/db/migration/V4.59__rename_time_in_sec_to_the_time_in_min_for_parse.sql
ALTER TABLE ptcore.parse_warmup_workout_item RENAME COLUMN time_in_sec TO time_in_min;
ALTER TABLE ptcore.parse_workout_item_set RENAME COLUMN time_in_sec TO time_in_min;
ALTER TABLE ptcore.parse_warmup_workout_item ALTER COLUMN time_in_min TYPE DECIMAL(9,2);
ALTER TABLE ptcore.parse_workout_item_set ALTER COLUMN time_in_min TYPE DECIMAL(9,2);
<file_sep>/src/main/java/com/osomapps/pt/xlsx/WorkoutItem.java
package com.osomapps.pt.xlsx;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@ToString
public class WorkoutItem {
    int columnIndex;
    int rowIndex;
    int exerciseId;
    Input input = new Input();
    Output output = new Output();
}
<file_sep>/src/main/resources/static/scripts/views/messages.js
/*jshint browser: true*/
/*global define*/
define([
  'underscore',
  'marionette',
  'models/messages'
],
function(_, Marionette, DialogModel) {
  'use strict';

  var template = _.template([
    '<div class="alert {{ className(type) }}">',
    '<a class="close" data-dismiss="alert">×</a>',
      '{% if(header != "") { %}',
      '<strong>{{ header }}</strong>',
      '{% } %}',
      '<p>{{ message }}</p>',
    '</div>'
  ].join(''));

  var MessageView = Marionette.ItemView.extend({
    className: 'component',
    template: template,
    templateHelpers: {
      className: function(type) {
        switch (type) {
          case DialogModel.MessageTypes.Error:
            return 'alert-danger';
          case DialogModel.MessageTypes.Success:
            return 'alert-success';
          case DialogModel.MessageTypes.Warning:
            return 'alert-warning';
          default:
            return 'alert-info';
        }
      }
    },
    events: { 'click': 'close' }
  });

  return Marionette.CollectionView.extend({
    className: 'messages empty-page-header',
    itemView: MessageView
  });
});
<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserTypeResponseDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserTypeResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserTypeResponseDTO(1L, null, null), notNullValue());
    }

    @Test
    public void setters() {
        UserTypeResponseDTO userTypeResponseDTO = new UserTypeResponseDTO();
        userTypeResponseDTO.setId(null);
        userTypeResponseDTO.setNameEn(null);
        userTypeResponseDTO.setNameNo(null);
        assertThat(userTypeResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserTypeResponseDTO userTypeResponseDTO = new UserTypeResponseDTO();
        userTypeResponseDTO.getId();
        userTypeResponseDTO.getNameEn();
        userTypeResponseDTO.getNameNo();
        assertThat(userTypeResponseDTO, notNullValue());
    }

    @Test
    public void builder() {
        UserTypeResponseDTO userTypeResponseDTO = UserTypeResponseDTO.builder().build();
        assertThat(userTypeResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/xlsx/WorkoutItemTest.java
package com.osomapps.pt.xlsx;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutItemTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new WorkoutItem(0, 0, 0, null, null), notNullValue());
    }

    @Test
    public void tostring() {
        assertThat(new WorkoutItem(0, 0, 0, null, null).toString(), notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseResourceTest.java
package com.osomapps.pt.admin.exercise;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseResourceTest {

    @Mock private AdminExerciseService adminExerciseService;

    @InjectMocks private AdminExerciseResource adminExerciseResource;

    @Test
    public void findAll() {
        adminExerciseResource.findAll();
        verify(adminExerciseService).findAll();
    }

    @Test
    public void findOne() {
        adminExerciseResource.findOne(1L);
        verify(adminExerciseService).findOne(eq(1L));
    }

    @Test
    public void create() {
        adminExerciseResource.create(new ExerciseRequestDTO());
        verify(adminExerciseService).create(any(ExerciseRequestDTO.class));
    }

    @Test
    public void update() {
        adminExerciseResource.update(1L, new ExerciseRequestDTO());
        verify(adminExerciseService).update(eq(1L), any(ExerciseRequestDTO.class));
    }

    @Test
    public void delete() {
        adminExerciseResource.delete(1L);
        verify(adminExerciseService).delete(anyLong());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/AdminExerciseResource.java
package com.osomapps.pt.admin.exercise;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/exercise")
class AdminExerciseResource {

    private final AdminExerciseService exerciseService;

    @Autowired
    AdminExerciseResource(AdminExerciseService exerciseService) {
        this.exerciseService = exerciseService;
    }

    @GetMapping
    List<ExerciseResponseDTO> findAll() {
        return exerciseService.findAll();
    }

    @GetMapping(value = "{id}")
    ExerciseResponseDTO findOne(@PathVariable Long id) {
        return exerciseService.findOne(id);
    }

    @PostMapping
    ExerciseResponseDTO create(@RequestBody ExerciseRequestDTO exerciseRequestDTO) {
        return exerciseService.create(exerciseRequestDTO);
    }

    @PutMapping(value = "{id}")
    ExerciseResponseDTO update(
            @PathVariable Long id, @RequestBody ExerciseRequestDTO exerciseRequestDTO) {
        return exerciseService.update(id, exerciseRequestDTO);
    }

    @DeleteMapping(value = "{id}")
    ExerciseResponseDTO delete(@PathVariable Long id) {
        return exerciseService.delete(id);
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/UserWorkoutResponseDTO.java
package com.osomapps.pt.admin.user;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class UserWorkoutResponseDTO {
    Long id;
    String name;
    UserWarmupWorkoutItemResponseDTO warmup;
    List<UserWorkoutItemResponseDTO> items;
}
<file_sep>/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.osomapps.pt</groupId>
  <artifactId>pt-backend</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <!-- Add Spring Boot as a parent -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.14</version>
  </parent>

  <name>pt-backend</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- Spring Boot Starter-->
    <!-- No need to specify version because that's handled by parent -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>

    <!-- JPA Starter -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- PostgreSQL Database -->
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
    </dependency>

    <!-- FlyWay DB Migration -->
    <dependency>
      <groupId>org.flywaydb</groupId>
      <artifactId>flyway-core</artifactId>
    </dependency>

    <!-- Lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-java8</artifactId>
    </dependency>

    <dependency>
      <groupId>com.github.scribejava</groupId>
      <artifactId>scribejava-apis</artifactId>
      <version>3.2.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>4.1.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>4.1.1</version>
    </dependency>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>[24.1.1,)</version>
      <type>jar</type>
    </dependency>

    <!-- Devtools -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <optional>true</optional>
    </dependency>

    <!-- Testing -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <scope>test</scope>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <addResources>true</addResources>
        </configuration>
      </plugin>
      <plugin>
        <groupId>com.github.bringking</groupId>
        <artifactId>requirejs-maven-plugin</artifactId>
        <version>2.0.4</version>
        <executions>
          <execution>
            <id>admin</id>
            <phase>process-resources</phase>
            <goals>
              <goal>optimize</goal>
            </goals>
            <configuration>
                <configFile>
                    ${basedir}/src/main/config/buildconfig.admin.js
                </configFile>
                <!-- optional path to optimizer executable -->
                <optimizerFile>
                    ${basedir}/src/main/scripts/r.js
                </optimizerFile>
                <!--
                Whether or not to process configFile with maven filters.
                If you use this option, some options in your configFile
                must resolve to absolute paths (see below)
                -->
                <filterConfig>
                    true
                </filterConfig>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.lesscss</groupId>
        <artifactId>lesscss-maven-plugin</artifactId>
        <version>1.3.3</version>
        <configuration>
          <sourceDirectory>${project.basedir}/src/main/resources/static</sourceDirectory>
          <outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
          <compress>true</compress>
          <includes>
            <include>styles/admin.less</include>
          </includes>
        </configuration>
        <executions>
          <execution>
            <phase>process-resources</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.7</version>
        <executions>
          <execution>
            <phase>prepare-package</phase>
            <configuration>
              <target>
                <move file="${project.build.directory}/${project.build.finalName}/scripts/admin-app.js" tofile="${project.build.directory}/classes/static/public/admin-app.js"/>
                <move file="${project.build.directory}/${project.build.finalName}/scripts/admin-app.js.map" tofile="${project.build.directory}/classes/static/public/admin-app.js.map"/>
                <move file="${project.build.directory}/${project.build.finalName}/styles/admin.css" tofile="${project.build.directory}/classes/static/public/admin.css"/>
              </target>
              </configuration>
              <goals>
                <goal>run</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.6</version>
        <configuration>
          <excludes>
            <exclude>**/*.xlsx</exclude>
            <exclude>**/App.*</exclude>
          </excludes>
        </configuration>
        <executions>
          <execution>
            <id>prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
        <excludes>
          <exclude>**/node_modules/**/*</exclude>
          <exclude>**/target/**/*</exclude>
          <exclude>**/*.woff</exclude>
          <exclude>**/*.ttf</exclude>
          <exclude>**/*.xlsx</exclude>
        </excludes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
        <includes>
          <include>**/*.woff</include>
          <include>**/*.ttf</include>
          <include>**/*.xlsx</include>
        </includes>
      </resource>
    </resources>
  </build>
</project>
<file_sep>/src/main/resources/db/migration/V4.6__add_new_columns_for_in_workout_item_table.sql
ALTER TABLE ptcore.in_workout_item ADD COLUMN d_exercise_type VARCHAR(45);
ALTER TABLE ptcore.in_workout_item ADD COLUMN time_in_min INT;
ALTER TABLE ptcore.in_workout_item ADD COLUMN speed INT;
ALTER TABLE ptcore.in_workout_item ADD COLUMN resistance INT;

ALTER TABLE ptcore.in_workout_item_report ADD COLUMN time_in_min INT;
ALTER TABLE ptcore.in_workout_item_report ADD COLUMN speed INT;
ALTER TABLE ptcore.in_workout_item_report ADD COLUMN resistance INT;
<file_sep>/src/main/resources/db/migration/V4.60__create_parse_exercise_table.sql
CREATE TABLE ptcore.parse_exercise (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_program_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    exercise_id INT,
    exercise_name VARCHAR(50),
    user_group_1_percent INT NOT NULL DEFAULT 0,
    user_group_2_percent INT NOT NULL DEFAULT 0,
    user_group_3_percent INT NOT NULL DEFAULT 0,
    user_group_4_percent INT NOT NULL DEFAULT 0,
    basis_for_calculations VARCHAR(30),
    FOREIGN KEY (parse_program_id) REFERENCES ptcore.parse_program (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/resources/db/migration/V4.14__add_exercise_description_for_exercise_table.sql
ALTER TABLE ptcore.exercise ADD COLUMN d_exercise_description VARCHAR(45);<file_sep>/src/main/java/com/osomapps/pt/CustomErrorController.java
package com.osomapps.pt;

import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;

@RestController
class CustomErrorController implements ErrorController {

    private static final String PATH = "/error";

    @Value("${logging.level.org.springframework.web}")
    private String loggingLevel;

    @Autowired private ErrorAttributes errorAttributes;

    @RequestMapping(value = PATH)
    ErrorDTO error(WebRequest webRequest, HttpServletResponse response) {
        // Appropriate HTTP response code (e.g. 404 or 500) is automatically set by Spring.
        // Here we just define response body.
        return new ErrorDTO(response.getStatus(), getErrorAttributes(webRequest, loggingLevel));
    }

    public String getErrorPath() {
        return PATH;
    }

    private Map<String, Object> getErrorAttributes(WebRequest webRequest, String loggingLevel) {
        return errorAttributes.getErrorAttributes(webRequest, "DEBUG".equals(loggingLevel)
                ? ErrorAttributeOptions.of(ErrorAttributeOptions.Include.STACK_TRACE) : ErrorAttributeOptions.defaults());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseTypeServiceTest.java
package com.osomapps.pt.admin.exercise;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

import com.osomapps.pt.exercises.ExerciseType;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseTypeServiceTest {

    @Mock private ExerciseTypeRepository exerciseTypeRepository;
    @InjectMocks private AdminExerciseTypeService adminExerciseTypeService;

    @Test
    public void findAll() {
        when(exerciseTypeRepository.findAll()).thenReturn(Arrays.asList(new ExerciseType()));
        List<ExerciseTypeResponseDTO> responseDTOs = adminExerciseTypeService.findAll();
        assertThat(responseDTOs.size(), equalTo(1));
    }
}
<file_sep>/src/main/config/buildconfig.admin.js
({
    // see https://github.com/jrburke/r.js/blob/master/build/example.build.js
    // for an explanation of these fields

    baseUrl: '${basedir}/src/main/resources/static/scripts/',
    inlineText: true,
    useStrict: false,
    name: 'external/devhelpers/almond',
    include: ['main'],
    out: '${project.build.directory}/${project.build.finalName}/scripts/admin-app.js',
    insertRequire: ['main'],
    wrap: false,
    mainConfigFile: '${basedir}/src/main/resources/static/scripts/main.js',
    generateSourceMaps: true,
    preserveLicenseComments: false,
    logLevel: 0,
    stubModules: ['text', 'hbs'],
    optimize: 'uglify2'
})
<file_sep>/src/main/resources/db/migration/V4.50__add_errors_to_parse_goal_table.sql
ALTER TABLE ptcore.parse_goal ADD COLUMN errors VARCHAR(1000);
ALTER TABLE ptcore.parse_goal ADD COLUMN sheet_index INT NOT NULL DEFAULT 0;
<file_sep>/src/main/java/com/osomapps/pt/tokenemail/InUserEmail.java
package com.osomapps.pt.tokenemail;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.osomapps.pt.token.InUser;
import java.time.LocalDateTime;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "in_user_email", schema = "ptcore")
@DynamicInsert
public class InUserEmail {
    @Id
    @GenericGenerator(
            name = "InUserEmailIdSequence",
            strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
            parameters = {
                @Parameter(name = "sequence_name", value = "ptcore.in_user_email_id_seq"),
                @Parameter(name = "initial_value", value = "1"),
                @Parameter(name = "increment_size", value = "1")
            })
    @GeneratedValue(generator = "InUserEmailIdSequence")
    Long id;

    @ManyToOne
    @JoinColumn(name = "in_user_id")
    @JsonBackReference
    InUser inUser;

    LocalDateTime created;
    String login;
    String password;
    String user_name;
    String device_id;
    LocalDateTime confirmed;
    Boolean is_confirmed;

    @Column(name = "confirm_token")
    String confirmToken = "em-" + UUID.randomUUID().toString().replace("-", "");

    LocalDateTime reseted;
    Boolean is_reseted;

    @Column(name = "reset_token")
    String resetToken;
}
<file_sep>/src/main/resources/static/jshint.sh
npm install && grunt jshint && rm -r node_modules
<file_sep>/src/main/java/com/osomapps/pt/token/TokenResource.java
package com.osomapps.pt.token;

import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/token")
class TokenResource {

    private final TokenService tokenService;

    @Autowired
    TokenResource(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    @GetMapping
    List<InUser> list() {
        return Collections.emptyList();
    }

    @PostMapping
    TokenResponseDTO create(@RequestBody TokenRequestDTO tokenRequest, HttpServletRequest request) {
        return tokenService.createOrReadNewToken(tokenRequest, request.getRemoteAddr());
    }

    @DeleteMapping
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    void delete(@RequestHeader(value = "X-Token") String token, HttpServletRequest request) {
        tokenService.deleteToken(token, request.getRemoteAddr());
    }
}
<file_sep>/src/main/resources/db/migration/V4.62__update_goal_parameter_table.sql
TRUNCATE TABLE ptcore.goal_parameter CASCADE;

INSERT INTO ptcore.goal_parameter(id, name) VALUES
(1, 'current-weight'),
(2, 'goal-weight'),
(3, 'distance');

SELECT setval('ptcore.goal_parameter_id_seq', (select max(id) from ptcore.goal_parameter) + 1, true);
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExerciseFilePreviewRepository.java
package com.osomapps.pt.exercises;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ExerciseFilePreviewRepository extends JpaRepository<ExerciseFilePreview, Long> {}
<file_sep>/src/main/resources/db/migration/V4.36__create_workout_item_set_report_table.sql
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN sets;
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN repetitions;
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN weight;
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN bodyweight;
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN time_in_min;
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN speed;
ALTER TABLE ptcore.in_workout_item_report DROP COLUMN resistance;

CREATE TABLE ptcore.in_workout_item_set_report (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_workout_item_report_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    repetitions INT,
    weight INT,
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    time_in_min INT,
    speed INT,
    incline INT,
    resistance INT,
    FOREIGN KEY (in_workout_item_report_id) REFERENCES ptcore.in_workout_item_report (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/test/java/com/osomapps/pt/reportworkout/WorkoutItemReportRequestDTOTest.java
package com.osomapps.pt.reportworkout;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutItemReportRequestDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new WorkoutItemReportRequestDTO(1L, null), notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.48__add_reseted_and_reset_token_to_in_user_email_table.sql
ALTER TABLE ptcore.in_user_email ADD COLUMN reseted TIMESTAMP WITHOUT TIME ZONE;
ALTER TABLE ptcore.in_user_email ADD COLUMN is_reseted BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE ptcore.in_user_email ADD COLUMN reset_token VARCHAR(35) NOT NULL DEFAULT '';
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserProgramServiceTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InProgramRepository;
import com.osomapps.pt.programs.InWarmupWorkoutItem;
import com.osomapps.pt.programs.InWorkout;
import com.osomapps.pt.programs.InWorkoutItem;
import com.osomapps.pt.programs.InWorkoutItemReport;
import com.osomapps.pt.programs.InWorkoutItemSet;
import com.osomapps.pt.programs.InWorkoutItemSetReport;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminUserProgramServiceTest {

    @Mock private InProgramRepository inProgramRepository;

    @InjectMocks private AdminUserProgramService adminUserProgramService;

    private InProgram getInProgram() {
        return new InProgram()
                .setInWorkouts(
                        Arrays.asList(
                                new InWorkout()
                                        .setInWarmupWorkoutItems(
                                                Arrays.asList(new InWarmupWorkoutItem()))
                                        .setInWorkoutItems(
                                                Arrays.asList(
                                                        new InWorkoutItem()
                                                                .setInWorkoutItemSets(
                                                                        Arrays.asList(
                                                                                new InWorkoutItemSet()))
                                                                .setInWorkoutItemReports(
                                                                        Arrays.asList(
                                                                                new InWorkoutItemReport()
                                                                                .setInWorkoutItemSetReports(
                                                                                Arrays
                                                                                .asList(
                                                                                new InWorkoutItemSetReport()))))))));
    }

    @Test
    public void findAll() {
        when(inProgramRepository.findAll()).thenReturn(Arrays.asList(getInProgram()));
        List<UserProgramResponseDTO> responseDTOs = adminUserProgramService.findAll();
        assertThat(responseDTOs.size(), equalTo(1));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void findOne_not_found() {
        adminUserProgramService.findOne(1L);
    }

    @Test
    public void findOne() {
        when(inProgramRepository.findById(eq(1L))).thenReturn(Optional.of(getInProgram()));
        UserProgramResponseDTO responseDTO = adminUserProgramService.findOne(1L);
        assertThat(responseDTO, notNullValue());
    }

    @Test
    public void create() {
        when(inProgramRepository.save(any(InProgram.class))).thenAnswer(i -> i.getArguments()[0]);
        UserProgramResponseDTO responseDTO =
                adminUserProgramService.create(
                        new UserProgramRequestDTO()
                                .setName("name")
                                .setWorkouts(
                                        Arrays.asList(
                                                new UserWorkoutRequestDTO()
                                                        .setItems(
                                                                Arrays.asList(
                                                                        new UserWorkoutItemRequestDTO()
                                                                                .setSets(
                                                                                Arrays
                                                                                .asList(
                                                                                new UserWorkoutItemSetRequestDTO())))))));
        assertThat(responseDTO, notNullValue());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void update_not_found() {
        adminUserProgramService.update(1L, new UserProgramRequestDTO());
    }

    @Test
    public void update() {
        when(inProgramRepository.findById(eq(1L))).thenReturn(Optional.of(getInProgram()));
        UserProgramResponseDTO responseDTO =
                adminUserProgramService.update(
                        1L,
                        new UserProgramRequestDTO()
                                .setName("name")
                                .setWorkouts(
                                        Arrays.asList(
                                                new UserWorkoutRequestDTO()
                                                        .setItems(
                                                                Arrays.asList(
                                                                        new UserWorkoutItemRequestDTO())))));
        assertThat(responseDTO, notNullValue());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void delete_not_found() {
        adminUserProgramService.delete(1L);
    }

    @Test
    public void delete() {
        when(inProgramRepository.findById(eq(1L))).thenReturn(Optional.of(getInProgram()));
        UserProgramResponseDTO responseDTO = adminUserProgramService.delete(1L);
        assertThat(responseDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/package-info.java
/**
 *
 *
 * <h1>Administrator user endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides user services
 * </ul>
 */
package com.osomapps.pt.admin.user;
<file_sep>/src/test/java/com/osomapps/pt/goals/GoalParameterTest.java
package com.osomapps.pt.goals;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class GoalParameterTest {
    @Test
    public void createAllArgs() {
        assertThat(new GoalParameter(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        GoalParameter goalParameter = new GoalParameter();
        goalParameter.setId(null);
        goalParameter.setCreated(null);
        goalParameter.setGoals(null);
        assertThat(goalParameter, notNullValue());
    }

    @Test
    public void getters() {
        GoalParameter goalParameter = new GoalParameter();
        goalParameter.getId();
        goalParameter.getCreated();
        goalParameter.getGoals();
        assertThat(goalParameter, notNullValue());
    }
}
<file_sep>/src/main/resources/static/styles/exercises.less
@height100pxInEm: 7.1429em;

.selectedId {
  background-color: aliceblue;
}

.empty-description {
  background-color: #e0e0e0;
}

.table {
    .preview-content {
        height: @height100pxInEm;
    }
}
<file_sep>/src/main/resources/db/migration/V4.30__create_exercise_type_table.sql
DROP TABLE ptcore.exercise_type CASCADE;
CREATE TABLE ptcore.exercise_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50)
);

INSERT INTO ptcore.exercise_type (name) VALUES
('OnTime'),
('OnRepetitions'),
('OnMaxWeight'),
('OnDistance');

ALTER TABLE ptcore.exercise ADD COLUMN exercise_type_id BIGINT;

ALTER TABLE ptcore.exercise ADD CONSTRAINT exercise_exercise_type_id_fkey FOREIGN KEY
 (exercise_type_id) REFERENCES ptcore.exercise_type (id) ON UPDATE CASCADE ON DELETE CASCADE;
<file_sep>/src/main/java/com/osomapps/pt/activecertificate/ActiveCertificateResponseDTO.java
package com.osomapps.pt.activecertificate;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.LocalDate;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Builder
class ActiveCertificateResponseDTO {
    Long id;
    String code;

    @JsonSerialize(using = LocalDateSerializer.class)
    LocalDate expiration_date;
}
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/UserSignupRequestDTOTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserSignupRequestDTOTest {

    @Test
    public void allArgsConstructor() {
        assertThat(new UserSignupRequestDTO(null, null, null), notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/program/ParseWarmupWorkoutItemDTO.java
package com.osomapps.pt.admin.program;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Builder
class ParseWarmupWorkoutItemDTO {
    Long id;
    String name;
    Integer speed;
    Integer incline;
    Float time_in_min;
}
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExerciseFileRepository.java
package com.osomapps.pt.exercises;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ExerciseFileRepository extends JpaRepository<ExerciseFile, Long> {}
<file_sep>/src/main/resources/db/migration/V3.3__add_user_id_user_name_and_picture_url_for_in_user_facebook.sql
TRUNCATE TABLE ptcore.in_user_facebook;
ALTER TABLE ptcore.in_user_facebook ADD COLUMN user_name VARCHAR(100) NOT NULL;
ALTER TABLE ptcore.in_user_facebook ADD COLUMN user_id VARCHAR(100) NOT NULL;
ALTER TABLE ptcore.in_user_facebook ADD COLUMN picture_url VARCHAR(200) NULL;

CREATE INDEX facebook_user_id_index ON ptcore.in_user_facebook (user_id);
<file_sep>/src/main/java/com/osomapps/pt/xlsx/ExcelGoal.java
package com.osomapps.pt.xlsx;

import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@ToString
public class ExcelGoal {
    String name;
    int sheetIndex;
    Integer loops;
    List<UserGroup> userGroups = new ArrayList<>();
    List<String> errors = new ArrayList<>();
}
<file_sep>/src/test/java/com/osomapps/pt/programs/WorkoutItemResponseDTOTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutItemResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new WorkoutItemResponseDTO(1L, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        WorkoutItemResponseDTO workoutItemResponseDTO =
                new WorkoutItemResponseDTO()
                        .setId(null)
                        .setExercise_id(null)
                        .setExercise_name(null)
                        .setExercise_type(null)
                        .setSets(null);
        assertThat(workoutItemResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        WorkoutItemResponseDTO workoutItemResponseDTO = new WorkoutItemResponseDTO();
        workoutItemResponseDTO.getId();
        workoutItemResponseDTO.getExercise_id();
        workoutItemResponseDTO.getExercise_name();
        workoutItemResponseDTO.getExercise_type();
        workoutItemResponseDTO.getSets();
        assertThat(workoutItemResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/auth/CustomUserDetailsTest.java
package com.osomapps.pt.auth;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import com.osomapps.pt.admin.ptuser.PtUser;
import org.junit.Test;

public class CustomUserDetailsTest {

    @Test
    public void getters() {
        CustomUserDetails customUserDetails =
                new CustomUserDetails(new PtUser().setIs_deleted(Boolean.FALSE));
        customUserDetails.getAuthorities();
        customUserDetails.getPassword();
        customUserDetails.getUsername();
        customUserDetails.isAccountNonExpired();
        customUserDetails.isAccountNonLocked();
        customUserDetails.isCredentialsNonExpired();
        customUserDetails.isEnabled();
        assertThat(customUserDetails, notNullValue());
        new CustomUserDetails(new PtUser().setIs_deleted(Boolean.TRUE)).isEnabled();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExerciseFileTest.java
package com.osomapps.pt.exercises;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseFileTest {
    @Test
    public void createAllArgs() {
        assertThat(new ExerciseFile(1L, null, null, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ExerciseFile exerciseFile = new ExerciseFile();
        exerciseFile.setId(null);
        exerciseFile.setCreated(null);
        exerciseFile.setExercises(null);
        assertThat(exerciseFile, notNullValue());
    }

    @Test
    public void getters() {
        ExerciseFile exerciseFile = new ExerciseFile();
        exerciseFile.getId();
        exerciseFile.getCreated();
        exerciseFile.getExercises();
        assertThat(exerciseFile, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseEquipmentTypeResourceTest.java
package com.osomapps.pt.admin.exercise;

import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseEquipmentTypeResourceTest {

    @Mock private AdminExerciseEquipmentTypeService adminExerciseEquipmentTypeService;

    @InjectMocks private AdminExerciseEquipmentTypeResource adminExerciseEquipmentTypeResource;

    @Test
    public void findAll() {
        adminExerciseEquipmentTypeResource.findAll();
        verify(adminExerciseEquipmentTypeService).findAll();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/goal/AdminGoalServiceTest.java
package com.osomapps.pt.admin.goal;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.goals.Goal;
import com.osomapps.pt.goals.GoalParameter;
import com.osomapps.pt.goals.GoalParameterRepository;
import com.osomapps.pt.goals.GoalRepository;
import com.osomapps.pt.goals.GoalType;
import com.osomapps.pt.goals.GoalTypeRepository;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Sort;

@RunWith(MockitoJUnitRunner.class)
public class AdminGoalServiceTest {

    @Mock private GoalRepository goalRepository;
    @Mock private GoalParameterRepository goalParameterRepository;
    @Mock private DictionaryService dictionaryService;
    @Mock private GoalTypeRepository goalTypeRepository;

    @InjectMocks private AdminGoalService adminGoalService;

    @Test
    public void findAll() {
        when(goalRepository.findAll(any(Sort.class)))
                .thenReturn(
                        Arrays.asList(
                                new Goal().setGoalParameters(Arrays.asList(new GoalParameter()))));
        List<GoalResponseDTO> goalResponseDTOs = adminGoalService.findAll();
        assertThat(goalResponseDTOs.size(), equalTo(1));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void findOne_not_found() {
        when(goalRepository.findById(eq(1L))).thenReturn(Optional.empty());
        adminGoalService.findOne(1L);
    }

    @Test
    public void findOne() {
        when(goalRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new Goal()
                                        .setGoalParameters(Arrays.asList(new GoalParameter()))
                                        .setGoalType(new GoalType())));
        GoalResponseDTO goalResponseDTO = adminGoalService.findOne(1L);
        assertThat(goalResponseDTO, notNullValue());
    }

    @Test
    public void create() {
        when(goalRepository.save((Goal) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        GoalResponseDTO goalResponseDTO =
                adminGoalService.create(
                        new GoalRequestDTO()
                                .setParameters(Arrays.asList(new GoalParameterRequestDTO()))
                                .setType(new GoalTypeRequestDTO().setId(1L)));
        assertThat(goalResponseDTO, notNullValue());
    }

    @Test
    public void create_type_is_null() {
        when(goalRepository.save((Goal) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        GoalResponseDTO goalResponseDTO =
                adminGoalService.create(
                        new GoalRequestDTO()
                                .setParameters(Arrays.asList(new GoalParameterRequestDTO()))
                                .setType(new GoalTypeRequestDTO()));
        assertThat(goalResponseDTO, notNullValue());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void update_not_found() {
        adminGoalService.update(
                1L,
                new GoalRequestDTO().setParameters(Arrays.asList(new GoalParameterRequestDTO())));
    }

    @Test
    public void update() {
        when(goalRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new Goal().setGoalParameters(Arrays.asList(new GoalParameter()))));
        when(goalRepository.save((Goal) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        GoalResponseDTO goalResponseDTO =
                adminGoalService.update(
                        1L,
                        new GoalRequestDTO()
                                .setParameters(Arrays.asList(new GoalParameterRequestDTO()))
                                .setType(new GoalTypeRequestDTO().setId(1L)));
        assertThat(goalResponseDTO, notNullValue());
    }

    @Test
    public void update_type_is_null() {
        when(goalRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new Goal().setGoalParameters(Arrays.asList(new GoalParameter()))));
        when(goalRepository.save((Goal) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        GoalResponseDTO goalResponseDTO =
                adminGoalService.update(
                        1L,
                        new GoalRequestDTO()
                                .setParameters(Arrays.asList(new GoalParameterRequestDTO()))
                                .setType(new GoalTypeRequestDTO()));
        assertThat(goalResponseDTO, notNullValue());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void delete_not_found() {
        adminGoalService.delete(1L);
    }

    @Test
    public void delete() {
        when(goalRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new Goal().setGoalParameters(Arrays.asList(new GoalParameter()))));
        GoalResponseDTO goalResponseDTO = adminGoalService.delete(1L);
        assertThat(goalResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.56__add_on_intervals_exercise_type.sql
INSERT INTO ptcore.exercise_type (name) VALUES
('OnIntervals');
<file_sep>/src/main/resources/db/migration/V4.25__rename_exercise_category_to_the_exercise_body_part_table.sql
CREATE TABLE ptcore.exercise_bodypart (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_bodypart_name VARCHAR(45)
);

INSERT INTO ptcore.exercise_bodypart
   (
      SELECT id,
             created,
             d_exercise_category_name
        FROM ptcore.exercise_category
   );

UPDATE ptcore.dictionary_data SET dname = 'exercise_bodypart_name' WHERE dname = 'exercise_category_name';

ALTER TABLE ptcore.exercise RENAME COLUMN exercise_category_id TO exercise_bodypart_id;

ALTER TABLE ONLY ptcore.exercise DROP CONSTRAINT exercise_exercise_category_id_fkey;

ALTER TABLE ptcore.exercise ADD CONSTRAINT exercise_exercise_bodypart_id_fkey FOREIGN KEY
 (exercise_bodypart_id) REFERENCES ptcore.exercise_bodypart (id) ON UPDATE CASCADE ON DELETE CASCADE;

DROP TABLE IF EXISTS ptcore.exercise_category;
<file_sep>/src/main/java/com/osomapps/pt/admin/ptuser/PtRoleRepository.java
package com.osomapps.pt.admin.ptuser;

import org.springframework.data.jpa.repository.JpaRepository;

interface PtRoleRepository extends JpaRepository<PtRole, Long> {}
<file_sep>/src/main/resources/static/scripts/views/login.js
/*jshint browser: true*/
/*global define*/
define([
  'underscore',
  'marionette'
],
function(_, Marionette) {
  'use strict';

  var template = _.template([
    '<div class="page-header app-header">',
      '<h1><span>pt admin</span></h1>',
    '</div>',
    '<form method="post" class="form-signin">',
    '<div class="alert alert-danger js-wrongpass" style="display:none">',
    ' <span class="glyphicon glyphicon-exclamation-sign"></span>',
    '  Feil brukernavn eller passord.',
    '</div>',
    '<div class="form-group">',
    '  <input type="text" class="form-control" name="username" placeholder="username" autofocus="">',
    '</div>',
    '<div class="form-group">',
    '  <input type="<PASSWORD>" class="form-control" name="password" placeholder="<PASSWORD>">',
    '</div>',
    '<button class="btn btn-lg btn-primary btn-block ladda-button js-login" data-style="zoom-out">',
    '  <span class="ladda-label">sign in</span>',
    '  <span class="ladda-spinner"></span>',
    '</button>',
    '</form>'
  ].join(''));

  return Marionette.ItemView.extend({

    template: template,

    events: { 'click .js-login': 'login' },
    modelEvents: {
      'credentials:invalid': 'unauthenticated',
      'sync': 'render'
    },

    login: function (event) {
      event.preventDefault();
      this.$('.js-wrongpass').slideUp(100);

      var username = _.escape(this.$('input[name=username]').val());
      var password = _.escape(this.$('input[name=password]').val());

      this.model.login(username, password);
    },
    unauthenticated: function () {
      this.$('.js-wrongpass').slideDown(100);
      this.$('input[name=username]').focus();
    }
  });

});
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/SendEmailServiceTest.java
package com.osomapps.pt.tokenemail;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.dictionary.DictionaryName;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.email.EmailMessageTemplate;
import com.osomapps.pt.email.EmailMessageType;
import com.osomapps.pt.email.EmailMessageTypeRepository;
import com.osomapps.pt.token.InUser;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;

@RunWith(MockitoJUnitRunner.class)
public class SendEmailServiceTest {

    @Mock private MailSender mailSender;
    @Mock private EmailMessageTypeRepository emailMessageTypeRepository;
    @Mock private DictionaryService dictionaryService;

    @InjectMocks private SendEmailService sendEmailService;

    @Test
    public void send_error() {
        doThrow(new MailException("") {}).when(mailSender).send(any(SimpleMailMessage.class));
        sendEmailService.send(new InUserEmail().setInUser(new InUser().setId(1L)));
        verify(mailSender).send(any(SimpleMailMessage.class));
    }

    @Test
    public void send() {
        sendEmailService.send(new InUserEmail().setInUser(new InUser().setId(1L)));
        verify(mailSender).send(any(SimpleMailMessage.class));
    }

    @Test
    public void send_with_template() {
        when(emailMessageTypeRepository.findByNameOrderByIdDesc(eq("WelcomeMessage")))
                .thenReturn(
                        Arrays.asList(
                                new EmailMessageType()
                                        .setEmailMessageTemplates(
                                                Arrays.asList(new EmailMessageTemplate()))));
        when(dictionaryService.getEnValue(any(DictionaryName.class), isNull(), anyString()))
                .thenReturn("test");
        sendEmailService.send(new InUserEmail().setInUser(new InUser().setId(1L)));
        verify(mailSender).send(any(SimpleMailMessage.class));
    }

    @Test
    public void sendForgotPassword_error() {
        doThrow(new MailException("") {}).when(mailSender).send(any(SimpleMailMessage.class));
        sendEmailService.sendForgotPassword(new InUserEmail().setInUser(new InUser().setId(1L)));
        verify(mailSender).send(any(SimpleMailMessage.class));
    }

    @Test
    public void sendForgotPassword() {
        sendEmailService.sendForgotPassword(new InUserEmail().setInUser(new InUser().setId(1L)));
        verify(mailSender).send(any(SimpleMailMessage.class));
    }

    @Test
    public void sendForgotPassword_with_template() {
        when(emailMessageTypeRepository.findByNameOrderByIdDesc(eq("ForgetPasswordMessage")))
                .thenReturn(
                        Arrays.asList(
                                new EmailMessageType()
                                        .setEmailMessageTemplates(
                                                Arrays.asList(new EmailMessageTemplate()))));
        when(dictionaryService.getEnValue(any(DictionaryName.class), isNull(), anyString()))
                .thenReturn("test");
        sendEmailService.sendForgotPassword(new InUserEmail().setInUser(new InUser().setId(1L)));
        verify(mailSender).send(any(SimpleMailMessage.class));
    }
}
<file_sep>/Procfile

web: java -Dserver.port=$PORT $JAVA_OPTS -Dspring.profiles.active=$PROFILE -jar target/*.jar
<file_sep>/run.sh
#!/usr/bin/env bash
# Start spring-boot with local properties
mvn spring-boot:run -Drun.jvmArguments='-Dspring.config.location=classpath:/application-local.properties'

<file_sep>/src/main/resources/static/scripts/appsetup.js
/*jshint browser: true*/
/*global define*/
define([
  'app',
  'routers/app',
  'controllers/app',
  // Include initializers which register themselves on the App object.
  'initializers'
],
function(App, AppRouter, AppController) {
    'use strict';

    App.appController = new AppController();

    App.appRouter = new AppRouter({
      controller: App.appController
    });

    // When `start()` is called, App initializers are run in registered order.
    App.start();

});
<file_sep>/src/test/java/com/osomapps/pt/admin/goal/GoalTypeResponseDTOTest.java
package com.osomapps.pt.admin.goal;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class GoalTypeResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new GoalTypeResponseDTO(1L, null), notNullValue());
    }

    @Test
    public void setters() {
        GoalTypeResponseDTO goalTypeResponseDTO = new GoalTypeResponseDTO();
        goalTypeResponseDTO.setId(null);
        goalTypeResponseDTO.setName(null);
        assertThat(goalTypeResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        GoalTypeResponseDTO goalTypeResponseDTO = new GoalTypeResponseDTO();
        goalTypeResponseDTO.getId();
        goalTypeResponseDTO.getName();
        assertThat(goalTypeResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/goals/GoalTypeRepository.java
package com.osomapps.pt.goals;

import org.springframework.data.jpa.repository.JpaRepository;

public interface GoalTypeRepository extends JpaRepository<GoalType, Long> {}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/ExerciseInputRepository.java
package com.osomapps.pt.admin.exercise;

import com.osomapps.pt.exercises.ExerciseInput;
import org.springframework.data.jpa.repository.JpaRepository;

interface ExerciseInputRepository extends JpaRepository<ExerciseInput, Long> {}
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExercisesResource.java
package com.osomapps.pt.exercises;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/exercises")
class ExercisesResource {

    private final ExerciseService exerciseService;

    @Autowired
    ExercisesResource(ExerciseService exerciseService) {
        this.exerciseService = exerciseService;
    }

    @GetMapping
    List<ExerciseDTO> findAll() {
        return exerciseService.findAll();
    }
}
<file_sep>/src/main/java/com/osomapps/pt/programs/InProgram.java
package com.osomapps.pt.programs;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.osomapps.pt.token.InUser;
import java.time.LocalDateTime;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "in_program", schema = "ptcore")
@DynamicInsert
public class InProgram {
    @Id
    @GenericGenerator(
            name = "InProgramIdSequence",
            strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
            parameters = {
                @Parameter(name = "sequence_name", value = "ptcore.in_program_id_seq"),
                @Parameter(name = "initial_value", value = "1"),
                @Parameter(name = "increment_size", value = "1")
            })
    @GeneratedValue(generator = "InProgramIdSequence")
    Long id;

    LocalDateTime created;
    String name;
    String d_program_type;
    Integer current_workout_index;

    @ManyToOne
    @JoinColumn(name = "in_user_id")
    @JsonBackReference
    InUser inUser;

    @OneToMany(mappedBy = "inProgram")
    List<InWorkout> inWorkouts;
}
<file_sep>/src/main/resources/static/scripts/models/emails.js
/*jshint browser: true*/
/*global define*/
define([
    'jquery',
    'underscore',
    'backbone'
  ],
  function ($, _, Backbone) {
    'use strict';

    var Email = Backbone.Model.extend({
      defaults: {
        'id': null,
        'emailSubjectEn': null,
        'emailSubjectNo': null,
        'emailTextEn': null,
        'emailTextNo': null,
        'type': {
          'id' : null
        }
      },
      url: function() {
        return '/api/v1/admin/email-message-template' + (this.isNew() ? '' : '/' + this.get('id'));
      },
      validate: function (attrs) {
        var errors = [];
        if (_.isNull(attrs.emailSubjectEn) || _.isEmpty($.trim(attrs.emailSubjectEn))) {
          errors.push({name: 'emailSubjectEn', message: 'Please fill email subject in English field.'});
        } else if (_.isNull(attrs.emailSubjectNo) || _.isEmpty($.trim(attrs.emailSubjectNo))) {
          errors.push({name: 'emailSubjectNo', message: 'Please fill email subject in Norwegian field.'});
        } else if (_.isNull(attrs.emailTextEn) || _.isEmpty($.trim(attrs.emailTextEn))) {
          errors.push({name: 'emailTextEn', message: 'Please fill email text in English field.'});
        } else if (_.isNull(attrs.emailTextNo) || _.isEmpty($.trim(attrs.emailTextNo))) {
          errors.push({name: 'emailTextNo', message: 'Please fill email text in Norwegian field.'});
        }
        return errors.length > 0 ? errors : false;
      }
    });

    var Emails = Backbone.Collection.extend({
      model: Email,
      initialize: function (models, options) {
      },
      url: '/api/v1/admin/email-message-template'
    });

    return {
      Email: Email,
      Emails: Emails
    };
  });
<file_sep>/src/main/resources/db/migration/V4.57__improve_goal_tables.sql
DELETE FROM ptcore.goal WHERE d_goal_title = '80' and d_goal_title_2 IS NULL;
<file_sep>/src/test/java/com/osomapps/pt/programs/ParseUserGroupTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class ParseUserGroupTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ParseUserGroup(1L, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ParseUserGroup parseUserGroup = new ParseUserGroup();
        parseUserGroup.setCreated(LocalDateTime.MAX);
        parseUserGroup.setParseGoal(null);
        assertThat(parseUserGroup, notNullValue());
    }

    @Test
    public void getters() {
        ParseUserGroup parseUserGroup = new ParseUserGroup();
        parseUserGroup.getCreated();
        parseUserGroup.getParseGoal();
        assertThat(parseUserGroup, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/reportphoto/ReportPhotoFileResourceTest.java
package com.osomapps.pt.reportphoto;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.OutputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletResponse;

@RunWith(MockitoJUnitRunner.class)
public class ReportPhotoFileResourceTest {

    @Mock private ReportPhotoFileService reportPhotoFileService;

    @InjectMocks private ReportPhotoFileResource reportPhotoFileResource;

    @Test
    public void findOne() throws Exception {
        when(reportPhotoFileService.findOne(eq("1"), eq(1L), eq(""), any(OutputStream.class)))
                .thenReturn(new ReportPhotoFileDTO());
        reportPhotoFileResource.findOne("1", 1L, "", new MockHttpServletResponse());
        verify(reportPhotoFileService).findOne(eq("1"), eq(1L), eq(""), any(OutputStream.class));
    }

    @Test(expected = IOException.class)
    public void findOne_with_error() throws Exception {
        when(reportPhotoFileService.findOne(eq("1"), eq(1L), eq(""), any(OutputStream.class)))
                .thenThrow(new IOException());
        reportPhotoFileResource.findOne("1", 1L, "", new MockHttpServletResponse());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/xlsx/Workout.java
package com.osomapps.pt.xlsx;

import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@ToString
public class Workout {
    String name;
    int columnIndex;
    int rowIndex;
    WarmupWorkoutItem warmup;
    List<WorkoutItem> workoutItems = new ArrayList<>();
}
<file_sep>/src/test/java/com/osomapps/pt/token/UserResponseDTOTest.java
package com.osomapps.pt.token;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(
                new UserResponseDTO(1L, "", "", "", "", "", 1L, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        UserResponseDTO userResponseDTO =
                new UserResponseDTO()
                        .setId(1L)
                        .setName("")
                        .setEmail("")
                        .setAvatar("")
                        .setAvatar_dataurl("")
                        .setGender("")
                        .setAge(1L)
                        .setBirthday(null)
                        .setLevel(null)
                        .setGoals(null)
                        .setHeight(null)
                        .setWeight(null);
        assertThat(userResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserResponseDTO userResponseDTO = new UserResponseDTO();
        userResponseDTO.getId();
        userResponseDTO.getName();
        userResponseDTO.getEmail();
        userResponseDTO.getAvatar();
        userResponseDTO.getAvatar_dataurl();
        userResponseDTO.getGender();
        userResponseDTO.getAge();
        userResponseDTO.getBirthday();
        userResponseDTO.getLevel();
        userResponseDTO.getGoals();
        userResponseDTO.getHeight();
        userResponseDTO.getWeight();
        assertThat(userResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExerciseRepository.java
package com.osomapps.pt.exercises;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ExerciseRepository extends JpaRepository<Exercise, Long> {

    List<Exercise> findByExerciseId(Integer exerciseId);
}
<file_sep>/src/main/java/com/osomapps/pt/programs/InProgramRepository.java
package com.osomapps.pt.programs;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface InProgramRepository extends JpaRepository<InProgram, Long> {}
<file_sep>/src/main/resources/static/scripts/app.js
/*jshint browser: true*/
/*global define*/
define([
  'underscore',
  'backbone',
  'marionette'
],
function (_, Backbone, Marionette) {
  'use strict';

  // Curly bracket notation in _ templates, eg {{ name }} and
  // {%foo(name) %}
  _.templateSettings = {
    evaluate: /\{\%([\s\S]+?)\%\}/g,
    interpolate: /\{\{([\s\S]+?)\}\}/g,
    escape: /\{\{-(.+?)\}\}/g
  };

  var App = new Marionette.Application();

  App.addRegions({
    mainRegion: '#main',
    headerRegion: '#header'
  });

  return App;

});
<file_sep>/src/main/resources/db/migration/V4.47__add_confirmed_and_confirmed_token_to_in_user_email_table.sql
ALTER TABLE ptcore.in_user_email ADD COLUMN confirmed TIMESTAMP WITHOUT TIME ZONE;
ALTER TABLE ptcore.in_user_email ADD COLUMN is_confirmed BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE ptcore.in_user_email ADD COLUMN confirm_token VARCHAR(35) NOT NULL DEFAULT '';
<file_sep>/src/test/java/com/osomapps/pt/admin/goal/GoalResponseDTOTest.java
package com.osomapps.pt.admin.goal;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class GoalResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new GoalResponseDTO(1L, null, null, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        GoalResponseDTO goalResponseDTO = new GoalResponseDTO();
        goalResponseDTO.setId(null);
        goalResponseDTO.setTitleEn(null);
        goalResponseDTO.setTitleNo(null);
        goalResponseDTO.setTitle2En(null);
        goalResponseDTO.setTitle2No(null);
        goalResponseDTO.setParameters(null);
        goalResponseDTO.setType(null);
        assertThat(goalResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        GoalResponseDTO goalResponseDTO = new GoalResponseDTO();
        goalResponseDTO.getId();
        goalResponseDTO.getTitleEn();
        goalResponseDTO.getTitleNo();
        goalResponseDTO.getTitle2En();
        goalResponseDTO.getTitle2No();
        goalResponseDTO.getParameters();
        goalResponseDTO.getType();
        assertThat(goalResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.18__create_parse_workout_table.sql
CREATE TABLE ptcore.parse_workout (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    column_index INT NOT NULL DEFAULT 0,
    row_index INT NOT NULL DEFAULT 0,
    FOREIGN KEY (parse_user_id) REFERENCES ptcore.parse_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_warmup_workout_item (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_workout_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    speed INT,
    incline INT,
    time_in_min INT,
    FOREIGN KEY (parse_workout_id) REFERENCES ptcore.parse_workout (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_workout_item (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_workout_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    sets INT,
    repetitions INT,
    weight INT,
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    time_in_min INT,
    speed INT,
    resistance INT,
    FOREIGN KEY (parse_workout_id) REFERENCES ptcore.parse_workout (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/test/java/com/osomapps/pt/goals/GoalDTOTest.java
package com.osomapps.pt.goals;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class GoalDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new GoalDTO(1L, null, null, null, null), notNullValue());
    }

    @Test
    public void createNoArgs() {
        assertThat(new GoalDTO(), notNullValue());
    }

    @Test
    public void setters() {
        GoalDTO goalDTO = new GoalDTO();
        goalDTO.setId(1L);
        goalDTO.setTitle(null);
        goalDTO.setTitle2(null);
        goalDTO.setParameters(null);
        goalDTO.setType(null);
        assertThat(goalDTO, notNullValue());
    }

    @Test
    public void getters() {
        GoalDTO goalDTO = new GoalDTO();
        goalDTO.getId();
        goalDTO.getTitle();
        goalDTO.getTitle2();
        goalDTO.getParameters();
        goalDTO.getType();
        assertThat(goalDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.58__rename_time_in_min_to_the_time_in_sec.sql
ALTER TABLE ptcore.in_warmup_workout_item RENAME COLUMN time_in_min TO time_in_sec;
ALTER TABLE ptcore.in_workout_item_set RENAME COLUMN time_in_min TO time_in_sec;
ALTER TABLE ptcore.in_workout_item_set_report RENAME COLUMN time_in_min TO time_in_sec;
ALTER TABLE ptcore.parse_warmup_workout_item RENAME COLUMN time_in_min TO time_in_sec;
ALTER TABLE ptcore.parse_workout_item_set RENAME COLUMN time_in_min TO time_in_sec;
<file_sep>/src/main/java/com/osomapps/pt/admin/certificate/package-info.java
/**
 *
 *
 * <h1>Administrator certificate endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides certificate services
 * </ul>
 */
package com.osomapps.pt.admin.certificate;
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExercisesImageResourceTest.java
package com.osomapps.pt.exercises;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.OutputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletResponse;

@RunWith(MockitoJUnitRunner.class)
public class ExercisesImageResourceTest {

    @Mock private ExerciseImageService exerciseImageService;

    @InjectMocks private ExercisesImageResource exercisesImageResource;

    @Test
    public void findOne() throws Exception {
        when(exerciseImageService.findOne(eq(1L), eq(""), any(OutputStream.class)))
                .thenReturn(new ExerciseImageDTO());
        exercisesImageResource.findOne(1L, "", new MockHttpServletResponse());
        verify(exerciseImageService).findOne(eq(1L), eq(""), any(OutputStream.class));
    }

    @Test(expected = IOException.class)
    public void findOne_with_error() throws Exception {
        when(exerciseImageService.findOne(eq(1L), eq(""), any(OutputStream.class)))
                .thenThrow(new IOException());
        exercisesImageResource.findOne(1L, "", new MockHttpServletResponse());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/TokenEmailSignupResourceTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;

import com.osomapps.pt.token.InUser;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletRequest;

@RunWith(MockitoJUnitRunner.class)
public class TokenEmailSignupResourceTest {

    @Mock private TokenEmailSignupService tokenEmailSignupService;

    @InjectMocks private TokenEmailSignupResource tokenEmailSignupResource;

    @Test
    public void list() {
        List<InUser> inUsers = tokenEmailSignupResource.list();
        assertThat(inUsers.isEmpty(), equalTo(true));
    }

    @Test
    public void create() {
        tokenEmailSignupResource.create(
                new TokenEmailSignupRequestDTO(), new MockHttpServletRequest());
        verify(tokenEmailSignupService)
                .createNewToken(any(TokenEmailSignupRequestDTO.class), anyString());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseTypeResourceTest.java
package com.osomapps.pt.admin.exercise;

import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseTypeResourceTest {

    @Mock private AdminExerciseTypeService adminExerciseTypeService;

    @InjectMocks private AdminExerciseTypeResource adminExerciseTypeResource;

    @Test
    public void findAll() {
        adminExerciseTypeResource.findAll();
        verify(adminExerciseTypeService).findAll();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/ParseSheetsTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ParseSheetsTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ParseSheets(null, null), notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/reportweight/InUserWeight.java
package com.osomapps.pt.reportweight;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.osomapps.pt.token.InUser;
import java.time.LocalDateTime;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "in_user_weight", schema = "ptcore")
@DynamicInsert
public class InUserWeight {
    @Id
    @SequenceGenerator(
            name = "InUserWeightIdSequence",
            sequenceName = "ptcore.in_user_weight_id_seq",
            allocationSize = 1,
            initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "InUserWeightIdSequence")
    Long id;

    LocalDateTime created;
    Float weight;

    @ManyToOne
    @JoinColumn(name = "in_user_id")
    @JsonBackReference
    InUser inUser;
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/UserWorkoutItemRequestDTO.java
package com.osomapps.pt.admin.user;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class UserWorkoutItemRequestDTO {
    Long exercise_id;
    String exercise_name;
    List<UserWorkoutItemSetRequestDTO> sets;
}
<file_sep>/src/main/java/com/osomapps/pt/reportweight/package-info.java
/**
 *
 *
 * <h1>Report weight endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides report weight services
 * </ul>
 */
package com.osomapps.pt.reportweight;
<file_sep>/src/main/resources/static/scripts/models/programs.js
/*jshint browser: true*/
/*global define*/
define([
    'jquery',
    'underscore',
    'backbone'
  ],
  function ($, _, Backbone) {
    'use strict';

    var Program = Backbone.Model.extend({
      defaults: {
        'id': null,
        'name': null,
        'fileName': '',
        'fileSize': 0,
        'fileType': '',
        'dataUrl': null,
        'updated': null,
        'parseGoals': []
      },
      url: function() {
        return '/api/v1/admin/program' + (this.isNew() ? '' : '/' + this.get('id'));
      },
      validate: function (attrs) {
        var errors = [];
        if (_.isNull(attrs.name) || _.isEmpty($.trim(attrs.name))) {
          errors.push({name: 'name', message: 'Please fill name field.'});
        } else if (_.isNull(attrs.dataUrl)) {
          errors.push({name: 'dataUrl', message: 'Please upload excel file.'});
        }
        return errors.length > 0 ? errors : false;
      }
    });

    var Programs = Backbone.Collection.extend({
      model: Program,
      initialize: function (models, options) {
      },
      url: '/api/v1/admin/program'
    });

    return {
      Program: Program,
      Programs: Programs
    };
  });
<file_sep>/src/main/resources/db/migration/V4.21__create_in_user_certificate_table.sql
CREATE TABLE ptcore.in_user_certificate (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    code VARCHAR(10) NOT NULL,
    amount_of_days INT NOT NULL,
    FOREIGN KEY (in_user_id) REFERENCES ptcore.in_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/resources/db/migration/V4.20__create_certificate_table.sql
CREATE TABLE ptcore.certificate (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    code VARCHAR(10) NOT NULL,
    amount_of_days INT NOT NULL,
    activated BOOLEAN NOT NULL
);
<file_sep>/src/main/java/com/osomapps/pt/exercises/ExerciseImageDTO.java
package com.osomapps.pt.exercises;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class ExerciseImageDTO {
    Long id;
    String fileName;
    String fileType;
}
<file_sep>/src/test/java/com/osomapps/pt/user/UserLevelSerializerTest.java
package com.osomapps.pt.user;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.junit.Test;

public class UserLevelSerializerTest {

    @Test
    public void serialize() throws Exception {
        JsonGenerator gen = mock(JsonGenerator.class);
        SerializerProvider serializers = mock(SerializerProvider.class);
        new UserLevelSerializer().serialize(UserLevel.Unexperienced, gen, serializers);
        verify(gen).writeNumber(eq(1));
    }

    @Test
    public void serialize_null() throws Exception {
        JsonGenerator gen = mock(JsonGenerator.class);
        SerializerProvider serializers = mock(SerializerProvider.class);
        new UserLevelSerializer().serialize(null, gen, serializers);
        verify(gen).writeNull();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/ParseGoalTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class ParseGoalTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ParseGoal(1L, null, null, null, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ParseGoal parseGoal = new ParseGoal();
        parseGoal.setCreated(LocalDateTime.MAX);
        parseGoal.setSheet_index(null);
        parseGoal.setParseProgram(null);
        assertThat(parseGoal, notNullValue());
    }

    @Test
    public void getters() {
        ParseGoal parseGoal = new ParseGoal();
        parseGoal.getCreated();
        parseGoal.getSheet_index();
        parseGoal.getParseProgram();
        assertThat(parseGoal, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.13__create_program_table.sql
CREATE TABLE ptcore.program (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(200),
    data_url TEXT,
    updated TIMESTAMP WITHOUT TIME ZONE,
    active BOOLEAN NOT NULL DEFAULT TRUE
);
<file_sep>/src/main/java/com/osomapps/pt/programs/ProgramsResource.java
package com.osomapps.pt.programs;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/programs")
class ProgramsResource {

    private final ProgramService programService;

    @Autowired
    ProgramsResource(ProgramService programService) {
        this.programService = programService;
    }

    @GetMapping
    List<ProgramResponseDTO> findAll(@RequestHeader(value = "X-Token") String token) {
        return programService.getExamples(token);
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/ParseWorkoutItemSetTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class ParseWorkoutItemSetTest {
    @Test
    public void allArgsConstructor() {
        assertThat(
                new ParseWorkoutItemSet(
                        1L, null, null, null, null, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        ParseWorkoutItemSet parseWorkoutItemSet = new ParseWorkoutItemSet();
        parseWorkoutItemSet.setId(null);
        parseWorkoutItemSet.setCreated(LocalDateTime.MAX);
        parseWorkoutItemSet.setParseWorkoutItem(null);
        assertThat(parseWorkoutItemSet, notNullValue());
    }

    @Test
    public void getters() {
        ParseWorkoutItemSet parseWorkoutItemSet = new ParseWorkoutItemSet();
        parseWorkoutItemSet.getId();
        parseWorkoutItemSet.getCreated();
        parseWorkoutItemSet.getParseWorkoutItem();
        assertThat(parseWorkoutItemSet, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/token/FacebookResponse.java
package com.osomapps.pt.token;

import java.time.LocalDate;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class FacebookResponse {
    String id;
    String name;
    String gender;
    LocalDate birthday;
    Long age;
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/UserLevelResponseDTO.java
package com.osomapps.pt.admin.user;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class UserLevelResponseDTO {
    Integer id;
    String name;
}
<file_sep>/src/test/java/com/osomapps/pt/xlsx/XlsxProgramModifierTest.java
package com.osomapps.pt.xlsx;

import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.osomapps.pt.dictionary.DictionaryName;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InWarmupWorkoutItem;
import com.osomapps.pt.programs.InWorkout;
import com.osomapps.pt.programs.InWorkoutItem;
import com.osomapps.pt.programs.InWorkoutItemSet;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserGoal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.util.FastByteArrayOutputStream;

@RunWith(MockitoJUnitRunner.class)
public class XlsxProgramModifierTest {

    private InUser getInUserWithProgram() {
        return new InUser()
                .setInPrograms(
                        Arrays.asList(
                                new InProgram()
                                        .setInWorkouts(
                                                Arrays.asList(
                                                        new InWorkout()
                                                                .setWorkout_index(0)
                                                                .setGoal_index(0)
                                                                .setInWarmupWorkoutItems(
                                                                        Arrays.asList(
                                                                                new InWarmupWorkoutItem()
                                                                                .setTime_in_sec(
                                                                                60)))
                                                                .setInWorkoutItems(
                                                                        Arrays.asList(
                                                                                new InWorkoutItem()
                                                                                .setInWorkoutItemSets(
                                                                                Arrays
                                                                                .asList(
                                                                                new InWorkoutItemSet()
                                                                                .setRepetitions(
                                                                                1)
                                                                                .setTime_in_sec(
                                                                                60)
                                                                                .setWeight(
                                                                                60.1F)))))))));
    }

    @Test
    public void updateCellData() {
        FastByteArrayOutputStream localOutputStream = getOutputStream();

        DictionaryService dictionaryService = mock(DictionaryService.class);
        XlsxProgramModifier xlsxProgramModifier =
                XlsxProgramModifier.of(localOutputStream.getInputStream(), dictionaryService);
        when(dictionaryService.getEnValue(eq(DictionaryName.goal_title), anyObject(), anyObject()))
                .thenReturn("Loose weight");
        xlsxProgramModifier.updateCellData(
                mock(OutputStream.class),
                getInUserWithProgram()
                        .setWeight(60F)
                        .setInUserGoals(Arrays.asList(new InUserGoal(), new InUserGoal())));
    }

    @Test
    public void updateCellData_no_goals() {
        FastByteArrayOutputStream localOutputStream = getOutputStream();

        DictionaryService dictionaryService = mock(DictionaryService.class);
        XlsxProgramModifier xlsxProgramModifier =
                XlsxProgramModifier.of(localOutputStream.getInputStream(), dictionaryService);
        xlsxProgramModifier.updateCellData(
                mock(OutputStream.class),
                getInUserWithProgram().setWeight(60F).setInUserGoals(Collections.emptyList()));
    }

    @Test
    public void updateCellData_one_goal() {
        FastByteArrayOutputStream localOutputStream = getOutputStream();

        DictionaryService dictionaryService = mock(DictionaryService.class);
        XlsxProgramModifier xlsxProgramModifier =
                XlsxProgramModifier.of(localOutputStream.getInputStream(), dictionaryService);
        xlsxProgramModifier.updateCellData(
                mock(OutputStream.class),
                getInUserWithProgram()
                        .setWeight(60F)
                        .setInUserGoals(Arrays.asList(new InUserGoal())));
    }

    private FastByteArrayOutputStream getOutputStream() {
        FastByteArrayOutputStream localOutputStream = new FastByteArrayOutputStream();
        final byte[] buffer = new byte[1024];
        try (InputStream inputStream =
                XlsxProgramParser.class.getResourceAsStream("program01.xlsx")) {
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                localOutputStream.write(buffer, 0, length);
            }
        } catch (IOException ex) {
        }
        return localOutputStream;
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/program/AdminProgramServiceTest.java
package com.osomapps.pt.admin.program;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.programs.ParseExercise;
import com.osomapps.pt.programs.ParseExerciseRepository;
import com.osomapps.pt.programs.ParseGoal;
import com.osomapps.pt.programs.ParseGoalRepository;
import com.osomapps.pt.programs.ParsePart;
import com.osomapps.pt.programs.ParsePartRepository;
import com.osomapps.pt.programs.ParseProgram;
import com.osomapps.pt.programs.ParseRound;
import com.osomapps.pt.programs.ParseRoundRepository;
import com.osomapps.pt.programs.ParseUserGroup;
import com.osomapps.pt.programs.ParseUserGroupRepository;
import com.osomapps.pt.programs.ParseWarmupWorkoutItemRepository;
import com.osomapps.pt.programs.ParseWorkout;
import com.osomapps.pt.programs.ParseWorkoutItem;
import com.osomapps.pt.programs.ParseWorkoutItemRepository;
import com.osomapps.pt.programs.ParseWorkoutItemSet;
import com.osomapps.pt.programs.ParseWorkoutItemSetRepository;
import com.osomapps.pt.programs.ParseWorkoutRepository;
import com.osomapps.pt.programs.ProgramRepository;
import com.osomapps.pt.reportworkout.InWorkoutItemRepository;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Sort;

@RunWith(MockitoJUnitRunner.class)
public class AdminProgramServiceTest {

    @Mock private ProgramRepository programRepository;
    @Mock private ParseExerciseRepository parseExerciseRepository;
    @Mock private ParseGoalRepository parseGoalRepository;
    @Mock private ParseUserGroupRepository parseUserGroupRepository;
    @Mock private ParseRoundRepository parseRoundRepository;
    @Mock private ParsePartRepository parsePartRepository;
    @Mock private ParseWorkoutRepository parseWorkoutRepository;
    @Mock private ParseWarmupWorkoutItemRepository parseWarmupWorkoutItemRepository;
    @Mock private ParseWorkoutItemRepository parseWorkoutItemRepository;
    @Mock private ParseWorkoutItemSetRepository parseWorkoutItemSetRepository;
    @Mock private InWorkoutItemRepository inWorkoutItemRepository;
    @Mock private AdminProgramAssignService adminProgramAssignService;

    @InjectMocks private AdminProgramService adminProgramService;

    @Test
    public void findAll() {
        adminProgramService.findAll();
        verify(programRepository).findAll(any(Sort.class));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void findOne_not_found() {
        adminProgramService.findOne(1L);
    }

    @Test
    public void findOne() {
        when(programRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new ParseProgram()
                                        .setParseExercises(Arrays.asList(new ParseExercise()))
                                        .setParseGoals(
                                                Arrays.asList(
                                                        new ParseGoal()
                                                                .setParseUserGroups(
                                                                        Arrays.asList(
                                                                                new ParseUserGroup()
                                                                                .setParseRounds(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseRound()
                                                                                .setParseParts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParsePart()
                                                                                .setParseWorkouts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkout()
                                                                                .setParseWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItem()
                                                                                .setParseWorkoutItemSets(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItemSet()))))))))))))))));
        adminProgramService.findOne(1L);
        verify(programRepository).findById(eq(1L));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void create() throws IOException {
        ProgramRequestDTO programRequestDTO = new ProgramRequestDTO();
        final java.io.ByteArrayOutputStream result = new java.io.ByteArrayOutputStream();
        final byte[] buffer = new byte[1024];
        try (InputStream inputStream =
                AdminProgramServiceTest.class.getResourceAsStream("dataurl02.txt")) {
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                result.write(buffer, 0, length);
            }
        }
        programRequestDTO.setDataUrl(result.toString());
        when(parseGoalRepository.saveAll(any(Iterable.class))).thenAnswer(i -> i.getArguments()[0]);
        when(parseWorkoutRepository.saveAll(any(Iterable.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        when(programRepository.save(any(ParseProgram.class))).thenAnswer(i -> i.getArguments()[0]);
        adminProgramService.create(programRequestDTO);
        verify(programRepository).save(any(ParseProgram.class));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void update_not_found() {
        adminProgramService.update(1L, new ProgramRequestDTO());
    }

    @Test
    @SuppressWarnings("unchecked")
    public void update() throws IOException {
        ProgramRequestDTO programRequestDTO = new ProgramRequestDTO();
        final java.io.ByteArrayOutputStream result = new java.io.ByteArrayOutputStream();
        final byte[] buffer = new byte[1024];
        try (InputStream inputStream =
                AdminProgramServiceTest.class.getResourceAsStream("dataurl02.txt")) {
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                result.write(buffer, 0, length);
            }
        }
        programRequestDTO.setDataUrl(result.toString());
        when(programRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new ParseProgram()
                                        .setParseGoals(
                                                Arrays.asList(
                                                        new ParseGoal()
                                                                .setParseUserGroups(
                                                                        Arrays.asList(
                                                                                new ParseUserGroup()
                                                                                .setParseRounds(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseRound()
                                                                                .setParseParts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParsePart()
                                                                                .setParseWorkouts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkout()
                                                                                .setParseWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItem()))))))))))))));
        when(parseGoalRepository.saveAll(any(Iterable.class))).thenAnswer(i -> i.getArguments()[0]);
        when(parseWorkoutRepository.saveAll(any(Iterable.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        when(programRepository.save(any(ParseProgram.class))).thenAnswer(i -> i.getArguments()[0]);
        adminProgramService.update(1L, programRequestDTO);
        verify(programRepository).save(any(ParseProgram.class));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void delete_not_found() {
        adminProgramService.delete(1L);
    }

    @Test
    public void delete() {
        when(programRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new ParseProgram()
                                        .setParseExercises(Arrays.asList(new ParseExercise()))
                                        .setParseGoals(
                                                Arrays.asList(
                                                        new ParseGoal()
                                                                .setParseUserGroups(
                                                                        Arrays.asList(
                                                                                new ParseUserGroup()
                                                                                .setParseRounds(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseRound()
                                                                                .setParseParts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParsePart()
                                                                                .setParseWorkouts(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkout()
                                                                                .setParseWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItem()
                                                                                .setParseWorkoutItemSets(
                                                                                Arrays
                                                                                .asList(
                                                                                new ParseWorkoutItemSet()))))))))))))))));
        adminProgramService.delete(1L);
        verify(programRepository).delete(any(ParseProgram.class));
    }

    @Test
    public void dataUrlToOutputStream() throws IOException {
        OutputStream outputStream = mock(OutputStream.class);
        adminProgramService.dataUrlToOutputStream(
                "data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0j"
                        + "vb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAA"
                        + "Re8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0Cc"
                        + "guWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7",
                outputStream);
        verify(outputStream).write(anyObject());
    }

    @Test
    public void dataUrlToOutputStream_wrong_data() throws IOException {
        OutputStream outputStream = mock(OutputStream.class);
        adminProgramService.dataUrlToOutputStream("data:image/gif;base64,!!!", outputStream);
        verify(outputStream, never()).write(anyObject());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/auth/package-info.java
/**
 *
 *
 * <h1>Administrator security user endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides security user services
 * </ul>
 */
package com.osomapps.pt.auth;
<file_sep>/src/main/java/com/osomapps/pt/admin/certificate/AmountOfDaysValidator.java
package com.osomapps.pt.admin.certificate;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

@Component
class AmountOfDaysValidator implements Validator {
    @Override
    public boolean supports(final Class<?> aClass) {
        return Integer.class.equals(aClass);
    }

    @Override
    public void validate(final Object obj, final Errors errors) {
        final Integer amountOfDays = (Integer) obj;
        if (amountOfDays == null) {
            errors.reject("amountOfDays", "Invalid empty amountOfDays");
            return;
        }
        if (amountOfDays < 1 || amountOfDays > 365) {
            errors.reject("amountOfDays", "Invalid amountOfDays value " + amountOfDays);
        }
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/InWorkoutTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class InWorkoutTest {
    @Test
    public void createAllArgs() {
        assertThat(
                new InWorkout(1L, null, null, null, null, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        InWorkout inWorkout = new InWorkout();
        inWorkout.setCreated(LocalDateTime.MAX);
        inWorkout.setWorkout_index(null);
        inWorkout.setGoal_index(null);
        inWorkout.setPart_name(null);
        assertThat(inWorkout, notNullValue());
    }

    @Test
    public void getters() {
        InWorkout inWorkout = new InWorkout();
        inWorkout.getCreated();
        inWorkout.getWorkout_index();
        inWorkout.getGoal_index();
        inWorkout.getPart_name();
        assertThat(inWorkout, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V3.2__add_device_id_for_in_user_facebook.sql
ALTER TABLE ptcore.in_user_facebook ADD COLUMN device_id VARCHAR(40) NOT NULL;<file_sep>/src/test/java/com/osomapps/pt/activecertificate/ActiveCertificateServiceTest.java
package com.osomapps.pt.activecertificate;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.admin.certificate.Certificate;
import com.osomapps.pt.admin.certificate.CertificateRepository;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.user.UserService;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ActiveCertificateServiceTest {
    @Mock private InUserCertificateRepository inUserCertificateRepository;
    @Mock private CertificateRepository certificateRepository;
    @Mock private UserService userService;

    @InjectMocks private ActiveCertificateService activeCertificateService;

    @Test
    public void firstActive() {
        assertThat(
                activeCertificateService.firstActive("").getCode(),
                equalTo(new ActiveCertificateResponseDTO().getCode()));
    }

    @Test
    public void firstActive_with_token() {
        InUserCertificate inUserCertificate = new InUserCertificate();
        inUserCertificate.setCreated(LocalDateTime.MAX.minusDays(1));
        inUserCertificate.setAmount_of_days(1);
        InUser inUser = new InUser();
        inUser.setInUserCertificates(Arrays.asList(inUserCertificate));
        InUserLogin inUserLogin = new InUserLogin();
        inUserLogin.setInUser(inUser);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        assertThat(
                activeCertificateService.firstActive("1").getCode(),
                equalTo(new ActiveCertificateResponseDTO().getCode()));
    }

    @Test
    public void create() {
        ActiveCertificateRequestDTO activeCertificateRequestDTO = new ActiveCertificateRequestDTO();
        assertThat(
                activeCertificateService.create("", activeCertificateRequestDTO).getCode(),
                equalTo(new ActiveCertificateResponseDTO().getCode()));
    }

    @Test
    public void create_with_token() {
        InUserCertificate inUserCertificate = new InUserCertificate();
        inUserCertificate.setId(1L);
        inUserCertificate.setCreated(LocalDateTime.MIN);
        inUserCertificate.setAmount_of_days(1);
        InUser inUser = new InUser();
        inUser.setInUserCertificates(Arrays.asList(inUserCertificate));
        InUserLogin inUserLogin = new InUserLogin();
        inUserLogin.setInUser(inUser);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(certificateRepository.findByCode(eq("123")))
                .thenReturn(
                        Arrays.asList(
                                new Certificate()
                                        .setActivated(Boolean.FALSE)
                                        .setAmount_of_days(1)));
        when(inUserCertificateRepository.save(any(InUserCertificate.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        ActiveCertificateRequestDTO activeCertificateRequestDTO =
                new ActiveCertificateRequestDTO().setCode("123");
        assertThat(
                activeCertificateService.create("1", activeCertificateRequestDTO).getCode(),
                equalTo(new ActiveCertificateResponseDTO().getCode()));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void create_with_token_code_not_found() {
        InUserCertificate inUserCertificate = new InUserCertificate();
        inUserCertificate.setId(1L);
        inUserCertificate.setCreated(LocalDateTime.MIN);
        inUserCertificate.setAmount_of_days(1);
        InUser inUser = new InUser();
        inUser.setInUserCertificates(Arrays.asList(inUserCertificate));
        InUserLogin inUserLogin = new InUserLogin();
        inUserLogin.setInUser(inUser);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(certificateRepository.findByCode(eq("123"))).thenReturn(Collections.emptyList());
        ActiveCertificateRequestDTO activeCertificateRequestDTO =
                new ActiveCertificateRequestDTO().setCode("123");
        activeCertificateService.create("1", activeCertificateRequestDTO);
    }

    @Test(expected = ResourceNotFoundException.class)
    public void create_with_token_no_active_certificates() {
        InUserCertificate inUserCertificate = new InUserCertificate();
        inUserCertificate.setId(1L);
        inUserCertificate.setCreated(LocalDateTime.MIN);
        inUserCertificate.setAmount_of_days(1);
        InUser inUser = new InUser();
        inUser.setInUserCertificates(Arrays.asList(inUserCertificate));
        InUserLogin inUserLogin = new InUserLogin();
        inUserLogin.setInUser(inUser);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(certificateRepository.findByCode(eq("123")))
                .thenReturn(
                        Arrays.asList(
                                new Certificate().setActivated(Boolean.TRUE).setAmount_of_days(1)));
        ActiveCertificateRequestDTO activeCertificateRequestDTO =
                new ActiveCertificateRequestDTO().setCode("123");
        assertThat(
                activeCertificateService.create("1", activeCertificateRequestDTO).getCode(),
                equalTo(new ActiveCertificateResponseDTO().getCode()));
    }
}
<file_sep>/src/main/resources/db/migration/V4.27__create_exercise_eqipment_type_table.sql
CREATE TABLE ptcore.exercise_equipment_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_equipment_type_name VARCHAR(45)
);

INSERT INTO ptcore.exercise_equipment_type (d_exercise_equipment_type_name) VALUES
('10'),
('20'),
('30');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('exercise_equipment_type_name', '10', 'Treadmill'),
('exercise_equipment_type_name', '20', 'Bike'),
('exercise_equipment_type_name', '30', 'Rowing Machine');

INSERT INTO ptcore.dictionary_data (dlanguage, dname, dkey, dvalue) VALUES
('nb', 'exercise_equipment_type_name', '10', 'Treadmill'),
('nb', 'exercise_equipment_type_name', '20', 'Bike'),
('nb', 'exercise_equipment_type_name', '30', 'Rowing Machine');

ALTER TABLE ptcore.exercise ADD COLUMN exercise_equipment_type_id BIGINT;

ALTER TABLE ptcore.exercise ADD CONSTRAINT exercise_exercise_equipment_type_id_fkey FOREIGN KEY
 (exercise_equipment_type_id) REFERENCES ptcore.exercise_equipment_type (id) ON UPDATE CASCADE ON DELETE CASCADE;
<file_sep>/src/main/java/com/osomapps/pt/admin/goal/AdminGoalTypeService.java
package com.osomapps.pt.admin.goal;

import com.osomapps.pt.goals.GoalType;
import com.osomapps.pt.goals.GoalTypeRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

@Service
class AdminGoalTypeService {

    private final GoalTypeRepository goalTypeRepository;

    AdminGoalTypeService(GoalTypeRepository goalTypeRepository) {
        this.goalTypeRepository = goalTypeRepository;
    }

    List<GoalTypeResponseDTO> findAll() {
        return goalTypeRepository.findAll().stream()
                .map(AdminGoalTypeService::goalTypeToDto)
                .collect(Collectors.toList());
    }

    private static GoalTypeResponseDTO goalTypeToDto(GoalType type) {
        return GoalTypeResponseDTO.builder().id(type.getId()).name(type.getName()).build();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/ExerciseOutputRequestDTOTest.java
package com.osomapps.pt.admin.exercise;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseOutputRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ExerciseOutputRequestDTO(null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new ExerciseOutputRequestDTO(), notNullValue());
    }

    @Test
    public void setters() {
        ExerciseOutputRequestDTO exerciseOutputRequestDTO =
                new ExerciseOutputRequestDTO().setId(null);
        assertThat(exerciseOutputRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        ExerciseOutputRequestDTO exerciseOutputRequestDTO = new ExerciseOutputRequestDTO();
        exerciseOutputRequestDTO.getId();
        assertThat(exerciseOutputRequestDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/UserProgramRequestDTO.java
package com.osomapps.pt.admin.user;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class UserProgramRequestDTO {
    String name;
    String type;
    List<UserWorkoutRequestDTO> workouts;
}
<file_sep>/src/main/resources/db/migration/V4.72__add_new_columns_for_in_workout_table.sql
ALTER TABLE ptcore.in_workout ADD COLUMN goal_index INT NOT NULL DEFAULT 0;
ALTER TABLE ptcore.in_workout ADD COLUMN part_name VARCHAR(50);
<file_sep>/src/main/java/com/osomapps/pt/reportweight/ReportWeightResource.java
package com.osomapps.pt.reportweight;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/report-weight")
class ReportWeightResource {

    private final ReportWeightService reportWeightService;

    @Autowired
    ReportWeightResource(ReportWeightService reportWeightService) {
        this.reportWeightService = reportWeightService;
    }

    @GetMapping
    List<WeightResponseDTO> findAll(@RequestHeader(value = "X-Token") String token) {
        return reportWeightService.findAll(token);
    }

    @PostMapping
    WeightResponseDTO create(
            @RequestHeader(value = "X-Token") String token,
            @RequestBody WeightRequestDTO weightRequestDTO) {
        return reportWeightService.create(token, weightRequestDTO);
    }
}
<file_sep>/src/main/resources/static/scripts/routers/app.js
/*jshint browser: true*/
/*global define*/
define([
  'marionette',
  'app'
],
function(Marionette, App) {
  'use strict';

  return Marionette.AppRouter.extend({
    //`index` etc must be a method in AppRouter's controller
    appRoutes: {
      'login': 'login',
      '': 'index'
    },
    initialize: function (options) {
      var controller = options.controller;
      App.vent.on('redirect:default', function() {
        controller.index();
        this.navigate('');
      }, this);

      App.vent.on('login:required', function() {
        controller.login();
        this.navigate('login');
      }, this);
    }
  });
});
<file_sep>/src/main/java/com/osomapps/pt/reportphoto/PhotoRequestDTO.java
package com.osomapps.pt.reportphoto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class PhotoRequestDTO {
    Long goal_id;
    String dataurl;
}
<file_sep>/src/test/java/com/osomapps/pt/reportweight/InUserWeightTest.java
package com.osomapps.pt.reportweight;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class InUserWeightTest {

    @Test
    public void createAllArgs() {
        assertThat(new InUserWeight(1L, LocalDateTime.now(), null, null), notNullValue());
    }

    @Test
    public void setters() {
        InUserWeight inUserWeight = new InUserWeight();
        inUserWeight.setId(1L);
        inUserWeight.setCreated(LocalDateTime.MAX);
        inUserWeight.setWeight(null);
        inUserWeight.setInUser(null);
        assertThat(inUserWeight, notNullValue());
    }

    @Test
    public void getters() {
        InUserWeight inUserWeight = new InUserWeight();
        inUserWeight.getId();
        inUserWeight.getCreated();
        inUserWeight.getInUser();
        inUserWeight.getWeight();
        assertThat(inUserWeight, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/program/ParseGoalDTOTest.java
package com.osomapps.pt.admin.program;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ParseGoalDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ParseGoalDTO(1L, null, null, null, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new ParseGoalDTO(), notNullValue());
    }

    @Test
    public void setters() {
        ParseGoalDTO parseGoalDTO = new ParseGoalDTO();
        parseGoalDTO.setId(null);
        parseGoalDTO.setName(null);
        parseGoalDTO.setLoops(null);
        parseGoalDTO.setUserGroups(null);
        parseGoalDTO.setErrors(null);
        assertThat(parseGoalDTO, notNullValue());
    }

    @Test
    public void getters() {
        ParseGoalDTO parseGoalDTO = new ParseGoalDTO();
        parseGoalDTO.getId();
        parseGoalDTO.getName();
        parseGoalDTO.getLoops();
        parseGoalDTO.getUserGroups();
        parseGoalDTO.getErrors();
        assertThat(parseGoalDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.8__add_categories_and_exercises.sql
INSERT INTO ptcore.exercise_category (d_exercise_category_name) VALUES
('800'),
('850'),
('890');

INSERT INTO ptcore.exercise (exercise_category_id, exercise_id, d_exercise_name) VALUES
(9, 810, '810'),
(9, 820, '820'),
(9, 830, '830'),
(9, 840, '840'),
(10, 860, '860'),
(10, 870, '870'),
(10, 880, '880'),
(11, 900, '900'),
(11, 910, '910'),
(11, 920, '920');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('exercise_category_name', '800', 'Treadmill'),
('exercise_category_name', '850', 'Bike'),
('exercise_category_name', '890', 'Rowing Machine');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('exercise_name', '810', 'Steady Pace Walk or Jog'),
('exercise_name', '820', '4 x 4 intervals'),
('exercise_name', '830', '3 x 3 intervals'),
('exercise_name', '840', '30 second sprints'),

('exercise_name', '860', 'Steady Pace'),
('exercise_name', '870', '4 x 4 intervals'),
('exercise_name', '880', '3 x 3 intervals'),

('exercise_name', '900', 'Steady Pace'),
('exercise_name', '910', '30 second intervals'),
('exercise_name', '920', '3 x 3');
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/EmailConfirmResourceTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class EmailConfirmResourceTest {

    @Mock private TokenEmailSignupService tokenEmailSignupService;

    @InjectMocks private EmailConfirmResource emailConfirmResource;

    @Test
    public void list() {
        assertThat(emailConfirmResource.list().size(), equalTo(0));
    }

    @Test
    public void create() {
        emailConfirmResource.create("");
        verify(tokenEmailSignupService).confirmToken(anyString());
    }

    @Test
    public void create_true() {
        when(tokenEmailSignupService.confirmToken(anyString())).thenReturn(true);
        emailConfirmResource.create("");
        verify(tokenEmailSignupService).confirmToken(anyString());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/AdminExerciseTypeResource.java
package com.osomapps.pt.admin.exercise;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/exercise-type")
class AdminExerciseTypeResource {

    private final AdminExerciseTypeService exerciseTypeService;

    @Autowired
    AdminExerciseTypeResource(AdminExerciseTypeService exerciseTypeService) {
        this.exerciseTypeService = exerciseTypeService;
    }

    @GetMapping
    List<ExerciseTypeResponseDTO> findAll() {
        return exerciseTypeService.findAll();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/user/UserGoalResponseDTOTest.java
package com.osomapps.pt.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserGoalResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserGoalResponseDTO(null, null), notNullValue());
    }

    @Test
    public void setters() {
        UserGoalResponseDTO userGoalResponseDTO = new UserGoalResponseDTO();
        userGoalResponseDTO.setId(null);
        userGoalResponseDTO.setValues(null);
        assertThat(userGoalResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserGoalResponseDTO userGoalResponseDTO = new UserGoalResponseDTO();
        userGoalResponseDTO.getId();
        userGoalResponseDTO.getValues();
        assertThat(userGoalResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExerciseInputTest.java
package com.osomapps.pt.exercises;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseInputTest {
    @Test
    public void createAllArgs() {
        assertThat(new ExerciseInput(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ExerciseInput exerciseInput = new ExerciseInput();
        exerciseInput.setCreated(null);
        exerciseInput.setExercises(null);
        assertThat(exerciseInput, notNullValue());
    }

    @Test
    public void getters() {
        ExerciseInput exerciseInput = new ExerciseInput();
        exerciseInput.getCreated();
        exerciseInput.getExercises();
        assertThat(exerciseInput, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.41__change_weigh_type_for_in_workout_and_in_workout_item_set_report_tables.sql
ALTER TABLE ptcore.in_workout_item ALTER COLUMN weight TYPE DECIMAL(9,2);
ALTER TABLE ptcore.in_workout_item_set_report ALTER COLUMN weight TYPE DECIMAL(9,2);
<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserGenderResponseDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserGenderResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserGenderResponseDTO(null, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new UserGenderResponseDTO(), notNullValue());
    }

    @Test
    public void setters() {
        UserGenderResponseDTO userGenderResponseDTO = new UserGenderResponseDTO();
        userGenderResponseDTO.setId(null);
        userGenderResponseDTO.setName(null);
        assertThat(userGenderResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserGenderResponseDTO userGenderResponseDTO = new UserGenderResponseDTO();
        userGenderResponseDTO.getId();
        userGenderResponseDTO.getName();
        assertThat(userGenderResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.65__add_new_column_for_parse_goal_table.sql
ALTER TABLE ptcore.parse_goal ADD COLUMN loops INT NOT NULL DEFAULT 0;
<file_sep>/src/main/resources/db/migration/V4.33__create_exercise_type_has_exercise_table.sql
ALTER TABLE ONLY ptcore.exercise DROP CONSTRAINT exercise_exercise_type_id_fkey;

ALTER TABLE ptcore.exercise DROP COLUMN exercise_type_id;
<file_sep>/src/test/java/com/osomapps/pt/xlsx/InputTest.java
package com.osomapps.pt.xlsx;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class InputTest {
    @Test
    public void createAllArgs() {
        assertThat(new Input(null, null), notNullValue());
    }

    @Test
    public void setters() {
        Input input = new Input().setExercise(null).setSets(null);
        assertThat(input, notNullValue());
    }

    @Test
    public void getters() {
        Input input = new Input();
        input.getExercise();
        input.getSets();
        assertThat(input, notNullValue());
    }

    @Test
    public void tostring() {
        Input input = new Input();
        assertThat(input.toString(), notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/TokenEmailRequestDTOTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TokenEmailRequestDTOTest {

    @Test
    public void getter() {
        assertThat(new TokenEmailRequestDTO().getName(), nullValue());
    }

    @Test
    public void setter() {
        assertThat(new TokenEmailRequestDTO().setName(""), notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V3__create_user_tables.sql
SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET search_path = ptcore;
SET default_tablespace = '';
SET default_with_oids = false;

CREATE SCHEMA IF NOT EXISTS ptcore;
CREATE TABLE ptcore.in_user (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_sex VARCHAR(45),
    age DECIMAL(9, 2),
    height DECIMAL(9, 2),
    weight DECIMAL(9, 2),
    d_level VARCHAR(45),
    updated TIMESTAMP WITHOUT TIME ZONE
);

CREATE TABLE ptcore.in_user_facebook (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    token VARCHAR(300),
    FOREIGN KEY (in_user_id) REFERENCES ptcore.in_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.in_user_login (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    token VARCHAR(35),
    ip_address VARCHAR(40),
    FOREIGN KEY (in_user_id) REFERENCES ptcore.in_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.in_user_logout (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    token VARCHAR(35),
    FOREIGN KEY (in_user_id) REFERENCES ptcore.in_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE INDEX facebook_token_index ON ptcore.in_user_facebook (token);
CREATE INDEX login_token_index ON ptcore.in_user_login (token);
CREATE INDEX logout_token_index ON ptcore.in_user_logout (token);
<file_sep>/src/main/resources/static/scripts/models/goals.js
/*jshint browser: true*/
/*global define*/
define([
    'jquery',
    'underscore',
    'backbone'
  ],
  function ($, _, Backbone) {
    'use strict';

    var Goal = Backbone.Model.extend({
      defaults: {
        'id': null,
        'titleEn': null,
        'titleNo': null,
        'title2En': null,
        'title2No': null,
        'parameters': [],
        'type': {
            id: null
        }
      },
      url: function() {
        return '/api/v1/admin/goal' + (this.isNew() ? '' : '/' + this.get('id'));
      },
      validate: function (attrs) {
        var errors = [];
        if (_.isNull(attrs.titleEn) || _.isEmpty($.trim(attrs.titleEn))) {
          errors.push({name: 'titleEn', message: 'Please fill title in English field.'});
        } else if (_.isNull(attrs.titleNo) || _.isEmpty($.trim(attrs.titleNo))) {
          errors.push({name: 'titleNo', message: 'Please fill title in Norwegian field.'});
        }
        return errors.length > 0 ? errors : false;
      }
    });

    var Goals = Backbone.Collection.extend({
      model: Goal,
      initialize: function (models, options) {
      },
      url: '/api/v1/admin/goal'
    });

    return {
      Goal: Goal,
      Goals: Goals
    };
  });
<file_sep>/src/test/java/com/osomapps/pt/admin/user/InUserTypeTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class InUserTypeTest {
    @Test
    public void createAllArgs() {
        assertThat(new InUserType(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        InUserType inUserType = new InUserType();
        inUserType.setCreated(null);
        inUserType.setInUsers(null);
        assertThat(inUserType, notNullValue());
    }

    @Test
    public void getters() {
        InUserType inUserType = new InUserType();
        inUserType.getCreated();
        inUserType.getInUsers();
        assertThat(inUserType, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/UserWorkoutItemSetRequestDTO.java
package com.osomapps.pt.admin.user;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class UserWorkoutItemSetRequestDTO {
    Integer repetitions;
    Integer weight;
    Boolean bodyweight;
}
<file_sep>/src/main/resources/db/migration/V4.34__create_exercise_input_has_exercise_and_exercise_output_has_exercise_table.sql
CREATE TABLE ptcore.exercise_input (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50)
);

INSERT INTO ptcore.exercise_input (name) VALUES
('Weight'),
('Reps'),
('Sets'),
('Time'),
('Speed'),
('Incline'),
('Resistance');

CREATE TABLE ptcore.exercise_input_has_exercise (
    exercise_input_id BIGINT NOT NULL REFERENCES ptcore.exercise_input(id),
    exercise_id      BIGINT NOT NULL REFERENCES ptcore.exercise(id)
);

CREATE TABLE ptcore.exercise_output (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50)
);

INSERT INTO ptcore.exercise_output (name) VALUES
('Weight'),
('Reps'),
('Sets'),
('Time'),
('Speed'),
('Incline'),
('Resistance');

CREATE TABLE ptcore.exercise_output_has_exercise (
    exercise_output_id BIGINT NOT NULL REFERENCES ptcore.exercise_output(id),
    exercise_id      BIGINT NOT NULL REFERENCES ptcore.exercise(id)
);
<file_sep>/src/main/resources/db/migration/V4.29__add_in_user_id_for_parse_user_table.sql
ALTER TABLE ptcore.parse_user ADD COLUMN in_user_id BIGINT NOT NULL DEFAULT 0;

<file_sep>/src/main/java/com/osomapps/pt/admin/user/AdminUserProgramFileResource.java
package com.osomapps.pt.admin.user;

import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/user-program-file")
class AdminUserProgramFileResource {

    private final AdminUserProgramFileService userProgramFileService;

    @Autowired
    AdminUserProgramFileResource(AdminUserProgramFileService userProgramFileService) {
        this.userProgramFileService = userProgramFileService;
    }

    @GetMapping(value = "{id}/{fileName}")
    @ResponseBody
    Object findOne(
            @PathVariable Long id, @PathVariable String fileName, HttpServletResponse response)
            throws IOException {
        try (FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream()) {
            final ProgramResponseDTO programResponseDTO =
                    userProgramFileService.createXlsx(id, outputStream);
            response.setContentType(programResponseDTO.getFileType());
            response.setHeader(
                    "Content-disposition",
                    "attachment; filename=" + programResponseDTO.getFileName());
            outputStream.writeTo(response.getOutputStream());
            response.getOutputStream().close();
            outputStream.reset();
        }
        return null;
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/ProgramResponseDTO.java
package com.osomapps.pt.admin.user;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class ProgramResponseDTO {
    String fileType;
    String fileName;
}
<file_sep>/src/main/resources/db/migration/V4.44__create_goal_tables.sql
CREATE TABLE ptcore.in_goal (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    goal_id BIGINT,
    d_goal_title VARCHAR(45),
    d_goal_title_2 VARCHAR(45)
);

CREATE TABLE ptcore.in_goal_parameter (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50)
);

CREATE TABLE ptcore.in_goal_has_in_goal_parameter (
    in_goal_id      BIGINT NOT NULL REFERENCES ptcore.in_goal(id),
    in_goal_parameter_id BIGINT NOT NULL REFERENCES ptcore.in_goal_parameter(id)
);

CREATE TABLE ptcore.goal (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_goal_title VARCHAR(45),
    d_goal_title_2 VARCHAR(45)
);

CREATE TABLE ptcore.goal_parameter (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50)
);

CREATE TABLE ptcore.goal_has_goal_parameter (
    goal_id      BIGINT NOT NULL REFERENCES ptcore.goal(id),
    goal_parameter_id BIGINT NOT NULL REFERENCES ptcore.goal_parameter(id)
);

CREATE TABLE ptcore.in_user_has_in_goal (
    in_user_id      BIGINT NOT NULL REFERENCES ptcore.in_user(id),
    in_goal_id      BIGINT NOT NULL REFERENCES ptcore.in_goal(id)
);

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('goal_title', '10', 'Loose weight'),
('goal_title', '20', 'Get a flat stomach'),
('goal_title', '30', 'Get stronger'),
('goal_title', '40', 'Build muscles'),
('goal_title', '50', 'Increase ednurance'),
('goal_title', '60', 'Correct posture'),
('goal_title', '70', 'Beat time on a specific distance'),
('goal_title', '80', 'Get back in shape after pregnancy');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('goal_title_2', '10', 'General'),
('goal_title_2', '20', 'Upper body'),
('goal_title_2', '30', 'Legs'),
('goal_title_2', '40', 'General'),
('goal_title_2', '50', 'Upper body'),
('goal_title_2', '60', 'Legs'),
('goal_title_2', '70', 'running'),
('goal_title_2', '80', 'cycling');

INSERT INTO ptcore.goal_parameter(name) VALUES
('Weight'),
('Distance');

INSERT INTO ptcore.goal(d_goal_title, d_goal_title_2) VALUES
('10', NULL),
('20', NULL),
('30', '10'),
('30', '20'),
('30', '30'),
('40', '40'),
('40', '50'),
('40', '60'),
('50', NULL),
('60', NULL),
('70', '70'),
('70', '80'),
('80', NULL);

<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserWarmupWorkoutItemRequestDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserWarmupWorkoutItemRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserWarmupWorkoutItemRequestDTO(1L, null, null, null, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new UserWarmupWorkoutItemRequestDTO(), notNullValue());
    }

    @Test
    public void setters() {
        UserWarmupWorkoutItemRequestDTO userWarmupWorkoutItemRequestDTO =
                new UserWarmupWorkoutItemRequestDTO();
        userWarmupWorkoutItemRequestDTO.setExercise_id(null);
        userWarmupWorkoutItemRequestDTO.setExercise_name(null);
        userWarmupWorkoutItemRequestDTO.setSpeed(null);
        userWarmupWorkoutItemRequestDTO.setIncline(null);
        userWarmupWorkoutItemRequestDTO.setTime_in_sec(null);
        assertThat(userWarmupWorkoutItemRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserWarmupWorkoutItemRequestDTO userWarmupWorkoutItemRequestDTO =
                new UserWarmupWorkoutItemRequestDTO();
        userWarmupWorkoutItemRequestDTO.getExercise_id();
        userWarmupWorkoutItemRequestDTO.getExercise_name();
        userWarmupWorkoutItemRequestDTO.getSpeed();
        userWarmupWorkoutItemRequestDTO.getIncline();
        userWarmupWorkoutItemRequestDTO.getTime_in_sec();
        assertThat(userWarmupWorkoutItemRequestDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/tokenemail/TemplateEngine.java
package com.osomapps.pt.tokenemail;

import java.util.HashMap;
import java.util.Map;

final class TemplateEngine {
    private static final String ALL_SYMBOLS = "([\\s\\S]+?)";
    private static final Map<String, String> TEMPLATE_SETTINGS = new HashMap<>();

    static {
        TEMPLATE_SETTINGS.put("evaluate", "\\{\\{" + ALL_SYMBOLS + "\\}\\}");
    }

    interface Template<F> {
        String apply(F arg);
    }

    static final class TemplateImpl<K, V> implements Template<Map<K, V>> {
        private final String template;

        TemplateImpl(String template) {
            this.template = template;
        }

        @Override
        @SuppressWarnings("unchecked")
        public String apply(Map<K, V> value) {
            final String evaluate = TEMPLATE_SETTINGS.get("evaluate");
            String result = template;
            for (final Map.Entry<K, V> element : value.entrySet()) {
                result =
                        java.util.regex.Pattern.compile(
                                        evaluate.replace(
                                                ALL_SYMBOLS,
                                                "\\s*"
                                                        + java.util.regex.Pattern.quote(
                                                                String.valueOf(element.getKey()))
                                                        + "\\s*"))
                                .matcher(result)
                                .replaceAll(String.valueOf(element.getValue()));
            }
            return result;
        }
    }

    static <K, V> TemplateEngine.Template<Map<K, V>> template(final String template) {
        return new TemplateImpl<>(template);
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserServiceTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.admin.program.AdminProgramAssignService;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.goals.Goal;
import com.osomapps.pt.goals.GoalRepository;
import com.osomapps.pt.goals.InUserGoalRepository;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InWarmupWorkoutItem;
import com.osomapps.pt.programs.InWorkout;
import com.osomapps.pt.programs.InWorkoutItem;
import com.osomapps.pt.programs.InWorkoutItemReport;
import com.osomapps.pt.programs.InWorkoutItemSet;
import com.osomapps.pt.programs.InWorkoutItemSetReport;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserFacebook;
import com.osomapps.pt.token.InUserFacebookRepository;
import com.osomapps.pt.token.InUserGoal;
import com.osomapps.pt.token.InUserRepository;
import com.osomapps.pt.tokenemail.EmailValidator;
import com.osomapps.pt.tokenemail.InUserEmail;
import com.osomapps.pt.tokenemail.InUserEmailRepository;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.Errors;

@RunWith(MockitoJUnitRunner.class)
public class AdminUserServiceTest {

    @Mock private InUserRepository inUserRepository;
    @Mock private InUserEmailRepository inUserEmailRepository;
    @Mock private InUserFacebookRepository inUserFacebookRepository;
    @Mock private InUserTypeRepository inUserTypeRepository;
    @Mock private PasswordEncoder passwordEncoder;
    @Mock private EmailValidator emailValidator;
    @Mock private DictionaryService dictionaryService;
    @Mock private InUserGoalRepository inUserGoalRepository;
    @Mock private GoalRepository goalRepository;
    @Mock private AdminProgramAssignService adminProgramAssignService;

    @InjectMocks private AdminUserService adminUserService;

    @Test
    public void findAll() {
        when(inUserRepository.findAll(any(Sort.class)))
                .thenReturn(Arrays.asList(new InUser().setInUserEmails(Collections.emptyList())));
        adminUserService.findAll();
        verify(inUserRepository).findAll(any(Sort.class));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void findOne_not_found() {
        adminUserService.findOne(1L);
    }

    private InProgram getInProgram() {
        return new InProgram()
                .setInWorkouts(
                        Arrays.asList(
                                new InWorkout()
                                        .setInWarmupWorkoutItems(
                                                Arrays.asList(new InWarmupWorkoutItem()))
                                        .setInWorkoutItems(
                                                Arrays.asList(
                                                        new InWorkoutItem()
                                                                .setInWorkoutItemSets(
                                                                        Arrays.asList(
                                                                                new InWorkoutItemSet()))
                                                                .setInWorkoutItemReports(
                                                                        Arrays.asList(
                                                                                new InWorkoutItemReport()
                                                                                .setInWorkoutItemSetReports(
                                                                                Arrays
                                                                                .asList(
                                                                                new InWorkoutItemSetReport()))))))));
    }

    @Test
    public void findOne() {
        when(inUserRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new InUser()
                                        .setInUserEmails(Collections.emptyList())
                                        .setInUserType(new InUserType())
                                        .setInPrograms(Arrays.asList(getInProgram()))));
        UserResponseDTO userResponseDTO = adminUserService.findOne(1L);
        assertThat(userResponseDTO.getName(), equalTo("?"));
    }

    @Test
    public void create() {
        when(adminProgramAssignService.assign(any(InUser.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        when(inUserRepository.save(any(InUser.class))).thenAnswer(i -> i.getArguments()[0]);
        when(goalRepository.findById(eq(1L))).thenReturn(Optional.of(new Goal().setId(1L)));
        when(inUserGoalRepository.save(any(InUserGoal.class))).thenAnswer(i -> i.getArguments()[0]);
        UserResponseDTO userResponseDTO =
                adminUserService.create(
                        new UserRequestDTO()
                                .setType(new UserTypeRequestDTO())
                                .setLevel(1)
                                .setGoals(Arrays.asList(new UserGoalRequestDTO().setId(1L))));
        assertThat(userResponseDTO.getName(), equalTo(null));
    }

    @Test(expected = UnauthorizedException.class)
    public void create_emailValidator() {
        doAnswer(
                        (Answer<Void>)
                                (InvocationOnMock invocation) -> {
                                    Object[] args = invocation.getArguments();
                                    ((Errors) args[1]).reject("email", "Invalid empty email");
                                    return null;
                                })
                .when(emailValidator)
                .validate(anyObject(), any(Errors.class));
        adminUserService.create(new UserRequestDTO().setType(new UserTypeRequestDTO()));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void update_not_found() {
        adminUserService.update(1L, new UserRequestDTO().setType(new UserTypeRequestDTO()));
    }

    @Test
    public void update() {
        when(inUserRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new InUser()
                                        .setInUserEmails(Collections.emptyList())
                                        .setInUserFacebooks(Arrays.asList(new InUserFacebook()))));
        when(adminProgramAssignService.assign(any(InUser.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        when(goalRepository.findById(eq(1L))).thenReturn(Optional.of(new Goal().setId(1L)));
        when(inUserGoalRepository.save(any(InUserGoal.class))).thenAnswer(i -> i.getArguments()[0]);
        UserResponseDTO userResponseDTO =
                adminUserService.update(
                        1L,
                        new UserRequestDTO()
                                .setType(new UserTypeRequestDTO())
                                .setLevel(2)
                                .setGoals(Arrays.asList(new UserGoalRequestDTO().setId(1L))));
        assertThat(userResponseDTO.getName(), equalTo(null));
    }

    @Test
    public void update_with_eamil() {
        when(inUserRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new InUser()
                                        .setInUserEmails(Arrays.asList(new InUserEmail()))
                                        .setInUserFacebooks(Arrays.asList(new InUserFacebook()))));
        when(adminProgramAssignService.assign(any(InUser.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        UserResponseDTO userResponseDTO =
                adminUserService.update(1L, new UserRequestDTO().setType(new UserTypeRequestDTO()));
        assertThat(userResponseDTO.getName(), equalTo(null));
    }

    @Test(expected = UnauthorizedException.class)
    public void update_with_invalid_eamil() {
        doAnswer(
                        (Answer<Void>)
                                (InvocationOnMock invocation) -> {
                                    Object[] args = invocation.getArguments();
                                    ((Errors) args[1]).reject("emailValidator", "emailValidator");
                                    return null;
                                })
                .when(emailValidator)
                .validate(anyObject(), any(Errors.class));
        when(inUserRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new InUser()
                                        .setInUserEmails(Arrays.asList(new InUserEmail()))
                                        .setInUserFacebooks(Arrays.asList(new InUserFacebook()))));
        adminUserService.update(1L, new UserRequestDTO().setType(new UserTypeRequestDTO()));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void delete_not_found() {
        adminUserService.delete(1L);
    }

    @Test
    public void delete() {
        when(inUserRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new InUser().setInUserEmails(Arrays.asList(new InUserEmail()))));
        UserResponseDTO userResponseDTO = adminUserService.delete(1L);
        assertThat(userResponseDTO.getName(), equalTo(null));
    }
}
<file_sep>/src/main/java/com/osomapps/pt/token/TokenRequestDTO.java
package com.osomapps.pt.token;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class TokenRequestDTO {
    String facebook_token;
    String device_id;
}
<file_sep>/src/main/resources/static/styles/common.less
.app-header {
  position: relative;
  text-align: center;
}
.app-header img {
  position: absolute;
  left: 0;
}

.empty-page-header {
  margin: 20px 0 20px;
}

body {
  overflow-x: hidden!important;
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
  background: @clr-bg;
}

footer {
  text-align: center;
  margin-top: 30px;
  padding: 15px;
  border-top: 1px solid @clr-border;
}

.disabled-data {
  color: @clr-disabled;
}

.table>tbody>tr>td.error-message-row {
  border-top: none;
  padding-top: 0;
  color: @clr-error;
}

.table > tbody > tr > td.warning-message-row {
  border-top: none;
  padding-top: 0;
  color: @clr-warning;
}

<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/AdminExerciseTypeService.java
package com.osomapps.pt.admin.exercise;

import com.osomapps.pt.exercises.ExerciseType;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

@Service
class AdminExerciseTypeService {

    private final ExerciseTypeRepository exerciseTypeRepository;

    AdminExerciseTypeService(ExerciseTypeRepository exerciseTypeRepository) {
        this.exerciseTypeRepository = exerciseTypeRepository;
    }

    List<ExerciseTypeResponseDTO> findAll() {
        return exerciseTypeRepository.findAll().stream()
                .map(AdminExerciseTypeService::exerciseTypeToDto)
                .collect(Collectors.toList());
    }

    private static ExerciseTypeResponseDTO exerciseTypeToDto(ExerciseType type) {
        return ExerciseTypeResponseDTO.builder().id(type.getId()).name(type.getName()).build();
    }
}
<file_sep>/src/main/java/com/osomapps/pt/tokenemail/InUserEmailRepository.java
package com.osomapps.pt.tokenemail;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface InUserEmailRepository extends JpaRepository<InUserEmail, Long> {

    List<InUserEmail> findByLogin(String login);

    List<InUserEmail> findByConfirmToken(String confirmToken);

    List<InUserEmail> findByResetToken(String resetToken);
}
<file_sep>/src/test/java/com/osomapps/pt/admin/program/ParseRoundDTOTest.java
package com.osomapps.pt.admin.program;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ParseRoundDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ParseRoundDTO(1L, null, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new ParseRoundDTO(), notNullValue());
    }

    @Test
    public void setters() {
        ParseRoundDTO parseRoundDTO = new ParseRoundDTO();
        parseRoundDTO.setId(null);
        parseRoundDTO.setName(null);
        parseRoundDTO.setParts(null);
        assertThat(parseRoundDTO, notNullValue());
    }

    @Test
    public void getters() {
        ParseRoundDTO parseRoundDTO = new ParseRoundDTO();
        parseRoundDTO.getId();
        parseRoundDTO.getName();
        parseRoundDTO.getParts();
        assertThat(parseRoundDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/program/ParseExerciseDTO.java
package com.osomapps.pt.admin.program;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Builder
class ParseExerciseDTO {
    Integer exercise_id;
    String exercise_name;
    Integer user_group_1_percent;
    Integer user_group_2_percent;
    Integer user_group_3_percent;
    Integer user_group_4_percent;
    String basis_for_calculations;
}
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExerciseTest.java
package com.osomapps.pt.exercises;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseTest {
    @Test
    public void createAllArgs() {
        assertThat(
                new Exercise(1L, null, null, null, null, null, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        Exercise exercise = new Exercise();
        exercise.setCreated(null);
        assertThat(exercise, notNullValue());
    }

    @Test
    public void getters() {
        Exercise exercise = new Exercise();
        exercise.getCreated();
        assertThat(exercise, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/email/EmailMessageTypeResponseDTOTest.java
package com.osomapps.pt.admin.email;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class EmailMessageTypeResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new EmailMessageTypeResponseDTO(null, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new EmailMessageTypeResponseDTO(), notNullValue());
    }

    @Test
    public void setters() {
        EmailMessageTypeResponseDTO emailMessageTypeResponseDTO =
                new EmailMessageTypeResponseDTO().setId(null).setName(null);
        assertThat(emailMessageTypeResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        EmailMessageTypeResponseDTO emailMessageTypeResponseDTO = new EmailMessageTypeResponseDTO();
        emailMessageTypeResponseDTO.getId();
        emailMessageTypeResponseDTO.getName();
        assertThat(emailMessageTypeResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/ExerciseOutputRepository.java
package com.osomapps.pt.admin.exercise;

import com.osomapps.pt.exercises.ExerciseOutput;
import org.springframework.data.jpa.repository.JpaRepository;

interface ExerciseOutputRepository extends JpaRepository<ExerciseOutput, Long> {}
<file_sep>/src/main/resources/db/migration/V4.64__add_new_columns_for_in_program_and_in_workout_tables.sql
ALTER TABLE ptcore.in_program ADD COLUMN current_workout_index INT NOT NULL DEFAULT 0;
ALTER TABLE ptcore.in_workout ADD COLUMN workout_index INT NOT NULL DEFAULT 0;
<file_sep>/src/main/java/com/osomapps/pt/admin/program/ExerciseResponse.java
package com.osomapps.pt.admin.program;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class ExerciseResponse {
    Long id;
    Long exerciseId;
    String nameEn;
    Integer cardioPercent;
}
<file_sep>/src/main/resources/db/migration/V4.31__add_cardio_percent_for_exercise_table.sql
ALTER TABLE ptcore.exercise ADD COLUMN cardio_percent INT NOT NULL DEFAULT 0;
<file_sep>/src/main/java/com/osomapps/pt/admin/ptuser/PtUser.java
package com.osomapps.pt.admin.ptuser;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "pt_user", schema = "ptcore")
@DynamicInsert
public class PtUser implements Serializable {
    @Id
    @SequenceGenerator(
            name = "PtUserIdSequence",
            sequenceName = "ptcore.pt_user_id_seq",
            allocationSize = 1,
            initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PtUserIdSequence")
    Long id;

    LocalDateTime created;
    String login;
    String password;
    String name;
    LocalDateTime activated;
    Boolean is_blocked;
    Boolean is_blocked_date_set;
    String blocked_comment;
    LocalDateTime blocked_start;
    LocalDateTime blocked_finish;
    LocalDateTime deleted;
    String deleted_comment;
    Boolean is_deleted;
    Boolean is_default_password;
    String description;
    String phone;
    String phone2;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "pt_user_has_pt_role",
            schema = "ptcore",
            joinColumns = {@JoinColumn(name = "pt_user_id")},
            inverseJoinColumns = {@JoinColumn(name = "pt_role_id")})
    List<PtRole> ptRoles = new ArrayList<>(0);
}
<file_sep>/docs/database-schema.md
User data store db schema:

![pt schema](pt-schema-login-v3.png)

User's program data store db schema:

![pt schema](pt-schema-program-v8.png)

Exercise data store db schema:

![pt schema](pt-schema-exercise-v6.png)

User extra data store db schema:

![pt schema](pt-schema-user-data-v1.png)

User goal store db schema:

![pt schema](pt-schema-user-goal-v5.png)

Admin program data store db schema:

![pt schema](pt-schema-program-data-v6.png)

Admin certificate data store db schema:

![pt schema](pt-schema-certificate-v1.png)

User type data store db schema:

![pt schema](pt-schema-user-type-v1.png)

PT user and pt role store db schema:

![pt schema](pt-schema-user-and-role-v2.png)
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/ExerciseTypeRequestDTOTest.java
package com.osomapps.pt.admin.exercise;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseTypeRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ExerciseTypeRequestDTO(null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new ExerciseTypeRequestDTO(), notNullValue());
    }

    @Test
    public void setters() {
        ExerciseTypeRequestDTO exerciseTypeRequestDTO = new ExerciseTypeRequestDTO().setId(null);
        assertThat(exerciseTypeRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        ExerciseTypeRequestDTO exerciseTypeRequestDTO = new ExerciseTypeRequestDTO();
        exerciseTypeRequestDTO.getId();
        assertThat(exerciseTypeRequestDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/ParseExerciseTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class ParseExerciseTest {
    @Test
    public void allArgsConstructor() {
        assertThat(
                new ParseExercise(1L, null, null, null, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        ParseExercise parseExercise = new ParseExercise();
        parseExercise.setId(null);
        parseExercise.setCreated(LocalDateTime.MAX);
        parseExercise.setParseProgram(null);
        assertThat(parseExercise, notNullValue());
    }

    @Test
    public void getters() {
        ParseExercise parseExercise = new ParseExercise();
        parseExercise.getId();
        parseExercise.getCreated();
        parseExercise.getParseProgram();
        assertThat(parseExercise, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.4__create_weight_table.sql
CREATE TABLE ptcore.in_user_weight (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    weight DECIMAL(9, 2),
    FOREIGN KEY (in_user_id) REFERENCES ptcore.in_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/test/java/com/osomapps/pt/reportweight/ReportWeightServiceTest.java
package com.osomapps.pt.reportweight;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.user.UserService;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ReportWeightServiceTest {

    @Mock private InUserWeightRepository inUserWeightRepository;
    @Mock private UserService userService;

    @InjectMocks private ReportWeightService reportWeightService;

    @Test
    public void findAll() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserForLogin.setInUserWeights(Arrays.asList(new InUserWeight().setId(1L).setWeight(1F)));
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        reportWeightService.findAll("1");
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void create() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(inUserWeightRepository.save(any(InUserWeight.class)))
                .thenReturn(new InUserWeight().setId(1L).setWeight(1F));
        reportWeightService.create("1", new WeightRequestDTO().setWeight(1L));
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void create_with_empty_token() {
        reportWeightService.create("", new WeightRequestDTO().setWeight(1L));
        verify(userService, never()).checkUserToken(anyString());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/reportweight/ReportWeightService.java
package com.osomapps.pt.reportweight;

import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.user.UserService;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
class ReportWeightService {
    private final InUserWeightRepository inUserWeightRepository;
    private final UserService userService;

    @Autowired
    ReportWeightService(InUserWeightRepository inUserWeightRepository, UserService userService) {
        this.inUserWeightRepository = inUserWeightRepository;
        this.userService = userService;
    }

    List<WeightResponseDTO> findAll(String token) {
        if (!token.isEmpty()) {
            final InUserLogin inUserLogin = userService.checkUserToken(token);
            return inUserLogin.getInUser().getInUserWeights().stream()
                    .map(
                            inUserWeight ->
                                    new WeightResponseDTO(
                                            inUserWeight.getId(),
                                            inUserWeight.getWeight().longValue()))
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    WeightResponseDTO create(String token, WeightRequestDTO weightRequestDTO) {
        if (!token.isEmpty()) {
            final InUserLogin inUserLogin = userService.checkUserToken(token);
            InUserWeight inUserWeight = new InUserWeight();
            inUserWeight.setInUser(inUserLogin.getInUser());
            inUserWeight.setWeight(weightRequestDTO.getWeight().floatValue());
            InUserWeight InUserWeightSaved = inUserWeightRepository.save(inUserWeight);
            return new WeightResponseDTO(
                    InUserWeightSaved.getId(), InUserWeightSaved.getWeight().longValue());
        }
        return new WeightResponseDTO();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/xlsx/XlsxProgramParserTest.java
package com.osomapps.pt.xlsx;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;

import java.io.InputStream;
import java.util.List;
import org.junit.Test;

public class XlsxProgramParserTest {
    @Test
    public void parse1() throws Exception {
        List<ExcelGoal> excelGoals;
        try (InputStream stream =
                XlsxProgramParserTest.class.getResourceAsStream("Dette_blir_algo.xlsx")) {
            XlsxProgramParser parser = XlsxProgramParser.of(stream);
            excelGoals = parser.getExcelSheets().getExcelGoals();
        }
        assertThat(excelGoals.size(), equalTo(8));
        assertThat(excelGoals.get(0).getName(), equalTo("Loose weight"));
        assertThat(excelGoals.get(0).getUserGroups().size(), equalTo(4));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .size(),
                equalTo(1));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getName(),
                equalTo("Loose weight_1_1_Part 1"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(5));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getExercise(),
                equalTo("Deadlift"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(5));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getExercise(),
                equalTo("Bench Press"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1F));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(5));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(2)
                        .getInput()
                        .getExercise(),
                equalTo("Pull Up"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(5));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(3)
                        .getInput()
                        .getExercise(),
                equalTo("Dips"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(5));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(4)
                        .getInput()
                        .getExercise(),
                equalTo("Plank"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(4)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getTimeInMin(),
                equalTo(2F));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(5));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getExercise(),
                equalTo("Deadlift"));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .size(),
                equalTo(3));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getRepetitions(),
                equalTo(10));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1F));
    }

    @Test
    public void parse2() throws Exception {
        ExcelSheets excelSheets;
        try (InputStream stream =
                XlsxProgramParserTest.class.getResourceAsStream("Dette_blir_algo2.xlsx")) {
            XlsxProgramParser parser = XlsxProgramParser.of(stream);
            excelSheets = parser.getExcelSheets();
        }
        List<ExcelExercise> excelExercises = excelSheets.getExcelExercises();
        assertThat(excelExercises.size(), equalTo(57));
        assertThat(excelExercises.get(0).getExercise_name(), equalTo("Squat"));
        assertThat(excelExercises.get(56).getExercise_name(), equalTo("Chin-Ups"));
        assertThat(excelExercises.get(56).getBasis_for_calculations(), equalTo("Reps"));
        List<ExcelGoal> excelGoals = excelSheets.getExcelGoals();
        assertThat(excelGoals.size(), equalTo(12));
        assertThat(excelGoals.get(0).getName(), equalTo("Loose weight"));
        assertThat(excelGoals.get(0).getUserGroups().size(), equalTo(4));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .size(),
                equalTo(1));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getName(),
                equalTo("Loose weight_1_1_Part 1"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(3));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getExercise(),
                equalTo("820 4 x 4 intervals"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(3));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getExercise(),
                equalTo("Front Squat"));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1F));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(3));
        assertThat(
                excelGoals
                        .get(0)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(2)
                        .getInput()
                        .getExercise(),
                equalTo("Russian Twists"));

        assertThat(excelGoals.get(1).getName(), equalTo("Get a flat stomach"));
        assertThat(excelGoals.get(1).getUserGroups().size(), equalTo(4));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .size(),
                equalTo(1));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getName(),
                equalTo("Get a flat stomach_1_1_Part 1"));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getExercise(),
                equalTo("Plank On a Ball"));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getExercise(),
                equalTo("Russian Twists"));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1F));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(1)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(2)
                        .getInput()
                        .getExercise(),
                equalTo("Hanginf Leg/Knee Raise"));

        assertThat(excelGoals.get(2).getName(), equalTo("Get stronger, general"));
        assertThat(excelGoals.get(2).getUserGroups().size(), equalTo(4));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .size(),
                equalTo(1));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getName(),
                equalTo("Get stronger, general_3_1_Part 1"));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getExercise(),
                equalTo("Deadlift"));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1.5F));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getExercise(),
                equalTo("Bench Press"));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(1)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1F));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(2)
                        .getUserGroups()
                        .get(2)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(2)
                        .getInput()
                        .getExercise(),
                equalTo("Bent Over Row"));

        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .size(),
                equalTo(4));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getExercise(),
                equalTo("Front Squat"));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .size(),
                equalTo(3));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getRepetitions(),
                equalTo(8));
        assertThat(
                excelGoals
                        .get(7)
                        .getUserGroups()
                        .get(0)
                        .getRounds()
                        .get(0)
                        .getParts()
                        .get(0)
                        .getWorkouts()
                        .get(0)
                        .getWorkoutItems()
                        .get(0)
                        .getInput()
                        .getSets()
                        .get(0)
                        .getWeight(),
                equalTo(1F));
    }
}
<file_sep>/src/main/resources/db/migration/V4.10__create_exercise_type_has_exercise_table.sql
CREATE TABLE ptcore.exercise_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_type_name VARCHAR(45)
);

INSERT INTO ptcore.exercise_type (d_exercise_type_name) VALUES
('10'),
('20'),
('30');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('exercise_type_name', '10', 'Strength'),
('exercise_type_name', '20', 'Cardio'),
('exercise_type_name', '30', 'Weight Loss');

INSERT INTO ptcore.dictionary_data (dlanguage, dname, dkey, dvalue) VALUES
('nb', 'exercise_type_name', '10', 'Strength'),
('nb', 'exercise_type_name', '20', 'Cardio'),
('nb', 'exercise_type_name', '30', 'Weight Loss');

CREATE TABLE ptcore.exercise_type_has_exercise (
    exercise_type_id BIGINT NOT NULL REFERENCES ptcore.exercise_type(id),
    exercise_id      BIGINT NOT NULL REFERENCES ptcore.exercise(id)
);

INSERT INTO ptcore.exercise_type_has_exercise (exercise_type_id, exercise_id) VALUES
(1, 1);                 -- 20 Squat : Strength

<file_sep>/src/main/resources/db/migration/V4.69__add_new_column_for_parse_workout_item_and_parse_warmup_wokrout_item_tables.sql
ALTER TABLE ptcore.parse_warmup_workout_item ADD COLUMN exercise_id INT NOT NULL DEFAULT 0;
ALTER TABLE ptcore.parse_workout_item ADD COLUMN exercise_id INT NOT NULL DEFAULT 0;
<file_sep>/src/main/resources/db/migration/V4.24__create_pt_user_and_pt_role_tables.sql
CREATE TABLE ptcore.pt_user (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    login VARCHAR(50),
    password VARCHAR(70),
    name VARCHAR(100),
    activated TIMESTAMP WITHOUT TIME ZONE,
    is_blocked BOOLEAN NOT NULL DEFAULT FALSE,
    is_blocked_date_set BOOLEAN NOT NULL DEFAULT FALSE,
    blocked_comment VARCHAR(500),
    blocked_start TIMESTAMP WITHOUT TIME ZONE,
    blocked_finish TIMESTAMP WITHOUT TIME ZONE,
    deleted TIMESTAMP WITHOUT TIME ZONE,
    deleted_comment VARCHAR(500),
    is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
    is_default_password BOOLEAN NOT NULL DEFAULT TRUE,
    description VARCHAR(500),
    phone VARCHAR(15),
    phone2 VARCHAR(15)
);

INSERT INTO ptcore.pt_user (login, password) VALUES
('admin', <PASSWORD>');

CREATE TABLE ptcore.pt_role (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(45)
);

INSERT INTO ptcore.pt_role (name) VALUES
('Administrator'),
('Trainer');

CREATE TABLE ptcore.pt_user_has_pt_role (
    pt_user_id BIGINT NOT NULL REFERENCES ptcore.pt_user(id),
    pt_role_id BIGINT NOT NULL REFERENCES ptcore.pt_role(id)
);

INSERT INTO ptcore.pt_user_has_pt_role (pt_user_id, pt_role_id) VALUES
(1, 1);
<file_sep>/src/main/java/com/osomapps/pt/admin/program/ParseWorkoutItemSetDTO.java
package com.osomapps.pt.admin.program;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Builder
class ParseWorkoutItemSetDTO {
    Integer repetitions;
    Boolean repetitions_to_failure;
    Float weight;
    Boolean bodyweight;
    Float time_in_min;
    Integer speed;
    Integer incline;
    Integer resistance;
}
<file_sep>/src/main/java/com/osomapps/pt/programs/ParseExercise.java
package com.osomapps.pt.programs;

import com.fasterxml.jackson.annotation.JsonBackReference;
import java.time.LocalDateTime;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "parse_exercise", schema = "ptcore")
@DynamicInsert
@DynamicUpdate
public class ParseExercise {
    @Id
    @SequenceGenerator(
            name = "ParseExerciseIdSequence",
            sequenceName = "ptcore.parse_exercise_id_seq",
            allocationSize = 1,
            initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ParseExerciseIdSequence")
    Long id;

    LocalDateTime created;
    Integer exercise_id;
    String exercise_name;
    Integer user_group_1_percent;
    Integer user_group_2_percent;
    Integer user_group_3_percent;
    Integer user_group_4_percent;
    String basis_for_calculations;

    @ManyToOne
    @JoinColumn(name = "parse_program_id")
    @JsonBackReference
    ParseProgram parseProgram;
}
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/AdminExerciseInputResource.java
package com.osomapps.pt.admin.exercise;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/admin/exercise-input")
class AdminExerciseInputResource {

    private final AdminExerciseInputService exerciseInputService;

    @Autowired
    AdminExerciseInputResource(AdminExerciseInputService exerciseInputService) {
        this.exerciseInputService = exerciseInputService;
    }

    @GetMapping
    List<ExerciseInputResponseDTO> findAll() {
        return exerciseInputService.findAll();
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserGoalServiceTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.goals.Goal;
import com.osomapps.pt.goals.GoalRepository;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Sort;

@RunWith(MockitoJUnitRunner.class)
public class AdminUserGoalServiceTest {
    @Mock private GoalRepository goalRepository;
    @Mock private DictionaryService dictionaryService;

    @InjectMocks private AdminUserGoalService adminUserGoalService;

    @Test
    public void findOne() {
        when(goalRepository.findAll(any(Sort.class))).thenReturn(Arrays.asList(new Goal()));
        List<UserGoalResponseDTO> goalResponseDTOs = adminUserGoalService.findAll();
        verify(goalRepository).findAll(any(Sort.class));
        assertThat(goalResponseDTOs.size(), equalTo(1));
    }
}
<file_sep>/src/main/java/com/osomapps/pt/programs/ParseSheets.java
package com.osomapps.pt.programs;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
public class ParseSheets {
    List<ParseExercise> parseExercises;
    List<ParseGoal> parseGoals;
}
<file_sep>/src/main/java/com/osomapps/pt/reportphoto/ReportPhotoFileResource.java
package com.osomapps.pt.reportphoto;

import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/report-photo-file")
class ReportPhotoFileResource {

    private final ReportPhotoFileService reportPhotoFileService;

    @Autowired
    ReportPhotoFileResource(ReportPhotoFileService reportPhotoFileService) {
        this.reportPhotoFileService = reportPhotoFileService;
    }

    @GetMapping("{id}/{fileName}")
    @ResponseBody
    void findOne(
            @RequestHeader(value = "X-Token") String token,
            @PathVariable Long id,
            @PathVariable String fileName,
            HttpServletResponse response)
            throws IOException {
        try (FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream()) {
            final ReportPhotoFileDTO reportPhotoFileDTO =
                    reportPhotoFileService.findOne(token, id, fileName, outputStream);
            response.setContentType(reportPhotoFileDTO.getFileType());
            outputStream.writeTo(response.getOutputStream());
            response.getOutputStream().close();
            outputStream.reset();
        }
    }
}
<file_sep>/src/main/resources/db/migration/V4.74__create_in_user_goal_photo_table.sql
CREATE TABLE ptcore.in_user_goal_photo (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    file_name VARCHAR(200) NOT NULL DEFAULT '',
    file_size BIGINT NOT NULL DEFAULT 0,
    file_type VARCHAR(100) NOT NULL DEFAULT '',
    data_url TEXT
);

CREATE TABLE ptcore.in_user_goal_has_in_user_goal_photo (
    in_user_goal_id BIGINT NOT NULL REFERENCES ptcore.in_user_goal(id),
    in_user_goal_photo_id BIGINT NOT NULL REFERENCES ptcore.in_user_goal_photo(id)
);
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserProgramFileResourceIntTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;

import javax.servlet.http.HttpServletResponse;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.FastByteArrayOutputStream;

@TestPropertySource("/application-test.properties")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class AdminUserProgramFileResourceIntTest {

    @MockBean AdminUserProgramFileService programFileService;
    @Autowired AdminUserProgramFileResource adminUserProgramFileResource;

    @Test
    public void findOne() throws Exception {
        given(programFileService.createXlsx(eq(1L), any(FastByteArrayOutputStream.class)))
                .willReturn(new ProgramResponseDTO());
        HttpServletResponse httpServletResponse = new MockHttpServletResponse();
        adminUserProgramFileResource.findOne(1L, "fileName", httpServletResponse);
        Assert.assertThat(httpServletResponse.getStatus(), equalTo(HttpStatus.OK.value()));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/InWorkoutItemSetTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class InWorkoutItemSetTest {
    @Test
    public void allArgsConstructor() {
        assertThat(
                new InWorkoutItemSet(
                        1L, null, null, null, null, null, null, null, null, null, null, null, null,
                        null, null, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        InWorkoutItemSet inWorkoutItemSet = new InWorkoutItemSet();
        inWorkoutItemSet.setId(null);
        inWorkoutItemSet.setCreated(LocalDateTime.MAX);
        inWorkoutItemSet.setInWorkoutItem(null);
        inWorkoutItemSet.setExercise_weight_percent(null);
        inWorkoutItemSet.setExercise_weight_in_kg(null);
        inWorkoutItemSet.setGoal_weight_coef(null);
        inWorkoutItemSet.setExercise_repetitions_percent(null);
        inWorkoutItemSet.setGoal_repetitions(null);
        inWorkoutItemSet.setExercise_time_percent(null);
        inWorkoutItemSet.setGoal_time_in_sec(null);
        inWorkoutItemSet.setExercise_speed_percent(null);
        inWorkoutItemSet.setGoal_speed(null);
        inWorkoutItemSet.setExercise_basis(null);
        assertThat(inWorkoutItemSet, notNullValue());
    }

    @Test
    public void getters() {
        InWorkoutItemSet inWorkoutItemSet = new InWorkoutItemSet();
        inWorkoutItemSet.getId();
        inWorkoutItemSet.getCreated();
        inWorkoutItemSet.getInWorkoutItem();
        inWorkoutItemSet.getExercise_weight_percent();
        inWorkoutItemSet.getExercise_weight_in_kg();
        inWorkoutItemSet.getGoal_weight_coef();
        inWorkoutItemSet.getExercise_repetitions_percent();
        inWorkoutItemSet.getGoal_repetitions();
        inWorkoutItemSet.getExercise_time_percent();
        inWorkoutItemSet.getGoal_time_in_sec();
        inWorkoutItemSet.getExercise_speed_percent();
        inWorkoutItemSet.getGoal_speed();
        inWorkoutItemSet.getExercise_basis();
        assertThat(inWorkoutItemSet, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/config/CachingConfig.java
package com.osomapps.pt.config;

import com.google.common.cache.CacheBuilder;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession;

@Configuration
@EnableCaching
@EnableJdbcHttpSession(tableName = "ptcore.SPRING_SESSION")
class CachingConfig {

    @Bean
    CacheManager cacheManager() {
        final SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(
                Arrays.asList(
                        new ConcurrentMapCache(
                                "dictionaryData",
                                CacheBuilder.newBuilder()
                                        .expireAfterWrite(1, TimeUnit.DAYS)
                                        .build()
                                        .asMap(),
                                false),
                        new ConcurrentMapCache(
                                "dictionaryAllData",
                                CacheBuilder.newBuilder()
                                        .expireAfterWrite(1, TimeUnit.DAYS)
                                        .build()
                                        .asMap(),
                                false)));
        return cacheManager;
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/ParseProgramTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.time.LocalDateTime;
import org.junit.Test;

public class ParseProgramTest {
    @Test
    public void createAllArgs() {
        assertThat(
                new ParseProgram(1L, null, null, null, null, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        ParseProgram parseProgram = new ParseProgram();
        parseProgram.setCreated(LocalDateTime.MAX);
        parseProgram.setActive(null);
        assertThat(parseProgram, notNullValue());
    }

    @Test
    public void getters() {
        ParseProgram parseProgram = new ParseProgram();
        parseProgram.getCreated();
        parseProgram.getActive();
        assertThat(parseProgram, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/exercises/package-info.java
/**
 *
 *
 * <h1>Exercises endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides exercise services
 * </ul>
 */
package com.osomapps.pt.exercises;
<file_sep>/src/test/java/com/osomapps/pt/user/UserResourceIntTest.java
package com.osomapps.pt.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import com.osomapps.pt.UnauthorizedException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;

@TestPropertySource("/application-test.properties")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class UserResourceIntTest {

    @Autowired UserResource userResource;

    @Test
    public void findOne() throws Exception {
        UserResponseDTO user = userResource.findOne("");
        assertThat(user, notNullValue());
    }

    @Test(expected = UnauthorizedException.class)
    public void findOneNotFound() throws Exception {
        UserResponseDTO user = userResource.findOne("1");
        assertThat(user, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserLevelServiceTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminUserLevelServiceTest {
    @InjectMocks private AdminUserLevelService adminUserLevelService;

    @Test
    public void findOne() {
        List<UserLevelResponseDTO> userLevelResponseDTOs = adminUserLevelService.findAll();
        assertThat(userLevelResponseDTOs.size(), equalTo(2));
    }
}
<file_sep>/src/main/resources/db/migration/V4__create_program_tables.sql
CREATE TABLE ptcore.in_program (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_user_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    d_program_type VARCHAR(45),
    FOREIGN KEY (in_user_id) REFERENCES ptcore.in_user (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.in_workout (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_program_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_workout_name VARCHAR(45),
    FOREIGN KEY (in_program_id) REFERENCES ptcore.in_program (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.in_workout_item (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    in_workout_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_id VARCHAR(45),
    d_exercise_name VARCHAR(45),
    sets INT,
    repetitions INT,
    weight INT,
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    FOREIGN KEY (in_workout_id) REFERENCES ptcore.in_workout (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/java/com/osomapps/pt/xlsx/ExcelSheets.java
package com.osomapps.pt.xlsx;

import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@ToString
public class ExcelSheets {
    List<ExcelExercise> excelExercises = new ArrayList<>();
    List<ExcelGoal> excelGoals = new ArrayList<>();
}
<file_sep>/src/main/resources/db/migration/V4.63__create_in_user_goal_type_table.sql
CREATE TABLE ptcore.in_user_goal_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_user_goal_type VARCHAR(45) NOT NULL
);

INSERT INTO ptcore.in_user_goal_type (d_user_goal_type) VALUES
('10'),
('20'),
('30'),
('40');

INSERT INTO ptcore.dictionary_data (dlanguage, dname, dkey, dvalue) VALUES
('en', 'user_goal_type', '10', 'weight'),
('en', 'user_goal_type', '20', 'percentage'),
('en', 'user_goal_type', '30', 'chart'),
('en', 'user_goal_type', '40', 'photos'),
('nb', 'user_goal_type', '10', 'weight'),
('nb', 'user_goal_type', '20', 'percentage'),
('nb', 'user_goal_type', '30', 'chart'),
('nb', 'user_goal_type', '40', 'photos');

ALTER TABLE ptcore.in_user_goal ADD COLUMN in_user_goal_type_id BIGINT;

ALTER TABLE ptcore.in_user_goal
  ADD CONSTRAINT in_user_goal_type_id_fkey FOREIGN KEY (in_user_goal_type_id)
      REFERENCES ptcore.in_user_goal_type (id)
      ON UPDATE CASCADE ON DELETE CASCADE;
<file_sep>/src/main/java/com/osomapps/pt/xlsx/InputSet.java
package com.osomapps.pt.xlsx;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@ToString
public class InputSet {
    Integer repetitions;
    Boolean repetitionsToFailure;
    Float weight;
    Boolean bodyweight;
    Float timeInMin;
    Integer speed;
    Integer incline;
    Integer resistance;
}
<file_sep>/src/test/java/com/osomapps/pt/programs/WarmupWorkoutItemSetResponseDTOTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WarmupWorkoutItemSetResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(
                new WarmupWorkoutItemSetResponseDTO(1, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        WarmupWorkoutItemSetResponseDTO warmupWorkoutItemSetResponseDTO =
                new WarmupWorkoutItemSetResponseDTO()
                        .setRepetitions(null)
                        .setWeight(null)
                        .setBodyweight(null)
                        .setTime_in_sec(null)
                        .setSpeed(null)
                        .setIncline(null)
                        .setResistance(null);
        assertThat(warmupWorkoutItemSetResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        WarmupWorkoutItemSetResponseDTO warmupWorkoutItemSetResponseDTO =
                new WarmupWorkoutItemSetResponseDTO();
        warmupWorkoutItemSetResponseDTO.getRepetitions();
        warmupWorkoutItemSetResponseDTO.getWeight();
        warmupWorkoutItemSetResponseDTO.getBodyweight();
        warmupWorkoutItemSetResponseDTO.getTime_in_sec();
        warmupWorkoutItemSetResponseDTO.getSpeed();
        warmupWorkoutItemSetResponseDTO.getIncline();
        warmupWorkoutItemSetResponseDTO.getResistance();
        assertThat(warmupWorkoutItemSetResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/user/UserLevel.java
package com.osomapps.pt.user;

public enum UserLevel {
    Unexperienced(1),
    Experienced(2);

    private final int level;

    private UserLevel(int level) {
        this.level = level;
    }

    public int getLevel() {
        return level;
    }

    public static UserLevel of(int level) {
        for (UserLevel userLevel : values()) {
            if (userLevel.level == level) {
                return userLevel;
            }
        }
        return null;
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/email/EmailMessageTemplateResponseDTOTest.java
package com.osomapps.pt.admin.email;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class EmailMessageTemplateResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(
                new EmailMessageTemplateResponseDTO(null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new EmailMessageTemplateResponseDTO(), notNullValue());
    }

    @Test
    public void setters() {
        EmailMessageTemplateResponseDTO emailMessageTemplateResponseDTO =
                new EmailMessageTemplateResponseDTO()
                        .setId(null)
                        .setEmailSubjectEn(null)
                        .setEmailSubjectNo(null)
                        .setEmailTextEn(null)
                        .setEmailTextNo(null)
                        .setType(null);
        assertThat(emailMessageTemplateResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        EmailMessageTemplateResponseDTO emailMessageTemplateResponseDTO =
                new EmailMessageTemplateResponseDTO();
        emailMessageTemplateResponseDTO.getId();
        emailMessageTemplateResponseDTO.getEmailSubjectEn();
        emailMessageTemplateResponseDTO.getEmailSubjectNo();
        emailMessageTemplateResponseDTO.getEmailTextEn();
        emailMessageTemplateResponseDTO.getEmailTextNo();
        emailMessageTemplateResponseDTO.getType();
        assertThat(emailMessageTemplateResponseDTO, notNullValue());
    }
}
<file_sep>/build.sh
#!/bin/bash

set -e

echo
echo "----------- Build Java with maven ------------"
mvn clean install
<file_sep>/src/test/java/com/osomapps/pt/admin/ptuser/PtRoleRequestDTOTest.java
package com.osomapps.pt.admin.ptuser;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class PtRoleRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new PtRoleRequestDTO(1L), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new PtRoleRequestDTO(), notNullValue());
    }

    @Test
    public void setters() {
        PtRoleRequestDTO ptRoleRequestDTO = new PtRoleRequestDTO();
        ptRoleRequestDTO.setId(null);
        assertThat(ptRoleRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        PtRoleRequestDTO ptRoleRequestDTO = new PtRoleRequestDTO();
        ptRoleRequestDTO.getId();
        assertThat(ptRoleRequestDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/token/package-info.java
/**
 *
 *
 * <h1>Token endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides login/logout services
 * </ul>
 */
package com.osomapps.pt.token;
<file_sep>/src/main/resources/db/migration/V4.45__drop_parse_workout_test_tables.sql
DROP TABLE ptcore.program_test CASCADE;
DROP TABLE ptcore.parse_workout_test CASCADE;
DROP TABLE ptcore.parse_warmup_workout_item_test CASCADE;
DROP TABLE ptcore.parse_workout_item_test CASCADE;
<file_sep>/src/main/resources/static/scripts/views/certificates.js
/*jshint browser: true*/
/*global define, console*/
define([
    'jquery',
    'underscore',
    'marionette',
    'app',
    'bootstrapTab'
],
function ($, _, Marionette, App) {
  'use strict';

  var EmptyView = Marionette.ItemView.extend({
        tagName: 'tr',
        template: _.template('<td colspan="4">There are no certificates available.</td>')
  });

  var Certificate = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ code }}',
      '</td>',
      '<td>',
        '{{ amountOfDays }}',
      '</td>',
      '<td>',
        '{{ activated }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-edit-value">',
          '<i class="glyphicon glyphicon-edit"></i>',
        '</button>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-delete-value">',
          '<i class="glyphicon glyphicon-remove"></i>',
        '</button>',
      '</td>'
    ].join('')),

    initialize: function(options) {
      this.collection = options.collection;
    },
    events: {
      'click .js-edit-value': 'editCertificate',
      'click .js-delete-value': 'deleteCertificate'
    },
    editCertificate: function() {
      this.collection.trigger('certificate:new', this.model);
    },
    deleteCertificate: function(evt) {
      evt.preventDefault();
      var model = this.model;
      var collection = this.collection;
      this.model.destroy()
        .done(function() {
        })
        .fail(function (xhr) {
          App.vent.trigger('xhr:error', 'Certificate ' + model.get('id') + ' delete was failed');
        })
        .always(function() {
          collection.fetch();
        });
    }
  });

  var Certificates = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: Certificate,
    emptyView: EmptyView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Certificates </h3>',
      '</div>',
      '<button class="btn btn-primary js-new-certificate" style="margin: 10px;">',
        'New certificate',
      '</button>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Code</th>',
            '<th>Amount of days</th>',
            '<th>Activated</th>',
            '<th></th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    collectionEvents: {
      'sync': 'render'
    },
    events: {
      'click .js-new-certificate': 'newCertificate'
    },
    newCertificate: function() {
      this.collection.trigger('certificate:new');
    }
  });

  var NewCertificateLayout = Marionette.Layout.extend({
    template: _.template([
      '<div class="panel panel-primary">',
        '<div class="panel-heading">',
          '<h3 class="panel-title"> {{ getHeader() }} </h3>',
        '</div>',
        '<div id="buttons"/>',
        '<div id="inputForm"/>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getHeader: function () {
          return model.isNew() ? 'New certificate' : 'Edit certificate';
        }
      };
    },
    tagName: 'form',
    className: 'form-horizontal',
    regions: {
      buttons: '#buttons',
      inputForm: '#inputForm'
    },
    onShow: function() {
      this.buttons.show(new NewCertificateButtons({model: this.model}));
      this.inputForm.show(new NewCertificateInputForm({model: this.model}));
    }
  });

  var NewCertificateButtons = Marionette.ItemView.extend({
    template: _.template([
      '<div class="btn-group">',
        '<button class="btn btn-default js-back" style="margin: 10px 0 0 10px;">',
          'Back',
        '</button>',
        '<button class="btn btn-danger js-save  {{ getSaveDisabled() }}" style="margin: 10px 0 0 0; min-width: 100px;">',
          'Save',
        '</button>',
        '<button class="btn btn-default js-discard" style="margin: 10px 0 0 0px;">',
          'Discard',
        '</button>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getSaveDisabled: function () {
          return view.model.isValid() ? '' : 'disabled';
        }
      };
    },
    events: {
      'click .js-back': 'back',
      'click .js-save': 'save',
      'click .js-discard': 'discard'
    },
    modelEvents: {
      'change': 'render'
    },
    initialize: function(options) {
      this._model = options.model.clone();
    },
    back: function(evt) {
      evt.preventDefault();
      this.model.trigger('certificate:back', this.model.get('id'));
    },
    save: function(evt) {
      evt.preventDefault();
      var model = this.model;
      this.model.save().done(function(data) {
        model.trigger('certificate:back', model.get('id'), data);
      })
      .fail(function (xhr) {
        App.vent.trigger('xhr:error', 'Certificate save was failed');
      });
    },
    discard: function(evt) {
      evt.preventDefault();
      this.model.set(this._model.toJSON());
      this.model.trigger('sync');
    }
  });

  var NewCertificateInputForm = Marionette.ItemView.extend({
    className: 'user-input-form',
    template: _.template([
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">ID</label>',
        '<div class="col-sm-8">',
          '<p class="form-control-static">',
            ' {{ id }}',
          '</p>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Code</label>',
        '<div class="col-sm-8">',
          '<textarea id="certificate-code" class="form-control" rows="3" placeholder="Please enter code" name="address" required="true">',
            '{{ code }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Amount of days</label>',
        '<div class="col-sm-8">',
          '<textarea id="certificate-amountOfDays" class="form-control" rows="3" placeholder="Please enter amount of days" name="address" required="true">',
            '{{ amountOfDays }}',
          '</textarea>',
        '</div>',
      '</div>'
    ].join('')),
    modelEvents: {
      'sync': 'render'
    },
    events: {
      'input #certificate-code': 'inputCode',
      'input #certificate-amountOfDays': 'inputAmountOfDays'
    },
    ui: {
      code: '#certificate-code',
      amountOfDays: '#certificate-amountOfDays'
    },
    inputCode: function() {
      this.model.set('code', this.ui.code.val());
    },
    inputAmountOfDays: function() {
      this.model.set('amountOfDays', this.ui.amountOfDays.val());
    }
  });

  return {
    Certificates: Certificates,
    NewCertificateLayout: NewCertificateLayout
  };

});
<file_sep>/src/main/resources/db/migration/V4.19__add_column_and_row_index_to_parse_workout_item_table.sql
ALTER TABLE ptcore.parse_workout_item ADD COLUMN column_index INT NOT NULL DEFAULT 0;
ALTER TABLE ptcore.parse_workout_item ADD COLUMN row_index INT NOT NULL DEFAULT 0;
<file_sep>/src/main/resources/db/migration/V4.28__make_exercise_bodypart_id_nullable.sql
ALTER TABLE ptcore.exercise ALTER COLUMN exercise_bodypart_id DROP NOT NULL;
<file_sep>/src/test/java/com/osomapps/pt/reportworkout/ReportWorkoutServiceTest.java
package com.osomapps.pt.reportworkout;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InProgramRepository;
import com.osomapps.pt.programs.InWorkout;
import com.osomapps.pt.programs.InWorkoutItem;
import com.osomapps.pt.programs.InWorkoutItemReport;
import com.osomapps.pt.programs.InWorkoutRepository;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.user.UserService;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ReportWorkoutServiceTest {

    @Mock private InProgramRepository inProgramRepository;
    @Mock private InWorkoutRepository inWorkoutRepository;
    @Mock private InWorkoutItemRepository inWorkoutItemRepository;
    @Mock private InWorkoutItemReportRepository inWorkoutItemReportRepository;
    @Mock private InWorkoutItemSetReportRepository inWorkoutItemSetReportRepository;
    @Mock private UserService userService;

    @InjectMocks private ReportWorkoutService reportWorkoutService;

    @Test
    public void findAll() {
        reportWorkoutService.findAll("1");
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void create() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        WorkoutReportRequestDTO workoutReportRequestDTO = new WorkoutReportRequestDTO();
        WorkoutItemSetReportRequestDTO workoutItemSetReportRequestDTO =
                new WorkoutItemSetReportRequestDTO();
        WorkoutItemReportRequestDTO workoutItemReportRequestDTO = new WorkoutItemReportRequestDTO();
        workoutItemReportRequestDTO.setId(1L);
        workoutItemReportRequestDTO.setSets(Arrays.asList(workoutItemSetReportRequestDTO));
        workoutReportRequestDTO.setId(1L).setItems(Arrays.asList(workoutItemReportRequestDTO));
        InWorkoutItem inWorkoutItem = new InWorkoutItem();
        InWorkout inWorkout = new InWorkout();
        inWorkoutItem.setInWorkout(inWorkout);
        InProgram inProgram = new InProgram();
        inWorkout.setInProgram(inProgram);
        InUser inUser = new InUser();
        inUser.setId(10L);
        inProgram.setInUser(inUser);
        when(inWorkoutItemReportRepository.save(any(InWorkoutItemReport.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        when(inWorkoutItemRepository.findById(eq(1L))).thenReturn(Optional.of(inWorkoutItem));
        when(inWorkoutRepository.findById(eq(1L))).thenReturn(Optional.of(getInWorkout()));
        reportWorkoutService.create("1", workoutReportRequestDTO);
        verify(userService).checkUserToken(eq("1"));
    }

    private InWorkout getInWorkout() {
        return new InWorkout()
                .setInProgram(
                        new InProgram()
                                .setCurrent_workout_index(0)
                                .setInWorkouts(Arrays.asList(new InWorkout())))
                .setInWorkoutItems(Arrays.asList(new InWorkoutItem().setId(1L)));
    }

    @Test
    public void create_with_not_null_weight() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        WorkoutReportRequestDTO workoutReportRequestDTO = new WorkoutReportRequestDTO();
        WorkoutItemSetReportRequestDTO workoutItemSetReportRequestDTO =
                new WorkoutItemSetReportRequestDTO();
        workoutItemSetReportRequestDTO.setWeight(1);
        WorkoutItemReportRequestDTO workoutItemReportRequestDTO = new WorkoutItemReportRequestDTO();
        workoutItemReportRequestDTO.setId(1L);
        workoutItemReportRequestDTO.setSets(Arrays.asList(workoutItemSetReportRequestDTO));
        workoutReportRequestDTO.setItems(Arrays.asList(workoutItemReportRequestDTO)).setId(1L);
        InWorkoutItem inWorkoutItem = new InWorkoutItem();
        InWorkout inWorkout = new InWorkout();
        inWorkoutItem.setInWorkout(inWorkout);
        InProgram inProgram = new InProgram();
        inWorkout.setInProgram(inProgram);
        InUser inUser = new InUser();
        inUser.setId(10L);
        inProgram.setInUser(inUser);
        when(inWorkoutItemReportRepository.save(any(InWorkoutItemReport.class)))
                .thenAnswer(i -> i.getArguments()[0]);
        when(inWorkoutItemRepository.findById(eq(1L))).thenReturn(Optional.of(inWorkoutItem));
        when(inWorkoutRepository.findById(eq(1L))).thenReturn(Optional.of(getInWorkout()));
        reportWorkoutService.create("1", workoutReportRequestDTO);
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void create_empty_token() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        reportWorkoutService.create("", new WorkoutReportRequestDTO());
        verify(userService, never()).checkUserToken(anyString());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void create_empty_workout_item() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        WorkoutReportRequestDTO workoutReportRequestDTO = new WorkoutReportRequestDTO();
        WorkoutItemReportRequestDTO workoutItemReportRequestDTO = new WorkoutItemReportRequestDTO();
        workoutItemReportRequestDTO.setId(1L);
        workoutReportRequestDTO.setItems(Arrays.asList(workoutItemReportRequestDTO)).setId(1L);
        InWorkoutItem inWorkoutItem = new InWorkoutItem();
        InWorkout inWorkout = new InWorkout();
        inWorkoutItem.setInWorkout(inWorkout);
        InProgram inProgram = new InProgram();
        inWorkout.setInProgram(inProgram);
        InUser inUser = new InUser();
        inUser.setId(10L);
        inProgram.setInUser(inUser);
        when(inWorkoutItemRepository.findById(eq(1L))).thenReturn(Optional.empty());
        when(inWorkoutRepository.findById(eq(1L))).thenReturn(Optional.of(getInWorkout()));
        reportWorkoutService.create("1", workoutReportRequestDTO);
    }

    @Test(expected = ResourceNotFoundException.class)
    public void create_workout_not_found() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        WorkoutReportRequestDTO workoutReportRequestDTO = new WorkoutReportRequestDTO();
        WorkoutItemReportRequestDTO workoutItemReportRequestDTO = new WorkoutItemReportRequestDTO();
        workoutItemReportRequestDTO.setId(1L);
        workoutReportRequestDTO.setItems(Arrays.asList(workoutItemReportRequestDTO)).setId(1L);
        InWorkoutItem inWorkoutItem = new InWorkoutItem();
        InWorkout inWorkout = new InWorkout();
        inWorkoutItem.setInWorkout(inWorkout);
        InProgram inProgram = new InProgram();
        inWorkout.setInProgram(inProgram);
        InUser inUser = new InUser();
        inUser.setId(10L);
        inProgram.setInUser(inUser);
        when(inWorkoutRepository.findById(eq(1L))).thenReturn(Optional.empty());
        reportWorkoutService.create("1", workoutReportRequestDTO);
    }

    @Test(expected = UnauthorizedException.class)
    public void create_different_user_id() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser();
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        WorkoutReportRequestDTO workoutReportRequestDTO = new WorkoutReportRequestDTO();
        WorkoutItemReportRequestDTO workoutItemReportRequestDTO = new WorkoutItemReportRequestDTO();
        workoutItemReportRequestDTO.setId(1L);
        workoutReportRequestDTO.setItems(Arrays.asList(workoutItemReportRequestDTO)).setId(1L);
        InWorkoutItem inWorkoutItem = new InWorkoutItem();
        InWorkout inWorkout = new InWorkout();
        inWorkoutItem.setInWorkout(inWorkout);
        InProgram inProgram = new InProgram();
        inWorkout.setInProgram(inProgram);
        InUser inUser = new InUser();
        inUser.setId(1L);
        inProgram.setInUser(inUser);
        when(inWorkoutItemRepository.findById(eq(1L))).thenReturn(Optional.of(inWorkoutItem));
        when(inWorkoutRepository.findById(eq(1L))).thenReturn(Optional.of(getInWorkout()));
        reportWorkoutService.create("1", workoutReportRequestDTO);
    }
}
<file_sep>/src/main/resources/db/migration/V4.71__create_goal_type_table.sql
CREATE TABLE ptcore.goal_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50) NOT NULL
);

INSERT INTO ptcore.goal_type (name) VALUES
('weight'),
('percentage'),
('chart'),
('photos');

ALTER TABLE ptcore.goal ADD COLUMN goal_type_id BIGINT;

ALTER TABLE ptcore.goal
  ADD CONSTRAINT goal_type_id_fkey FOREIGN KEY (goal_type_id)
      REFERENCES ptcore.goal_type (id)
      ON UPDATE CASCADE ON DELETE CASCADE;
<file_sep>/src/main/resources/db/migration/V4.51__create_exercise_file_table.sql
CREATE TABLE ptcore.exercise_file (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    file_name VARCHAR(200) NOT NULL DEFAULT '',
    file_size BIGINT NOT NULL DEFAULT 0,
    file_type VARCHAR(100) NOT NULL DEFAULT '',
    data_url TEXT
);

CREATE TABLE ptcore.exercise_file_has_exercise (
    exercise_file_id BIGINT NOT NULL REFERENCES ptcore.exercise_file(id),
    exercise_id      BIGINT NOT NULL REFERENCES ptcore.exercise(id)
);
<file_sep>/src/main/java/com/osomapps/pt/programs/ParseProgram.java
package com.osomapps.pt.programs;

import java.time.LocalDateTime;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "parse_program", schema = "ptcore")
@DynamicInsert
public class ParseProgram {
    @Id
    @SequenceGenerator(
            name = "ParseProgramIdSequence",
            sequenceName = "ptcore.parse_program_id_seq",
            allocationSize = 1,
            initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ParseProgramIdSequence")
    Long id;

    LocalDateTime created;
    String name;
    String file_name;
    Long file_size;
    String file_type;
    String data_url;
    LocalDateTime updated;
    Boolean active;

    @OneToMany(mappedBy = "parseProgram")
    List<ParseGoal> parseGoals;

    @OneToMany(mappedBy = "parseProgram")
    List<ParseExercise> parseExercises;
}
<file_sep>/src/main/resources/db/migration/V4.17__rename_parse_result_table.sql
DROP TABLE ptcore.parse_result;
CREATE TABLE ptcore.parse_user (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    program_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(200),
    sheet_index INT NOT NULL DEFAULT 0,
    errors VARCHAR(1000),
    FOREIGN KEY (program_id) REFERENCES ptcore.program (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/java/com/osomapps/pt/reportphoto/package-info.java
/**
 *
 *
 * <h1>Report photo endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides report photo services
 * </ul>
 */
package com.osomapps.pt.reportphoto;
<file_sep>/src/main/java/com/osomapps/pt/programs/InWorkoutItemSet.java
package com.osomapps.pt.programs;

import com.fasterxml.jackson.annotation.JsonBackReference;
import java.time.LocalDateTime;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "in_workout_item_set", schema = "ptcore")
@DynamicInsert
public class InWorkoutItemSet {
    @Id
    @SequenceGenerator(
            name = "InWorkoutItemSetIdSequence",
            sequenceName = "ptcore.in_workout_item_set_id_seq",
            allocationSize = 1,
            initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "InWorkoutItemSetIdSequence")
    Long id;

    LocalDateTime created;
    Integer repetitions;
    Boolean repetitions_to_failure;
    Float weight;
    Boolean bodyweight;
    Integer time_in_sec;
    Integer speed;
    Integer incline;
    Integer resistance;
    Integer exercise_weight_percent;
    Float exercise_weight_in_kg;
    Float goal_weight_coef;
    Integer exercise_repetitions_percent;
    Integer goal_repetitions;
    Integer exercise_time_percent;
    Integer goal_time_in_sec;
    Integer exercise_speed_percent;
    Integer goal_speed;
    String exercise_basis;

    @ManyToOne
    @JoinColumn(name = "in_workout_item_id")
    @JsonBackReference
    InWorkoutItem inWorkoutItem;
}
<file_sep>/src/main/resources/db/migration/V4.75__create_in_user_photo_table.sql
DROP TABLE ptcore.in_user_goal_photo CASCADE;
DROP TABLE ptcore.in_user_goal_has_in_user_goal_photo CASCADE;

CREATE TABLE ptcore.in_user_photo (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    goal_id BIGINT NOT NULL,
    file_name VARCHAR(200) NOT NULL DEFAULT '',
    file_size BIGINT NOT NULL DEFAULT 0,
    file_type VARCHAR(100) NOT NULL DEFAULT '',
    data_url TEXT
);

CREATE TABLE ptcore.in_user_has_in_user_photo (
    in_user_id BIGINT NOT NULL REFERENCES ptcore.in_user(id),
    in_user_photo_id BIGINT NOT NULL REFERENCES ptcore.in_user_photo(id)
);
<file_sep>/src/main/java/com/osomapps/pt/tokenemail/TokenEmailService.java
package com.osomapps.pt.tokenemail;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.token.InUserLoginRepository;
import com.osomapps.pt.token.InUserLogout;
import com.osomapps.pt.token.InUserLogoutRepository;
import com.osomapps.pt.token.InUserRepository;
import com.osomapps.pt.user.UserGoalResponseDTO;
import com.osomapps.pt.user.UserLevel;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.data.util.Pair;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
class TokenEmailService {

    private final InUserRepository inUserRepository;
    private final InUserEmailRepository inUserEmailRepository;
    private final InUserLoginRepository inUserLoginRepository;
    private final InUserLogoutRepository inUserLogoutRepository;
    private final PasswordEncoder passwordEncoder;

    TokenEmailService(
            InUserRepository inUserRepository,
            InUserEmailRepository inUserEmailRepository,
            InUserLoginRepository inUserLoginRepository,
            InUserLogoutRepository inUserLogoutRepository,
            PasswordEncoder passwordEncoder) {
        this.inUserRepository = inUserRepository;
        this.inUserEmailRepository = inUserEmailRepository;
        this.inUserLoginRepository = inUserLoginRepository;
        this.inUserLogoutRepository = inUserLogoutRepository;
        this.passwordEncoder = passwordEncoder;
    }

    Pair<Boolean, InUserEmail> readOrCreateInUserEmail(TokenEmailRequestDTO tokenEmailRequest) {
        final InUserEmail inUserEmail;
        final boolean isNewLogin;
        final String email = tokenEmailRequest.getEmail().toLowerCase().trim();
        final List<InUserEmail> inUserEmails = inUserEmailRepository.findByLogin(email);
        if (inUserEmails.isEmpty()) {
            throw new UnauthorizedException("E-mail is not registered");
        } else {
            inUserEmail = inUserEmails.get(inUserEmails.size() - 1);
            if (!passwordEncoder.matches(
                    tokenEmailRequest.getPassword(), inUserEmail.getPassword())) {
                throw new UnauthorizedException("Wrong password");
            }
            final List<InUserLogout> inUserLogouts =
                    inUserLogoutRepository.findByToken(
                            inUserEmail
                                    .getInUser()
                                    .getInUserLogins()
                                    .get(inUserEmail.getInUser().getInUserLogins().size() - 1)
                                    .getToken());
            isNewLogin = !inUserLogouts.isEmpty();
        }
        return Pair.of(isNewLogin, inUserEmail);
    }

    TokenEmailResponseDTO createOrReadNewToken(
            TokenEmailRequestDTO tokenRequest, String remoteAddr) {
        final Pair<Boolean, InUserEmail> inUserEmailData = readOrCreateInUserEmail(tokenRequest);
        final boolean isNewLogin = inUserEmailData.getFirst();
        final InUserEmail inUserEmail = inUserEmailData.getSecond();
        final InUserLogin inUserLogin;
        if (isNewLogin) {
            inUserLogin = new InUserLogin();
        } else {
            inUserLogin =
                    inUserEmail
                            .getInUser()
                            .getInUserLogins()
                            .get(inUserEmail.getInUser().getInUserLogins().size() - 1);
        }
        final InUser inUser = inUserEmail.getInUser();
        inUser.getInUserEmails().add(inUserEmail);
        inUser.getInUserLogins().add(inUserLogin);
        final InUser savedInUser = inUserRepository.save(inUser);
        inUserLogin.setInUser(savedInUser);
        inUserLogin.setIp_address(remoteAddr);
        inUserLoginRepository.saveAndFlush(inUserLogin);
        inUserEmail.setInUser(savedInUser);
        inUserEmailRepository.save(inUserEmail);
        final TokenEmailResponseDTO tokenEmailResponseDTO = new TokenEmailResponseDTO();
        tokenEmailResponseDTO.setToken(inUserLogin.getToken());
        final UserSignupResponseDTO user = new UserSignupResponseDTO();
        user.setId(inUserEmail.getInUser().getId());
        user.setName(inUserEmail.getUser_name());
        user.setEmail(inUserEmail.getLogin());
        user.setGender(inUserEmail.getInUser().getD_sex());
        user.setAge(
                inUserEmail.getInUser().getAge() == null
                        ? null
                        : inUserEmail.getInUser().getAge().intValue());
        user.setBirthday(inUserEmail.getInUser().getBirthday());
        user.setAvatar_dataurl(inUserEmail.getInUser().getAvatar_dataurl());
        if (inUser.getD_level() != null) {
            user.setLevel(UserLevel.of(Integer.parseInt(inUser.getD_level())));
        }
        user.setGoals(
                inUser.getInUserGoals().stream()
                        .map(
                                inUserGoal -> {
                                    Map<String, Integer> map = null;
                                    try {
                                        map =
                                                inUserGoal.getGoal_value() == null
                                                        ? null
                                                        : new ObjectMapper()
                                                                .readValue(
                                                                        inUserGoal.getGoal_value(),
                                                                        new TypeReference<
                                                                                Map<
                                                                                String,
                                                                                Integer>>() {});
                                    } catch (IOException ex) {
                                    }
                                    return new UserGoalResponseDTO()
                                            .setId(inUserGoal.getGoalId())
                                            .setValues(map);
                                })
                        .collect(Collectors.toList()));
        user.setHeight(inUser.getHeight() == null ? null : inUser.getHeight().longValue());
        user.setWeight(inUser.getWeight() == null ? null : inUser.getWeight().longValue());
        tokenEmailResponseDTO.setUser(user);
        return tokenEmailResponseDTO;
    }

    void deleteToken(String token, String remoteAddr) {
        final List<InUserLogin> inUserLogins = inUserLoginRepository.findByToken(token);
        if (!inUserLogins.isEmpty()) {
            final List<InUserLogout> inUserLogouts = inUserLogoutRepository.findByToken(token);
            if (!inUserLogouts.isEmpty()) {
                throw new UnauthorizedException("Invalid token");
            }
            InUserLogout inUserLogout = new InUserLogout();
            inUserLogout.setToken(token);
            inUserLogout.setInUser(inUserLogins.get(inUserLogins.size() - 1).getInUser());
            inUserLogout.setIp_address(remoteAddr);
            inUserLogoutRepository.saveAndFlush(inUserLogout);
        } else {
            throw new UnauthorizedException("Token not found");
        }
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseServiceTest.java
package com.osomapps.pt.admin.exercise;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.exercises.Exercise;
import com.osomapps.pt.exercises.ExerciseBodypart;
import com.osomapps.pt.exercises.ExerciseFilePreview;
import com.osomapps.pt.exercises.ExerciseFilePreviewRepository;
import com.osomapps.pt.exercises.ExerciseFileRepository;
import com.osomapps.pt.exercises.ExerciseRepository;
import com.osomapps.pt.tokenemail.DataurlValidator;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Sort;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseServiceTest {

    @Mock private ExerciseRepository exerciseRepository;
    @Mock private ExerciseBodypartRepository exerciseBodypartRepository;
    @Mock private ExerciseTypeRepository exerciseTypeRepository;
    @Mock private ExerciseInputRepository exerciseInputRepository;
    @Mock private ExerciseOutputRepository exerciseOutputRepository;
    @Mock private ExerciseFileRepository exerciseFileRepository;
    @Mock private ExerciseFilePreviewRepository exerciseFilePreviewRepository;
    @Mock private DictionaryService dictionaryService;
    @Mock private DataurlValidator dataurlValidator;

    @InjectMocks private AdminExerciseService tokenService;

    @Test
    public void findAll() {
        tokenService.findAll();
        verify(exerciseRepository).findAll(any(Sort.class));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void findOne_not_found() {
        tokenService.findOne(1L);
    }

    @Test
    public void findOne() {
        ExerciseBodypart existedExerciseBodypart = new ExerciseBodypart();
        existedExerciseBodypart.setId(1L);
        existedExerciseBodypart.setDExerciseBodypartName("10");
        Exercise savedExercise = new Exercise();
        savedExercise.setId(1L);
        savedExercise.setDExerciseName("10");
        savedExercise.setExerciseBodypart(existedExerciseBodypart);
        when(exerciseRepository.findById(eq(1L))).thenReturn(Optional.of(savedExercise));
        tokenService.findOne(1L);
        verify(exerciseRepository).findById(eq(1L));
    }

    @Test
    public void create() {
        ExerciseRequestDTO exerciseRequestDTO = new ExerciseRequestDTO();
        exerciseRequestDTO.setBodypart(new ExerciseBodypartRequestDTO(1L));
        exerciseRequestDTO.setNameEn("nameEn");
        exerciseRequestDTO.setNameEn("nameNo");
        exerciseRequestDTO.setTypes(Collections.emptyList());
        exerciseRequestDTO.setInputs(Collections.emptyList());
        exerciseRequestDTO.setOutputs(Collections.emptyList());
        exerciseRequestDTO.setFiles(
                Arrays.asList(
                        new ExerciseFileRequestDTO()
                                .setData_url(
                                        "data:image/gif;base64,"
                                                + "R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///"
                                                + "yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjg"
                                                + "aORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7")));
        ExerciseBodypart existedExerciseBodypart = new ExerciseBodypart();
        existedExerciseBodypart.setId(1L);
        existedExerciseBodypart.setDExerciseBodypartName("10");
        when(exerciseBodypartRepository.findById(eq(1L)))
                .thenReturn(Optional.of(existedExerciseBodypart));
        Exercise savedExercise = new Exercise();
        savedExercise.setId(1L);
        savedExercise.setDExerciseName("10");
        savedExercise.setExerciseBodypart(existedExerciseBodypart);
        savedExercise.setExerciseFiles(Arrays.asList(new ExerciseFilePreview()));
        when(exerciseRepository.save(any(Exercise.class))).thenReturn(savedExercise);
        tokenService.create(exerciseRequestDTO);
        verify(exerciseRepository).save(any(Exercise.class));
    }

    @Test(expected = UnauthorizedException.class)
    public void create_invalid_data_url() {
        ExerciseRequestDTO exerciseRequestDTO = new ExerciseRequestDTO();
        exerciseRequestDTO.setBodypart(new ExerciseBodypartRequestDTO(1L));
        exerciseRequestDTO.setNameEn("nameEn");
        exerciseRequestDTO.setNameEn("nameNo");
        exerciseRequestDTO.setTypes(Collections.emptyList());
        exerciseRequestDTO.setInputs(Collections.emptyList());
        exerciseRequestDTO.setOutputs(Collections.emptyList());
        exerciseRequestDTO.setFiles(Arrays.asList(new ExerciseFileRequestDTO()));
        ExerciseBodypart existedExerciseBodypart = new ExerciseBodypart();
        existedExerciseBodypart.setId(1L);
        existedExerciseBodypart.setDExerciseBodypartName("10");
        when(exerciseBodypartRepository.findById(eq(1L)))
                .thenReturn(Optional.of(existedExerciseBodypart));
        Exercise savedExercise = new Exercise();
        savedExercise.setId(1L);
        savedExercise.setDExerciseName("10");
        savedExercise.setExerciseBodypart(existedExerciseBodypart);
        savedExercise.setExerciseFiles(Arrays.asList(new ExerciseFilePreview()));
        tokenService.create(exerciseRequestDTO);
    }

    @Test(expected = ResourceNotFoundException.class)
    public void update_not_found() {
        tokenService.update(1L, new ExerciseRequestDTO());
    }

    @Test
    public void update() {
        ExerciseRequestDTO exerciseRequestDTO = new ExerciseRequestDTO();
        exerciseRequestDTO.setBodypart(new ExerciseBodypartRequestDTO(1L));
        exerciseRequestDTO.setNameEn("nameEn");
        exerciseRequestDTO.setNameEn("nameNo");
        exerciseRequestDTO.setTypes(Collections.emptyList());
        exerciseRequestDTO.setInputs(Collections.emptyList());
        exerciseRequestDTO.setOutputs(Collections.emptyList());
        exerciseRequestDTO.setFiles(
                Arrays.asList(
                        new ExerciseFileRequestDTO()
                                .setData_url(
                                        "data:image/gif;base64,"
                                                + "R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///"
                                                + "yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjg"
                                                + "aORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7")));
        Exercise existedExercise = new Exercise();
        when(exerciseRepository.findById(eq(1L))).thenReturn(Optional.of(existedExercise));
        ExerciseBodypart existedExerciseBodypart = new ExerciseBodypart();
        existedExerciseBodypart.setId(1L);
        existedExerciseBodypart.setDExerciseBodypartName("10");
        when(exerciseBodypartRepository.findById(eq(1L)))
                .thenReturn(Optional.of(existedExerciseBodypart));
        Exercise savedExercise = new Exercise();
        savedExercise.setId(1L);
        savedExercise.setDExerciseName("10");
        savedExercise.setExerciseBodypart(existedExerciseBodypart);
        savedExercise.setExerciseFiles(Arrays.asList(new ExerciseFilePreview()));
        when(exerciseRepository.save(any(Exercise.class))).thenReturn(savedExercise);
        tokenService.update(1L, exerciseRequestDTO);
        verify(exerciseRepository).save(any(Exercise.class));
    }

    @Test(expected = UnauthorizedException.class)
    public void update_invalid_data_url() {
        ExerciseRequestDTO exerciseRequestDTO = new ExerciseRequestDTO();
        exerciseRequestDTO.setBodypart(new ExerciseBodypartRequestDTO(1L));
        exerciseRequestDTO.setNameEn("nameEn");
        exerciseRequestDTO.setNameEn("nameNo");
        exerciseRequestDTO.setTypes(Collections.emptyList());
        exerciseRequestDTO.setInputs(Collections.emptyList());
        exerciseRequestDTO.setOutputs(Collections.emptyList());
        exerciseRequestDTO.setFiles(Arrays.asList(new ExerciseFileRequestDTO()));
        Exercise existedExercise = new Exercise();
        when(exerciseRepository.findById(eq(1L))).thenReturn(Optional.of(existedExercise));
        ExerciseBodypart existedExerciseBodypart = new ExerciseBodypart();
        existedExerciseBodypart.setId(1L);
        existedExerciseBodypart.setDExerciseBodypartName("10");
        when(exerciseBodypartRepository.findById(eq(1L)))
                .thenReturn(Optional.of(existedExerciseBodypart));
        Exercise savedExercise = new Exercise();
        savedExercise.setId(1L);
        savedExercise.setDExerciseName("10");
        savedExercise.setExerciseBodypart(existedExerciseBodypart);
        savedExercise.setExerciseFiles(Arrays.asList(new ExerciseFilePreview()));
        tokenService.update(1L, exerciseRequestDTO);
    }

    @Test(expected = ResourceNotFoundException.class)
    public void delete_not_found() {
        tokenService.delete(1L);
    }

    @Test
    public void delete() {
        ExerciseBodypart existedExerciseBodypart = new ExerciseBodypart();
        existedExerciseBodypart.setId(1L);
        existedExerciseBodypart.setDExerciseBodypartName("10");
        Exercise savedExercise = new Exercise();
        savedExercise.setId(1L);
        savedExercise.setDExerciseName("10");
        savedExercise.setExerciseBodypart(existedExerciseBodypart);
        when(exerciseRepository.findById(eq(1L))).thenReturn(Optional.of(savedExercise));
        tokenService.delete(1L);
        verify(exerciseRepository).deleteById(eq(1L));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/CustomErrorControllerTest.java
package com.osomapps.pt;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.context.request.WebRequest;

@RunWith(MockitoJUnitRunner.class)
public class CustomErrorControllerTest {

    @Mock private ErrorAttributes errorAttributes;

    @InjectMocks private CustomErrorController customErrorController;

    @Test
    public void error() {
        customErrorController.error(mock(WebRequest.class), new MockHttpServletResponse());
        verify(errorAttributes).getErrorAttributes(any(WebRequest.class), any());
    }

    @Test
    public void getErrorPath() {
        assertThat(customErrorController.getErrorPath(), equalTo("/error"));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/reportworkout/WorkoutItemSetReportRequestDTOTest.java
package com.osomapps.pt.reportworkout;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutItemSetReportRequestDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new WorkoutItemSetReportRequestDTO(1L, 1, 1, true, 1, 1, 1, 1), notNullValue());
    }

    @Test
    public void setters() {
        WorkoutItemSetReportRequestDTO workoutItemSetReportRequestDTO =
                new WorkoutItemSetReportRequestDTO();
        workoutItemSetReportRequestDTO.setId(1L);
        assertThat(workoutItemSetReportRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        WorkoutItemSetReportRequestDTO workoutItemSetReportRequestDTO =
                new WorkoutItemSetReportRequestDTO();
        workoutItemSetReportRequestDTO.getId();
        assertThat(workoutItemSetReportRequestDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/static/scripts/views/users.js
/*jshint browser: true*/
/*global define, console*/
define([
    'jquery',
    'underscore',
    'backbone',
    'marionette',
    'moment',
    'app',
    'bootstrapModals',
    'bootstrapTab'
],
function ($, _, Backbone, Marionette, moment, App, BackboneBootstrapModals) {
  'use strict';

  var Layout = Marionette.Layout.extend({
    regions: {
      mainUsers: '#usersMappingConfig',
      mainExercises: '#exercisesMappingConfig',
      mainGoals: '#goalsMappingConfig',
      mainPrograms: '#programsMappingConfig',
      mainCertificates: '#certificatesMappingConfig',
      mainEmails: '#emailsMappingConfig'
    },
    template: _.template([
      '<!-- Nav tabs -->',
      '<ul class="nav nav-tabs">',
      '  <li class="active"><a href="#user" data-toggle="tab">Users</a></li>',
      '  <li><a href="#exercise" data-toggle="tab">Exercises</a></li>',
      '  <li><a href="#goal" data-toggle="tab">Goals</a></li>',
      '  <li><a href="#program" data-toggle="tab" class="js-admin-config">Programs</a></li>',
      '  <li><a href="#certificate" data-toggle="tab" class="js-admin-config">Certificates</a></li>',
      '  <li><a href="#email" data-toggle="tab" class="js-admin-config">Email templates</a></li>',
      '</ul>',
      '<!-- Tab panes -->',
      '<div class="tab-content">',
      '  <div class="tab-pane active" id="user">',
      '    <div id="usersMappingConfig"></div>',
      '  </div>',
      '  <div class="tab-pane" id="exercise">',
      '    <div id="exercisesMappingConfig"></div>',
      '  </div>',
      '  <div class="tab-pane" id="goal">',
      '    <div id="goalsMappingConfig"></div>',
      '  </div>',
      '  <div class="tab-pane" id="program">',
      '    <div id="programsMappingConfig"></div>',
      '  </div>',
      '  <div class="tab-pane" id="certificate">',
      '    <div id="certificatesMappingConfig"></div>',
      '  </div>',
      '  <div class="tab-pane" id="email">',
      '    <div id="emailsMappingConfig"></div>',
      '  </div>',
      '</div>'
    ].join(''))
  });

  var EmptyView = Marionette.ItemView.extend({
        tagName: 'tr',
        template: _.template('<td colspan="8">There are no users available.</td>')
  });

  var EmptyProgramTableItemView = Marionette.ItemView.extend({
        tagName: 'tr',
        template: _.template('<td colspan="5">There are no programs</td>')
  });

  var EmptyWorkoutTableItemView = Marionette.ItemView.extend({
        tagName: 'tr',
        template: _.template('<td colspan="4">There are no workouts</td>')
  });

  var EmptyExerciseTableItemView = Marionette.ItemView.extend({
        tagName: 'tr',
        template: _.template('<td colspan="3">There are no exercises</td>')
  });

  var User = Marionette.ItemView.extend({
    tagName: 'tr',
    className: function() {
      return this.collection._modelId === this.model.get('id') ? 'selectedId' : '';
    },
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ email }}',
      '</td>',
      '<td>',
        '{{ type == null ? "" : type.nameEn }}',
      '</td>',
      '<td>',
        '<a type="button" class="btn btn-default btn-sm" href="/api/v1/admin/user-program-file/{{ id }}/program_for_user_{{ id }}.xlsx" download>',
          '<i class="glyphicon glyphicon-download"></i>',
        '</a>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-value">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-edit-value">',
          '<i class="glyphicon glyphicon-edit"></i>',
        '</button>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-delete-value">',
          '<i class="glyphicon glyphicon-remove"></i>',
        '</button>',
      '</td>'
    ].join('')),

    initialize: function(options) {
      this.collection = options.collection;
    },
    events: {
      'click .js-view-value': 'viewUser',
      'click .js-edit-value': 'editUser',
      'click .js-delete-value': 'deleteUser'
    },
    viewUser: function() {
      this.collection.trigger('user:view', this.model);
    },
    editUser: function() {
      this.collection.trigger('user:new', this.model);
    },
    deleteUser: function(evt) {
      evt.preventDefault();
      var model = this.model;
      var collection = this.collection;
      var modal = new BackboneBootstrapModals.ConfirmationModal({
        label: 'Confirm Action',
        text: 'Are you sure you want to delete user ' + model.get('name') + ' (' + model.get('id') + ')' + '?',
        onConfirm: function() {

          model.destroy()
            .done(function() {
            })
            .fail(function (xhr) {
              App.vent.trigger('xhr:error', 'User ' + model.get('id') + ' delete was failed');
            })
            .always(function() {
              collection.fetch();
            });
        }
      });
      modal.render();
    }
  });

  var Users = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: User,
    emptyView: EmptyView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Users </h3>',
      '</div>',
      '<button class="btn btn-primary js-new-user" style="margin: 10px;">',
        'New user',
      '</button>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Name</th>',
            '<th>E-mail</th>',
            '<th>Type</th>',
            '<th></th>',
            '<th></th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    collectionEvents: {
      'sync': 'render'
    },
    events: {
      'click .js-new-user': 'newUser'
    },
    newUser: function() {
      this.collection.trigger('user:new');
    }
  });

  var ViewUserLayout = Marionette.Layout.extend({
    template: _.template([
      '<div class="panel panel-primary">',
        '<div class="panel-heading">',
          '<h3 class="panel-title"> View user </h3>',
        '</div>',
        '<div id="buttons"/>',
        '<div id="inputForm"/>',
        '<div id="programTable"/>',
        '<div id="workoutTable"/>',
        '<div id="exerciseTable"/>',
      '</div>'
    ].join('')),
    tagName: 'form',
    className: 'form-horizontal',
    regions: {
      buttons: '#buttons',
      inputForm: '#inputForm',
      programTable: '#programTable',
      workoutTable: '#workoutTable',
      exerciseTable: '#exerciseTable'
    },
    onShow: function() {
      this.buttons.show(new ViewUserButtons({model: this.model}));
      this.inputForm.show(new ViewUserInputForm({model: this.model}));
      this.programTable.show(new ProgramTableForm({model: this.model,
          collection: new Backbone.Collection(_.last(this.model.get('programs'), 3))}));
      var workouts = new Backbone.Collection();
      this.workoutTable.show(new WorkoutTableForm({model: this.model,
          collection: workouts}));
      this.model.on('refresh:workouts', function(data) {
          workouts.set(data);
          workouts.trigger('sync');
      });
      var exercises = new Backbone.Collection();
      this.exerciseTable.show(new ExerciseTableForm({model: this.model,
          collection: exercises}));
      this.model.on('refresh:exercises', function(data) {
          exercises.set(data);
          exercises.trigger('sync');
      });
    }
  });

  var NewUserLayout = Marionette.Layout.extend({
    template: _.template([
      '<div class="panel panel-primary">',
        '<div class="panel-heading">',
          '<h3 class="panel-title"> {{ getHeader() }} </h3>',
        '</div>',
        '<div id="buttons"/>',
        '<div id="inputForm"/>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getHeader: function () {
          return model.isNew() ? 'New user' : 'Edit user';
        }
      };
    },
    tagName: 'form',
    className: 'form-horizontal',
    regions: {
      buttons: '#buttons',
      inputForm: '#inputForm'
    },
    onShow: function() {
      this.buttons.show(new NewUserButtons({model: this.model}));
      this.inputForm.show(new NewUserInputForm({model: this.model}));
    }
  });

  var ViewUserButtons = Marionette.ItemView.extend({
    template: _.template([
      '<div class="btn-group">',
        '<button class="btn btn-default js-back" style="margin: 10px 0 0 10px;">',
          'Back',
        '</button>',
      '</div>'
    ].join('')),
    events: {
      'click .js-back': 'back'
    },
    modelEvents: {
      'change': 'render'
    },
    initialize: function(options) {
      this._model = options.model.clone();
    },
    back: function(evt) {
      evt.preventDefault();
      this.model.trigger('user:back', this.model.get('id'));
    }
  });

  var NewUserButtons = Marionette.ItemView.extend({
    template: _.template([
      '<div class="btn-group">',
        '<button class="btn btn-default js-back" style="margin: 10px 0 0 10px;">',
          'Back',
        '</button>',
        '<button class="btn btn-danger js-save  {{ getSaveDisabled() }}" style="margin: 10px 0 0 0; min-width: 100px;">',
          'Save',
        '</button>',
        '<button class="btn btn-default js-discard" style="margin: 10px 0 0 0px;">',
          'Discard',
        '</button>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getSaveDisabled: function () {
          return view.model.isValid() ? '' : 'disabled';
        }
      };
    },
    events: {
      'click .js-back': 'back',
      'click .js-save': 'save',
      'click .js-discard': 'discard'
    },
    modelEvents: {
      'change': 'render'
    },
    initialize: function(options) {
      this._model = options.model.clone();
    },
    back: function(evt) {
      evt.preventDefault();
      this.model.trigger('user:back', this.model.get('id'));
    },
    save: function(evt) {
      evt.preventDefault();
      var model = this.model;
      this.model.save().done(function(data) {
        model.trigger('user:back', model.get('id'), data);
      })
      .fail(function (xhr) {
        App.vent.trigger('xhr:error', 'User save was failed');
      });
    },
    discard: function(evt) {
      evt.preventDefault();
      this.model.set(this._model.toJSON());
      this.model.trigger('sync');
    }
  });

  var ProgramTableItem = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ _.map(workouts, function(item) {return item.name;}) }}',
      '</td>',
      '<td>',
        '{{ formatDate(created) }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-workouts">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    templateHelpers: function() {
      return {
        formatDate: function(dateTime) {
          return moment(dateTime).format('DD.MM.YYYY HH:mm');
        }
      };
    },
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-workouts': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._programName = this.model.get('name');
      this._model.trigger('refresh:workouts', this.model.get('workouts'));
      this._model._workoutName = '';
      this._model.trigger('refresh:exercises', []);
    }
  });

  var WorkoutTableItem = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ _.map(items, function(item) {return item.exercise_name;}) }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-exercises">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-exercises': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._workoutName = this.model.get('name');
      this._model.trigger('refresh:exercises', this.model.get('items'));
    }
  });

  var ExerciseTableItem = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ exercise_name }}',
      '</td>',
      '<td>',
        '{{ getInputs() }}',
      '</td>',
      '<td>',
        '{{ getOutputs() }}',
      '</td>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getInputs: function () {
          return 'sets ' + model.get('sets') +
                  (_.isEmpty(_.compact(model.get('timeInSec'))) ? '' : ', time in sec ' + model.get('timeInSec')) +
                  (_.isEmpty(_.compact(model.get('repetitions'))) ? '' : ', repetitions ' + model.get('repetitions')) +
                  (_.isEmpty(_.compact(model.get('weight'))) ? '' : ', weight ' + model.get('weight'));
        },
        getOutputs: function () {
          return (_.isNull(model.get('reportSets')) ? '' : 'sets ' + model.get('reportSets')) +
                  (_.isEmpty(_.compact(model.get('reportRepetitions'))) ? '' : ', repetitions ' + model.get('reportRepetitions').join(', ')) +
                  (_.isEmpty(_.compact(model.get('reportWeight'))) ? '' : ', weight ' + model.get('reportWeight').join(', '));
        }
      };
    }
  });

  var ProgramTableForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ProgramTableItem,
    emptyView: EmptyProgramTableItemView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Assigned programs </h3>',
      '</div>',
      '<button class="btn btn-primary js-reload-data" style="margin: 10px;">',
        'Refresh',
      '</button>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Program name</th>',
            '<th>Workouts</th>',
            '<th>Updated</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    modelEvents: {
      'sync': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    },
    events: {
      'click .js-reload-data': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      var view = this;
      this.model.clone().fetch().done(function(data) {
        view.collection.set(_.last(data.programs, 3));
        view.model._programName = '';
        view.model._workoutName = '';
        view.model.trigger('refresh:workouts', []);
        view.model.trigger('refresh:exercises', []);
      });
    }
  });

  var WorkoutTableForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: WorkoutTableItem,
    emptyView: EmptyWorkoutTableItemView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Assigned workouts {{ _.isEmpty(getProgramName()) ? "" : "for " + getProgramName() }}</h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Workout name</th>',
            '<th>Exercises</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getProgramName: function () {
          return view.model._programName;
        }
      };
    },
    modelEvents: {
      'sync': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ExerciseTableForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ExerciseTableItem,
    emptyView: EmptyExerciseTableItemView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Assigned exercises {{ _.isEmpty(getWorkoutName()) ? "" : "for " + getWorkoutName() }}</h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Exercise name</th>',
            '<th>Inputs</th>',
            '<th>Outputs</th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getWorkoutName: function () {
          return view.model._workoutName;
        }
      };
    },
    modelEvents: {
      'sync': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ViewUserInputForm = Marionette.ItemView.extend({
    className: 'user-input-form',
    template: _.template([
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">ID</label>',
        '<div class="col-sm-8">',
          '<p class="form-control-static">',
            ' {{ id }}',
          '</p>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Type</label>',
        '<div class="col-sm-8">',
          '{{ getTypes() }}',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Gender</label>',
        '<div class="col-sm-8">',
          '{{ getGenders() }}',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Level</label>',
        '<div class="col-sm-8">',
          '{{ getLevels() }}',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Goals</label>',
        '<div class="col-sm-8">',
          '{{ getGoals() }}',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Weight, kg</label>',
        '<div class="col-sm-8">',
          '<textarea id="user-weight" class="form-control" rows="3" placeholder="Please enter weight" name="address" required="true" readonly>',
            '{{ weight }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Name</label>',
        '<div class="col-sm-8">',
          '<textarea id="user-name" class="form-control" rows="3" placeholder="Please enter name" name="address" required="true" readonly>',
            '{{ name }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Email</label>',
        '<div class="col-sm-8">',
          '<textarea id="user-email" class="form-control" rows="3" placeholder="Please enter email" name="address" required="true" readonly>',
            '{{ email }}',
          '</textarea>',
        '</div>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getTypes: function() {
          var types = model._types || [];
          var result = _.compact(_.map(types, function(item) {
            if (_.isNull(item.id)) {
              return '';
            }
            return !!model.get('type') && model.get('type').id === item.id ? item.nameEn : null;
          }));
          return result.join('');
        },
        getGenders: function() {
          var genders = model._genders || [];
          var result = _.compact(_.map(genders, function(item) {
            if (_.isNull(item.id)) {
              return '';
            }
            return !!model.get('gender') && model.get('gender') === item.id ? item.name : null;
          }));
          return result.join('');
        },
        getLevels: function() {
          var levels = model._levels || [];
          var result = _.compact(_.map(levels, function(item) {
            if (_.isNull(item.id)) {
              return '';
            }
            return !!model.get('level') && model.get('level') === item.id ? item.name : null;
          }));
          return result.join('');
        },
        getGoals: function() {
          var goals = model._goals || [];
          var modelGoals = _.map(model.get('goals'), function(item) {
             return item.id;
          });
          var result = _.map(goals, function(item) {
            if (_.isNull(item.id)) {
              return '';
            }
            return _.contains(modelGoals, item.id) ? _.compact([item.title, item.title2]).join(',') : '';
          });
          return _.compact(result).join(', ');
        }
      };
    },
    modelEvents: {
      'sync': 'render'
    },
    events: {
      'input #user-weight': 'inputWeight',
      'input #user-name': 'inputName',
      'input #user-email': 'inputEmail'
    },
    ui: {
      weight: '#user-weight',
      userType: '#user-type',
      name: '#user-name',
      email: '#user-email'
    },
    inputWeight: function() {
      this.model.set('weight', _.isEmpty(this.ui.weight.val()) ? null : parseInt(this.ui.weight.val(), 10));
    },
    inputName: function() {
      this.model.set('name', this.ui.name.val());
    },
    inputEmail: function() {
      this.model.set('email', this.ui.email.val());
    },
    onShow: function() {
      this.onRender();
    },
    onRender: function() {
      var view = this;
      $('.selectpicker').selectpicker({
        style: 'btn-default',
        size: false
      });
      this.ui.userType.on('changed.bs.select', function (e) {
        view.model.set('type', {id: parseInt(e.target.value, 10) });
      });
    }
  });

  var NewUserInputForm = Marionette.ItemView.extend({
    className: 'user-input-form',
    template: _.template([
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">ID</label>',
        '<div class="col-sm-8">',
          '<p class="form-control-static">',
            ' {{ id }}',
          '</p>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Type</label>',
        '<div class="col-sm-8">',
          '<select id="user-type" class="selectpicker show-tick">',
            '{{ getTypes() }}',
          '</select>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Gender</label>',
        '<div class="col-sm-8">',
          '<select id="user-gender" class="selectpicker show-tick">',
            '{{ getGenders() }}',
          '</select>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Level</label>',
        '<div class="col-sm-8">',
          '<select id="user-level" class="selectpicker show-tick">',
            '{{ getLevels() }}',
          '</select>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Goals</label>',
        '<div class="col-sm-8">',
          '<select id="user-goal" class="selectpicker show-tick" multiple data-max-options="2">',
            '{{ getGoals() }}',
          '</select>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Weight, kg</label>',
        '<div class="col-sm-8">',
          '<textarea id="user-weight" class="form-control" rows="3" placeholder="Please enter weight" name="address" required="true">',
            '{{ weight }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Name</label>',
        '<div class="col-sm-8">',
          '<textarea id="user-name" class="form-control" rows="3" placeholder="Please enter name" name="address" required="true">',
            '{{ name }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Email</label>',
        '<div class="col-sm-8">',
          '<textarea id="user-email" class="form-control" rows="3" placeholder="Please enter email" name="address" required="true">',
            '{{ email }}',
          '</textarea>',
        '</div>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getTypes: function() {
          var types = model._types || [];
          var result = _.map(types, function(item) {
            if (_.isNull(item.id)) {
              return '<option data-hidden="true"></option>';
            }
            return '<option value="' + item.id + '"' +
              (!!model.get('type') && model.get('type').id === item.id ? ' selected' : '') +
              '>' + item.nameEn + '</option>';
          });
          return result;
        },
        getGenders: function() {
          var genders = model._genders || [];
          var result = _.map(genders, function(item) {
            if (_.isNull(item.id)) {
              return '<option></option>';
            }
            return '<option value="' + item.id + '"' +
              (!!model.get('gender') && model.get('gender') === item.id ? ' selected' : '') +
              '>' + item.name + '</option>';
          });
          return result;
        },
        getLevels: function() {
          var levels = model._levels || [];
          var result = _.map(levels, function(item) {
            if (_.isNull(item.id)) {
              return '<option></option>';
            }
            return '<option value="' + item.id + '"' +
              (!!model.get('level') && model.get('level') === item.id ? ' selected' : '') +
              '>' + item.name + '</option>';
          });
          return result;
        },
        getGoals: function() {
          var goals = model._goals || [];
          var modelGoals = _.map(model.get('goals'), function(item) {
             return item.id;
          });
          var result = _.map(goals, function(item) {
            if (_.isNull(item.id)) {
              return '<option data-hidden="true"></option>';
            }
            return '<option value="' + item.id + '"' +
              (_.contains(modelGoals, item.id) ? ' selected' : '') +
              '>' + item.title + (_.isNull(item.title2) ? '' : ', ' + item.title2) + '</option>';
          });
          return result;
        }
      };
    },
    modelEvents: {
      'sync': 'render'
    },
    events: {
      'input #user-weight': 'inputWeight',
      'input #user-name': 'inputName',
      'input #user-email': 'inputEmail'
    },
    ui: {
      userType: '#user-type',
      userGender: '#user-gender',
      userLevel: '#user-level',
      userGoal: '#user-goal',
      weight: '#user-weight',
      name: '#user-name',
      email: '#user-email'
    },
    inputWeight: function() {
      this.model.set('weight', _.isEmpty(this.ui.weight.val()) ? null : parseInt(this.ui.weight.val(), 10));
    },
    inputName: function() {
      this.model.set('name', this.ui.name.val());
    },
    inputEmail: function() {
      this.model.set('email', this.ui.email.val());
    },
    onShow: function() {
      this.onRender();
    },
    onRender: function() {
      var view = this;
      $('.selectpicker').selectpicker({
        style: 'btn-default',
        size: false
      });
      this.ui.userType.on('changed.bs.select', function (e) {
        view.model.set('type', {id: parseInt(e.target.value, 10) });
      });
      this.ui.userGender.on('changed.bs.select', function (e) {
        view.model.set('gender', _.isEmpty(e.target.value) ? null : e.target.value);
      });
      this.ui.userLevel.on('changed.bs.select', function (e) {
        view.model.set('level', _.isEmpty(e.target.value) ? null : parseInt(e.target.value, 10));
      });
      this.ui.userGoal.on('changed.bs.select', function (e) {
        var selectedGoals = _.map(e.target.selectedOptions, function(item) {
            return {id: parseInt(item.value, 10) };
        });
        view.model.set('goals', selectedGoals);
      });
    }
  });

  return {
    Users: Users,
    ViewUserLayout: ViewUserLayout,
    NewUserLayout: NewUserLayout,
    Layout: Layout
  };

});
<file_sep>/src/main/resources/db/migration/V4.2__add_ip_address_for_logout_table.sql
ALTER TABLE ptcore.in_user_logout ADD COLUMN ip_address VARCHAR(40);<file_sep>/src/test/java/com/osomapps/pt/tokenemail/EmailResetResourceTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class EmailResetResourceTest {

    @Mock private TokenEmailSignupService tokenEmailSignupService;

    @InjectMocks private EmailResetResource emailResetResource;

    @Test
    public void list() {
        assertThat(emailResetResource.list().size(), equalTo(0));
    }

    @Test
    public void create() {
        when(tokenEmailSignupService.resetToken(anyString())).thenReturn(Optional.empty());
        emailResetResource.create("");
        verify(tokenEmailSignupService).resetToken(anyString());
    }

    @Test
    public void create_true() {
        when(tokenEmailSignupService.resetToken(anyString())).thenReturn(Optional.of("new"));
        emailResetResource.create("");
        verify(tokenEmailSignupService).resetToken(anyString());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/certificate/AdminCertificateResourceTest.java
package com.osomapps.pt.admin.certificate;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminCertificateResourceTest {

    @Mock private AdminCertificateService adminCertificateService;

    @InjectMocks private AdminCertificateResource adminCertificateResource;

    @Test
    public void findOne() {
        adminCertificateResource.findOne(1L);
        verify(adminCertificateService).findOne(anyLong());
    }

    @Test
    public void create() {
        adminCertificateResource.create(new CertificateRequestDTO());
        verify(adminCertificateService).create(any(CertificateRequestDTO.class));
    }

    @Test
    public void update() {
        adminCertificateResource.update(1L, new CertificateRequestDTO());
        verify(adminCertificateService).update(anyLong(), any(CertificateRequestDTO.class));
    }

    @Test
    public void delete() {
        adminCertificateResource.delete(1L);
        verify(adminCertificateService).delete(anyLong());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/ptuser/AdminPtUserServiceTest.java
package com.osomapps.pt.admin.ptuser;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.UnauthorizedException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminPtUserServiceTest {

    @Mock private PtUserRepository ptUserRepository;
    @Mock private PtRoleRepository ptRoleRepository;
    @InjectMocks private AdminPtUserService adminPtUserService;

    @Test
    public void findAll() {
        when(ptUserRepository.findAll()).thenReturn(Arrays.asList(new PtUser()));
        List<PtUserResponseDTO> responseDTOs = adminPtUserService.findAll();
        assertThat(responseDTOs.size(), equalTo(1));
    }

    @Test(expected = ResourceNotFoundException.class)
    public void findOne_not_found() {
        adminPtUserService.findOne(1L);
    }

    @Test
    public void findOne() {
        when(ptUserRepository.findById(eq(1L))).thenReturn(Optional.of(new PtUser()));
        PtUserResponseDTO responseDTO = adminPtUserService.findOne(1L);
        assertThat(responseDTO, notNullValue());
    }

    @Test
    public void create() {
        when(ptUserRepository.save((PtUser) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        PtUserResponseDTO responseDTO =
                adminPtUserService.create(new PtUserRequestDTO().setRoles(Collections.emptyList()));
        assertThat(responseDTO, notNullValue());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void update_not_found() {
        adminPtUserService.update(1L, new PtUserRequestDTO());
    }

    @Test(expected = UnauthorizedException.class)
    public void update_not_allowed_for_1() {
        when(ptUserRepository.findById(eq(1L))).thenReturn(Optional.of(new PtUser()));
        adminPtUserService.update(1L, new PtUserRequestDTO().setRoles(Collections.emptyList()));
    }

    @Test
    public void update() {
        when(ptUserRepository.findById(eq(2L))).thenReturn(Optional.of(new PtUser()));
        when(ptUserRepository.save((PtUser) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        PtUserResponseDTO responseDTO =
                adminPtUserService.update(
                        2L, new PtUserRequestDTO().setRoles(Collections.emptyList()));
        assertThat(responseDTO, notNullValue());
    }

    @Test(expected = ResourceNotFoundException.class)
    public void delete_not_found() {
        adminPtUserService.delete(1L);
    }

    @Test(expected = UnauthorizedException.class)
    public void delete_not_allowed() {
        when(ptUserRepository.findById(eq(1L))).thenReturn(Optional.of(new PtUser()));
        adminPtUserService.delete(1L);
    }

    @Test
    public void delete() {
        when(ptUserRepository.findById(eq(2L))).thenReturn(Optional.of(new PtUser()));
        PtUserResponseDTO responseDTO = adminPtUserService.delete(2L);
        assertThat(responseDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/reportweight/WeightRequestDTO.java
package com.osomapps.pt.reportweight;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class WeightRequestDTO {
    Long weight;
}
<file_sep>/src/main/java/com/osomapps/pt/token/InUserLoginRepository.java
package com.osomapps.pt.token;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface InUserLoginRepository extends JpaRepository<InUserLogin, Long> {

    List<InUserLogin> findByToken(String token);
}
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExerciseTypeTest.java
package com.osomapps.pt.exercises;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseTypeTest {
    @Test
    public void createAllArgs() {
        assertThat(new ExerciseType(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ExerciseType exerciseType = new ExerciseType();
        exerciseType.setCreated(null);
        exerciseType.setExercises(null);
        assertThat(exerciseType, notNullValue());
    }

    @Test
    public void getters() {
        ExerciseType exerciseType = new ExerciseType();
        exerciseType.getCreated();
        exerciseType.getExercises();
        assertThat(exerciseType, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/reportphoto/ReportPhotoResourceTest.java
package com.osomapps.pt.reportphoto;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ReportPhotoResourceTest {

    @Mock private ReportPhotoService reportPhotoService;

    @InjectMocks private ReportPhotoResource reportPhotoResource;

    @Test
    public void findAll() throws Exception {
        reportPhotoResource.findAll("");
        verify(reportPhotoService).findAll(eq(""));
    }

    @Test
    public void create() {
        reportPhotoResource.create("", new PhotoRequestDTO());
        verify(reportPhotoService).create(eq(""), any(PhotoRequestDTO.class));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/ResourceNotFoundExceptionTest.java
package com.osomapps.pt;

import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import org.junit.Test;

public class ResourceNotFoundExceptionTest {

    @Test
    public void create() {
        final ResourceNotFoundException exception = new ResourceNotFoundException();
        assertThat(exception.getMessage(), nullValue());
    }

    @Test
    public void createWithMessage() {
        final ResourceNotFoundException exception = new ResourceNotFoundException("message");
        assertThat(exception.getMessage(), equalTo("message"));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/reportphoto/ReportPhotoServiceTest.java
package com.osomapps.pt.reportphoto;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.goals.InUserPhotoRepository;
import com.osomapps.pt.reportweight.InUserWeight;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserGoal;
import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.token.InUserPhoto;
import com.osomapps.pt.tokenemail.DataurlValidator;
import com.osomapps.pt.user.UserService;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.validation.Errors;

@RunWith(MockitoJUnitRunner.class)
public class ReportPhotoServiceTest {

    @Mock private InUserPhotoRepository inUserPhotoRepository;
    @Mock private UserService userService;
    @Mock private DataurlValidator dataurlValidator;

    @InjectMocks private ReportPhotoService reportPhotoService;

    @Test
    public void findAll() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin = new InUser().setInUserPhotos(Arrays.asList(new InUserPhoto()));
        inUserForLogin.setId(10L);
        inUserForLogin.setInUserWeights(Arrays.asList(new InUserWeight().setId(1L).setWeight(1F)));
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        reportPhotoService.findAll("1");
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void findAll_empty_token() {
        List<PhotoResponseDTO> photoResponseDTOs = reportPhotoService.findAll("");
        assertThat(photoResponseDTOs, notNullValue());
    }

    @Test
    public void create() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin =
                new InUser().setInUserGoals(Arrays.asList(new InUserGoal().setGoalId(1L)));
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(inUserPhotoRepository.save(any(InUserPhoto.class)))
                .thenReturn(new InUserPhoto().setId(1L));
        reportPhotoService.create(
                "1",
                new PhotoRequestDTO()
                        .setGoal_id(1L)
                        .setDataurl(
                                "data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0j"
                                        + "vb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAA"
                                        + "Re8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0Cc"
                                        + "guWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"));
        verify(userService).checkUserToken(eq("1"));
    }

    @Test(expected = UnauthorizedException.class)
    public void create_invalid_dataurl() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin =
                new InUser().setInUserGoals(Arrays.asList(new InUserGoal().setGoalId(1L)));
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        doAnswer(
                        (Answer<Void>)
                                (InvocationOnMock invocation) -> {
                                    Object[] args = invocation.getArguments();
                                    ((Errors) args[1])
                                            .reject("dataurlValidator", "dataurlValidator");
                                    return null;
                                })
                .when(dataurlValidator)
                .validate(anyObject(), any(Errors.class));
        reportPhotoService.create(
                "1",
                new PhotoRequestDTO()
                        .setGoal_id(1L)
                        .setDataurl(
                                "data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0j"
                                        + "vb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAA"
                                        + "Re8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0Cc"
                                        + "guWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"));
    }

    @Test
    public void create_photo_png() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin =
                new InUser().setInUserGoals(Arrays.asList(new InUserGoal().setGoalId(1L)));
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(inUserPhotoRepository.save(any(InUserPhoto.class)))
                .thenReturn(new InUserPhoto().setId(1L));
        reportPhotoService.create(
                "1",
                new PhotoRequestDTO()
                        .setGoal_id(1L)
                        .setDataurl(
                                "data:image/png;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0j"
                                        + "vb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAA"
                                        + "Re8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0Cc"
                                        + "guWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"));
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void create_photo_jpg() {
        InUserLogin inUserLogin = new InUserLogin();
        InUser inUserForLogin =
                new InUser().setInUserGoals(Arrays.asList(new InUserGoal().setGoalId(1L)));
        inUserForLogin.setId(10L);
        inUserLogin.setInUser(inUserForLogin);
        when(userService.checkUserToken(eq("1"))).thenReturn(inUserLogin);
        when(inUserPhotoRepository.save(any(InUserPhoto.class)))
                .thenReturn(new InUserPhoto().setId(1L));
        reportPhotoService.create(
                "1",
                new PhotoRequestDTO()
                        .setGoal_id(1L)
                        .setDataurl(
                                "data:image/jpeg;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0j"
                                        + "vb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAA"
                                        + "Re8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0Cc"
                                        + "guWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"));
        verify(userService).checkUserToken(eq("1"));
    }

    @Test
    public void create_with_empty_token() {
        reportPhotoService.create(
                "",
                new PhotoRequestDTO()
                        .setGoal_id(1L)
                        .setDataurl(
                                "data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0j"
                                        + "vb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAA"
                                        + "Re8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0Cc"
                                        + "guWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"));
        verify(userService, never()).checkUserToken(anyString());
    }
}
<file_sep>/src/main/resources/static/scripts/backbone-extend.js
/*jshint browser: true*/
/*global define*/
define([
  'underscore',
  'baseBackbone'
],
function (_, Backbone) {
  'use strict';

  // Override Backbone.sync to add some defaults
  var originalSync = Backbone.sync;
  Backbone.sync = function (method, model, options, error) {

    _.extend(options, { });

    return originalSync(method, model, options);
  };

  return Backbone;
});
<file_sep>/src/main/resources/db/migration/V4.73__add_new_columns_for_in_workout_item_set_table.sql
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN exercise_weight_percent INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN exercise_weight_in_kg DECIMAL(9,2);
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN goal_weight_coef DECIMAL(9,2);
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN exercise_repetitions_percent INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN goal_repetitions INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN exercise_time_percent INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN goal_time_in_sec INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN exercise_speed_percent INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN goal_speed INT;
ALTER TABLE ptcore.in_workout_item_set ADD COLUMN exercise_basis VARCHAR(30);
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/TemplateEngineTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

import java.util.HashMap;
import org.junit.Test;

public class TemplateEngineTest {

    @Test
    public void constructor() {
        new TemplateEngine();
        new TemplateEngine.TemplateImpl<String, String>("");
    }

    @Test
    public void template() {
        assertThat(
                TemplateEngine.<String, String>template("Hi, {{test}}!")
                        .apply(
                                new HashMap<String, String>() {
                                    {
                                        put("test", "Example");
                                    }
                                }),
                equalTo("Hi, Example!"));
    }

    @Test
    public void template2() {
        assertThat(
                TemplateEngine.<String, String>template("Hi, {{ test }}!")
                        .apply(
                                new HashMap<String, String>() {
                                    {
                                        put("test", "Example");
                                    }
                                }),
                equalTo("Hi, Example!"));
    }

    @Test
    public void template3() {
        assertThat(
                TemplateEngine.<String, String>template("Hi, {{ test }}!").apply(new HashMap<>()),
                equalTo("Hi, {{ test }}!"));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/programs/WorkoutResponseDTOTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class WorkoutResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new WorkoutResponseDTO(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        WorkoutResponseDTO workoutResponseDTO =
                new WorkoutResponseDTO().setId(null).setName(null).setWarmup(null).setItems(null);
        assertThat(workoutResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        WorkoutResponseDTO workoutResponseDTO = new WorkoutResponseDTO();
        workoutResponseDTO.getId();
        workoutResponseDTO.getName();
        workoutResponseDTO.getWarmup();
        workoutResponseDTO.getItems();
        assertThat(workoutResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/EmailValidatorTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

import java.util.HashMap;
import org.junit.Test;
import org.springframework.validation.MapBindingResult;

public class EmailValidatorTest {

    @Test
    public void supports() {
        assertThat(new EmailValidator().supports(String.class), equalTo(true));
    }

    @Test
    public void valid() {
        final MapBindingResult errors =
                new MapBindingResult(new HashMap<>(), String.class.getName());
        new EmailValidator().validate("<EMAIL>", errors);
        assertThat(errors.getAllErrors().size(), equalTo(0));
    }

    @Test
    public void not_valid_null() {
        final MapBindingResult errors =
                new MapBindingResult(new HashMap<>(), String.class.getName());
        new EmailValidator().validate(null, errors);
        assertThat(errors.getAllErrors().size(), equalTo(1));
    }

    @Test
    public void not_valid_empty() {
        final MapBindingResult errors =
                new MapBindingResult(new HashMap<>(), String.class.getName());
        new EmailValidator().validate("", errors);
        assertThat(errors.getAllErrors().size(), equalTo(1));
    }

    @Test
    public void not_valid() {
        final MapBindingResult errors =
                new MapBindingResult(new HashMap<>(), String.class.getName());
        new EmailValidator().validate("test", errors);
        assertThat(errors.getAllErrors().size(), equalTo(1));
    }
}
<file_sep>/src/main/resources/db/migration/V4.35__rename_reps_to_the_repetitions.sql
UPDATE ptcore.exercise_input SET name='Repetitions' WHERE name = 'Reps';
UPDATE ptcore.exercise_output SET name='Repetitions' WHERE name = 'Reps';
<file_sep>/src/main/java/com/osomapps/pt/admin/exercise/AdminExerciseFileService.java
package com.osomapps.pt.admin.exercise;

import com.osomapps.pt.exercises.ExerciseFileRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

@Service
class AdminExerciseFileService {
    private final ExerciseFileRepository exerciseFileRepository;

    AdminExerciseFileService(ExerciseFileRepository exerciseFileRepository) {
        this.exerciseFileRepository = exerciseFileRepository;
    }

    List<ExerciseFileResponseDTO> findAll(List<Long> ids) {
        return exerciseFileRepository.findAllById(ids).stream()
                .map(
                        file ->
                                ExerciseFileResponseDTO.builder()
                                        .id(file.getId())
                                        .file_name(file.getFile_name())
                                        .file_size(file.getFile_size())
                                        .file_type(file.getFile_type())
                                        .data_url(file.getData_url())
                                        .build())
                .collect(Collectors.toList());
    }
}
<file_sep>/src/main/resources/static/styles/admin.less
// Colors
@clr-border: #1c1e22;
@clr-bg: #f9f9f9;
@clr-bg-table-hover: #fff;
@clr-bg-table-selected: #428bca;
@clr-bg-header-hover: #ddd;
@clr-after: #434244;
@clr-disabled: #808080;
@clr-error: red;
@clr-warning: #333333;

@import "common.less";
@import "bootstrap-select.less";
@import "login.less";
@import "exercises.less";
@import "programs.less";
<file_sep>/src/test/java/com/osomapps/pt/admin/exercise/AdminExerciseEquipmentTypeServiceTest.java
package com.osomapps.pt.admin.exercise;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.exercises.ExerciseEquipmentType;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminExerciseEquipmentTypeServiceTest {

    @Mock private ExerciseEquipmentTypeRepository exerciseEquipmentTypeRepository;
    @Mock private DictionaryService dictionaryService;
    @InjectMocks private AdminExerciseEquipmentTypeService adminExerciseEquipmentTypeService;

    @Test
    public void findAll() {
        when(exerciseEquipmentTypeRepository.findAll())
                .thenReturn(Arrays.asList(new ExerciseEquipmentType()));
        List<ExerciseEquipmentTypeResponseDTO> responseDTOs =
                adminExerciseEquipmentTypeService.findAll();
        assertThat(responseDTOs.size(), equalTo(1));
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserGoalResourceTest.java
package com.osomapps.pt.admin.user;

import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AdminUserGoalResourceTest {

    @Mock private AdminUserGoalService userGoalService;
    @InjectMocks private AdminUserGoalResource adminUserGoalResource;

    @Test
    public void findAll() {
        adminUserGoalResource.findAll();
        verify(userGoalService).findAll();
    }
}
<file_sep>/README.md
# pt-backend
Spring-boot application with flyway and javascript frontend

[![Java CI](https://github.com/javadev/pt-backend/actions/workflows/maven.yml/badge.svg)](https://github.com/javadev/pt-backend/actions/workflows/maven.yml)
[![codecov.io](http://codecov.io/github/javadev/pt-backend/coverage.svg?branch=master)](http://codecov.io/github/javadev/pt-backend?branch=master)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=javadev_pt-backend&metric=sqale_rating)](https://sonarcloud.io/summary/overall?id=javadev_pt-backend)
[![Scrutinizer](https://img.shields.io/scrutinizer/g/javadev/pt-backend.svg)](https://scrutinizer-ci.com/g/javadev/pt-backend/)
<file_sep>/src/main/resources/db/migration/V4.52__create_in_user_goal_tables.sql
DROP TABLE ptcore.in_goal CASCADE;
DROP TABLE ptcore.in_goal_parameter CASCADE;
DROP TABLE ptcore.in_goal_has_in_goal_parameter CASCADE;

CREATE TABLE ptcore.in_user_goal (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    goal_id BIGINT,
    d_goal_title VARCHAR(45),
    d_goal_title_2 VARCHAR(45),
    goal_value INT
);

CREATE TABLE ptcore.in_user_has_in_user_goal (
    in_user_id      BIGINT NOT NULL REFERENCES ptcore.in_user(id),
    in_user_goal_id BIGINT NOT NULL REFERENCES ptcore.in_user_goal(id)
);
<file_sep>/src/test/java/com/osomapps/pt/config/CustomAuthenticationEntryPointTest.java
package com.osomapps.pt.config;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.security.core.AuthenticationException;

@RunWith(MockitoJUnitRunner.class)
public class CustomAuthenticationEntryPointTest {

    @Test
    public void commence() throws IOException, ServletException {
        HttpServletResponse httpServletResponse = mock(HttpServletResponse.class);
        when(httpServletResponse.getWriter()).thenReturn(mock(PrintWriter.class));
        new CustomAuthenticationEntryPoint()
                .commence(
                        mock(HttpServletRequest.class),
                        httpServletResponse,
                        mock(AuthenticationException.class));
        verify(httpServletResponse).setStatus(eq(HttpServletResponse.SC_UNAUTHORIZED));
    }

    @Test
    public void commence_null() throws IOException, ServletException {
        HttpServletResponse httpServletResponse = mock(HttpServletResponse.class);
        new CustomAuthenticationEntryPoint()
                .commence(mock(HttpServletRequest.class), httpServletResponse, null);
        verify(httpServletResponse, never()).setStatus(eq(HttpServletResponse.SC_UNAUTHORIZED));
    }
}
<file_sep>/src/main/resources/db/migration/V4.16__create_parse_result_table.sql
CREATE TABLE ptcore.parse_result (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    program_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    user_name VARCHAR(200),
    workouts VARCHAR(1000),
    errors VARCHAR(1000),
    FOREIGN KEY (program_id) REFERENCES ptcore.program (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/main/java/com/osomapps/pt/xlsx/XlsxProgramModifier.java
package com.osomapps.pt.xlsx;

import static org.apache.poi.ss.usermodel.CellType.NUMERIC;

import com.osomapps.pt.dictionary.DictionaryName;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InWarmupWorkoutItem;
import com.osomapps.pt.programs.InWorkoutItem;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserGoal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

@Slf4j
public class XlsxProgramModifier {
    private final InputStream inputStream;
    private final DictionaryService dictionaryService;

    private XlsxProgramModifier(InputStream inputStream, DictionaryService dictionaryService) {
        this.inputStream = inputStream;
        this.dictionaryService = dictionaryService;
    }

    public static XlsxProgramModifier of(
            InputStream inputStream, DictionaryService dictionaryService) {
        return new XlsxProgramModifier(inputStream, dictionaryService);
    }

    public void updateCellData(OutputStream outputStream, InUser inUser) {
        try (final XSSFWorkbook book = new XSSFWorkbook(inputStream)) {
            final XSSFSheet inputSheet = book.getSheetAt(0);
            fillCell(inputSheet, 2, 1, inUser.getD_sex());
            fillCell(inputSheet, 2, 2, emptyOrInteger(inUser.getAge()));
            fillCell(inputSheet, 2, 3, emptyOrInteger(inUser.getWeight()));
            fillCell(inputSheet, 2, 4, emptyOrInteger(inUser.getHeight()));
            fillCell(inputSheet, 2, 5, nullOrInteger(inUser.getD_level()));
            if (inUser.getInUserGoals().size() > 0) {
                fillCell(inputSheet, 2, 7, getGoalName(inUser.getInUserGoals().get(0)));
            } else {
                fillCell(inputSheet, 1, 7, "");
                fillCell(inputSheet, 2, 7, "");
            }
            if (inUser.getInUserGoals().size() > 1) {
                fillCell(inputSheet, 2, 8, getGoalName(inUser.getInUserGoals().get(1)));
            } else {
                fillCell(inputSheet, 1, 8, "");
                fillCell(inputSheet, 2, 8, "");
            }
            if (!inUser.getInPrograms().isEmpty()) {
                fillProgram(
                        book.getSheetAt(2),
                        inUser.getInPrograms().get(inUser.getInPrograms().size() - 1));
            }
            book.write(outputStream);
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
        }
    }

    private void fillProgram(XSSFSheet programSheet, InProgram inProgram) {
        for (int index = 0; index < 16; index += 1) {
            fillCell(programSheet, 2 + index, 3, "");
            fillCell(programSheet, 2 + index, 4, "");
            fillCell(programSheet, 2 + index, 5, "");
        }
        for (int index = 0; index < inProgram.getInWorkouts().size(); index += 1) {
            fillCell(
                    programSheet,
                    2 + index,
                    3,
                    "Goal " + (inProgram.getInWorkouts().get(index).getGoal_index() + 1));
            fillCell(
                    programSheet,
                    2 + index,
                    4,
                    inProgram.getInWorkouts().get(index).getPart_name());
            fillCell(
                    programSheet,
                    2 + index,
                    5,
                    "Workout " + (inProgram.getInWorkouts().get(index).getWorkout_index() + 1));
            final InWarmupWorkoutItem inWarmupWorkoutItem =
                    inProgram.getInWorkouts().get(index).getInWarmupWorkoutItems().get(0);
            fillCell(programSheet, 2 + index, 7, inWarmupWorkoutItem.getD_exercise_name());
            fillCell(programSheet, 2 + index, 8, inWarmupWorkoutItem.getSpeed() + " km/h");
            fillCell(programSheet, 2 + index, 9, inWarmupWorkoutItem.getIncline() + "%");
            fillCell(
                    programSheet,
                    2 + index,
                    10,
                    (inWarmupWorkoutItem.getTime_in_sec() / 60) + " min");
            for (int index2 = 0;
                    index2 < inProgram.getInWorkouts().get(index).getInWorkoutItems().size();
                    index2 += 1) {
                final InWorkoutItem inWorkoutItem =
                        inProgram.getInWorkouts().get(index).getInWorkoutItems().get(index2);
                fillCell(
                        programSheet,
                        2 + index,
                        11 + 7 * index2,
                        inWorkoutItem.getD_exercise_name());
                fillCell(
                        programSheet,
                        2 + index,
                        12 + 7 * index2,
                        inWorkoutItem.getInWorkoutItemSets().size());
                if (inWorkoutItem.getInWorkoutItemSets().get(0).getRepetitions() != null) {
                    fillCell(
                            programSheet,
                            2 + index,
                            13 + 7 * index2,
                            inWorkoutItem.getInWorkoutItemSets().stream()
                                    .map(set -> "" + set.getRepetitions())
                                    .collect(Collectors.joining(",")));
                }
                if (inWorkoutItem.getInWorkoutItemSets().get(0).getTime_in_sec() != null) {
                    fillCell(
                            programSheet,
                            2 + index,
                            13 + 7 * index2,
                            inWorkoutItem.getInWorkoutItemSets().stream()
                                    .map(set -> round(set.getTime_in_sec() / 60F) + " min")
                                    .collect(Collectors.joining(",")));
                }
                if (inWorkoutItem.getInWorkoutItemSets().get(0).getWeight() != null) {
                    fillCell(
                            programSheet,
                            2 + index,
                            14 + 7 * index2,
                            inWorkoutItem.getInWorkoutItemSets().stream()
                                    .map(set -> round(set.getWeight()))
                                    .collect(Collectors.joining(",")));
                }
            }
        }
    }

    private String getGoalName(InUserGoal inUserGoal) {
        return Arrays.asList(
                        dictionaryService.getEnValue(
                                DictionaryName.goal_title, inUserGoal.getD_goal_title(), null),
                        dictionaryService.getEnValue(
                                DictionaryName.goal_title_2, inUserGoal.getD_goal_title_2(), null))
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.joining(", "));
    }

    private Integer emptyOrInteger(Float value) {
        return value == null ? null : value.intValue();
    }

    private Integer nullOrInteger(String value) {
        return value == null ? null : Integer.parseInt(value);
    }

    private void fillCell(XSSFSheet sheet, int columnNumber, int rowNumber, String value) {
        XSSFRow row = sheet.getRow(rowNumber);
        XSSFCell cell = row.getCell(columnNumber);
        if (cell == null) {
            cell = row.createCell(columnNumber);
        }
        cell.setCellValue(value == null ? "" : value);
        cell.setCellFormula(null);
    }

    private void fillCell(XSSFSheet sheet, int columnNumber, int rowNumber, Integer value) {
        XSSFRow row = sheet.getRow(rowNumber);
        XSSFCell cell = row.getCell(columnNumber);
        if (cell == null) {
            cell = row.createCell(columnNumber, NUMERIC);
        }
        if (value == null) {
            cell.setCellValue("");
        } else {
            cell.setCellValue(value);
        }
        cell.setCellFormula(null);
    }

    private String round(Float value) {
        if (value.floatValue() == value.intValue()) {
            return Integer.toString(value.intValue());
        }
        return "" + value;
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/AdminUserProgramFileServiceTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.programs.InProgram;
import com.osomapps.pt.programs.InWarmupWorkoutItem;
import com.osomapps.pt.programs.InWorkout;
import com.osomapps.pt.programs.InWorkoutItem;
import com.osomapps.pt.programs.InWorkoutItemSet;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserRepository;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.util.FastByteArrayOutputStream;

@RunWith(MockitoJUnitRunner.class)
public class AdminUserProgramFileServiceTest {

    @Mock private DictionaryService dictionaryService;
    @Mock private InUserRepository inUserRepository;
    @InjectMocks private AdminUserProgramFileService adminUserProgramFileService;

    @Test(expected = ResourceNotFoundException.class)
    public void createXlsx_not_found() {
        adminUserProgramFileService.createXlsx(1L, new FastByteArrayOutputStream());
    }

    @Test
    public void createXlsx() {
        when(inUserRepository.findById(eq(1L)))
                .thenReturn(
                        Optional.of(
                                new InUser()
                                        .setInPrograms(
                                                Arrays.asList(
                                                        new InProgram()
                                                                .setInWorkouts(
                                                                        Arrays.asList(
                                                                                new InWorkout()
                                                                                .setWorkout_index(
                                                                                0)
                                                                                .setGoal_index(
                                                                                0)
                                                                                .setInWarmupWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new InWarmupWorkoutItem()
                                                                                .setTime_in_sec(
                                                                                60)))
                                                                                .setInWorkoutItems(
                                                                                Arrays
                                                                                .asList(
                                                                                new InWorkoutItem()
                                                                                .setInWorkoutItemSets(
                                                                                Arrays
                                                                                .asList(
                                                                                new InWorkoutItemSet()))))))))));
        ProgramResponseDTO programResponseDTO =
                adminUserProgramFileService.createXlsx(1L, new FastByteArrayOutputStream());
        assertThat(programResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.15__add_file_name_size_and_type_for_program_table_1.sql
ALTER TABLE ptcore.program ADD COLUMN file_name VARCHAR(200) NOT NULL DEFAULT '';
ALTER TABLE ptcore.program ADD COLUMN file_size BIGINT NOT NULL DEFAULT 0;
ALTER TABLE ptcore.program ADD COLUMN file_type VARCHAR(100) NOT NULL DEFAULT '';
<file_sep>/src/test/java/com/osomapps/pt/admin/ptuser/PtRoleResponseDTOTest.java
package com.osomapps.pt.admin.ptuser;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class PtRoleResponseDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new PtRoleResponseDTO(1L, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new PtRoleResponseDTO(), notNullValue());
    }

    @Test
    public void setters() {
        PtRoleResponseDTO ptRoleResponseDTO = new PtRoleResponseDTO();
        ptRoleResponseDTO.setId(null);
        ptRoleResponseDTO.setName(null);
        assertThat(ptRoleResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        PtRoleResponseDTO ptRoleResponseDTO = new PtRoleResponseDTO();
        ptRoleResponseDTO.getId();
        ptRoleResponseDTO.getName();
        assertThat(ptRoleResponseDTO, notNullValue());
    }
}
<file_sep>/src/main/resources/db/migration/V4.43__create_parse_workout_test_table.sql
CREATE TABLE ptcore.program_test (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(200),
    data_url TEXT,
    updated TIMESTAMP WITHOUT TIME ZONE,
    active BOOLEAN NOT NULL DEFAULT TRUE,
    file_name VARCHAR(200) NOT NULL DEFAULT '',
    file_size BIGINT NOT NULL DEFAULT 0,
    file_type VARCHAR(100) NOT NULL DEFAULT ''
);

CREATE TABLE ptcore.parse_workout_test (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    program_test_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    FOREIGN KEY (program_test_id) REFERENCES ptcore.program_test (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_warmup_workout_item_test (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_workout_test_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    speed INT,
    incline INT,
    time_in_min INT,
    FOREIGN KEY (parse_workout_test_id) REFERENCES ptcore.parse_workout_test (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_workout_item_test (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_workout_test_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    sets INT,
    repetitions INT,
    weight INT,
    bodyweight BOOLEAN NOT NULL DEFAULT FALSE,
    time_in_min INT,
    speed INT,
    resistance INT,
    FOREIGN KEY (parse_workout_test_id) REFERENCES ptcore.parse_workout_test (id) ON UPDATE CASCADE ON DELETE CASCADE
);
<file_sep>/src/test/java/com/osomapps/pt/programs/ProgramResponseDTOTest.java
package com.osomapps.pt.programs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ProgramResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new ProgramResponseDTO(1L, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ProgramResponseDTO programResponseDTO = new ProgramResponseDTO();
        programResponseDTO.setName(null);
        programResponseDTO.setType(null);
        assertThat(programResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        ProgramResponseDTO programResponseDTO = new ProgramResponseDTO();
        programResponseDTO.getName();
        programResponseDTO.getType();
        assertThat(programResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExerciseDTOTest.java
package com.osomapps.pt.exercises;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new ExerciseDTO(1L, null, null, null, null, null), notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/user/UserGenderTest.java
package com.osomapps.pt.user;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

import java.util.Optional;
import org.junit.Test;

public class UserGenderTest {

    @Test
    public void of_male2_is_empty() {
        assertThat(UserGender.of("male2"), equalTo(Optional.empty()));
    }

    @Test
    public void of_male() {
        assertThat(UserGender.of("male"), equalTo(Optional.of(UserGender.Male)));
    }
}
<file_sep>/src/main/java/com/osomapps/pt/goals/GoalParameterRepository.java
package com.osomapps.pt.goals;

import org.springframework.data.jpa.repository.JpaRepository;

public interface GoalParameterRepository extends JpaRepository<GoalParameter, Long> {}
<file_sep>/src/main/resources/db/migration/V4.49__create_parse_tables.sql
CREATE TABLE ptcore.parse_program (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(200),
    data_url TEXT,
    updated TIMESTAMP WITHOUT TIME ZONE,
    active BOOLEAN NOT NULL DEFAULT TRUE,
    file_name VARCHAR(200) NOT NULL DEFAULT '',
    file_size BIGINT NOT NULL DEFAULT 0,
    file_type VARCHAR(100) NOT NULL DEFAULT ''
);

CREATE TABLE ptcore.parse_goal (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_program_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    FOREIGN KEY (parse_program_id) REFERENCES ptcore.parse_program (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_user_group (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_goal_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    FOREIGN KEY (parse_goal_id) REFERENCES ptcore.parse_goal (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_round (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_user_group_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    FOREIGN KEY (parse_user_group_id) REFERENCES ptcore.parse_user_group (id) ON UPDATE CASCADE ON DELETE CASCADE
);

CREATE TABLE ptcore.parse_part (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_round_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    FOREIGN KEY (parse_round_id) REFERENCES ptcore.parse_round (id) ON UPDATE CASCADE ON DELETE CASCADE
);

DROP TABLE ptcore.parse_workout CASCADE;

CREATE TABLE ptcore.parse_workout (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    parse_part_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(100),
    column_index INT NOT NULL DEFAULT 0,
    row_index INT NOT NULL DEFAULT 0,
    FOREIGN KEY (parse_part_id) REFERENCES ptcore.parse_part (id) ON UPDATE CASCADE ON DELETE CASCADE
);

DROP TABLE ptcore.parse_user CASCADE;

DROP TABLE ptcore.program CASCADE;
<file_sep>/src/test/java/com/osomapps/pt/token/InUserTest.java
package com.osomapps.pt.token;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import org.junit.Test;

public class InUserTest {
    @Test
    public void create() {
        assertThat(new InUser(), notNullValue());
    }

    @Test
    public void createAllArgs() {
        assertThat(
                new InUser(
                        1L,
                        LocalDateTime.now(),
                        "d_sex",
                        20F,
                        LocalDate.now(),
                        2F,
                        3F,
                        "d_level",
                        null,
                        LocalDateTime.now(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        null,
                        null,
                        null),
                notNullValue());
    }

    @Test
    public void setters() {
        InUser inUser = new InUser();
        inUser.setId(1L);
        inUser.setCreated(LocalDateTime.MAX);
        inUser.setD_sex("");
        inUser.setAge(0F);
        inUser.setBirthday(LocalDate.MAX);
        inUser.setHeight(Float.MAX_VALUE);
        inUser.setWeight(Float.MAX_VALUE);
        inUser.setD_level("");
        inUser.setAvatar_dataurl("");
        inUser.setUpdated(LocalDateTime.MAX);
        inUser.setInUserFacebooks(Collections.emptyList());
        inUser.setInUserLogins(Collections.emptyList());
        inUser.setInUserLogouts(Collections.emptyList());
        inUser.setInPrograms(Collections.emptyList());
        inUser.setInUserWeights(Collections.emptyList());
        inUser.setInUserCertificates(Collections.emptyList());
        inUser.setInUserEmails(Collections.emptyList());
        inUser.setInUserType(null);
        inUser.setInUserGoals(Collections.emptyList());
        inUser.setInUserPhotos(Collections.emptyList());
        assertThat(inUser, notNullValue());
    }

    @Test
    public void getters() {
        InUser inUser = new InUser();
        inUser.getId();
        inUser.getCreated();
        inUser.getD_sex();
        inUser.getAge();
        inUser.getBirthday();
        inUser.getHeight();
        inUser.getWeight();
        inUser.getD_level();
        inUser.getAvatar_dataurl();
        inUser.getUpdated();
        inUser.getInUserFacebooks();
        inUser.getInUserLogins();
        inUser.getInUserLogouts();
        inUser.getInPrograms();
        inUser.getInUserWeights();
        inUser.getInUserCertificates();
        inUser.getInUserEmails();
        inUser.getInUserType();
        inUser.getInUserGoals();
        inUser.getInUserPhotos();
        assertThat(inUser, notNullValue());
    }
}
<file_sep>/src/main/resources/static/scripts/models/messages.js
/*jshint browser: true*/
/*global define*/
define([
  'backbone'
],
function (Backbone) {
  'use strict';

  var DialogModel = {};

  DialogModel.MessageTypes = {
    Info: 'info',
    Warning: 'warning',
    Error: 'error',
    Success: 'success'
  };

  DialogModel.Message = Backbone.Model.extend({
    defaults: {
      header: '',
      message: '',
      type: DialogModel.MessageTypes.Info
    }
  });

  DialogModel.GENERAL_ERROR_MESSAGE = function() {
    return new DialogModel.Message({
      header: 'Error',
      message: 'En feil oppstod ved opprettelse av ny arbeidsordre. Kontakt PT.',
      type: DialogModel.MessageTypes.Error
    });
  };

  DialogModel.Messages = Backbone.Collection.extend({
    model: DialogModel.Message
  });

  return DialogModel;
});
<file_sep>/src/main/java/com/osomapps/pt/dictionary/DictionaryData.java
package com.osomapps.pt.dictionary;

import java.time.LocalDateTime;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Entity
@Table(name = "dictionary_data", schema = "ptcore")
@DynamicInsert
public class DictionaryData {
    @Id
    @GenericGenerator(
            name = "DictionaryIdSequence",
            strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
            parameters = {
                @Parameter(name = "sequence_name", value = "ptcore.dictionary_data_id_seq"),
                @Parameter(name = "initial_value", value = "1"),
                @Parameter(name = "increment_size", value = "1")
            })
    @GeneratedValue(generator = "DictionaryIdSequence")
    Long id;

    LocalDateTime created;
    String dlanguage;
    Boolean valid;
    LocalDateTime fromdate;
    LocalDateTime todate;
    String dname;
    String dkey;
    String dvalue;
}
<file_sep>/src/main/resources/db/migration/V4.1__create_exercise_tables.sql
CREATE TABLE ptcore.exercise_category (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_category_name VARCHAR(45)
);

INSERT INTO ptcore.exercise_category (d_exercise_category_name) VALUES
('10'),
('140'),
('250'),
('330'),
('430'),
('510'),
('520'),
('590');

CREATE TABLE ptcore.exercise (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    exercise_category_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_exercise_name VARCHAR(45),
    FOREIGN KEY (exercise_category_id) REFERENCES ptcore.exercise_category (id) ON UPDATE CASCADE ON DELETE CASCADE
);

INSERT INTO ptcore.exercise (exercise_category_id, d_exercise_name) VALUES
(1, '20'),
(1, '30'),
(1, '40'),
(1, '50'),
(1, '60'),
(1, '70'),
(1, '80'),
(1, '90'),
(1, '100'),
(1, '110'),
(1, '120'),
(1, '130'),

(2, '150'),
(2, '160'),
(2, '170'),
(2, '180'),
(2, '190'),
(2, '200'),
(2, '210'),
(2, '220'),
(2, '230'),
(2, '240'),

(3, '260'),
(3, '270'),
(3, '280'),
(3, '290'),
(3, '300'),
(3, '310'),
(3, '320'),

(4, '340'),
(4, '350'),
(4, '360'),
(4, '370'),
(4, '380'),
(4, '390'),
(4, '400'),
(4, '410'),
(4, '420'),

(5, '440'),
(5, '450'),
(5, '460'),
(5, '470'),
(5, '480'),
(5, '490'),
(5, '500'),

(7, '520'),
(7, '530'),
(7, '540'),
(7, '550'),
(7, '560'),
(7, '570'),
(7, '580'),

(8, '600'),
(8, '610'),
(8, '620'),
(8, '630'),
(8, '640'),
(8, '650');

CREATE TABLE ptcore.dictionary_data (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    dlanguage VARCHAR(30) DEFAULT 'en',
    valid BOOLEAN NOT NULL DEFAULT TRUE,
    fromdate TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    todate TIMESTAMP WITHOUT TIME ZONE,
    dname VARCHAR(30),
    dkey VARCHAR(50),
    dvalue VARCHAR(1000)
);

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('exercise_category_name', '10', 'Legs'),
('exercise_category_name', '140', 'Back'),
('exercise_category_name', '250', 'Chest'),
('exercise_category_name', '330', 'Shoulders'),
('exercise_category_name', '430', 'Abs'),
('exercise_category_name', '510', 'Arms'),
('exercise_category_name', '520', 'Tricep'),
('exercise_category_name', '590', 'Bicep');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('exercise_name', '20', 'Squat'),
('exercise_name', '30', 'Front Squat'),
('exercise_name', '40', 'Deadlift'),
('exercise_name', '50', 'Sumo Deadlift'),
('exercise_name', '60', 'Lunge'),
('exercise_name', '70', 'Bulgarian Split-Squat'),
('exercise_name', '80', 'Nordic Hamstrings'),
('exercise_name', '90', 'Hip Thrust'),
('exercise_name', '100', 'One-legged Hip Thrust'),
('exercise_name', '110', 'Hyperextension'),
('exercise_name', '120', 'Legpress'),
('exercise_name', '130', 'Standing Calf Raise '),
('exercise_name', '150', 'Pull-ups'),
('exercise_name', '160', 'Chin-ups'),
('exercise_name', '170', 'Bent Over Row'),
('exercise_name', '180', 'One Arm Dumbbell Row'),

('exercise_name', '190', 'Straight Arm Pulldown'),
('exercise_name', '200', 'Lat Pulldown'),
('exercise_name', '210', 'Deadlift'),
('exercise_name', '220', 'Hyperextension'),
('exercise_name', '230', 'Face Pull'),
('exercise_name', '240', 'TRX/Redcord Face Pull'),

('exercise_name', '250', 'Chest'),
('exercise_name', '260', 'Bench Press'),
('exercise_name', '270', 'Incline Bench Press'),
('exercise_name', '280', 'Dumbbell Chest Press'),
('exercise_name', '290', 'Incline Dumbbell Chest Press'),
('exercise_name', '300', 'Push-Ups'),
('exercise_name', '310', 'TRX/Redcord Push-Ups'),
('exercise_name', '320', 'Chest Press Machine'),

('exercise_name', '330', 'Shoulders'),
('exercise_name', '340', 'Barbell Shoulder Press'),
('exercise_name', '350', 'Dumbbell Shoulder Press'),
('exercise_name', '360', 'Dumbbell Front Raise'),
('exercise_name', '370', 'Cable Front Raise'),
('exercise_name', '380', 'Dumbbell Side Raise'),
('exercise_name', '390', 'Cable Side Raise'),
('exercise_name', '400', 'Reverse Fly'),
('exercise_name', '410', 'Face Pull'),
('exercise_name', '420', 'TRX/Redcord Face Pull'),

('exercise_name', '430', 'Abs'),
('exercise_name', '440', 'Plank'),
('exercise_name', '450', 'Plank On a Ball'),
('exercise_name', '460', 'The Boat'),
('exercise_name', '470', 'Russian Twists'),
('exercise_name', '480', 'Leg/Knee Raise'),
('exercise_name', '490', 'Hanginf Leg/Knee Raise'),
('exercise_name', '500', 'Redcord Knee Raise'),

('exercise_name', '510', 'Arms'),

('exercise_name', '520', 'Tricep'),
('exercise_name', '530', 'Dips'),
('exercise_name', '540', 'Close Grip Bench Press'),
('exercise_name', '550', 'Scull Crusher'),
('exercise_name', '560', 'Hindu Push-Ups'),
('exercise_name', '570', 'Close Grip Push-Ups'),
('exercise_name', '580', 'Cable Tricep Extension '),

('exercise_name', '590', 'Bicep'),
('exercise_name', '600', 'Barbell Bicep Curl'),
('exercise_name', '610', 'Dumbbell Bicep Curl'),
('exercise_name', '620', 'Dumbbell Hammer Curl'),
('exercise_name', '630', 'TRX/Redcord Bicep Curl'),
('exercise_name', '640', 'Cable Bicep Curl'),
('exercise_name', '650', 'Chin Ups');
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/TokenEmailSignupServiceTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserLoginRepository;
import com.osomapps.pt.token.InUserRepository;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.Errors;

@RunWith(MockitoJUnitRunner.class)
public class TokenEmailSignupServiceTest {

    @Mock private SendEmailService sendEmailService;
    @Mock private InUserEmailRepository inUserEmailRepository;
    @Mock private EmailValidator emailValidator;
    @Mock private PasswordEncoder passwordEncoder;
    @Mock private InUserRepository inUserRepository;
    @Mock private InUserLoginRepository inUserLoginRepository;
    @Mock private DataurlValidator dataurlValidator;
    @InjectMocks private TokenEmailSignupService tokenEmailSignupService;

    @Test
    public void createInUserEmail() {
        tokenEmailSignupService.createInUserEmail(
                new TokenEmailSignupRequestDTO()
                        .setUser(new UserSignupRequestDTO().setEmail("<EMAIL>")));
    }

    @Test(expected = UnauthorizedException.class)
    public void createInUserEmail_wrong_email() {
        doAnswer(
                        (Answer<Void>)
                                (InvocationOnMock invocation) -> {
                                    Object[] args = invocation.getArguments();
                                    ((Errors) args[1]).reject("emailValidator", "emailValidator");
                                    return null;
                                })
                .when(emailValidator)
                .validate(anyObject(), any(Errors.class));
        tokenEmailSignupService.createInUserEmail(
                new TokenEmailSignupRequestDTO()
                        .setUser(new UserSignupRequestDTO().setEmail("<EMAIL>")));
    }

    @Test(expected = UnauthorizedException.class)
    public void createInUserEmail_wrong_dataurl() {
        doAnswer(
                        (Answer<Void>)
                                (InvocationOnMock invocation) -> {
                                    Object[] args = invocation.getArguments();
                                    ((Errors) args[1])
                                            .reject("dataurlValidator", "dataurlValidator");
                                    return null;
                                })
                .when(dataurlValidator)
                .validate(anyObject(), any(Errors.class));
        tokenEmailSignupService.createInUserEmail(
                new TokenEmailSignupRequestDTO()
                        .setUser(new UserSignupRequestDTO().setEmail("<EMAIL>")));
    }

    @Test(expected = UnauthorizedException.class)
    public void createInUserEmail_already_registered() {
        when(inUserEmailRepository.findByLogin(anyString()))
                .thenReturn(Arrays.asList(new InUserEmail()));
        tokenEmailSignupService.createInUserEmail(
                new TokenEmailSignupRequestDTO()
                        .setUser(new UserSignupRequestDTO().setEmail("<EMAIL>")));
    }

    @Test
    public void createNewToken() {
        when(inUserRepository.save((InUser) anyObject())).thenAnswer(i -> i.getArguments()[0]);
        when(inUserEmailRepository.save((InUserEmail) anyObject()))
                .thenAnswer(i -> i.getArguments()[0]);
        tokenEmailSignupService.createNewToken(
                new TokenEmailSignupRequestDTO()
                        .setUser(new UserSignupRequestDTO().setEmail("<EMAIL>")),
                "");
    }

    @Test
    public void confirmToken() {
        assertThat(tokenEmailSignupService.confirmToken(""), equalTo(false));
    }

    @Test
    public void confirmToken_true() {
        when(inUserEmailRepository.findByConfirmToken(anyString()))
                .thenReturn(Arrays.asList(new InUserEmail().setIs_confirmed(Boolean.FALSE)));
        assertThat(tokenEmailSignupService.confirmToken(""), equalTo(true));
    }

    @Test
    public void confirmToken_false() {
        when(inUserEmailRepository.findByConfirmToken(anyString()))
                .thenReturn(Arrays.asList(new InUserEmail().setIs_confirmed(Boolean.TRUE)));
        assertThat(tokenEmailSignupService.confirmToken(""), equalTo(true));
    }

    @Test(expected = UnauthorizedException.class)
    public void forgotPassword() {
        tokenEmailSignupService.forgotPassword(
                new ForgotPasswordRequestDTO().setEmail("<EMAIL>"), "");
    }

    @Test
    public void forgotPassword_true() {
        when(inUserEmailRepository.findByLogin(anyString()))
                .thenReturn(Arrays.asList(new InUserEmail().setIs_confirmed(Boolean.FALSE)));
        tokenEmailSignupService.forgotPassword(
                new ForgotPasswordRequestDTO().setEmail("<EMAIL>"), "");
        verify(inUserEmailRepository).save(any(InUserEmail.class));
    }

    @Test
    public void resetToken() {
        assertThat(tokenEmailSignupService.resetToken(""), equalTo(Optional.empty()));
    }

    @Test
    public void resetToken_true() {
        when(inUserEmailRepository.findByResetToken(anyString()))
                .thenReturn(Arrays.asList(new InUserEmail().setIs_confirmed(Boolean.FALSE)));
        assertThat(tokenEmailSignupService.resetToken(""), notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/user/package-info.java
/**
 *
 *
 * <h1>User endpoint package</h1>
 *
 * <h2>Responsibilities</h2>
 *
 * <ul>
 *   <li>Provides user profile services
 * </ul>
 */
package com.osomapps.pt.user;
<file_sep>/src/test/java/com/osomapps/pt/config/CachingConfigTest.java
package com.osomapps.pt.config;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.springframework.cache.support.SimpleCacheManager;

public class CachingConfigTest {

    @Test
    public void cacheManager() {
        CachingConfig instance = new CachingConfig();
        assertTrue(instance.cacheManager() instanceof SimpleCacheManager);
    }
}
<file_sep>/src/main/resources/db/migration/V4.54__fix_sequence_for_exercise_table.sql
--
-- SEQUENCES
--

SELECT setval('ptcore.exercise_id_seq', (select max(id) from ptcore.exercise) + 1, true);
<file_sep>/src/main/resources/db/migration/V4.68__change_user_name_for_in_user_email_table.sql
ALTER TABLE ptcore.in_user_email ALTER COLUMN user_name DROP NOT NULL;
<file_sep>/src/main/java/com/osomapps/pt/email/EmailMessageTemplateRepository.java
package com.osomapps.pt.email;

import org.springframework.data.jpa.repository.JpaRepository;

public interface EmailMessageTemplateRepository extends JpaRepository<EmailMessageTemplate, Long> {}
<file_sep>/src/main/java/com/osomapps/pt/admin/program/ProgramRequestDTO.java
package com.osomapps.pt.admin.program;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@Builder
class ProgramRequestDTO {
    String name;
    String fileName;
    Long fileSize;
    String fileType;
    String dataUrl;
}
<file_sep>/src/test/java/com/osomapps/pt/admin/program/ProgramRequestDTOTest.java
package com.osomapps.pt.admin.program;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ProgramRequestDTOTest {

    @Test
    public void allArgsConstructor() {
        assertThat(new ProgramRequestDTO(null, null, null, null, null), notNullValue());
    }

    @Test
    public void builder() {
        ProgramRequestDTO programRequestDTO = ProgramRequestDTO.builder().build();
        assertThat(programRequestDTO, notNullValue());
    }
}
<file_sep>/.travis.yml
language: java

cache:
  directories:
  - $HOME/.m2

jdk:
  - openjdk11
  - openjdk15

services:
  - postgresql

addons:
   hosts:
       - travis
   hostname: travis
   postgresql: "9.6"

before_script:
  - psql -c "CREATE USER ptcoretest WITH PASSWORD '<PASSWORD>';"
  - psql -c 'create database ptcoretest;' -U postgres
  - psql -c 'GRANT ALL PRIVILEGES ON DATABASE ptcoretest to ptcoretest;'
  - pip install --user codecov

script:
  - mvn -T 1C -B clean package jacoco:report

after_success:
  - codecov
  - mvn sonar:sonar -Dsonar.projectKey=javadev_pt-backend -Dsonar.organization=javadev-github -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=$SONAR_LOGIN

<file_sep>/src/main/resources/db/migration/V4.38__add_incline_for_in_workout_item_table.sql
ALTER TABLE ptcore.in_workout_item ADD COLUMN incline INT;
ALTER TABLE ptcore.in_workout_item ADD COLUMN repetitions_to_failure BOOLEAN NOT NULL DEFAULT FALSE;
<file_sep>/src/main/java/com/osomapps/pt/admin/ptuser/PtUserRequestDTO.java
package com.osomapps.pt.admin.ptuser;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
class PtUserRequestDTO {
    String login;
    String name;
    String password;

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    LocalDateTime activated;

    Boolean is_blocked;
    Boolean is_blocked_date_set;
    String blocked_comment;

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    LocalDateTime blocked_start;

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    LocalDateTime blocked_finish;

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    LocalDateTime deleted;

    String deleted_comment;
    Boolean is_deleted;
    Boolean is_default_password;
    String description;
    String phone;
    String phone2;
    List<PtRoleRequestDTO> roles;
}
<file_sep>/src/main/java/com/osomapps/pt/xlsx/Output.java
package com.osomapps.pt.xlsx;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Getter
@Setter
@ToString
public class Output {
    Integer sets;
    List<Integer> repetitions;
    List<Integer> weights;
    List<Integer> timeInMins;
    List<Integer> speeds;
    List<Integer> inclines;
    List<Integer> resistances;
}
<file_sep>/src/test/java/com/osomapps/pt/admin/program/ProgramResponseDTOTest.java
package com.osomapps.pt.admin.program;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ProgramResponseDTOTest {

    @Test
    public void allArgsConstructor() {
        assertThat(
                new ProgramResponseDTO(null, null, null, null, null, null, null, null, null),
                notNullValue());
    }

    @Test
    public void setters() {
        ProgramResponseDTO programResponseDTO = new ProgramResponseDTO();
        programResponseDTO.setId(null);
        programResponseDTO.setName(null);
        programResponseDTO.setFileName(null);
        programResponseDTO.setFileSize(null);
        programResponseDTO.setFileType(null);
        programResponseDTO.setDataUrl(null);
        programResponseDTO.setUpdated(null);
        programResponseDTO.setParseExercises(null);
        programResponseDTO.setParseGoals(null);
        assertThat(programResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        ProgramResponseDTO programResponseDTO = new ProgramResponseDTO();
        programResponseDTO.getId();
        programResponseDTO.getName();
        programResponseDTO.getFileName();
        programResponseDTO.getFileSize();
        programResponseDTO.getFileType();
        programResponseDTO.getDataUrl();
        programResponseDTO.getUpdated();
        programResponseDTO.getParseExercises();
        programResponseDTO.getParseGoals();
        assertThat(programResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/exercises/ExerciseFileViewTest.java
package com.osomapps.pt.exercises;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ExerciseFileViewTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ExerciseFileView(1L, null, null, null, null, null), notNullValue());
    }

    @Test
    public void setters() {
        ExerciseFileView exerciseFile = new ExerciseFileView();
        exerciseFile.setId(null);
        exerciseFile.setCreated(null);
        exerciseFile.setFile_size(null);
        exerciseFile.setFile_type(null);
        exerciseFile.setExercises(null);
        assertThat(exerciseFile, notNullValue());
    }

    @Test
    public void getters() {
        ExerciseFileView exerciseFile = new ExerciseFileView();
        exerciseFile.getId();
        exerciseFile.getCreated();
        exerciseFile.getFile_size();
        exerciseFile.getFile_type();
        exerciseFile.getExercises();
        assertThat(exerciseFile, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/programs/ParsePartRepository.java
package com.osomapps.pt.programs;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ParsePartRepository extends JpaRepository<ParsePart, Long> {}
<file_sep>/src/test/java/com/osomapps/pt/admin/user/UserWorkoutItemRequestDTOTest.java
package com.osomapps.pt.admin.user;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserWorkoutItemRequestDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new UserWorkoutItemRequestDTO(1L, null, null), notNullValue());
    }

    @Test
    public void setters() {
        UserWorkoutItemRequestDTO userWorkoutItemRequestDTO = new UserWorkoutItemRequestDTO();
        userWorkoutItemRequestDTO.setExercise_id(null);
        userWorkoutItemRequestDTO.setExercise_name(null);
        userWorkoutItemRequestDTO.setSets(null);
        assertThat(userWorkoutItemRequestDTO, notNullValue());
    }

    @Test
    public void getters() {
        UserWorkoutItemRequestDTO userWorkoutItemRequestDTO = new UserWorkoutItemRequestDTO();
        userWorkoutItemRequestDTO.getExercise_id();
        userWorkoutItemRequestDTO.getExercise_name();
        userWorkoutItemRequestDTO.getSets();
        assertThat(userWorkoutItemRequestDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/admin/goal/GoalParameterResponseDTOTest.java
package com.osomapps.pt.admin.goal;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class GoalParameterResponseDTOTest {
    @Test
    public void createAllArgs() {
        assertThat(new GoalParameterResponseDTO(1L, null), notNullValue());
    }

    @Test
    public void setters() {
        GoalParameterResponseDTO goalParameterResponseDTO = new GoalParameterResponseDTO();
        goalParameterResponseDTO.setId(null);
        goalParameterResponseDTO.setName(null);
        assertThat(goalParameterResponseDTO, notNullValue());
    }

    @Test
    public void getters() {
        GoalParameterResponseDTO goalParameterResponseDTO = new GoalParameterResponseDTO();
        goalParameterResponseDTO.getId();
        goalParameterResponseDTO.getName();
        assertThat(goalParameterResponseDTO, notNullValue());
    }
}
<file_sep>/src/test/java/com/osomapps/pt/reportworkout/ReportWorkoutResourceTest.java
package com.osomapps.pt.reportworkout;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;

import com.osomapps.pt.admin.program.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ReportWorkoutResourceTest {

    @Mock private ReportWorkoutService reportWorkoutService;

    @InjectMocks private ReportWorkoutResource reportWorkoutResource;

    @Test
    public void findAll() throws Exception {
        reportWorkoutResource.findAll("");
        verify(reportWorkoutService).findAll(eq(""));
    }

    @Test
    public void create() {
        reportWorkoutResource.create("", new WorkoutReportRequestDTO());
        verify(reportWorkoutService).create(eq(""), any(WorkoutReportRequestDTO.class));
    }
}
<file_sep>/src/main/resources/db/migration/V4.70__change_exercise_id_type_for_in_workout_item_table.sql
UPDATE ptcore.in_workout_item SET d_exercise_id = '0' WHERE d_exercise_id is NULL;
ALTER TABLE ptcore.in_workout_item
  RENAME COLUMN d_exercise_id TO exercise_id;
ALTER TABLE ptcore.in_workout_item
  ALTER COLUMN exercise_id TYPE INT USING exercise_id::integer,
  ALTER COLUMN exercise_id SET NOT NULL,
  ALTER COLUMN exercise_id SET DEFAULT 0;
UPDATE ptcore.in_warmup_workout_item SET d_exercise_id = '0' WHERE d_exercise_id is NULL;
ALTER TABLE ptcore.in_warmup_workout_item
  RENAME COLUMN d_exercise_id TO exercise_id;
ALTER TABLE ptcore.in_warmup_workout_item
  ALTER COLUMN exercise_id TYPE INT USING exercise_id::integer,
  ALTER COLUMN exercise_id SET NOT NULL,
  ALTER COLUMN exercise_id SET DEFAULT 0;
<file_sep>/src/main/resources/static/scripts/views/programs.js
/*jshint browser: true*/
/*global define, document*/
define([
    'jquery',
    'underscore',
    'backbone',
    'marionette',
    'moment',
    'app',
    'bootstrapTab'
],
function ($, _, Backbone, Marionette, moment, App) {
  'use strict';

  var EmptyView = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template('<td colspan="7">There are no programs available.</td>')
  });

  var EmptyExercisView = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template('<td colspan="7">There are no exercises available.</td>')
  });

  var EmptyParseView = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template('<td colspan="6">There are no goals available.</td>')
  });

  var Program = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ fileName }}',
      '</td>',
      '<td>',
        '{{ updated == null ? "" : formatDate(updated) }}',
      '</td>',
      '<td>',
        '<a type="button" class="btn btn-default btn-sm" href="/api/v1/admin/program-file/{{ id }}/{{ fileName }}" download>',
          '<i class="glyphicon glyphicon-download"></i>',
        '</a>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-edit-value">',
          '<i class="glyphicon glyphicon-edit"></i>',
        '</button>',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-delete-value">',
          '<i class="glyphicon glyphicon-remove"></i>',
        '</button>',
      '</td>'
    ].join('')),
    templateHelpers: function() {
      return {
        formatDate: function(dateTime) {
          return moment(dateTime).format('DD.MM.YYYY HH:mm');
        }
      };
    },
    initialize: function(options) {
      this.collection = options.collection;
    },
    events: {
      'click .js-edit-value': 'editProgram',
      'click .js-delete-value': 'deleteProgram'
    },
    editProgram: function() {
      this.collection.trigger('program:new', this.model);
    },
    deleteProgram: function(evt) {
      evt.preventDefault();
      var model = this.model;
      var collection = this.collection;
      this.model.destroy()
        .done(function() {
        })
        .fail(function (xhr) {
          App.vent.trigger('xhr:error', 'Program ' + model.get('id') + ' delete was failed');
        })
        .always(function() {
          collection.fetch();
        });
    }
  });

  var ParseResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ loops }}',
      '</td>',
      '<td>',
        '{{ _.map(userGroups, function(item) {return item.name;}) }}',
      '</td>',
      '<td>',
        '{{ errors }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-userGroups">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-userGroups': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._goalName = this.model.get('name');
      this._model.trigger('refresh:userGroups', this.model.get('userGroups'));
      this._model._roundName = '';
      this._model.trigger('refresh:rounds', []);
      this._model._partName = '';
      this._model.trigger('refresh:parts', []);
      this._model._workoutName = '';
      this._model.trigger('refresh:workouts', []);
      this._model.trigger('refresh:workoutItems', []);
    }
  });

  var ParseExerciseResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ exercise_id }}',
      '</td>',
      '<td>',
        '{{ exercise_name }}',
      '</td>',
      '<td>',
        '{{ user_group_1_percent }}',
      '</td>',
      '<td>',
        '{{ user_group_2_percent }}',
      '</td>',
      '<td>',
        '{{ user_group_2_percent }}',
      '</td>',
      '<td>',
        '{{ user_group_4_percent }}',
      '</td>',
      '<td>',
        '{{ basis_for_calculations }}',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    }
  });

  var ParseUserGroupResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ _.map(rounds, function(item) {return item.name;}) }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-round">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-round': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._userGroupName = this.model.get('name');
      this._model.trigger('refresh:rounds', this.model.get('rounds'));
      this._model.trigger('refresh:parts', []);
      this._model._workoutName = '';
      this._model.trigger('refresh:workouts', []);
      this._model.trigger('refresh:workoutItems', []);
    }
  });

  var ParseRoundResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ _.map(parts, function(item) {return item.name;}) }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-round">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-round': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._roundName = this.model.get('name');
      this._model.trigger('refresh:parts', this.model.get('parts'));
      this._model._partName = '';
      this._model.trigger('refresh:workouts', []);
      this._model._workoutName = '';
      this._model.trigger('refresh:workoutItems', []);
    }
  });

  var ParsePartResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ _.map(workouts, function(item) {return item.name;}) }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-workout">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-workout': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._partName = this.model.get('name');
      this._model.trigger('refresh:workouts', this.model.get('workouts'));
      this._model._workoutName = '';
      this._model.trigger('refresh:workoutItems', []);
    }
  });

  var ParseWorkoutResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ _.map(workoutItems, function(item) {return item.name;}) }}',
      '</td>',
      '<td>',
        '<button type="button" class="btn btn-default btn-sm js-view-workout">',
          '<i class="glyphicon glyphicon-expand"></i>',
        '</button>',
      '</td>'
    ].join('')),
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-workout': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._workoutName = this.model.get('name');
      this._model.trigger('refresh:workoutItems', this.model.get('workoutItems'));
    }
  });

  var ParseWorkoutItemResult = Marionette.ItemView.extend({
    tagName: 'tr',
    template: _.template([
      '<td>',
        '{{ id }}',
      '</td>',
      '<td>',
        '{{ name }}',
      '</td>',
      '<td>',
        '{{ getInputs() }}',
      '</td>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getInputs: function () {
          var repetitions = _.compact(_.map(model.get('sets'), function(item) { return item.repetitions; }));
          var weight = _.compact(_.map(model.get('sets'), function(item) { return item.weight; }));
          var timeInMin = _.compact(_.map(model.get('sets'), function(item) { return item['time_in_min']; }));
          return 'sets ' + model.get('sets').length +
                  (_.isEmpty(repetitions) ? '' : ', repetitions ' + repetitions.join(',')) +
                  (_.isEmpty(weight) ? '' : ', weight ' + weight.join(',')) +
                  (_.isEmpty(timeInMin) ? '' : ', time ' + timeInMin.join(','));
        }
      };
    },
    initialize: function(options) {
      this._model = options.rootModel;
    },
    events: {
      'click .js-view-workout': 'reloadData'
    },
    reloadData: function(evt) {
      evt.preventDefault();
      this._model._workoutName = this.model.get('name');
      this._model.trigger('refresh:workoutItemss', this.model.get('workoutItems'));
    }
  });

  var Programs = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: Program,
    emptyView: EmptyView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Programs </h3>',
      '</div>',
      '<button class="btn btn-primary js-new-program" style="margin: 10px;">',
        'New program',
      '</button>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Name</th>',
            '<th>File name</th>',
            '<th>Updated</th>',
            '<th></th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    collectionEvents: {
      'sync': 'render'
    },
    events: {
      'click .js-new-program': 'newProgram'
    },
    newProgram: function() {
      this.collection.trigger('program:new');
    }
  });

  var NewProgramLayout = Marionette.Layout.extend({
    template: _.template([
      '<div class="panel panel-primary">',
        '<div class="panel-heading">',
          '<h3 class="panel-title"> {{ getHeader() }} </h3>',
        '</div>',
        '<div id="buttons"/>',
        '<div id="inputForm"/>',
        '<div id="parseResultTable"/>',
        '<div id="parseGoalResultTable"/>',
        '<div id="parseUserGroupResultTable"/>',
        '<div id="parseRoundResultTable"/>',
        '<div id="parsePartResultTable"/>',
        '<div id="parseWorkoutResultTable"/>',
        '<div id="parseWorkoutItemResultTable"/>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var model = this.model;
      return {
        getHeader: function () {
          return model.isNew() ? 'New program' : 'Edit program';
        }
      };
    },
    tagName: 'form',
    className: 'form-horizontal',
    regions: {
      buttons: '#buttons',
      inputForm: '#inputForm',
      parseResultTable: '#parseResultTable',
      parseGoalResultTable: '#parseGoalResultTable',
      parseUserGroupResultTable: '#parseUserGroupResultTable',
      parseRoundResultTable: '#parseRoundResultTable',
      parsePartResultTable: '#parsePartResultTable',
      parseWorkoutResultTable: '#parseWorkoutResultTable',
      parseWorkoutItemResultTable: '#parseWorkoutItemResultTable'
    },
    onShow: function() {
      this.buttons.show(new NewProgramButtons({model: this.model}));
      this.inputForm.show(new NewProgramInputForm({model: this.model}));
      var goalCollection = new Backbone.Collection(this.model.get('parseGoals'));
      this.parseResultTable.show(new ParseExerciseResultForm({model: this.model,
          collection: new Backbone.Collection(this.model.get('parseExercises')),
          goalCollection: goalCollection
      }));
      this.parseGoalResultTable.show(new ParseResultForm({model: this.model,
          collection: goalCollection}));
      var userGroups = new Backbone.Collection();
      this.parseUserGroupResultTable.show(new ParseUserGroupForm({model: this.model,
          collection: userGroups}));
      this.model.on('refresh:userGroups', function(data) {
          userGroups.set(data);
          userGroups.trigger('sync');
      });
      var rounds = new Backbone.Collection();
      this.parseRoundResultTable.show(new ParseRoundForm({model: this.model,
          collection: rounds}));
      this.model.on('refresh:rounds', function(data) {
          rounds.set(data);
          rounds.trigger('sync');
      });
      var parts = new Backbone.Collection();
      this.parsePartResultTable.show(new ParsePartForm({model: this.model,
          collection: parts}));
      this.model.on('refresh:parts', function(data) {
          parts.set(data);
          parts.trigger('sync');
      });
      var workouts = new Backbone.Collection();
      this.parseWorkoutResultTable.show(new ParseWorkoutForm({model: this.model,
          collection: workouts}));
      this.model.on('refresh:workouts', function(data) {
          workouts.set(data);
          workouts.trigger('sync');
      });
      var workoutItems = new Backbone.Collection();
      this.parseWorkoutItemResultTable.show(new ParseWorkoutItemForm({model: this.model,
          collection: workoutItems}));
      this.model.on('refresh:workoutItems', function(data) {
          workoutItems.set(data);
          workoutItems.trigger('sync');
      });
    }
  });

  var NewProgramButtons = Marionette.ItemView.extend({
    template: _.template([
      '<div class="btn-group">',
        '<button class="btn btn-default js-back" style="margin: 10px 0 0 10px;">',
          'Back',
        '</button>',
        '<button class="btn btn-danger js-save  {{ getSaveDisabled() }}" style="margin: 10px 0 0 0; min-width: 100px;">',
          'Save',
        '</button>',
        '<button class="btn btn-default js-discard" style="margin: 10px 0 0 0px;">',
          'Discard',
        '</button>',
      '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getSaveDisabled: function () {
          return view.model.isValid() ? '' : 'disabled';
        }
      };
    },
    events: {
      'click .js-back': 'back',
      'click .js-save': 'save',
      'click .js-discard': 'discard'
    },
    modelEvents: {
      'change': 'render'
    },
    initialize: function(options) {
      this._model = options.model.clone();
    },
    back: function(evt) {
      evt.preventDefault();
      this.model.trigger('program:back', this.model.get('id'));
    },
    save: function(evt) {
      evt.preventDefault();
      var model = this.model;
      this.model.save().done(function(data) {
        model.trigger('program:back', model.get('id'), data);
      })
      .fail(function (xhr) {
        App.vent.trigger('xhr:error', 'Program save was failed');
      });
    },
    discard: function(evt) {
      evt.preventDefault();
      this.model.set(this._model.toJSON());
      this.model.trigger('sync');
    }
  });

  var ParseResultForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParseResult,
    emptyView: EmptyParseView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Goals </h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Goal name</th>',
            '<th>Loops</th>',
            '<th>User groups</th>',
            '<th>Errors</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ParseExerciseResultForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParseExerciseResult,
    emptyView: EmptyExercisView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function(options) {
        this.goalCollection = options.goalCollection;
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Exercises </h3>',
      '</div>',
      '<button class="btn btn-primary js-parse-file" style="margin: 10px;" {{ getReparseDisabled() }}>',
        'Reparse',
      '</button>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Name</th>',
            '<th>User group 1</th>',
            '<th>User group 2</th>',
            '<th>User group 3</th>',
            '<th>User group 4</th>',
            '<th>Basis for calculations</th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getReparseDisabled: function () {
          return view.model.isValid() ? '' : 'disabled';
        }
      };
    },
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    },
    events: {
      'click .js-parse-file': 'parseFile'
    },
    parseFile: function(evt) {
      evt.preventDefault();
      var model = this.model;
      var view = this;
      this.model.save().done(function() {
        view.collection.reset();
        view.collection.set(model.get('parseExercises'));
        view.goalCollection.set(model.get('parseGoals'));
      })
      .fail(function (xhr) {
        App.vent.trigger('xhr:error', 'Program save was failed');
      });
    }
  });

  var ParseUserGroupForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParseUserGroupResult,
    emptyView: EmptyParseView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> User groups {{ _.isEmpty(getGoalName()) ? "" : "for goal " + getGoalName() }} </h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>User group</th>',
            '<th>Rounds</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getGoalName: function () {
          return view.model._goalName;
        }
      };
    },
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ParseRoundForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParseRoundResult,
    emptyView: EmptyParseView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Rounds {{ _.isEmpty(getUserGroupName()) ? "" : "for user group " + getUserGroupName() }} </h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Round</th>',
            '<th>Parts</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getUserGroupName: function () {
          return view.model._userGroupName;
        }
      };
    },
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ParsePartForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParsePartResult,
    emptyView: EmptyParseView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Parts {{ _.isEmpty(getRoundName()) ? "" : "for round " + getRoundName() }} </h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Part</th>',
            '<th>Workouts</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getRoundName: function () {
          return view.model._roundName;
        }
      };
    },
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ParseWorkoutForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParseWorkoutResult,
    emptyView: EmptyParseView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Workouts {{ _.isEmpty(getPartName()) ? "" : "for part " + getPartName() }} </h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Workout</th>',
            '<th>Exercises</th>',
            '<th></th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getPartName: function () {
          return view.model._partName;
        }
      };
    },
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var ParseWorkoutItemForm = Marionette.CompositeView.extend({
    itemViewContainer: 'tbody',
    itemView: ParseWorkoutItemResult,
    emptyView: EmptyParseView,
    tagName: 'div',
    className: 'js-users-mapping-config',
    ui: {
      table: '.table'
    },
    itemViewOptions : function () {
      return { collection: this.collection, rootModel: this.model };
    },
    initialize: function() {
    },
    template: _.template([
    '<div class="panel panel-primary">',
      '<div class="panel-heading">',
        '<h3 class="panel-title"> Exercises {{ _.isEmpty(getWorkoutName()) ? "" : "for workout " + getWorkoutName() }} </h3>',
      '</div>',
      '<table class="table">',
        '<thead>',
          '<tr>',
            '<th>ID</th>',
            '<th>Exercise</th>',
            '<th>Inputs</th>',
          '</tr>',
        '</thead>',
        '<tbody></tbody>',
      '</table>',
    '</div>'
    ].join('')),
    templateHelpers: function() {
      var view = this;
      return {
        getWorkoutName: function () {
          return view.model._workoutName;
        }
      };
    },
    modelEvents: {
      'change': 'render'
    },
    collectionEvents: {
      'sync': 'render'
    }
  });

  var NewProgramInputForm = Marionette.ItemView.extend({
    className: 'user-input-form',
    template: _.template([
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">ID</label>',
        '<div class="col-sm-8">',
          '<p class="form-control-static">',
            ' {{ id }}',
          '</p>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Name</label>',
        '<div class="col-sm-8">',
          '<textarea id="program-name" class="form-control" rows="3" placeholder="Please enter program name" name="programName" required="true">',
            '{{ name }}',
          '</textarea>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">File name</label>',
        '<div class="col-sm-8">',
          '<p class="form-control-static">',
            ' {{ fileName }}',
          '</p>',
        '</div>',
      '</div>',
      '<div class="form-group">',
        '<label class="col-sm-3 control-label">Excel file (xlsx)</label>',
        '<div class="col-sm-8">',
           '<button class="btn btn-default js-file-upload">Upload file</button>',
           '<input type="file" id="addFile" name="files[]" multiple />',
        '</div>',
      '</div>'
    ].join('')),
    ui: {
      name: '#program-name',
      fileButton: '#addFile'
    },
    events: {
      'input #program-name': 'inputName',
      'click .js-file-upload': 'redirectFileUploading',
      'change #addFile': 'handleFileSelect'
    },
    modelEvents: {
      'sync': 'render'
    },
    inputName: function() {
      this.model.set('name', this.ui.name.val());
    },
    redirectFileUploading: function(evt) {
      evt.preventDefault();
      this.ui.fileButton.click();
    },
    _filerFiles: function(files) {
      return _.filter(files, function(file) {
        return file.type.match(/.*vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet/) ||
            file.name.match(/.*\.xlsx$/);
      });
    },
    handleFileSelect: function(evt) {
      // FileList object
      var files = evt.target.files;
      var view = this;
      // Only process excel documents.
      var filteredFiles = this._filerFiles(files);
      _.each(filteredFiles, function(file) {
        view.model.set({
          fileName: file.name,
          fileSize: file.size,
          fileType: file.type || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        });
        view.model.trigger('sync');
        var reader = new FileReader();
        // Closure to capture the file information.
        reader.onload = (function () {
          return function (e) {
            view.model.set('dataUrl', e.target.result);
            view.model.trigger('sync');
          };
        })();
        // Read in the image file as a data URL.
        reader.readAsDataURL(file);
      });
    }
  });

  return {
    Programs: Programs,
    NewProgramLayout: NewProgramLayout
  };

});
<file_sep>/src/main/resources/db/migration/V4.40__add_device_id_to_in_user_email_table.sql
ALTER TABLE ptcore.in_user_email ADD COLUMN device_id VARCHAR(40) NOT NULL DEFAULT '';
<file_sep>/src/test/java/com/osomapps/pt/tokenemail/TokenEmailServiceTest.java
package com.osomapps.pt.tokenemail;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.osomapps.pt.UnauthorizedException;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserGoal;
import com.osomapps.pt.token.InUserLogin;
import com.osomapps.pt.token.InUserLoginRepository;
import com.osomapps.pt.token.InUserLogout;
import com.osomapps.pt.token.InUserLogoutRepository;
import com.osomapps.pt.token.InUserRepository;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.util.Pair;
import org.springframework.security.crypto.password.PasswordEncoder;

@RunWith(MockitoJUnitRunner.class)
public class TokenEmailServiceTest {

    @Mock private InUserRepository inUserRepository;
    @Mock private InUserEmailRepository inUserEmailRepository;
    @Mock private InUserLoginRepository inUserLoginRepository;
    @Mock private InUserLogoutRepository inUserLogoutRepository;
    @Mock private PasswordEncoder passwordEncoder;
    @InjectMocks private TokenEmailService tokenEmailService;

    @Test
    public void createOrReadNewToken() {
        when(inUserEmailRepository.findByLogin(anyString()))
                .thenReturn(
                        Arrays.asList(
                                new InUserEmail()
                                        .setInUser(
                                                new InUser()
                                                        .setId(1L)
                                                        .setD_level("1")
                                                        .setInUserGoals(
                                                                new ArrayList<>(
                                                                        Arrays.asList(
                                                                                new InUserGoal()
                                                                                .setGoal_value(
                                                                                "{\"key\":10}"))))
                                                        .setHeight(160F)
                                                        .setWeight(80F)
                                                        .setInUserEmails(new ArrayList<>())
                                                        .setInUserLogins(
                                                                new ArrayList<>(
                                                                        Arrays.asList(
                                                                                new InUserLogin()))))));
        when(passwordEncoder.matches(anyObject(), anyObject())).thenReturn(Boolean.TRUE);
        when(inUserLogoutRepository.findByToken(anyString())).thenReturn(Collections.emptyList());
        when(inUserRepository.save(any(InUser.class))).thenAnswer(i -> i.getArguments()[0]);
        TokenEmailResponseDTO tokenEmailResponseDTO =
                tokenEmailService.createOrReadNewToken(
                        new TokenEmailRequestDTO().setEmail("<EMAIL>"), "");
        assertThat(tokenEmailResponseDTO, notNullValue());
    }

    @Test
    public void createOrReadNewToken_not_empty() {
        when(inUserEmailRepository.findByLogin(anyString()))
                .thenReturn(
                        Arrays.asList(
                                new InUserEmail()
                                        .setInUser(
                                                new InUser()
                                                        .setId(1L)
                                                        .setAge(20F)
                                                        .setD_level("1")
                                                        .setInUserGoals(
                                                                Arrays.asList(
                                                                        new InUserGoal()
                                                                                .setGoal_value(
                                                                                "{\"key\":10}")))
                                                        .setInUserEmails(new ArrayList<>())
                                                        .setInUserLogins(
                                                                new ArrayList<>(
                                                                        Arrays.asList(
                                                                                new InUserLogin()))))));
        when(passwordEncoder.matches(anyObject(), anyObject())).thenReturn(Boolean.TRUE);
        when(inUserLogoutRepository.findByToken(anyString()))
                .thenReturn(Arrays.asList(new InUserLogout()));
        when(inUserRepository.save(any(InUser.class))).thenAnswer(i -> i.getArguments()[0]);
        TokenEmailResponseDTO tokenEmailResponseDTO =
                tokenEmailService.createOrReadNewToken(
                        new TokenEmailRequestDTO().setEmail("<EMAIL>"), "");
        assertThat(tokenEmailResponseDTO, notNullValue());
    }

    @Test(expected = UnauthorizedException.class)
    public void readOrCreateInUserEmail_invalid_email() {
        when(inUserEmailRepository.findByLogin(eq("email"))).thenReturn(Collections.emptyList());
        tokenEmailService.readOrCreateInUserEmail(new TokenEmailRequestDTO().setEmail("email"));
    }

    @Test(expected = UnauthorizedException.class)
    public void readOrCreateInUserEmail_wrong_password() {
        when(inUserEmailRepository.findByLogin(eq("email")))
                .thenReturn(Arrays.asList(new InUserEmail()));
        tokenEmailService.readOrCreateInUserEmail(new TokenEmailRequestDTO().setEmail("email"));
    }

    @Test
    public void readOrCreateInUserEmail() {
        when(inUserEmailRepository.findByLogin(eq("email")))
                .thenReturn(
                        Arrays.asList(
                                new InUserEmail()
                                        .setInUser(
                                                new InUser()
                                                        .setInUserLogins(
                                                                Arrays.asList(
                                                                        new InUserLogin())))));
        when(passwordEncoder.matches(anyObject(), anyObject())).thenReturn(Boolean.TRUE);
        when(inUserLogoutRepository.findByToken(anyString()))
                .thenReturn(Arrays.asList(new InUserLogout()));
        Pair<Boolean, InUserEmail> pair =
                tokenEmailService.readOrCreateInUserEmail(
                        new TokenEmailRequestDTO().setEmail("email"));
        assertThat(pair.getFirst(), equalTo(true));
    }

    @Test
    public void readOrCreateInUserEmail_empty() {
        when(inUserEmailRepository.findByLogin(eq("email")))
                .thenReturn(
                        Arrays.asList(
                                new InUserEmail()
                                        .setInUser(
                                                new InUser()
                                                        .setInUserLogins(
                                                                Arrays.asList(
                                                                        new InUserLogin())))));
        when(passwordEncoder.matches(anyObject(), anyObject())).thenReturn(Boolean.TRUE);
        when(inUserLogoutRepository.findByToken(anyString())).thenReturn(Collections.emptyList());
        Pair<Boolean, InUserEmail> pair =
                tokenEmailService.readOrCreateInUserEmail(
                        new TokenEmailRequestDTO().setEmail("email"));
        assertThat(pair.getFirst(), equalTo(false));
    }

    @Test(expected = UnauthorizedException.class)
    public void deleteToken_not_found() {
        tokenEmailService.deleteToken("1", "");
    }

    @Test
    public void deleteToken() {
        InUserLogin inUserLogin = new InUserLogin();
        when(inUserLoginRepository.findByToken(anyString())).thenReturn(Arrays.asList(inUserLogin));
        tokenEmailService.deleteToken("1", "");
        verify(inUserLogoutRepository).saveAndFlush(any());
    }

    @Test(expected = UnauthorizedException.class)
    public void deleteToken_invalid() {
        InUserLogin inUserLogin = new InUserLogin();
        when(inUserLoginRepository.findByToken(anyString())).thenReturn(Arrays.asList(inUserLogin));
        when(inUserLogoutRepository.findByToken(anyString()))
                .thenReturn(Arrays.asList(new InUserLogout()));
        tokenEmailService.deleteToken("1", "");
    }
}
<file_sep>/src/main/resources/db/migration/V4.46__create_email_message_tables.sql
CREATE TABLE ptcore.email_message_type (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    name VARCHAR(50)
);

INSERT INTO ptcore.email_message_type (name) VALUES
('WelcomeMessage'),
('ForgetPasswordMessage');

CREATE TABLE ptcore.email_message_template (
    id BIGSERIAL PRIMARY KEY NOT NULL,
    email_message_type_id BIGINT NOT NULL,
    created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
    d_email_subject VARCHAR(45),
    d_email_text VARCHAR(45),
    FOREIGN KEY (email_message_type_id) REFERENCES ptcore.email_message_type (id) ON UPDATE CASCADE ON DELETE CASCADE
);

INSERT INTO ptcore.email_message_template (email_message_type_id, d_email_subject, d_email_text) VALUES
(1, '10', '10'),
(2, '20', '20');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('email_subject', '10', 'Welcome to the Personal Trainer Application!'),
('email_subject', '20', 'Reset password service');

INSERT INTO ptcore.dictionary_data (dname, dkey, dvalue) VALUES
('email_text', '10', 'Dear {{user_name}}!\n\nYour registration was completed successfully. Please click to the link to confirm your e-mail {{email_confirm_link}}.\n\nYours PT support team.'),
('email_text', '20', 'Dear {{user_name}}!\n\nPlease click to the link to reset your password {{reset_password_link}}.\n\nYours PT support team.');

<file_sep>/src/test/java/com/osomapps/pt/admin/program/ParseWorkoutItemDTOTest.java
package com.osomapps.pt.admin.program;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class ParseWorkoutItemDTOTest {
    @Test
    public void allArgsConstructor() {
        assertThat(new ParseWorkoutItemDTO(1L, null, null), notNullValue());
    }

    @Test
    public void noArgsConstructor() {
        assertThat(new ParseWorkoutItemDTO(), notNullValue());
    }

    @Test
    public void setters() {
        ParseWorkoutItemDTO parseWorkoutItemDTO = new ParseWorkoutItemDTO();
        parseWorkoutItemDTO.setId(null);
        parseWorkoutItemDTO.setName(null);
        parseWorkoutItemDTO.setSets(null);
        assertThat(parseWorkoutItemDTO, notNullValue());
    }

    @Test
    public void getters() {
        ParseWorkoutItemDTO parseWorkoutItemDTO = new ParseWorkoutItemDTO();
        parseWorkoutItemDTO.getId();
        parseWorkoutItemDTO.getName();
        parseWorkoutItemDTO.getSets();
        assertThat(parseWorkoutItemDTO, notNullValue());
    }
}
<file_sep>/src/main/java/com/osomapps/pt/admin/user/AdminUserProgramFileService.java
package com.osomapps.pt.admin.user;

import com.osomapps.pt.ResourceNotFoundException;
import com.osomapps.pt.dictionary.DictionaryService;
import com.osomapps.pt.token.InUser;
import com.osomapps.pt.token.InUserRepository;
import com.osomapps.pt.xlsx.XlsxProgramModifier;
import com.osomapps.pt.xlsx.XlsxProgramParser;
import java.io.IOException;
import java.io.InputStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream;

@Slf4j
@Service
class AdminUserProgramFileService {

    private final DictionaryService dictionaryService;
    private final InUserRepository inUserRepository;

    AdminUserProgramFileService(
            DictionaryService dictionaryService, InUserRepository inUserRepository) {
        this.dictionaryService = dictionaryService;
        this.inUserRepository = inUserRepository;
    }

    ProgramResponseDTO createXlsx(Long id, FastByteArrayOutputStream outputStream) {
        final InUser inUser = inUserRepository.findById(id).orElse(null);
        if (inUser == null) {
            throw new ResourceNotFoundException("User with id " + id + " not found.");
        }
        try (InputStream inputStream =
                        XlsxProgramParser.class.getResourceAsStream("program01.xlsx");
                FastByteArrayOutputStream localOutputStream = new FastByteArrayOutputStream()) {
            final byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                localOutputStream.write(buffer, 0, length);
            }
            final XlsxProgramModifier xlsxProgramModifier =
                    XlsxProgramModifier.of(localOutputStream.getInputStream(), dictionaryService);
            xlsxProgramModifier.updateCellData(outputStream, inUser);
            return new ProgramResponseDTO()
                    .setFileName("program_for_user_" + id + ".xlsx")
                    .setFileType(
                            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
            throw new UnsupportedOperationException(ex);
        }
    }
}

languages:
Shell
Java
Markdown
Procfile
SQL
YAML
JavaScript
Less
Maven POM

repo_language: Shell

repo_name: javadev/pt-backend