고객 수 추이에 +- 추가

This commit is contained in:
Hyojin Ahn 2026-06-24 10:03:41 -04:00
parent 0b2e744a0f
commit 4110a9f2f1
3 changed files with 29 additions and 14 deletions

View File

@ -19,6 +19,12 @@ public class CustomerActiveTrendPointDto {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate date;
// 날짜 활성( cus_contract_date <= date AND (terminated IS NULL OR terminated > date) ) 고객
// 날짜 활성 고객 (cus_status='A' 기준, 날짜로 과거 재구성)
private long count;
// 날짜에 계약 시작한 고객 (cus_contract_date = date)
private long added;
// 날짜에 해지된 고객 (cus_terminated_date = date)
private long removed;
}

View File

@ -30,24 +30,29 @@ public interface CustomerRepository extends JpaRepository<Customer, Long> {
// 오늘 추가된 고객 : cus_contract_date = 오늘
long countByCusContractDate(LocalDate cusContractDate);
// 날짜별 활성 고객 (그래프용).
// - 활성 기준 = cus_status='A' (현재 활성 플래그가 진짜 기준)
// - 위에 날짜로 과거 시점 재구성: cus_contract_date <= D AND (cus_terminated_date IS NULL OR cus_terminated_date > D)
// - "지금 활성('A')이면서 그 날짜에 계약기간 안에 있던" 고객 오늘 값은 전체(활성) 고객 수와 일치
// - generate_series [startDate, endDate] 날짜 만들고 LEFT JOIN 으로 카운트 날도 0으로 채워짐
// - return: [0]=날짜(date), [1]=활성 고객 (bigint)
// 날짜별 활성 고객 + 신규/해지 (선그래프·막대그래프용).
// - active_count = cus_status='A' 이고 날짜에 계약기간 안에 있던 고객 (날짜로 과거 재구성)
// - added_count = 날짜에 계약 시작 (cus_contract_date = D)
// - removed_count = 날짜에 해지 (cus_terminated_date = D)
// - generate_series [startDate, endDate] 날짜 생성 날도 0
// - return: [0]=날짜(date), [1]=active(bigint), [2]=added(bigint), [3]=removed(bigint)
@Query(value = """
SELECT CAST(series.day AS date) AS day,
COUNT(c.cus_id) AS active_count
(SELECT COUNT(*) FROM crm.customer c
WHERE c.cus_status = 'A'
AND c.cus_contract_date IS NOT NULL
AND c.cus_contract_date <= CAST(series.day AS date)
AND (c.cus_terminated_date IS NULL OR c.cus_terminated_date > CAST(series.day AS date))
) AS active_count,
(SELECT COUNT(*) FROM crm.customer a
WHERE a.cus_contract_date = CAST(series.day AS date)
) AS added_count,
(SELECT COUNT(*) FROM crm.customer r
WHERE r.cus_terminated_date = CAST(series.day AS date)
) AS removed_count
FROM generate_series(CAST(:startDate AS timestamp),
CAST(:endDate AS timestamp),
INTERVAL '1 day') AS series(day)
LEFT JOIN crm.customer c
ON c.cus_status = 'A'
AND c.cus_contract_date IS NOT NULL
AND c.cus_contract_date <= CAST(series.day AS date)
AND (c.cus_terminated_date IS NULL OR c.cus_terminated_date > CAST(series.day AS date))
GROUP BY series.day
ORDER BY series.day
""", nativeQuery = true)
List<Object[]> findActiveCustomerTrend(@Param("startDate") LocalDate startDate,

View File

@ -124,10 +124,14 @@ public class CustomerService {
day = LocalDate.parse(row[0].toString());
}
long count = ((Number) row[1]).longValue();
long added = ((Number) row[2]).longValue();
long removed = ((Number) row[3]).longValue();
result.add(CustomerActiveTrendPointDto.builder()
.date(day)
.count(count)
.added(added)
.removed(removed)
.build());
}
return result;