Merge branch 'dev'
This commit is contained in:
@@ -61,10 +61,10 @@ public class CategoryController {
|
|||||||
return categoryService.reorder(current.getId(), req.getType(), req.getIds());
|
return categoryService.reorder(current.getId(), req.getType(), req.getIds());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 기존 내역의 분류를 목록으로 가져오기 */
|
/** 관리자가 정의한 기본 분류를 내 분류로 불러오기 */
|
||||||
@PostMapping("/import")
|
@PostMapping("/import")
|
||||||
public List<CategoryResponse> importFromEntries(
|
public List<CategoryResponse> importDefaults(
|
||||||
@RequestAttribute(AuthInterceptor.CURRENT_MEMBER) SessionUser current) {
|
@RequestAttribute(AuthInterceptor.CURRENT_MEMBER) SessionUser current) {
|
||||||
return categoryService.importFromEntries(current.getId());
|
return categoryService.importDefaults(current.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.sb.web.account.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기본(디폴트) 분류 — 전체 사용자 공용 템플릿(관리자 관리). 사용자는 자기 분류로 복사해 사용.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DefaultCategory implements Serializable {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String type; // INCOME / EXPENSE
|
||||||
|
private String name;
|
||||||
|
private Long parentId; // 대분류 id (NULL=대분류, 값=소분류)
|
||||||
|
private Integer sortOrder;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
}
|
||||||
@@ -16,6 +16,11 @@ public interface CategoryMapper {
|
|||||||
|
|
||||||
AccountCategory findByIdAndMember(@Param("id") Long id, @Param("memberId") Long memberId);
|
AccountCategory findByIdAndMember(@Param("id") Long id, @Param("memberId") Long memberId);
|
||||||
|
|
||||||
|
/** 이름으로 조회 (기본분류 불러오기 중복 확인용) */
|
||||||
|
AccountCategory findByMemberTypeName(@Param("memberId") Long memberId,
|
||||||
|
@Param("type") String type,
|
||||||
|
@Param("name") String name);
|
||||||
|
|
||||||
/** 해당 대분류(parent_id)에 속한 소분류 개수 */
|
/** 해당 대분류(parent_id)에 속한 소분류 개수 */
|
||||||
int countChildren(@Param("memberId") Long memberId, @Param("parentId") Long parentId);
|
int countChildren(@Param("memberId") Long memberId, @Param("parentId") Long parentId);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.sb.web.account.mapper;
|
||||||
|
|
||||||
|
import com.sb.web.account.domain.DefaultCategory;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기본(디폴트) 분류 매퍼 — 전체 공용(소유자 격리 없음).
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface DefaultCategoryMapper {
|
||||||
|
|
||||||
|
List<DefaultCategory> findAll();
|
||||||
|
|
||||||
|
DefaultCategory findById(@Param("id") Long id);
|
||||||
|
|
||||||
|
int countChildren(@Param("parentId") Long parentId);
|
||||||
|
|
||||||
|
int countByName(@Param("type") String type, @Param("name") String name, @Param("excludeId") Long excludeId);
|
||||||
|
|
||||||
|
int insert(DefaultCategory category);
|
||||||
|
|
||||||
|
int update(DefaultCategory category);
|
||||||
|
|
||||||
|
int delete(@Param("id") Long id);
|
||||||
|
|
||||||
|
int updateSortOrder(@Param("id") Long id, @Param("sortOrder") int sortOrder);
|
||||||
|
|
||||||
|
Integer maxSortOrder(@Param("type") String type);
|
||||||
|
}
|
||||||
@@ -1,21 +1,25 @@
|
|||||||
package com.sb.web.account.service;
|
package com.sb.web.account.service;
|
||||||
|
|
||||||
import com.sb.web.account.domain.AccountCategory;
|
import com.sb.web.account.domain.AccountCategory;
|
||||||
|
import com.sb.web.account.domain.DefaultCategory;
|
||||||
import com.sb.web.account.dto.CategoryRequest;
|
import com.sb.web.account.dto.CategoryRequest;
|
||||||
import com.sb.web.account.dto.CategoryResponse;
|
import com.sb.web.account.dto.CategoryResponse;
|
||||||
import com.sb.web.account.mapper.AccountEntryMapper;
|
import com.sb.web.account.mapper.AccountEntryMapper;
|
||||||
import com.sb.web.account.mapper.BudgetMapper;
|
import com.sb.web.account.mapper.BudgetMapper;
|
||||||
import com.sb.web.account.mapper.CategoryMapper;
|
import com.sb.web.account.mapper.CategoryMapper;
|
||||||
|
import com.sb.web.account.mapper.DefaultCategoryMapper;
|
||||||
import com.sb.web.common.exception.ApiException;
|
import com.sb.web.common.exception.ApiException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 분류(카테고리) 서비스. 사용자별 CRUD, 이름 변경 시 내역·예산 전파, 기존 분류 불러오기.
|
* 분류(카테고리) 서비스. 사용자별 CRUD, 이름 변경 시 내역·예산 전파, 기본분류 불러오기.
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -24,6 +28,7 @@ public class CategoryService {
|
|||||||
private final CategoryMapper categoryMapper;
|
private final CategoryMapper categoryMapper;
|
||||||
private final AccountEntryMapper entryMapper;
|
private final AccountEntryMapper entryMapper;
|
||||||
private final BudgetMapper budgetMapper;
|
private final BudgetMapper budgetMapper;
|
||||||
|
private final DefaultCategoryMapper defaultCategoryMapper;
|
||||||
|
|
||||||
public List<CategoryResponse> list(Long memberId) {
|
public List<CategoryResponse> list(Long memberId) {
|
||||||
return categoryMapper.findByMember(memberId).stream().map(CategoryResponse::from).toList();
|
return categoryMapper.findByMember(memberId).stream().map(CategoryResponse::from).toList();
|
||||||
@@ -114,18 +119,42 @@ public class CategoryService {
|
|||||||
categoryMapper.delete(id, memberId);
|
categoryMapper.delete(id, memberId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 기존 내역에 쓰인 분류명을 분류 목록으로 가져오기 (중복 무시) */
|
/** 관리자가 정의한 기본(디폴트) 분류를 내 분류로 복사 (대/소분류 계층 유지, 같은 이름은 건너뜀) */
|
||||||
@Transactional
|
@Transactional
|
||||||
public List<CategoryResponse> importFromEntries(Long memberId) {
|
public List<CategoryResponse> importDefaults(Long memberId) {
|
||||||
for (String type : new String[]{"INCOME", "EXPENSE"}) {
|
List<DefaultCategory> defaults = defaultCategoryMapper.findAll();
|
||||||
for (String name : entryMapper.findDistinctCategories(memberId, type)) {
|
// 1) 대분류 먼저 생성/확보 → default.id → 내 분류.id 매핑
|
||||||
categoryMapper.insertIgnore(AccountCategory.builder()
|
Map<Long, Long> majorMap = new HashMap<>();
|
||||||
.memberId(memberId).type(type).name(name).sortOrder(0).build());
|
for (DefaultCategory d : defaults) {
|
||||||
|
if (d.getParentId() != null) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
majorMap.put(d.getId(), ensureCategory(memberId, d.getType(), d.getName(), null));
|
||||||
|
}
|
||||||
|
// 2) 소분류 생성 (매핑된 대분류 아래; 부모 매핑이 없으면 대분류로 취급)
|
||||||
|
for (DefaultCategory d : defaults) {
|
||||||
|
if (d.getParentId() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ensureCategory(memberId, d.getType(), d.getName(), majorMap.get(d.getParentId()));
|
||||||
}
|
}
|
||||||
return list(memberId);
|
return list(memberId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 같은 이름 분류가 있으면 그 id, 없으면 생성해서 id 반환 */
|
||||||
|
private Long ensureCategory(Long memberId, String type, String name, Long parentId) {
|
||||||
|
AccountCategory existing = categoryMapper.findByMemberTypeName(memberId, type, name);
|
||||||
|
if (existing != null) {
|
||||||
|
return existing.getId();
|
||||||
|
}
|
||||||
|
Integer max = categoryMapper.maxSortOrder(memberId, type);
|
||||||
|
AccountCategory c = AccountCategory.builder()
|
||||||
|
.memberId(memberId).type(type).name(name).parentId(parentId)
|
||||||
|
.sortOrder(max == null ? 0 : max + 1).build();
|
||||||
|
categoryMapper.insert(c);
|
||||||
|
return c.getId();
|
||||||
|
}
|
||||||
|
|
||||||
private AccountCategory mustFind(Long id, Long memberId) {
|
private AccountCategory mustFind(Long id, Long memberId) {
|
||||||
AccountCategory c = categoryMapper.findByIdAndMember(id, memberId);
|
AccountCategory c = categoryMapper.findByIdAndMember(id, memberId);
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package com.sb.web.account.service;
|
||||||
|
|
||||||
|
import com.sb.web.account.domain.DefaultCategory;
|
||||||
|
import com.sb.web.account.dto.CategoryReorderRequest;
|
||||||
|
import com.sb.web.account.dto.CategoryRequest;
|
||||||
|
import com.sb.web.account.dto.CategoryResponse;
|
||||||
|
import com.sb.web.account.mapper.DefaultCategoryMapper;
|
||||||
|
import com.sb.web.common.exception.ApiException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기본(디폴트) 분류 서비스 — 전체 공용 템플릿(관리자 전용 CRUD). 2단계(대/소분류) 제한.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DefaultCategoryService {
|
||||||
|
|
||||||
|
private final DefaultCategoryMapper mapper;
|
||||||
|
|
||||||
|
public List<CategoryResponse> list() {
|
||||||
|
return mapper.findAll().stream().map(this::toResponse).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public CategoryResponse create(CategoryRequest req) {
|
||||||
|
String name = req.getName().trim();
|
||||||
|
if (mapper.countByName(req.getType(), name, null) > 0) {
|
||||||
|
throw new ApiException(HttpStatus.CONFLICT, "이미 존재하는 분류입니다.");
|
||||||
|
}
|
||||||
|
validateParent(req.getParentId(), req.getType());
|
||||||
|
Integer max = mapper.maxSortOrder(req.getType());
|
||||||
|
DefaultCategory c = DefaultCategory.builder()
|
||||||
|
.type(req.getType()).name(name).parentId(req.getParentId())
|
||||||
|
.sortOrder(max == null ? 0 : max + 1).build();
|
||||||
|
mapper.insert(c);
|
||||||
|
return toResponse(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public CategoryResponse update(Long id, CategoryRequest req) {
|
||||||
|
DefaultCategory c = mustFind(id);
|
||||||
|
String newName = req.getName().trim();
|
||||||
|
if (mapper.countByName(c.getType(), newName, id) > 0) {
|
||||||
|
throw new ApiException(HttpStatus.CONFLICT, "이미 존재하는 분류입니다.");
|
||||||
|
}
|
||||||
|
Long newParent = req.getParentId();
|
||||||
|
if (newParent != null) {
|
||||||
|
if (newParent.equals(id)) {
|
||||||
|
throw new ApiException(HttpStatus.BAD_REQUEST, "자기 자신을 대분류로 지정할 수 없습니다.");
|
||||||
|
}
|
||||||
|
if (mapper.countChildren(id) > 0) {
|
||||||
|
throw new ApiException(HttpStatus.BAD_REQUEST, "소분류가 있는 대분류는 소분류로 바꿀 수 없습니다.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validateParent(newParent, c.getType());
|
||||||
|
c.setName(newName);
|
||||||
|
c.setParentId(newParent);
|
||||||
|
mapper.update(c);
|
||||||
|
return toResponse(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void delete(Long id) {
|
||||||
|
mustFind(id);
|
||||||
|
if (mapper.countChildren(id) > 0) {
|
||||||
|
throw new ApiException(HttpStatus.BAD_REQUEST, "소분류가 있는 대분류는 삭제할 수 없습니다. 소분류를 먼저 옮기거나 삭제하세요.");
|
||||||
|
}
|
||||||
|
mapper.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<CategoryResponse> reorder(CategoryReorderRequest req) {
|
||||||
|
int i = 0;
|
||||||
|
for (Long id : req.getIds()) {
|
||||||
|
DefaultCategory c = mapper.findById(id);
|
||||||
|
if (c != null && c.getType().equals(req.getType())) {
|
||||||
|
mapper.updateSortOrder(id, i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateParent(Long parentId, String type) {
|
||||||
|
if (parentId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DefaultCategory parent = mapper.findById(parentId);
|
||||||
|
if (parent == null || !parent.getType().equals(type)) {
|
||||||
|
throw new ApiException(HttpStatus.BAD_REQUEST, "대분류가 올바르지 않습니다.");
|
||||||
|
}
|
||||||
|
if (parent.getParentId() != null) {
|
||||||
|
throw new ApiException(HttpStatus.BAD_REQUEST, "대분류 아래에만 소분류를 둘 수 있습니다(2단계).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefaultCategory mustFind(Long id) {
|
||||||
|
DefaultCategory c = mapper.findById(id);
|
||||||
|
if (c == null) {
|
||||||
|
throw new ApiException(HttpStatus.NOT_FOUND, "기본 분류를 찾을 수 없습니다.");
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CategoryResponse toResponse(DefaultCategory c) {
|
||||||
|
return CategoryResponse.builder()
|
||||||
|
.id(c.getId()).type(c.getType()).name(c.getName()).parentId(c.getParentId())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.sb.web.admin.controller;
|
||||||
|
|
||||||
|
import com.sb.web.account.dto.CategoryReorderRequest;
|
||||||
|
import com.sb.web.account.dto.CategoryRequest;
|
||||||
|
import com.sb.web.account.dto.CategoryResponse;
|
||||||
|
import com.sb.web.account.service.DefaultCategoryService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 관리자 기본(디폴트) 분류 관리 API. (/api/admin/** — AdminInterceptor 로 ADMIN 권한 필요)
|
||||||
|
* GET /default-categories 기본 분류 목록
|
||||||
|
* POST /default-categories 생성(대/소분류)
|
||||||
|
* PUT /default-categories/{id} 수정(이름·대분류)
|
||||||
|
* DELETE /default-categories/{id} 삭제
|
||||||
|
* PUT /default-categories/reorder 순서 변경
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/admin/default-categories")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AdminCategoryController {
|
||||||
|
|
||||||
|
private final DefaultCategoryService service;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<CategoryResponse> list() {
|
||||||
|
return service.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<CategoryResponse> create(@Valid @RequestBody CategoryRequest req) {
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).body(service.create(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public CategoryResponse update(@PathVariable Long id, @Valid @RequestBody CategoryRequest req) {
|
||||||
|
return service.update(id, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ResponseEntity<Void> delete(@PathVariable Long id) {
|
||||||
|
service.delete(id);
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/reorder")
|
||||||
|
public List<CategoryResponse> reorder(@RequestBody CategoryReorderRequest req) {
|
||||||
|
return service.reorder(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -114,6 +114,18 @@ CREATE TABLE IF NOT EXISTS account_category (
|
|||||||
-- 대/소분류 계층 추가(기존 DB 마이그레이션) — 소분류 이름은 그대로, parent_id 만 부여
|
-- 대/소분류 계층 추가(기존 DB 마이그레이션) — 소분류 이름은 그대로, parent_id 만 부여
|
||||||
ALTER TABLE account_category ADD COLUMN IF NOT EXISTS parent_id BIGINT NULL COMMENT '대분류 id. NULL=대분류, 값=소분류';
|
ALTER TABLE account_category ADD COLUMN IF NOT EXISTS parent_id BIGINT NULL COMMENT '대분류 id. NULL=대분류, 값=소분류';
|
||||||
|
|
||||||
|
-- 기본(디폴트) 분류 — 전체 사용자 공용 템플릿(관리자 관리). 사용자가 '기본 분류 불러오기'로 자기 분류에 복사.
|
||||||
|
CREATE TABLE IF NOT EXISTS default_category (
|
||||||
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
type VARCHAR(10) NOT NULL COMMENT 'INCOME / EXPENSE',
|
||||||
|
name VARCHAR(50) NOT NULL,
|
||||||
|
parent_id BIGINT NULL COMMENT '대분류 id(default_category.id). NULL=대분류, 값=소분류',
|
||||||
|
sort_order INT NOT NULL DEFAULT 0,
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY uk_default_category_type_name (type, name)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- 예산 (사용자별, 카테고리별)
|
-- 예산 (사용자별, 카테고리별)
|
||||||
-- fixed=1(고정): base_unit/base_amount 로 일수기준 환산 / fixed=0(비고정): daily/weekly/monthly/yearly 직접
|
-- fixed=1(고정): base_unit/base_amount 로 일수기준 환산 / fixed=0(비고정): daily/weekly/monthly/yearly 직접
|
||||||
CREATE TABLE IF NOT EXISTS budget (
|
CREATE TABLE IF NOT EXISTS budget (
|
||||||
|
|||||||
@@ -31,6 +31,13 @@
|
|||||||
WHERE member_id = #{memberId} AND parent_id = #{parentId}
|
WHERE member_id = #{memberId} AND parent_id = #{parentId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="findByMemberTypeName" resultMap="categoryResultMap">
|
||||||
|
SELECT id, member_id, type, name, parent_id, sort_order, created_at
|
||||||
|
FROM account_category
|
||||||
|
WHERE member_id = #{memberId} AND type = #{type} AND name = #{name}
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="countByName" resultType="int">
|
<select id="countByName" resultType="int">
|
||||||
SELECT COUNT(*) FROM account_category
|
SELECT COUNT(*) FROM account_category
|
||||||
WHERE member_id = #{memberId} AND type = #{type} AND name = #{name}
|
WHERE member_id = #{memberId} AND type = #{type} AND name = #{name}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.sb.web.account.mapper.DefaultCategoryMapper">
|
||||||
|
|
||||||
|
<resultMap id="defaultCategoryResultMap" type="com.sb.web.account.domain.DefaultCategory">
|
||||||
|
<id property="id" column="id"/>
|
||||||
|
<result property="type" column="type"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
<result property="parentId" column="parent_id"/>
|
||||||
|
<result property="sortOrder" column="sort_order"/>
|
||||||
|
<result property="createdAt" column="created_at"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="findAll" resultMap="defaultCategoryResultMap">
|
||||||
|
SELECT id, type, name, parent_id, sort_order, created_at
|
||||||
|
FROM default_category
|
||||||
|
ORDER BY type, sort_order, name
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="findById" resultMap="defaultCategoryResultMap">
|
||||||
|
SELECT id, type, name, parent_id, sort_order, created_at
|
||||||
|
FROM default_category
|
||||||
|
WHERE id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countChildren" resultType="int">
|
||||||
|
SELECT COUNT(*) FROM default_category WHERE parent_id = #{parentId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countByName" resultType="int">
|
||||||
|
SELECT COUNT(*) FROM default_category
|
||||||
|
WHERE type = #{type} AND name = #{name}
|
||||||
|
<if test="excludeId != null">AND id != #{excludeId}</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="com.sb.web.account.domain.DefaultCategory"
|
||||||
|
useGeneratedKeys="true" keyProperty="id">
|
||||||
|
INSERT INTO default_category (type, name, parent_id, sort_order, created_at)
|
||||||
|
VALUES (#{type}, #{name}, #{parentId}, #{sortOrder}, NOW())
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="update" parameterType="com.sb.web.account.domain.DefaultCategory">
|
||||||
|
UPDATE default_category SET name = #{name}, parent_id = #{parentId}
|
||||||
|
WHERE id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="delete">
|
||||||
|
DELETE FROM default_category WHERE id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<update id="updateSortOrder">
|
||||||
|
UPDATE default_category SET sort_order = #{sortOrder} WHERE id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<select id="maxSortOrder" resultType="java.lang.Integer">
|
||||||
|
SELECT MAX(sort_order) FROM default_category WHERE type = #{type}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user