From 60c287904b71e6f0a925d33a9013996f06915357 Mon Sep 17 00:00:00 2001 From: smarcet Date: Tue, 7 Oct 2025 13:56:32 -0300 Subject: [PATCH 1/4] feat: add new filters to orders/tickets endpoints GET api/v1/summits/{id}/orders/me * tickets_owner_email * tickets_number GET api/v1/summits/{id}/orders/all/tickets/me * order_number * number * order_owner_email GET api/v1/summits/all/orders/{order_id}/tickets * number * owner_email --- .../Summit/OAuth2SummitOrdersApiController.php | 12 ++++++++++-- .../Summit/OAuth2SummitTicketApiController.php | 4 ++-- .../DoctrineSummitAttendeeTicketRepository.php | 6 ++++-- .../Summit/DoctrineSummitOrderRepository.php | 6 ++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitOrdersApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitOrdersApiController.php index 6ed450c13..403d557c0 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitOrdersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitOrdersApiController.php @@ -420,13 +420,15 @@ public function getAllMyOrdersBySummit($summit_id) return $this->_getAll( function () { return [ - 'number' => ['=@', '=='], + 'number' => ['=@', '==','@@'], 'summit_id' => ['=='], 'status' => ['==', '<>'], 'owner_id' => ['=='], 'created' => ['>', '<', '<=', '>=', '==','[]'], + 'tickets_number' => ['=@', '==','@@'], 'tickets_assigned_to' => ['=='], 'tickets_owner_status' => ['=='], + 'tickets_owner_email' => ['=@', '==','@@'], 'tickets_badge_features_id' => ['=='], 'tickets_type_id' => ['=='], 'amount' => ['==', '<>', '>=', '>'], @@ -440,7 +442,9 @@ function () { 'summit_id' => 'sometimes|integer', 'owner_id' => 'sometimes|integer', 'created' => 'sometimes|required|date_format:U|epoch_seconds', + 'tickets_number' => 'sometimes|string', 'tickets_assigned_to' => sprintf('sometimes|in:%s', implode(',', ['Me', 'SomeoneElse', 'Nobody'])), + 'tickets_owner_email' => 'sometimes|string', 'tickets_owner_status' => sprintf('sometimes|in:%s', implode(',', SummitAttendee::AllowedStatus)), 'tickets_badge_features_id' => 'sometimes|integer', 'tickets_type_id' => 'sometimes|integer', @@ -1121,6 +1125,8 @@ public function getMyTicketsByOrderId($order_id) return $this->_getAll( function () { return [ + 'number' => ['=@', '==', '@@'], + 'owner_email' => ['=@', '==', '@@'], 'order_id' => ['=='], 'order_owner_id' => ['=='], 'is_active' => ['=='], @@ -1134,6 +1140,8 @@ function () { }, function () { return [ + 'number' => 'sometimes|string', + 'owner_email' => 'sometimes|string', 'order_id' => 'sometimes|integer', 'order_owner_id' => 'sometimes|integer', 'is_active' => ['sometimes', new Boolean()], @@ -1370,4 +1378,4 @@ public function delegateTicket($summit_id, $order_id, $ticket_id) )); }); } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php index b4aab852f..4e6bfca73 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php @@ -621,8 +621,8 @@ public function getAllMyTicketsBySummit($summit_id) return $this->_getAll( function () { return [ - 'number' => ['=@', '=='], - 'order_number' => ['=@', '=='], + 'number' => ['=@', '==', '@@'], + 'order_number' => ['=@', '==', '@@'], 'summit_id' => ['=='], 'order_id' => ['=='], 'status' => ['==', '<>'], diff --git a/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php b/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php index 4a3068c54..9629a92fd 100644 --- a/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php +++ b/app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php @@ -98,9 +98,10 @@ private function requiredAliases(?Filter $filter, ?Order $order): array $val = fn(string $f) => $filter?->getValue($f)[0] ?? null; // --- Filters --- - if ($has('order_number') || $has('order_id') || $has('order_owner_id') || $has('bought_date') || $has('summit_id')) { + if ($has('order_number') || $has('order_id') || $has('order_owner_id') || $has('order_owner_email') + || $has('bought_date') || $has('summit_id')) { $need['o'] = true; - if ($has('order_owner_id')) { + if ($has('order_owner_id') || $has('order_owner_email')) { $this->joinCatalog['ord_m'][1] = 'join'; $need['ord_m'] = true; } @@ -265,6 +266,7 @@ protected function getFilterMappings() 'number' => 'e.number:json_string', 'is_active' => 'e.is_active', 'order_number' => 'o.number:json_string', + 'order_owner_email' => 'COALESCE(ord_m.email, o.owner_email)', 'owner_name' => "COALESCE(LOWER(CONCAT(a.first_name, ' ', a.surname)),LOWER(CONCAT(m.first_name, ' ', m.last_name)))", 'owner_company' => 'COALESCE(a.company_name, a_c.name)', 'has_owner_company' => new DoctrineSwitchFilterMapping([ diff --git a/app/Repositories/Summit/DoctrineSummitOrderRepository.php b/app/Repositories/Summit/DoctrineSummitOrderRepository.php index c2988e1c2..eebf3c547 100644 --- a/app/Repositories/Summit/DoctrineSummitOrderRepository.php +++ b/app/Repositories/Summit/DoctrineSummitOrderRepository.php @@ -19,6 +19,7 @@ use models\summit\IOrderConstants; use models\summit\Summit; use models\summit\SummitAttendee; +use models\summit\SummitAttendeeTicket; use models\summit\SummitOrder; use models\utils\SilverstripeBaseModel; use utils\DoctrineCaseFilterMapping; @@ -72,6 +73,11 @@ protected function getFilterMappings() 'tickets_owner_status' => 'to.status:json_string', 'tickets_promo_code' => 'pc.code:json_string', 'tickets_type_id' => 'tt.id', + 'tickets_owner_email' => sprintf('EXISTS ( SELECT 1 FROM %s to1:i + JOIN to1:i.owner to1_o:i + LEFT JOIN to1_o:i.member to1_o_m:i + WHERE to1:i.order = e AND COALESCE(LOWER(to1_o:i.email), LOWER(to1_o_m:i.email)) :operator :value )',SummitAttendeeTicket::class), + 'tickets_number' => sprintf('EXISTS ( SELECT 1 FROM %s to1:i where to1:i.order = e )',SummitAttendeeTicket::class), 'tickets_badge_features_id' => ['bf.id:json_int','bt_bf.id:json_int'], 'tickets_assigned_to' => new DoctrineSwitchFilterMapping([ 'Me' => new DoctrineCaseFilterMapping( From 803d698775796ee7427b80fb939c78a026f52e38 Mon Sep 17 00:00:00 2001 From: smarcet Date: Thu, 9 Oct 2025 14:22:52 -0300 Subject: [PATCH 2/4] fix: add missing filter order_owner_email --- .../Apis/Protected/Summit/OAuth2SummitTicketApiController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php index 4e6bfca73..9ee2fb37f 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php @@ -623,6 +623,7 @@ function () { return [ 'number' => ['=@', '==', '@@'], 'order_number' => ['=@', '==', '@@'], + 'order_owner_email' => ['=@', '==', '@@'], 'summit_id' => ['=='], 'order_id' => ['=='], 'status' => ['==', '<>'], @@ -640,6 +641,7 @@ function () { return [ 'number' => 'sometimes|string', 'order_number' => 'sometimes|string', + 'order_owner_email' => 'sometimes|string', 'summit_id' => 'sometimes|integer', 'order_id' => 'sometimes|integer', 'order_owner_id' => 'sometimes|integer', From 0f82a983748e97f97d98336739817701b82f5d54 Mon Sep 17 00:00:00 2001 From: smarcet Date: Thu, 9 Oct 2025 14:58:52 -0300 Subject: [PATCH 3/4] fix: query missing class --- .../DoctrineApiEndpointRepository.php | 25 +++++++++++-------- .../Summit/DoctrineSummitOrderRepository.php | 13 +++++----- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php b/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php index b44c9d667..f876ebb3e 100644 --- a/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php +++ b/app/Repositories/ResourceServer/DoctrineApiEndpointRepository.php @@ -38,17 +38,22 @@ final class DoctrineApiEndpointRepository public function getApiEndpointByUrlAndMethod($url, $http_method) { try { - return $this->getEntityManager()->createQueryBuilder() - ->select("e") - ->from(\App\Models\ResourceServer\ApiEndpoint::class, "e") + $em = $this->getEntityManager(); + + $qb = $em->createQueryBuilder(); + $qb->select('e') + ->from(ApiEndpoint::class, 'e') + ->leftJoin('e.scopes', 's', 'WITH', 's.active = true') + ->addSelect('s') ->where('e.route = :route') - ->andWhere('e.http_method = :http_method') + ->andWhere('e.http_method = :method') ->setParameter('route', trim($url)) - ->setParameter('http_method', trim($http_method)) - ->setCacheable(true) - ->setCacheRegion('resource_server_region') - ->getQuery() - ->getOneOrNullResult(); + ->setParameter('method', strtoupper(trim($http_method))); + + $q = $qb->getQuery(); + $q->setCacheable(false); + + return $q->getOneOrNullResult(); } catch(\Exception $ex){ Log::error($ex); @@ -80,4 +85,4 @@ protected function getOrderMappings() return []; } -} \ No newline at end of file +} diff --git a/app/Repositories/Summit/DoctrineSummitOrderRepository.php b/app/Repositories/Summit/DoctrineSummitOrderRepository.php index eebf3c547..afd28f04b 100644 --- a/app/Repositories/Summit/DoctrineSummitOrderRepository.php +++ b/app/Repositories/Summit/DoctrineSummitOrderRepository.php @@ -73,11 +73,11 @@ protected function getFilterMappings() 'tickets_owner_status' => 'to.status:json_string', 'tickets_promo_code' => 'pc.code:json_string', 'tickets_type_id' => 'tt.id', - 'tickets_owner_email' => sprintf('EXISTS ( SELECT 1 FROM %s to1:i - JOIN to1:i.owner to1_o:i - LEFT JOIN to1_o:i.member to1_o_m:i - WHERE to1:i.order = e AND COALESCE(LOWER(to1_o:i.email), LOWER(to1_o_m:i.email)) :operator :value )',SummitAttendeeTicket::class), - 'tickets_number' => sprintf('EXISTS ( SELECT 1 FROM %s to1:i where to1:i.order = e )',SummitAttendeeTicket::class), + 'tickets_owner_email' => new DoctrineFilterMapping(sprintf('EXISTS ( SELECT 1 FROM %s to1 + JOIN to1.owner to1_o + LEFT JOIN to1_o.member to1_o_m + WHERE to1.order = e AND COALESCE(LOWER(to1_o.email), LOWER(to1_o_m.email)) :operator :value )',SummitAttendeeTicket::class)), + 'tickets_number' => sprintf('EXISTS ( SELECT 1 FROM %s to2 where to2.order = e )',SummitAttendeeTicket::class), 'tickets_badge_features_id' => ['bf.id:json_int','bt_bf.id:json_int'], 'tickets_assigned_to' => new DoctrineSwitchFilterMapping([ 'Me' => new DoctrineCaseFilterMapping( @@ -207,9 +207,10 @@ public function getByPaymentGatewayCartIdExclusiveLock(string $payment_gateway_c { $query = $this->getEntityManager() ->createQueryBuilder() - ->select("DISTINCT o, t") + ->select("o") ->from($this->getBaseEntity(), "o") ->leftJoin('o.tickets', 't') + ->addSelect('t') ->where("o.payment_gateway_cart_id = :payment_gateway_cart_id") ->setParameter("payment_gateway_cart_id", trim($payment_gateway_cart_id)); From 412e652c7807c9a0499f702c421a4afc914033df Mon Sep 17 00:00:00 2001 From: smarcet Date: Thu, 9 Oct 2025 15:10:09 -0300 Subject: [PATCH 4/4] chore: fix filter --- .../Summit/DoctrineSummitOrderRepository.php | 333 +++++++++--------- 1 file changed, 166 insertions(+), 167 deletions(-) diff --git a/app/Repositories/Summit/DoctrineSummitOrderRepository.php b/app/Repositories/Summit/DoctrineSummitOrderRepository.php index afd28f04b..317bbe5cd 100644 --- a/app/Repositories/Summit/DoctrineSummitOrderRepository.php +++ b/app/Repositories/Summit/DoctrineSummitOrderRepository.php @@ -11,6 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + use App\Models\Foundation\Summit\Repositories\ISummitOrderRepository; use App\Repositories\SilverStripeDoctrineRepository; use Doctrine\ORM\QueryBuilder; @@ -29,6 +30,7 @@ use utils\Order; use utils\PagingInfo; use utils\PagingResponse; + /** * Class DoctrineSummitOrderRepository * @package App\Repositories\Summit @@ -38,148 +40,6 @@ final class DoctrineSummitOrderRepository implements ISummitOrderRepository { - /** - * @return array - */ - protected function getFilterMappings() - { - $args = func_get_args(); - $filter = count($args) > 0 ? $args[0] : null; - $tickets_owner_member_id = 0; - $tickets_owner_member_email = null; - if(!is_null($filter) && $filter instanceof Filter) { - if ($filter->hasFilter("tickets_owner_member_id")) { - $tickets_owner_member_id = $filter->getValue("tickets_owner_member_id")[0]; - } - if ($filter->hasFilter("tickets_owner_member_email")) { - $tickets_owner_member_email = $filter->getValue("tickets_owner_member_email")[0]; - } - } - return [ - 'number' => 'e.number:json_string', - 'summit_id' => new DoctrineFilterMapping("s.id :operator :value"), - 'owner_id' => new DoctrineFilterMapping("o.id :operator :value"), - 'owner_name' => "COALESCE(LOWER(CONCAT(o.first_name, ' ', o.last_name)), LOWER(CONCAT(e.owner_first_name, ' ', e.owner_surname)))", - 'owner_email' => "COALESCE(LOWER(o.email), LOWER(e.owner_email))", - 'owner_company' => ['e.owner_company_name:json_string', 'oc.name:json_string'], - 'status' => 'e.status:json_string', - 'ticket_owner_name' => "COALESCE(LOWER(CONCAT(to.first_name, ' ', to.surname)), LOWER(CONCAT(tom.first_name, ' ', tom.last_name)))", - 'ticket_owner_email' => "COALESCE(LOWER(to.email), LOWER(tom.email))", - 'ticket_number' => new DoctrineFilterMapping("t.number :operator :value"), - 'created' => sprintf('e.created:datetime_epoch|%s', SilverstripeBaseModel::DefaultTimeZone), - 'last_edited' => sprintf('e.last_edited:datetime_epoch|%s', SilverstripeBaseModel::DefaultTimeZone), - 'amount' => 'SUMMIT_ORDER_FINAL_AMOUNT(e.id)', - 'payment_method' => 'e.payment_method:json_string', - 'tickets_owner_status' => 'to.status:json_string', - 'tickets_promo_code' => 'pc.code:json_string', - 'tickets_type_id' => 'tt.id', - 'tickets_owner_email' => new DoctrineFilterMapping(sprintf('EXISTS ( SELECT 1 FROM %s to1 - JOIN to1.owner to1_o - LEFT JOIN to1_o.member to1_o_m - WHERE to1.order = e AND COALESCE(LOWER(to1_o.email), LOWER(to1_o_m.email)) :operator :value )',SummitAttendeeTicket::class)), - 'tickets_number' => sprintf('EXISTS ( SELECT 1 FROM %s to2 where to2.order = e )',SummitAttendeeTicket::class), - 'tickets_badge_features_id' => ['bf.id:json_int','bt_bf.id:json_int'], - 'tickets_assigned_to' => new DoctrineSwitchFilterMapping([ - 'Me' => new DoctrineCaseFilterMapping( - 'Me', - sprintf - ( - "( to is not null and ( tom.id = %s or to.email = '%s' ))", - $tickets_owner_member_id, - $tickets_owner_member_email - ), - ), - 'SomeoneElse' => new DoctrineCaseFilterMapping( - 'SomeoneElse', - sprintf - ( - "( to is not null and tom.id <> %s and to.email <> '%s' )", - $tickets_owner_member_id, - $tickets_owner_member_email - ), - ), - 'Nobody' => new DoctrineCaseFilterMapping( - 'Nobody', - "to is null" - ), - ] - ), - ]; - } - - /** - * @param QueryBuilder $query - * @return QueryBuilder - */ - protected function applyExtraJoins(QueryBuilder $query, ?Filter $filter = null, ?Order $order = null){ - $query - ->join('e.tickets','t') - ->join('e.summit','s') - ->leftJoin('e.owner','o') - ->leftJoin('t.owner','to') - ->leftJoin('to.member', 'tom'); - - if((!is_null($filter) && $filter->hasFilter("owner_company")) || - (!is_null($order)) && $order->hasOrder("owner_company")){ - $query = $query->leftJoin("e.owner_company","oc"); - } - if((!is_null($filter) && $filter->hasFilter("tickets_badge_features_id"))){ - $query = $query->leftJoin('t.badge','b') - ->leftJoin('b.features','bf') - ->leftJoin('b.type','bt') - ->leftJoin('bt.badge_features','bt_bf'); - } - if((!is_null($filter) && $filter->hasFilter("tickets_type_id"))){ - $query = $query->leftJoin('t.ticket_type','tt'); - } - if((!is_null($filter) && $filter->hasFilter("tickets_promo_code"))){ - $query = $query->leftJoin('t.promo_code','pc'); - } - return $query; - } - - /** - * @return array - */ - protected function getOrderMappings() - { - return [ - 'number' => 'e.number', - 'id' => 'e.id', - 'status' => 'e.status', - 'created' => 'e.created', - 'owner_name' => << << << 'o.id', - 'amount' => 'SUMMIT_ORDER_FINAL_AMOUNT(e.id)', - 'payment_method' => 'e.payment_method' - ]; - } - - /** - * @param QueryBuilder $query - * @return QueryBuilder - */ - protected function applyExtraFilters(QueryBuilder $query){ - $query = $query->andWhere("e.status <> :cancelled")->setParameter("cancelled", IOrderConstants::CancelledStatus); - return $query; - } - - /** - * @return string - */ - protected function getBaseEntity() - { - return SummitOrder::class; - } - /** * @param string $hash * @return SummitOrder|null @@ -199,6 +59,14 @@ public function getByHashLockExclusive(string $hash): ?SummitOrder ->getOneOrNullResult(); } + /** + * @return string + */ + protected function getBaseEntity() + { + return SummitOrder::class; + } + /** * @param string $payment_gateway_cart_id * @return SummitOrder|null @@ -244,7 +112,8 @@ public function getAllByOwnerEmail(string $email) * @param string $email * @return mixed */ - public function getAllByOwnerEmailAndOwnerNotSet(string $email){ + public function getAllByOwnerEmailAndOwnerNotSet(string $email) + { $query = $this->getEntityManager() ->createQueryBuilder() @@ -337,12 +206,10 @@ public function getByExternalIdAndSummitLockExclusive(Summit $summit, string $ex ->from($this->getBaseEntity(), "e") ->join('e.summit', 's') ->where("e.external_id = :external_id") - ->andWhere('s.id = :summit_id') - ; + ->andWhere('s.id = :summit_id'); $query->setParameter("external_id", $externalId); - $query->setParameter("summit_id", $summit->getId()) - ; + $query->setParameter("summit_id", $summit->getId()); return $query->getQuery() ->setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) ->setHint(\Doctrine\ORM\Query::HINT_REFRESH, true) @@ -354,15 +221,15 @@ public function getByExternalIdAndSummitLockExclusive(Summit $summit, string $ex * @param PagingInfo $paging_info * @return PagingResponse */ - public function getAllOrderThatNeedsEmailActionReminder(Summit $summit, PagingInfo $paging_info):PagingResponse + public function getAllOrderThatNeedsEmailActionReminder(Summit $summit, PagingInfo $paging_info): PagingResponse { $query = $this->getEntityManager() ->createQueryBuilder() ->select("e") ->from($this->getBaseEntity(), "e") - ->join("e.tickets","t") - ->join("e.summit","s") - ->leftJoin("t.owner","o") + ->join("e.tickets", "t") + ->join("e.summit", "s") + ->leftJoin("t.owner", "o") ->where('e.status = :order_status') ->andWhere('s.id = :summit_id') ->andWhere("o is null OR o.status = :attendee_status"); @@ -371,15 +238,15 @@ public function getAllOrderThatNeedsEmailActionReminder(Summit $summit, PagingIn $query->setParameter("summit_id", $summit->getId()); $query->setParameter("attendee_status", SummitAttendee::StatusIncomplete); - $query= $query + $query = $query ->setFirstResult($paging_info->getOffset()) ->setMaxResults($paging_info->getPerPage()); $paginator = new Paginator($query, $fetchJoinCollection = true); - $total = $paginator->count(); - $data = []; + $total = $paginator->count(); + $data = []; - foreach($paginator as $entity) + foreach ($paginator as $entity) $data[] = $entity; return new PagingResponse @@ -397,7 +264,8 @@ public function getAllOrderThatNeedsEmailActionReminder(Summit $summit, PagingIn * @return bool * @throws \Doctrine\DBAL\Driver\Exception */ - public function deleteAllBySummit(int $summit_id):bool{ + public function deleteAllBySummit(int $summit_id): bool + { try { $sql = <<getEntityManager()->getConnection()->prepare($sql); return $stmt->executeStatement([ - 'summit_id' => $summit_id, - ]) > 0; + 'summit_id' => $summit_id, + ]) > 0; - } - catch (\Exception $ex) - { + } catch (\Exception $ex) { Log::error($ex); } } @@ -422,9 +288,9 @@ public function getAllOrderIdsThatNeedsEmailActionReminder(Summit $summit, Pagin ->distinct(true) ->select("e.id") ->from($this->getBaseEntity(), "e") - ->join("e.tickets","t") - ->join("e.summit","s") - ->leftJoin("t.owner","o") + ->join("e.tickets", "t") + ->join("e.summit", "s") + ->leftJoin("t.owner", "o") ->where('e.status = :order_status') ->andWhere('s.id = :summit_id') ->andWhere("o is null OR o.status = :attendee_status"); @@ -433,7 +299,7 @@ public function getAllOrderIdsThatNeedsEmailActionReminder(Summit $summit, Pagin $query->setParameter("summit_id", $summit->getId()); $query->setParameter("attendee_status", SummitAttendee::StatusIncomplete); - $query= $query + $query = $query ->setFirstResult($paging_info->getOffset()) ->setMaxResults($paging_info->getPerPage()); @@ -453,7 +319,7 @@ public function getAllOrderIdsThatNeedsPaymentInfo(Summit $summit, PagingInfo $p ->distinct(true) ->select("e.id") ->from($this->getBaseEntity(), "e") - ->join("e.summit","s") + ->join("e.summit", "s") ->where('e.status = :order_status') ->andWhere('s.id = :summit_id') ->andWhere("e.payment_info_type is null") @@ -462,11 +328,144 @@ public function getAllOrderIdsThatNeedsPaymentInfo(Summit $summit, PagingInfo $p $query->setParameter("order_status", IOrderConstants::PaidStatus); $query->setParameter("summit_id", $summit->getId()); - $query= $query + $query = $query ->setFirstResult($paging_info->getOffset()) ->setMaxResults($paging_info->getPerPage()); $res = $query->getQuery()->getArrayResult(); return array_column($res, 'id'); } + + /** + * @return array + */ + protected function getFilterMappings() + { + $args = func_get_args(); + $filter = count($args) > 0 ? $args[0] : null; + $tickets_owner_member_id = 0; + $tickets_owner_member_email = null; + if (!is_null($filter) && $filter instanceof Filter) { + if ($filter->hasFilter("tickets_owner_member_id")) { + $tickets_owner_member_id = $filter->getValue("tickets_owner_member_id")[0]; + } + if ($filter->hasFilter("tickets_owner_member_email")) { + $tickets_owner_member_email = $filter->getValue("tickets_owner_member_email")[0]; + } + } + return [ + 'number' => 'e.number:json_string', + 'summit_id' => new DoctrineFilterMapping("s.id :operator :value"), + 'owner_id' => new DoctrineFilterMapping("o.id :operator :value"), + 'owner_name' => "COALESCE(LOWER(CONCAT(o.first_name, ' ', o.last_name)), LOWER(CONCAT(e.owner_first_name, ' ', e.owner_surname)))", + 'owner_email' => "COALESCE(LOWER(o.email), LOWER(e.owner_email))", + 'owner_company' => ['e.owner_company_name:json_string', 'oc.name:json_string'], + 'status' => 'e.status:json_string', + 'ticket_owner_name' => "COALESCE(LOWER(CONCAT(to.first_name, ' ', to.surname)), LOWER(CONCAT(tom.first_name, ' ', tom.last_name)))", + 'ticket_owner_email' => "COALESCE(LOWER(to.email), LOWER(tom.email))", + 'ticket_number' => new DoctrineFilterMapping("t.number :operator :value"), + 'created' => sprintf('e.created:datetime_epoch|%s', SilverstripeBaseModel::DefaultTimeZone), + 'last_edited' => sprintf('e.last_edited:datetime_epoch|%s', SilverstripeBaseModel::DefaultTimeZone), + 'amount' => 'SUMMIT_ORDER_FINAL_AMOUNT(e.id)', + 'payment_method' => 'e.payment_method:json_string', + 'tickets_owner_status' => 'to.status:json_string', + 'tickets_promo_code' => 'pc.code:json_string', + 'tickets_type_id' => 'tt.id', + 'tickets_owner_email' => new DoctrineFilterMapping(sprintf('EXISTS ( SELECT 1 FROM %s to1 JOIN to1.owner to1_o LEFT JOIN to1_o.member to1_o_m WHERE to1.order = e AND COALESCE(LOWER(to1_o.email), LOWER(to1_o_m.email)) :operator :value )', SummitAttendeeTicket::class)), + 'tickets_number' => new DoctrineFilterMapping(sprintf('EXISTS ( SELECT 1 FROM %s to2 where to2.order = e AND to2.number :operator :value )', SummitAttendeeTicket::class)), + 'tickets_badge_features_id' => ['bf.id:json_int', 'bt_bf.id:json_int'], + 'tickets_assigned_to' => new DoctrineSwitchFilterMapping([ + 'Me' => new DoctrineCaseFilterMapping( + 'Me', + sprintf + ( + "( to is not null and ( tom.id = %s or to.email = '%s' ))", + $tickets_owner_member_id, + $tickets_owner_member_email + ), + ), + 'SomeoneElse' => new DoctrineCaseFilterMapping( + 'SomeoneElse', + sprintf + ( + "( to is not null and tom.id <> %s and to.email <> '%s' )", + $tickets_owner_member_id, + $tickets_owner_member_email + ), + ), + 'Nobody' => new DoctrineCaseFilterMapping( + 'Nobody', + "to is null" + ), + ] + ), + ]; + } + + /** + * @param QueryBuilder $query + * @return QueryBuilder + */ + protected function applyExtraJoins(QueryBuilder $query, ?Filter $filter = null, ?Order $order = null) + { + $query + ->join('e.tickets', 't') + ->join('e.summit', 's') + ->leftJoin('e.owner', 'o') + ->leftJoin('t.owner', 'to') + ->leftJoin('to.member', 'tom'); + + if ((!is_null($filter) && $filter->hasFilter("owner_company")) || + (!is_null($order)) && $order->hasOrder("owner_company")) { + $query = $query->leftJoin("e.owner_company", "oc"); + } + if ((!is_null($filter) && $filter->hasFilter("tickets_badge_features_id"))) { + $query = $query->leftJoin('t.badge', 'b') + ->leftJoin('b.features', 'bf') + ->leftJoin('b.type', 'bt') + ->leftJoin('bt.badge_features', 'bt_bf'); + } + if ((!is_null($filter) && $filter->hasFilter("tickets_type_id"))) { + $query = $query->leftJoin('t.ticket_type', 'tt'); + } + if ((!is_null($filter) && $filter->hasFilter("tickets_promo_code"))) { + $query = $query->leftJoin('t.promo_code', 'pc'); + } + return $query; + } + + /** + * @return array + */ + protected function getOrderMappings() + { + return [ + 'number' => 'e.number', + 'id' => 'e.id', + 'status' => 'e.status', + 'created' => 'e.created', + 'owner_name' => << << << 'o.id', + 'amount' => 'SUMMIT_ORDER_FINAL_AMOUNT(e.id)', + 'payment_method' => 'e.payment_method' + ]; + } + + /** + * @param QueryBuilder $query + * @return QueryBuilder + */ + protected function applyExtraFilters(QueryBuilder $query) + { + $query = $query->andWhere("e.status <> :cancelled")->setParameter("cancelled", IOrderConstants::CancelledStatus); + return $query; + } }