Files
kupshop/bundles/KupShop/KupShopBundle/Context/VatContext.php
2025-08-02 16:30:27 +02:00

219 lines
5.7 KiB
PHP

<?php
namespace KupShop\KupShopBundle\Context;
use KupShop\KupShopBundle\Util\Contexts;
use Symfony\Contracts\Service\Attribute\Required;
class VatContext implements ContextInterface
{
private $activeId;
protected $vatsCache;
protected $defaultVatsCache;
private bool $loaded = false;
public const NO_VAT = 'NO_VAT';
private $countryContext;
/**
* @required
*/
public function setCountryContext(CountryContext $countryContext): void
{
$this->countryContext = $countryContext;
}
public static function getAdminVats(bool $forceAll = false): array
{
static $cache = [];
if (($cache[$forceAll] ?? null) === null) {
$vatsQb = sqlQueryBuilder()->select('v.id, v.descr, v.vat, JSON_VALUE(v.data, \'$.level\') level')->from('vats', 'v');
if (findModule(\Modules::OSS_VATS)) {
if ($forceAll) {
$vatsQb->addSelect('IF(v.id_country IS NULL, v.descr, CONCAT(v.id_country, " ", v.descr)) AS descr')
->orderBy('v.id_country');
} else {
$vatsQb->andWhere('v.automanaged=0');
}
}
$vatsQb->addOrderBy('(v.is_default = "Y")', 'DESC')
->addOrderBy('v.vat', 'DESC');
$cache[$forceAll] = sqlFetchAll($vatsQb, 'id');
}
return $cache[$forceAll];
}
public function translate($vat)
{
$active = $this->getActive();
if ($active == self::NO_VAT) {
return 0;
} elseif ($active) {
return $active[$vat] ?? $vat;
}
return $vat;
}
public function getDefault(?string $activeCountry = null)
{
if (!$this->vatsCache) {
$this->loadVats();
}
if ($this->isOssActive()) {
if (!$activeCountry) {
$countryContext = Contexts::get(CountryContext::class);
$activeCountry = $countryContext->getActiveId();
}
return $this->defaultVatsCache[$activeCountry] ?? $this->defaultVatsCache[null];
}
return $this->defaultVatsCache;
}
public function getVat($id)
{
if (!$this->vatsCache) {
$this->loadVats();
}
return $this->vatsCache[$id];
}
protected function loadVats()
{
$ossVatsActive = $this->isOssActive();
$allVats = sqlQueryBuilder()->select('*')->from('vats');
foreach ($allVats->execute() as $vat) {
$this->vatsCache[$vat['id']] = $vat;
if ($vat['is_default'] == 'Y') {
if ($ossVatsActive) {
$this->defaultVatsCache[$vat['id_country']] = &$this->vatsCache[$vat['id']];
} elseif (($vat['id_country'] ?? null) === null) {
$this->defaultVatsCache = &$this->vatsCache[$vat['id']];
}
}
}
}
public function isCountryOssActive(?string $activeCountry = null)
{
if (!$this->isOssActive()) {
return false;
}
if (!$this->vatsCache) {
$this->loadVats();
}
if (!$activeCountry) {
$activeCountry = Contexts::get(CountryContext::class)->getActiveId();
}
$homeCountry = $this->getHomeCountry() ?? false;
return $homeCountry != $activeCountry && !empty($this->defaultVatsCache[$activeCountry]);
}
public function getHomeCountry(): ?string
{
return \Settings::getDefault()['oss_vats']['homeCountry'] ?? null;
}
public function isOssActive()
{
$dbCfg = \Settings::getDefault();
return findModule(\Modules::OSS_VATS) && ($dbCfg['oss_vats']['active'] ?? 'N') == 'Y';
}
public function activate(?string $id)
{
if (null === $id) {
trigger_error('Passing $id=null into ContextInterface::activate is deprecated! Use ::clearCache instead.', \E_USER_DEPRECATED);
}
$this->loaded = true;
$this->activeId = $id;
return true;
}
public function getActiveId(): ?string
{
if (!$this->loaded) {
$this->activeId = $this->loadActive();
}
return $this->activeId;
}
public function getActive()
{
$activeId = $this->getActiveId();
return ($activeId === self::NO_VAT) ? $activeId : $this->getSupported()[$activeId] ?? null;
}
public function getSupported(): array
{
return [];
}
protected function loadActive(): ?string
{
$this->loaded = true;
if ($this->isOssActive() && $this->isVatFree()) {
return self::NO_VAT;
}
return null;
}
protected function isVatFree(): bool
{
// pokud je pro danou zemi aktivni OSS
if ($this->isCountryOssActive($this->countryContext->getActiveId())) {
$ossVats = \Settings::getDefault()->oss_vats ?? [];
// pokud se jedna o B2B prodej (je vyplnene DIC)
if (Contexts::get(UserContext::class)->isVatPayer()) {
// pokud je platcem DPH pro danou zemi, tak nechceme aplikovat 0% DPH, takze vratime false
if (in_array($this->countryContext->getActiveId(), $ossVats['vatPayerCountry'] ?? [])) {
return false;
}
return true;
}
}
return !$this->isEUCountry();
}
public function clearCache(): void
{
$this->activeId = null;
$this->loaded = false;
}
public function isValid(string $id): bool
{
return true;
}
public function isEUCountry(): bool
{
return in_array(Contexts::get(CountryContext::class)->getActiveId(), CountryContext::EU_COUNTRIES);
}
}