Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 128
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
RewardController
0.00% covered (danger)
0.00%
0 / 128
0.00% covered (danger)
0.00%
0 / 15
1560
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getAllRewards
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getAllPromotions
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getRewardsFromAPI
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 getRewardsFromCache
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPointsAndRewardsByPhone
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
 redeemRewardByPhone
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
30
 addMember
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getRewardsUIDsForFiveStarsAPI
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getRedeemedRewards
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 insertRedemption
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 removeDuplicateRedemptions
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
 getPromotionsByPhone
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getPromotionsFromCache
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPromotionsFromAPI
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
1<?php /** @noinspection PhpObjectFieldsAreOnlyWrittenInspection */
2
3namespace BuyerKiosk\FiveStars\Controllers;
4
5
6use BuyerKiosk\FiveStars\API;
7use BuyerKiosk\FiveStars\Points;
8use BuyerKiosk\FiveStars\Reward;
9class RewardController extends BaseController {
10    private $predis;
11    private $key;
12    
13    public function __construct($app, \Store $store) {
14        parent::__construct($app, $store);
15        $this->predis = new \Predis\Client($_ENV['REDIS_URL']);
16        $this->key = $store->getTypeNum()."_rewards";
17        $this->promotionKey = $store->getTypeNum()."_promotions";
18    }
19    //Check the Redis cache for our rewards array first before making an API call to the FS API for the rewards.
20    public function getAllRewards() {
21        if($this->predis->exists($this->key)) {
22            return $this->getRewardsFromCache();
23        }
24        return $this->getRewardsFromAPI();
25    }
26    public function getAllPromotions() {
27        if($this->predis->exists($this->promotionKey)) {
28            return $this->getPromotionsFromCache();
29        }
30        return $this->getPromotionsFromAPI();
31    }
32
33    //Fetch rewards from the FS API and return the array. Also add the array to Redis cache set to expire after 2 hours
34    public function getRewardsFromAPI() {
35        $endpoint = $this->endpointBase."/rewards";
36        $API = new API($this->store->getDev());
37        $result = $API->api_call($endpoint);
38        $rewardArray = [];
39        if(isset($result['items'])) {
40            foreach($result['items'] as $item) {
41                $reward = new Reward($item['uid'], $item['point_cost'], $item['perk']);
42                $rewardArray[] = $reward;
43            }
44        }
45        $this->predis->set($this->key, json_encode($rewardArray));
46        $this->predis->expire($this->key, 60*60*2);
47        return $rewardArray;
48    }
49    //Load rewards array from Redis cache. (Check to make sure key exists before calling this function).
50    public function getRewardsFromCache() {
51        return json_decode($this->predis->get($this->key));
52    }
53    //Call the FS API to get the points the customer has (look up by phone number). Also include the rewards this customer can redeem.
54    public function getPointsAndRewardsByPhone($phone) {
55        $rewardsArray = $this->getAllRewards();
56        $API = new API($this->store->getDev());
57        $phoneHash = $API->phone_hash($phone);
58        $endpoint = $this->endpointBase."/memberships/by-phone/".$phoneHash;
59        $start_time = microtime(TRUE);
60        $result = $API->api_call($endpoint);
61        $end_time = microtime(TRUE);
62        $executionTime = $end_time - $start_time;
63        if($executionTime > 1) {
64            $this->log->LogDebug("Slow API Call");
65            $this->log->LogDebug("Time: ".$executionTime);
66            $this->log->LogDebug("Endpoint: ".$endpoint);
67            $this->log->LogDebug("Phone: ".$phone);
68            $this->log->LogDebug("/////////////");
69        }
70        $customer = [];
71        if(isset($result['account'])) {
72            $customer['points'] = $result['points'];
73            $customer['name'] = $result['account']['name'];
74            $customer['phone'] = $result['account']['phone'];
75            $customer['subscription_status'] = $result['subscription_status'];
76        }
77        $availableRewardsArray = [];
78        foreach($rewardsArray as $reward) {
79            if($reward->pointCost <= $customer['points']) {
80                $reward->type = 0;
81                $availableRewardsArray[] = $reward;
82            }
83        }
84        //$availableRewardsArray = $this->getPromotionsByPhone($phone, $availableRewardsArray);
85        return array("customer" => $customer, "rewards" => $availableRewardsArray);
86    }
87
88    public function redeemRewardByPhone($phone, $rewards) {
89        $API = new API($this->store->getDev());
90        $endpoint = $this->endpointBase."/sales";
91        $this->log->LogDebug("Rewards Variable: ". json_encode($rewards));
92        //RedeemedArray is an array of coupon UID's specifically for sending to the FiveStars API
93        $redeemedArray = $this->getRewardsUIDsForFiveStarsAPI($rewards);
94        //This array will be used to enter data for the redemtion in the fiveStarsPoints table.
95        $redeemedDataArray = $this->getRedeemedRewards($rewards);
96        $duplicateUIDArray = [];
97        //Post redemptions to the fiveStarsData table. If a slug collision occurs then add that UID to the duplicateUIDArray for removal
98        foreach($redeemedDataArray as $redeemedData) {
99            if(!$this->insertRedemption($redeemedData->pointCost, $phone)) {
100                $duplicateUIDArray[] = $redeemedData->uid;
101            }
102        }
103        //If we found any duplicated redemptions then we need to remove them from the array before we send it to the FiveStars API
104        $redeemedArray = $this->removeDuplicateRedemptions($redeemedArray, $duplicateUIDArray);
105        $this->log->LogDebug("Rewards After Remove Duplicates: ". json_encode($redeemedArray));
106        //Post to the FiveStars API and return any errors
107        $this->log->LogDebug(json_encode($redeemedArray));
108        $data = array("phone" => (String)$phone, "points" => array(array("amount"=>0)), "rewards" => $redeemedArray);
109        $this->log->LogDebug("RewardArray: ".json_encode($data));
110        if(count($redeemedArray) > 0) {
111            $result = $API->api_call($endpoint, $data);
112        } else {
113            return array("errorCode"=> 3, "errorMessage" => "No redemptions that weren't duplicates");
114        }
115        if($result == "Not enough points") {
116            return array("errorCode"=> 1, "errorMessage" => "Not Enough Points");
117        }
118        $this->log->LogDebug(json_encode($result));
119        return array("errorCode"=> 0, "errorMessage" => "");
120    }
121
122    public function addMember($phone)
123    {
124        $API = new API($this->store->getDev());
125        $endpoint = $this->endpointBase . "/memberships";
126        $data = array("phone" => (string)$phone);
127        $this->log->LogDebug(json_encode($data));
128        $result = $API->api_call($endpoint, $data);
129        return true;
130    }
131
132    public function getRewardsUIDsForFiveStarsAPI($rewards) {
133        foreach($rewards as $uid) {
134            $redeemedArray[] = array("uid" => $uid['uid']);
135        }
136        return $redeemedArray;
137    }
138
139    public function getRedeemedRewards($rewards) {
140        //Get the store rewards from cache or from the API. This will contain all rewards that the store offers.
141        $storeRewardsArray = $this->getAllRewards();
142        $redeemedDataArray = [];
143        foreach($rewards as $reward) {
144            foreach($storeRewardsArray as $storeReward) {
145                if($reward['uid'] == $storeReward->uid) {
146                    $redeemedDataArray[] = $storeReward;
147                }
148            }
149        }
150        return $redeemedDataArray;
151    }
152    public function insertRedemption($pointsRedeemed, $phone) {
153        try {
154            $points = new Points($this->store, $this->storeDB);
155            $points->totalBuys = 0;
156            $points->totalSales = 0;
157            $points->totalTax = 0;
158            $points->phone = $phone;
159            $today = new \DateTime("now", new \DateTimeZone($this->store->getTimeZone()));
160            $points->date = $today->format("Y-m-d");
161            $points->pointsRedeemed =  $pointsRedeemed;
162            return $points->insert();
163        } catch (\PDOException $e) {
164            $this->log->LogError($e->getMessage());
165        }
166    }
167    public function removeDuplicateRedemptions($redeemedArray, $duplicateUIDArray) {
168        if(count($duplicateUIDArray) > 0) {
169            foreach($duplicateUIDArray as $duplicateUID) {
170                foreach($redeemedArray as $key => $redeemedUID) {
171                    $this->log->LogDebug("Key: ". $key." Value: ".json_encode($redeemedUID));
172                    if($duplicateUID == $redeemedUID['uid']) {
173                        unset($redeemedArray[$key]);
174                    }
175                }
176            }
177        }
178        return $redeemedArray;
179    }
180    public function getPromotionsByPhone($phone, $rewardsArray) {
181        $API = new API($this->store->getDev());
182        $phoneHash = $API->phone_hash($phone);
183        $endpoint = $this->endpointBase."/memberships/by-phone/".$phoneHash."/promotions";
184        $result = $API->api_call($endpoint);
185        if(isset($result['promotions'])) {
186            foreach($result['promotions'] as $promotion) {
187                $promotion['type'] = 1;
188                $rewardsArray[] = $promotion;
189            }
190        }
191        return $rewardsArray;
192    }
193    public function getPromotionsFromCache() {
194        return json_decode($this->predis->get($this->promotionKey));
195    }
196    public function getPromotionsFromAPI() {
197        $API = new API($this->store->getDev());
198        $endpoint = $this->endpointBase."/perks";
199        $result = $API->api_call($endpoint);
200        $promotionsArray = [];
201        foreach($result['items'] as $item) {
202            $tempPromotion = [];
203            $tempPromotion['uid'] = $item['uid'];
204            $tempPromotion['name'] = $item['name'];
205            $tempPromotion['shortname'] = $item['shortname'];
206            $tempPromotion['expiration_date'] = $item['expiration_date'];
207            $tempPromotion['start_date'] = $item['start_date'];
208            $promotionsArray[$item['uid']] = $tempPromotion;
209        }
210        $this->predis->set($this->promotionKey, json_encode($promotionsArray));
211        $this->predis->expire($this->promotionKey, 60*60*24);
212        return $promotionsArray;
213    }
214}