feat(customers): store customer phone numbers as 62…
A customer's phone number (customers.phone_number, the one they log in with) has one stored form, 62 followed by the number without its 0: 6281234561234. util.NormalizePhoneNumber rewrites 0812…, +62 812…, 62812…, 812… and +62 0812…, with spaces, dashes, dots or parentheses, to it, and refuses anything that is not an Indonesian mobile number (628 and 7 to 11 more digits). It is applied wherever a customer types their number: check-phone, register, login and resend-OTP (the validator rewrites the request), and the transfer recipient. Before, the number was matched as typed and a leading 0 was refused, so the same customer written another way was not found. The masked recipient stays 08**-****-1234 as customers write numbers. Migration 000116 rewrites the numbers already stored in customers and otp_sessions. When several become the same number, the customer that already has it keeps it, else a registered one, else the oldest; the others, and numbers that are not Indonesian mobile numbers, are left as they are and cannot log in until fixed by hand (the query to find them is in the migration). Down does nothing. The migration was run, twice, against Postgres with a reduced customers and otp_sessions schema and sample numbers; not against the real schema. The Postgres tests were not run. customers.phone (the POS contact number) is not touched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4b7eddbd3e
commit
19afa50b9c
@@ -15,6 +15,7 @@ import (
|
||||
"apskel-pos-be/internal/logger"
|
||||
"apskel-pos-be/internal/models"
|
||||
"apskel-pos-be/internal/repository"
|
||||
"apskel-pos-be/internal/util"
|
||||
)
|
||||
|
||||
// ErrWalletRecipientNotFound means no customer of the sender's organization has the
|
||||
@@ -213,10 +214,13 @@ func (p *WalletTransferProcessor) Transfer(ctx context.Context, senderID uuid.UU
|
||||
// them: an active customer of the same organization, not the walk-in customer, and
|
||||
// not the sender.
|
||||
func (p *WalletTransferProcessor) recipient(ctx context.Context, sender *repository.WalletMoveCustomer, phoneNumber string) (*repository.WalletMoveCustomer, error) {
|
||||
phoneNumber = strings.TrimSpace(phoneNumber)
|
||||
if phoneNumber == "" {
|
||||
if strings.TrimSpace(phoneNumber) == "" {
|
||||
return nil, fmt.Errorf("%w: the recipient's phone number is required", ErrWalletMoveRejected)
|
||||
}
|
||||
phoneNumber, err := util.NormalizePhoneNumber(phoneNumber)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: the recipient's phone number is not valid", ErrWalletMoveRejected)
|
||||
}
|
||||
recipient, err := p.customers.FindCustomerByPhone(ctx, phoneNumber)
|
||||
if errors.Is(err, repository.ErrWalletNotFound) {
|
||||
return nil, ErrWalletRecipientNotFound
|
||||
@@ -282,10 +286,14 @@ func maskName(name string) string {
|
||||
return strings.Join(words, " ")
|
||||
}
|
||||
|
||||
// maskPhoneNumber keeps the first two and the last four digits:
|
||||
// "081234561234" → "08**-****-1234".
|
||||
// maskPhoneNumber keeps the first two and the last four digits of the number as
|
||||
// customers write it, with 0 for 62: "6281234561234" → "08**-****-1234".
|
||||
func maskPhoneNumber(phone string) string {
|
||||
runes := []rune(strings.TrimSpace(phone))
|
||||
phone = strings.TrimSpace(phone)
|
||||
if strings.HasPrefix(phone, "62") {
|
||||
phone = "0" + phone[2:]
|
||||
}
|
||||
runes := []rune(phone)
|
||||
if len(runes) < 8 {
|
||||
return "****"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user