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)); } }