1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of EC-CUBE |
5
|
|
|
* |
6
|
|
|
* Copyright(c) LOCKON CO.,LTD. All Rights Reserved. |
7
|
|
|
* |
8
|
|
|
* http://www.lockon.co.jp/ |
9
|
|
|
* |
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
11
|
|
|
* file that was distributed with this source code. |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Eccube\Controller\Admin; |
15
|
|
|
|
16
|
|
|
use Carbon\Carbon; |
17
|
|
|
use Doctrine\Common\Collections\Criteria; |
18
|
|
|
use Doctrine\ORM\NoResultException; |
19
|
|
|
use Doctrine\ORM\Query\ResultSetMapping; |
20
|
|
|
use Eccube\Controller\AbstractController; |
21
|
|
|
use Eccube\Entity\Master\CustomerStatus; |
22
|
|
|
use Eccube\Entity\Master\OrderStatus; |
23
|
|
|
use Eccube\Entity\Master\ProductStatus; |
24
|
|
|
use Eccube\Entity\ProductStock; |
25
|
|
|
use Eccube\Event\EccubeEvents; |
26
|
|
|
use Eccube\Event\EventArgs; |
27
|
|
|
use Eccube\Form\Type\Admin\ChangePasswordType; |
28
|
|
|
use Eccube\Form\Type\Admin\LoginType; |
29
|
|
|
use Eccube\Repository\CustomerRepository; |
30
|
|
|
use Eccube\Repository\Master\OrderStatusRepository; |
31
|
|
|
use Eccube\Repository\MemberRepository; |
32
|
|
|
use Eccube\Repository\OrderRepository; |
33
|
|
|
use Eccube\Repository\ProductRepository; |
34
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
35
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
36
|
|
|
use Symfony\Component\HttpFoundation\Request; |
37
|
|
|
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; |
38
|
|
|
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; |
39
|
|
|
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; |
40
|
|
|
|
41
|
|
|
class AdminController extends AbstractController |
42
|
|
|
{ |
43
|
|
|
/** |
44
|
|
|
* @var AuthorizationCheckerInterface |
45
|
|
|
*/ |
46
|
|
|
protected $authorizationChecker; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var AuthenticationUtils |
50
|
|
|
*/ |
51
|
|
|
protected $helper; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var MemberRepository |
55
|
|
|
*/ |
56
|
|
|
protected $memberRepository; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var EncoderFactoryInterface |
60
|
|
|
*/ |
61
|
|
|
protected $encoderFactory; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var OrderRepository |
65
|
|
|
*/ |
66
|
|
|
protected $orderRepository; |
67
|
|
|
|
68
|
10 |
|
/** |
69
|
|
|
* @var OrderStatusRepository |
70
|
|
|
*/ |
71
|
|
|
protected $orderStatusRepository; |
72
|
|
|
|
73
|
|
|
/** |
74
|
10 |
|
* @var CustomerRepository |
75
|
10 |
|
*/ |
76
|
10 |
|
protected $customerRepository; |
77
|
10 |
|
|
78
|
|
|
/** |
79
|
|
|
* @var ProductRepository |
80
|
|
|
*/ |
81
|
|
|
protected $productRepository; |
82
|
|
|
|
83
|
|
|
/** |
84
|
2 |
|
* AdminController constructor. |
85
|
|
|
* |
86
|
2 |
|
* @param AuthorizationCheckerInterface $authorizationChecker |
87
|
|
|
* @param AuthenticationUtils $helper |
88
|
|
|
* @param MemberRepository $memberRepository |
89
|
|
|
* @param EncoderFactoryInterface $encoderFactory |
90
|
|
|
* @param OrderRepository $orderRepository |
91
|
2 |
|
* @param OrderStatusRepository $orderStatusRepository |
92
|
|
|
* @param CustomerRepository $custmerRepository |
93
|
2 |
|
* @param ProductRepository $productRepository |
94
|
|
|
*/ |
95
|
2 |
|
public function __construct( |
96
|
|
|
AuthorizationCheckerInterface $authorizationChecker, |
97
|
2 |
|
AuthenticationUtils $helper, |
98
|
|
|
MemberRepository $memberRepository, |
99
|
2 |
|
EncoderFactoryInterface $encoderFactory, |
100
|
|
|
OrderRepository $orderRepository, |
101
|
2 |
|
OrderStatusRepository $orderStatusRepository, |
102
|
|
|
CustomerRepository $custmerRepository, |
103
|
|
|
ProductRepository $productRepository |
104
|
2 |
|
) { |
105
|
2 |
|
$this->authorizationChecker = $authorizationChecker; |
106
|
|
|
$this->helper = $helper; |
107
|
|
|
$this->memberRepository = $memberRepository; |
108
|
|
|
$this->encoderFactory = $encoderFactory; |
109
|
|
|
$this->orderRepository = $orderRepository; |
110
|
|
|
$this->orderStatusRepository = $orderStatusRepository; |
111
|
|
|
$this->customerRepository = $custmerRepository; |
112
|
|
|
$this->productRepository = $productRepository; |
113
|
4 |
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
4 |
|
* @Route("/%eccube_admin_route%/login", name="admin_login") |
117
|
|
|
* @Template("@admin/login.twig") |
118
|
|
|
*/ |
119
|
|
|
public function login(Request $request) |
120
|
|
|
{ |
121
|
|
|
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) { |
122
|
|
|
return $this->redirectToRoute('admin_homepage'); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/* @var $form \Symfony\Component\Form\FormInterface */ |
126
|
|
|
$builder = $this->formFactory->createNamedBuilder('', LoginType::class); |
127
|
|
|
|
128
|
|
|
$event = new EventArgs( |
129
|
|
|
[ |
130
|
4 |
|
'builder' => $builder, |
131
|
|
|
], |
132
|
4 |
|
$request |
133
|
|
|
); |
134
|
4 |
|
$this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_LOGIN_INITIALIZE, $event); |
135
|
|
|
|
136
|
4 |
|
$form = $builder->getForm(); |
137
|
|
|
|
138
|
4 |
|
return [ |
139
|
4 |
|
'error' => $this->helper->getLastAuthenticationError(), |
140
|
4 |
|
'form' => $form->createView(), |
141
|
|
|
]; |
142
|
4 |
|
} |
143
|
|
|
|
144
|
4 |
|
/** |
145
|
|
|
* 管理画面ホーム |
146
|
|
|
* |
147
|
4 |
|
* @param Request $request |
148
|
|
|
* |
149
|
|
|
* @return array |
150
|
4 |
|
* |
151
|
|
|
* @throws NoResultException |
152
|
|
|
* @throws \Doctrine\ORM\NonUniqueResultException |
153
|
4 |
|
* |
154
|
|
|
* @Route("/%eccube_admin_route%/", name="admin_homepage") |
155
|
|
|
* @Template("@admin/index.twig") |
156
|
|
|
*/ |
157
|
|
|
public function index(Request $request) |
158
|
4 |
|
{ |
159
|
4 |
|
/** |
160
|
4 |
|
* 受注状況. |
161
|
4 |
|
*/ |
162
|
4 |
|
$excludes = []; |
163
|
|
|
$excludes[] = OrderStatus::PENDING; |
164
|
4 |
|
$excludes[] = OrderStatus::PROCESSING; |
165
|
|
|
$excludes[] = OrderStatus::CANCEL; |
166
|
4 |
|
$excludes[] = OrderStatus::DELIVERED; |
167
|
|
|
|
168
|
4 |
|
$event = new EventArgs( |
169
|
|
|
[ |
170
|
4 |
|
'excludes' => $excludes, |
171
|
4 |
|
], |
172
|
|
|
$request |
173
|
|
|
); |
174
|
4 |
|
$this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_ORDER, $event); |
175
|
|
|
$excludes = $event->getArgument('excludes'); |
176
|
4 |
|
|
177
|
|
|
// 受注ステータスごとの受注件数. |
178
|
|
|
$Orders = $this->getOrderEachStatus($this->entityManager, $excludes); |
179
|
|
|
|
180
|
|
|
// 受注ステータスの一覧. |
181
|
4 |
|
$Criteria = new Criteria(); |
182
|
4 |
|
$Criteria->where($Criteria::expr()->notIn('id', $excludes)); |
183
|
4 |
|
$OrderStatuses = $this->orderStatusRepository->matching($Criteria, $Criteria->orderBy(['sort_no' => 'ASC'])); |
|
|
|
|
184
|
4 |
|
|
185
|
|
|
/** |
186
|
4 |
|
* 売り上げ状況 |
187
|
|
|
*/ |
188
|
4 |
|
$excludes = []; |
189
|
|
|
$excludes[] = OrderStatus::PROCESSING; |
190
|
4 |
|
$excludes[] = OrderStatus::CANCEL; |
191
|
|
|
$excludes[] = OrderStatus::PENDING; |
192
|
4 |
|
|
193
|
4 |
|
$event = new EventArgs( |
194
|
|
|
[ |
195
|
|
|
'excludes' => $excludes, |
196
|
4 |
|
], |
197
|
|
|
$request |
198
|
4 |
|
); |
199
|
|
|
$this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_SALES, $event); |
200
|
4 |
|
$excludes = $event->getArgument('excludes'); |
201
|
|
|
|
202
|
|
|
// 今日の売上/件数 |
203
|
|
|
$salesToday = $this->getSalesByDay($this->entityManager, new \DateTime(), $excludes); |
204
|
|
|
// 昨日の売上/件数 |
205
|
|
|
$salesYesterday = $this->getSalesByDay($this->entityManager, new \DateTime('-1 day'), $excludes); |
206
|
4 |
|
// 今月の売上/件数 |
207
|
|
|
$salesThisMonth = $this->getSalesByMonth($this->entityManager, new \DateTime(), $excludes); |
208
|
4 |
|
|
209
|
|
|
// 週間の売上金額 |
210
|
4 |
|
$toDate = Carbon::now(); |
211
|
|
|
$fromDate = Carbon::today()->subWeek(); |
212
|
4 |
|
$rawWeekly = $this->getData($excludes, $fromDate, $toDate, 'Y/m/d'); |
213
|
4 |
|
|
214
|
4 |
|
// 月間の売上金額 |
215
|
4 |
|
$fromDate = Carbon::now()->startOfMonth(); |
216
|
4 |
|
$rawMonthly = $this->getData($excludes, $fromDate, $toDate, 'Y/m/d'); |
217
|
4 |
|
|
218
|
4 |
|
// 年間の売上金額 |
219
|
|
|
$fromDate = Carbon::now()->subYear()->startOfMonth(); |
220
|
4 |
|
$rawYear = $this->getData($excludes, $fromDate, $toDate, 'Y/m'); |
221
|
|
|
|
222
|
4 |
|
$datas = [$rawWeekly, $rawMonthly, $rawYear]; |
223
|
|
|
|
224
|
|
|
/** |
225
|
4 |
|
* ショップ状況 |
226
|
4 |
|
*/ |
227
|
4 |
|
// 在庫切れ商品数 |
228
|
4 |
|
$countNonStockProducts = $this->countNonStockProducts(); |
229
|
4 |
|
|
230
|
4 |
|
// 取り扱い商品数 |
231
|
4 |
|
$countProducts = $this->countProducts(); |
232
|
4 |
|
|
233
|
4 |
|
// 本会員数 |
234
|
4 |
|
$countCustomers = $this->countCustomers(); |
235
|
|
|
|
236
|
|
|
$event = new EventArgs( |
237
|
|
|
[ |
238
|
|
|
'Orders' => $Orders, |
239
|
|
|
'OrderStatuses' => $OrderStatuses, |
240
|
|
|
'salesThisMonth' => $salesThisMonth, |
241
|
|
|
'salesToday' => $salesToday, |
242
|
|
|
'salesYesterday' => $salesYesterday, |
243
|
|
|
'countNonStockProducts' => $countNonStockProducts, |
244
|
|
|
'countProducts' => $countProducts, |
245
|
|
|
'countCustomers' => $countCustomers, |
246
|
|
|
'datas' => $datas, |
247
|
|
|
], |
248
|
3 |
|
$request |
249
|
|
|
); |
250
|
3 |
|
$this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_COMPLETE, $event); |
251
|
3 |
|
|
252
|
|
|
return [ |
253
|
3 |
|
'Orders' => $Orders, |
254
|
|
|
'OrderStatuses' => $OrderStatuses, |
255
|
3 |
|
'salesThisMonth' => $salesThisMonth, |
256
|
|
|
'salesToday' => $salesToday, |
257
|
3 |
|
'salesYesterday' => $salesYesterday, |
258
|
|
|
'countNonStockProducts' => $countNonStockProducts, |
259
|
3 |
|
'countProducts' => $countProducts, |
260
|
|
|
'countCustomers' => $countCustomers, |
261
|
3 |
|
'datas' => $datas, |
262
|
3 |
|
]; |
263
|
|
|
} |
264
|
3 |
|
|
265
|
1 |
|
/** |
266
|
1 |
|
* パスワード変更画面 |
267
|
1 |
|
* |
268
|
|
|
* @Route("/%eccube_admin_route%/change_password", name="admin_change_password") |
269
|
1 |
|
* @Template("@admin/change_password.twig") |
270
|
|
|
* |
271
|
|
|
* @param Request $request |
272
|
1 |
|
* |
273
|
|
|
* @return \Symfony\Component\HttpFoundation\RedirectResponse|array |
274
|
|
|
*/ |
275
|
|
|
public function changePassword(Request $request) |
276
|
1 |
|
{ |
277
|
|
|
$builder = $this->formFactory |
278
|
|
|
->createBuilder(ChangePasswordType::class); |
279
|
1 |
|
|
280
|
1 |
|
$event = new EventArgs( |
281
|
|
|
[ |
282
|
1 |
|
'builder' => $builder, |
283
|
|
|
], |
284
|
1 |
|
$request |
285
|
|
|
); |
286
|
1 |
|
$this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_CHANGE_PASSWORD_INITIALIZE, $event); |
287
|
1 |
|
|
288
|
|
|
$form = $builder->getForm(); |
289
|
1 |
|
$form->handleRequest($request); |
290
|
|
|
|
291
|
1 |
|
if ($form->isSubmitted() && $form->isValid()) { |
292
|
|
|
$Member = $this->getUser(); |
293
|
1 |
|
$salt = $Member->getSalt(); |
294
|
|
|
$password = $form->get('change_password')->getData(); |
295
|
1 |
|
|
296
|
|
|
$encoder = $this->encoderFactory->getEncoder($Member); |
|
|
|
|
297
|
|
|
|
298
|
|
|
// 2系からのデータ移行でsaltがセットされていない場合はsaltを生成. |
299
|
2 |
|
if (empty($salt)) { |
300
|
|
|
$salt = $encoder->createSalt(); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
$password = $encoder->encodePassword($password, $salt); |
304
|
|
|
|
305
|
|
|
$Member |
306
|
|
|
->setPassword($password) |
307
|
|
|
->setSalt($salt); |
308
|
|
|
|
309
|
|
|
$this->memberRepository->save($Member); |
|
|
|
|
310
|
|
|
|
311
|
|
|
$event = new EventArgs( |
312
|
2 |
|
[ |
313
|
|
|
'form' => $form, |
314
|
|
|
'Member' => $Member, |
315
|
|
|
], |
316
|
2 |
|
$request |
317
|
2 |
|
); |
318
|
2 |
|
$this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIN_CHANGE_PASSWORD_COMPLETE, $event); |
319
|
|
|
|
320
|
2 |
|
$this->addSuccess('admin.change_password.save.complete', 'admin'); |
321
|
2 |
|
|
322
|
|
|
return $this->redirectToRoute('admin_change_password'); |
323
|
1 |
|
} |
324
|
1 |
|
|
325
|
1 |
|
return [ |
326
|
1 |
|
'form' => $form->createView(), |
327
|
|
|
]; |
328
|
1 |
|
} |
329
|
1 |
|
|
330
|
1 |
|
/** |
331
|
|
|
* 在庫なし商品の検索結果を表示する. |
332
|
|
|
* |
333
|
1 |
|
* @Route("/%eccube_admin_route%/nonstock", name="admin_homepage_nonstock") |
334
|
|
|
* |
335
|
|
|
* @param Request $request |
336
|
|
|
* |
337
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
338
|
|
|
*/ |
339
|
|
|
public function searchNonStockProducts(Request $request) |
340
|
|
|
{ |
341
|
|
|
// 在庫なし商品の検索条件をセッションに付与し, 商品マスタへリダイレクトする. |
342
|
4 |
|
$searchData = []; |
343
|
|
|
$searchData['stock'] = [ProductStock::OUT_OF_STOCK]; |
344
|
|
|
$session = $request->getSession(); |
345
|
|
|
$session->set('eccube.admin.product.search', $searchData); |
346
|
4 |
|
|
347
|
4 |
|
return $this->redirectToRoute('admin_product_page', [ |
348
|
|
|
'page_no' => 1, |
349
|
|
|
'status' => $this->eccubeConfig['eccube_admin_product_stock_status'], ]); |
350
|
4 |
|
} |
351
|
4 |
|
|
352
|
4 |
|
/** |
353
|
4 |
|
* 本会員の検索結果を表示する. |
354
|
|
|
* |
355
|
|
|
* @Route("/%eccube_admin_route%/customer", name="admin_homepage_customer") |
356
|
|
|
* |
357
|
|
|
* @param Request $request |
358
|
|
|
* |
359
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
360
|
|
|
*/ |
361
|
|
|
public function searchCustomer(Request $request) |
362
|
4 |
|
{ |
363
|
|
|
$searchData = []; |
364
|
4 |
|
$searchData['customer_status'] = [CustomerStatus::REGULAR]; |
365
|
|
|
$session = $request->getSession(); |
366
|
|
|
$session->set('eccube.admin.customer.search', $searchData); |
367
|
|
|
|
368
|
|
|
return $this->redirectToRoute('admin_customer_page', [ |
369
|
|
|
'page_no' => 1, |
370
|
|
|
]); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* @param \Doctrine\ORM\EntityManagerInterface $em |
375
|
4 |
|
* @param array $excludes |
376
|
4 |
|
* |
377
|
4 |
|
* @return null|Request |
378
|
4 |
|
*/ |
379
|
4 |
|
private function getOrderEachStatus($em, array $excludes) |
380
|
4 |
|
{ |
381
|
4 |
|
$sql = 'SELECT |
382
|
4 |
|
t1.order_status_id as status, |
383
|
1 |
|
COUNT(t1.id) as count |
384
|
|
|
FROM |
385
|
|
|
dtb_order t1 |
386
|
4 |
|
WHERE |
387
|
|
|
t1.order_status_id NOT IN (:excludes) |
388
|
|
|
GROUP BY |
389
|
|
|
t1.order_status_id |
390
|
|
|
ORDER BY |
391
|
|
|
t1.order_status_id'; |
392
|
|
|
$rsm = new ResultSetMapping(); |
393
|
|
|
$rsm->addScalarResult('status', 'status'); |
394
|
|
|
$rsm->addScalarResult('count', 'count'); |
395
|
|
|
$query = $em->createNativeQuery($sql, $rsm); |
396
|
4 |
|
$query->setParameters([':excludes' => $excludes]); |
397
|
|
|
$result = $query->getResult(); |
398
|
|
|
$orderArray = []; |
399
|
|
|
foreach ($result as $row) { |
400
|
4 |
|
$orderArray[$row['status']] = $row['count']; |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
return $orderArray; |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
/** |
407
|
|
|
* @param \Doctrine\ORM\EntityManagerInterface $em |
408
|
|
|
* @param \DateTime $dateTime |
409
|
|
|
* @param array $excludes |
410
|
|
|
* |
411
|
|
|
* @return null|Request |
412
|
|
|
*/ |
413
|
4 |
View Code Duplication |
private function getSalesByMonth($em, $dateTime, array $excludes) |
|
|
|
|
414
|
4 |
|
{ |
415
|
4 |
|
// concat... for pgsql |
416
|
|
|
// http://stackoverflow.com/questions/1091924/substr-does-not-work-with-datatype-timestamp-in-postgres-8-3 |
417
|
4 |
|
$dql = 'SELECT |
418
|
|
|
SUBSTRING(CONCAT(o.order_date, \'\'), 1, 7) AS order_month, |
419
|
4 |
|
SUM(o.payment_total) AS order_amount, |
420
|
3 |
|
COUNT(o) AS order_count |
421
|
|
|
FROM |
422
|
|
|
Eccube\Entity\Order o |
423
|
|
|
WHERE |
424
|
4 |
|
o.OrderStatus NOT IN (:excludes) |
425
|
|
|
AND SUBSTRING(CONCAT(o.order_date, \'\'), 1, 7) = SUBSTRING(:targetDate, 1, 7) |
426
|
|
|
GROUP BY |
427
|
|
|
order_month'; |
428
|
|
|
|
429
|
|
|
$q = $em |
430
|
|
|
->createQuery($dql) |
431
|
|
|
->setParameter(':excludes', $excludes) |
432
|
|
|
->setParameter(':targetDate', $dateTime); |
433
|
|
|
|
434
|
4 |
|
$result = []; |
435
|
|
|
try { |
436
|
|
|
$result = $q->getSingleResult(); |
437
|
|
|
} catch (NoResultException $e) { |
438
|
4 |
|
// 結果がない場合は空の配列を返す. |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
return $result; |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
/** |
445
|
|
|
* @param \Doctrine\ORM\EntityManagerInterface $em |
446
|
|
|
* @param \DateTime $dateTime |
447
|
|
|
* @param array $excludes |
448
|
|
|
* |
449
|
|
|
* @return null|Request |
450
|
|
|
*/ |
451
|
4 |
View Code Duplication |
private function getSalesByDay($em, $dateTime, array $excludes) |
|
|
|
|
452
|
4 |
|
{ |
453
|
4 |
|
// concat... for pgsql |
454
|
|
|
// http://stackoverflow.com/questions/1091924/substr-does-not-work-with-datatype-timestamp-in-postgres-8-3 |
455
|
4 |
|
$dql = 'SELECT |
456
|
|
|
SUBSTRING(CONCAT(o.order_date, \'\'), 1, 10) AS order_day, |
457
|
4 |
|
SUM(o.payment_total) AS order_amount, |
458
|
3 |
|
COUNT(o) AS order_count |
459
|
|
|
FROM |
460
|
|
|
Eccube\Entity\Order o |
461
|
|
|
WHERE |
462
|
4 |
|
o.OrderStatus NOT IN (:excludes) |
463
|
|
|
AND SUBSTRING(CONCAT(o.order_date, \'\'), 1, 10) = SUBSTRING(:targetDate, 1, 10) |
464
|
|
|
GROUP BY |
465
|
|
|
order_day'; |
466
|
|
|
|
467
|
|
|
$q = $em |
468
|
|
|
->createQuery($dql) |
469
|
|
|
->setParameter(':excludes', $excludes) |
470
|
|
|
->setParameter(':targetDate', $dateTime); |
471
|
|
|
|
472
|
|
|
$result = []; |
473
|
4 |
|
try { |
474
|
|
|
$result = $q->getSingleResult(); |
475
|
|
|
} catch (NoResultException $e) { |
476
|
4 |
|
// 結果がない場合は空の配列を返す. |
477
|
4 |
|
} |
478
|
4 |
|
|
479
|
4 |
|
return $result; |
480
|
4 |
|
} |
481
|
4 |
|
|
482
|
|
|
/** |
483
|
|
|
* 在庫切れ商品数を取得 |
484
|
4 |
|
* |
485
|
4 |
|
* @return mixed |
486
|
|
|
* |
487
|
|
|
* @throws \Doctrine\ORM\NonUniqueResultException |
488
|
|
|
*/ |
489
|
|
|
private function countNonStockProducts() |
490
|
|
|
{ |
491
|
|
|
$qb = $this->productRepository->createQueryBuilder('p') |
492
|
|
|
->select('count(DISTINCT p.id)') |
493
|
|
|
->innerJoin('p.ProductClasses', 'pc') |
494
|
|
|
->where('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0') |
495
|
|
|
->setParameter('StockUnlimited', false); |
496
|
4 |
|
|
497
|
|
|
return $qb->getQuery()->getSingleScalarResult(); |
498
|
|
|
} |
499
|
4 |
|
|
500
|
4 |
|
/** |
501
|
|
|
* 商品数を取得 |
502
|
|
|
* |
503
|
4 |
|
* @return mixed |
504
|
4 |
|
* |
505
|
4 |
|
* @throws \Doctrine\ORM\NonUniqueResultException |
506
|
4 |
|
*/ |
507
|
4 |
|
private function countProducts() |
508
|
|
|
{ |
509
|
|
|
$qb = $this->productRepository->createQueryBuilder('p') |
510
|
4 |
|
->select('count(p.id)') |
511
|
4 |
|
->where('p.Status in (:Status)') |
512
|
|
|
->setParameter('Status', [ProductStatus::DISPLAY_SHOW, ProductStatus::DISPLAY_HIDE]); |
513
|
|
|
|
514
|
|
|
return $qb->getQuery()->getSingleScalarResult(); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
/** |
518
|
|
|
* 本会員数を取得 |
519
|
|
|
* |
520
|
|
|
* @return mixed |
521
|
|
|
* |
522
|
|
|
* @throws \Doctrine\ORM\NonUniqueResultException |
523
|
|
|
*/ |
524
|
|
|
private function countCustomers() |
525
|
|
|
{ |
526
|
|
|
$qb = $this->customerRepository->createQueryBuilder('c') |
527
|
|
|
->select('count(c.id)') |
528
|
|
|
->where('c.Status = :Status') |
529
|
|
|
->setParameter('Status', CustomerStatus::REGULAR); |
530
|
|
|
|
531
|
|
|
return $qb->getQuery()->getSingleScalarResult(); |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
/** |
535
|
|
|
* 期間指定のデータを取得 |
536
|
|
|
* |
537
|
|
|
* @param array $excludes |
538
|
|
|
* @param Carbon $fromDate |
539
|
|
|
* @param Carbon $toDate |
540
|
|
|
* @param $format |
541
|
|
|
* |
542
|
|
|
* @return array |
543
|
|
|
*/ |
544
|
|
|
private function getData(array $excludes, Carbon $fromDate, Carbon $toDate, $format) |
545
|
|
|
{ |
546
|
|
|
$qb = $this->orderRepository->createQueryBuilder('o') |
547
|
|
|
->andWhere('o.order_date >= :fromDate') |
548
|
|
|
->andWhere('o.order_date <= :toDate') |
549
|
|
|
->andWhere('o.OrderStatus NOT IN (:excludes)') |
550
|
|
|
->setParameter(':excludes', $excludes) |
551
|
|
|
->setParameter(':fromDate', $fromDate->copy()) |
552
|
|
|
->setParameter(':toDate', $toDate->copy()) |
553
|
|
|
->orderBy('o.order_date'); |
554
|
|
|
|
555
|
|
|
$result = $qb->getQuery()->getResult(); |
556
|
|
|
|
557
|
|
|
return $this->convert($result, $fromDate, $toDate, $format); |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
/** |
561
|
|
|
* 期間毎にデータをまとめる |
562
|
|
|
* |
563
|
|
|
* @param $result |
564
|
|
|
* @param Carbon $fromDate |
565
|
|
|
* @param Carbon $toDate |
566
|
|
|
* @param $format |
567
|
|
|
* |
568
|
|
|
* @return array |
569
|
|
|
*/ |
570
|
|
|
private function convert($result, Carbon $fromDate, Carbon $toDate, $format) |
571
|
|
|
{ |
572
|
|
|
$raw = []; |
573
|
|
|
for ($date = $fromDate; $date <= $toDate; $date = $date->addDay()) { |
574
|
|
|
$raw[$date->format($format)]['price'] = 0; |
575
|
|
|
$raw[$date->format($format)]['count'] = 0; |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
foreach ($result as $Order) { |
579
|
|
|
$raw[$Order->getOrderDate()->format($format)]['price'] += $Order->getPaymentTotal(); |
580
|
|
|
++$raw[$Order->getOrderDate()->format($format)]['count']; |
581
|
|
|
} |
582
|
|
|
|
583
|
|
|
return $raw; |
584
|
|
|
} |
585
|
|
|
} |
586
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.