684 lines
32 KiB
Java
684 lines
32 KiB
Java
package com.bizcare.agent;
|
|
|
|
import jakarta.persistence.EntityManager;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.ZoneId;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* 영업점관리 — billing_react BranchController / BranchGroupController / BranchFee entries 이식.
|
|
*/
|
|
@RestController
|
|
@RequestMapping("/api/agent/homes")
|
|
@RequiredArgsConstructor
|
|
class CareBranchController {
|
|
private static final ZoneId KST = ZoneId.of("Asia/Seoul");
|
|
private static final DateTimeFormatter DT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
private final EntityManager em;
|
|
private final PasswordEncoder encoder;
|
|
|
|
// ---- 영업점 그룹 ----
|
|
|
|
@GetMapping("/branch-groups")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse branchGroups(@AuthenticationPrincipal JwtUser u) {
|
|
List<HomesBranchGroup> list = em.createQuery(
|
|
"select g from HomesBranchGroup g where g.groupId=:gid order by g.seq asc, g.id asc",
|
|
HomesBranchGroup.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.getResultList();
|
|
return ApiResponse.ok(list.stream().map(this::groupMap).toList());
|
|
}
|
|
|
|
@PostMapping("/branch-groups")
|
|
@Transactional
|
|
ApiResponse createBranchGroup(@RequestBody Map<String, Object> body, @AuthenticationPrincipal JwtUser u) {
|
|
String name = str(body.get("name"));
|
|
if (blank(name)) return ApiResponse.fail("그룹명을 입력하세요.");
|
|
HomesBranchGroup g = new HomesBranchGroup();
|
|
g.setGroupId(u.getGroupId());
|
|
g.setName(name.trim());
|
|
g.setSeq(body.get("seq") instanceof Number n ? n.intValue() : 0);
|
|
em.persist(g);
|
|
return ApiResponse.ok(groupMap(g));
|
|
}
|
|
|
|
// ---- 영업점 목록 / CRUD ----
|
|
|
|
@GetMapping("/branches")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse branches(@AuthenticationPrincipal JwtUser u) {
|
|
List<HomesBranch> list = em.createQuery(
|
|
"select b from HomesBranch b where b.groupId=:gid order by b.id desc",
|
|
HomesBranch.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.getResultList();
|
|
Map<Long, String> groupNames = groupNameMap(u.getGroupId());
|
|
return ApiResponse.ok(list.stream().map(b -> listMap(b, groupNames)).toList());
|
|
}
|
|
|
|
@PostMapping("/branches")
|
|
@Transactional
|
|
ApiResponse createBranch(@RequestBody Map<String, Object> body,
|
|
@RequestParam(defaultValue = "1") int level,
|
|
@RequestParam(required = false) Long branchGroupId,
|
|
@AuthenticationPrincipal JwtUser u) {
|
|
String userid = str(body.get("userid"));
|
|
String password = str(body.get("password"));
|
|
String officeName = str(body.get("officeName"));
|
|
String name = str(body.get("name"));
|
|
String phone = str(body.get("phone"));
|
|
String email = str(body.get("email"));
|
|
if (blank(userid) || blank(password)) return ApiResponse.fail("아이디와 패스워드를 입력하세요.");
|
|
if (blank(officeName) || blank(name)) return ApiResponse.fail("영업점명과 대표자명을 입력하세요.");
|
|
if (blank(phone) || blank(email)) return ApiResponse.fail("휴대폰과 이메일을 입력하세요.");
|
|
if (existsUserid(u.getGroupId(), userid, null)) return ApiResponse.fail("다른사람이 사용중인 아이디입니다.");
|
|
if (existsOfficeName(u.getGroupId(), officeName, null)) return ApiResponse.fail("다른사람이 사용중인 영업점명입니다.");
|
|
if (existsEmail(u.getGroupId(), email, null)) return ApiResponse.fail("다른 사람이 사용중인 이메일입니다.");
|
|
|
|
HomesBranch b = new HomesBranch();
|
|
b.setGroupId(u.getGroupId());
|
|
b.setUserid(userid.trim());
|
|
b.setPasswordHash(encoder.encode(password));
|
|
b.setName(name.trim());
|
|
b.setOfficeName(officeName.trim());
|
|
b.setTel(str(body.get("tel")));
|
|
b.setPhone(phone.trim());
|
|
b.setFax(str(body.get("fax")));
|
|
b.setEmail(email.trim());
|
|
b.setZipcode(str(body.get("zipcode")));
|
|
b.setAddress(str(body.get("address")));
|
|
b.setAddressDetail(str(body.get("addressDetail")));
|
|
b.setSido(deriveSido(str(body.get("zipcode")), str(body.get("sido")), str(body.get("address"))));
|
|
b.setLevel(level);
|
|
b.setGrantFlag(1); // 관리자 등록 시 승인
|
|
b.setBranchGroupId(branchGroupId != null ? branchGroupId : longOrNull(body.get("branchGroupId")));
|
|
b.setIsTax(body.get("isTax") instanceof Number n ? n.intValue() : 1);
|
|
b.setMemo(str(body.get("memo")));
|
|
em.persist(b);
|
|
return ApiResponse.ok(listMap(b, groupNameMap(u.getGroupId())));
|
|
}
|
|
|
|
@GetMapping("/branches/{id}/detail")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse branchDetail(@PathVariable Long id, @AuthenticationPrincipal JwtUser u) {
|
|
HomesBranch b = findBranch(id, u);
|
|
if (b == null) return ApiResponse.fail("영업점을 찾을 수 없습니다.");
|
|
return ApiResponse.ok(detailMap(b));
|
|
}
|
|
|
|
@PutMapping("/branches/{id}/detail")
|
|
@Transactional
|
|
ApiResponse updateBranchDetail(@PathVariable Long id, @RequestBody Map<String, Object> body,
|
|
@AuthenticationPrincipal JwtUser u) {
|
|
HomesBranch b = findBranch(id, u);
|
|
if (b == null) return ApiResponse.fail("영업점을 찾을 수 없습니다.");
|
|
|
|
String officeName = str(body.get("officeName"));
|
|
String email = str(body.get("email"));
|
|
String name = str(body.get("name"));
|
|
if (blank(officeName) || blank(name)) return ApiResponse.fail("영업점명과 이름을 입력하세요.");
|
|
if (existsOfficeName(u.getGroupId(), officeName, id)) return ApiResponse.fail("다른사람이 사용중인 영업점명입니다.");
|
|
if (!blank(email) && existsEmail(u.getGroupId(), email, id)) return ApiResponse.fail("다른 사람이 사용중인 이메일입니다.");
|
|
|
|
String password = str(body.get("password"));
|
|
String passwordConfirmation = str(body.get("passwordConfirmation"));
|
|
if (!blank(password)) {
|
|
if (!password.equals(passwordConfirmation)) return ApiResponse.fail("패스워드 확인이 일치하지 않습니다.");
|
|
b.setPasswordHash(encoder.encode(password));
|
|
}
|
|
|
|
Long oldGroupId = b.getBranchGroupId();
|
|
Long newGroupId = longOrNull(body.get("branchGroupId"));
|
|
boolean keepFee = Boolean.TRUE.equals(body.get("keepFee"))
|
|
|| "true".equalsIgnoreCase(String.valueOf(body.get("keepFee")));
|
|
|
|
b.setName(name.trim());
|
|
b.setOfficeName(officeName.trim());
|
|
b.setTel(str(body.get("tel")));
|
|
b.setPhone(str(body.get("phone")));
|
|
b.setFax(str(body.get("fax")));
|
|
b.setEmail(email);
|
|
b.setZipcode(str(body.get("zipcode")));
|
|
b.setAddress(str(body.get("address")));
|
|
b.setAddressDetail(str(body.get("addressDetail")));
|
|
b.setSido(deriveSido(str(body.get("zipcode")), str(body.get("sido")), str(body.get("address"))));
|
|
if (body.get("level") instanceof Number n) b.setLevel(n.intValue());
|
|
b.setBranchGroupId(newGroupId);
|
|
b.setCenterName(str(body.get("centerName")));
|
|
if (blank(b.getCenterName()) && body.get("centerId") != null) {
|
|
// centerId 호환: 숫자면 무시, 문자열이면 이름
|
|
b.setCenterName(str(body.get("centerId")));
|
|
}
|
|
|
|
boolean isPersonal = Boolean.TRUE.equals(body.get("isPersonal"))
|
|
|| "true".equalsIgnoreCase(String.valueOf(body.get("isPersonal")));
|
|
b.setHasBusinessLicense(!isPersonal);
|
|
b.setLicenseNumber(isPersonal ? null : str(body.get("licenseNumber")));
|
|
b.setLicenseType(isPersonal ? null : str(body.get("licenseType")));
|
|
b.setLicenseItem(isPersonal ? null : str(body.get("licenseItem")));
|
|
|
|
b.setAccountBank(str(body.get("accountBank")));
|
|
b.setAccountNumber(str(body.get("accountNumber")));
|
|
boolean accountNameIsName = Boolean.TRUE.equals(body.get("accountNameIsName"))
|
|
|| "true".equalsIgnoreCase(String.valueOf(body.get("accountNameIsName")));
|
|
b.setAccountName(accountNameIsName ? b.getName() : str(body.get("accountName")));
|
|
|
|
b.setContactPhone(str(body.get("contactPhone")));
|
|
b.setContactNateon(str(body.get("contactNateon")));
|
|
if (body.get("acceptPhone") instanceof Number n) b.setAcceptPhone(n.intValue());
|
|
if (body.get("acceptNateon") instanceof Number n) b.setAcceptNateon(n.intValue());
|
|
if (body.get("isTax") instanceof Number n) b.setIsTax(n.intValue());
|
|
b.setMemo(str(body.get("memo")));
|
|
b.setAdminMemo(str(body.get("adminMemo")));
|
|
b.setNotifyPhonesJson(toNotifyJson(body.get("notifyPhones")));
|
|
|
|
b.setPermissionOrderDateUpdate(bool(body.get("permissionOrderDateUpdate")));
|
|
b.setPermissionCalculate(bool(body.get("permissionCalculate")));
|
|
b.setPermissionConfig(bool(body.get("permissionConfig")));
|
|
b.setPermissionExcelDownload(bool(body.get("permissionExcelDownload")));
|
|
b.setPermissionChart(bool(body.get("permissionChart")));
|
|
|
|
// keepFee=false 이고 그룹이 바뀌면 개별 수수료는 유지, 그룹 매핑은 이름만 바뀌므로 별도 처리 없음
|
|
if (!keepFee && !Objects.equals(oldGroupId, newGroupId) && newGroupId != null) {
|
|
HomesBranchGroup ng = em.find(HomesBranchGroup.class, newGroupId);
|
|
if (ng != null && Objects.equals(ng.getGroupId(), u.getGroupId())) {
|
|
// 그룹 수수료는 branchGroupName 문자열 키 — 접수의 branchGroup 과 맞추는 용도만
|
|
// (실제 접수 일괄 갱신은 범위 외)
|
|
}
|
|
}
|
|
|
|
return ApiResponse.ok(detailMap(b));
|
|
}
|
|
|
|
@PostMapping("/branches/{id}/grant/{grant}")
|
|
@Transactional
|
|
ApiResponse setGrant(@PathVariable Long id, @PathVariable int grant, @AuthenticationPrincipal JwtUser u) {
|
|
HomesBranch b = findBranch(id, u);
|
|
if (b == null) return ApiResponse.fail("영업점을 찾을 수 없습니다.");
|
|
if (grant != 0 && grant != 1) return ApiResponse.fail("승인값은 0 또는 1이어야 합니다.");
|
|
b.setGrantFlag(grant);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
|
|
@DeleteMapping("/branches/{id}")
|
|
@Transactional
|
|
ApiResponse deleteBranch(@PathVariable Long id, @AuthenticationPrincipal JwtUser u) {
|
|
HomesBranch b = findBranch(id, u);
|
|
if (b == null) return ApiResponse.fail("영업점을 찾을 수 없습니다.");
|
|
em.remove(b);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
|
|
/** 영업점 수수료 목록 (개별 + 소속 그룹) — billing GET /branch-fee/branch/{id}/entries */
|
|
@GetMapping("/branches/{id}/fees")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse branchFees(@PathVariable Long id, @AuthenticationPrincipal JwtUser u) {
|
|
HomesBranch b = findBranch(id, u);
|
|
if (b == null) return ApiResponse.fail("영업점을 찾을 수 없습니다.");
|
|
|
|
List<Map<String, Object>> entries = new ArrayList<>();
|
|
List<HomesBranchFee> alone = em.createQuery(
|
|
"select f from HomesBranchFee f where f.groupId=:gid and f.feeType='alone' and f.branchName=:name",
|
|
HomesBranchFee.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.setParameter("name", b.getOfficeName())
|
|
.getResultList();
|
|
for (HomesBranchFee f : alone) {
|
|
entries.add(feeEntryMap(f, "alone"));
|
|
}
|
|
|
|
if (b.getBranchGroupId() != null) {
|
|
HomesBranchGroup g = em.find(HomesBranchGroup.class, b.getBranchGroupId());
|
|
if (g != null && Objects.equals(g.getGroupId(), u.getGroupId())) {
|
|
List<HomesBranchFee> groupFees = em.createQuery(
|
|
"select f from HomesBranchFee f where f.groupId=:gid and f.feeType='group' and f.branchGroupName=:name",
|
|
HomesBranchFee.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.setParameter("name", g.getName())
|
|
.getResultList();
|
|
for (HomesBranchFee f : groupFees) {
|
|
entries.add(feeEntryMap(f, "group"));
|
|
}
|
|
}
|
|
}
|
|
// 적용일 내림차순, 동일일이면 개별(alone) 우선
|
|
entries.sort((a, b2) -> {
|
|
String sa = String.valueOf(a.get("startDate") == null ? "" : a.get("startDate"));
|
|
String sb = String.valueOf(b2.get("startDate") == null ? "" : b2.get("startDate"));
|
|
int c = sb.compareTo(sa);
|
|
if (c != 0) return c;
|
|
int pa = "alone".equals(a.get("type")) ? 0 : 1;
|
|
int pb = "alone".equals(b2.get("type")) ? 0 : 1;
|
|
return Integer.compare(pa, pb);
|
|
});
|
|
return ApiResponse.ok(entries);
|
|
}
|
|
|
|
/** 수수료 상세 — billing branch-fee/{id}/read/{type} */
|
|
@GetMapping("/branch-fees/{feeId}")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse feeDetail(@PathVariable Long feeId,
|
|
@RequestParam(defaultValue = "alone") String type,
|
|
@AuthenticationPrincipal JwtUser u) {
|
|
HomesBranchFee f = em.find(HomesBranchFee.class, feeId);
|
|
if (f == null || !Objects.equals(f.getGroupId(), u.getGroupId())) {
|
|
return ApiResponse.fail("수수료를 찾을 수 없습니다.");
|
|
}
|
|
String want = "group".equalsIgnoreCase(type) ? "group" : "alone";
|
|
if (!want.equals(f.getFeeType())) {
|
|
return ApiResponse.fail("수수료 종류가 일치하지 않습니다.");
|
|
}
|
|
return ApiResponse.ok(feeDetailMap(f));
|
|
}
|
|
|
|
/** 개별 수수료 등록 */
|
|
@PostMapping("/branches/{id}/fees")
|
|
@Transactional
|
|
ApiResponse createAloneFee(@PathVariable Long id, @RequestBody Map<String, Object> body,
|
|
@AuthenticationPrincipal JwtUser u) {
|
|
HomesBranch b = findBranch(id, u);
|
|
if (b == null) return ApiResponse.fail("영업점을 찾을 수 없습니다.");
|
|
String carrier = str(body.get("carrier"));
|
|
if (blank(carrier)) return ApiResponse.fail("통신사를 선택하세요.");
|
|
LocalDateTime start = parseDateTime(body.get("startDate"));
|
|
if (start == null) return ApiResponse.fail("적용일을 입력하세요.");
|
|
if (existsAloneFee(u.getGroupId(), b.getOfficeName(), carrier, start, null)) {
|
|
return ApiResponse.fail("이미 등록되어 있는 적용일입니다.");
|
|
}
|
|
HomesBranchFee fee = new HomesBranchFee();
|
|
fee.setGroupId(u.getGroupId());
|
|
fee.setFeeType("alone");
|
|
fee.setBranchName(b.getOfficeName());
|
|
if (b.getBranchGroupId() != null) {
|
|
HomesBranchGroup g = em.find(HomesBranchGroup.class, b.getBranchGroupId());
|
|
if (g != null) fee.setBranchGroupName(g.getName());
|
|
}
|
|
fee.setCarrier(carrier);
|
|
fee.setStartDate(start);
|
|
fee.setMemo(str(body.get("memo")));
|
|
em.persist(fee);
|
|
em.flush();
|
|
replaceProducts(fee.getId(), u.getGroupId(), body.get("products"));
|
|
return ApiResponse.ok(feeDetailMap(fee));
|
|
}
|
|
|
|
/** 개별 수수료 수정 — 그룹은 거부 */
|
|
@PutMapping("/branch-fees/{feeId}")
|
|
@Transactional
|
|
ApiResponse updateAloneFee(@PathVariable Long feeId, @RequestBody Map<String, Object> body,
|
|
@AuthenticationPrincipal JwtUser u) {
|
|
HomesBranchFee f = em.find(HomesBranchFee.class, feeId);
|
|
if (f == null || !Objects.equals(f.getGroupId(), u.getGroupId())) {
|
|
return ApiResponse.fail("수수료를 찾을 수 없습니다.");
|
|
}
|
|
if (!"alone".equals(f.getFeeType())) {
|
|
return ApiResponse.fail("그룹 수수료는 여기서 수정할 수 없습니다.");
|
|
}
|
|
LocalDateTime start = parseDateTime(body.get("startDate"));
|
|
if (start == null) return ApiResponse.fail("적용일을 입력하세요.");
|
|
String carrier = blank(str(body.get("carrier"))) ? f.getCarrier() : str(body.get("carrier"));
|
|
if (existsAloneFee(u.getGroupId(), f.getBranchName(), carrier, start, feeId)) {
|
|
return ApiResponse.fail("이미 등록되어 있는 적용일입니다.");
|
|
}
|
|
f.setCarrier(carrier);
|
|
f.setStartDate(start);
|
|
f.setMemo(str(body.get("memo")));
|
|
if (body.containsKey("file1")) f.setFile1(str(body.get("file1")));
|
|
if (body.containsKey("file2")) f.setFile2(str(body.get("file2")));
|
|
if (body.containsKey("file3")) f.setFile3(str(body.get("file3")));
|
|
if (body.containsKey("file4")) f.setFile4(str(body.get("file4")));
|
|
if (body.containsKey("file5")) f.setFile5(str(body.get("file5")));
|
|
replaceProducts(feeId, u.getGroupId(), body.get("products"));
|
|
return ApiResponse.ok(feeDetailMap(f));
|
|
}
|
|
|
|
@DeleteMapping("/branch-fees/{feeId}")
|
|
@Transactional
|
|
ApiResponse deleteAloneFee(@PathVariable Long feeId, @AuthenticationPrincipal JwtUser u) {
|
|
HomesBranchFee f = em.find(HomesBranchFee.class, feeId);
|
|
if (f == null || !Objects.equals(f.getGroupId(), u.getGroupId())) {
|
|
return ApiResponse.fail("수수료를 찾을 수 없습니다.");
|
|
}
|
|
if (!"alone".equals(f.getFeeType())) {
|
|
return ApiResponse.fail("그룹 수수료는 여기서 삭제할 수 없습니다.");
|
|
}
|
|
em.createQuery("delete from HomesBranchFeeProduct p where p.feeId=:fid and p.groupId=:gid")
|
|
.setParameter("fid", feeId)
|
|
.setParameter("gid", u.getGroupId())
|
|
.executeUpdate();
|
|
em.remove(f);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
|
|
/** 등록 폼용 기본 상품 템플릿 (시드/기존 수수료 상품명 재사용) */
|
|
@GetMapping("/branch-fee-product-templates")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse productTemplates(@RequestParam(required = false) String carrier,
|
|
@AuthenticationPrincipal JwtUser u) {
|
|
List<HomesBranchFeeProduct> samples = em.createQuery(
|
|
"select p from HomesBranchFeeProduct p where p.groupId=:gid order by p.id asc",
|
|
HomesBranchFeeProduct.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.setMaxResults(40)
|
|
.getResultList();
|
|
LinkedHashMap<String, Map<String, Object>> uniq = new LinkedHashMap<>();
|
|
for (HomesBranchFeeProduct p : samples) {
|
|
String key = p.getProductType() + "|" + p.getProductName();
|
|
if (uniq.containsKey(key)) continue;
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("productType", p.getProductType());
|
|
m.put("productName", p.getProductName());
|
|
m.put("fee", 0);
|
|
uniq.put(key, m);
|
|
}
|
|
if (uniq.isEmpty()) {
|
|
Object[][] defaults = {
|
|
{"e01", "기가인터넷 1G"}, {"e01", "안심 인터넷"},
|
|
{"e03", "B tv 프리미엄"}, {"e02", "집전화 스마트"}, {"e04", "기타"},
|
|
};
|
|
for (Object[] d : defaults) {
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("productType", d[0]);
|
|
m.put("productName", d[1]);
|
|
m.put("fee", 0);
|
|
uniq.put(d[0] + "|" + d[1], m);
|
|
}
|
|
}
|
|
return ApiResponse.ok(new ArrayList<>(uniq.values()));
|
|
}
|
|
|
|
/** 입력처(센터) 후보 — 레벨5 영업점 + 접수 processor distinct */
|
|
@GetMapping("/branch-centers")
|
|
@Transactional(readOnly = true)
|
|
ApiResponse centers(@AuthenticationPrincipal JwtUser u) {
|
|
LinkedHashSet<String> names = new LinkedHashSet<>();
|
|
em.createQuery(
|
|
"select b.officeName from HomesBranch b where b.groupId=:gid and b.level=5 and b.officeName is not null",
|
|
String.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.getResultList()
|
|
.forEach(names::add);
|
|
em.createQuery(
|
|
"select distinct r.processor from HomesReception r where r.groupId=:gid and r.processor is not null and r.processor<>''",
|
|
String.class)
|
|
.setParameter("gid", u.getGroupId())
|
|
.getResultList()
|
|
.forEach(names::add);
|
|
List<Map<String, Object>> out = new ArrayList<>();
|
|
int i = 1;
|
|
for (String n : names) {
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("id", i++);
|
|
m.put("name", n);
|
|
out.add(m);
|
|
}
|
|
return ApiResponse.ok(out);
|
|
}
|
|
|
|
// ---- helpers ----
|
|
|
|
private void replaceProducts(Long feeId, String groupId, Object productsRaw) {
|
|
em.createQuery("delete from HomesBranchFeeProduct p where p.feeId=:fid and p.groupId=:gid")
|
|
.setParameter("fid", feeId)
|
|
.setParameter("gid", groupId)
|
|
.executeUpdate();
|
|
if (!(productsRaw instanceof List<?> list)) return;
|
|
for (Object o : list) {
|
|
if (!(o instanceof Map<?, ?> m)) continue;
|
|
String productType = str(m.get("productType"));
|
|
String productName = str(m.get("productName"));
|
|
if (blank(productName)) continue;
|
|
HomesBranchFeeProduct p = new HomesBranchFeeProduct();
|
|
p.setGroupId(groupId);
|
|
p.setFeeId(feeId);
|
|
p.setProductType(blank(productType) ? "e01" : productType);
|
|
p.setProductName(productName);
|
|
Object feeObj = m.get("fee");
|
|
int fee = feeObj instanceof Number n ? n.intValue() : 0;
|
|
try {
|
|
if (!(feeObj instanceof Number) && feeObj != null && !String.valueOf(feeObj).isBlank()) {
|
|
fee = Integer.parseInt(String.valueOf(feeObj).replace(",", "").replace("원", "").trim());
|
|
}
|
|
} catch (Exception ignored) { /* keep 0 */ }
|
|
p.setFee(fee);
|
|
em.persist(p);
|
|
}
|
|
}
|
|
|
|
private boolean existsAloneFee(String gid, String branchName, String carrier, LocalDateTime start, Long excludeId) {
|
|
String jpql = "select count(f) from HomesBranchFee f where f.groupId=:gid and f.feeType='alone'"
|
|
+ " and f.branchName=:name and f.carrier=:c and f.startDate=:sd"
|
|
+ (excludeId != null ? " and f.id<>:id" : "");
|
|
var q = em.createQuery(jpql, Long.class)
|
|
.setParameter("gid", gid)
|
|
.setParameter("name", branchName)
|
|
.setParameter("c", carrier)
|
|
.setParameter("sd", start);
|
|
if (excludeId != null) q.setParameter("id", excludeId);
|
|
return q.getSingleResult() > 0;
|
|
}
|
|
|
|
private Map<String, Object> feeDetailMap(HomesBranchFee f) {
|
|
List<HomesBranchFeeProduct> products = em.createQuery(
|
|
"select p from HomesBranchFeeProduct p where p.feeId=:fid and p.groupId=:gid order by p.productType, p.id",
|
|
HomesBranchFeeProduct.class)
|
|
.setParameter("fid", f.getId())
|
|
.setParameter("gid", f.getGroupId())
|
|
.getResultList();
|
|
Map<String, Object> fee = new LinkedHashMap<>();
|
|
fee.put("id", f.getId());
|
|
fee.put("type", f.getFeeType());
|
|
fee.put("branchName", f.getBranchName());
|
|
fee.put("branchGroupName", f.getBranchGroupName());
|
|
fee.put("carrier", f.getCarrier());
|
|
fee.put("ispName", f.getCarrier());
|
|
fee.put("startDate", f.getStartDate() == null ? null : DT.format(f.getStartDate()));
|
|
fee.put("memo", f.getMemo());
|
|
fee.put("file1", f.getFile1());
|
|
fee.put("file2", f.getFile2());
|
|
fee.put("file3", f.getFile3());
|
|
fee.put("file4", f.getFile4());
|
|
fee.put("file5", f.getFile5());
|
|
fee.put("source", String.valueOf(f.getId()));
|
|
|
|
List<Map<String, Object>> productMaps = new ArrayList<>();
|
|
for (HomesBranchFeeProduct p : products) {
|
|
Map<String, Object> pm = new LinkedHashMap<>();
|
|
pm.put("id", p.getId());
|
|
pm.put("productType", p.getProductType());
|
|
pm.put("productName", p.getProductName());
|
|
pm.put("fee", p.getFee() == null ? 0 : p.getFee());
|
|
productMaps.add(pm);
|
|
}
|
|
Map<String, Object> out = new LinkedHashMap<>();
|
|
out.put("fee", fee);
|
|
out.put("products", productMaps);
|
|
return out;
|
|
}
|
|
|
|
private static LocalDateTime parseDateTime(Object raw) {
|
|
if (raw == null) return null;
|
|
String s = String.valueOf(raw).trim().replace('T', ' ');
|
|
if (s.isEmpty()) return null;
|
|
try {
|
|
if (s.length() == 10) return LocalDateTime.parse(s + " 00:00:00", DT);
|
|
if (s.length() >= 19) return LocalDateTime.parse(s.substring(0, 19), DT);
|
|
return LocalDateTime.parse(s, DT);
|
|
} catch (Exception e) {
|
|
try {
|
|
return LocalDateTime.parse(s.substring(0, 10) + "T00:00:00");
|
|
} catch (Exception e2) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private HomesBranch findBranch(Long id, JwtUser u) {
|
|
HomesBranch b = em.find(HomesBranch.class, id);
|
|
if (b == null || !Objects.equals(b.getGroupId(), u.getGroupId())) return null;
|
|
return b;
|
|
}
|
|
|
|
private Map<Long, String> groupNameMap(String groupId) {
|
|
return em.createQuery(
|
|
"select g from HomesBranchGroup g where g.groupId=:gid", HomesBranchGroup.class)
|
|
.setParameter("gid", groupId)
|
|
.getResultList()
|
|
.stream()
|
|
.collect(Collectors.toMap(HomesBranchGroup::getId, HomesBranchGroup::getName, (a, b) -> a));
|
|
}
|
|
|
|
private boolean existsUserid(String gid, String userid, Long excludeId) {
|
|
String jpql = "select count(b) from HomesBranch b where b.groupId=:gid and b.userid=:uid"
|
|
+ (excludeId != null ? " and b.id<>:id" : "");
|
|
var q = em.createQuery(jpql, Long.class).setParameter("gid", gid).setParameter("uid", userid.trim());
|
|
if (excludeId != null) q.setParameter("id", excludeId);
|
|
return q.getSingleResult() > 0;
|
|
}
|
|
|
|
private boolean existsOfficeName(String gid, String officeName, Long excludeId) {
|
|
String jpql = "select count(b) from HomesBranch b where b.groupId=:gid and b.officeName=:n"
|
|
+ (excludeId != null ? " and b.id<>:id" : "");
|
|
var q = em.createQuery(jpql, Long.class).setParameter("gid", gid).setParameter("n", officeName.trim());
|
|
if (excludeId != null) q.setParameter("id", excludeId);
|
|
return q.getSingleResult() > 0;
|
|
}
|
|
|
|
private boolean existsEmail(String gid, String email, Long excludeId) {
|
|
String jpql = "select count(b) from HomesBranch b where b.groupId=:gid and b.email=:e"
|
|
+ (excludeId != null ? " and b.id<>:id" : "");
|
|
var q = em.createQuery(jpql, Long.class).setParameter("gid", gid).setParameter("e", email.trim());
|
|
if (excludeId != null) q.setParameter("id", excludeId);
|
|
return q.getSingleResult() > 0;
|
|
}
|
|
|
|
private Map<String, Object> groupMap(HomesBranchGroup g) {
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("id", g.getId());
|
|
m.put("name", g.getName());
|
|
m.put("seq", g.getSeq());
|
|
return m;
|
|
}
|
|
|
|
private Map<String, Object> listMap(HomesBranch b, Map<Long, String> groupNames) {
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("id", b.getId());
|
|
m.put("name", b.getName());
|
|
m.put("officeName", b.getOfficeName());
|
|
m.put("userid", b.getUserid());
|
|
m.put("tel", b.getTel());
|
|
m.put("phone", b.getPhone());
|
|
m.put("email", b.getEmail());
|
|
m.put("sido", b.getSido());
|
|
m.put("level", b.getLevel() == null ? 1 : b.getLevel());
|
|
m.put("grant", b.getGrantFlag() == null ? 0 : b.getGrantFlag());
|
|
m.put("branchGroupId", b.getBranchGroupId());
|
|
m.put("branchGroupName", b.getBranchGroupId() == null ? null : groupNames.get(b.getBranchGroupId()));
|
|
m.put("centerName", b.getCenterName());
|
|
m.put("hasBusinessLicense", b.isHasBusinessLicense());
|
|
m.put("isTax", b.getIsTax() == null ? 1 : b.getIsTax());
|
|
m.put("createdAt", b.getCreatedAt() == null ? null
|
|
: DT.format(b.getCreatedAt().atZone(KST).toLocalDateTime()));
|
|
return m;
|
|
}
|
|
|
|
private Map<String, Object> detailMap(HomesBranch b) {
|
|
Map<String, Object> m = listMap(b, groupNameMap(b.getGroupId()));
|
|
m.put("fax", b.getFax());
|
|
m.put("zipcode", b.getZipcode());
|
|
m.put("address", b.getAddress());
|
|
m.put("addressDetail", b.getAddressDetail());
|
|
m.put("isPersonal", !b.isHasBusinessLicense());
|
|
m.put("accountBank", b.getAccountBank());
|
|
m.put("accountNumber", b.getAccountNumber());
|
|
m.put("accountName", b.getAccountName());
|
|
m.put("contactPhone", b.getContactPhone());
|
|
m.put("contactNateon", b.getContactNateon());
|
|
m.put("acceptPhone", b.getAcceptPhone() == null ? 0 : b.getAcceptPhone());
|
|
m.put("acceptNateon", b.getAcceptNateon() == null ? 0 : b.getAcceptNateon());
|
|
m.put("memo", b.getMemo());
|
|
m.put("adminMemo", b.getAdminMemo());
|
|
m.put("licenseNumber", b.getLicenseNumber());
|
|
m.put("licenseType", b.getLicenseType());
|
|
m.put("licenseItem", b.getLicenseItem());
|
|
m.put("notifyPhones", parseNotify(b.getNotifyPhonesJson()));
|
|
m.put("permissionOrderDateUpdate", b.isPermissionOrderDateUpdate());
|
|
m.put("permissionCalculate", b.isPermissionCalculate());
|
|
m.put("permissionConfig", b.isPermissionConfig());
|
|
m.put("permissionExcelDownload", b.isPermissionExcelDownload());
|
|
m.put("permissionChart", b.isPermissionChart());
|
|
return m;
|
|
}
|
|
|
|
private Map<String, Object> feeEntryMap(HomesBranchFee f, String type) {
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("id", f.getId());
|
|
m.put("type", type);
|
|
m.put("ispName", f.getCarrier());
|
|
m.put("carrier", f.getCarrier());
|
|
m.put("category", "공통");
|
|
m.put("startDate", f.getStartDate() == null ? null : DT.format(f.getStartDate()));
|
|
return m;
|
|
}
|
|
|
|
private static List<String> parseNotify(String json) {
|
|
List<String> phones = new ArrayList<>();
|
|
if (json != null && json.startsWith("[")) {
|
|
String inner = json.substring(1, json.endsWith("]") ? json.length() - 1 : json.length()).trim();
|
|
if (!inner.isEmpty()) {
|
|
for (String part : inner.split(",")) {
|
|
phones.add(part.trim().replace("\"", ""));
|
|
}
|
|
}
|
|
}
|
|
while (phones.size() < 6) phones.add("");
|
|
return phones.subList(0, 6);
|
|
}
|
|
|
|
private static String toNotifyJson(Object raw) {
|
|
List<String> phones = new ArrayList<>();
|
|
if (raw instanceof List<?> list) {
|
|
for (Object o : list) phones.add(o == null ? "" : String.valueOf(o));
|
|
}
|
|
while (phones.size() < 6) phones.add("");
|
|
StringBuilder sb = new StringBuilder("[");
|
|
for (int i = 0; i < 6; i++) {
|
|
if (i > 0) sb.append(',');
|
|
sb.append('"').append(phones.get(i).replace("\"", "")).append('"');
|
|
}
|
|
sb.append(']');
|
|
return sb.toString();
|
|
}
|
|
|
|
private static String deriveSido(String zipcode, String sido, String address) {
|
|
if (!blank(sido)) return sido.trim();
|
|
if (!blank(address)) {
|
|
String[] parts = address.trim().split("\\s+");
|
|
if (parts.length > 0) return parts[0];
|
|
}
|
|
if (!blank(zipcode) && zipcode.length() >= 2) return zipcode.substring(0, 2);
|
|
return "";
|
|
}
|
|
|
|
private static boolean blank(String s) { return s == null || s.isBlank(); }
|
|
private static String str(Object o) { return o == null ? "" : String.valueOf(o).trim(); }
|
|
private static boolean bool(Object o) {
|
|
return Boolean.TRUE.equals(o) || "true".equalsIgnoreCase(String.valueOf(o));
|
|
}
|
|
private static Long longOrNull(Object o) {
|
|
if (o == null || "".equals(o) || "null".equals(String.valueOf(o))) return null;
|
|
if (o instanceof Number n) return n.longValue();
|
|
try { return Long.parseLong(String.valueOf(o)); } catch (Exception e) { return null; }
|
|
}
|
|
}
|