<file_sep>package com.dmitrykazanbaev.alfa3task.service;

import com.dmitrykazanbaev.alfa3task.model.Branch;
import com.dmitrykazanbaev.alfa3task.model.BranchWithDistance;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
public interface BranchCrudRepository extends CrudRepository<Branch, Integer> {
    @Query(value = "select \n" +
            "  br.*, \n" +
            "  round(\n" +
            "    2 * 6371000 * asin(\n" +
            "      sqrt(\n" +
            "        power(\n" +
            "          sin(\n" +
            "            (radians(:givenLat) - radians(br.lat))/ 2.0\n" +
            "          ), \n" +
            "          2.0\n" +
            "        )+ cos(radians(:givenLat))* cos(radians(br.lat))* power(\n" +
            "          sin(\n" +
            "            (radians(:givenLon) - radians(br.lon))/ 2.0\n" +
            "          ), \n" +
            "          2.0\n" +
            "        )\n" +
            "      )\n" +
            "    )\n" +
            "  ) as distance \n" +
            "from \n" +
            "  branches br \n" +
            "order by \n" +
            "  distance \n" +
            "limit \n" +
            "  1",
    nativeQuery = true)
    BranchWithDistance getClosestBranch(@Param("givenLat") BigDecimal givenLat, @Param("givenLon") BigDecimal givenLon);
}
<file_sep>package com.dmitrykazanbaev.alfa3task;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Alfa3taskApplication {

	public static void main(String[] args) {
		SpringApplication.run(Alfa3taskApplication.class, args);
	}

}
<file_sep>package com.dmitrykazanbaev.alfa3task.model;

import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class BranchWithPrediction {
    @JsonUnwrapped
    private Branch branch;

    private Integer dayOfWeek;

    private Integer hourOfDay;

    private Long predicting;
}
<file_sep>package com.dmitrykazanbaev.alfa3task.controller;

import com.dmitrykazanbaev.alfa3task.exception.ApiError;
import com.dmitrykazanbaev.alfa3task.exception.NotFoundBranchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class BranchesExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler
    public ResponseEntity<Object> handle(NotFoundBranchException exception) {
        return new ResponseEntity<>(new ApiError("branch not found"), HttpStatus.NOT_FOUND);
    }
}
<file_sep>package com.dmitrykazanbaev.alfa3task.model;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;

@Entity
@Table(name = "branches")
@Data
public class Branch {
    @Id
    private Integer id;
    @Column
    private String title;
    @Column
    private BigDecimal lon;
    @Column
    private BigDecimal lat;
    @Column
    private String address;
}
<file_sep>package com.dmitrykazanbaev.alfa3task.model;

import java.math.BigDecimal;

public interface BranchWithDistance {
    Integer getId();

    String getTitle();

    BigDecimal getLon();

    BigDecimal getLat();

    String getAddress();

    Long getDistance();
}
<file_sep>package com.dmitrykazanbaev.alfa3task.model;

import lombok.Data;

import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalTime;

@Entity
@Table(name = "queue_log")
@Data
public class QueueLog {
    @Column
    private LocalDate data;
    @Column
    private LocalTime startTimeOfWait;
    @Column
    private LocalTime endTimeOfWait;
    @Column
    private LocalTime endTimeOfService;
    @ManyToOne(targetEntity = Branch.class)
    private Integer branchesId;
    @Id
    private Integer id;
}
