Skip to content

Commit 471a8ff

Browse files
committed
fix: improve ticket repository performance
remove not needed extra joins
1 parent 5b048ac commit 471a8ff

1 file changed

Lines changed: 153 additions & 43 deletions

File tree

app/Repositories/Summit/DoctrineSummitAttendeeTicketRepository.php

Lines changed: 153 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,130 @@ final class DoctrineSummitAttendeeTicketRepository
4040
implements ISummitAttendeeTicketRepository
4141
{
4242

43+
/** @var array<string, array{0:string,1:'join'|'leftJoin',2:array<int,string>}> */
44+
private array $joinCatalog = [
45+
'o' => ['e.order', 'join', []],
46+
's' => ['o.summit', 'join', ['o']],
47+
'ord_m' => ['o.owner', 'leftJoin', ['o']],
48+
'a' => ['e.owner', 'leftJoin', []],
49+
'a_c' => ['a.company', 'leftJoin', ['a']],
50+
'm' => ['a.member', 'leftJoin', ['a']],
51+
'am' => ['a.manager', 'leftJoin', ['a']],
52+
'm2' => ['am.member', 'leftJoin', ['am']],
53+
'b' => ['e.badge', 'leftJoin', []],
54+
'bt' => ['b.type', 'leftJoin', ['b']],
55+
'al' => ['bt.access_levels', 'leftJoin', ['bt']],
56+
'bf' => ['b.features', 'leftJoin', ['b']],
57+
'bt_bf' => ['bt.badge_features', 'leftJoin', ['bt']],
58+
'prt' => ['b.prints', 'leftJoin', ['b']],
59+
'rr' => ['e.refund_requests', 'leftJoin', []],
60+
'ta' => ['e.applied_taxes', 'leftJoin', []],
61+
'tt' => ['e.ticket_type', 'join', []],
62+
'pc' => ['e.promo_code', 'leftJoin', []],
63+
'pct' => ['pc.tags', 'leftJoin', ['pc']],
64+
'avt' => ['bt.allowed_view_types', 'join', ['bt']],
65+
];
66+
67+
private function ensureJoin(QueryBuilder $qb, string $alias): void
68+
{
69+
if (\in_array($alias, $qb->getAllAliases(), true)) return;
70+
71+
[$path, $type, $deps] = $this->joinCatalog[$alias] ?? [null, null, []];
72+
foreach ($deps as $dep) $this->ensureJoin($qb, $dep);
73+
74+
if ($type === 'join') $qb->join($path, $alias);
75+
else $qb->leftJoin($path, $alias);
76+
}
77+
78+
/**
79+
* choose alias needed
80+
* @return string[]
81+
*/
82+
private function requiredAliases(?Filter $filter, ?Order $order): array
83+
{
84+
$need = [];
85+
86+
$has = fn(string $f) => $filter?->hasFilter($f) ?? false;
87+
$ord = fn(string $f) => $order?->hasOrder($f) ?? false;
88+
$val = fn(string $f) => $filter?->getValue($f)[0] ?? null;
89+
90+
// --- Filters ---
91+
if ($has('order_number') || $has('order_id') || $has('order_owner_id') || $has('bought_date') || $has('summit_id')) {
92+
$need['o'] = true;
93+
}
94+
if ($has('summit_id')) $need['s'] = true;
95+
96+
if ($has('owner_first_name') || $has('owner_last_name') || $has('owner_name') || $has('owner_id')) {
97+
$need['a'] = true;
98+
if ($has('owner_name')) $need['m'] = true;
99+
}
100+
101+
if ($has('owner_email')) {
102+
$need['a'] = $need['m'] = $need['am'] = $need['m2'] = true;
103+
}
104+
105+
if ($has('owner_company') || $has('has_owner_company')) { $need['a'] = $need['a_c'] = true; }
106+
107+
if ($has('has_owner')) {
108+
if ((string)$val('has_owner') === '1') $this->joinCatalog['a'][1] = 'join';
109+
$need['a'] = true;
110+
}
111+
112+
if ($has('has_order_owner')) {
113+
if ((string)$val('has_order_owner') === '1') $this->joinCatalog['ord_m'][1] = 'join';
114+
$need['o'] = $need['ord_m'] = true;
115+
}
116+
117+
if ($has('promo_code') || $has('promo_code_id') || $has('promo_code_description')) {
118+
$need['pc'] = true;
119+
}
120+
if ($has('promo_code_tag') || $has('promo_code_tag_id')) {
121+
$need['pc'] = $need['pct'] = true;
122+
}
123+
124+
if ($has('ticket_type_id') || $ord('ticket_type')) $need['tt'] = true;
125+
126+
if ($has('has_badge') || $ord('badge_type') || $ord('badge_type_id') || $has('badge_type_id')) {
127+
$need['b'] = $need['bt'] = true;
128+
}
129+
130+
if ($has('access_level_type_id') || $has('access_level_type_name') || $has('is_printable')) {
131+
$need['b'] = $need['bt'] = $need['al'] = $need['a'] = true;
132+
if ($has('is_printable') && (string)$val('is_printable') === '1') {
133+
$this->joinCatalog['a'][1] = 'join';
134+
$this->joinCatalog['bt'][1] = 'join';
135+
$this->joinCatalog['al'][1] = 'join';
136+
}
137+
}
138+
139+
if ($has('badge_features_id')) {
140+
$need['b'] = $need['bt'] = $need['bf'] = $need['bt_bf'] = true;
141+
}
142+
143+
if ($has('has_badge_prints') || $ord('badge_prints_count')) {
144+
$need['b'] = $need['prt'] = true;
145+
}
146+
147+
if ($has('has_requested_refund_requests') || $ord('refunded_amount') || $ord('final_amount_adjusted')) {
148+
$need['rr'] = true;
149+
}
150+
151+
if ($has('view_type_id')) {
152+
$need['b'] = $need['bt'] = $need['avt'] = true;
153+
}
154+
155+
// --- Order ---
156+
if ($ord('owner_first_name') || $ord('owner_last_name') || $ord('owner_name')) {
157+
$need['a'] = $need['m'] = true;
158+
}
159+
if ($ord('owner_company')) { $need['a'] = $need['a_c'] = true; }
160+
if ($ord('owner_email')) { $need['a'] = $need['m'] = true; }
161+
if ($ord('promo_code')) { $need['pc'] = true; }
162+
163+
return array_keys($need);
164+
}
165+
166+
43167
/**
44168
* @return string
45169
*/
@@ -55,22 +179,31 @@ protected function getBaseEntity()
55179
* @return QueryBuilder
56180
*/
57181
protected function applyExtraSelects(QueryBuilder $query, ?Filter $filter = null, ?Order $order = null):QueryBuilder{
58-
//$query = $query->addSelect("COALESCE(SUM(ta.amount),0) AS HIDDEN HIDDEN_APPLIED_TAXES");
59-
60-
if(!is_null($order)){
61-
if ($order->hasOrder('final_amount'))
62-
$query = $query->addSelect("(e.raw_cost - e.discount) AS HIDDEN HIDDEN_FINAL_AMOUNT");
63182

64-
if ($order->hasOrder('refunded_amount'))
65-
$query = $query->addSelect("COALESCE(SUM(rr.refunded_amount),0) AS HIDDEN HIDDEN_REFUNDED_AMOUNT");
183+
$needsAggregation = false;
66184

67-
if ($order->hasOrder('final_amount_adjusted'))
68-
$query = $query->addSelect("( (e.raw_cost - e.discount) - COALESCE(SUM(rr.refunded_amount),0) ) AS HIDDEN HIDDEN_FINAL_AMOUNT_ADJUSTED");
185+
if ($order) {
186+
if ($order->hasOrder('final_amount')) {
187+
$query->addSelect("(e.raw_cost - e.discount) AS HIDDEN HIDDEN_FINAL_AMOUNT");
188+
}
189+
if ($order->hasOrder('refunded_amount')) {
190+
$query->addSelect("COALESCE(SUM(rr.refunded_amount),0) AS HIDDEN HIDDEN_REFUNDED_AMOUNT");
191+
$needsAggregation = true;
192+
}
193+
if ($order->hasOrder('final_amount_adjusted')) {
194+
$query->addSelect("((e.raw_cost - e.discount) - COALESCE(SUM(rr.refunded_amount),0)) AS HIDDEN HIDDEN_FINAL_AMOUNT_ADJUSTED");
195+
$needsAggregation = true;
196+
}
197+
if ($order->hasOrder('badge_prints_count')) {
198+
$query->addSelect("COUNT(prt.id) AS HIDDEN HIDDEN_BADGE_PRINTS_COUNT");
199+
$needsAggregation = true;
200+
}
201+
}
69202

70-
if ($order->hasOrder('badge_prints_count'))
71-
$query = $query->addSelect("COUNT(prt.id) AS HIDDEN HIDDEN_BADGE_PRINTS_COUNT");
203+
if ($needsAggregation) {
204+
$query->groupBy('e.id');
72205
}
73-
$query->groupBy("e");
206+
74207
return $query;
75208
}
76209
/**
@@ -276,37 +409,14 @@ protected function getFilterMappings()
276409
*/
277410
protected function applyExtraJoins(QueryBuilder $query, ?Filter $filter = null, ?Order $order = null)
278411
{
279-
$query->join("e.order", "o");
280-
$query = $query->join("o.summit", "s");
281-
$query = $query->leftJoin("o.owner", "ord_m");
282-
$query = $query->leftJoin("e.owner", "a");
283-
$query = $query->leftJoin("a.company", "a_c");
284-
$query = $query->leftJoin("e.badge", "b");
285-
$query = $query->leftJoin("b.features", "bf");
286-
$query = $query->leftJoin("b.prints", "prt");
287-
$query = $query->leftJoin("b.type", "bt");
288-
$query = $query->leftJoin("bt.access_levels", "al");
289-
$query = $query->leftJoin('bt.badge_features','bt_bf');
290-
$query = $query->leftJoin("a.member", "m");
291-
$query = $query->leftJoin("e.refund_requests", "rr");
292-
$query = $query->leftJoin("e.applied_taxes", "ta");
293-
$query = $query->join("e.ticket_type", "tt");
294-
$query = $query->leftJoin("e.promo_code", "pc");
295-
296-
if ($filter->hasFilter('promo_code_tag_id') || $filter->hasFilter('promo_code_tag')) {
297-
if (!collect($query->getAllAliases())->contains('pc')) {
298-
$query = $query->leftJoin("e.promo_code", "pc");
299-
}
300-
$query = $query->leftJoin("pc.tags", "pct");
301-
}
302-
if ($filter->hasFilter('view_type_id')) {
303-
$query = $query->join("bt.allowed_view_types", "avt");
304-
}
305-
if($filter->hasFilter("owner_email")){
306-
// add all managed tickets too
307-
$query = $query->leftJoin("a.manager", "am");
308-
$query = $query->leftJoin("am.member", "m2");
412+
$this->joinCatalog['a'][1] = 'leftJoin';
413+
$this->joinCatalog['bt'][1] = 'leftJoin';
414+
$this->joinCatalog['al'][1] = 'leftJoin';
415+
416+
foreach ($this->requiredAliases($filter, $order) as $alias) {
417+
$this->ensureJoin($query, $alias);
309418
}
419+
310420
return $query;
311421
}
312422

@@ -581,4 +691,4 @@ public function getAllTicketsIdsByOrder(int $order_id, PagingInfo $paging_info):
581691
$res = $query->getQuery()->getArrayResult();
582692
return array_column($res, 'id');
583693
}
584-
}
694+
}

0 commit comments

Comments
 (0)