Initial Ladill Queue release — enterprise QMS standalone app.
Deploy Ladill Queue / deploy (push) Successful in 56s
Deploy Ladill Queue / deploy (push) Successful in 56s
Phases 1–6: tickets, counters, displays, appointments, workflows, rules, analytics, reports, feedback, admin, device API, and Gitea deploy workflow for queue.ladill.com. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\CrossApp;
|
||||
|
||||
use App\Models\Customer;
|
||||
use App\Models\Deal;
|
||||
use App\Support\CrmPrefillCodec;
|
||||
use App\Support\LadillAppUrl;
|
||||
|
||||
class CrossAppLinkService
|
||||
{
|
||||
public function invoiceFromDeal(Deal $deal): string
|
||||
{
|
||||
$deal->loadMissing(['customer', 'lines']);
|
||||
|
||||
$customer = $deal->customer;
|
||||
$lines = $deal->lines->map(fn ($line) => [
|
||||
'description' => $line->description,
|
||||
'quantity' => (float) $line->quantity,
|
||||
'unit_price' => number_format($line->unit_price_minor / 100, 2, '.', ''),
|
||||
])->values()->all();
|
||||
|
||||
if ($lines === [] && (int) $deal->value_minor > 0) {
|
||||
$lines = [[
|
||||
'description' => $deal->title,
|
||||
'quantity' => 1,
|
||||
'unit_price' => number_format($deal->value_minor / 100, 2, '.', ''),
|
||||
]];
|
||||
}
|
||||
|
||||
$prefill = CrmPrefillCodec::encode([
|
||||
'kind' => 'invoice',
|
||||
'crm_customer_id' => $customer?->id,
|
||||
'client_name' => $customer?->name ?: $deal->title,
|
||||
'client_email' => $customer?->email,
|
||||
'client_address' => $customer ? $this->formatAddress($customer) : null,
|
||||
'notes' => 'Invoice for CRM deal: '.$deal->title,
|
||||
'payment_enabled' => true,
|
||||
'lines' => $lines,
|
||||
]);
|
||||
|
||||
return LadillAppUrl::connect('invoice', '/invoices/create?prefill='.urlencode($prefill));
|
||||
}
|
||||
|
||||
public function merchantStorefrontFromDeal(Deal $deal): string
|
||||
{
|
||||
$deal->loadMissing('customer');
|
||||
|
||||
$amount = number_format(((int) $deal->value_minor) / 100, 2, '.', '');
|
||||
$itemName = $deal->title;
|
||||
|
||||
$prefill = CrmPrefillCodec::encode([
|
||||
'kind' => 'merchant_storefront',
|
||||
'type' => 'shop',
|
||||
'label' => 'Payment — '.$deal->title,
|
||||
'shop_title' => $deal->customer?->company ?: $deal->title,
|
||||
'sections' => [[
|
||||
'name' => 'Payment',
|
||||
'items' => [[
|
||||
'name' => $itemName,
|
||||
'description' => $deal->notes ?: 'Payment for '.$deal->title,
|
||||
'price' => $amount,
|
||||
'image_path' => '',
|
||||
]],
|
||||
]],
|
||||
'accepts_payment' => true,
|
||||
]);
|
||||
|
||||
return LadillAppUrl::connect('merchant', '/storefronts/create?prefill='.urlencode($prefill));
|
||||
}
|
||||
|
||||
public function businessQrFromContact(Customer $contact): string
|
||||
{
|
||||
$prefill = CrmPrefillCodec::encode([
|
||||
'kind' => 'qr_business',
|
||||
'type' => 'business',
|
||||
'label' => 'Card — '.$contact->name,
|
||||
'name' => $contact->company ?: $contact->name,
|
||||
'phone' => $contact->phone,
|
||||
'email' => $contact->email,
|
||||
'address' => $this->formatAddress($contact, singleLine: true),
|
||||
]);
|
||||
|
||||
return LadillAppUrl::connect('qrplus', '/qr-codes/create?prefill='.urlencode($prefill));
|
||||
}
|
||||
|
||||
public function eventsHubForContact(Customer $contact): string
|
||||
{
|
||||
$query = http_build_query(array_filter([
|
||||
'search' => $contact->company ?: $contact->name,
|
||||
]));
|
||||
|
||||
return LadillAppUrl::connect('events', '/attendees'.($query !== '' ? '?'.$query : ''));
|
||||
}
|
||||
|
||||
private function formatAddress(Customer $contact, bool $singleLine = false): ?string
|
||||
{
|
||||
$parts = array_filter([
|
||||
$contact->address_line1,
|
||||
$contact->address_line2,
|
||||
trim(implode(', ', array_filter([$contact->city, $contact->region, $contact->country]))),
|
||||
]);
|
||||
|
||||
if ($parts === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $singleLine
|
||||
? implode(', ', $parts)
|
||||
: implode("\n", $parts);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user