feat(shipments): add ShipmentProviderInterface and ShipmentProviderRegistry

- Introduced ShipmentProviderInterface to define the contract for shipment providers.
- Implemented ShipmentProviderRegistry to manage and retrieve shipment providers.
- Added a new tool for probing Apaczka order_send payload variants, enhancing debugging capabilities.
This commit is contained in:
2026-03-08 23:45:10 +01:00
parent af052e1ff5
commit 2b12fde248
34 changed files with 3285 additions and 233 deletions

View File

@@ -434,7 +434,7 @@ final class ShopproOrdersSyncService
'customer_login' => $this->nullableString((string) $this->readPath($payload, [
'buyer_email', 'customer.email', 'buyer.email', 'client.email', 'email', 'customer.login', 'buyer.login',
])),
'is_invoice' => !empty($this->readPath($payload, ['is_invoice', 'invoice.required'])),
'is_invoice' => $this->resolveInvoiceRequested($payload),
'is_encrypted' => false,
'is_canceled_by_buyer' => false,
'currency' => $currency,
@@ -548,6 +548,11 @@ final class ShopproOrdersSyncService
],
];
$invoiceAddress = $this->buildInvoiceAddress($payload, $customerName, $customerEmail, $customerPhone);
if ($invoiceAddress !== null) {
$result[] = $invoiceAddress;
}
$deliveryFirstName = $this->nullableString((string) $this->readPath($payload, [
'delivery.address.first_name', 'delivery.address.firstname', 'shipping.address.first_name', 'shipping.address.firstname',
'delivery_address.first_name', 'delivery_address.firstname', 'shipping_address.first_name', 'shipping_address.firstname',
@@ -638,6 +643,119 @@ final class ShopproOrdersSyncService
return $result;
}
/**
* @param array<string, mixed> $payload
*/
private function resolveInvoiceRequested(array $payload): bool
{
$explicitInvoice = $this->readPath($payload, ['is_invoice', 'invoice.required', 'invoice']);
if (!empty($explicitInvoice)) {
return true;
}
$companyName = $this->nullableString((string) $this->readPath($payload, [
'invoice.company_name', 'invoice.company', 'billing.company_name', 'billing.company',
'firm_name', 'company_name', 'client_company', 'buyer_company',
]));
$taxNumber = $this->nullableString((string) $this->readPath($payload, [
'invoice.tax_id', 'invoice.nip', 'billing.tax_id', 'billing.nip',
'firm_nip', 'company_nip', 'tax_id', 'nip',
]));
return $companyName !== null || $taxNumber !== null;
}
/**
* @param array<string, mixed> $payload
* @return array<string, mixed>|null
*/
private function buildInvoiceAddress(
array $payload,
?string $customerName,
?string $customerEmail,
?string $customerPhone
): ?array {
$companyName = $this->nullableString((string) $this->readPath($payload, [
'invoice.company_name', 'invoice.company', 'billing.company_name', 'billing.company',
'firm_name', 'company_name', 'client_company', 'buyer_company',
]));
$companyTaxNumber = $this->nullableString((string) $this->readPath($payload, [
'invoice.tax_id', 'invoice.nip', 'billing.tax_id', 'billing.nip',
'firm_nip', 'company_nip', 'tax_id', 'nip',
]));
$invoiceFirstName = $this->nullableString((string) $this->readPath($payload, [
'invoice.first_name', 'invoice.firstname', 'billing_address.first_name', 'billing_address.firstname',
'buyer.first_name', 'customer.first_name', 'client_name',
]));
$invoiceLastName = $this->nullableString((string) $this->readPath($payload, [
'invoice.last_name', 'invoice.lastname', 'billing_address.last_name', 'billing_address.lastname',
'buyer.last_name', 'customer.last_name', 'client_surname',
]));
$invoiceName = $companyName ?? $this->composeName($invoiceFirstName, $invoiceLastName, $customerName ?? 'Faktura');
$streetName = $this->nullableString((string) $this->readPath($payload, [
'invoice.address.street', 'invoice.street', 'billing_address.street', 'billing.street',
'firm_street', 'company_street',
]));
$streetNumber = $this->nullableString((string) $this->readPath($payload, [
'invoice.address.street_number', 'invoice.street_number', 'invoice.house_number',
'billing_address.street_number', 'billing_address.house_number',
'billing.street_number', 'house_number', 'street_number',
]));
$city = $this->nullableString((string) $this->readPath($payload, [
'invoice.address.city', 'invoice.city', 'billing_address.city', 'billing.city',
'firm_city', 'company_city',
]));
$zipCode = $this->nullableString((string) $this->readPath($payload, [
'invoice.address.zip', 'invoice.address.postcode', 'invoice.zip', 'invoice.postcode',
'billing_address.zip', 'billing_address.postcode', 'billing.zip', 'billing.postcode',
'firm_postal_code', 'company_postal_code',
]));
$country = $this->nullableString((string) $this->readPath($payload, [
'invoice.address.country', 'invoice.country', 'billing_address.country', 'billing.country',
'firm_country', 'company_country',
]));
$email = $this->nullableString((string) $this->readPath($payload, [
'invoice.email', 'billing_address.email', 'billing.email', 'client_email',
])) ?? $customerEmail;
$phone = $this->nullableString((string) $this->readPath($payload, [
'invoice.phone', 'billing_address.phone', 'billing.phone', 'client_phone',
])) ?? $customerPhone;
$hasInvoiceData = $companyName !== null
|| $companyTaxNumber !== null
|| $streetName !== null
|| $city !== null
|| $zipCode !== null;
if (!$hasInvoiceData) {
return null;
}
return [
'address_type' => 'invoice',
'name' => $invoiceName ?? 'Faktura',
'phone' => $phone,
'email' => $email,
'street_name' => $streetName,
'street_number' => $streetNumber,
'city' => $city,
'zip_code' => $zipCode,
'country' => $country,
'company_tax_number' => $companyTaxNumber,
'company_name' => $companyName,
'payload_json' => [
'invoice' => $this->readPath($payload, ['invoice']),
'billing' => $this->readPath($payload, ['billing']),
'billing_address' => $this->readPath($payload, ['billing_address']),
'firm_name' => $this->readPath($payload, ['firm_name']),
'firm_nip' => $this->readPath($payload, ['firm_nip']),
'firm_street' => $this->readPath($payload, ['firm_street']),
'firm_postal_code' => $this->readPath($payload, ['firm_postal_code']),
'firm_city' => $this->readPath($payload, ['firm_city']),
],
];
}
private function composeName(?string $firstName, ?string $lastName, ?string $fallback): ?string
{
$name = trim(trim((string) $firstName) . ' ' . trim((string) $lastName));