<?php
namespace App\Controller;
use App\Entity\Purchase;
use App\Entity\PurchaseAPOD;
use App\Entity\PurchaseEtsy;
use App\Entity\PurchaseItemEtsy;
use App\Entity\PurchaseItemSide;
use App\Entity\PurchaseItemsEtsySellerNotes;
use App\Entity\PurchaseShipStationRate;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Psr\Log\LoggerInterface;
use App\Service\Stripe\StripeHelper;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Doctrine\ORM\Query\Expr\Join;
class DashboardController extends AbstractHappyLauncherController
{
public function __construct(
private EntityManagerInterface $entityManager,
private LoggerInterface $logger,
protected StripeHelper $stripeHelper,
) {
}
#[Route('/', name: 'app_dashboard')]
public function index(Request $request): Response
{
$query = $request->query->all();
/** @var User $user */
$user = $this->getUser();
$storeList = [];
foreach ($user->getUserStores() as $store) {
$storeList[] = $store->getId();
}
if (empty($storeList)) $storeList = [ -1 ]; // avoid SQL errors
$capability = in_array( 'ROLE_ADMIN', $user->getRoles() );
$purchaseRepo = $this->entityManager->getRepository(Purchase::class);
$working_page = (int)($query['working_page'] ?? 1) ?: 1;
$working_page_size = (int)($query['working_page_size'] ?? 10) ?: 10;
// $working_order_criteria = [
// 'userStore' => $storeList,
// 'status' => [
// Purchase::STATUS_PURCHASE_ERROR,
// Purchase::STATUS_FOUND,
// Purchase::STATUS_ODESK_PROCESSNG,
// Purchase::STATUS_PAID,
// Purchase::STATUS_SENT_TO_ORDER_DESK,
// ]
// ];
$working_qb = $this->entityManager->createQueryBuilder();
$working_qb->select('p')
->from(Purchase::class, 'p')
->leftJoin(PurchaseAPOD::class, 'p_apod', Join::WITH, 'p.id = p_apod.id')
->where($working_qb->expr()->in('p.status', [
Purchase::STATUS_PURCHASE_ERROR,
Purchase::STATUS_FOUND,
Purchase::STATUS_ODESK_PROCESSNG,
Purchase::STATUS_PAID,
Purchase::STATUS_SENT_TO_ORDER_DESK,
]))
->andWhere($working_qb->expr()->orX(
$working_qb->expr()->in('p.userStore', $storeList), // Etsy
$working_qb->expr()->eq('p_apod.user', $user->getId()), // APOD
));
// $countOfWorking = $purchaseRepo->count($working_order_criteria);
$countOfWorking = count($working_qb->getQuery()->getResult());
$countOfWorkingPages = (int)($countOfWorking / $working_page_size);
$countOfWorkingPages += (int)(($countOfWorking % $working_page_size) != 0);
$working_purchases = [];
if ($working_page - 1 * $working_page_size < $countOfWorking) {
/** @var Purchase[] $working_purchases */
// $working_purchases = $purchaseRepo->findBy(
// $working_order_criteria,
// null,
// $working_page_size,
// ($working_page - 1) * $working_page_size,
// );
$working_purchases = $working_qb->getQuery()->setMaxResults($working_page_size)->setFirstResult(($working_page - 1) * $working_page_size)->getResult();
usort($working_purchases, function ($a, $b) {
return $b->getId() - $a->getId();
});
}
$complete_page = ((int)($query['complete_page'] ?? 1)) ?: 1;
$complete_page_size = ((int)($query['complete_page_size'] ?? 10)) ?: 10;
// $complete_order_criteria = [
// 'userStore' => $storeList,
// 'status' => [
// Purchase::STATUS_CANCELED,
// Purchase::STATUS_COMPLETE,
// Purchase::STATUS_SHIPPED,
// ]
// ];
$complete_qb = $this->entityManager->createQueryBuilder();
$complete_qb->select('p')
->from(Purchase::class, 'p')
->leftJoin(PurchaseAPOD::class, 'p_apod', Join::WITH, 'p.id = p_apod.id')
->where($complete_qb->expr()->in('p.status', [
Purchase::STATUS_CANCELED,
Purchase::STATUS_COMPLETE,
Purchase::STATUS_SHIPPED,
]))
->andWhere($complete_qb->expr()->orX(
$complete_qb->expr()->in('p.userStore', $storeList), // Etsy
$complete_qb->expr()->eq('p_apod.user', $user->getId()), // APOD
))
->orderBy('p.id', 'DESC');
// $countOfComplete = $purchaseRepo->count($complete_order_criteria);
$countOfComplete = count($complete_qb->getQuery()->getResult());
$countOfCompletePages = (int)($countOfComplete / $complete_page_size);
$countOfCompletePages += (int)(($countOfComplete % $complete_page_size) != 0);
$complete_purchases = [];
if ($complete_page - 1 * $complete_page_size < $countOfComplete) {
/** @var Purchase[] $complete_purchases */
// $complete_purchases = $purchaseRepo->findBy(
// $complete_order_criteria,
// [
// 'id' => 'DESC'
// ],
// $complete_page_size,
// ($complete_page - 1) * $complete_page_size,
// );
$complete_purchases = $complete_qb->getQuery()->setMaxResults($complete_page_size)->setFirstResult(($complete_page - 1) * $complete_page_size)->getResult();
}
$notShippedPurchases = [];
$personalizedCountData = [];
$customize_status = [];
$purchaseShipmentRates = [];
$purchaseShipment = [];
$hasSelectedRates = [];
foreach ($working_purchases as $purchase) {
$rates = $purchase->getPurchaseShipStationRates();
$purchaseRates = [];
$itemId = null;
$hasSelectedRates[$purchase->getId()] = false;
if (! $rates->isEmpty()) {
foreach ($rates as $rate) {
if ($rate->getServiceCode() == 'usps_media_mail') {
continue;
}
if (! $purchase instanceof PurchaseAPOD) {
$item = $rate->getPurchaseItemEtsy()->getId();
$itemId ??= $item;
if ($itemId !== $item) {
continue;
}
}
if ($rate->getSelected() == 'yes') {
$hasSelectedRates[$purchase->getId()] = true;
}
$purchaseRates[] = $rate;
}
$purchaseShipmentRates[$purchase->getId()] = $purchaseRates;
}
$purchaseId = $purchase->getId();
if ($purchase->getHasPersonalizedItem()) {
$getPersonalizedCountData = $this->getPersonalizedItemsCountData($purchaseId);
$personalizedCountData[$purchaseId] = $getPersonalizedCountData;
$customize_status[$purchaseId] =
$getPersonalizedCountData['itemsCount'] == $getPersonalizedCountData['completedItemsCount'];
} else {
$personalizedCountData[$purchaseId] = [
'needCustomization' => false,
];
$customize_status[$purchaseId] = true;
}
$notShippedPurchases[] = $purchase;
}
$shippedPurchases = [];
foreach ($complete_purchases as $purchase) {
$purchaseId = $purchase->getId();
if ($purchase->getHasPersonalizedItem()) {
$getPersonalizedCountData = $this->getPersonalizedItemsCountData($purchaseId);
$personalizedCountData[$purchaseId] = $getPersonalizedCountData;
$customize_status[$purchaseId] =
$getPersonalizedCountData['itemsCount'] == $getPersonalizedCountData['completedItemsCount'];
} else {
$personalizedCountData[$purchaseId] = [
'needCustomization' => false,
];
$customize_status[$purchaseId] = true;
}
if (! $purchase->getShipStationShipments()->isEmpty()) {
$purchaseShipment[$purchase->getId()] = $purchase->getShipStationShipments()->get(0);
}
$shippedPurchases[] = $purchase;
}
$showPage = $this->checkPartnerAndStripeExistance();
return $this->render('dashboard/index.html.twig', [
'controller_name' => 'DashboardController',
'showPage' => $showPage,
'purchases' => [
'shipped' => $shippedPurchases,
'notShipped' => $notShippedPurchases,
'personalizedCountData' => $personalizedCountData,
'customize_status' => $customize_status,
'capability' => $capability,
'purchaseShipmentRates' => $purchaseShipmentRates,
'purchaseShipment' => $purchaseShipment,
'hasSelectedRate' => $hasSelectedRates,
],
'complete_pagination' => [
'first_page_link' => $this->generateUrl(
'app_dashboard',
[
'complete_page' => 1,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page,
'working_page_size' => $working_page_size,
]
),
'has_previous' => $complete_page > 1,
'previous_page_link' => $complete_page == 1 ? null : $this->generateUrl(
'app_dashboard',
[
'complete_page' => $complete_page - 1,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page,
'working_page_size' => $working_page_size,
]
),
'page' => $complete_page,
'page_size' => $complete_page_size,
'page_count' => $countOfCompletePages,
'has_next' => $complete_page < $countOfCompletePages,
'next_page_link' => $complete_page >= $countOfCompletePages ? null : $this->generateUrl(
'app_dashboard',
[
'complete_page' => $complete_page + 1,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page,
'working_page_size' => $working_page_size,
]
),
'last_page_link' => $this->generateUrl(
'app_dashboard',
[
'complete_page' => $countOfCompletePages,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page,
'working_page_size' => $working_page_size,
]
),
],
'working_pagination' => [
'first_page_link' => $this->generateUrl(
'app_dashboard',
[
'complete_page' => $complete_page,
'complete_page_size' => $complete_page_size,
'working_page' => 1,
'working_page_size' => $working_page_size,
]
),
'has_previous' => $working_page > 1,
'previous_page_link' => $working_page == 1 ? null : $this->generateUrl(
'app_dashboard',
[
'complete_page' => $complete_page,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page - 1,
'working_page_size' => $working_page_size,
]
),
'page' => $working_page,
'page_size' => $working_page_size,
'page_count' => $countOfWorkingPages,
'has_next' => $complete_page < $countOfCompletePages,
'next_page_link' => $complete_page >= $countOfCompletePages ? null : $this->generateUrl(
'app_dashboard',
[
'complete_page' => $complete_page + 1,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page,
'working_page_size' => $working_page_size,
]
),
'last_page_link' => $this->generateUrl(
'app_dashboard',
[
'complete_page' => $countOfCompletePages,
'complete_page_size' => $complete_page_size,
'working_page' => $working_page,
'working_page_size' => $working_page_size,
]
),
],
]);
}
public function getPersonalizedItemsCountData($purchaseId): array
{
$purchaseItemEtsyRepository = $this->entityManager->getRepository(PurchaseItemEtsy::class);
$purchaseItemsEtsy = $purchaseItemEtsyRepository->findBy(['purchase' => $purchaseId]);
$countPersonalized = 0;
$countCompleted = 0;
foreach ($purchaseItemsEtsy as $purchaseItemEtsy) {
if (empty($purchaseItemEtsy->getPersonalizationInstruction())) {
continue;
}
$sideByNumber = [];
foreach ($purchaseItemEtsy->getPurchaseItemSides() as $purchaseItemSide) {
$sideByNumber[$purchaseItemSide->getItemNumber()] ??= 1;
}
$countPersonalized += $purchaseItemEtsy->getQuantity();
$countCompleted += count($sideByNumber);
}
return [
'itemsCount' => $countPersonalized,
'completedItemsCount' => $countCompleted,
'needCustomization' => true,
];
}
#[Route('/purchase-item-seller-notes', name: 'purchaseItemSellerNotes', methods: ["POST"])]
public function purchaseItemSellerNotes(Request $request): JsonResponse
{
//@todo check that the user has access to the purchase
$data = json_decode($request->getContent(), true);
$purchaseId = $data['purchaseId'] ?? null;
$notes = $data['notes'] ?? '';
$type = $data['type'] ?? '';
if(!$purchaseId && $notes == ''){
return new JsonResponse(
[
'message' => 'Something went wrong.',
'status' => false
]);
}
if( $type == 'order'){
$purchaseEtsyRepository = $this->entityManager->getRepository(PurchaseEtsy::class);
$purchaseEtsy = $purchaseEtsyRepository->find($purchaseId);
$purchaseEtsy->setSellerNotes($notes);
$this->entityManager->persist($purchaseEtsy);
}
$purchaseItemRepository = $this->entityManager->getRepository(PurchaseItemEtsy::class);
$purchaseItemsEtsy = $purchaseItemRepository->findBy(['purchase' => $purchaseId]);
$purchaseItemsEtsySellerNotesRepository = new PurchaseItemsEtsySellerNotes;
foreach ($purchaseItemsEtsy as $purchaseItemEtsy) {
$purchaseItemsEtsySellerNotesRepository->setSellerNotes($notes);
$purchaseItemsEtsySellerNotesRepository->setPurchaseItem($purchaseItemEtsy);
$this->entityManager->persist($purchaseItemsEtsySellerNotesRepository);
}
$this->entityManager->flush();
return new JsonResponse(
[
'message' => 'Notes saved successfully.',
'status' => true
]);
}
#[Route('/purchase-set-shipping-rate', name: 'purchaseSetShippingRate', methods: ["POST"])]
public function purchaseSetShippingRate(Request $request): JsonResponse
{
//@todo check that the user has access to the purchase
$data = $request->toArray();
$purchaseId = $data['purchaseId'] ?? null;
$rateId = $data['rateId'] ?? null;
if(!$purchaseId && !$rateId){
return new JsonResponse(
[
'message' => 'Data is incomplete.',
'status' => false
]);
}
$purchaseRepository = $this->entityManager->getRepository(Purchase::class);
$purchase = $purchaseRepository->find($purchaseId);
$purchaseShipStationRateRepository = $this->entityManager->getRepository(PurchaseShipStationRate::class);
$purchaseShipStationRate = $purchaseShipStationRateRepository->findOneBy(
[
'purchase' => $purchase,
'id' => $rateId,
],
);
$selectedRates = $purchaseShipStationRateRepository->findBy(
[
'purchase' => $purchase,
'selected' => 'yes',
]
);
foreach ($selectedRates as $selectedRate) {
if ($selectedRate->getId() == $rateId) {
continue;
}
$selectedRate->setSelected('no');
$this->entityManager->persist($selectedRate);
$this->entityManager->flush();
}
$purchaseShipStationRate->setSelected('yes');
$this->entityManager->persist($purchaseShipStationRate);
$this->entityManager->flush();
return new JsonResponse(
[
'message' => 'Purchase shipping rate successfully saved.',
'status' => true,
]);
}
}