123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- <?php
- namespace statistics;
- use Log;
- use merchantModel;
- class refill_balance
- {
- const DaySecs = 86400;
- private $mMerchantNames = [];
- private $mProviderNames = [];
- private $mStoreidPID = [];
- private $mTimesTypes = [];
- public function __construct()
- {
- $mod_merchant = Model('merchant');
- $items = $mod_merchant->getMerchantList(['mchid' => ['gt',0]]);
- foreach ($items as $item) {
- $mchid = intval($item['mchid']);
- $this->mMerchantNames[$mchid] = !empty($item['company_name']) ? $item['company_name'] : $item['name'];
- }
- $items = Model('')->table('refill_provider,store')
- ->field('refill_provider.store_id,store.store_name,refill_provider.provider_id')->join('inner')
- ->on('store.store_id=refill_provider.store_id')
- ->where(['refill_provider.provider_id' => ['gt',0]])
- ->select();
- foreach ($items as $item) {
- $store_id = intval($item['store_id']);
- $this->mProviderNames[$store_id] = $item['store_name'];
- $this->mStoreidPID[$store_id] = intval($item['provider_id']);
- }
- $cfg_reader = function ($name, $field) {
- $data = rcache($name, 'refill-', $field);
- $val = $data[$field] ?? serialize([]);
- return unserialize($val);
- };
- $this->mTimesTypes['system'] = [0 => ['order_time']];
- $this->mTimesTypes['merchant'] = $cfg_reader('balance-cfg','merchant');
- $this->mTimesTypes['provider'] = $cfg_reader('balance-cfg','provider');
- }
- private function find_timetypes($type,$cid)
- {
- if(array_key_exists($type,$this->mTimesTypes))
- {
- if(array_key_exists($cid,$this->mTimesTypes[$type])) {
- return $this->mTimesTypes[$type][$cid];
- }
- }
- return [];
- }
- public function stat_all($end)
- {
- $mchids = function ()
- {
- $result = [];
- foreach ($this->mMerchantNames as $mchid => $name) {
- $result[] = $mchid;
- }
- return $result;
- };
- $store_ids = function ()
- {
- $result = [];
- foreach ($this->mProviderNames as $storeid => $name) {
- $result[] = $storeid;
- }
- return $result;
- };
-
- $types = ['system','merchant','provider'];
- foreach ($types as $type)
- {
- if ($type == 'system') {
- $cids = [0];
- } elseif ($type == 'merchant') {
- $cids = $mchids();
- } else {
- $cids = $store_ids();
- }
- foreach ($cids as $cid)
- {
- $time_types = $this->find_timetypes($type,$cid);
- foreach ($time_types as $time_type)
- {
- [$parent_id,$start,$confirmed] = $this->find_parent($type, $cid, $time_type);
- if($start == $end) {
- Log::record("type=$type cid=$cid, time_type=$time_type has been stat.",Log::DEBUG);
- continue;
- }
- if($parent_id > 0 && $confirmed == false) {
- Log::record("type=$type cid=$cid, time_type=$time_type had not confirmed.",Log::DEBUG);
- continue;
- }
- $ret = $this->add_balance($type, $cid, $start, $end, $time_type, $parent_id);
- if(!$ret) {
- Log::record("type=$type cid=$cid, time_type=$time_type fail",Log::ERR);
- }
- }
- }
- }
- }
- private function find_parent($type, $cid, $time_type)
- {
- $mod = Model('refill_balance');
- $cond = ['type' => $type, 'cid' => $cid, 'time_type' => $time_type];
- $item = $mod->field('balance_id,end_stamp,confirmed')->where($cond)->order('end_stamp desc')->find();
- $confirmed = boolval($item['confirmed']);
- return [intval($item['balance_id']), intval($item['end_stamp']), $confirmed];
- }
- private function refill_time_finder($type, $cid, $start,$end)
- {
- if ($start != 0) {
- return $start;
- }
- if ($type == 'system') {
- $mod_refill = Model('refill_order');
- $item = $mod_refill->table('refill_order')->field('order_id,order_time')
- ->where(['order_time' => ['lt', $end]])
- ->order('order_id asc')->find();
- $time = $item['order_time'] ?? $end;
- } elseif ($type == 'merchant') {
- $mod_refill = Model('refill_order');
- $item = $mod_refill->table('refill_order')->field('order_id,order_time')
- ->where(['mchid' => $cid, 'order_time' => ['lt', $end]])
- ->order('order_id asc')->find();
- $time = $item['order_time'] ?? $end;
- } else {
- $mod_refill = Model('vr_order');
- $item = $mod_refill->table('vr_order')->field('order_id,add_time')
- ->where(['store_id' => $cid,'add_time' => ['lt', $end]])
- ->order('order_id asc')->find();
- $time = $item['add_time'] ?? $end;
- }
- return $time;
- }
- private function merchant_paytime_finder($cid, $start, $end)
- {
- if ($start != 0) {
- return $start;
- }
- $mod_pay = Model();
- if ($cid == 0)
- {
- $item = $mod_pay->table('refill_evidence')
- ->field('min(add_time) as madd_time')
- ->where(['add_time' => ['lt', $end]])
- ->find();
- }
- else
- {
- $item = $mod_pay->table('refill_evidence')
- ->field('min(add_time) as madd_time')
- ->where(['mchid' => $cid,'add_time' => ['lt', $end]])
- ->find();
- }
- $time = $item['madd_time'] ?? $end;
- return $time;
- }
- private function provider_paytime_finder($cid, $start,$end)
- {
- if ($start != 0) {
- return $start;
- }
- $mod_pay = Model();
- if ($cid == 0)
- {
- $item = $mod_pay->table('provider_amount')
- ->field('min(add_time) as madd_time')
- ->where(['add_time' => ['lt', $end]])
- ->find();
- }
- else
- {
- $item = $mod_pay->table('provider_amount')
- ->field('min(add_time) as madd_time')
- ->where(['provider_id' => $cid,'add_time' => ['lt', $end]])
- ->find();
- }
- $time = $item['madd_time'] ?? $end;
- return $time;
- }
- private function balance_data($type, $cid, $start, $end, $time_type, $parent_balance, $remark)
- {
- $refill_time = $this->refill_time_finder($type, $cid, $start,$end);
- $order_stat = $this->order_stat($type, $cid, $refill_time, $end, $time_type);
- $transfer_calcer = function ($detail,$types = [])
- {
- $result = 0.0;
- foreach ($detail as $type => $amount)
- {
- if(empty($types)) {
- $result += $amount;
- }
- elseif(in_array($type,$types)) {
- $result += $amount;
- }
- }
- return $result;
- };
- if ($type == 'system') {
- $merchant_time = $this->merchant_paytime_finder($cid, $start,$end);
- $transfer_detail = $this->merchant_evidence_stat($cid, $merchant_time, $end);
- $provider_time = $this->provider_paytime_finder($cid, $start,$end);
- $out = $this->provider_amount_stat(0, $provider_time, $end);
- $cname = 'system';
- $pay_time = min($merchant_time,$provider_time);
- $in = $transfer_calcer($transfer_detail);
- $balance = ncPriceFormat($in - $out);
- } elseif ($type == 'merchant') {
- $pay_time = $this->merchant_paytime_finder($cid, $start, $end);
- $transfer_detail = $this->merchant_evidence_stat($cid, $pay_time, $end);
- $out = "0.0000";
- $cname = $this->mMerchantNames[$cid];
- $in = $transfer_calcer($transfer_detail);
- $balance = ncPriceFormat($in - $order_stat['mch_amounts']);
- } else {
- $pid = $this->mStoreidPID[$cid];
- $pay_time = $this->provider_paytime_finder($pid, $start,$end);
- $out = $this->provider_amount_stat($pid, $pay_time, $end);
- $cname = $this->mProviderNames[$cid];
- $balance = ncPriceFormat($out - $order_stat['channel_amounts']);
- }
- if ($start == 0) {
- $time = min($refill_time, $pay_time);
- $start = strtotime(date('Y-m-d', $time));
- }
- $accumuter = function ($parent_id)
- {
- if ($parent_id > 0) {
- $item = Model('refill_balance')->getBalance(['balance_id' => $parent_id]);
- } else {
- $item = [];
- }
- if (empty($item)) {
- return 0.00;
- } else {
- return $item['accumulate_balance'] + $item['balance'];
- }
- };
- $transfer_in = $transfer_calcer($transfer_detail,[merchantModel::type_mch_deposit,merchantModel::type_adm_deposit]);
- $except_amount = $transfer_calcer($transfer_detail,[merchantModel::type_adm_adjust,merchantModel::type_adm_finpos]);
- $refund_amount = $transfer_calcer($transfer_detail,[merchantModel::type_refund_back]);
- return ['parent_id' => $parent_balance, 'type' => $type, 'cid' => $cid, 'cname' => $cname,
- 'start_stamp' => $start, 'end_stamp' => $end, 'end_text' => date('Y-m-d H:i:s', $end),
- 'success_count' => intval($order_stat['order_counts']),
- 'refill_amount' => ncPriceFormat($order_stat['refill_amounts']),
- 'mch_amount' => ncPriceFormat($order_stat['mch_amounts']),
- 'channel_amount' => ncPriceFormat($order_stat['channel_amounts']),
- 'service_amount' => ncPriceFormat(0),
- 'profit_amount' => ncPriceFormat($order_stat['profit_amounts']),
- 'transfer_detail' => json_encode($transfer_detail),
- 'transfer_in' => ncPriceFormat($transfer_in),
- 'except_amount' => ncPriceFormat($except_amount),
- 'refund_amount' => ncPriceFormat($refund_amount),
- 'transfer_out' => ncPriceFormat($out),
- 'accumulate_balance' => ncPriceFormat($accumuter($parent_balance)),
- 'balance' => ncPriceFormat($balance),
- 'update_time' => time(),
- 'confirmed' => 0,
- 'time_type' => $time_type,
- 'remark' => $remark,
- ];
- }
- //system,provider,merchant
- //cid=0,mchid,store_id
- public function add_balance($type, $cid, $start, $end, $time_type, $parent_balance = 0, $remark = '系统自动生成')
- {
- $data = $this->balance_data($type, $cid, $start, $end, $time_type, $parent_balance, $remark);
- if(empty($data)) {
- return false;
- }
- $ret = Model('refill_balance')->insert($data);
- return $ret != false;
- }
- public function rebuild_balance($balance_id)
- {
- $balance = Model('refill_balance')->getBalance(['balance_id' => $balance_id]);
- if(empty($balance)) return false;
- $type = $balance['type'];
- $cid = $balance['cid'];
- $start = $balance['start_stamp'];
- $end = $balance['end_stamp'];
- $time_type = $balance['time_type'];
- $parent_balance = $balance['parent_id'];
- $remark = '记录重新生成';
- $data = $this->balance_data($type, $cid, $start, $end, $time_type, $parent_balance, $remark);
- if(empty($data)) {
- return false;
- }
- $ret = Model('refill_balance')->where(['balance_id' => $balance_id])->update($data);
- return $ret != false;
- }
- private function order_stat($type, $cid, $start, $end, $time_type)
- {
- $cond = [
- 'refill_order.inner_status' => 0,
- 'vr_order.order_state' => 40
- ];
- if($type == 'provider') {
- $cond['vr_order.store_id'] = $cid;
- }
- elseif($type == 'merchant') {
- $cond['refill_order.mchid'] = $cid;
- }
- if($time_type == 'notify_time') {
- $order_start = $start - 3 * self::DaySecs;
- if($order_start < 0) {
- $order_start = 0;
- }
- $cond["refill_order.notify_time&refill_order.notify_time"] = ['_multi' => true, ['egt', $start], ['lt', $end]];
- $cond["refill_order.order_time&refill_order.order_time"] = ['_multi' => true, ['egt', $order_start], ['lt', $end]];
- $cond["vr_order.add_time&vr_order.add_time"] = ['_multi' => true, ['egt', $order_start], ['lt', $end]];
- }
- else {
- $add_end = $end + 3 * self::DaySecs;
- $cond["refill_order.order_time&refill_order.order_time"] = ['_multi' => true, ['egt', $start], ['lt', $end]];
- $cond["vr_order.add_time&vr_order.add_time"] = ['_multi' => true, ['egt', $start], ['lt', $add_end]];
- }
- $record = Model('')->table('refill_order,vr_order')
- ->field('count(*) as order_counts, sum(refill_amount) as refill_amounts, sum(mch_amount) as mch_amounts, sum(channel_amount) as channel_amounts')
- ->join('inner')
- ->on('refill_order.order_id=vr_order.order_id')
- ->where($cond)
- ->find();
- if(!empty($record)) {
- $record['profit_amounts'] = ncPriceFormat($record['mch_amounts'] - $record['channel_amounts']);
- }
- return $record;
- }
- private function merchant_evidence_stat($cid, $start, $end)
- {
- $cond['status'] = merchantModel::status_passed;
- $cond['is_operation'] = merchantModel::oper_deposited;
- if($cid > 0) {
- $cond['mchid'] = $cid;
- }
- $cond['check_time&check_time'] = ['_multi' => true, ['egt', $start], ['lt', $end]];
- $items = Model('')->table('refill_evidence')
- ->field('add_type,sum(amount) as amounts')
- ->where($cond)
- ->group('add_type')
- ->select();
- $records = [];
- foreach ($items as $item) {
- $add_type = intval($item['add_type']);
- $amounts = floatval(ncPriceFormat($item['amounts']));
- $records[$add_type] = $amounts;
- }
- return $records;
- }
- private function provider_amount_stat($provider_id, $start, $end)
- {
- if($provider_id > 0) {
- $cond['provider_id'] = $provider_id;
- }
- $cond['add_time&add_time'] = ['_multi' => true, ['egt', $start], ['lt', $end]];
- $record = Model('')->table('provider_amount')
- ->field('sum(amount) as amounts')
- ->where($cond)
- ->find();
- return ncPriceFormat($record['amounts']);
- }
- }
|