icon picker
경매형 이벤트 상품 firebase

이웃 경매 데이터 구조 (현재 입찰가, 입찰자 정보) IUT_BID_PRICE

20230601_181935.png
image.png

Firebase 접근 규칙

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
read, write: true로 변경 시, 알림이 오는 문제 때문에 해당 규칙을 적용
→ Firebase 데이터 조회 및 수정/삭제 하기 위해서 auth 값이 필요한데 event-list 페이지에 접근할 때마다 익명 로그인을 수행하도록 하여 해결.

// event-list.vue
const eventGrid = useWijmoFlexGrid({
isReadOnly: false,
selection: {
mode: "Check",
},
onCellDblClick: async (col: number, row: number, data, e: MouseEvent) => {
changeTabSelection(1, {
evtId: data.evtId
});
},
onAfterInitialized: async (control: FlexGrid) => {
eventGrid.collectionView.trackChanges = true;
const user = await getUser() // 이벤트 리스트 조회 시, 로그인 여부를 확인
console.log(user)
// trackChanges: true
},
...
})
// ../plugin/firebase.ts
import { getAuth, signInAnonymously } from 'firebase/auth'

// 익명 로그인
const getUser = async () => {
const auth = await getAuth(app)
let user = auth.currentUser

if(user) return user
let newUser = await signInAnonymously(auth)

return auth.currentUser
}

Firebase method


1. 해당 evtId에 대한 이벤트 상품 document 조회

const readData = async (evtId) => {
const q = query(collection(store, "IUT_BID_PRICE"), where("evtId", "==", evtId));
const querySnapshot = await getDocs(q);
return querySnapshot
}e
‘IUT_BID_PRICE’ collection에서 evtid에 해당하는 document 정보 반환
image.png

2. 이벤트 상품에 대한 document 생성

// test 데이터
const testUser = {
usrId: 'testuser',
nickNm: 'tester1',
price: 1000,
attendDt: new Date()
}

const createAucPrd = async (evtId, itemId) => {
const key = `${evtId}-${itemId}`
const itemDoc = doc(store, 'IUT_BID_PRICE', key)
const biddersDoc = doc(itemDoc, 'NOW_BIDDERS', testUser.usrId)

const addedData = await setDoc(itemDoc, {
evtId: evtId,
itemId: itemId,
currBid: testUser.price,
nickNm: testUser.nickNm,
usrId: testUser.usrId
})
// test data 추가
const testBid = await setDoc(biddersDoc, {
usrId: testUser.usrId,
price: testUser.price,
attendDt: testUser.attendDt
})
return addedData
}
해당 상품에 대한 document 생성시 ID는 ‘evtId-itemId’ 패턴으로 생성한다.

3. 이벤트 상품에 대한 document 삭제

const deleteAucPrd = async (evtId, itemIds) => {
const q = query(collection(store, "IUT_BID_PRICE"), and(where("evtId", "==", evtId), where("itemId", "in", itemIds)))
const querySnapshot = await getDocs(q);

querySnapshot.forEach(async (doc) => {
await deleteDoc(doc.ref)
})
}
IUT_BID_PRICE collection 내에 evtId, 파라미터로 보내준 itemId 해당하는 document를 한번에 삭제

4. 해당 이벤트 상품에 대한 경매 참여자 수 조회

// 해당 이벤트 상품에 대한 경매 참여자 수 조회
const countBidders = async (evtId, itemId) => {
const key = `${evtId}-${itemId}`
const coll = collection(store, `IUT_BID_PRICE/${key}/NOW_BIDDERS`)

const snapshot = await getCountFromServer(coll)
return snapshot.data().count;
}

5. 입찰자, 차순위 입찰자 정보 조회

const getWinner = async (evtId, itemId) => {
const key = `${evtId}-${itemId}`

// 상위 2명 입찰자 query
const q = query(collection(store, `IUT_BID_PRICE/${key}/NOW_BIDDERS`), orderBy("price", "desc"), limit(2))
const querySnapshot = await getDocs(q)

const data = []
querySnapshot.forEach(d => {
data.push({
usrId: d.data().usrId,
currBidPc: d.data().price
})
})

return data
}
evtId, itemId에 해당하는 document에 NOW_BIDDERS(입찰자 정보) collection에서 입찰가 기준으로 정렬 후 상위 2명을 조회한다.

경매형 이벤트 그리드 적용


1. Firebase에 저장된 경매 이벤트 상품 정보 그리드 데이터에 mapping

async function getAucData(evtId, items) {
const data = await readData(evtId)

const dataObject = await data.docs.reduce(async (result, d) => {
for (let i = 0; i < items.length; i++) {
if (items[i].itemId === d.data().itemId) {
const count = await countBidders(eventDetail.evtId, items[i].itemId)
console.log(count)
items[i].pplNum = count > 0 ? count : 0
items[i].currBid = d.data().currBid
}
items[i].rownum = i + 1
}
return result
}, {})

console.log(dataObject)
return dataObject
}

그리드 내부에 load 할 때마다 위 코드를 실행시켜서 mapping 시켜준다. (경매형 이벤트일 경우에만)
if (eventDetail.evtDispTpCd === "200") await getAucData(eventDetail.evtId, data.body.evtPrdDto)


2. 상품 테이블에 추가/삭제 하는 메소드에 Firebase document 생성/삭제 메소드 삽입

추가
if (eventDetail.evtDispTpCd === "200") { // 경매형 일경우만
await addAucPrd(evtDlspCreateParam.dlspList)
}

async function addAucPrd(items) {
console.log(items)
const process = await Promise.all(items.map(async item => {
return createAucPrd(eventDetail.evtId, item.itemId)
}))
}
경매 이벤트 상품 정보는 firebase 데이터베이스에 적용하는 순서는 상관 없으므로, Promise.all을 사용하여 해당 itemId에 맞는 상품들에 대한 document들을 생성해준다.

삭제
if (eventDetail.evtDispTpCd === "200") { // 경매형 일경우만
await removeAucPrd(evtDlspDeleteParam.dlspList)
}

async function removeAucPrd(items) {
console.log(items)
const ids = items.map(item => item.itemId)
return await deleteAucPrd(eventDetail.evtId, ids)
}
삭제 메소드는 삭제할 itemId를 모두 받아서 query로 처리하여, deleteAucPrd 함수 내에서 한번에 처리한다.
→ 상품 삭제시, 기존 firebase 입찰자 정보는 로그성 데이터 으로 남겨두기 위해. 삭제기능을 제거.

3. 경매 확정 (입찰자, 차순위 입찰자)

async function confirmBidResult() {

const confrimYn = await useGlobal().confirm("확정 하시겠습니까?");

if (confrimYn) {
// firebase에서 1,2 순위 입찰자 정보 load
const data = await getWinner(props.evtId, props.itemId)

if (data.length <= 0) {
alert("입찰자 정보가 없습니다.")
return
}

for (let i = 0; i < data.length; i++) {
data[i].evtId = props.evtId
data[i].webPrdId = props.itemId
}

data[0].entWinYnf = "Y"

// 차순위 입찰자가 있는 경우
if (data.length > 2) data[1].entWinYnf = "N"

console.log(data)
const result = await useAucResultService().postAucResultList(props.evtId, data)

if (result.data.success) {
useGlobal()
.alert("확정 되었습니다.")
.then(() => {
grid.pagination.loadPageData()
})
} else {
alert("확정 실패하였습니다.")
}
}
}
입찰 확정 버튼 클릭시, Firebase에서 입찰자, 차순위 입찰자를 조회하여 해당 상품에 대한 응모자 테이블에 저장한다.
→ 입찰자 정보 테이블에는 최대 2명까지 저장되어야 하기 때문에 확정 후, 더 이상 추가되지 못하게 하기 위해 그리드에 정보가 있으면 확정 버튼을 비활성화 시킨다.

4. 경매 유찰

유찰 조건
입찰자 정보 없을시
입찰자 1명 인경우
입찰자 Y → 입찰자 F
입찰자 2명인 경우
입찰자 Y, 차순위 입찰자 N → 입찰자 F, 차순위 입찰자 Y
입찰자 F, 차순위 입찰자 Y → 입찰자 F, 차순위 입찰자 F

async function fallBidResult() {
console.log(grid.collectionView.items)
const data = grid.collectionView.items

// 입찰자 정보 없음
if (data.length <= 0) {
alert("입찰자 정보가 없습니다.")
return
}

// 입찰자 1명일 경우
else if (data.length === 1) {
if (data[0].entWinYnf === 'Y') {
data[0].entWinYnf = 'F'
} else {
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.