Skip to main content

ลองเพิ่ม placeorder ลดจำนวนสินค้า

เพิ่ม productId ลงตะกร้าไป

import { defineStore } from 'pinia'

import {
collection,
getDocs,
query,
where
} from 'firebase/firestore'

import { db } from '@/firebase'

export const useUserProductStore = defineStore('user-product', {
state: () => ({
list: [],
loaded: false,
page: 1,
limit: 2
}),
actions: {
async loadProduct () {
const productsCol = query(collection(db, 'products'), where('status', '==', 'open'))
const productSnapshop = await getDocs(productsCol)
const productList = productSnapshop.docs.map(doc => ({
productId: doc.id, // เพิ่ม productId เพื่อให้เพิ่มตอน add ตะกร้าเข้าไป
...doc.data()
}))
if (productList && productList.length > 0) {
this.list = productList
}
this.loaded = true
},
/* function อื่นเหมือนเดิม */
}
})

เพิ่ม increment หลังจากรับสินค้ามาในตะกร้า

  • ลองจำลอง placeorder โดยการแก้ให้ checkout สามารถลดจำนวน remain product ได้

แก้ที่ stores/user/cart.js

import { defineStore } from 'pinia'

import {
doc,
increment,
updateDoc
} from 'firebase/firestore'

import { db } from '@/firebase'

export const useUserCartStore = defineStore('user-cart', {
state: () => ({
items: [],
checkout: {}
}),
actions: {
// แก้แค่ checkout
async checkout (checkoutData) {
try {
let checkout = {
...checkoutData,
totalPrice: this.summaryPrice,
paymentMethod: 'Credit Card',
createdAt: (new Date()).toLocaleString(),
orderNumber: `AA${(Math.floor(Math.random() * 900000) + 100000).toString()}`,
products: this.items
}

// workaround (update stock = checkout complete), not write order
for (const product of checkout.products) {
const productRef = doc(db, 'products', product.productId)
// update จำนวน remainQuantity ลงทีละ 1
await updateDoc(productRef, {
remainQuantity: increment(-1)
})
}

localStorage.setItem('checkout-data', JSON.stringify(checkout))
} catch (error) {
console.log('error', error.code)
throw new Error('out of stock')
}
}
}
})

เพิ่ม Firebase rule ดักจำนวนสินค้า

  • ดักให้ update ได้เฉพาะสินค้ามี stock (หากไม่ใช่ admin)

เพิ่มเงื่อนไขนี้เข้ามาใน firestore.rules

rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {
match /products/{productId} {
allow read: if (request.auth != null && isAdmin()) || (resource.data.status == 'open');
allow write: if (request.auth != null && isAdmin()) || (resource.data.status == 'open' && resource.data.remainQuantity > 0);
}
}
}

เมื่อทดสอบโดยปรับให้ remainQuantity เป็น 0 จะเจอ Error permission denied ออกมาแทน

increment-01

ใช้ batch ในการ update รวดเดียว

เอกสารต้นฉบับ: https://firebase.google.com/docs/firestore/manage-data/transactions

เปลี่ยนมายิงเป็นแบบ batch แบบทีเดียวแทน

import { defineStore } from 'pinia'

import {
doc,
increment,
// updateDoc,
writeBatch // import writeBatch มาแทน
} from 'firebase/firestore'

import { db } from '@/firebase'

export const useUserCartStore = defineStore('user-cart', {
state: () => ({
items: [],
checkout: {}
})
actions: {
/* code เหมือนเดิม */
async checkout (checkoutData) {
try {
let checkout = {
...checkoutData,
totalPrice: this.summaryPrice,
paymentMethod: 'Credit Card',
createdAt: (new Date()).toLocaleString(),
orderNumber: `AA${(Math.floor(Math.random() * 900000) + 100000).toString()}`,
products: this.items
}

// เปลี่ยนมาใช้ batch แทน
const batch = writeBatch(db)
// workaround (update stock = checkout complete), not write order
for (const product of checkout.products) {
const productRef = doc(db, 'products', product.productId)
batch.update(productRef, {
remainQuantity: increment(-1)
})
}
await batch.commit()

localStorage.setItem('checkout-data', JSON.stringify(checkout))
} catch (error) {
console.log('error', error.code)
throw new Error('out of stock')
}
}
}
})

สำหรับบทนี้ก็ประมาณนี้ เดี๋ยวเราจะค่อยมาทำ placeorder ให้สมบูรณ์กันตอนเข้าหัวข้อ Cloud function