Wire POS register loyalty earn and redeem through CRM.
Deploy Ladill POS / deploy (push) Has been cancelled

Redeem at charge, earn on payment, reverse on cancel, and surface
balances on the till, customer display, sales, and receipts.
This commit is contained in:
isaacclad
2026-07-15 15:46:28 +00:00
parent 38b7f96714
commit 468346b183
12 changed files with 680 additions and 25 deletions
+62
View File
@@ -62,6 +62,61 @@ class CrmClient
return $this->post('timeline', $data);
}
/** @return array<string, mixed> */
public function loyaltyProgram(): array
{
return $this->get('loyalty/program');
}
/**
* @return array<string, mixed>
*/
public function customerLoyalty(int|string $customerId, ?int $amountMinor = null): array
{
$query = [];
if ($amountMinor !== null) {
$query['amount_minor'] = $amountMinor;
}
return $this->get("customers/{$customerId}/loyalty", $query);
}
/**
* @param array{customer_id: int, subtotal_minor: int, redeem_points?: int} $data
* @return array<string, mixed>
*/
public function loyaltyQuote(array $data): array
{
return $this->post('loyalty/quote', $data);
}
/**
* @param array{customer_id: int, subtotal_minor: int, redeem_points: int, external_ref: string, source?: string, description?: string} $data
* @return array<string, mixed>
*/
public function loyaltyRedeem(array $data): array
{
return $this->post('loyalty/redeem', $data);
}
/**
* @param array{customer_id: int, amount_minor: int, external_ref: string, source?: string, description?: string} $data
* @return array<string, mixed>
*/
public function loyaltyEarn(array $data): array
{
return $this->post('loyalty/earn', $data);
}
/**
* @param array{external_ref: string, source?: string} $data
* @return array<string, mixed>
*/
public function loyaltyReverse(array $data): array
{
return $this->post('loyalty/reverse', $data);
}
private function client(): PendingRequest
{
return Http::baseUrl((string) config('crm.url'))
@@ -98,6 +153,13 @@ class CrmClient
}
if ($response->failed()) {
if ($response->status() === 422) {
$message = (string) ($response->json('message')
?? collect((array) $response->json('errors'))->flatten()->first()
?? 'CRM validation failed.');
throw ValidationException::withMessages(['crm' => [$message]]);
}
abort($response->status() === 404 ? 404 : 502, 'CRM service error.');
}