# Phương thức thanh toán

Danh mục dùng chung cho mọi sản phẩm: khai các phương thức thanh toán của tổ chức (tiền mặt,
chuyển khoản, thẻ, ví điện tử...) một chỗ, các màn thu tiền chỉ việc chọn.

## Khai phương thức

Mỗi phương thức gồm tên tự đặt, loại chuẩn hoá và thứ tự hiển thị. Tên là chữ khách thấy trên
màn thu tiền (ví dụ "Chuyển khoản VCB"), còn loại giúp báo cáo gom đúng bản chất dòng tiền dù
tên đặt kiểu gì. Phương thức tắt hoạt động sẽ không hiện ở màn thu tiền nhưng chứng từ cũ đã
thu bằng phương thức đó vẫn giữ nguyên.

## Ghi chú cho dev sản phẩm khi nối

Bảng `saas_payment_methods` chỉ là danh mục theo công ty; giao dịch của sản phẩm trỏ mềm
`payment_method_id` vào đây, không khoá ngoại. Lấy danh sách cho màn thu tiền qua scope
`PaymentMethod::activeForCompany($companyId)`. Nhóm menu đổi qua filter
`saas_payment_method_navigation_group`. Phần riêng từng sản phẩm (chi nhánh áp dụng, cấu hình
cổng thanh toán online) ở lại gói chức năng sản phẩm.

Công ty vừa lập thì gọi `PaymentMethod::seedDefaultsFor($companyId)` để có sẵn hai dòng Tiền mặt
và Chuyển khoản. Gọi lại nhiều lần không sinh dòng trùng, và không đụng tới phương thức công ty
đã tự sửa.

### Phiếu thu và loại phiếu

Model chứng từ nào nhận tiền thì gắn trait `ReceivesPayments`. Mỗi lần khách trả là một dòng
trong `saas_payments`, cột `kind` cho biết đó là loại nào:

| Giá trị | Nghĩa | Ảnh hưởng tới số đã thu |
|---|---|---|
| `payment` | khách trả tiền, đây là mặc định | cộng vào |
| `deposit` | đặt cọc trước | cộng vào, và đếm riêng qua `getDepositAmount()` |
| `refund` | trả lại tiền cho khách | trừ ra |

Số tiền luôn ghi số dương, dấu nằm ở loại phiếu. `getPaidAmount()` đã tự trừ phần hoàn nên sản
phẩm không phải nhớ trừ.

Cột `amount` là số nguyên **không âm**, đây là quyết định chứ không phải sót. Sổ tiền chỉ nhận số
dương, chiều tiền do loại phiếu nói. Gặp dữ liệu cũ có chứng từ mang số âm, ví dụ hoá đơn nhập từ
phần mềm khác, thì đừng đổi kiểu cột: dựng lại thành phiếu `refund` số dương, hoặc để sản phẩm xử
bằng chứng từ ghi có của mình rồi mới ghi phiếu thu sang đây. Ghi thẳng số âm là cơ sở dữ liệu chối,
và nó chối đúng.

Sản phẩm nào từ trước đã có ô khai tài khoản ngân hàng riêng thì **để tài khoản khai ở đây đè lên
ô cũ**, ô cũ chỉ còn là đường lùi cho công ty chưa bật gói. Hai chỗ khai lệch nhau là khách chuyển
vào một nơi còn cổng ngồi soi nơi khác: tiền về thật mà sổ vẫn báo chưa thu.

Cột `kind` là **chuỗi trần**, cố ý không đúc sang enum, vì gói dùng chung không biết trước sản
phẩm nào cần thêm loại nào. Sản phẩm nào trước đây đúc enum ở bảng riêng thì phải so bằng chuỗi khi
chuyển sang đây: `whereIn('kind', [PaymentKind::Deposit])` không khớp dòng nào và tiền cọc đọc ra
bằng không, trong khi không có lỗi nào báo. Dùng hằng số `Payment::KIND_DEPOSIT` cho chắc.

Số tiền có dấu đọc bằng thuộc tính `$payment->signed_amount`, không phải hàm.

`seedDefaultsFor()` đặt tên phương thức theo ngôn ngữ đang dùng, nên chỗ nào cần tra lại thì tra
theo `type` (`PaymentMethod::TYPE_CASH`, `TYPE_BANK_TRANSFER`), đừng tra theo tên.

Đừng ném lỗi trong hook `creating` của `Payment`. Khi tiền về từ cổng, phiếu thu được ghi bên
trong một giao dịch cơ sở dữ liệu, nên ném lỗi ở đó là huỷ cả lượt ghi nhận và đồng tiền ấy rơi
ra ngoài sổ trong khi nhà cung cấp vẫn gọi lại. Muốn chặn thu lố hay chặn chứng từ đã huỷ thì
chặn ở phiếu ghi tay, còn đường tự động cứ để tiền vào sổ rồi xếp vào mục chưa khớp.

Phiếu ghi tay mà bên gọi quên `created_by` thì gói tự điền người đang đăng nhập, vì chứng từ tiền
phải có người lập; phiếu cổng tự ghi thì để trống.

### Sổ Khoản thu chỉ lấy chứng từ tiền vào

Màn **Thanh toán › Khoản thu** là sổ phiếu thu của công ty. Bảng `saas_payments` chở cả tiền mình
trả người khác (cọc đơn mua trả nhà cung cấp) cùng loại phiếu `payment`, `deposit`, nên sổ chỉ lấy
phiếu gắn loại chứng từ đã khai **tiền vào** qua móc `saas_payment_payable_types`:

```php
add_filter('saas_payment_payable_types', fn (array $types) => $types + [
    (new Invoice)->getMorphClass() => [
        'label' => __('Invoice'),
        'direction' => 'in',
        'number' => fn (Invoice $doc): ?string => $doc->number,
        'number_column' => 'number',
        'party' => fn (Invoice $doc): ?string => $doc->customer?->name,
        'path' => fn (Invoice $doc): ?string => '/app/' . $doc->company_id . '/invoices/' . $doc->getKey(),
    ],
]);
```

- Không ghi `direction` thì coi là tiền vào; ghi `out` là tiền ra, không vào sổ.
- Loại **chưa khai** thì phiếu không vào sổ, ô số, tệp xuất, cả sổ ở panel. Thà vắng một phiếu
  (khai là về) còn hơn cộng tiền trả nhà cung cấp thành tiền thu.
- Khai ở gói giữ lớp của tờ, đừng khai ở gói vệ tinh: gói tắt thì lời khai tắt theo, phiếu của loại
  ấy vắng khỏi sổ.
- Tự cộng tiền trên `saas_payments` thì lọc `payable_type` hoặc đi qua scope
  `Payment::onIncomingDocuments()`; cộng trần cả bảng là tiền trả nhà cung cấp bị đếm thành tiền bán.

### Ô tìm của sổ nhận cả số tờ và tên bên kia

Gõ số chứng từ vào ô tìm của sổ **Khoản thu** hay **Phiếu chi** là ra mọi phiếu gắn tờ ấy: gõ
`HD-0120` ra bốn phiếu của hoá đơn đó, gõ số đơn mua ra các phiếu chi của đơn. Gõ **tên khách hàng**
hay **tên nhà cung cấp** cũng ra phiếu của các tờ mang tên ấy. Ô tìm vẫn nhận số phiếu và mã giao
dịch như trước.

- Số hiệu tờ đọc ở cột `number_column` của bảng gốc, mặc định là `number`; bảng nào đặt tên cột khác
  thì khai lại trong lời khai loại chứng từ.
- Tên bên kia đọc qua `party_relation` (quan hệ tới khách hàng hay nhà cung cấp) và cột
  `party_name_column`, mặc định `name`. Không khai quan hệ thì sổ chỉ tìm theo số tờ.
- Bên kia **đã xoá mềm** vẫn tìm ra, vì cột *Khách hoặc người nộp* của sổ vẫn bày tên họ.
- Loại chứng từ **chưa nạp lớp** (gói đang tắt), bảng **không có cột** ấy hay **không có quan hệ** ấy
  thì phần đó vắng khỏi phép tìm, sổ vẫn chạy bình thường.

### Số phiếu và tờ in theo chiều tiền

- Phiếu gắn chứng từ tiền vào đi dãy **PT** (`payment`). Phiếu gắn chứng từ khai `out` (đơn mua trả
  nhà cung cấp) đi dãy **PC** chung với phiếu chi của gói Chi phí (`expense`), chủ sản phẩm chốt
  15/09/2026. Loại chưa khai vẫn đi dãy PT, nên sản phẩm muốn phiếu trả nhà cung cấp mang số PC thì
  phải khai loại tờ của mình với `direction` `out`. Phiếu đã có số giữ nguyên số cũ.
- Ba loại phiếu của một chiều vẫn đi chung một dãy: tiền trả, tiền cọc, trả lại.
- Tờ in theo chiều tiền thật (`$payment->paysOut()`): tiền rời công ty in **phiếu chi** mẫu 02-TT
  (trả nhà cung cấp, trả lại tiền khách), tiền vào in **phiếu thu** mẫu 01-TT (khách trả, nhà cung
  cấp trả lại tiền).

## Phân quyền

Nhóm quyền Phương thức thanh toán cấp cho vai trò Quản lý khi tạo tổ chức mới; tổ chức có sẵn
thì chủ tổ chức vào Phân quyền tự tick.

## Tài khoản nhận tiền

Màn **Tài khoản nhận tiền** giữ các tài khoản ngân hàng công ty dùng để nhận tiền của khách. Nó
phục vụ việc in thông tin chuyển khoản lên hoá đơn, sinh mã QR chuyển khoản, và về sau là đối
chiếu tiền vào khi bật cổng thanh toán tự động.

Ngân hàng chọn từ **danh mục dùng chung**, không gõ tay. Hệ nhận diện ngân hàng bằng mã BIN nên
ngân hàng có đổi tên thì tài khoản của bạn vẫn trỏ đúng chỗ.

- **Số tài khoản**: chỉ gồm chữ cái và chữ số, không có khoảng trắng, vì thư báo tiền về của ngân
  hàng cũng ghi liền như vậy, để lệch một dấu cách là đối chiếu trượt.
- **Chủ tài khoản**: ghi đúng như ngân hàng hiển thị, viết không dấu.
- **Tên gọi**: đặt cho dễ phân biệt khi có nhiều tài khoản, thường là tên chi nhánh.
- **Tài khoản mặc định**: dùng khi chứng từ không chỉ định tài khoản nào. Mỗi công ty chỉ có một
  tài khoản mặc định, đặt cái mới là cái cũ tự nhường chỗ.

Công ty nhiều chi nhánh khai mỗi nơi một tài khoản đều được, không giới hạn số lượng.

Tài khoản đã xoá vẫn nằm trong thùng rác nên phiếu thu cũ không mất dấu vết; muốn ẩn khỏi màn thu
tiền mà giữ nguyên dữ liệu thì tắt **Đang hoạt động**.
