Hai sai lầm hay gặp khi tự code một trang web… bán hàng

Làm lập trình viên, hẳn ai cũng biết tới khái niệm … web bán hàng. Code một trang web bán hàng là cách rất tốt để áp dụng ngôn ngữ/công nghệ mới. Thông qua các chức năng đăng kí, đăng nhập, show sản phẩm, ta học được cách phân quyền, routing, phân trang, xử lý business logic.

Nhiều bạn sinh viên cho rằng code web bán hàng là một chuyện đơn giản, phần nhiều chỉ là thêm bớt xóa sửa. Thật vậy chăng? Hãy đọc bài viết này để xem bạn có mắc phải hai sai lầm dưới không nhé nhé.

Sai lầm 1 – Không lưu giá tiền của sản phẩm vào trong hóa đơn

11

Quan hệ giữa OrderItem là many-to-many, do đó ta phải thêm 1 bảng ở giữa để kết nối 2 bảng này. Theo lý thuyết, khi hiển thị hóa đơn, có thể tham chiếu qua bên bảng Item để lấy giá của sản phẩm và đem ra hiển thị.

Tuy nhiên theo thực tế, giá tiền của sản phẩm thường thay đổi. Giả sử 10/5, giá một ổ bánh mì là 10k; đến ngày 12/5, giá của một ổ bánh mì là 15k. Khi ta xem chiếu lại hóa đơn ngày 10/5, ta thấy giá ổ bánh mì vẫn là 15k, vì nó tham chiếu tới giá hiện tại trong bảng Item. Ngoài ra, giá còn bị tác động các chương trình khuyến mãi, giảm giá. Nếu chỉ lưu giá sản phẩm thì lúc hiển thị hay xuất báo cáo, thông tin sẽ bị sai lệch.

Vậy ta xử lý như thế nào? Cách đơn giản nhất là thêm 1 column chứa giá sản phẩm trong hóa đơn vào bảng OrderItem. Nhiều khi người ta còn dùng 1 bảng riêng để lưu sự thay đổi về giá cả cho từng sản phẩm, sau đó dựa theo ngày trên hóa đơn để tìm giá của sản phẩm trong ngày đó.

22
Database sau khi đã sửa

(Lưu ý: bảng OrderItem có thể dùng ItemIDOrderID làm composite primary key nhé, mình tạo ID cho dễ query khi dùng Entity Framework thôi)

Sai lầm 2 – Lưu giỏ hàng trong session

Khi học về session trong Web, người ta thường dùng web bán hàng làm ví dụ. Mỗi user có 1 session riêng, do đó ta dùng session để lưu giỏ hàng cho mỗi user. Tuy nhiên, cách này chỉ phù hợp với web demo hoặc đồ án trong trường, chứ trong thực tế thì … rất dễ phát sinh vấn đề.

Chúng ta thường không hiểu rõ quá trình mua hàng của người dùng. Nhiều trường hợp người dùng bỏ hàng vào giỏ rồi check out. Đôi khi, người dùng lại bỏ hàng vào giỏ để lưu tạm, dồn vài hôm cho nhiều rồi mua luôn 1 lượt để hưởng khuyến mãi. Nếu lưu giỏ hàng vào session, giỏ hàng sẽ bị biến mất khi session timeout, gây khó chịu cho người dùng.

3057306-poster-p-1-how-the-shopping-cart-shaped-our-buying-habits

Hoặc giả sử người dùng sử dụng cả web và di động để mua hàng, nếu lưu trên session thì khi chuyển qua thiết bị khác, người dùng sẽ không thấy giỏ hàng của mình đâu nữa! Ngoài ra, về mặt technical, session chạy trong môi trường server farm sẽ gặp phải một số vấn đề (xem thêm).

Vậy ta xử lý thế nào?

Cách 1 – Lưu trong local storage: Cách này ko dùng được với trình duyệt cũ (có thể dùng cookie tạm). Cách này làm nhẹ tải server vì dữ liệu được đọc và ghi ở phía client. Nhược điểm là khi đổi device thì không thể xem được giỏ hàng. Bên tiki.vn có vẻ là dùng cách này.

34

Cách 2 – Lưu trong database: Với user đã tồn tại, ta lưu giỏ hàng của họ trong DB. Với user không đăng mới, ta lưu 1 chuỗi id ở cookie hay local storage của họ, dùng cookie đó để truy vấn giỏ hàng trên DB.

Nếu người dùng chỉ cho hàng vào giỏ, sau đó không quay lại website thì DB sẽ có khá nhiều dữ liệu rác. Để giải quyết chuyện này, người ta thường tạo 1 vài task chạy ngầm để xóa dữ liệu rác khỏi DB.  (Trên amazon giỏ hàng bị xóa sau 90 ngày). Ngoài ra, để tăng tốc độ lưu, ta có thể dùng một số database NoSQL có tốc độ đọc ghi nhanh để lưu giỏ hàng.

Nopcommerce, một trong số các framework e-commerce nổi tiếng của C# cũng lưu cart vào database (Các bạn nào code PHP thì vào xác nhận xem framework các bạn dùng có lưu cart vào DB không nhé, mình nghĩ là có).

Nếu bạn vẫn chưa tin điều mình nói, hãy thử mua hàng trên Amazon và Ebay xem. Bạn sẽ thấy, sau khi cho hàng vào giỏ, bạn log out ra, sử dụng điện thoại để vào thì giỏ hàng vẫn còn đấy. Điều này chỉ có thể làm được khi giỏ hàng được lưu trong database.

44

Kết

Thế nhé, đừng coi thường sự phức tạp của 1 trang web bán hàng nhé. Để làm được một trang web bán hàng tiện dụng, cần có sự thấu hiểu về UI/UX (xem thêm bài viết 1 button giá 300 triệu đô). Một số chức năng phức tạp như: người mua sản phẩm A cũng mua sản phẩm B, recommend sản phẩm theo đặc điểm người dùng,… cũng đòi hỏi một số thuật toán data mining rất phức tạp phía sau sau.

Nói chung, việc tự code một trang web bán hàng là một cách học rất tốt. Song nếu code cho doanh nghiệp, cần làm nghiêm túc thì bạn nên sử dụng một số Framework/CMS có sẵn. Ở VN thì Web bán hàng khá rẻ là do người ta dùng framework rồi custom lại cho nhanh thôi. Nếu như thiết kế và code từ đầu, thêm 1 số chức năng phức tạp thì không có giá 3-5 triệu đâu nhé.

17 thoughts on “Hai sai lầm hay gặp khi tự code một trang web… bán hàng”

    1. Về chuyện này thì không có best practice nhé. Theo lý thuyết thì người ta không lưu tổng tiền. Tuy nhiên, nếu cần truy vấn giá trị tổng nhiều lần thì người ta mới lưu để đỡ tốn thời gian truy vấn.

      VD cả tháng mới check tổng giá tiền toàn bộ order thì thôi, còn nếu phải xuất report hàng ngày, cả chục người cùng truy vấn thì phải lưu vào DB. Trong trường hợp này thì field “Tổng tiền” cũng giống như cache thôi.

      Với các hệ thống lớn, cần tính toán report nhiều thì production database họ không lưu, nhưng data warehouse của họ sẽ lưu hết để thuận tiện cho việc report.

      Em chịu khó google và đọc thêm là ra. Mấy hệ thống ở VN nếu nho nhỏ thì lưu kiểu gì cũng được =))
      https://www.google.co.uk/search?q=should+i+store+order+sum+in+database

      Liked by 2 people

  1. em đã thử vào trang tiki và xem local storage như hình, mỗi lần thêm hàng thì trường cart có thêm một id. Em xóa trường đó, tắt web và lần sau vào thì vẫn thấy giỏ hàng nguyên như cũ là do thế nào ạ?

    Like

  2. Cách 2 – Lưu trong database: … Với user không đăng mới, ta lưu 1 chuỗi id ở cookie hay local storage của họ, dùng cookie đó để truy vấn giỏ hàng trên DB.

    Tôi chưa rõ nếu trường hợp trên nếu user thực hiện mua hàng tại nhiều thiết bị khác nhau coder sẽ phải xử lý ntn để đảm bảo đúng người đúng hàng. Bạn có thể chia sẽ cách xử lý không?

    Like

    1. Không đăng kí mà mua hàng ở nhiều thiết bị khác nhau thì làm sao biết là user nào đc bạn :D. Ở đây chúng ta lưu cookie với local storage để lần sau user dùng device đó thì giỏ hàng vẫn còn thôi :D.

      Like

  3. Tuyệt quá, anh nói đúng cái sai của em là lưu cart vào session. Rất cảm ơn anh về bài viết.

    Like

  4. Em đã code phần lưu tổng tiền của hóa đơn và giảm giá của hóa đơn (trong hóa đơn _order_ có thuộc tính Total và thuộc tính Discount) ở CSDL, nếu giỏ hàng em lưu vào trong ViewModel của web được không ạ?

    Like

  5. Xin phép anh cho em đào mộ phát ạ 😀

    Anh có nói ở cách 2 có thể lưu giỏ hàng vào Nodejs, vậy ý anh là Nodejs chỉ là database phụ chuyên trách việc lưu giỏ hàng thôi, hay có thể sử dụng kết hợp cả SQL và NoSQL phục vụ nhiều mục đích khác nhau của web app ạ ? Tại em cũng đang làm app rao vặt, em dự định thông tin quan trọng của khách hàng thì lưu vào MySQL, còn các thông tin khác như comment, like, voting thì sẽ đẩy qua Node để push notification cho nhanh ạ.

    Like

  6. Em dùng ReactJs đã tìm hiểu qua một số headless CMS build ecommerce, nhưng chưa biết chọn ẻm nào?
    Strapi => Thằng này thiếu tính năng checkout phải implement thêm thằng stripe, khó mở rộng
    Vendure => Em đang tìm hiểu thằng này, thằng này hiện đang support beta và cộng đồng ít nên cũng khó approach
    Reaction => Anh lead bảo thằng này khó approach, hơn nữa có mình em làm
    Không biết anh có thằng nào không? suggest em mới
    Thanks anh 😀

    Like

Leave a comment