James Perry, Richard Newmark
Chương 8
Qui trình bán hàng - thu tiền
Form nhập liệu thâu ngân Cash Receipt Entry
Khi kế toán viên của Pipefitters nhận một chi phiếu từ khách hàng, họ phải có khả năng so sánh số tiền nhận được cho một hóa đơn cụ thể với dư nợ (balance due) trên đợt bán đó. Nếu số tiền thu ít hơn trị giá bán hàng, kế toán viên phải kiểm tra xem khách hàng được phép chi trả từng phần hay không. Nếu số tiền thu nhiều hơn dư nợ, kế toán viên phải tìm lý do tại sao có khác biệt đó. Ngoài ra, sẽ hữu ích khi thấy lịch sử chi trả của khách hàng đối với hóa đơn liên quan đến đợt thâu ngân hiện thời. Vì thế, bạn sẽ tạo một truy vấn cho form để tính dư nợ hiện thời theo hóa đơn. Dư nợ sẽ được dùng trong form nhập liệu thâu ngân Cash Receipt Entry như một kiểm soát. Vì truy vấn dư nợ phải được chạy lại để cân đối khoản nợ, bạn sẽ thêm một nút vào form để cập nhật dư nợ. Nếu không, dư nợ sẽ không cập nhật cho đến khi form được đóng và mở lại.
BÀI TẬP 8.40: TẠO TRUY VẤN ĐỂ TÍNH DƯ NỢ HÓA ĐƠN – TỔNG NHỮNG LẦN THÂU NGÂN TRƯỚC
Trong bài tập này bạn sẽ tạo truy vấn đầu tiên trong hai truy vấn. Truy vấn thứ nhất sẽ dùng một
hàm gộp (aggregate function) để tính tổng số tiền đã nhận cho từng hóa đơn. Truy vấn thứ hai (Bài tập 8.41) sẽ dùng
tính toán hàng ngang (horizontal computation) để trừ tổng số tiền đã nhận ra khỏi trị giá hóa đơn để được dư nợ. Cần hai truy vấn vì hàm gộp sẽ kết hợp (trong trường hợp này là tính tổng) nhiều giá trị trong một cột (một trường thuộc nhiều bản ghi), và phải có trước khi tính toán hàng ngang dùng số liệu gộp này để thực hiện một tính toán với nhiều trường trên cùng một dòng. Vì thế, quy tắc chung trong cơ sở dữ liệu là thực hiện các hàm gộp và tính toán hàng ngang trong các truy vấn riêng.
1. Kích
CREATE tab rồi kích
Query Design trong Queries group. Kích kép
tblCashReceipt trong hộp thoại Show Table. Đóng hộp thoại.
2. Kích kép
InvoiceID và
CashReceiptAmount từ danh sách trường trong tblCashReceipt.
3. Kích
Totals (ký hiệu tổng) trong nhóm Show/Hide. Vì bạn muốn tính tổng số tiền đã nhận cho từng đợt bán, hãy để nguyên ô Total cho InvoiceID là
Group By. Đổi ô Total cho CashReceiptAmount thành
Sum.
4. Mở
Property Sheet. Kích Property Sheet trong nhóm Show/Hide. Gõ
Prior Receipts làm phụ đề Caption cho tổng những lần thâu ngân. Đóng Property Sheet.
5. Lưu truy vấn với tên
qrySumOfCashReceiptsByInvoice.
6. Thi hành truy vấn. Bạn cần có 79 hóa đơn với những lần thâu ngân trước. Đóng truy vấn.
BÀI TẬP 8.41: TẠO TRUY VẤN ĐỂ TÍNH DƯ NỢ HÓA ĐƠN – TÍNH DƯ NỢ
1. Tạo truy vấn mới với
Query Design. Kích kép
tblSale trong hộp thoại Show Table, kích
Queries tab, rồi kích kép
qrySumOfCashReceiptsByInvoice. Đóng hộp thoại.
2. Kích kép liên kết giữa tblSale và qrySumOfCashReceiptsByInvoice. Kích nút radio thứ hai trong hộp thoại Join Properties (xem Hình 8.48). Kích
OK để đóng. Để ý mũi tên trỏ từ bảng trái sang bảng phải. Cách này gọi là
nối ngoại trái (left outer join). Ta sẽ thảo luận về tầm quan trọng của nó ngay sau đây.
Hình 8.48. Hộp thoại nối thuộc tính Join Properties.
3. Kích kép
InvoiceID,
SaleAmount, và
CustomerID từ
tblSale trong Table Pane; kích kép
SumOfCashReceiptAmount trong
qrySumOfCashReceiptsByInvoice.
4. Lưu truy vấn với tên
qryBalanceDueFromCustomer.
5. Kích trường Field trống đầu tiên trên Criteria Pane. Kích
Builder trong nhóm Query Setup. Nhập
BalanceDue: [SaleAmount]-Nz([SumOfCashReceiptAmount],0). Ở Bước 2, bạn đã tạo một phép nối ngoại (outer join) sao cho mọi hóa đơn trong
tblSale sẽ được chọn cho dù không có lần thâu ngân nào tương ứng, điều này thường xảy ra với những đợt bán hiện thời vì khách hàng chưa chi trả.
Nz là hàm
Null-to-zero (chuyển rỗng thành 0). Nếu chưa có chi trả nào ứng với một đợt bán, giá trị của SumOfCashReceiptAmount sẽ bằng
null (rỗng), từ đó sẽ ngăn Access tính hiệu số. Hàm Nz sẽ thay giá trị null bằng tham biến thứ hai trong hàm, trường hợp này là 0 để tính toán có được kết quả hợp lệ.
6. Mở Property Sheet trong nhóm Show/Hide. Gõ
Balance Due làm phụ đề Caption cho trường BalanceDue mới tạo.
7. Kích kép
ShippingDate từ
tblSale trong Table Pane. Đặt Caption trên Property Sheet là
Invoice Date.
8. Lưu truy vấn rồi thi hành nó. Để ý có 90 hóa đơn – 79 hóa đơn đầu tiên có dư nợ 0 (giống 79 hóa đơn từ
qrySumOfCashReceiptsByInvoice) và 11 hóa đơn cuối chưa được chi trả (không có lần thâu ngân nào gắn với chúng).
Đóng truy vấn.
BÀI TẬP 8.42: TẠO FORM NHẬP LIỆU THÂU NGÂN CASH RECEIPT ENTRY
Form nhập liệu thâu ngân Cash Receipt Entry sẽ dùng thiết kế form/subform. Phần đầu của form nhập liệu thâu ngân Cash Receipt Entry sẽ chứa dữ liệu liên quan đến hóa đơn từ
qryBalanceDueFromCustomer. Không thể sửa trường nào ở đây vì chúng chỉ để tham khảo. Form chính còn hiển thị thông tin khách hàng (chẳng hạn tên và địa chỉ) mà bạn sẽ thêm vào
sau khi chạy Form Wizard vì Form Wizard sẽ thêm thông tin khách hàng vào subform. Đây là vấn đề vì subform chỉ nên chứa các trường từ
tblCashReceipt. Các trường CustomerID và InvoiceID sẽ được liên kết với form chính để tự động đổ dữ liệu vào các trường subform này, đảm bảo rằng việc thâu ngân được ghi nhận đúng theo khách hàng và hóa đơn. Việc dùng dữ liệu bán hàng trong
qryBalanceDueFromCustomer sẽ đóng vai trò kiểm soát vì các lần thâu ngân nhập vào form phải liên kết với các đợt bán có mặt trong
tblSale.
1. Kích
Form Wizard trong nhóm Forms trên CREATE tab. Kích
Query: qryBalanceDueFromCustomer trong Tables/Queries combo box. Kích
>> để chọn tất cả các trường từ truy vấn.
2. Kích mũi tên xuống của Tables/Queries combo box, rồi kích
Table: tblCashReceipt từ danh sách. Kích
>> để chuyển tất cả các trường từ Available Fields sang danh sách Selected Fields.
3. Kích
Next. Kích
qryBalanceDueFromCustomer trong ô danh sách
How do you want to view your data? (nếu nó chưa được chọn) để đảm bảo việc gom nhóm đúng.
4. Kích
Next. Chọn
Datasheet cho định dạng subform.
5. Kích
Next. Kích kép ô
Form, gõ
frmCashReceipt để đặt tên form, tab sang ô Subform rồi gõ
fsubCashReceipt. Kích nút
Finish. Đóng form.
BÀI TẬP 8.43: HOÀN THÀNH FORM NHẬP LIỆU THÂU NGÂN CASH RECEIPT
Thay đổi trên subform.
1. Mở
fsubCashReceipt ở Design View. Đổi nhãn của CashReceiptAmount thành
Amount, đổi nhãn của CashReceiptDate thành
Date, đổi nhãn của CashAccountID thành
Cash Acct. #.
2. Các giá trị CustomerID và InvoiceID sẽ được gán nhờ liên kết giữa subform và form. Hãy làm chúng không thay đổi được như đã làm ở Bài tập 8.26.
3. Hợp lý hóa giao diện subform. Chọn
Form từ Property Sheet combo box. Trên Format tab, đổi thuộc tính Navigation Buttons thành
No, và đổi thuộc tính Scroll Bars thành
Neither. Lưu các thay đổi.
4. Điều chỉnh độ rộng cột của subform datasheet. Chuyển sang
Datasheet View. Kích
Datasheet Selector (xem Hình 8.49), kích
More menu trong nhóm Records trên dải HOME, chọn
Field Width, rồi kích nút
Best Fit để làm đầu đề cột và dữ liệu đều khả kiến. Lưu và đóng subform.
Hình 8.49 fsubCashReceipt ở Datasheet View.
Thêm thông tin khách hàng vào form.
5. Mở
frmCashReceipt ở góc nhìn Design và mở
Property Sheet. Chọn
Form từ Property Sheet combo box rồi kích Data tab. Kích nút Query Builder (dấu ba chấm) trong thuộc tính Record Source. Kích
Show Table trong nhóm Query Setup, rồi thêm
qryCustomerInfo vào Table Pane. Liên kết
qryCustomerInfo với
tblSale bằng cách kích và kéo
CustomerID từ
qryCustomerInfo đến
CustomerID trong
tblSale. Nếu quan hệ vừa tạo không trực tiếp trỏ đến 2 bảng, kích kép quan hệ nhằm mở Join Properties để sửa sai.
6. Thêm các trường sau vào Criteria Pane:
CustomerName,
CustomerAddress1,
CustomerAddress2,
CityStateZip,
CustomerTelephone, và
CustomerPrimaryContact. Đóng và lưu các thay đổi. Mở
qryBalanceDueFromCustomer ở Datasheet View. Để ý rằng các trường bạn đã thêm vào truy vấn từ trong form đã thay đổi thường trực qryBalanceDueFromCustomer. Nhớ rằng bất kỳ thay đổi bạn tạo trong truy vấn sẽ tác động đến forms và các đối tượng cơ sở dữ liệu nào sử dụng truy vấn đó.
7. Sao chép các thành phần điều khiển từ
frmSale. Mở
frmSale ở
Design View. Chọn các thành phần điều khiển cho các trường mà bạn vừa thêm vào truy vấn Record Source của form, và nhãn Primary Contact bằng cách nhấn và giữ phím
Shift rồi kích các thành phần điều khiển. Nhấn
Ctrl+C, trở về
frmCashReceipt, di chuyển subform xuống dưới 2,5cm (1 inch), kích phần Detail, rồi kích
Ctrl+V, canh trái nhãn
Primary Contact. Đóng frmSale. Hãy dùng Hình 8.50 làm hướng dẫn.
Hình 8.50 Form nhập liệu thâu ngân Cash Receipt Entry ở Design View với Subform Field Linker đang mở.
8. Làm tất cả các thành phần điều khiển mà không phải khách hàng thì không thay đổi được như đã làm ở Bài tập 8.26. Nếu chọn tất cả 6 thành phần điều khiển, bạn có thể đồng thời thay đổi thuộc tính của tất cả các thành phần điều khiển này.
9. Liên kết CustomerID từ subform đến form. Chọn
fsubCashReceipt từ Property Sheet combo box, kích Data tab. Kích thuộc tính Link Master Fields rồi kích nút
Builder để mở Subform Field Linker. Thêm
CustomerID vào cả 2 cột Master Fields và Child Fields (xem Hình 8.50). Kích
OK.
10. Kết thúc việc soạn thảo form bằng cách dùng Hình 8.50 làm hướng dẫn. Canh trái dữ liệu hóa đơn. Hơn nữa, bạn sẽ cần định cỡ subform và có thể khớp tự động (autofit) các cột một lần nữa (bạn có thể làm bên trong
frmCashReceipt). Hãy bỏ qua nút lệnh trên form. Bạn sẽ thêm nó vào ở bài tập kế.
11. Lưu form. Xem form ở
Form View. Để ý Customer # và Invoice # sẽ khớp với các dòng giấy báo chuyển tiền khi chuyển đến các bản ghi tiếp theo.
BÀI TẬP 8.44: DÙNG MACRO ĐỂ CẬP NHẬT DƯ NỢ TRONG FORM NHẬP LIỆU THÂU NGÂN CASH RECEIPT ENTRY
Tạo macro cập nhật.
1. Từ CREATE tab, kích
Macro trong nhóm
Macros & Code. Bạn sắp sửa tạo macro một-hành-động (one-action macro), tên là
Requery, sẽ thi hành truy vấn bên trong đối tượng đang hoạt động là
frmCashReceipt. Nhớ rằng lệnh này sẽ trở về bản ghi đầu tiên trong form. Việc trở về bản ghi hiện thời sẽ cần kỹ năng lập trình vượt quá phạm vi của tài liệu này. Gõ
Requery vào Add New Action combo box rồi nhấn phím Enter. Đừng thêm gì vào ô Control Name.
2. Đóng macro và đặt tên là
mcrRerunQuery. Để ý rằng ta đã dùng
mcr để ký hiệu các macros.
3. Mở
frmCashReceipt ở Design View. Trên dải DESIGN, kích
Button trong nhóm Controls. Di chuyển con trỏ đến vị trí nút ở Hình 8.50 rồi
kích kép để khởi động Command Button Wizard.
4. Kích
Miscellaneous trong danh sách Categories, kích
Run Macro trong danh sách Actions, rồi kích
Next.
5. Vì
mcrRerunQuery là macro duy nhất, nên nó đã được chọn, vì thế chỉ cần kích
Next. Kích nút radio
Text rồi gõ
Update Balance Due vào ô văn bản. Kích
Next.
6. Đặt tên nút là
cmdUpdateBalanceDue. Định cỡ và di chuyển nút nếu cần. Lưu rồi đóng form.
THỬ NGHIỆM
Hãy kiểm thử nút Update Balance Due trong
frmCashReceipt. Kích kép
frmCashReceipt trong Navigation Pane. Đến bản ghi cuối cùng. Trị giá hóa đơn Amount là $786.35 và chưa có chi trả trước đó nên dư nợ Balance Due là $786.35. Thử thêm bản ghi sau: RA #
999999, Cash Acct.
101, Employee #
120, Amount
$500, Customer Check #
7777, và Date
9/9/2012. Kích nút
Update Balance Due. Để ý rằng form trở về bản ghi đầu tiên. Hãy đến bản ghi cuối cùng. Các lần thâu ngân trước đây Prior Receipts bây giờ là $500.00 và dư nợ Balance Due đã được cập nhật thành $286.35. Xóa RA #999999 bằng cách kích
nút chọn bản ghi (record selector) rồi nhấn phím
Delete.