-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
src/main/java/app/teamwize/api/holiday/config/HolidayConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package app.teamwize.api.holiday.config; | ||
|
||
import app.teamwize.api.holiday.provider.OpenHolidayProvider; | ||
import app.teamwize.api.holiday.provider.PublicHolidayProvider; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.client.RestClient; | ||
|
||
|
||
@Configuration | ||
public class HolidayConfig { | ||
|
||
@Bean | ||
PublicHolidayProvider openHolidayProvider() { | ||
var restClient = RestClient.builder().baseUrl("https://openholidaysapi.org") | ||
.build(); | ||
return new OpenHolidayProvider(restClient); | ||
} | ||
|
||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/app/teamwize/api/holiday/controller/HolidayController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package app.teamwize.api.holiday.controller; | ||
|
||
import app.teamwize.api.auth.service.SecurityService; | ||
import app.teamwize.api.holiday.domain.exception.PublicHolidayProviderConnectionBrokenException; | ||
import app.teamwize.api.holiday.domain.response.FetchedPublicHoliday; | ||
import app.teamwize.api.holiday.domain.request.HolidayCreateRequest; | ||
import app.teamwize.api.holiday.domain.response.HolidayResponse; | ||
import app.teamwize.api.holiday.mapper.HolidayMapper; | ||
import app.teamwize.api.holiday.service.HolidayService; | ||
import app.teamwize.api.organization.exception.OrganizationNotFoundException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.util.List; | ||
|
||
@RestController | ||
@RequestMapping("holidays") | ||
@RequiredArgsConstructor | ||
public class HolidayController { | ||
|
||
private final HolidayService holidayService; | ||
private final SecurityService securityService; | ||
private final HolidayMapper holidayMapper; | ||
|
||
@PostMapping("batch") | ||
public List<HolidayResponse> createHolidays(@RequestBody List<HolidayCreateRequest> requests) throws OrganizationNotFoundException { | ||
var holidays = holidayService.createHolidays(securityService.getUserOrganizationId(), requests); | ||
return holidayMapper.toHolidayResponses(holidays); | ||
} | ||
|
||
@GetMapping("fetch") | ||
public List<FetchedPublicHoliday> fetchPublicHoliday(Integer year) throws OrganizationNotFoundException, PublicHolidayProviderConnectionBrokenException { | ||
return holidayService.fetchPublicHolidays(securityService.getUserOrganizationId(), year); | ||
} | ||
|
||
@GetMapping | ||
public List<HolidayResponse> getHolidays(Integer year, String countryCode) { | ||
var holidays = holidayService.getHolidays(securityService.getUserOrganizationId(), year, countryCode); | ||
return holidayMapper.toHolidayResponses(holidays); | ||
} | ||
|
||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/app/teamwize/api/holiday/domain/HolidayStatus.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package app.teamwize.api.holiday.domain; | ||
|
||
public enum HolidayStatus { | ||
ACTIVE, | ||
ARCHIVED | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/app/teamwize/api/holiday/domain/entity/Holiday.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package app.teamwize.api.holiday.domain.entity; | ||
|
||
import app.teamwize.api.base.domain.entity.BaseAuditEntity; | ||
import app.teamwize.api.holiday.domain.HolidayStatus; | ||
import app.teamwize.api.organization.domain.entity.Organization; | ||
import jakarta.persistence.*; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
import java.time.LocalDate; | ||
|
||
@Getter | ||
@Setter | ||
@Entity | ||
@Table(name = "holidays") | ||
public class Holiday extends BaseAuditEntity { | ||
@Id | ||
@GeneratedValue(generator = "holiday_id_seq_generator") | ||
@SequenceGenerator(name = "holiday_id_seq_generator", sequenceName = "holiday_id_seq", allocationSize = 10) | ||
protected Long id; | ||
|
||
private LocalDate date; | ||
|
||
private String countryCode; | ||
|
||
private String description; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private HolidayStatus status; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
private Organization organization; | ||
|
||
} |
4 changes: 4 additions & 0 deletions
4
...teamwize/api/holiday/domain/exception/PublicHolidayProviderConnectionBrokenException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package app.teamwize.api.holiday.domain.exception; | ||
|
||
public class PublicHolidayProviderConnectionBrokenException extends Exception { | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/app/teamwize/api/holiday/domain/request/HolidayCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package app.teamwize.api.holiday.domain.request; | ||
|
||
import java.time.LocalDate; | ||
|
||
public record HolidayCreateRequest(String description, LocalDate date,String countryCode) { | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/app/teamwize/api/holiday/domain/response/FetchedPublicHoliday.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package app.teamwize.api.holiday.domain.response; | ||
|
||
import java.time.LocalDate; | ||
|
||
public record FetchedPublicHoliday(LocalDate date, String type, String name){} |
6 changes: 6 additions & 0 deletions
6
src/main/java/app/teamwize/api/holiday/domain/response/HolidayResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package app.teamwize.api.holiday.domain.response; | ||
|
||
import java.time.LocalDate; | ||
|
||
public record HolidayResponse(Long id, String description, LocalDate date, String countryCode) { | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/app/teamwize/api/holiday/mapper/HolidayMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package app.teamwize.api.holiday.mapper; | ||
|
||
import app.teamwize.api.base.config.DefaultMapperConfig; | ||
import app.teamwize.api.holiday.domain.entity.Holiday; | ||
import app.teamwize.api.holiday.domain.response.HolidayResponse; | ||
import org.mapstruct.Mapper; | ||
|
||
import java.util.List; | ||
|
||
@Mapper(config = DefaultMapperConfig.class) | ||
public interface HolidayMapper { | ||
List<HolidayResponse> toHolidayResponses(List<Holiday> holidays); | ||
} |
57 changes: 57 additions & 0 deletions
57
src/main/java/app/teamwize/api/holiday/provider/OpenHolidayProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package app.teamwize.api.holiday.provider; | ||
|
||
import app.teamwize.api.holiday.domain.response.FetchedPublicHoliday; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.core.ParameterizedTypeReference; | ||
import org.springframework.web.client.RestClient; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
import static org.springframework.http.MediaType.APPLICATION_JSON; | ||
|
||
@RequiredArgsConstructor | ||
public class OpenHolidayProvider implements PublicHolidayProvider { | ||
|
||
private final RestClient restClient; | ||
|
||
record OpenHolidayResponse( | ||
String id, | ||
LocalDate startDate, | ||
String endDate, | ||
String type, | ||
List<OpenHolidayResponseName> name, | ||
boolean nationwide) { | ||
} | ||
|
||
record OpenHolidayResponseName( | ||
String language, | ||
String text) { | ||
} | ||
|
||
|
||
@Override | ||
public List<FetchedPublicHoliday> getPublicHolidays(String countryCode, Integer year) { | ||
List<OpenHolidayResponse> publicHolidays = this.restClient.get().uri(uriBuilder -> uriBuilder | ||
.path("/PublicHolidays") | ||
.queryParam("countryIsoCode", countryCode) | ||
.queryParam("languageIsoCode", "EN") | ||
.queryParam("validFrom", LocalDate.of(year, 1, 1).toString()) | ||
.queryParam("validTo", LocalDate.of(year + 1, 1, 1).toString()) | ||
.build()) | ||
|
||
.accept(APPLICATION_JSON).retrieve() | ||
.body(new ParameterizedTypeReference<>() { | ||
}); | ||
|
||
return publicHolidays | ||
.stream() | ||
.map(this::toFetchedPublicHoliday) | ||
.toList(); | ||
} | ||
|
||
|
||
private FetchedPublicHoliday toFetchedPublicHoliday(OpenHolidayResponse response) { | ||
return new FetchedPublicHoliday(response.startDate, response.type, response.name.get(0).text); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/app/teamwize/api/holiday/provider/PublicHolidayProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package app.teamwize.api.holiday.provider; | ||
|
||
|
||
import app.teamwize.api.holiday.domain.response.FetchedPublicHoliday; | ||
|
||
import java.util.List; | ||
|
||
public interface PublicHolidayProvider { | ||
List<FetchedPublicHoliday> getPublicHolidays(String countryCode, Integer year); | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/app/teamwize/api/holiday/repository/HolidayRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package app.teamwize.api.holiday.repository; | ||
|
||
import app.teamwize.api.holiday.domain.entity.Holiday; | ||
import io.hypersistence.utils.spring.repository.BaseJpaRepository; | ||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
@RequestMapping | ||
public interface HolidayRepository extends BaseJpaRepository<Holiday, Long>, JpaSpecificationExecutor<Holiday> { | ||
List<Holiday> findByOrganizationIdAndCountryCodeAndDateIsBetween(Long organizationId, String countryCode, LocalDate startDate,LocalDate endDate); | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/app/teamwize/api/holiday/service/HolidayService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package app.teamwize.api.holiday.service; | ||
|
||
import app.teamwize.api.holiday.domain.exception.PublicHolidayProviderConnectionBrokenException; | ||
import app.teamwize.api.holiday.domain.response.FetchedPublicHoliday; | ||
import app.teamwize.api.holiday.domain.entity.Holiday; | ||
import app.teamwize.api.holiday.domain.request.HolidayCreateRequest; | ||
import app.teamwize.api.holiday.provider.PublicHolidayProvider; | ||
import app.teamwize.api.holiday.repository.HolidayRepository; | ||
import app.teamwize.api.organization.exception.OrganizationNotFoundException; | ||
import app.teamwize.api.organization.service.OrganizationService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class HolidayService { | ||
|
||
private final HolidayRepository holidayRepository; | ||
private final OrganizationService organizationService; | ||
private final PublicHolidayProvider publicHolidayProvider; | ||
|
||
@Transactional | ||
public List<Holiday> createHolidays(Long organizationId, List<HolidayCreateRequest> requests) throws OrganizationNotFoundException { | ||
var organization = organizationService.getOrganization(organizationId); | ||
var holidays = requests.stream().map(holidayCreateRequest -> new Holiday() | ||
.setDescription(holidayCreateRequest.description()) | ||
.setDate(holidayCreateRequest.date()) | ||
.setCountryCode(holidayCreateRequest.countryCode()) | ||
.setOrganization(organization) | ||
).toList(); | ||
return holidayRepository.persistAll(holidays); | ||
} | ||
|
||
@Transactional | ||
public List<FetchedPublicHoliday> fetchPublicHolidays(Long organizationId, Integer year) throws OrganizationNotFoundException, PublicHolidayProviderConnectionBrokenException { | ||
if (year == null) { | ||
year = LocalDate.now().getYear(); | ||
} | ||
var organization = organizationService.getOrganization(organizationId); | ||
try { | ||
return publicHolidayProvider.getPublicHolidays(organization.getCountry(), year); | ||
} catch (Exception ex) { | ||
throw new PublicHolidayProviderConnectionBrokenException(); | ||
} | ||
} | ||
|
||
public List<Holiday> getHolidays(Long organizationId, Integer year, String countryCode) { | ||
var startDate = LocalDate.of(year, 1, 1); | ||
var endDate = startDate.plusYears(1); | ||
return holidayRepository.findByOrganizationIdAndCountryCodeAndDateIsBetween(organizationId, countryCode, startDate, endDate); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/main/resources/db/changelog/20240815-1430-create-holidays-table.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<databaseChangeLog | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog | ||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"> | ||
|
||
<changeSet id="20240815-1430-create-holidays-table" author="M.Karimi"> | ||
<createSequence sequenceName="holiday_id_seq" startValue="1" minValue="1" incrementBy="10" cycle="false"/> | ||
|
||
<createTable tableName="holidays"> | ||
<column name="id" type="BIGINT" defaultValue="nextval('holiday_id_seq')"> | ||
<constraints nullable="false" primaryKey="true" primaryKeyName="holiday_key_pkey"/> | ||
</column> | ||
<column name="created_at" type="TIMESTAMP WITHOUT TIME ZONE"/> | ||
<column name="updated_at" type="TIMESTAMP WITHOUT TIME ZONE"/> | ||
|
||
|
||
<column name="description" type="VARCHAR"/> | ||
|
||
<column name="status" type="VARCHAR"/> | ||
|
||
<column name="country_code" type="VARCHAR"/> | ||
|
||
<column name="date" type="DATE"/> | ||
|
||
<column name="organization_id" type="BIGINT"> | ||
<constraints nullable="false"/> | ||
</column> | ||
|
||
<column name="metadata" type="JSONB"/> | ||
</createTable> | ||
|
||
<addForeignKeyConstraint baseTableName="holidays" baseColumnNames="organization_id" | ||
constraintName="holidays_organization_id_fkey" | ||
referencedTableName="organizations" referencedColumnNames="id"/> | ||
</changeSet> | ||
</databaseChangeLog> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters