autocomit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package com.ldpv2.controller;
|
||||
|
||||
import com.ldpv2.dto.request.CreateBusinessUnitRequest;
|
||||
import com.ldpv2.dto.request.UpdateBusinessUnitRequest;
|
||||
import com.ldpv2.dto.response.BusinessUnitResponse;
|
||||
import com.ldpv2.service.BusinessUnitService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/business-units")
|
||||
@Tag(name = "Business Units", description = "Business unit management endpoints")
|
||||
@SecurityRequirement(name = "bearerAuth")
|
||||
public class BusinessUnitController {
|
||||
|
||||
@Autowired
|
||||
private BusinessUnitService businessUnitService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "Create business unit", description = "Create a new business unit")
|
||||
public ResponseEntity<BusinessUnitResponse> create(@Valid @RequestBody CreateBusinessUnitRequest request) {
|
||||
BusinessUnitResponse response = businessUnitService.create(request);
|
||||
return new ResponseEntity<>(response, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "Update business unit", description = "Update an existing business unit")
|
||||
public ResponseEntity<BusinessUnitResponse> update(
|
||||
@PathVariable UUID id,
|
||||
@Valid @RequestBody UpdateBusinessUnitRequest request) {
|
||||
BusinessUnitResponse response = businessUnitService.update(id, request);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "Get business unit", description = "Get business unit by ID")
|
||||
public ResponseEntity<BusinessUnitResponse> getById(@PathVariable UUID id) {
|
||||
BusinessUnitResponse response = businessUnitService.findById(id);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "List business units", description = "Get paginated list of business units")
|
||||
public ResponseEntity<Page<BusinessUnitResponse>> getAll(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size,
|
||||
@RequestParam(defaultValue = "name") String sortBy,
|
||||
@RequestParam(defaultValue = "asc") String sortDirection) {
|
||||
|
||||
Sort sort = sortDirection.equalsIgnoreCase("desc")
|
||||
? Sort.by(sortBy).descending()
|
||||
: Sort.by(sortBy).ascending();
|
||||
|
||||
Pageable pageable = PageRequest.of(page, size, sort);
|
||||
Page<BusinessUnitResponse> response = businessUnitService.findAll(pageable);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@GetMapping("/search")
|
||||
@Operation(summary = "Search business units", description = "Search business units by name")
|
||||
public ResponseEntity<Page<BusinessUnitResponse>> search(
|
||||
@RequestParam String q,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<BusinessUnitResponse> response = businessUnitService.search(q, pageable);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "Delete business unit", description = "Delete a business unit")
|
||||
public ResponseEntity<Void> delete(@PathVariable UUID id) {
|
||||
businessUnitService.delete(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.ldpv2.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Business Unit entity representing organizational units
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "business_unit")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BusinessUnit extends BaseEntity {
|
||||
|
||||
@Column(nullable = false, unique = true, length = 255)
|
||||
private String name;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ldpv2.dto.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CreateBusinessUnitRequest {
|
||||
|
||||
@NotBlank(message = "Name is required")
|
||||
@Size(max = 255, message = "Name must not exceed 255 characters")
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ldpv2.dto.request;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UpdateBusinessUnitRequest {
|
||||
|
||||
@Size(max = 255, message = "Name must not exceed 255 characters")
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ldpv2.dto.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BusinessUnitResponse {
|
||||
private UUID id;
|
||||
private String name;
|
||||
private String description;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ldpv2.dto.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BusinessUnitSummaryResponse {
|
||||
private UUID id;
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ldpv2.repository;
|
||||
|
||||
import com.ldpv2.domain.entity.BusinessUnit;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface BusinessUnitRepository extends JpaRepository<BusinessUnit, UUID> {
|
||||
Optional<BusinessUnit> findByName(String name);
|
||||
boolean existsByName(String name);
|
||||
Page<BusinessUnit> findByNameContainingIgnoreCase(String name, Pageable pageable);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.ldpv2.service;
|
||||
|
||||
import com.ldpv2.domain.entity.BusinessUnit;
|
||||
import com.ldpv2.dto.request.CreateBusinessUnitRequest;
|
||||
import com.ldpv2.dto.request.UpdateBusinessUnitRequest;
|
||||
import com.ldpv2.dto.response.BusinessUnitResponse;
|
||||
import com.ldpv2.exception.BadRequestException;
|
||||
import com.ldpv2.exception.ResourceNotFoundException;
|
||||
import com.ldpv2.repository.BusinessUnitRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class BusinessUnitService {
|
||||
|
||||
@Autowired
|
||||
private BusinessUnitRepository businessUnitRepository;
|
||||
|
||||
@Transactional
|
||||
public BusinessUnitResponse create(CreateBusinessUnitRequest request) {
|
||||
// Check if name already exists
|
||||
if (businessUnitRepository.existsByName(request.getName())) {
|
||||
throw new BadRequestException("Business unit with name '" + request.getName() + "' already exists");
|
||||
}
|
||||
|
||||
BusinessUnit businessUnit = new BusinessUnit();
|
||||
businessUnit.setName(request.getName());
|
||||
businessUnit.setDescription(request.getDescription());
|
||||
|
||||
businessUnit = businessUnitRepository.save(businessUnit);
|
||||
return mapToResponse(businessUnit);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public BusinessUnitResponse update(UUID id, UpdateBusinessUnitRequest request) {
|
||||
BusinessUnit businessUnit = businessUnitRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Business unit not found with id: " + id));
|
||||
|
||||
// Check if new name already exists (excluding current business unit)
|
||||
if (request.getName() != null && !request.getName().equals(businessUnit.getName())) {
|
||||
if (businessUnitRepository.existsByName(request.getName())) {
|
||||
throw new BadRequestException("Business unit with name '" + request.getName() + "' already exists");
|
||||
}
|
||||
businessUnit.setName(request.getName());
|
||||
}
|
||||
|
||||
if (request.getDescription() != null) {
|
||||
businessUnit.setDescription(request.getDescription());
|
||||
}
|
||||
|
||||
businessUnit = businessUnitRepository.save(businessUnit);
|
||||
return mapToResponse(businessUnit);
|
||||
}
|
||||
|
||||
public BusinessUnitResponse findById(UUID id) {
|
||||
BusinessUnit businessUnit = businessUnitRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Business unit not found with id: " + id));
|
||||
return mapToResponse(businessUnit);
|
||||
}
|
||||
|
||||
public Page<BusinessUnitResponse> findAll(Pageable pageable) {
|
||||
return businessUnitRepository.findAll(pageable).map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public Page<BusinessUnitResponse> search(String query, Pageable pageable) {
|
||||
return businessUnitRepository.findByNameContainingIgnoreCase(query, pageable)
|
||||
.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(UUID id) {
|
||||
if (!businessUnitRepository.existsById(id)) {
|
||||
throw new ResourceNotFoundException("Business unit not found with id: " + id);
|
||||
}
|
||||
businessUnitRepository.deleteById(id);
|
||||
}
|
||||
|
||||
private BusinessUnitResponse mapToResponse(BusinessUnit businessUnit) {
|
||||
return new BusinessUnitResponse(
|
||||
businessUnit.getId(),
|
||||
businessUnit.getName(),
|
||||
businessUnit.getDescription(),
|
||||
businessUnit.getCreatedAt(),
|
||||
businessUnit.getUpdatedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
<insert tableName="users">
|
||||
<column name="username" value="admin"/>
|
||||
<!-- <column name="password" value="$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"/>-->
|
||||
<column name="password" value="$2a$12$ZDflpzoNCyt/hDu9PyMqE.jinzhLtQ8Cjc/NgvXU7BIxni.SH2PnW"/>
|
||||
<column name="password" value="$2a$12$mCGWGeNM3r11.yFhPFi22e./YQl2pRTIpJBVUwydScZioE3y6xm3m"/>
|
||||
<column name="email" value="admin@ldpv2.com"/>
|
||||
<column name="role" value="ADMIN"/>
|
||||
</insert>
|
||||
|
||||
@@ -10,4 +10,7 @@
|
||||
<include file="db/changelog/v1.0/002-create-environment-table.xml"/>
|
||||
<include file="db/changelog/data/initial-data.xml"/>
|
||||
|
||||
<!-- Story 1: Business Units -->
|
||||
<include file="db/changelog/v1.0/003-create-business-unit-table.xml"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
||||
|
||||
<changeSet id="003-create-business-unit-table" author="ldpv2-team">
|
||||
|
||||
<!-- Create business_unit table -->
|
||||
<createTable tableName="business_unit">
|
||||
<column name="id" type="UUID" defaultValueComputed="uuid_generate_v4()">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(255)">
|
||||
<constraints nullable="false" unique="true"/>
|
||||
</column>
|
||||
<column name="description" type="TEXT"/>
|
||||
<column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<!-- Create index on name for search performance -->
|
||||
<createIndex tableName="business_unit" indexName="idx_business_unit_name">
|
||||
<column name="name"/>
|
||||
</createIndex>
|
||||
|
||||
<!-- Insert sample data for testing -->
|
||||
<insert tableName="business_unit">
|
||||
<column name="name" value="Digital Services"/>
|
||||
<column name="description" value="Digital transformation initiatives and online services"/>
|
||||
</insert>
|
||||
|
||||
<insert tableName="business_unit">
|
||||
<column name="name" value="Operations"/>
|
||||
<column name="description" value="Core business operations and support"/>
|
||||
</insert>
|
||||
|
||||
<insert tableName="business_unit">
|
||||
<column name="name" value="Finance"/>
|
||||
<column name="description" value="Financial services and accounting systems"/>
|
||||
</insert>
|
||||
|
||||
<insert tableName="business_unit">
|
||||
<column name="name" value="Human Resources"/>
|
||||
<column name="description" value="HR management and employee services"/>
|
||||
</insert>
|
||||
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user