diff --git a/src/main/java/com/mobility/api/domain/office/controller/OfficeV1Controller.java b/src/main/java/com/mobility/api/domain/office/controller/OfficeV1Controller.java index fc20a67..cab9e60 100644 --- a/src/main/java/com/mobility/api/domain/office/controller/OfficeV1Controller.java +++ b/src/main/java/com/mobility/api/domain/office/controller/OfficeV1Controller.java @@ -1,14 +1,8 @@ package com.mobility.api.domain.office.controller; import com.mobility.api.domain.dispatch.entity.Dispatch; -import com.mobility.api.domain.office.dto.request.CancelDispatchReq; -import com.mobility.api.domain.office.dto.request.CreateDispatchReq; -import com.mobility.api.domain.office.dto.request.DispatchSearchDto; -import com.mobility.api.domain.office.dto.request.UpdateDispatchReq; -import com.mobility.api.domain.office.dto.response.DispatchFeedRes; -import com.mobility.api.domain.office.dto.response.DispatchSummaryRes; -import com.mobility.api.domain.office.dto.response.GetAllDispatchRes; -import com.mobility.api.domain.office.dto.response.GetDispatchDetailRes; +import com.mobility.api.domain.office.dto.request.*; +import com.mobility.api.domain.office.dto.response.*; import com.mobility.api.domain.office.service.OfficeService; import com.mobility.api.domain.transporter.dto.request.TransporterCreateReq; import com.mobility.api.domain.transporter.dto.request.TransporterStatusUpdateReq; @@ -40,6 +34,34 @@ public class OfficeV1Controller { private final OfficeService officeService; + /** + *
+     * 사무실 정보 조회
+     * 
+ */ + @Operation(summary = "사무실 정보 조회", description = "현재 로그인한 관리자가 소속된 사무실의 상세 정보를 조회합니다.") + @GetMapping("/profile") // URL: /api/v1/office/profile + public CommonResponse getOfficeProfile( + @AuthenticationPrincipal PrincipalDetails user + ) { + return CommonResponse.success(officeService.getOfficeProfile(user.getManager())); + } + + /** + *
+     * 사무실 정보 수정
+     * 
+ */ + @Operation(summary = "사무실 정보 수정", description = "소속된 사무실의 상세 정보를 수정합니다.") + @PatchMapping("/profile") + public CommonResponse updateOfficeProfile( + @AuthenticationPrincipal PrincipalDetails user, + @RequestBody @Valid OfficeUpdateReq req + ) { + officeService.updateOfficeProfile(user.getManager(), req); + return CommonResponse.success("사무실 정보가 성공적으로 수정되었습니다."); + } + /** *
      *     사무실 - 배차 리스트 조회
diff --git a/src/main/java/com/mobility/api/domain/office/dto/request/OfficeUpdateReq.java b/src/main/java/com/mobility/api/domain/office/dto/request/OfficeUpdateReq.java
new file mode 100644
index 0000000..6c61fbd
--- /dev/null
+++ b/src/main/java/com/mobility/api/domain/office/dto/request/OfficeUpdateReq.java
@@ -0,0 +1,16 @@
+package com.mobility.api.domain.office.dto.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+
+public record OfficeUpdateReq(
+
+        String name,            // officeName 매핑
+
+        String registrationNumber, // officeRegistrationNumber 매핑
+
+        String address,         // officeAddress 매핑
+
+        @Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$", message = "올바른 전화번호 형식이 아닙니다.")
+        String telNumber        // officeTelNumber 매핑
+) {}
\ No newline at end of file
diff --git a/src/main/java/com/mobility/api/domain/office/dto/response/OfficeProfileRes.java b/src/main/java/com/mobility/api/domain/office/dto/response/OfficeProfileRes.java
new file mode 100644
index 0000000..1bc1277
--- /dev/null
+++ b/src/main/java/com/mobility/api/domain/office/dto/response/OfficeProfileRes.java
@@ -0,0 +1,27 @@
+package com.mobility.api.domain.office.dto.response;
+
+import com.mobility.api.domain.office.entity.Office;
+import lombok.Builder;
+
+@Builder
+public record OfficeProfileRes(
+        Long id,
+        String name,           // 사무실 이름
+        String registrationNumber, // 사업자 번호
+        String telNumber,          // 사업장 전화번호
+        String address,        // 주소
+        String createdAt,       // 가입일
+        String updatedAt       // 수정일
+) {
+    public static OfficeProfileRes from(Office office) {
+        return OfficeProfileRes.builder()
+                .id(office.getId())
+                .name(office.getOfficeName())
+                .registrationNumber(office.getOfficeRegistrationNumber())
+                .telNumber(office.getOfficeTelNumber())
+                .address(office.getOfficeAddress())
+                .createdAt(office.getCreatedAt().toString())
+                .updatedAt(office.getUpdatedAt().toString())
+                .build();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/mobility/api/domain/office/entity/Manager.java b/src/main/java/com/mobility/api/domain/office/entity/Manager.java
index 7440721..7b1b5ea 100644
--- a/src/main/java/com/mobility/api/domain/office/entity/Manager.java
+++ b/src/main/java/com/mobility/api/domain/office/entity/Manager.java
@@ -4,10 +4,7 @@
 import com.mobility.api.domain.office.enums.ManagerStatus;
 import com.mobility.api.global.entity.BaseSoftDeleteEntity;
 import jakarta.persistence.*;
-import lombok.AccessLevel;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
+import lombok.*;
 import org.hibernate.annotations.SQLDelete;
 
 @Entity
diff --git a/src/main/java/com/mobility/api/domain/office/entity/Office.java b/src/main/java/com/mobility/api/domain/office/entity/Office.java
index b6c6fe7..b973b33 100644
--- a/src/main/java/com/mobility/api/domain/office/entity/Office.java
+++ b/src/main/java/com/mobility/api/domain/office/entity/Office.java
@@ -1,5 +1,7 @@
 package com.mobility.api.domain.office.entity;
 
+import com.mobility.api.domain.office.dto.request.OfficeUpdateReq;
+import com.mobility.api.global.entity.BaseEntity;
 import jakarta.persistence.*;
 import lombok.*;
 
@@ -8,7 +10,7 @@
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
 @AllArgsConstructor
 @Table(name = "office")
-public class Office {
+public class Office extends BaseEntity {
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -37,4 +39,20 @@ public Office(String officeName, String officeRegistrationNumber, String officeA
         this.officeAddress = officeAddress;
         this.officeTelNumber = officeTelNumber;
     }
+
+    public void updateProfile(OfficeUpdateReq req) {
+        // 값이 null이 아니고, (필요시) 비어있지 않은 경우에만 업데이트
+        if (req.name() != null) {
+            this.officeName = req.name();
+        }
+        if (req.registrationNumber() != null) {
+            this.officeRegistrationNumber = req.registrationNumber();
+        }
+        if (req.address() != null) {
+            this.officeAddress = req.address();
+        }
+        if (req.telNumber() != null) {
+            this.officeTelNumber = req.telNumber();
+        }
+    }
 }
diff --git a/src/main/java/com/mobility/api/domain/office/service/OfficeService.java b/src/main/java/com/mobility/api/domain/office/service/OfficeService.java
index 0b3ce20..5422ea1 100644
--- a/src/main/java/com/mobility/api/domain/office/service/OfficeService.java
+++ b/src/main/java/com/mobility/api/domain/office/service/OfficeService.java
@@ -5,16 +5,11 @@
 import com.mobility.api.domain.dispatch.enums.StatusType;
 import com.mobility.api.domain.dispatch.repository.DispatchRepository;
 import com.mobility.api.domain.dispatch.service.AutoDispatchService;
-import com.mobility.api.domain.office.dto.request.CancelDispatchReq;
-import com.mobility.api.domain.office.dto.request.CreateDispatchReq;
-import com.mobility.api.domain.office.dto.request.DispatchSearchDto;
-import com.mobility.api.domain.office.dto.request.UpdateDispatchReq;
-import com.mobility.api.domain.office.dto.response.DispatchFeedRes;
-import com.mobility.api.domain.office.dto.response.DispatchSummaryRes;
-import com.mobility.api.domain.office.dto.response.GetAllDispatchRes;
-import com.mobility.api.domain.office.dto.response.GetDispatchDetailRes;
+import com.mobility.api.domain.office.dto.request.*;
+import com.mobility.api.domain.office.dto.response.*;
 import com.mobility.api.domain.office.entity.Manager;
 import com.mobility.api.domain.office.entity.Office;
+import com.mobility.api.domain.office.repository.OfficeRepository;
 import com.mobility.api.domain.transporter.TransporterStatus;
 import com.mobility.api.domain.transporter.dto.request.TransporterCreateReq;
 import com.mobility.api.domain.transporter.dto.response.TransporterRes;
@@ -43,6 +38,40 @@ public class OfficeService {
     private final DispatchRepository dispatchRepository;
     private final TransporterRepository transporterRepository;
     private final AutoDispatchService autoDispatchService;
+    private final OfficeRepository officeRepository;
+
+    /**
+     * 사무실 정보 조회
+     */
+    @Transactional(readOnly = true)
+    public OfficeProfileRes getOfficeProfile(Manager manager) {
+
+        Long officeId = manager.getOffice().getId(); // 여기의 manager객체는 office의 id만 가지고 있음
+
+        Office office = officeRepository.findById(officeId)
+                .orElseThrow(() -> new GlobalException(ResultCode.NOT_FOUND_OFFICE));
+
+        // 2. DTO 변환
+        return OfficeProfileRes.from(office);
+    }
+
+    /**
+     * 사무실 정보 수정
+     */
+    @Transactional
+    public void updateOfficeProfile(Manager manager, OfficeUpdateReq req) {
+        // 1. 매니저가 가진 프록시 객체에서 ID만 추출 (쿼리 안나감)
+        Long officeId = manager.getOffice().getId();
+
+        // 2. 수정을 위해 진짜 엔티티 조회
+        Office office = officeRepository.findById(officeId)
+                .orElseThrow(() -> new GlobalException(ResultCode.NOT_FOUND_OFFICE));
+
+        // 3. 비즈니스 로직 호출 (변경 감지 활용)
+        office.updateProfile(req);
+
+        // 트랜잭션 종료 시점에 Dirty Checking으로 DB 반영
+    }
 
     public Page findAllDispatch(DispatchSearchDto searchDto, Pageable pageable) {
 
diff --git a/src/main/java/com/mobility/api/global/entity/BaseEntity.java b/src/main/java/com/mobility/api/global/entity/BaseEntity.java
index 7c481c9..cead1b6 100644
--- a/src/main/java/com/mobility/api/global/entity/BaseEntity.java
+++ b/src/main/java/com/mobility/api/global/entity/BaseEntity.java
@@ -19,11 +19,17 @@
 @NoArgsConstructor
 public abstract class BaseEntity {
 
+    // db에 직접 데이터를 넣을 때에도 자동으로 시간이 들어가도록 columnDefinition 설정
     @CreationTimestamp
-    @Column(name = "created_at", updatable = false)
+    @Column(name = "created_at",
+            updatable = false,
+            nullable = false,
+            columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
     private LocalDateTime createdAt;
 
     @UpdateTimestamp
-    @Column(name = "updated_at")
+    @Column(name = "updated_at",
+            nullable = false,
+            columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
     private LocalDateTime updatedAt;
 }
\ No newline at end of file