Passed
Push — master ( fcc5a2...2d3f95 )
by Andrii
03:33
created

SaleRepository::buildTargetCond()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 14
ccs 0
cts 13
cp 0
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
/**
3
 * API for Billing
4
 *
5
 * @link      https://github.com/hiqdev/billing-hiapi
6
 * @package   billing-hiapi
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2017-2018, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\billing\hiapi\sale;
12
13
use hiqdev\php\billing\action\ActionInterface;
14
use hiqdev\php\billing\customer\CustomerInterface;
15
use hiqdev\php\billing\order\OrderInterface;
16
use hiqdev\php\billing\plan\PlanInterface;
17
use hiqdev\php\billing\sale\Sale;
18
use hiqdev\php\billing\sale\SaleInterface;
19
use hiqdev\php\billing\sale\SaleRepositoryInterface;
20
use hiqdev\yii\DataMapper\expressions\CallExpression;
21
use hiqdev\yii\DataMapper\expressions\HstoreExpression;
22
use hiqdev\yii\DataMapper\models\relations\Bucket;
23
use hiqdev\yii\DataMapper\query\Specification;
24
use hiqdev\yii\DataMapper\repositories\BaseRepository;
25
use Yii;
26
use yii\db\Query;
27
28
class SaleRepository extends BaseRepository implements SaleRepositoryInterface
29
{
30
    /** {@inheritdoc} */
31
    public $queryClass = SaleQuery::class;
32
33
    public function findId(SaleInterface $sale)
34
    {
35
        if ($sale->hasId()) {
36
            return $sale->getId();
37
        }
38
        $hstore = new HstoreExpression(array_filter([
39
            'buyer'     => $sale->getCustomer()->getLogin(),
40
            'buyer_id'  => $sale->getCustomer()->getId(),
41
            'object_id' => $sale->getTarget()->getId(),
42
            'tariff_id' => $sale->getPlan()->getId(),
43
        ]));
44
        $call = new CallExpression('sale_id', [$hstore]);
45
        $command = (new Query())->select($call);
46
47
        return $command->scalar($this->db);
48
    }
49
50
    /**
51
     * @param OrderInterface $order
52
     * @return Sale[]|SaleInterface[]
53
     */
54
    public function findByOrder(OrderInterface $order)
55
    {
56
        return array_map([$this, 'findByAction'], $order->getActions());
57
    }
58
59
    /**
60
     * @param ActionInterface $action
61
     * @return SaleInterface
62
     */
63
    public function findByAction(ActionInterface $action)
64
    {
65
        $type = $action->getTarget()->getType();
66
67
        if ($type === 'certificate') {
68
            $target_id = new CallExpression('class_id', ['certificate']);
69
        } elseif ($type === 'domain') {
70
            $target_id = new CallExpression('class_id', ['zone']);
71
        } elseif ($type === 'server') {
72
            $target_id = $action->getTarget()->getId();
73
        } else {
74
            throw new \Exception('not implemented for: ' . $type);
75
        }
76
77
        $spec = Yii::createObject(Specification::class)
78
            /// XXX how to pass if we want with prices into joinPlans?
79
            ->with('plans')
80
            ->where($this->buildTargetCond($target_id, $action->getCustomer()));
81
82
        return $this->findOne($spec);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->findOne($spec) could also return false which is incompatible with the documented return type hiqdev\php\billing\sale\SaleInterface. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
83
    }
84
85
    protected function buildTargetCond($target_id, CustomerInterface $client)
86
    {
87
        $client_id = $client->getId();
88
        if ($client_id) {
89
            $seller_id = null;
90
        } else {
91
            $seller_id = $client->getSeller()->getId();
92
            $client_id = $seller_id;
93
        }
94
95
        return array_filter([
96
            'target-id'     => $target_id,
97
            'customer-id'   => $client_id,
98
            'seller-id'     => $seller_id,
99
        ]);
100
    }
101
102
    protected function joinPlans(&$rows)
103
    {
104
        $bucket = Bucket::fromRows($rows, 'plan-id');
105
        $spec = (new Specification())
106
            ->with('prices')
107
            ->where(['id' => $bucket->getKeys()]);
108
        $raw_plans = $this->getRepository(PlanInterface::class)->queryAll($spec);
109
        /// TODO for SilverFire: try to do with bucket
110
        $plans = [];
111
        foreach ($raw_plans as $plan) {
112
            $plans[$plan['id']] = $plan;
113
        }
114
        foreach ($rows as &$sale) {
115
            $sale['plan'] = $plans[$sale['plan-id']];
116
        }
117
    }
118
119
    /**
120
     * @param SaleInterface $sale
121
     */
122
    public function save(SaleInterface $sale)
123
    {
124
        $hstore = new HstoreExpression([
125
            'object_id'     => $sale->getTarget()->getId(),
126
            'contact_id'    => $sale->getCustomer()->getId(),
127
            'tariff_id'     => $sale->getPlan() ? $sale->getPlan()->getId() : null,
128
            'time'          => $sale->getTime()->format('c'),
129
        ]);
130
        $call = new CallExpression('sale_object', [$hstore]);
131
        $command = (new Query())->select($call);
132
        $sale->setId($command->scalar($this->db));
133
    }
134
}
135