Bộ Lọc Thống Kê & Khóa Phiếu Nhập Xuất AppSheet (P.3)

quan ly ban hang quan ly cong no

Ở Phần 2 App Quản Lý Bán Hàng, hệ thống đã tự động cập nhật công nợ, tên khách hàng/nhà cung cấp và tồn kho. Sang Phần 3 này, mình làm hai việc: dựng một bộ lọc thống kê để xem nhanh nhập/xuất theo khoảng thời gian, và xử lý bài toán khóa phiếu – khi một phiếu nhập/xuất đã hoàn tất thì không ai được sửa hay xóa nữa, để bảo vệ dữ liệu lịch sử.

Tạo bảng Thống kê để lọc theo ngày và loại giao dịch

Mở lại file Google Sheet, tạo một sheet mới tên “Thống kê” với 3 cột: ID (mã cố định, chỉ cần 1 dòng duy nhất), Từ ngày, Đến ngày, và Loại (dùng để chọn xem Nhập, Xuất, hay cả hai cùng lúc).

Add sheet này vào app, rồi cấu hình kiểu dữ liệu:

  • Từ ngày, Đến ngày: kiểu Date.
  • Loại: kiểu Enum list (chứ không phải Enum thường) để có thể chọn đồng thời cả “Nhập” và “Xuất”, với hai giá trị cho sẵn: Nhập, Xuất.

Tạo một View kiểu Detail cho bảng Thống kê, chỉ hiện 3 cột Từ ngày / Đến ngày / Loại (ẩn cột ID vì không cần người dùng thấy).

Viết công thức lọc kết quả Nhập theo khoảng ngày

Đây là phần đòi hỏi công thức phức tạp nhất. Tạo một cột ảo (virtual column) tên “Kết quả nhập” trong bảng Thống kê, dùng hàm FILTER kết hợp SELECT để lọc từ bảng Phiếu nhập chi tiết – nhưng vì ngày giao dịch nằm ở Phiếu nhập (bảng cha) chứ không phải ở phiếu chi tiết, nên công thức phải “nhảy” qua bảng cha để lấy ngày:

FILTER(
  "Phiếu nhập chi tiết",
  AND(
    [ID phiếu nhập].[Ngày] >= [_THISROW].[Từ ngày],
    [ID phiếu nhập].[Ngày] <= [_THISROW].[Đến ngày],
    IN("Nhập", [_THISROW].[Loại])
  )
)

Ban đầu công thức bị lỗi vì quên rằng phải đi qua tham chiếu [ID phiếu nhập].[Ngày] thay vì lấy trực tiếp cột Ngày (cột này không tồn tại ở bảng chi tiết). Sau khi sửa, cột ảo chạy đúng: lọc ra danh sách các dòng phiếu nhập chi tiết nằm trong khoảng Từ ngày – Đến ngày đã chọn.

Video P3 :Tự tay tạo app quản lý bán hàng bằng appsheet

Mặc định hiện hết khi chưa chọn ngày/loại

Muốn khi mở view lên là thấy toàn bộ dữ liệu (chưa cần chọn gì), nên bọc thêm điều kiện: nếu người dùng chưa chọn Loại thì luôn coi như đúng (TRUE), việc lọc chỉ áp dụng khi có chọn cụ thể. Dùng IF(ISBLANK([_THISROW].[Loại]), TRUE, IN("Nhập", [_THISROW].[Loại])) lồng vào điều kiện lọc phía trên.

Thêm cột ảo “Kết quả xuất” với logic tương tự nhưng đổi nguồn sang Phiếu xuất chi tiết và điều kiện IN("Xuất", ...).

Đưa cả hai cột ảo này vào view Thống kê – giờ chỉ cần chọn khoảng ngày và tick Nhập/Xuất là danh sách giao dịch tương ứng hiện ra ngay, không cần mở từng phiếu để dò.

Thêm cột Tổng giá trị nhập / Tổng giá trị xuất

Ngoài danh sách chi tiết, mình muốn có luôn con số tổng để biết nhanh giá trị nhập/xuất trong khoảng thời gian đó. Thêm hai cột ảo:

Tổng giá trị nhập = SUM(SELECT(Phiếu nhập chi tiết[Thành tiền], <cùng điều kiện lọc ngày & loại ở trên>))
Tổng giá trị xuất = SUM(SELECT(Phiếu xuất chi tiết[Thành tiền], <cùng điều kiện lọc ngày & loại ở trên>))

Kéo hai cột này lên đầu view Thống kê để dễ thấy. Muốn xem thêm tổng số lượng thì chỉ cần copy công thức, đổi Thành tiền thành Số lượng.

Bài toán khóa phiếu: không cho sửa/xóa khi đã hoàn tất

Cột Tình trạng (Đang mở / Đã khóa) đã có sẵn từ Phần 1, nhưng chưa gắn hành vi thực tế nào. Mục tiêu: khi người dùng bấm nút khóa, cả phiếu chính lẫn các dòng chi tiết bên trong đều không được sửa, xóa, hay thêm mới nữa.

Tạo Action “Khóa phiếu”

Ở bảng Phiếu nhập, tạo Action mới:

  • Kiểu: Data – set the value of a column → chọn cột Tình trạng, gán giá trị "Đã khóa".
  • Đặt hiển thị dạng inline, gắn (attach) vào cột Tên nhà cung cấp – vì cột này vốn đã ẩn khỏi bảng chính (chỉ chạy ngầm để tự động điền tên), nên gắn action vào đây sẽ khiến nút khóa hiện thẳng trên danh sách mà không chiếm thêm cột.
  • Icon chọn hình ổ khóa (lock) cho trực quan.
  • Vào Behavior, đặt điều kiện chỉ hiện nút này khi [Tình trạng] = "Đang mở" – phiếu đã khóa rồi thì nút biến mất, tránh bấm khóa lần hai.

Làm tương tự để tạo Action “Khóa phiếu xuất” cho bảng Phiếu xuất.

Ẩn nút Sửa/Xóa khi phiếu đã khóa

Vào Action mặc định Edit và Delete của Phiếu nhập, ở phần Behavior, thêm điều kiện [Tình trạng] = "Đang mở" – chỉ khi đang mở thì hai nút này mới hiện. Làm y hệt cho Phiếu xuất.

Khóa luôn cả phiếu chi tiết bên trong

Với Phiếu nhập chi tiết, muốn khi phiếu cha đã khóa thì dòng chi tiết cũng không sửa/xóa được. Vì cột Tình trạng nằm ở bảng cha, công thức Behavior phải tham chiếu qua Ref:

[ID phiếu nhập].[Tình trạng] = "Đang mở"

Đặt điều kiện này cho cả Edit và Delete của Phiếu nhập chi tiết. Làm tương tự cho Phiếu xuất chi tiết, tham chiếu qua [ID phiếu xuất].[Tình trạng].

Xử lý nút “Thêm mới” (Add) – nút hệ thống không ẩn được trực tiếp

Đây là phần rắc rối nhất: nút Add để thêm dòng chi tiết mới là nút do hệ thống AppSheet tự sinh, không thể gắn điều kiện Behavior để ẩn như các nút Edit/Delete thông thường. Vậy nên dù đã khóa phiếu, người dùng vẫn bấm “Thêm” và điền được dữ liệu vào dòng chi tiết mới.

Cách xử lý (mẹo): lợi dụng việc cột ID (Unique ID) của Phiếu nhập chi tiết là bắt buộc phải có giá trị mới lưu được. Đặt App Formula cho cột ID:

IF([ID phiếu nhập].[Tình trạng] = "Đã khóa", "", UNIQUEID())

Nghĩa là: nếu phiếu cha đã khóa, cột ID sẽ bị gán thành rỗng – mà ID là cột bắt buộc (Required), nên AppSheet sẽ chặn không cho lưu dòng mới. Người dùng vẫn mở được form “Thêm”, vẫn chọn được sản phẩm/số lượng, nhưng bấm Lưu sẽ báo lỗi và không ghi được dữ liệu – coi như phiếu đã “đóng băng” hoàn toàn.

Áp dụng công thức tương tự cho cột ID của Phiếu xuất chi tiết, tham chiếu qua [ID phiếu xuất].[Tình trạng].

Kiểm tra lại toàn bộ

Test kịch bản: mở một phiếu xuất đang “Đang mở” – vẫn sửa, xóa, thêm dòng chi tiết bình thường. Bấm nút khóa (icon ổ khóa) — trạng thái chuyển “Đã khóa”, nút Sửa và Xóa biến mất khỏi cả phiếu chính lẫn phiếu chi tiết. Thử bấm “Thêm” dòng chi tiết mới: vẫn chọn được sản phẩm, số lượng, đơn giá, nhưng khi Lưu thì hệ thống báo lỗi và không ghi nhận – đúng như mong muốn.

Kết luận

Sau Phần 3, app đã có thêm hai khả năng quan trọng:

  • Bộ lọc thống kê theo khoảng ngày và loại giao dịch (Nhập/Xuất), hiện luôn số lượng và tổng giá trị mà không cần mở từng phiếu để cộng tay.
  • Cơ chế khóa phiếu: một khi phiếu nhập/xuất đã được đánh dấu “Đã khóa”, toàn bộ dữ liệu – cả phiếu chính lẫn các dòng chi tiết – đều được bảo vệ khỏi sửa, xóa hoặc thêm mới ngoài ý muốn.

Ở phần tiếp theo, sẽ tập trung vào việc tinh chỉnh giao diện: chỉnh màu sắc, đổi tên các cột cho thân thiện, định dạng lại các view, và dựng một menu Home để gom các chức năng lại thành một app hoàn chỉnh, gọn gàng. Hẹn gặp lại các bạn ở phần sau!

Link xem trên Youtube: P3.Tự tạo phần mềm quản lý bán hàng nhập xuất tồn kho, quản lý công nợ và khách hàng bằng appsheet

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *