Completed
Push — master ( 601cd4...b7c5b8 )
by Nicolaas
03:09
created

code/model/BuyableStockCalculatedQuantity.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 *@author: Nicolaas [at] Sunny Side Up . Co . Nz
4
 *@description:
5
 * works out the quantity available for each buyable
6
 * based on the the number of items sold, recorded in BuyableStockOrderEntry,
7
 * and manual corrections, recorded in BuyableStockManualUpdate.
8
 *
9
 *
10
 **/
11
12
class BuyableStockCalculatedQuantity extends DataObject
13
{
14
    private static $db = array(
15
        "BaseQuantity" => "Int",
16
        "BuyableID" => "Int",
17
        "BuyableClassName" => "Varchar"
18
    );
19
20
    private static $has_many = array(
21
        "BuyableStockOrderEntry" => "BuyableStockOrderEntry",
22
        "BuyableStockManualUpdate" => "BuyableStockManualUpdate"
23
    );
24
25
    private static $defaults = array(
26
        "BaseQuantity" => 0
27
    );
28
29
    private static $casting = array(
30
        "Name" => "Varchar",
31
        "Buyable" => "DataObject",
32
        "UnlimitedStock" => "Boolean"
33
    );
34
35
    //MODEL ADMIN STUFF
36
    private static $searchable_fields = array(
37
        "BaseQuantity"
38
    );
39
40
    private static $field_labels = array(
41
        "BaseQuantity" => "Calculated Quantity On Hand",
42
        "BuyableID" => "Buyable ID",
43
        "LastEdited" => "Last Calculated"
44
    );
45
46
    private static $summary_fields = array(
47
        "Name",
48
        "BaseQuantity",
49
        "LastEdited"
50
    );
51
52
    private static $indexes = array(
53
        "BuyableID" => true,
54
        "BuyableClassName" => true
55
    );
56
57
    private static $default_sort = "\"BuyableClassName\", \"BaseQuantity\" DESC";
58
59
    private static $singular_name = "Stock Calculated Quantity";
60
61
    private static $plural_name = "Stock Calculated Quantities";
62
63
    private static $calculation_done = array();
64
65
    public function canCreate($member = null)
66
    {
67
        return false;
68
    }
69
70
    public function canEdit($member = null)
71
    {
72
        return false;
73
    }
74
75
    public function canDelete($member = null)
76
    {
77
        return false;
78
    }
79
80
    public function canView($member = null)
81
    {
82
        return $this->canDoAnything();
83
    }
84
85
    public function Link($action = "update")
86
    {
87
        return "/update-stock/".$action."/".$this->ID."/";
88
    }
89
90
    public function HistoryLink()
91
    {
92
        return $this->Link("history");
93
    }
94
95
    public function Buyable()
96
    {
97
        return $this->getBuyable();
98
    }
99
    public function getBuyable()
100
    {
101
        if ($this->BuyableID && class_exists($this->BuyableClassName)) {
102
            $className = $this->BuyableClassName;
103
            return $className::get()->byID($this->BuyableID);
104
        }
105
    }
106
107
    public function UnlimitedStock()
108
    {
109
        return $this->geUnlimitedStock();
110
    }
111
    public function getUnlimitedStock()
112
    {
113
        if ($buyable = $this->getBuyable()) {
114
            return $buyable->UnlimitedStock;
115
        }
116
    }
117
118
    public function Name()
119
    {
120
        return $this->getName();
121
    }
122
    public function getName()
123
    {
124
        if ($buyable = $this->getBuyable()) {
125
            return $buyable->getTitle();
126
        }
127
        return "no name";
128
    }
129
130
    protected function canDoAnything($member = null)
131
    {
132
        if ($buyable = $this->getBuyable()) {
133
            if ($buyable->canEdit($member)) {
134
                return true;
135
            }
136
        }
137
        Security::permissionFailure($this, _t('Security.PERMFAILURE', ' This page is secured and you need administrator rights to access it. Enter your credentials below and we will send you right along.'));
138
    }
139
140
    public static function get_quantity_by_buyable($buyable)
141
    {
142
        $value = 0;
143
        $item = self::get_by_buyable($buyable);
144
        if ($item) {
145
            $value = $item->calculatedBaseQuantity();
146
            if ($value < 0) {
147
                $value = 0;
148
            }
149
        }
150
        return $value;
151
    }
152
153
    public static function get_by_buyable($buyable)
154
    {
155
        $obj = BuyableStockCalculatedQuantity::get()
156
                        ->filter(
157
                            array(
158
                                'BuyableID' => $buyable->ID,
159
                                'BuyableClassName' => $buyable->ClassName
160
                            )
161
                        )
162
                        ->First();
163
        if ($obj) {
164
            //do nothing
165
        } else {
166
            $obj = new BuyableStockCalculatedQuantity();
167
            $obj->BuyableID = $buyable->ID;
168
            $obj->BuyableClassName = $buyable->ClassName;
169
        }
170
        if ($obj) {
171
            if (isset($obj->ID) && $obj->exists() && $obj->UnlimitedStock == $buyable->UnlimitedStock) {
172
                //do nothing
173
            } else {
174
                $obj->UnlimitedStock = $buyable->UnlimitedStock;
175
                //we must write here to calculate quantities
176
                $obj->write();
177
            }
178
            return $obj;
179
        }
180
        user_error("Could not find / create BuyableStockCalculatedQuantity for buyable with ID / ClassName ".$buyableID."/".$buyableClassName, E_WARNING);
181
    }
182
183
    public function calculatedBaseQuantity()
184
    {
185
        if (!$this->ID) {
186
            return 0;
187
        }
188
        $actualQuantity = $this->workoutActualQuantity();
189
        if ($actualQuantity != $this->BaseQuantity) {
190
            $this->BaseQuantity = $actualQuantity;
191
            $this->write();
192
            return $actualQuantity;
193
        } else {
194
            return $this->getField("BaseQuantity");
195
        }
196
    }
197
198
    protected function calculatedBaseQuantities($buyables = null)
199
    {
200
        if ($buyables) {
201
            foreach ($buyables as $buyable) {
202
                $buyableStockCalculatedQuantity = BuyableStockCalculatedQuantity::get_by_buyable($buyable);
203
                if ($buyableStockCalculatedQuantity) {
204
                    $buyableStockCalculatedQuantity->calculatedBaseQuantity();
205
                }
206
            }
207
        }
208
    }
209
210
    /**
211
     * TODO: change to submitted from CustomerCanEdit criteria
212
     */
213
214
215
    protected function workoutActualQuantity()
216
    {
217
        $actualQuantity = 0;
218
        if ($buyable = $this->getBuyable()) {
219
            //set name
220
            //add total order quantities
221
            $data = DB::query("
222
				SELECT
223
					\"OrderItem\".\"BuyableID\",
224
					Sum(\"OrderItem\".\"Quantity\")+0 \"QuantitySum\",
225
					\"Order\".\"ID\" \"OrderID\",
226
					\"OrderAttribute\".\"ClassName\",
227
					\"OrderItem\".\"BuyableClassName\",
228
					\"OrderStep\".\"CustomerCanEdit\"
229
				FROM
230
					\"Order\"
231
					INNER JOIN \"OrderAttribute\" ON \"OrderAttribute\".\"OrderID\" = \"Order\".\"ID\"
232
					INNER JOIN \"OrderItem\" ON \"OrderAttribute\".\"ID\" = \"OrderItem\".\"ID\"
233
					INNER JOIN \"OrderStep\" ON \"OrderStep\".\"ID\" = \"Order\".\"StatusID\"
234
				GROUP BY
235
					\"Order\".\"ID\", \"BuyableID\"
236
				HAVING
237
					\"OrderItem\".\"BuyableID\" = ".(intval($this->BuyableID) - 0)."
238
					AND
239
					\"OrderItem\".\"BuyableClassName\" = '".$this->BuyableClassName."'
240
					AND
241
					\"OrderStep\".\"CustomerCanEdit\" = 0
242
					AND
243
					\"Order\".\"ID\" <> ".ShoppingCart::current_order()->ID."
244
			");
245
            if ($data) {
246
                foreach ($data as $row) {
247
                    if ($row["OrderID"] && $this->ID && $row["QuantitySum"]) {
248
                        $buyableStockOrderEntry = BuyableStockOrderEntry::get()
249
                                                                                ->filter(
250
                                                                                    array(
251
                                                                                        'OrderID' => $row["OrderID"],
252
                                                                                        'ParentID' => $this->ID
253
                                                                                    )
254
                                                                                )
255
                                                                                ->First();
256
                        if ($buyableStockOrderEntry) {
257
                            //do nothing
258
                        } else {
259
                            $buyableStockOrderEntry = new BuyableStockOrderEntry();
260
                            $buyableStockOrderEntry->OrderID = $row["OrderID"];
0 ignored issues
show
The property OrderID does not exist on object<BuyableStockOrderEntry>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
261
                            $buyableStockOrderEntry->ParentID = $this->ID;
262
                            $buyableStockOrderEntry->IncludeInCurrentCalculation = 1;
263
                            $buyableStockOrderEntry->Quantity = 0;
264
                        }
265
                        if ($buyableStockOrderEntry->Quantity != $row["QuantitySum"]) {
266
                            $buyableStockOrderEntry->Quantity = $row["QuantitySum"];
267
                            $buyableStockOrderEntry->write();
268
                        }
269
                    }
270
                }
271
            }
272
            //find last adjustment
273
            $latestManualUpdate = BuyableStockManualUpdate::get()
274
                                                            ->filter(array('ParentID' => $this->ID))
275
                                                            ->sort(array('LastEdited' => 'DESC'))
276
                                                            ->First();
277
            //nullify order quantities that were entered before last adjustment
278
            if ($latestManualUpdate) {
279
                $latestManualUpdateQuantity = $latestManualUpdate->Quantity;
280
                DB::query("
281
					UPDATE \"BuyableStockOrderEntry\"
282
					SET \"IncludeInCurrentCalculation\" = 0
283
					WHERE
284
					\"LastEdited\" < '".$latestManualUpdate->LastEdited."'
285
						AND
286
						\"ParentID\" = ".$this->ID
287
                );
288
            } else {
289
                $latestManualUpdateQuantity = 0;
290
            }
291
            //work out additional purchases
292
            $orderQuantityToDeduct = BuyableStockOrderEntry::get()
293
                                        ->filter(
294
                                            array(
295
                                                'ParentID' => $this->ID,
296
                                                'IncludeInCurrentCalculation' => 1
297
                                            )
298
                                        )->sum('Quantity');
299
            if (!$orderQuantityToDeduct) {
300
                $orderQuantityToDeduct = 0;
301
            }
302
            //work out base total
303
            $actualQuantity = $latestManualUpdateQuantity - $orderQuantityToDeduct;
304
            if (isset($_GET["debug"])) {
305
                echo "<hr />";
306
                echo $this->Name;
307
                echo " | Manual SUM: ".$latestManualUpdateQuantity;
308
                echo " | Order SUM: ".$orderQuantityToDeduct;
309
                echo " | Total SUM: ".$this->BaseQuantity;
310
                echo "<hr />";
311
            }
312
        }
313
        return $actualQuantity;
314
    }
315
}
316