Point history
Bối cảnh
Trên Shukah, app đọc toàn bộ lịch sử điểm của client bằng một lời gọi,
GET /maeda/client/point-history: trên dev, 8,134 dòng của client test trả về trong một mảng
(8,136 vào 2026-10-02).
GET /api/v2/client/point-history của Locate trả về cùng hai shape dòng, nhưng mỗi lần một trang:
mặc định 20 dòng và tối đa 100. App không gửi page hay limit, nên sau khi chuyển
nó chỉ thấy 20 dòng mới nhất. Có ba điều khác cần chú ý: id của một dòng expense là chuỗi 24 ký tự,
nhiều dòng earn có description rỗng, và Locate liệt kê mọi dòng ledger,
kể cả các dòng reversal và các dòng không làm thay đổi số dư.
Tính năng
Lịch sử là danh sách các giao dịch điểm của client. Trong snapshot app ngày 2026-02-26 có hai
màn hình dùng nó. Chúng dùng chung một lời gọi, không gửi page hay limit:
| Ở đâu trong app | Nó làm gì |
|---|---|
| Màn hình Wallet | Danh sách "last transactions" gọi nó khi màn hình mở và hiển thị 3 dòng đầu của câu trả lời. |
| Màn hình Wallet history | Danh sách đầy đủ gọi nó khi màn hình mở và khi pull-to-refresh, và hiển thị toàn bộ câu trả lời. |
App cũng tải lại lịch sử sau khi nó đổi một gift-card code và sau khi một món quà được thanh toán.
Hiện nay trên dev chỉ có token Shukah chạy: một JWT Locate nhận 401 Invalid or expired token trên route
này vào 2026-10-02, dù cả hai token đều chạy trên route balance vào 2026-10-01 (xem
Which tokens work). order-v2 chuyển lời gọi sang point
service và trả câu trả lời không đổi.
Phân trang. page bắt đầu từ 1 và limit mặc định là 20, tối đa 100. Câu trả lời là một
mảng trần. Nó không có total, không có marker "next page" và không có header phân trang, nên app phải tiếp tục
hỏi cho đến khi một trang trả về ít dòng hơn limit. Các dòng được sắp theo thời điểm tạo, mới nhất trước,
và các dòng có cùng thời điểm tạo không có thứ tự cố định, nên một dòng có thể di chuyển giữa các trang.
Hai shape dòng. Rẽ nhánh theo points_type. Một dòng earn có 7 key và một dòng expense có 14.
Những gì có thể có trong danh sách. Service không lọc gì cả:
- Dòng quà tặng. Một món quà thanh toán bằng điểm ghi một dòng expense cho người gửi và một dòng earn cho người nhận. Một món quà thanh toán bằng thẻ ghi dòng earn cho người nhận khi khoản thanh toán được capture.
- Dòng hết hạn. Shukah ghi một lần hết hạn dưới dạng dòng âm. Các dòng copy từ lịch sử của Shukah
giữ dạng đó: một dòng earn với
total_pointsâm. Các lần hết hạn từ 2026-09-16 và những lần do job của chính Locate tạo là dòng expense với số tiền dương. - Dòng reversal. Admin có thể đảo ngược một giao dịch. Điều đó thêm một dòng mới thuộc loại ngược lại
với cùng số tiền, và dòng gốc vẫn còn. Không có gì đánh dấu nó: nó trông như bất kỳ dòng earn hay
expense nào, và text của nó bắt đầu bằng
reversal of. App không bao giờ tạo ra một dòng như vậy. - Các dòng không được tính. Một dòng từ Shukah mà status không phải active, và reversal của
một dòng như vậy, được lưu là không tính. Nó không làm thay đổi số dư, nhưng vẫn được liệt kê với
total_pointsbình thường. Một dòng expense loại đó vẫn ghi"status": "active".
GET /api/v2/client/point-history
GET /maeda/client/point-history✅ Đã thay thế- 🔴 Locate phân trang 20 dòng (tối đa 100); Shukah gửi cả 8,136; app không gửi tham số phân trang nên dừng ở 20.
- 🔴 Không có tổng số hay dấu trang kế; hãy lặp với page và limit (mặc định 20, tối đa 100) đến khi gặp trang ngắn.
- 🟡 Dòng chi tiêu: 14 key, total_points "360.00" (chuỗi), không có shukah_id; app đọc 5 key và hiển thị nó.
- 🟡 8 trên 9 dòng cộng điểm có description "" (Shukah có chữ); app hiển thị một dòng trống dưới ngày.
- 🟡 Dòng mới nhất của Locate là 2026-09-29 12:45:07 (id 1351722); của Shukah là 2026-10-01 17:00:01 (id 1351767).
- 🟡 Các dòng cùng date_created không có thứ tự cố định giữa các trang; keyExtractor của app là date + points.
- 🟡 JWT của Locate nhận 401 trên dev; hãy gửi token của Shukah.
Request
| Field | Vị trí | Kiểu | Bắt buộc | Ràng buộc | Mô tả |
|---|---|---|---|---|---|
Authorization | header | string | có | Bearer <token>: một token Shukah trên dev hiện nay. Một JWT Locate nhận 401 Invalid or expired token (capture trên dev, 2026-10-02): xem Which tokens work. | Token của chính client. Client id lấy từ nó. |
page | query | integer | không | Mặc định 1. Một số nguyên dương sau khi text được chuyển thành số. | Trang, đếm từ 1. |
limit | query | integer | không | Mặc định 20. Một số nguyên dương, tối đa 100. | Số dòng mỗi trang. |
language | query | string | không | Được chấp nhận và bỏ qua. App thêm nó vào mọi lời gọi. | Giữ lại để query string Shukah cũ vẫn chạy. |
Các giá trị được chuyển thành số trước khi kiểm tra, nên 1e1 là 10 và " 2 " là 2. page=
hoặc limit= rỗng, 0, giá trị âm, 1.5 và abc bị từ chối với 400.
Response
200 với một mảng trần, mới nhất trước. Nó là [] khi trang vượt quá cuối.
Dòng earn (points_type là earn), 7 key theo thứ tự này:
| Field | Kiểu | Nullable | Định dạng / ràng buộc | Mô tả |
|---|---|---|---|---|
shukah_id | integer | có | Id của Shukah cho dòng khi có. null cho các dòng do chính Locate ghi. | Id dòng phía Shukah. |
total_points | number | không | Số JSON. Âm trên các dòng hết hạn cũ. | Điểm được cộng. |
date_created | string | không | YYYY-MM-DD HH:mm:ss, giờ đồng hồ Asia/Riyadh, không có dấu múi giờ. | Khi dòng được tạo. |
description | string | không | "" khi không có text. 8 trong 9 dòng earn trong 10 dòng đầu là "" vào 2026-10-02, và một dòng là manual credit. | Text tự do của dòng. |
message | string | không | Luôn là "". | Không dùng. |
points_type | string | không | Luôn là "earn". | Loại dòng. |
trans_type | string | không | adjustment trên mọi dòng đã capture. Khi dòng không có type, là adjustment. | Loại giao dịch của Shukah. |
{
"shukah_id": 1351722,
"total_points": 60,
"date_created": "2026-09-29 12:45:07",
"description": "",
"message": "",
"points_type": "earn",
"trans_type": "adjustment"
}
Capture trên dev, 2026-10-01 (client 356259, page=1&limit=5): dòng đầu tiên trong năm dòng.
Dòng expense (points_type là expenses), 14 key theo thứ tự này:
| Field | Kiểu | Nullable | Định dạng / ràng buộc | Mô tả |
|---|---|---|---|---|
id | string | không | Id hex 24 ký tự của dòng ledger. Của Shukah là một số. | Id dòng. |
client_id | integer | không | Người gọi. | Client id. |
merchant_id | integer | không | 0 khi không có merchant. | Merchant. |
order_id | integer | không | 0 khi không có order. | Order. |
total_points | string | không | Chính xác hai chữ số thập phân, ví dụ "360.00". Lưu ý một dòng earn gửi một số. | Điểm đã tiêu. |
status | string | không | Luôn là "active", kể cả với một dòng không được tính. | Status của dòng. |
date_created | string | không | YYYY-MM-DD HH:mm:ss, Asia/Riyadh. | Khi dòng được tạo. |
ip_address | string | không | Luôn là "". | Không dùng. |
total_points_amt | number | không | Giá trị SAR của điểm, 0.25 SAR mỗi điểm (360 điểm cho 90). 0 khi chưa đặt. | Giá trị tính bằng SAR. |
trans_type | string | không | order trên dòng đã capture. Khi dòng không có type, là order. | Loại giao dịch. |
points_type | string | không | Luôn là "expenses". | Loại dòng. |
remarks | string | không | Cùng text với description. | Text tự do. |
external_id | null | có | Luôn là null. | Không dùng. |
description | string | không | "" khi không có text. | Text tự do của dòng. |
{
"id": "6ab5fee68fd829e4e33785f9",
"client_id": 356259,
"merchant_id": 0,
"order_id": 0,
"total_points": "360.00",
"status": "active",
"date_created": "2026-09-25 07:56:06",
"ip_address": "",
"total_points_amt": 90,
"trans_type": "order",
"points_type": "expenses",
"remarks": "You have sent a gift Graduation of 300 points to Test User (*****0000) #100004",
"external_id": null,
"description": "You have sent a gift Graduation of 300 points to Test User (*****0000) #100004"
}
Capture trên dev, 2026-10-01 (client 356259, page=1&limit=100): dòng expense duy nhất trong mười
dòng đầu được lưu; tên người nhận và các chữ số phone đã được thay thế. Đó là một món quà 300 điểm
tốn của người gửi 360 điểm.
Text của quà tặng. Các dòng mà Locate ghi cho một món quà có nội dung You have sent a gift … to <name> (*****<last 4 digits>) #<order number> cho người gửi, và You have received a gift … from … cho
người nhận. Text theo ngôn ngữ của chủ sở hữu. Với chủ sở hữu có ngôn ngữ là tiếng Ả Rập, text
đến từ một template trong point settings, và template trống để description rỗng. Template có được
điền trên dev hay production hay không: Chưa được tài liệu hóa.
Lỗi
| HTTP | Body | Khi nào |
|---|---|---|
400 | {"success":false,"error":{"code":"VALIDATION_ERROR","message":"Invalid query","details":{"formErrors":[],"fieldErrors":{"limit":["Number must be less than or equal to 100"]}}}} | page hoặc limit không qua được kiểm tra. Ví dụ là cho ?limit=101, từ một lần chạy local của schema của service, không capture live. Các message cho giá trị khác là Number must be greater than 0, Expected integer, received float và Expected number, received nan. |
401 | {"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing or invalid authorization header"}} | Không có header Authorization, hoặc nó không bắt đầu bằng Bearer . Đã capture trên dev, 2026-10-01, khi không có token. |
401 | Cùng shape, với message là Invalid or expired token, auth service unreachable: <error text> hoặc auth response missing numeric client id. | Auth service từ chối token, không kết nối được (sự cố auth trông giống token xấu), hoặc trả lời mà không có client id. Invalid or expired token đã được capture trên dev, 2026-10-02, với một JWT Locate. |
500 | {"success":false,"error":{"code":"INTERNAL_ERROR","message":"Internal server error"}} | Bất kỳ lỗi không mong đợi nào trong point service, ví dụ lỗi database. Message là AUTH_SERVICE_URL not set khi service bị cấu hình sai. Chưa capture. |
502 | {"success":false,"error":{"code":"POINT_SERVICE_UNAVAILABLE","message":"Point service unavailable: <error text>"}} | order-v2 không kết nối được point service. Body này đến từ order-v2, không phải từ point service. Chưa capture. |
504 | {"success":false,"error":{"code":"POINT_SERVICE_TIMEOUT","message":"Point service did not respond in time; the request outcome is unknown"}} | Point service không trả lời trong 10 giây. Body này đến từ order-v2. Chưa capture. |
Mọi lỗi từ point service đều có envelope {"success":false,"error":{"code":"…","message":"…"}}.
Thử ngay
export ORDER_BASE_URL=https://dev.v2.api.order.locate.sa
export SHUKAH_TOKEN='<shukah-token>' # a Locate JWT gets 401 here today; see "Which tokens work" on Points wallet
curl -s "$ORDER_BASE_URL/api/v2/client/point-history?page=1&limit=5" -H "Authorization: Bearer $SHUKAH_TOKEN"
Kỳ vọng: 200 và một mảng tối đa năm dòng, mới nhất trước. Hãy dùng token Shukah trên dev hiện nay: một
JWT Locate nhận 401 Invalid or expired token (2026-10-02). Với limit=101 bạn nhận 400 như ở mục
Lỗi.
Khác biệt so với Shukah
| Khía cạnh | Shukah | Locate | Tác động lên app |
|---|---|---|---|
| URL | GET $SHUKAH_BASE_URL/maeda/client/point-history | GET $ORDER_BASE_URL/api/v2/client/point-history | Đổi base URL và path. |
| Token | Token opaque của Shukah. | Chỉ token Shukah trên dev hiện nay. Một JWT Locate nhận 401 (capture trên dev, 2026-10-02). | App phải tiếp tục gửi token Shukah ở đây. Với các môi trường khác: Chưa được tài liệu hóa. |
| Phân trang | Toàn bộ lịch sử trong một mảng: 8,134 dòng cho client 356259 (capture trên dev, 2026-10-01, 2.3 s), 8,136 vào 2026-10-02. | Mặc định 20 dòng, tối đa 100 (limit=100 trả 100 dòng trên dev). Không có total và không có marker next-page. | App không gửi page hay limit, nên nó chỉ hiển thị 20 dòng mới nhất. Nó phải phân trang cho đến khi một trang ngắn hơn limit. |
id của dòng expense | Một số (báo cáo parity tháng 7; không có dòng expense trong capture đã lưu của Shukah). | Một chuỗi 24 ký tự (capture trên dev, 2026-10-01). | Không có với app hiện nay: type lịch sử của nó không có id hay shukah_id. |
| Key của dòng earn | 7 key. | Cùng 7 key theo cùng thứ tự (capture trên dev, 2026-10-01). | Không có. |
description của earn | Text như Points gained by buy item Order ID L07678739 trên các dòng mới nhất của Shukah. | "" trên 8 trong 9 dòng earn trong 10 dòng đầu, manual credit trên một dòng (capture trên dev, 2026-10-02). Hai phía không chung id dòng nào trong các dòng mới nhất, nên các dòng giống nhau không được so sánh. | App sẽ hiển thị một dòng trống cho các dòng không có text. Các bản copy của chính Shukah của những dòng đó có text hay không: Chưa được tài liệu hóa. |
| Dòng mới nhất | 2026-10-01 17:00:01, shukah_id 1351767 (capture trên dev, 2026-10-02). | 2026-09-29 12:45:07, shukah_id 1351722: kém 45 Shukah id và cũ hơn khoảng hai ngày (suy luận: bản copy từ Shukah bị trễ). | Một giao dịch thực hiện trong những ngày gần đây có thể thiếu trong danh sách. Feed trên dev có cập nhật hay không: Chưa được tài liệu hóa. |
| Số tiền earn | total_points là 2, 2, 2, 2, 10 trên các dòng mới nhất (capture trên dev, 2026-10-02). | 2, 2, 2, 10, 60 trên các dòng mới nhất. | Không có: cùng thang đo. Vào 2026-10-01 các dòng mới nhất của Shukah là 0.5, 0.5, 2.5, 0.5, 4, trông như một thang đo khác. |
| Dòng hết hạn | Một dòng earn âm. | Một dòng expense với số tiền dương cho các lần hết hạn từ 2026-09-16. Các dòng cũ hơn là dòng earn âm. | Nếu app cộng hoặc tô màu dòng theo points_type và dấu, các lần hết hạn trông khác. |
| Dòng reversal và không được tính | Shukah có liệt kê chúng hay không: Chưa được tài liệu hóa. | Được liệt kê như các dòng bình thường. | App có thể hiển thị một dòng chưa bao giờ làm thay đổi số dư. |
status của expense | Có (báo cáo parity tháng 7 năm 2026); chưa capture giá trị. | Luôn là "active". | Không có. |
| Body lỗi | {"name":"Unauthorized","message":"Your request was made with invalid credentials.","code":0,"status":401,"type":"Illuminate\\Auth\\AuthenticationException"} (capture trên dev, 2026-10-01, không token). | Envelope của point-service ở mục Lỗi. | Mọi chỗ so khớp theo text lỗi, name hay type đều phải đổi. |
Lưu ý
- App không gửi
pagehaylimit, nên với Locate nó chỉ hiển thị 20 dòng mới nhất. Không có total, nên nó phải phân trang cho đến khi gặp một trang ngắn. - Dòng earn gửi
total_pointsdạng số và dòng expense gửi nó dạng chuỗi với hai chữ số thập phân, mà app khai báo kiểu là number. - Các dòng không được tính, và các reversal của admin, được liệt kê như bất kỳ dòng nào khác.
Chi tiết (cho backend)
Chỉ kiểm tra dev, qua order-v2 tại https://dev.v2.api.order.locate.sa, prefix /api/v2/client.
Host UAT và production: Chưa được tài liệu hóa. Trong mục này OV2: nghĩa là
locate-order-v2-api@d9e4e5f6 và PS: nghĩa là locate-point-service@2c44ce3. Cách proxy, việc
kiểm tra token và error envelope hoạt động được mô tả một lần, ở
Các lời gọi proxy hoạt động thế nào.
Route và proxy
GET /api/v2/client/point-history đi tới GET /api/client/point-history trên point service. order-v2
forward Authorization và toàn bộ query (kể cả language và mọi key khác), với giới hạn 10 giây
(OV2: src/modules/client/point/point.controller.ts:31-45,
PS: services/api/src/routes/client.routes.ts:18,
PS: services/api/src/handlers/client-point-history.ts:13-19). Point service chỉ đọc page và
limit, phần còn lại bị bỏ qua (PS: services/api/src/handlers/client-point-history.ts:7-10,14). Tài liệu
service nói như vậy về language
(PS: docs/integrations/2026-07-16-client-facing-point-apis.md:113).
Các quy tắc coercion đến từ một lần chạy local của schema của service với zod 3.25.76 (phiên bản trong
lockfile): giá trị rỗng coerce thành 0 và fail, 0x10 thành 16, 1.5 và abc fail.
Query
point_transactions.find({client_id}).sort({created_at: -1}).skip((page - 1) * limit).limit(limit)
(PS: services/api/src/services/client-points.service.ts:35-39). Không có filter theo counted, theo
type hay theo link reversal. Sort key chỉ là created_at, nên các dòng có created_at giống hệt nhau không có thứ tự
cố định giữa các trang. Response là mảng và không có gì khác
(PS: services/api/src/handlers/client-point-history.ts:17-18). Một dòng nhận shape nào phụ thuộc vào type
ledger của nó (PS: services/api/src/services/client-points.mappers.ts:73-91).
Dòng reversal
Một reversal là một dòng ledger mới thuộc type ngược lại với cùng độ lớn, reason là
reversal of <original correlation_id>, ref.source là reversal và một link tới dòng gốc.
Dòng gốc không bao giờ bị thay đổi, và ledger chỉ append
(PS: packages/core/src/points/reverse-point-transaction.ts:50-55,145-148,
PS: packages/core/src/db/models/point-transaction.model.ts:55-63). Chỉ một route admin tạo ra
nó: POST /api/admin/wallets/:client_id/transactions/:id/reverse
(PS: services/api/src/routes/admin.routes.ts:31). Mapper không có marker cho nó. trans_type của nó
fallback về adjustment (earn) hoặc order (expense) trừ khi Shukah-first delivery đã ghi một giá trị
(PS: packages/core/src/points/reverse-point-transaction.ts:236-241).
Các dòng không được tính
Các dòng counted: false được lưu khi status của một dòng Shukah không phải active
(PS: packages/core/src/points/sync-shukah-points.ts:104) và khi một dòng không được tính bị đảo ngược
(PS: packages/core/src/points/reverse-point-transaction.ts:54). Chúng không làm thay đổi số dư và bị
bỏ qua khi tính ngày hết hạn (PS: packages/core/src/points/apply-point-txn.ts:53,58-59), nhưng chúng được
liệt kê với total_points danh nghĩa. Lịch sử của Shukah có liệt kê các dòng inactive hay không: Chưa được tài liệu
hóa; câu hỏi này đã mở từ tháng 7
(PS: docs/integrations/2026-07-16-client-facing-point-apis.md:471-474).
Dòng hết hạn
Shukah ghi một lần hết hạn dưới dạng dòng âm trong bảng earn của nó. Các dòng copy từ lịch sử của nó
được lưu dưới dạng earn âm, nên chúng trả về có shape earn với total_points âm. Các dòng được push
live từ 2026-09-16 và các dòng từ job hết hạn của Locate được lưu dưới dạng expense với độ lớn dương,
nên chúng trả về có shape expense
(PS: packages/core/src/points/sync-shukah-points.ts:97-102,
PS: docs/plans/2026-09-16-point-expiration-job.md:53,59,
PS: docs/plans/2026-07-30-accept-negative-earn.md:6). Text của chúng là
Points expired after <days> days of inactivity <YYYY-MM-DD>
(PS: packages/core/src/points/expire-points.ts:68-70).
Dòng quà tặng và text của chúng
Các dòng mà Locate ghi cho một món quà (các chân của một order trả bằng điểm, và khoản credit của một
order trả bằng thẻ) mang ref.source là point_order và một transfer id. Chúng không có shukah_id và
không có trans_type riêng, nên dòng earn hiển thị adjustment và dòng expense hiển thị order. Chủ sở hữu
tiếng Anh nhận câu tiếng Anh. Chủ sở hữu tiếng Ả Rập nhận template từ point settings, và một
template trống để description rỗng (PS: packages/core/src/points/order-reason.ts:62-87,
PS: docs/plans/2026-10-01-app-language-and-arabic-reason.md:21-42). Trong 118,029 user live, 117,965
dùng tiếng Ả Rập làm ngôn ngữ (PS: packages/core/src/points/client-lookup.ts:8-9), nên template
trống là vấn đề đáng kể. Template có được điền hay không: Chưa được tài liệu hóa.
Description earn rỗng và ngày
Shukah dựng text của một dòng earn khi nó đọc dòng đó, và live push sang Locate có thể không mang nó,
nên các dòng earn đến qua feed đó có thể có description: ""
(PS: docs/integrations/2026-07-16-client-facing-point-apis.md:486-489,
PS: docs/reports/2026-07-17-client-api-parity.md:22). date_created được định dạng từ thời gian UTC
đã lưu. Lỗi lệch +3 giờ mà báo cáo tháng 7 tìm thấy đến từ inbound sync và đã được sửa ở đó
(PS: packages/core/src/points/shukah-date.ts:4-13,
PS: packages/core/src/points/sync-shukah-points.ts:105). Không thể kiểm tra nó trên các capture hôm nay,
vì không dòng nào trong năm dòng Locate chung id với các dòng Shukah đã lưu.
App
Type lịch sử của app có năm key: total_points, date_created, description, points_type và
trans_type. Nó không đọc id hay shukah_id, và hai màn hình danh sách gọi lịch sử mà không có
query (mobile/locate-client@e960c3a: src/entities/points/model/types/pointsHistory.server.ts:6-12,
mobile/locate-client@e960c3a: src/entities/points/model/api/dto/points.dto.ts:70-88,
mobile/locate-client@e960c3a: src/entities/points/model/api/services/points.service.ts:46-60).
Khi tài liệu và code mâu thuẫn (code thắng)
- Báo cáo parity tháng 7 thấy Locate phân trang ở 50 và Shukah trả mọi thứ, và Locate liệt kê
các dòng reversal và không được tính. Cả hai vẫn đúng vào 2026-10-01, với mặc định của Locate giờ là 20 và
tối đa 100 (
PS: docs/reports/2026-07-17-client-api-parity.md:62). - Finding "
total_points_amtcó phần thập phân" của báo cáo tháng 7 là do so sánh nhầm hai dòng khác nhau; lần kiểm tra lại cho thấy cùng một dòng với171ở cả hai phía (PS: docs/reports/2026-07-17-client-api-parity-recheck.md:97-134). - 2026-10-02: trang này nói một token Shukah và một JWT Locate đều chạy ở đây. JWT giờ nhận
401, và mục Thử ngay dùng một token Shukah (PS: services/api/src/services/client-auth.service.ts:22-29; xem Which tokens work). - 2026-10-02: trang này nói các số tiền earn mới nhất của Shukah (0.5, 0.5, 2.5, 0.5, 4) ở một thang đo khác với của Locate. Các dòng mới nhất của Shukah giờ là 2, 2, 2, 2, 10: không còn chênh thang đo. Dòng mới nhất của nó là 2026-10-01 17:00:01, không phải 10:40:44, và nó có 8,136 dòng, không phải 8,134.
- 2026-10-02: trang này nói bốn trong năm dòng earn của Locate có
descriptionrỗng. Trong 10 dòng đầu là 8 trong 9.
Sources
locate-order-v2-api@d9e4e5f6:src/modules/client/point/point.controller.ts:31-45locate-point-service@2c44ce3:services/api/src/routes/client.routes.ts:18,services/api/src/handlers/client-point-history.ts:7-19,services/api/src/services/client-points.service.ts:35-39,services/api/src/services/client-points.mappers.ts:10-28,73-91,services/api/src/routes/admin.routes.ts:31,packages/core/src/points/reverse-point-transaction.ts:50-55,145-148,236-241,packages/core/src/db/models/point-transaction.model.ts:55-63,packages/core/src/points/sync-shukah-points.ts:97-105,packages/core/src/points/apply-point-txn.ts:53,58-59,packages/core/src/points/expire-points.ts:68-70,packages/core/src/points/order-reason.ts:62-87,packages/core/src/points/client-lookup.ts:8-9,packages/core/src/points/shukah-date.ts:4-13- Tài liệu của
locate-point-service@2c44ce3:docs/integrations/2026-07-16-client-facing-point-apis.md:113,471-474,486-489,docs/plans/2026-09-16-point-expiration-job.md:53,59,docs/plans/2026-07-30-accept-negative-earn.md:6,docs/plans/2026-10-01-app-language-and-arabic-reason.md:21-42,docs/reports/2026-07-17-client-api-parity.md:22,62,docs/reports/2026-07-17-client-api-parity-recheck.md:97-134 - Snapshot mobile
mobile/locate-client@e960c3a(branchdevelopment, 2026-02-26; code của chính app, không phải Locate):src/entities/points/model/api/services/points.service.ts:46-60,src/entities/points/model/api/dto/points.dto.ts:70-88,src/entities/points/model/types/pointsHistory.server.ts:6-12,src/features/LastPointsTransactionsList/ui/LastPointsTransactionsList/LastPointsTransactionsList.tsx:34-36,src/entities/points/model/api/rtk/pointsApi.ts:48-68,src/features/PointsHistoryList/ui/PointsHistoryList/PointsHistoryList.tsx:27,platforms/mobile/products/locate/screens/home/mainInner/Wallet/ui/Wallet/Wallet.tsx:81,platforms/mobile/products/locate/screens/home/WalletHistory/ui/WalletHistory/WalletHistory.tsx:25,src/widgets/ApplyPointsPromoCode/model/services/applyPointsPromoCode.ts:27-50,src/widgets/PointGiftsCheckout/model/hooks/usePointGiftsCheckout.ts:221-232 - Capture dev, 2026-10-02 (parity audit):
point-history--shukah,point-history--locate-st,point-history--locate-jwt - Capture dev, 2026-10-01:
locate-point-history,locate-point-history-limit-100,shukah-point-history,probe-locate-point-history,probe-shukah-point-history