본문으로 건너뛰기

관리자 주문 상세보기 성능 개선

PHP 8 · GODO26
변경 파일 수: 5개
변경 파일 목록
5
변경 파일 코드
추가삭제
Admin/order/order_view.php+32-1
변경 전order_view.php
if ($('#tabOrderStatus .nav-tabs li').hasClass('active')) {
$('#tabOrderStatus .nav-tabs li.active a').trigger('show.bs.tab');
}
 
 
 
 
 
 
 
 
 
if ($('#tabClaimStatus .nav-tabs li').hasClass('active')) {
$('#tabClaimStatus .nav-tabs li.active a').trigger('show.bs.tab');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
}
 
// 일괄 처리 모드의 체크
 
변경 후order_view.php
if ($('#tabOrderStatus .nav-tabs li').hasClass('active')) {
$('#tabOrderStatus .nav-tabs li.active a').trigger('show.bs.tab');
}
// 클레임 내역은 데이터가 있을 때만 초기 로드 (불필요한 inc_claim_view → getOrderView 호출 방지)
// 데이터가 없으면 초기 AJAX를 생략하고, 탭 클릭 시 기존 show.bs.tab 핸들러로 지연 로드된다.
var hasClaimData = false;
$('#tabClaimStatus .nav-tabs a strong').each(function () {
if (parseInt($(this).text().replace(/[^0-9]/g, ''), 10) > 0) {
hasClaimData = true;
return false;
}
});
if ($('#tabClaimStatus .nav-tabs li').hasClass('active')) {
var $activeClaimPane = $('#tabClaimStatus .tab-pane.active');
if (hasClaimData || $activeClaimPane.attr('id') !== 'tab-claim-cancel') {
// 클레임 데이터가 있거나, 활성 탭이 취소탭이 아닌 경우(공급사/교환·반품·환불 등) → 기존대로 AJAX 로드
$('#tabClaimStatus .nav-tabs li.active a').trigger('show.bs.tab');
} else {
// 클레임이 전혀 없고 활성 탭이 취소탭인 가장 흔한 케이스 → AJAX 없이 동일한 '취소정보가 없습니다' 빈 상태를 렌더
$('#tabClaimStatus .tab-content').removeClass('loading');
$activeClaimPane.html(
'<table class="table table-rows">'
+ '<thead><tr>'
+ '<th class="width3p">번호</th>'
+ '<th class="width5p">처리상태</th>'
+ '<th class="width8p">공급사</th>'
+ '<th class="width-3xs">이미지</th>'
+ '<th>상품</th>'
+ '<th class="width5p">취소수량</th>'
+ '<th class="width8p">취소사유</th>'
+ '<th class="width10p">상세사유</th>'
+ '</tr></thead>'
+ '<tbody><tr><td class="no-data" colspan="25">취소정보가 없습니다.</td></tr></tbody>'
+ '</table>'
);
}
}
 
// 일괄 처리 모드의 체크
 
Component/Order/OrderAdminNew.php+40-28
변경 전OrderAdminNew.php
use Origin\Enum\Order\OrderStatusGroup;
use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService;
use Origin\Service\WebHook\OrderWebHookService;
 
 
use Request;
use Session;
use Component\Page\Page;
 
$deliveryUniqueKey = '';
$aCancelDeliveryKey = array(); // 품목 하나가 부분으로 취소되서 품목수가 나뉘어진경우 취소배송비 중복계산이 안되도록 체크하기위해서 orderDeliverySno로 키값 저장&체크 todo 취소부분 환불과 맞추면 다 삭제될 내용
// 전체 정책별 배송비와 지역별 배송비의 총합 구하기
 
 
 
foreach ($getData['goods'] as $sKey => $sVal) {
foreach ($sVal as $dKey => $dVal) {
// $dVal = array_shift($dVal);
foreach ($dVal as $gKey => $gVal) {
$realDeliveryTaxSum = gd_array_sum([
$gVal['realTaxSupplyDeliveryCharge'],
$gVal['realTaxVatDeliveryCharge'],
$gVal['realTaxFreeDeliveryCharge'],
]);
// 전체 배송비 계산 (주문상품추가/주문타상품교환으로 같은 배송비 조건(deliverySno)이더라도 주문배송비(orderDeliverySno)가 추가된다
$deliveryKeyCheck = $gVal['deliverySno'] . '-' . $gVal['orderDeliverySno'];
if ($deliveryKeyCheck == $deliveryUniqueKey) {
if (gd_in_array($gVal['orderStatus'], ['c1', 'c2', 'c3', 'c4'])) {
$tempCancelDeliveryKey = substr($gVal['orderStatus'], 0, 1) . '-' . $gVal['orderDeliverySno'];
if (!gd_in_array($tempCancelDeliveryKey, $aCancelDeliveryKey)) {
// $gVal['handleSno'] 값으로 orderHandle에 기록된 취소 배송비 값 가져와서 계산
$aHandleInfo = $this->getOrderHandleInfo($gVal['handleSno']);
$aDeliveryOriginalInfo = $this->getOrderDeliveryOriginal($gVal['orderDeliverySno']);
$getData['dashBoardPrice']['cancelPrice'] += $aHandleInfo['refundDeliveryCharge'] - ($aDeliveryOriginalInfo['divisionMemberDeliveryDcPrice'] - $gVal['divisionMemberDeliveryDcPrice']);
$aCancelDeliveryKey[] = $tempCancelDeliveryKey;
}
}
} else {
// 주문상세내 배송비 금액 합산
if (!gd_in_array($gVal['orderStatus'], ['o1', 'c1', 'c2', 'c3', 'c4'])) {
$getData['dashBoardPrice']['settlePrice'] += $realDeliveryTaxSum;
}
if (gd_in_array($gVal['orderStatus'], ['o1'])) {
$getData['dashBoardPrice']['dueSettlePrice'] += $realDeliveryTaxSum;
}
if (gd_in_array($gVal['orderStatus'], ['c1', 'c2', 'c3', 'c4'])) {
$tempCancelDeliveryKey = substr($gVal['orderStatus'], 0, 1) . '-' . $gVal['orderDeliverySno'];
if (!gd_in_array($tempCancelDeliveryKey, $aCancelDeliveryKey)) {
// $gVal['handleSno'] 값으로 orderHandle에 기록된 취소 배송비 값 가져와서 계산
$aHandleInfo = $this->getOrderHandleInfo($gVal['handleSno']);
$aDeliveryOriginalInfo = $this->getOrderDeliveryOriginal($gVal['orderDeliverySno']);
$getData['dashBoardPrice']['cancelPrice'] += $aHandleInfo['refundDeliveryCharge'] - ($aDeliveryOriginalInfo['divisionMemberDeliveryDcPrice'] - $gVal['divisionMemberDeliveryDcPrice']);
$aCancelDeliveryKey[] = $tempCancelDeliveryKey;
}
}
if (gd_in_array($gVal['orderStatus'], ['r1', 'r2'])) {
$getData['dashBoardPrice']['dueRefundPrice'] += $realDeliveryTaxSum;
}
$getData['totalDeliveryPolicyCharge'] += $gVal['deliveryPolicyCharge'];
// 배송무게 계산
$getData['totalDeliveryWeights'] = json_decode($gVal['deliveryWeightInfo'], true);
}
 
 
 
 
 
 
 
 
 
 
$deliveryUniqueKey = $deliveryKeyCheck;
 
// 해당 주문의 배송비es_orderDelivery.sno에 대한 배송비 세율정보
}
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
if (Manager::isProvider()) {
$getData = $this->getProviderTotalPrice($getData);
}
 
변경 후OrderAdminNew.php
use Origin\Enum\Order\OrderStatusGroup;
use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService;
use Origin\Service\WebHook\OrderWebHookService;
use Repository\Order\OrderDeliveryOriginalRepository;
use Repository\Order\OrderHandleRepository;
use Request;
use Session;
use Component\Page\Page;
 
$deliveryUniqueKey = '';
$aCancelDeliveryKey = array(); // 품목 하나가 부분으로 취소되서 품목수가 나뉘어진경우 취소배송비 중복계산이 안되도록 체크하기위해서 orderDeliverySno로 키값 저장&체크 todo 취소부분 환불과 맞추면 다 삭제될 내용
 
// 전체 정책별 배송비와 지역별 배송비의 총합 구하기 (DB 불필요 합산은 단일 순회로 처리, 취소행/sno는 수집만)
$cancelRows = [];
$handleSnoList = $deliveryOriginalSnoList = [];
foreach ($getData['goods'] as $sKey => $sVal) {
foreach ($sVal as $dKey => $dVal) {
 
foreach ($dVal as $gKey => $gVal) {
$realDeliveryTaxSum = array_sum([
$gVal['realTaxSupplyDeliveryCharge'],
$gVal['realTaxVatDeliveryCharge'],
$gVal['realTaxFreeDeliveryCharge'],
]);
// 전체 배송비 계산 (주문상품추가/주문타상품교환으로 같은 배송비 조건(deliverySno)이더라도 주문배송비(orderDeliverySno)가 추가된다
$deliveryKeyCheck = $gVal['deliverySno'] . '-' . $gVal['orderDeliverySno'];
if ($deliveryKeyCheck != $deliveryUniqueKey) {
 
 
 
 
 
 
 
 
 
 
 
// 주문상세내 배송비 금액 합산
if (!in_array($gVal['orderStatus'], ['o1', 'c1', 'c2', 'c3', 'c4'])) {
$getData['dashBoardPrice']['settlePrice'] += $realDeliveryTaxSum;
}
if (in_array($gVal['orderStatus'], ['o1'])) {
$getData['dashBoardPrice']['dueSettlePrice'] += $realDeliveryTaxSum;
}
if (in_array($gVal['orderStatus'], ['r1', 'r2'])) {
 
 
 
 
 
 
 
 
 
 
$getData['dashBoardPrice']['dueRefundPrice'] += $realDeliveryTaxSum;
}
$getData['totalDeliveryPolicyCharge'] += $gVal['deliveryPolicyCharge'];
// 배송무게 계산
$getData['totalDeliveryWeights'] = json_decode($gVal['deliveryWeightInfo'], true);
}
// 취소행은 기존에 배송키 분기와 무관하게 동일 처리됐으므로 모아두고, N+1 제거 위해 일괄조회 후 후처리
if (in_array($gVal['orderStatus'], ['c1', 'c2', 'c3', 'c4'])) {
$cancelRows[] = $gVal;
if ($gVal['handleSno'] > 0) {
$handleSnoList[] = $gVal['handleSno'];
}
if ($gVal['orderDeliverySno'] > 0) {
$deliveryOriginalSnoList[] = $gVal['orderDeliverySno'];
}
}
$deliveryUniqueKey = $deliveryKeyCheck;
 
// 해당 주문의 배송비es_orderDelivery.sno에 대한 배송비 세율정보
}
}
 
// 취소상태 배송행의 handleSno/orderDeliverySno 를 일괄 1회씩 조회 (N+1 제거)
$handleInfoMap = \App::getInstance(OrderHandleRepository::class)
->findMapBySnos(array_values(array_unique($handleSnoList)));
$deliveryOriginalMap = \App::getInstance(OrderDeliveryOriginalRepository::class)
->findMapBySnos(array_values(array_unique($deliveryOriginalSnoList)));
 
// 취소 배송비 합산 (동일 orderDeliverySno 키는 1회만 계산)
foreach ($cancelRows as $gVal) {
$tempCancelDeliveryKey = substr($gVal['orderStatus'], 0, 1) . '-' . $gVal['orderDeliverySno'];
if (in_array($tempCancelDeliveryKey, $aCancelDeliveryKey)) {
continue;
}
// $gVal['handleSno'] 값으로 orderHandle에 기록된 취소 배송비 값 가져와서 계산 (일괄조회 맵에서 룩업)
$refundDeliveryCharge = $handleInfoMap[$gVal['handleSno']]['refundDeliveryCharge'] ?? 0;
$originalDcPrice = $deliveryOriginalMap[$gVal['orderDeliverySno']]['divisionMemberDeliveryDcPrice'] ?? 0;
$getData['dashBoardPrice']['cancelPrice'] += $refundDeliveryCharge - ($originalDcPrice - $gVal['divisionMemberDeliveryDcPrice']);
$aCancelDeliveryKey[] = $tempCancelDeliveryKey;
}
 
if (Manager::isProvider()) {
$getData = $this->getProviderTotalPrice($getData);
}
 
Component/Order/OrderAdmin.php+40-28
변경 전OrderAdmin.php
use Origin\Enum\Order\OrderStatusGroup;
use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService;
use Origin\Service\WebHook\OrderWebHookService;
 
 
use Request;
use Session;
use Vendor\Spreadsheet\Excel\Reader as SpreadsheetExcelReader;
 
$deliveryUniqueKey = '';
$aCancelDeliveryKey = array(); // 품목 하나가 부분으로 취소되서 품목수가 나뉘어진경우 취소배송비 중복계산이 안되도록 체크하기위해서 orderDeliverySno로 키값 저장&체크 todo 취소부분 환불과 맞추면 다 삭제될 내용
// 전체 정책별 배송비와 지역별 배송비의 총합 구하기
 
 
 
foreach ($getData['goods'] as $sKey => $sVal) {
foreach ($sVal as $dKey => $dVal) {
// $dVal = array_shift($dVal);
foreach ($dVal as $gKey => $gVal) {
$realDeliveryTaxSum = gd_array_sum([
$gVal['realTaxSupplyDeliveryCharge'],
$gVal['realTaxVatDeliveryCharge'],
$gVal['realTaxFreeDeliveryCharge'],
]);
// 전체 배송비 계산 (주문상품추가/주문타상품교환으로 같은 배송비 조건(deliverySno)이더라도 주문배송비(orderDeliverySno)가 추가된다
$deliveryKeyCheck = $gVal['deliverySno'] . '-' . $gVal['orderDeliverySno'];
if ($deliveryKeyCheck == $deliveryUniqueKey) {
if (gd_in_array($gVal['orderStatus'], ['c1', 'c2', 'c3', 'c4'])) {
$tempCancelDeliveryKey = substr($gVal['orderStatus'], 0, 1) . '-' . $gVal['orderDeliverySno'];
if (!gd_in_array($tempCancelDeliveryKey, $aCancelDeliveryKey)) {
// $gVal['handleSno'] 값으로 orderHandle에 기록된 취소 배송비 값 가져와서 계산
$aHandleInfo = $this->getOrderHandleInfo($gVal['handleSno']);
$aDeliveryOriginalInfo = $this->getOrderDeliveryOriginal($gVal['orderDeliverySno']);
$getData['dashBoardPrice']['cancelPrice'] += $aHandleInfo['refundDeliveryCharge'] - ($aDeliveryOriginalInfo['divisionMemberDeliveryDcPrice'] - $gVal['divisionMemberDeliveryDcPrice']);
$aCancelDeliveryKey[] = $tempCancelDeliveryKey;
}
}
} else {
// 주문상세내 배송비 금액 합산
if (!gd_in_array($gVal['orderStatus'], ['o1', 'c1', 'c2', 'c3', 'c4'])) {
$getData['dashBoardPrice']['settlePrice'] += $realDeliveryTaxSum;
}
if (gd_in_array($gVal['orderStatus'], ['o1'])) {
$getData['dashBoardPrice']['dueSettlePrice'] += $realDeliveryTaxSum;
}
if (gd_in_array($gVal['orderStatus'], ['c1', 'c2', 'c3', 'c4'])) {
$tempCancelDeliveryKey = substr($gVal['orderStatus'], 0, 1) . '-' . $gVal['orderDeliverySno'];
if (!gd_in_array($tempCancelDeliveryKey, $aCancelDeliveryKey)) {
// $gVal['handleSno'] 값으로 orderHandle에 기록된 취소 배송비 값 가져와서 계산
$aHandleInfo = $this->getOrderHandleInfo($gVal['handleSno']);
$aDeliveryOriginalInfo = $this->getOrderDeliveryOriginal($gVal['orderDeliverySno']);
$getData['dashBoardPrice']['cancelPrice'] += $aHandleInfo['refundDeliveryCharge'] - ($aDeliveryOriginalInfo['divisionMemberDeliveryDcPrice'] - $gVal['divisionMemberDeliveryDcPrice']);
$aCancelDeliveryKey[] = $tempCancelDeliveryKey;
}
}
if (gd_in_array($gVal['orderStatus'], ['r1', 'r2'])) {
$getData['dashBoardPrice']['dueRefundPrice'] += $realDeliveryTaxSum;
}
$getData['totalDeliveryPolicyCharge'] += $gVal['deliveryPolicyCharge'];
// 배송무게 계산
$getData['totalDeliveryWeights'] = json_decode($gVal['deliveryWeightInfo'], true);
}
 
 
 
 
 
 
 
 
 
 
$deliveryUniqueKey = $deliveryKeyCheck;
 
// 해당 주문의 배송비es_orderDelivery.sno에 대한 배송비 세율정보
}
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
if (Manager::isProvider()) {
$getData = $this->getProviderTotalPrice($getData);
}
 
변경 후OrderAdmin.php
use Origin\Enum\Order\OrderStatusGroup;
use Origin\Service\Statistics\Analytics\Order\OrderCompleteAnalyticsCollectorService;
use Origin\Service\WebHook\OrderWebHookService;
use Repository\Order\OrderDeliveryOriginalRepository;
use Repository\Order\OrderHandleRepository;
use Request;
use Session;
use Vendor\Spreadsheet\Excel\Reader as SpreadsheetExcelReader;
 
$deliveryUniqueKey = '';
$aCancelDeliveryKey = array(); // 품목 하나가 부분으로 취소되서 품목수가 나뉘어진경우 취소배송비 중복계산이 안되도록 체크하기위해서 orderDeliverySno로 키값 저장&체크 todo 취소부분 환불과 맞추면 다 삭제될 내용
 
// 전체 정책별 배송비와 지역별 배송비의 총합 구하기 (DB 불필요 합산은 단일 순회로 처리, 취소행/sno는 수집만)
$cancelRows = [];
$handleSnoList = $deliveryOriginalSnoList = [];
foreach ($getData['goods'] as $sKey => $sVal) {
foreach ($sVal as $dKey => $dVal) {
 
foreach ($dVal as $gKey => $gVal) {
$realDeliveryTaxSum = array_sum([
$gVal['realTaxSupplyDeliveryCharge'],
$gVal['realTaxVatDeliveryCharge'],
$gVal['realTaxFreeDeliveryCharge'],
]);
// 전체 배송비 계산 (주문상품추가/주문타상품교환으로 같은 배송비 조건(deliverySno)이더라도 주문배송비(orderDeliverySno)가 추가된다
$deliveryKeyCheck = $gVal['deliverySno'] . '-' . $gVal['orderDeliverySno'];
if ($deliveryKeyCheck != $deliveryUniqueKey) {
 
 
 
 
 
 
 
 
 
 
 
// 주문상세내 배송비 금액 합산
if (!in_array($gVal['orderStatus'], ['o1', 'c1', 'c2', 'c3', 'c4'])) {
$getData['dashBoardPrice']['settlePrice'] += $realDeliveryTaxSum;
}
if (in_array($gVal['orderStatus'], ['o1'])) {
$getData['dashBoardPrice']['dueSettlePrice'] += $realDeliveryTaxSum;
}
if (in_array($gVal['orderStatus'], ['r1', 'r2'])) {
 
 
 
 
 
 
 
 
 
 
$getData['dashBoardPrice']['dueRefundPrice'] += $realDeliveryTaxSum;
}
$getData['totalDeliveryPolicyCharge'] += $gVal['deliveryPolicyCharge'];
// 배송무게 계산
$getData['totalDeliveryWeights'] = json_decode($gVal['deliveryWeightInfo'], true);
}
// 취소행은 기존에 배송키 분기와 무관하게 동일 처리됐으므로 모아두고, N+1 제거 위해 일괄조회 후 후처리
if (in_array($gVal['orderStatus'], ['c1', 'c2', 'c3', 'c4'])) {
$cancelRows[] = $gVal;
if ($gVal['handleSno'] > 0) {
$handleSnoList[] = $gVal['handleSno'];
}
if ($gVal['orderDeliverySno'] > 0) {
$deliveryOriginalSnoList[] = $gVal['orderDeliverySno'];
}
}
$deliveryUniqueKey = $deliveryKeyCheck;
 
// 해당 주문의 배송비es_orderDelivery.sno에 대한 배송비 세율정보
}
}
 
// 취소상태 배송행의 handleSno/orderDeliverySno 를 일괄 1회씩 조회 (N+1 제거)
$handleInfoMap = \App::getInstance(OrderHandleRepository::class)
->findMapBySnos(array_values(array_unique($handleSnoList)));
$deliveryOriginalMap = \App::getInstance(OrderDeliveryOriginalRepository::class)
->findMapBySnos(array_values(array_unique($deliveryOriginalSnoList)));
 
// 취소 배송비 합산 (동일 orderDeliverySno 키는 1회만 계산)
foreach ($cancelRows as $gVal) {
$tempCancelDeliveryKey = substr($gVal['orderStatus'], 0, 1) . '-' . $gVal['orderDeliverySno'];
if (in_array($tempCancelDeliveryKey, $aCancelDeliveryKey)) {
continue;
}
// $gVal['handleSno'] 값으로 orderHandle에 기록된 취소 배송비 값 가져와서 계산 (일괄조회 맵에서 룩업)
$refundDeliveryCharge = $handleInfoMap[$gVal['handleSno']]['refundDeliveryCharge'] ?? 0;
$originalDcPrice = $deliveryOriginalMap[$gVal['orderDeliverySno']]['divisionMemberDeliveryDcPrice'] ?? 0;
$getData['dashBoardPrice']['cancelPrice'] += $refundDeliveryCharge - ($originalDcPrice - $gVal['divisionMemberDeliveryDcPrice']);
$aCancelDeliveryKey[] = $tempCancelDeliveryKey;
}
 
if (Manager::isProvider()) {
$getData = $this->getProviderTotalPrice($getData);
}
 
Repository/Order/OrderDeliveryOriginalRepository.php+34
변경 전OrderDeliveryOriginalRepository.php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
변경 후OrderDeliveryOriginalRepository.php
<?php
/*
* Copyright (C) 2026 NHN COMMERCE. - All Rights Reserved
*
* Unauthorized copying or redistribution of this file in source and binary forms via any medium
* is strictly prohibited.
*/
 
namespace Bundle\Repository\Order;
 
use Origin\Model\Order\OrderDeliveryOriginal;
 
class OrderDeliveryOriginalRepository
{
/**
* sno 목록으로 orderDeliveryOriginal 정보를 일괄 조회해 [sno => row] 맵으로 반환 (주문상세 N+1 제거용)
*
* @param array $snos orderDeliveryOriginal.sno 목록
* @return array sno 를 키로 하는 orderDeliveryOriginal row 맵
*/
public function findMapBySnos(array $snos): array
{
if (empty($snos)) {
return [];
}
 
return OrderDeliveryOriginal::query()
->whereIn('sno', $snos)
->get()
->keyBy('sno')
->map(fn ($model) => $model->toArray())
->all();
}
}
 
Repository/Order/OrderHandleRepository.php+34
변경 전OrderHandleRepository.php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
변경 후OrderHandleRepository.php
<?php
/*
* Copyright (C) 2026 NHN COMMERCE. - All Rights Reserved
*
* Unauthorized copying or redistribution of this file in source and binary forms via any medium
* is strictly prohibited.
*/
 
namespace Bundle\Repository\Order;
 
use Origin\Model\Order\OrderHandle;
 
class OrderHandleRepository
{
/**
* sno 목록으로 orderHandle 정보를 일괄 조회해 [sno => row] 맵으로 반환 (주문상세 N+1 제거용)
*
* @param array $snos orderHandle.sno 목록
* @return array sno 를 키로 하는 orderHandle row 맵
*/
public function findMapBySnos(array $snos): array
{
if (empty($snos)) {
return [];
}
 
return OrderHandle::query()
->whereIn('sno', $snos)
->get()
->keyBy('sno')
->map(fn ($model) => $model->toArray())
->all();
}
}