<?php
namespace WebBundle\Serializer\Normalizer;
use DateTime;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\ORMException;
use Exception;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareTrait;
use WebBundle\Constant\CookieKeysConstant;
use WebBundle\Entity\BuyOrder;
use WebBundle\Entity\BuyOrderArticle;
use WebBundle\Entity\OrderHistory;
use WebBundle\Entity\OrderPayment;
use WebBundle\Enum\BuyOrderStatusEnum;
use WebBundle\Helper\App;
use WebBundle\Helper\ConversionHelper;
use WebBundle\Helper\CookieHelper;
use WebBundle\Helper\DateHelper;
use WebBundle\Helper\LocaleHelper;
use WebBundle\Helper\OrderHelper;
use WebBundle\Helper\RequestHelper;
use WebBundle\Helper\StrHelper;
use WebBundle\Helper\TwigTe;
use WebBundle\Helper\UserHelper;
use WebBundle\Service\LocationService;
use WebBundle\Service\OrderPaymentService;
/**
* Class BuyOrderNormalizer
* @package WebBundle\Serializer\Normalizer
*/
class OrderNormalizer implements NormalizerInterface
{
use SerializerAwareTrait;
/** @required */
public LocationService $locationService;
/** @required */
public OrderPaymentService $orderPaymentService;
/** @required */
public DateTimeNormalizer $dateTimeNormalizer;
/** @required */
public WarehouseNormalizer $warehouseNormalizer;
/** @required */
public OrderAddressNormalizer $orderAddressNormalizer;
/** @required */
public OrderItemNormalizer $orderItemNormalizer;
/** @required */
public OrderHistoryNormalizer $orderHistoryNormalizer;
/** @required */
public OrderPaymentNormalizer $orderPaymentNormalizer;
/**
* @param BuyOrder $order
* @param string|null $format
* @param array $context
* @return array|bool|float|int|string
* @throws NonUniqueResultException
* @throws ORMException
*/
public function normalize($order, ?string $format = null, array $context = [])
{
$subtotal = [
'items' => 0,
'boxes' => 0,
'weight' => 0,
'pallets' => 0,
'sum' => 0,
];
$ip = App::getIp();
$record = $this->locationService->getCityRecord($ip);
$ipCountry = StrHelper::toLower($record->country->isoCode);
foreach ($order->getArticles() as $item) {
if ($item->getArticle()->getDelivery()->getId() == 6) {
continue;
}
$subtotal['items']++;
$subtotal['boxes'] += ceil($item->getAmount() / $item->getPackagingCount());
$subtotal['weight'] += $item->getAmount() / $item->getPackagingCount() * $item->getWeight();
$subtotal['pallets'] += ($item->getPallet() ? ceil($item->getAmount() / $item->getPallet()) : 1);
$subtotal['sum'] += $item->getAmount() * $item->getPrice();
}
$subtotal['weight'] = round($subtotal['weight']);
$subtotal['sum'] = round($subtotal['sum'], 2);
$weight = round($order->getWeightGross()
?: ($order->getMeasure() == 'm'
? OrderHelper::totalWeight($order)
: ConversionHelper::convertKgLb((float) OrderHelper::totalWeight($order))
), 2);
$dueSum = $this->orderPaymentService->getAmount($order);
$itemsByCollection = $this->mapItem($order->getArticles(), $format, $context);
uasort(
$itemsByCollection,
function ($a, $b) {
return $a['id'] < $b['id'] ? 1 : -1;
}
);
$context['order'] = $order;
$baseData = [
'step' => $order->getStep(),
'hash' => $order->getHash(),
'number' => $order->getNumber(),
'title' => OrderHelper::header($order),
'header' => TwigTe::headerBO($order),
'status' => [
'id' => $order->getStatus(),
'name' => App::trans(BuyOrderStatusEnum::from($order->getStatus())->getAlias()),
'type' => App::trans($order->getStatus() < BuyOrderStatusEnum::PARTIALLY_PAID ? 'order.status.draft' : 'buyOrder.title'),
],
'createDate' => empty($context['history'])
? StrHelper::ucFirst(DateHelper::localizedDate($order->getCreateDate(), 'long', 'none'))
: $order->getCreateDate()->getTimestamp(),
'createDateForHistory' => $order->getCreateDate()->getTimestamp(),
'updateDate' => empty($context['history'])
? StrHelper::ucFirst(DateHelper::localizedDate($order->getUpdateDate(), 'long', 'none'))
: $order->getUpdateDate()->getTimestamp(),
'updateDateForHistory' => $order->getUpdateDate()->getTimestamp(),
'country' => $order->getAddressRecipient() && $order->getAddressRecipient()->getCountry()
? StrHelper::toLower($order->getAddressRecipient()->getCountry()->getCode())
: CookieHelper::get(CookieKeysConstant::COUNTRY),
'discount' => $order->getDiscount(),
'delivery' => [
'type' => $order->getDeliveryType() == 1 ? 1 : 0,
'price' => $order->getDelivery()
?: (
$order->getStatus() == BuyOrderStatusEnum::AWAITING_CALCULATION
? App::trans('order.status.awaiting_calculation')
: App::trans('buyOrder.info.request_calculation')
),
'lift' => $order->getLift(),
'timeType' => $order->getDeliveryTimeType(),
'timePeriod' => DateHelper::getTimePeriod(
$order->getDeliveryTimeMin(),
$order->getDeliveryTimeMax(),
$order->getStatus()
),
'timeFastPayPeriod' => $order->getDeliveryTimeFastPayMin() ? DateHelper::getTimePeriod(
$order->getDeliveryTimeFastPayMin(),
$order->getDeliveryTimeFastPayMax(),
$order->getStatus()
) : null,
'timeConfirmPeriod' => $order->getDeliveryTimeConfirmMin()
? DateHelper::getTimePeriod(
$order->getDeliveryTimeConfirmMin(),
$order->getDeliveryTimeConfirmMax(),
$order->getStatus()
)
: null,
'timePeriodStatusMarker' => $order->getDeliveryTimeConfirmMin()
? DateHelper::getTimePeriodStatusMarker(
$order->getDeliveryTimeConfirmMin(),
$order->getStatus()
)
: DateHelper::getTimePeriodStatusMarker(
$order->getDeliveryTimeMin(),
$order->getStatus()
),
'daysFast' => $order->getDeliveryTimeFastPayMin() && $order->getDeliveryTimeMin()
? ceil(
($order->getDeliveryTimeMin()->getTimestamp() - $order->getDeliveryTimeFastPayMin()->getTimestamp()) / 86400
)
: null,
'freeSampleDelivery' => App::trans(
'order.free_delivery_sample',
App::getCurLocale(),
[
'%sum%' => $order->getDeliveryCountry()->getFreeSampleDelivery(),
'%currency%' => $order->getCurrency(),
]
),
'onlySamplesAndNotEmptyBasketOfOrder' => OrderHelper::onlySamplesAndNotEmptyBasketOfOrder($order),
'calculationType' => $order->getDeliveryCalculateType(),
],
'payment' => [
'type' => $order->getPayType(),
'feePercents' => [
// в таком порядке отображаем на странице заказа
'1' => OrderHelper::paymentPercent($order, 1),
'2' => OrderHelper::paymentPercent($order, 2),
'3' => OrderHelper::paymentPercent($order, 3),
'4' => OrderHelper::paymentPercent($order, 4),
'5' => OrderHelper::paymentPercent($order, 5),
'6' => OrderHelper::paymentPercent($order, 6),
],
'feeAmount' => [
'1' => OrderHelper::percent($dueSum, OrderHelper::paymentPercent($order, 1), false),
'2' => OrderHelper::percent($dueSum, OrderHelper::paymentPercent($order, 2), false),
'3' => OrderHelper::percent($dueSum, OrderHelper::paymentPercent($order, 3), false),
'4' => OrderHelper::percent($dueSum, OrderHelper::paymentPercent($order, 4), false),
'5' => OrderHelper::percent($dueSum, OrderHelper::paymentPercent($order, 5), false),
'6' => OrderHelper::percent($dueSum, OrderHelper::paymentPercent($order, 6), false),
],
'showRuCC' => App::getContainer()->hasParameter('card_ru_url'),
'dueSum' => round($dueSum, 2),
'total' => OrderHelper::totalSum($order),
],
'payments' => $this->mapPayment($order->getPayments(), $format, $context),
'payDateExecution' => $this->dateTimeNormalizer
->normalize($order->getPayDateExecution(), $format, $context),
'payDateExecutionISO' => $order->getPayDateExecution() && $order->getPayDateExecution()->getTimestamp(
) > (new DateTime())->getTimestamp()
? $order->getPayDateExecution()->getTimestamp()
: null,
'offset' => OrderHelper::offsetReason($order),
'holiday' => OrderHelper::isHoliday($order) ? App::trans('buyOrder.longTime') : null,
'proposedDate' => $order->getProposedDate() ? $order->getProposedDate()->format('Y-m-d') : null,
'shipDate' => $order->getShipDate(),
'factDate' => $order->getFactDate()
? $order->getFactDate()->format(
LocaleHelper::dateMask(1, App::getCountryCode())
)
: '',
'cancelDate' => $order->getCancelDate()
? $order->getCancelDate()->format(
LocaleHelper::dateMask(1, App::getCountryCode())
)
: '',
'trackingNumber' => $order->getTrackingNumber(),
'carrier' => [
'name' => $order->getCarrierName(),
'phone' => $order->getCarrierContactData(),// @deprecated
'contactDate' => $order->getCarrierContactData(),
],
'customsPayment' => $order->getCustomsPayment(),
'weight' => [
'measure' => App::trans('measure_' . ($order->getMeasure() == 'm' ? 'kgs' : 'lb')),
'measures' => App::trans('measure_' . ($order->getMeasure() == 'm' ? 'kgs' : 'lbs')),
'limit' => ($order->getWeightLimit() ?? 0)
? App::trans('order.status.more_weight', null, ['%d%' => $order->getWeightLimit()])
: null,
'report' => $order->getWeightReport() ? App::trans(
'buyOrder.info.weightReport',
App::getCurLocale(),
[
'%d%' => App::trans(LocaleHelper::weightLabel($order->getWeightReport())),
]
) : null,
'smallWeight' => $weight <= 300 && !OrderHelper::onlySamples($order)
? [
'text' => App::trans('order.low_weight'),
'help' => App::trans('order.low_weight_help', App::getCurLocale(), [
'%weight%' => LocaleHelper::weightLabel(300.0, true, $order->getMeasure()),
]),
]
: null,
'total' => $weight,
],
'manager' => [
'name' => $order->getManagerName(),
'email' => $order->getManagerEmail(),
'phone' => $order->getManagerPhone(),
],
'locale' => $order->getLocale(),
'curRate' => $order->getCurRate(),
'currency' => [
'sign' => LocaleHelper::getCurrency($order->getCurrency()),
'code' => $order->getCurrency(),
],
'measure' => $order->getMeasure(),
'emailSend' => $order->getEmailSend(),
'remember' => $order->getRemember(),
'markerTest' => (
$order->getMarkerTest() == true
|| UserHelper::isEmployee($order->getEmail())
),
'name' => OrderHelper::humanName($order->getName(), $order->getStatus(), $order->getBankTransferRequested()),
'description' => $order->getDescription(),
'subtotal' => $subtotal,
'totalSum' => OrderHelper::totalSum($order), // общая сумма заказа
'warehouse' => $this->warehouseNormalizer->normalize($order->getWarehouse(), $format, $context),
'recipient' => $this->orderAddressNormalizer->normalize($order->getAddressRecipient(), $format, $context),
'payer' => $this->orderAddressNormalizer->normalize($order->getAddressPayer(), $format, $context),
'addressEqual' => !!$order->getAddressEqual(),
'items' => array_values($itemsByCollection),
'personalDataAgree' => !!$order->getPersonalDataAgree(),
'updating' => false,
'updatingDetails' => [
'items' => [],
],
'vatIncludes' => $vatIncludes = OrderHelper::vatIncludes($order),
'vatPercent' => $vatIncludes ? $order->getVatPercent() : 0,
'pdf' => App::getRequest()->get('share') == 'pdf',
'EORIRequired' => OrderHelper::EORIRequired($order),
'captcha' => ($ipCountry != 'cn' && empty($_SESSION['captcha-order'])),
'authRedirect' => (App::getCurUser() == null
? App::generateUrl(
'app_login',
[
'redirect_url' => App::generateUrl(
'app_buy_order',
[
'orderId' => $order->getHash(),
],
0
),
]
)
: null),
];
$baseData['history'] = $this->mapHistory($order->getHistories(), $format, $context);
if (empty($context['master'])) {
return $baseData;
}
$additionData = [
'email' => $order->getEmail()
];
$payment = $order->getCustomsPayment() ?? 0.00;
$currency = $order->getCurrency();
$customsPayment = App::getCurLocale() === 'en'
? "$currency $payment"
: "$payment $currency";
$additionData['customsPaymentMessage'] = App::trans(
'customs_payments.notInclud',
App::getCurLocale(),
[
'USD100' => $customsPayment,
]
);
return array_merge($baseData, $additionData);
}
/**
* @param BuyOrder $data
* @param null $format
* @return bool
*/
public function supportsNormalization($data, $format = null)
{
return $data instanceof BuyOrder;
}
/**
* @param Collection<BuyOrderArticle> $buyOrderArticlesCollection
* @param string|null $format
* @param array $context
* @return array
* @throws Exception
*/
public function mapItem(Collection $buyOrderArticlesCollection, ?string $format = null, array $context = []): array
{
$orders = [];
foreach ($buyOrderArticlesCollection->toArray() as $order) {
$orders[] = $this->orderItemNormalizer->normalize($order, $format, $context);
}
return $orders;
}
/**
* @param OrderHistory[] $arr
* @param string $format
* @param array $context
* @return array
* @throws Exception
*/
public function mapHistory($arr, $format, $context): array
{
$orders = [];
foreach ($arr as $row) {
$orders[] = $this->orderHistoryNormalizer->normalize($row, $format, $context);
}
return $orders;
}
/**
* @param OrderPayment[] $arr
* @param string $format
* @param array $context
* @return array
* @throws Exception
*/
public function mapPayment($arr, $format, $context): array
{
$orders = [];
foreach ($arr as $row) {
// Добавляем только успешные и подвешанные оплаты
if (in_array($row->getStatus(), [1, 3, 4])) {
$orders[] = $this->orderPaymentNormalizer->normalize($row, $format, $context);
}
}
return $orders;
}
}