keyboard_tabSkip to content
listVue Firebase Masterclass

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

สารบัญ

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

javascript
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

javascript
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 แบบทีเดียวแทน

javascript
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