stanley-king hace 4 años
padre
commit
08dd29d6de

+ 2 - 1
helper/refill/XYZRefillFactory.php

@@ -14,7 +14,8 @@ require_once(BASE_HELPER_PATH . '/refill/policy/ctl_item.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/mchctl.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/quaility.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/merchant_price.php');
-
+require_once(BASE_HELPER_PATH . '/refill/policy/rlock.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/rstorage.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/xyz/quality_ploy.php');
 
 use Log;

+ 3 - 3
helper/refill/policy/rlock.php

@@ -18,7 +18,7 @@ class rlock
     public static function set_open($card_type,$opened)
     {
         $ins = Cache::getInstance('cacheredis');
-        $name = self::mch_storage_name;
+        $name = self::sys_storage_name;
         $key = "{$card_type}-open";
 
         $ins->hset($name, '', [$key => $opened]);
@@ -27,7 +27,7 @@ class rlock
     public static function get_open($card_type)
     {
         $ins = Cache::getInstance('cacheredis');
-        $name = self::mch_storage_name;
+        $name = self::sys_storage_name;
         $key = "{$card_type}-open";
 
         $value = $ins->hget($name,'',$key);
@@ -172,7 +172,7 @@ class rlock
     {
         $ins = Cache::getInstance('cacheredis');
         $name = self::mch_storage_name;
-        $value = $ins->hget($name);
+        $value = $ins->hget($name,'');
         return $value;
     }
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

+ 329 - 0
helper/refill/policy/rstorage.php

@@ -0,0 +1,329 @@
+<?php
+
+namespace refill;
+
+class system
+{
+    private $mCardType;
+    private $mOpened;
+    private $mSpecs;
+    public function __construct($card_type)
+    {
+        $this->mCardType = $card_type;
+        $this->mSpecs = [];
+        $this->mOpened = false;
+    }
+
+    public function card_type() {
+        return $this->mCardType;
+    }
+
+    public function add_amount($amount)
+    {
+        $this->mSpecs[] = $amount;
+    }
+
+    public function set_opened($opened) {
+        $this->mOpened = $opened;
+    }
+
+    public function opened() : bool {
+        return $this->mOpened;
+    }
+
+    public function total()
+    {
+        $amounts = 0;
+        foreach ($this->mSpecs as $spec) {
+            $amount = rlock::hget_sys_storage($this->mCardType,$spec);
+            $amount = intval($amount);
+            $amount = $amount > 0 ? $amount : 0;
+            $amounts += $amount;
+        }
+        return $amounts;
+    }
+
+    public function spec_total($spec)
+    {
+        $amount = rlock::hget_sys_storage($this->mCardType,$spec);
+        $amount = intval($amount);
+        return $amount > 0 ? $amount : 0;
+    }
+}
+
+class merchant
+{
+    private $mMchid;
+    private $mTotalLocks;
+    private $mSpecLocks;
+
+    public function __construct($mchid)
+    {
+        $this->mMchid = $mchid;
+        $this->mTotalLocks = [];
+        $this->mSpecLocks = [];
+    }
+
+    public function mchid() {
+        return $this->mMchid;
+    }
+
+    public function set_total_lock($card_type, $lock_type)
+    {
+        if ($lock_type != rlock::CLOSE) {
+            $this->mTotalLocks[$card_type] = $lock_type;
+        }
+    }
+
+    public function total($card_type)
+    {
+        if(array_key_exists($card_type,$this->mTotalLocks)) {
+            $amount = rlock::hget_mch_total_storage($this->mMchid,$card_type);
+            $amount = intval($amount);
+            return $amount > 0 ? $amount : 0;
+        }
+        else {
+            return 0;
+        }
+    }
+
+    public function spec_total($card_type,$spec)
+    {
+        if (array_key_exists($card_type, $this->mSpecLocks) && array_key_exists($spec, $this->mSpecLocks[$card_type])) {
+            $amount = rlock::hget_mch_storage($this->mMchid, $card_type, $spec);
+            $amount = intval($amount);
+            return $amount > 0 ? $amount : 0;
+        } else {
+            return 0;
+        }
+    }
+
+    public function set_spec_lock($card_type,$spec,$lock_type)
+    {
+        if ($lock_type != rlock::CLOSE) {
+            $this->mSpecLocks[$card_type][$spec] = $lock_type;
+        }
+    }
+
+    public function has_lock()
+    {
+        return !empty($this->mTotalLocks) || !empty($this->mSpecLocks);
+    }
+
+    public function lock_type($card_type,$spec)
+    {
+        $total_lock = rlock::CLOSE;
+        if(array_key_exists($card_type,$this->mTotalLocks)) {
+            $total_lock = $this->mTotalLocks[$card_type];
+        }
+
+        $spec_lock = rlock::CLOSE;
+        if(array_key_exists($card_type,$this->mSpecLocks) && array_key_exists($spec,$this->mSpecLocks[$card_type])) {
+            $spec_lock = $this->mSpecLocks[$card_type][$spec];
+        }
+
+        return [$total_lock,$spec_lock];
+    }
+}
+
+
+class rstorage
+{
+    private $mSystems;
+    private $mMerchants;
+    public function __construct()
+    {
+        $this->load();
+    }
+
+    public function load()
+    {
+        $this->mSystems = [];
+        $this->read_sys();
+        $this->mMerchants = [];
+        $this->read_merchant();
+    }
+
+    private function locked($card_type)
+    {
+        if(array_key_exists($card_type,$this->mSystems)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public function allow($mchid,$card_type,$spec) : bool
+    {
+        if(!$this->locked($card_type)) {
+            return true;
+        }
+
+        [$total_lock_type,$spec_lock_type] = $this->merchant_lock_type($mchid,$card_type,$spec);
+        $merchant = $this->mMerchants[$mchid];
+
+        if($spec_lock_type == rlock::ASSIGN) {
+            return $merchant->spec_total($spec) >= $spec;
+        }
+        elseif($spec_lock_type == rlock::RETAIN)
+        {
+            //是否已经满足 Spec
+            $mch_spec_total = $merchant->spec_total($card_type);
+            if($mch_spec_total >= $spec) return true;
+        }
+        else {
+            //CLOSE情况,其它两种情况优先。
+        }
+
+        if ($total_lock_type == rlock::ASSIGN) {
+            $mch_total = $merchant->total($card_type);
+            if($mch_total < $spec) return false;
+        }
+
+        $system = $this->mSystems[$card_type];
+        $total = $system->total();
+        $spec_total = $system->spec_total($spec);
+
+        $diff_total = $total - $this->lowest_total($mchid,$card_type);
+        $diff_spec_total = $spec_total - $this->lowest_spec_total($mchid,$card_type,$spec);
+
+        return $diff_spec_total >= $spec && $diff_total >= $spec;
+    }
+
+    //return [$toal_lock,$spec_lock]
+    private function merchant_lock_type($mchid, $card_type, $spec)
+    {
+        if(!array_key_exists($mchid,$this->mMerchants)) {
+            return [rlock::CLOSE,rlock::CLOSE];
+        }
+
+        $merchant = $this->mMerchants[$mchid];
+        return $merchant->lock_type($card_type, $spec);
+    }
+
+    //需要为锁定的机构保留的最低量
+    private function lowest_total($mchid,$card_type)
+    {
+        $total = 0;
+        foreach ($this->mMerchants as $merchant)
+        {
+            if($mchid != $merchant->mchid()){
+                $total += $merchant->total($card_type);
+            }
+        }
+        return $total;
+    }
+
+    private function lowest_spec_total($mchid,$card_type,$spec)
+    {
+        $total = 0;
+        foreach ($this->mMerchants as $merchant)
+        {
+            if($mchid != $merchant->mchid()){
+                $total += $merchant->spec_total($card_type,$spec);
+            }
+        }
+        return $total;
+    }
+
+    private function read_sys()
+    {
+        $items = rlock::get_sys();
+        $parser = function ($key,$val)
+        {
+            $datas = explode('-',$key);
+            $len = count($datas);
+            if($len != 2) return [false,'','',''];
+
+            $card_type = intval($datas[0]);
+            if($datas[1] == 'open') {
+                return [true,'open',$card_type,boolval($val)];
+            }
+            elseif(is_numeric($datas[1])) {
+                return [true,'card',$card_type,intval($datas[1])];
+            }
+            else {
+                return [false,'','',''];
+            }
+        };
+
+        $systems = [];
+        foreach ($items as $key => $val)
+        {
+            [$succ,$name,$card_type,$value] = $parser($key,$val);
+            if($succ)
+            {
+                if(array_key_exists($card_type,$systems)) {
+                    $system = $systems[$card_type];
+                } else {
+                    $system = new system($card_type);
+                    $systems[$card_type] = $system;
+                }
+
+                if($name == 'open') {
+                    $system->set_opened($value);
+                }
+                elseif($name == 'card') {
+                    $system->add_amount($value);
+                }
+            }
+        }
+
+        foreach ($systems as $system)
+        {
+            if($system->opened()) {
+                $card_type = $system->card_type();
+                $this->mSystems[$card_type] = $system;
+            }
+        }
+    }
+
+    private function read_merchant()
+    {
+        $parser = function ($key,$val,&$merchants)
+        {
+            $items = explode('-',$key);
+            $len = count($items);
+            if($len < 3) return;
+
+            $mchid = intval($items[0]);
+            if(array_key_exists($mchid,$merchants)) {
+                $merchant = $merchants[$mchid];
+            } else {
+                $merchant = new merchant($mchid);
+                $merchants[$mchid] = $merchant;
+            }
+
+            $card_type = intval($items[1]);
+            if($len == 3)
+            {
+                if($items[2] == 'turn') {
+                    $lock_type = intval($val);
+                    $merchant->set_total_lock($card_type,$lock_type);
+                }
+            }
+            elseif($len == 4)
+            {
+                $amount = intval($items[2]);
+                if($items[3] == 'turn') {
+                    $lock_type = intval($val);
+                    $merchant->set_spec_lock($card_type,$amount,$lock_type);
+                }
+            }
+        };
+
+        $merchants = [];
+        $items = rlock::get_merchant();
+        foreach ($items as $key => $val) {
+            $parser($key, $val, $merchants);
+        }
+
+        foreach ($merchants as $merchant)
+        {
+            if($merchant->has_lock()) {
+                $mchid = $merchant->mchid();
+                $this->mMerchants[$mchid] = $merchant;
+            }
+        }
+    }
+}

+ 0 - 42
helper/refill/policy/rstorge.php

@@ -1,42 +0,0 @@
-<?php
-
-namespace refill;
-
-class sys_amount
-{
-
-}
-
-class retain
-{
-
-}
-
-class assign
-{
-
-}
-
-
-class rstorge
-{
-    public function __construct()
-    {
-
-    }
-
-    public function load()
-    {
-
-    }
-
-    private function read_sys()
-    {
-
-    }
-
-    private function read_merchant()
-    {
-
-    }
-}

+ 5 - 8
helper/refill/policy/xyz/policy.php

@@ -15,6 +15,7 @@ class policy extends ProviderManager implements IPolicy
     protected $mQuality;
     protected $mPrices;
     protected $mAmountLockTurn;
+    protected $mStorageLocker;
 
     public function __construct()
     {
@@ -23,6 +24,7 @@ class policy extends ProviderManager implements IPolicy
         $this->mMchctl = new mchctl();
         $this->mQuality = new quality_ploy();
         $this->mPrices = new merchant_price();
+        $this->mStorageLocker = new rstorage();
     }
 
     public function load()
@@ -37,6 +39,8 @@ class policy extends ProviderManager implements IPolicy
         $turn_name = 'oil_amount_lock_turn';
         $this->mAmountLockTurn = rkcache($turn_name);
         Log::record("AmountLockTurn = {$this->mAmountLockTurn}",Log::DEBUG);
+
+        $this->mStorageLocker->load();
     }
 
 
@@ -121,14 +125,7 @@ class policy extends ProviderManager implements IPolicy
 
     public function allow($mchid,$card_type,$amount,$quality) : bool
     {
-        return true;
-        
-//        if(empty($this->mAmountLockTurn)) {
-//            return true;
-//        }
-//        else {
-//            return util::get_amount_lock($mchid) > 0;
-//        }
+        return $this->mStorageLocker->allow($mchid,$card_type,$amount);
     }
 
     private function allow_storge($mchid,$card_type,$amount,$quality)

+ 15 - 1
test/TestRedis.php

@@ -9,6 +9,8 @@ require_once(BASE_ROOT_PATH . '/fooder.php');
 
 require_once (BASE_ROOT_PATH . '/helper/util_helper.php');
 require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/rlock.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/rstorage.php');
 
 
 function sub_callback($redis, $chan, $msg)
@@ -217,9 +219,21 @@ class TestRedis extends TestCase
         return $time;
     }
 
-    public static function tearDownAfterClass() : void
+    public function testStorage()
+    {
+        $storage = new refill\rstorage();
+        $storage->allow(1,1,200);
+    }
+
+    public function testRlock()
     {
+        $val = refill\rlock::hget_mch_storage(1,1,200);
+        $val = refill\rlock::incr_mch_storage(1,1,200,1);
 
+    }
+
+    public static function tearDownAfterClass() : void
+    {
 
     }
 }