Files
esun3d/app/code/Esun/CustomerVat/Model/VatApplicationService.php
T
2026-09-15 10:35:56 +08:00

129 lines
4.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\CustomerVat\Model;
use Esun\CustomerVat\Model\ResourceModel\VatApplication as VatResource;
use Esun\CustomerVat\Model\ResourceModel\VatApplication\CollectionFactory;
use Magento\Framework\Exception\LocalizedException;
class VatApplicationService
{
public function __construct(
private readonly VatApplicationFactory $applicationFactory,
private readonly VatResource $resource,
private readonly CollectionFactory $collectionFactory,
private readonly EuCountries $euCountries
) {
}
public function getByIdForCustomer(int $id, int $customerId): VatApplication
{
$application = $this->applicationFactory->create();
$this->resource->load($application, $id);
if (!$application->getId() || (int)$application->getData('customer_id') !== $customerId) {
throw new LocalizedException(__('The VAT application no longer exists.'));
}
return $application;
}
public function saveForCustomer(int $customerId, array $data, int $id = 0): VatApplication
{
$companyName = trim((string)($data['company_name'] ?? ''));
$countryId = strtoupper(trim((string)($data['country_id'] ?? '')));
$vatNumber = trim((string)($data['vat_number'] ?? ''));
$normalized = $this->normalize($vatNumber);
if ($companyName === '' || mb_strlen($companyName) > 255) {
throw new LocalizedException(__('Enter a valid company name.'));
}
if (!$this->euCountries->isEu($countryId)) {
throw new LocalizedException(__('Select a valid EU country.'));
}
if (strlen($normalized) < 4 || strlen($normalized) > 64) {
throw new LocalizedException(__('Enter a valid VAT number.'));
}
$duplicate = $this->collectionFactory->create()
->addFieldToFilter('customer_id', $customerId)
->addFieldToFilter('country_id', $countryId)
->addFieldToFilter('normalized_vat_number', $normalized);
if ($id > 0) {
$duplicate->addFieldToFilter('entity_id', ['neq' => $id]);
}
if ($duplicate->getSize()) {
throw new LocalizedException(__('This VAT number has already been submitted for the selected country.'));
}
$application = $id > 0
? $this->getByIdForCustomer($id, $customerId)
: $this->applicationFactory->create()->setData('customer_id', $customerId);
$changed = !$application->getId()
|| (string)$application->getData('company_name') !== $companyName
|| (string)$application->getData('country_id') !== $countryId
|| (string)$application->getData('normalized_vat_number') !== $normalized;
$application->addData([
'company_name' => $companyName,
'country_id' => $countryId,
'vat_number' => $vatNumber,
'normalized_vat_number' => $normalized,
]);
if ($changed) {
$application->addData([
'status' => VatApplication::STATUS_PENDING,
'review_note' => null,
'reviewed_by' => null,
'reviewed_at' => null,
]);
}
$this->resource->save($application);
return $application;
}
public function deleteForCustomer(int $id, int $customerId): void
{
$this->resource->delete($this->getByIdForCustomer($id, $customerId));
}
public function findApproved(int $customerId, string $countryId): ?VatApplication
{
if ($customerId <= 0 || !$this->euCountries->isEu($countryId)) {
return null;
}
$application = $this->collectionFactory->create()
->addFieldToFilter('customer_id', $customerId)
->addFieldToFilter('country_id', strtoupper($countryId))
->addFieldToFilter('status', VatApplication::STATUS_APPROVED)
->setOrder('reviewed_at', 'DESC')
->setPageSize(1)
->getFirstItem();
return $application->getId() ? $application : null;
}
public function getCustomerStatus(int $customerId): string
{
if ($customerId <= 0) {
return 'guest';
}
$statuses = $this->collectionFactory->create()
->addFieldToFilter('customer_id', $customerId)
->getColumnValues('status');
if (in_array(VatApplication::STATUS_APPROVED, $statuses, true)) {
return VatApplication::STATUS_APPROVED;
}
if (in_array(VatApplication::STATUS_PENDING, $statuses, true)) {
return VatApplication::STATUS_PENDING;
}
if (in_array(VatApplication::STATUS_REJECTED, $statuses, true)) {
return VatApplication::STATUS_REJECTED;
}
return 'none';
}
public function normalize(string $vatNumber): string
{
return strtoupper((string)preg_replace('/[^A-Z0-9]/i', '', $vatNumber));
}
}