diff --git a/app/common/dao/store/SupplyStoreBrandDao.php b/app/common/dao/store/SupplyStoreBrandDao.php new file mode 100644 index 00000000..4a9cbe50 --- /dev/null +++ b/app/common/dao/store/SupplyStoreBrandDao.php @@ -0,0 +1,72 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\dao\store; + +use app\common\dao\BaseDao; +use app\common\model\store\SupplyStoreBrand as model; +use crmeb\traits\CategoresDao; + +class SupplyStoreBrandDao extends BaseDao +{ + + use CategoresDao; + + protected function getModel(): string + { + return model::class; + } + + + public function getAll() + { + $query = $this->getModel()::hasWhere('brandCategory',function($query){ + $query->where('is_show',1); + }); + $query->where('StoreBrand.is_show',1); + $list = $query->order('StoreBrand.sort DESC,StoreBrand.create_time DESC')->select()->toArray(); + array_push($list,[ + "brand_id" => 0, + "brand_category_id" => 0, + "brand_name" => "其他", + "sort" => 999, + "pic" => "", + "is_show" => 1, + "create_time" => "", + ]); + return $list; + } + + + public function merFieldExists($field, $value, $except = null) + { + return ($this->getModel())::getDB() + ->when($except, function ($query, $except) use ($field) { + $query->where($field, '<>', $except); + }) + ->where($field, $value)->count() > 0; + } + + public function search(array $where) + { + $query = $this->getModel()::getDB(); + if(isset($where['brand_category_id']) && $where['brand_category_id']) + $query->where('brand_category_id',$where['brand_category_id']); + if(isset($where['brand_name']) && $where['brand_name']) + $query->where('brand_name','like','%'.$where['brand_name'].'%'); + if((isset($where['ids']) && $where['ids'])) + $query->where($this->getPk(),'in',$where['ids']); + return $query->order('sort DESC,create_time desc'); + + } + +} diff --git a/app/common/dao/store/SupplyStoreCategoryDao.php b/app/common/dao/store/SupplyStoreCategoryDao.php new file mode 100644 index 00000000..fd9d1ca3 --- /dev/null +++ b/app/common/dao/store/SupplyStoreCategoryDao.php @@ -0,0 +1,117 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\dao\store; + +use app\common\dao\BaseDao; +use app\common\model\store\SupplyStoreCategory as model; +use crmeb\traits\CategoresDao; + +class SupplyStoreCategoryDao extends BaseDao +{ + + use CategoresDao; + + protected function getModel(): string + { + return model::class; + } + + public function getAll($mer_id = 0,$status = null, $type = 0) + { + return $this->getModel()::getDB() + ->where('mer_id', $mer_id) + ->where('type',$type) + ->when(($status !== null),function($query)use($status){ + $query->where($this->getStatus(),$status); + }) + ->order('sort DESC,'.$this->getPk().' DESC') + ->select() + ->append(['has_product']); + } + + public function findChildrenId($id) + { + return model::getDB()->whereLike('path', '%/'. $id . '/%')->column('store_category_id'); + } + + public function selectChildrenId(array $ids) + { + if (!is_array($ids) || empty($ids)) return []; + $query = model::getDB()->where(function($query) use($ids){ + foreach ($ids as $id) { + $query->whereOr('path', 'like','%/'. $id . '/%'); + } + }); + return $query->column('store_category_id'); + } + + + public function fieldExistsList(?int $merId,$field,$value,$except = null) + { + return ($this->getModel()::getDB())->when($except ,function($query)use($field,$except){ + $query->where($field,'<>',$except); + })->when(($merId !== null) ,function($query)use($merId){ + $query->where('mer_id',$merId); + })->where($field,$value); + + } + + public function getTwoLevel($merId = 0) + { + $pid = model::getDB()->where('pid', 0)->where('is_show',1)->where('type',0)->where('mer_id', $merId)->order('sort DESC')->column('store_category_id'); + return model::getDB()->whereIn('pid', $pid)->where('is_show', 1)->where('mer_id', $merId)->limit(20)->order('sort DESC')->column('store_category_id,cate_name,pid'); + } + + public function children($pid, $merId = 0) + { + return model::getDB()->where('pid', $pid)->where('mer_id', $merId)->where('is_show', 1)->order('sort DESC')->column('store_category_id,cate_name,pic'); + } + + public function allChildren($id) + { + $path = model::getDB()->where('store_category_id', is_array($id) ? 'IN' : '=', $id)->where('mer_id', 0)->column('path', 'store_category_id'); + if (!count($path)) return []; + return model::getDB()->where(function ($query) use ($path) { + foreach ($path as $k => $v) { + $query->whereOr('path', 'LIKE', "$v$k/%"); + } + })->where('mer_id', 0)->order('sort DESC')->column('store_category_id'); + } + + public function idsByAllChildren(array $ids) + { + $paths = model::getDB()->whereIn('store_category_id', $ids)->where('mer_id', 0)->column('path'); + if (!count($paths)) return []; + return model::getDB()->where(function ($query) use ($paths) { + foreach ($paths as $path) { + $query->whereOr('path', 'LIKE', "$path%"); + } + })->where('mer_id', 0)->order('sort DESC')->column('store_category_id'); + } + + public function getMaxLevel($merId = null) + { + if($merId) return 2; + return 3; + } + + public function searchLevelAttr($query, $value) + { + $query->where('level', $value); + } + + public function clear(int $id, string $field) + { + $this->getModel()::getDB()->where($field, $id)->delete(); + } +} diff --git a/app/common/dao/store/order/SupplyStoreCartDao.php b/app/common/dao/store/order/SupplyStoreCartDao.php new file mode 100644 index 00000000..932fc391 --- /dev/null +++ b/app/common/dao/store/order/SupplyStoreCartDao.php @@ -0,0 +1,156 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\dao\store\order; + + +use app\common\dao\BaseDao; +use app\common\model\BaseModel; +use app\common\model\store\order\SupplyStoreCart; +use app\common\model\user\UserAddress; +use app\common\repositories\store\order\SupplyStoreCartRepository; +use think\model\Relation; + +class SupplyStoreCartDao extends BaseDao +{ + + protected function getModel(): string + { + return SupplyStoreCart::class; + } + + /** + * @param array $ids + * @param $uid + * @param int|null $merId + * @return array + * @author xaboy + * @day 2020/6/5 + */ + public function validIntersection(array $ids, $uid, int $merId = null): array + { + return SupplyStoreCart::getDB()->whereIn('cart_id', $ids) + ->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + }) + ->where('is_del', 0)->where('is_fail', 0)->where('is_pay', 0)->where('uid', $uid)->column('cart_id'); + } + + /** + * @Author:Qinii + * @Date: 2020/6/1 + * @param int $uid + * @return mixed + */ + public function getAll(int $uid) + { + $query = ($this->getModel())::where(['uid' => $uid, 'is_del' => 0, 'is_new' => 0, 'is_pay' => 0]) + ->with([ + 'product' => function ($query) { + $query->field('product_id,image,store_name,is_show,status,is_del,unit_name,price,mer_status,is_used,product_type,once_max_count,once_min_count,pay_limit,mer_svip_status,svip_price_type'); + }, + 'productAttr' => function ($query) { + $query->field('product_id,stock,price,unique,sku,image,svip_price'); + }, + 'merchant' => function ($query) { + $query->field('mer_id,mer_name,mer_state,mer_avatar,is_trader,type_id')->with(['type_name']); + } + ])->limit(SupplyStoreCartRepository::CART_LIMIT_COUNT)->select(); + + return $query; + } + + public function cartIbByData(array $ids, int $uid, ?UserAddress $address) + { + return SupplyStoreCart::getDb()->where('uid', $uid)->with([ + 'product' => function (Relation $query) use ($address) { + $query->field('product_id,cate_id,image,store_name,is_show,status,is_del,unit_name,price,mer_status,temp_id,give_coupon_ids,is_gift_bag,is_used,product_type,old_product_id,integral_rate,delivery_way,delivery_free,type,extend,pay_limit,once_max_count,once_min_count,mer_svip_status,svip_price_type,refund_switch,mer_form_id'); + if ($address) { + $cityIds = array_filter([$address->province_id, $address->city_id, $address->district_id, $address->street_id]); + $query->with([ + 'temp' => [ + 'region' => function (Relation $query) use ($cityIds) { + $query->where(function ($query) use ($cityIds) { + foreach ($cityIds as $v) { + $query->whereOr('city_id', 'like', "%/{$v}/%"); + } + $query->whereOr('city_id', '0'); + })->order('shipping_template_region_id DESC')->withLimit(1); + }, + 'undelives' => function ($query) use ($cityIds) { + foreach ($cityIds as $v) { + $query->whereOr('city_id', 'like', "%/{$v}/%"); + } + }, + 'free' => function (Relation $query) use ($cityIds) { + foreach ($cityIds as $v) { + $query->whereOr('city_id', 'like', "%/{$v}/%"); + } + $query->order('shipping_template_free_id DESC')->withLimit(1); + }]]); + } + }, + 'productAttr' => function (Relation $query) { + $query->field('value_id,image,extension_one,extension_two,product_id,stock,price,unique,sku,volume,weight,ot_price,cost,svip_price') + ->append(['bc_extension_one', 'bc_extension_two']); + }, + 'merchant' => function (Relation $query) use ($uid) { + $query->field('mer_id,mer_name,mer_state,mer_avatar,delivery_way,commission_rate,category_id') + ->with([ + 'coupon' => function ($query) use ($uid) { + $query->where('uid', $uid); + }, + 'config' => function ($query) { + $query->whereIn('config_key', ['mer_integral_status', 'mer_integral_rate', 'mer_store_stock', 'mer_take_status', 'mer_take_name', 'mer_take_phone', 'mer_take_address', 'mer_take_location', 'mer_take_day', 'mer_take_time']); + }, + 'merchantCategory' + ]); + }])->whereIn('cart_id', $ids)->order('product_type DESC,cart_id DESC')->select(); + } + + /** + * @param array $cartIds + * @param int $uid + * @author Qinii + */ + public function batchDelete(array $cartIds, int $uid) + { + return ($this->getModel()::getDB())->where('uid', $uid)->whereIn('cart_id', $cartIds)->delete(); + } + + /** + * @param int $uid + * @return mixed + * @author Qinii + */ + public function getCartCount(int $uid) + { + $data = ($this->getModel()::getDB())->where(['uid' => $uid, 'is_del' => 0, 'is_new' => 0, 'is_pay' => 0])->field('SUM(cart_num) as count')->select(); + $data[0]['count'] = $data[0]['count'] ? $data[0]['count'] : 0; + return $data; + } + + /** + * @param $source + * @param array|null $ids + * @author xaboy + * @day 2020/8/31 + */ + public function getSourcePayInfo($source, ?array $ids = null) + { + return SupplyStoreCart::getDB()->alias('A')->where('A.source', $source)->where('A.is_pay', 1)->when($ids, function ($query, $ids) { + $query->whereIn('A.source_id', $ids); + })->leftJoin('SupplyStoreOrderProduct B', 'A.cart_id = B.cart_id') + ->field('sum(B.product_num) as pay_num,sum(B.product_price) as pay_price,A.source_id')->group('A.source_id')->select(); + } +} diff --git a/app/common/dao/store/order/SupplyStoreOrderDao.php b/app/common/dao/store/order/SupplyStoreOrderDao.php new file mode 100644 index 00000000..1ff42811 --- /dev/null +++ b/app/common/dao/store/order/SupplyStoreOrderDao.php @@ -0,0 +1,968 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\dao\store\order; + + +use app\common\dao\BaseDao; +use app\common\model\store\order\SupplyStoreOrder; +use app\common\model\store\order\SupplyStoreOrderProduct; +use app\common\model\store\order\SupplyStoreOrderStatus; +use app\common\model\user\User; +// use app\common\repositories\store\product\ProductAssistSetRepository; +// use app\common\repositories\store\product\ProductGroupBuyingRepository; +use think\db\BaseQuery; +use think\db\exception\DataNotFoundException; +use think\db\exception\DbException; +use think\db\exception\ModelNotFoundException; +use think\facade\Db; +use think\Model; + +/** + * Class SupplyStoreOrderDao + * @package app\common\dao\store\order + * @author xaboy + * @day 2020/6/8 + */ +class SupplyStoreOrderDao extends BaseDao +{ + //订单状态(0:待发货;1:待收货;2:待评价;3:已完成; 9: 拼团中 10: 待付尾款 11:尾款超时未付 -1:已退款) + const ORDER_STATUS_BE_SHIPPED = 0; + const ORDER_STATUS_BE_RECEIVE = 1; + const ORDER_STATUS_REPLY = 2; + const ORDER_STATUS_SUCCESS = 3; + const ORDER_STATUS_SPELL = 9; + const ORDER_STATUS_TAIL = 10; + const ORDER_STATUS_TAIL_FAIL = 11; + const ORDER_STATUS_REFUND = -1; + + + /** + * @return string + * @author xaboy + * @day 2020/6/8 + */ + protected function getModel(): string + { + return SupplyStoreOrder::class; + } + + /** + * @param array $where + * @param int $sysDel + * @return BaseQuery + * @author xaboyCRMEB + * @day 2020/6/16 + */ + public function search(array $where, $sysDel = 0) + { + $query = SupplyStoreOrder::hasWhere('merchant', function ($query) use ($where) { + if (isset($where['is_trader']) && $where['is_trader'] !== '') { + $query->where('is_trader', $where['is_trader']); + } + $query->where('is_del', 0); + }); + $query->where('SupplyStoreOrder.activity_type', '<>', 20); + $query->when(($sysDel !== null), function ($query) use ($sysDel) { + $query->where('is_system_del', $sysDel); + }); + $query->when(isset($where['order_type']) && $where['order_type'] >= 0 && $where['order_type'] !== '', function ($query) use ($where) { + if ($where['order_type'] == 2) { + $query->where('is_virtual', 1); + } else if ($where['order_type'] == 3) { // 卡密商品 + $query->where('is_virtual', 2); + } else { + $query->where('order_type', $where['order_type']); + } + }); + $query->when(isset($where['activity_type']) && $where['activity_type'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.activity_type', $where['activity_type']); + }) + ->when(isset($where['status']) && $where['status'] !== '', function ($query) use ($where) { + switch ($where['status']) { + case 0 : + $query->whereIn('SupplyStoreOrder.status', [0, 9]); + break; + case -2 : + $query->where('paid', 1)->whereNotIn('SupplyStoreOrder.status', [10, 11]); + break; + case 10 : + $query->where('paid', 1)->whereIn('SupplyStoreOrder.status', [10, 11]); + break; + default: + $query->where('SupplyStoreOrder.status', $where['status']); + break; + } + }) + ->when(isset($where['uid']) && $where['uid'] !== '', function ($query) use ($where) { + $query->where('uid', $where['uid']); + }) + ->when(isset($where['is_spread']) && $where['is_spread'] !== '', function ($query) use ($where) { + if ($where['is_spread']) { + $query->where(function ($query) { + $query->where('SupplyStoreOrder.spread_uid', '>', 0)->whereOr('SupplyStoreOrder.top_uid', '>', 0); + }); + } + }) + ->when(isset($where['is_user']) && $where['is_user'] !== '', function ($query) use ($where) { + $query->where(function ($query) { + $query->where('order_type', 0)->whereOr(function ($query) { + $query->where('order_type', 1)->where('main_id', 0); + }); + }); + }) + //待核销订单 + ->when(isset($where['is_verify']) && $where['is_verify'], function ($query) use ($where) { + $query->where('SupplyStoreOrder.order_type', 1)->where('SupplyStoreOrder.status', 0)->where('paid', 1); + }) + ->when(isset($where['pay_type']) && $where['pay_type'] !== '', function ($query) use ($where) { + if (is_int($where['pay_type'])) { + $query->where('SupplyStoreOrder.pay_type', $where['pay_type']); + } else { + $query->whereIn('SupplyStoreOrder.pay_type', $where['pay_type']); + } + }) + ->when(isset($where['order_ids']) && $where['order_ids'] !== '', function ($query) use ($where) { + $query->whereIn('order_id', $where['order_ids']); + }) + ->when(isset($where['order_id']) && $where['order_id'] !== '', function ($query) use ($where) { + $query->where('order_id', $where['order_id']); + }) + ->when(isset($where['take_order']) && $where['take_order'] != '', function ($query) use ($where) { + $query->where('order_type', 1)->whereNotNull('verify_time'); + }) + ->when(isset($where['mer_id']) && $where['mer_id'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.mer_id', $where['mer_id']); + }) + ->when(isset($where['date']) && $where['date'] !== '', function ($query) use ($where) { + getModelTime($query, $where['date'], 'SupplyStoreOrder.create_time'); + }) + ->when(isset($where['verify_date']) && $where['verify_date'] !== '', function ($query) use ($where) { + getModelTime($query, $where['verify_date'], 'verify_time'); + }) + ->when(isset($where['order_sn']) && $where['order_sn'] !== '', function ($query) use ($where) { + $query->where('order_sn', 'like', '%' . $where['order_sn'] . '%'); + }) + ->when(isset($where['paid']) && $where['paid'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.paid', $where['paid']); + }) + ->when(isset($where['is_del']) && $where['is_del'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.is_del', $where['is_del']); + }) + ->when(isset($where['service_id']) && $where['service_id'] !== '', function ($query) use ($where) { + $query->where('service_id', $where['service_id']); + }) + ->when(isset($where['username']) && $where['username'] !== '', function ($query) use ($where) { + $query->join('User U', 'SupplyStoreOrder.uid = U.uid') + ->where(function ($query) use ($where) { + $query->where('nickname', 'like', "%{$where['username']}%") + ->whereOr('phone', 'like', "%{$where['username']}%") + ->whereOr('SupplyStoreOrder.user_phone', 'like', "%{$where['username']}%"); + }); + }) + ->when(isset($where['spread_name']) && $where['spread_name'] !== '', function ($query) use ($where) { + $uid = User::where('nickname', 'like', "%{$where['spread_name']}%")->column('uid'); + $query->whereIn('SupplyStoreOrder.spread_uid', $uid); + }) + ->when(isset($where['top_spread_name']) && $where['top_spread_name'] !== '', function ($query) use ($where) { + $uid = User::where('nickname', 'like', "%{$where['top_spread_name']}%")->column('uid'); + $query->whereIn('SupplyStoreOrder.top_uid', $uid); + }) + ->when(isset($where['store_name']) && $where['store_name'] !== '', function ($query) use ($where) { + $orderId = SupplyStoreOrderProduct::alias('op') + ->join('supplyStoreProduct sp', 'op.product_id = sp.product_id') + ->whereLike('store_name', "%{$where['store_name']}%") + ->when((isset($where['sp.mer_id']) && $where['mer_id'] !== ''), function ($query) use ($where) { + $query->where('mer_id', $where['mer_id']); + })->column('order_id'); + $query->whereIn('order_id', $orderId ?: ''); + }) + ->when(isset($where['search']) && $where['search'] !== '', function ($query) use ($where) { + $orderId = SupplyStoreOrderProduct::alias('op') + ->join('supplyStoreProduct sp', 'op.product_id = sp.product_id') + ->whereLike('store_name', "%{$where['search']}%") + ->when((isset($where['sp.mer_id']) && $where['mer_id'] !== ''), function ($query) use ($where) { + $query->where('mer_id', $where['mer_id']); + })->column('order_id'); + $query->where(function ($query) use ($orderId, $where) { + $query->whereIn('order_id', $orderId ? $orderId : '') + ->whereOr('order_sn', 'like', "%{$where['search']}%") + ->whereOr('SupplyStoreOrder.user_phone', 'like', "%{$where['search']}%"); + }); + }) + ->when(isset($where['group_order_sn']) && $where['group_order_sn'] !== '', function ($query) use ($where) { + $query->join('StoreGroupOrder GO', 'SupplyStoreOrder.group_order_id = GO.group_order_id')->where('group_order_sn', $where['group_order_sn']); + }) + ->when(isset($where['keywords']) && $where['keywords'] !== '', function ($query) use ($where) { + $query->where(function ($query) use ($where) { + $query->whereLike('SupplyStoreOrder.real_name|SupplyStoreOrder.user_phone|order_sn', "%" . $where['keywords'] . "%"); + }); + }) + ->when(isset($where['filter_delivery']) && $where['filter_delivery'] !== '', function ($query) use ($where) { + //1 快递 2 配送 3 虚拟 + //按发货方式:1快递订单、2配送订单、4核销订单、3虚拟发货、6自动发货 + switch ($where['filter_delivery']) { + case 1: + $query->whereIn('delivery_type', '1,4'); + break; + case 2: + $query->whereIn('delivery_type', '2,5'); + break; + case 3: + $query->whereIn('delivery_type', '3'); + break; + case 4: + $query->where('order_type', 1); + break; + case 6: + $query->whereIn('delivery_type', '6'); + break; + } + }) + ->when(isset($where['filter_product']) && $where['filter_product'] !== '', function ($query) use ($where) { + // 1 实物商品、2虚拟商品、3卡密商品 + switch ($where['filter_product']) { + case 1: + $query->where('is_virtual', 0); + break; + case 2: + $query->where('is_virtual', 1); + break; + case 3: + $query->where('is_virtual', 2); + break; + } + }) + ->order('SupplyStoreOrder.create_time DESC'); + + return $query; + } + + public function searchAll(array $where, $sysDel = 0, $is_points = null) + { + $query = SupplyStoreOrder::getDB()->alias('SupplyStoreOrder'); + $query->when(($sysDel !== null), function ($query) use ($sysDel) { + $query->where('is_system_del', $sysDel); + }); + $query->when(!is_null($is_points), function ($query) use ($is_points) { + if ($is_points) { + $query->where('activity_type', 20); + } else { + $query->where('activity_type', '<>', 20); + } + }); + $query->when(isset($where['order_type']) && $where['order_type'] >= 0 && $where['order_type'] !== '', function ($query) use ($where) { + if ($where['order_type'] == 2) { + $query->where('is_virtual', 1); + } else if ($where['order_type'] == 0) { //实体发货订单 + $query->where('order_type', 0)->where('is_virtual', 0); + } else if ($where['order_type'] == 3) { //发货订单 + $query->where('order_type', 0); + } else { + $query->where('order_type', $where['order_type']); + } + }); + $query->when(isset($where['activity_type']) && $where['activity_type'] !== '', function ($query) use ($where) { + $query->where('activity_type', $where['activity_type']); + }) + ->when(isset($where['status']) && $where['status'] !== '', function ($query) use ($where) { + switch ($where['status']) { + case 0 : + $query->whereIn('SupplyStoreOrder.status', [0, 9])->where('paid', 1)->where('is_del', 0); + break; + case -2 : + $query->where('paid', 1)->whereNotIn('SupplyStoreOrder.status', [10, 11])->where('is_del', 0); + break; + case -3 : + $query->where('paid', 0)->where('is_del', 0); + break; + case 10 : + $query->where('paid', 1)->whereIn('SupplyStoreOrder.status', [10, 11])->where('is_del', 0); + break; + default: + $query->where('SupplyStoreOrder.status', $where['status'])->where('is_del', 0); + break; + } + + }) + ->when(isset($where['uid']) && $where['uid'] !== '', function ($query) use ($where) { + $query->where('uid', $where['uid']); + }) + ->when(isset($where['is_user']) && $where['is_user'] !== '', function ($query) use ($where) { + $query->where(function ($query) { + $query->where('order_type', 0)->whereOr(function ($query) { + $query->where('order_type', 1)->where('main_id', 0); + }); + }); + }) + //待核销订单 + ->when(isset($where['is_verify']) && $where['is_verify'], function ($query) use ($where) { + $query->where('SupplyStoreOrder.order_type', 1)->where('SupplyStoreOrder.status', 0); + }) + ->when(isset($where['pay_type']) && $where['pay_type'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.pay_type', $where['pay_type']); + }) + ->when(isset($where['order_ids']) && $where['order_ids'] !== '', function ($query) use ($where) { + $query->whereIn('order_id', $where['order_ids']); + }) + ->when(isset($where['order_id']) && $where['order_id'] !== '', function ($query) use ($where) { + $query->where('order_id', $where['order_id']); + }) + ->when(isset($where['take_order']) && $where['take_order'] != '', function ($query) use ($where) { + $query->where('order_type', 1)->whereNotNull('verify_time'); + }) + ->when(isset($where['date']) && $where['date'] !== '', function ($query) use ($where) { + getModelTime($query, $where['date'], 'SupplyStoreOrder.create_time'); + }) + ->when(isset($where['order_sn']) && $where['order_sn'] !== '', function ($query) use ($where) { + $query->where('order_sn', 'like', '%' . $where['order_sn'] . '%'); + }) + ->when(isset($where['paid']) && $where['paid'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.paid', $where['paid']); + }) + ->when(isset($where['is_del']) && $where['is_del'] !== '', function ($query) use ($where) { + $query->where('SupplyStoreOrder.is_del', $where['is_del']); + }) + ->when(isset($where['service_id']) && $where['service_id'] !== '', function ($query) use ($where) { + $query->where('service_id', $where['service_id']); + }) + ->when(isset($where['username']) && $where['username'] !== '', function ($query) use ($where) { + $query->join('User U', 'SupplyStoreOrder.uid = U.uid') + ->where(function ($query) use ($where) { + $query->where('nickname', 'like', "%{$where['username']}%") + ->whereOr('phone', 'like', "%{$where['username']}%") + ->whereOr('user_phone', 'like', "%{$where['username']}%"); + }); + }) + ->when(isset($where['nickname']) && $where['nickname'] !== '', function ($query) use ($where) { + $query->whereLike('SupplyStoreOrder.real_name', "%" . $where['nickname'] . "%"); + }) + ->when(isset($where['phone']) && $where['phone'] !== '', function ($query) use ($where) { + $query->join('User U', 'SupplyStoreOrder.uid = U.uid')->where('phone', 'like', "%{$where['phone']}%"); + }) + ->when(isset($where['store_name']) && $where['store_name'] !== '', function ($query) use ($where) { + $orderId = SupplyStoreOrderProduct::alias('op') + ->join('supplyStoreProduct sp', 'op.product_id = sp.product_id') + ->whereLike('store_name', "%{$where['store_name']}%") + ->when((isset($where['sp.mer_id']) && $where['mer_id'] !== ''), function ($query) use ($where) { + $query->where('mer_id', $where['mer_id']); + })->column('order_id'); + $query->whereIn('order_id', $orderId ?: ''); + }) + ->when(isset($where['search']) && $where['search'] !== '', function ($query) use ($where) { + $orderId = SupplyStoreOrderProduct::alias('op') + ->join('supplyStoreProduct sp', 'op.product_id = sp.product_id') + ->whereLike('store_name', "%{$where['search']}%") + ->when((isset($where['sp.mer_id']) && $where['mer_id'] !== ''), function ($query) use ($where) { + $query->where('mer_id', $where['mer_id']); + })->column('order_id'); + $query->where(function ($query) use ($orderId, $where) { + $query->whereIn('order_id', $orderId ? $orderId : '') + ->whereOr('order_sn', 'like', "%{$where['search']}%") + ->whereOr('user_phone', 'like', "%{$where['search']}%"); + }); + }) + ->when(isset($where['product_id']) && $where['product_id'] !== '', function ($query) use ($where) { + $orderId = SupplyStoreOrderProduct::alias('op') + ->join('supplyStoreProduct sp', 'op.product_id = sp.product_id') + ->where('sp.product_id', $where['product_id']) + ->column('order_id'); + $query->whereIn('order_id', $orderId ? $orderId : ''); + }) + ->when(isset($where['group_order_sn']) && $where['group_order_sn'] !== '', function ($query) use ($where) { + $query->join('StoreGroupOrder GO', 'SupplyStoreOrder.group_order_id = GO.group_order_id')->where('group_order_sn', $where['group_order_sn']); + }) + ->when(isset($where['keywords']) && $where['keywords'] !== '', function ($query) use ($where) { + $query->where(function ($query) use ($where) { + $query->whereLike('SupplyStoreOrder.real_name|SupplyStoreOrder.user_phone|order_sn', "%" . $where['keywords'] . "%"); + }); + }) + ->order('SupplyStoreOrder.create_time DESC'); + + return $query; + } + + /** + * @param $id + * @param $uid + * @return array|Model|null + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author xaboy + * @day 2020/6/11 + */ + public function userOrder($id, $uid) + { + return SupplyStoreOrder::getDB()->where('order_id', $id)->where('uid', $uid)->where('is_del', 0)->where('paid', 1)->where('is_system_del', 0)->find(); + } + + /** + * @param array $where + * @param $ids + * @return BaseQuery + * @author xaboy + * @day 2020/6/26 + */ + public function usersOrderQuery(array $where, $ids, $uid) + { + return SupplyStoreOrder::getDB()->where(function ($query) use ($uid, $ids) { + $query->whereIn('uid', $ids) + ->whereOr(function ($query) use ($uid) { + if ($uid) { + $query->where('uid', $uid)->where('is_selfbuy', 1); + } + }); + })->when(isset($where['date']) && $where['date'] !== '', function ($query) use ($where) { + getModelTime($query, $where['date'], 'pay_time'); + })->when(isset($where['create_time']) && $where['create_time'] !== '', function ($query) use ($where) { + getModelTime($query, $where['create_time'], 'create_time'); + })->when(isset($where['keyword']) && $where['keyword'] !== '', function ($query) use ($where) { + $_uid = User::where('nickname', 'like', "%{$where['keyword']}%")->column('uid'); + $orderId = SupplyStoreOrderProduct::alias('op') + ->join('supplyStoreProduct sp', 'op.product_id = sp.product_id') + ->whereLike('store_name', "%{$where['keyword']}%") + ->column('order_id'); + $query->where(function ($query) use ($orderId, $where, $_uid) { + $query->whereLike('order_id|order_sn', "%{$where['keyword']}%")->whereOr('order_id', 'in', $orderId)->whereOr('uid', 'in', $_uid); + }); + })->where('paid', 1)->order('pay_time DESC'); + } + + /** + * @param $field + * @param $value + * @param int|null $except + * @return bool + * @author xaboy + * @day 2020/6/11 + */ + public function fieldExists($field, $value, ?int $except = null): bool + { + return ($this->getModel()::getDB())->when($except, function ($query) use ($field, $except) { + $query->where($field, '<>', $except); + })->where($field, $value)->count() > 0; + } + + /** + * @param $id + * @return mixed + * @author xaboy + * @day 2020/6/12 + */ + public function getMerId($id) + { + return SupplyStoreOrder::getDB()->where('order_id', $id)->value('mer_id'); + } + + /** + * @param array $where + * @return bool + * @author Qinii + * @day 2020-06-12 + */ + public function merFieldExists(array $where) + { + return ($this->getModel()::getDB())->where($where)->count() > 0; + } + + /** + * TODO + * @param $reconciliation_id + * @return mixed + * @author Qinii + * @day 2020-06-15 + */ + public function reconciliationUpdate($reconciliation_id) + { + return ($this->getModel()::getDB())->whereIn('reconciliation_id', $reconciliation_id)->update(['reconciliation_id' => 0]); + } + + public function dayOrderNum($day, $merId = null) + { + return SupplyStoreOrder::getDB()->where('paid', 1)->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($day, function ($query, $day) { + getModelTime($query, $day, 'pay_time'); + })->count(); + } + + public function dayOrderPrice($day, $merId = null) + { + return getModelTime(SupplyStoreOrder::getDB()->where('paid', 1)->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + }), $day, 'pay_time')->sum('pay_price'); + } + + public function dateOrderPrice($date, $merId = null) + { + return SupplyStoreOrder::getDB()->where('paid', 1)->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->sum('pay_price'); + } + + public function dateOrderNum($date, $merId = null) + { + return SupplyStoreOrder::getDB()->where('paid', 1)->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->count(); + } + + public function dayOrderUserNum($day, $merId = null) + { + return SupplyStoreOrder::getDB()->where('paid', 1)->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($day, function ($query, $day) { + getModelTime($query, $day, 'pay_time'); + })->group('uid')->count(); + } + + public function orderUserNum($date, $paid = null, $merId = null) + { + return SupplyStoreOrder::getDB()->when($paid, function ($query, $paid) { + $query->where('paid', $paid); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($date, function ($query, $date) use ($paid) { + if (!$paid) { + getModelTime($query, $date); + } else + getModelTime($query, $date, 'pay_time'); + })->group('uid')->count(); + } + + public function orderUserGroup($date, $paid = null, $merId = null) + { + return SupplyStoreOrder::getDB()->when($paid, function ($query, $paid) { + $query->where('paid', $paid); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->group('uid')->field(Db::raw('uid,sum(pay_price) as pay_price,count(order_id) as total'))->select(); + } + + public function oldUserNum(array $ids, $merId = null) + { + return SupplyStoreOrder::getDB()->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->whereIn('uid', $ids)->where('paid', 1)->group('uid')->count(); + } + + public function oldUserIds(array $ids, $merId = null) + { + return SupplyStoreOrder::getDB()->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->whereIn('uid', $ids)->where('paid', 1)->group('uid')->column('uid'); + } + + public function orderPrice($date, $paid = null, $merId = null) + { + return SupplyStoreOrder::getDB()->when($paid, function ($query, $paid) { + $query->where('paid', $paid); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->when($date, function ($query, $date) use ($paid) { + if (!$paid) { + $query->where(function ($query) use ($date) { + $query->where(function ($query) use ($date) { + $query->where('paid', 1); + getModelTime($query, $date, 'pay_time'); + })->whereOr(function ($query) use ($date) { + $query->where('paid', 0); + getModelTime($query, $date); + }); + }); + } else + getModelTime($query, $date, 'pay_time'); + })->sum('pay_price'); + } + + public function orderGroupNum($date, $merId = null) + { + $field = Db::raw('sum(pay_price) as pay_price,count(*) as total,count(distinct uid) as user,pay_time,from_unixtime(unix_timestamp(pay_time),\'%m-%d\') as `day`'); + if ($date == 'year') { + $field = Db::raw('sum(pay_price) as pay_price,count(*) as total,count(distinct uid) as user,pay_time,from_unixtime(unix_timestamp(pay_time),\'%m\') as `day`'); + } + $query = SupplyStoreOrder::getDB()->field($field) + ->where('paid', 1)->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + }); + return $query->order('pay_time ASC')->group('day')->select(); + } + + public function orderGroupNumPage($where, $page, $limit, $merId = null) + { + return SupplyStoreOrder::getDB()->when(isset($where['dateRange']), function ($query) use ($where) { + getModelTime($query, date('Y/m/d 00:00:00', $where['dateRange']['start']) . '-' . date('Y/m/d 00:00:00', $where['dateRange']['stop']), 'pay_time'); + })->field(Db::raw('sum(pay_price) as pay_price,count(*) as total,count(distinct uid) as user,pay_time,from_unixtime(unix_timestamp(pay_time),\'%m-%d\') as `day`')) + ->where('paid', 1)->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->order('pay_time DESC')->page($page, $limit)->group('day')->select(); + } + + public function dayOrderPriceGroup($date, $merId = null) + { + return SupplyStoreOrder::getDB()->field(Db::raw('sum(pay_price) as price, from_unixtime(unix_timestamp(pay_time),\'%H:%i\') as time')) + ->where('paid', 1)->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->group('time')->select(); + } + + public function dayOrderNumGroup($date, $merId = null) + { + return SupplyStoreOrder::getDB()->field(Db::raw('count(*) as total, from_unixtime(unix_timestamp(pay_time),\'%H:%i\') as time')) + ->where('paid', 1)->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->group('time')->select(); + } + + public function dayOrderUserGroup($date, $merId = null) + { + return SupplyStoreOrder::getDB()->field(Db::raw('count(DISTINCT uid) as total, from_unixtime(unix_timestamp(pay_time),\'%H:%i\') as time')) + ->where('paid', 1)->when($date, function ($query, $date) { + getModelTime($query, $date, 'pay_time'); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->group('time')->select(); + } + + /** + * 获取当前时间到指定时间的支付金额 管理员 + * @param string $start 开始时间 + * @param string $stop 结束时间 + * @return mixed + */ + public function chartTimePrice($start, $stop, $merId = null) + { + return SupplyStoreOrder::getDB()->where('paid', 1) + ->where('pay_time', '>=', $start) + ->where('pay_time', '<', $stop) + ->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + }) + ->field('sum(pay_price) as num,FROM_UNIXTIME(unix_timestamp(pay_time), \'%Y-%m-%d\') as time') + ->group('time') + ->order('pay_time ASC')->select()->toArray(); + } + + /** + * @param $date + * @param null $merId + * @return mixed + */ + public function chartTimeNum($date, $merId = null) + { + return SupplyStoreOrder::getDB()->where('paid', 1)->when($date, function ($query) use ($date) { + getModelTime($query, $date, 'pay_time'); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->field('count(order_id) as num,FROM_UNIXTIME(unix_timestamp(pay_time), \'%Y-%m-%d\') as time') + ->group('time') + ->order('pay_time ASC')->select()->toArray(); + } + + /** + * @param $end + * @return mixed + * @author xaboy + * @day 2020/9/16 + */ + public function getFinishTimeoutIds($end) + { + return SupplyStoreOrderStatus::getDB()->alias('A')->leftJoin('SupplyStoreOrder B', 'A.order_id = B.order_id') + ->where('A.change_type', 'take') + ->where('A.change_time', '<', $end)->where('B.paid', 1)->where('B.status', 2) + ->column('A.order_id'); + } + + + /** + * TODO 参与人数 + * @param array $data + * @param int|null $uid + * @return BaseQuery + * @author Qinii + * @day 2020-11-11 + */ + public function getTattendCount(array $data, ?int $uid) + { + $query = SupplyStoreOrder::hasWhere('orderProduct', function ($query) use ($data, $uid) { + $query->when(isset($data['activity_id']), function ($query) use ($data) { + $query->where('activity_id', $data['activity_id']); + }) + ->when(isset($data['product_sku']), function ($query) use ($data) { + $query->where('product_sku', $data['product_sku']); + }) + ->when(isset($data['product_id']), function ($query) use ($data) { + $query->where('product_id', $data['product_id']); + }) + // ->when(isset($data['exsits_id']), function ($query) use ($data) { + // switch ($data['product_type']) { + // case 3: + // $make = app()->make(ProductAssistSetRepository::class); + // $id = 'product_assist_id'; + // break; + // case 4: + // $make = app()->make(ProductGroupBuyingRepository::class); + // $id = 'product_group_id'; + // break; + // } + // $where = [$id => $data['exsits_id']]; + // $activity_id = $make->getSearch($where)->column($make->getPk()); + // if ($activity_id) { + // $id = array_unique($activity_id); + // $query->where('activity_id', 'in', $id); + // } else { + // $query->where('activity_id', '<', 0); + // } + // }) + ->where('product_type', $data['product_type']); + if ($uid) $query->where('uid', $uid); + }); + $query->where('activity_type', $data['product_type']); + switch ($data['product_type']) { + case 0: + $query->where(function ($query) { + $query->where(function ($query) { + $query->where('paid', 1); + })->whereOr(function ($query) { + $query->where('paid', 0)->where('is_del', 0); + }); + }); + break; + case 1: //秒杀 + $query->where(function ($query) { + $query->where(function ($query) { + $query->where('paid', 1); + })->whereOr(function ($query) { + $query->where('paid', 0)->where('is_del', 0); + }); + })->when(isset($data['day']), function ($query) use ($data) { + $query->whereDay('SupplyStoreOrder.create_time', $data['day']); + }); + break; + case 2: //预售 + + /** + * 第一阶段参与人数:所有人 + * 第二阶段参与人数:支付了第一阶段 + */ + //第二阶段 + if ($data['type'] == 1) { + $query->where(function ($query) { + $query->where('paid', 1)->whereOr(function ($query) { + $query->where('paid', 0)->where('is_del', 0); + }); + }); + } + if ($data['type'] == 2) $query->where('paid', 1)->where('status', 'in', [0, 1, 2, 3, -1]); + break; + case 3: //助力 + $query->where(function ($query) { + $query->where('paid', 1)->whereOr(function ($query) { + $query->where('paid', 0)->where('is_del', 0); + }); + }); + break; + case 4: // + $query->where(function ($query) { + $query->where('paid', 1)->whereOr(function ($query) { + $query->where('paid', 0)->where('is_del', 0); + }) + ->where('status', '>', -1); + }); + break; + } + return $query; + } + + /** + * 未使用 + * TODO 成功支付人数 + * @param int $productType + * @param int $activityId + * @param int|null $uid + * @param int|null $status + * @author Qinii + * @day 2020-10-30 + */ + public function getTattendSuccessCount($data, ?int $uid) + { + $query = SupplyStoreOrder::hasWhere('orderProduct', function ($query) use ($data, $uid) { + $query->when(isset($data['activity_id']), function ($query) use ($data) { + $query->where('activity_id', $data['activity_id']); + }) + ->when(isset($data['product_sku']), function ($query) use ($data) { + $query->where('product_sku', $data['product_sku']); + }) + ->when(isset($data['product_id']), function ($query) use ($data) { + $query->where('product_id', $data['product_id']); + }) + // ->when(isset($data['exsits_id']), function ($query) use ($data) { + // switch ($data['product_type']) { + // case 3: + // $make = app()->make(ProductAssistSetRepository::class); + // $id = 'product_assist_id'; + // break; + // case 4: + // $make = app()->make(ProductGroupBuyingRepository::class); + // $id = 'product_group_id'; + // break; + // } + // $where = [$id => $data['exsits_id']]; + // $activity_id = $make->getSearch($where)->column($make->getPk()); + // if ($activity_id) { + // $id = array_unique($activity_id); + // $query->where('activity_id', 'in', $id); + // } else { + // $query->where('activity_id', '<', 0); + // } + // }) + ->where('product_type', $data['product_type']); + if ($uid) $query->where('uid', $uid); + }); + $query->where('activity_type', $data['product_type'])->where('paid', 1); + + switch ($data['product_type']) { + case 1: //秒杀 + $query->where(function ($query) { + $query->where(function ($query) { + $query->where('paid', 1); + }); + })->when(isset($data['day']), function ($query) use ($data) { + $query->whereDay('SupplyStoreOrder.create_time', $data['day']); + }); + break; + case 2: //预售 + if ($data['type'] == 1) { //第一阶段 + $query->where('status', 'in', [0, 1, 2, 3, 10]); + } else { //第二阶段 + $query->where('status', 'in', [0, 1, 2, 3]); + } + break; + case 3: //助力 + break; + case 4: + break; + } + return $query; + } + + + /** + * TODO 获取退款单数量 + * @param $where + * @return mixed + * @author Qinii + * @day 1/4/21 + */ + public function getSeckillRefundCount($where, $type = 1) + { + $query = SupplyStoreOrderProduct::getDB()->alias('P')->join('StoreRefundOrder R', 'P.order_id = R.order_id'); + $query->join('SupplyStoreOrder O', 'O.order_id = P.order_id'); + $query + ->when(isset($where['activity_id']), function ($query) use ($where) { + $query->where('P.activity_id', $where['activity_id']); + }) + ->when(isset($where['product_sku']), function ($query) use ($where) { + $query->where('P.product_sku', $where['product_sku']); + }) + ->when(isset($where['day']), function ($query) use ($where) { + $query->whereDay('P.create_time', $where['day']); + }) + ->when($type == 1, function ($query) use ($where) { + $query->where('O.verify_time', null)->where('O.delivery_type', null); + }, function ($query) { + $query->where('R.refund_type', 2); + }) + ->where('P.product_type', 1)->where('R.status', 3); + return $query->sum('R.refund_num'); + } + + + /** + * TODO 用户的某个商品购买数量 + * @param int $uid + * @param int $productId + * @return int + * @author Qinii + * @day 2022/9/26 + */ + public function getMaxCountNumber(int $uid, int $productId) + { +// return StoreOrder::hasWhere('orderProduct',function($query) use($productId){ +// $query->where('product_id', $productId); +// }) +// ->where(function($query) { +// $query->where('is_del',0)->whereOr(function($query){ +// $query->where('is_del',1)->where('paid',1); +// }); +// })->where('StoreOrder.uid',$uid)->select() +// ; + return (int)SupplyStoreOrderProduct::hasWhere('orderInfo', function ($query) use ($uid) { + $query->where('uid', $uid)->where(function ($query) { + $query->where('is_del', 0)->whereOr(function ($query) { + $query->where('is_del', 1)->where('paid', 1); + }); + }); + })->where('product_id', $productId)->sum('product_num'); + } + + public function getOrderSn($order_id) + { + return SupplyStoreOrder::getDB()->where($this->getPk(), $order_id)->value('order_sn', ''); + } + + public function getSubOrderNotSend(int $group_order_id, int $order_id) + { + return SupplyStoreOrder::getDB()->where('group_order_id', $group_order_id)->where('status', 0)->where('order_id', '<>', $order_id)->count(); + } + + + /** + * 获取商户排行 + * @param string $date + * @param string $type + * @param string $sort + * @return mixed + */ + public function getMerchantTop(string $date, string $type = 'sales', string $sort = 'desc') + { + + $query = SupplyStoreOrder::getDB()->with(['merchant' => function ($query) { + $query->field('mer_id,mer_name,mer_avatar'); + }]); + $query = getModelTime($query, $date)->where('paid', 1)->where('mer_id', '>', 0)->field('mer_id,sum(total_num) as sales,sum(pay_price + pay_postage) as price')->group('mer_id'); + switch ($type) { + case 'sales': + $query->order('sales ' . $sort); + break; + case 'price': + $query->order('price ' . $sort); + break; + } + + return $query->limit(0, 10)->select()->toArray(); + } +} diff --git a/app/common/dao/store/order/SupplyStoreOrderProductDao.php b/app/common/dao/store/order/SupplyStoreOrderProductDao.php new file mode 100644 index 00000000..2a3343a3 --- /dev/null +++ b/app/common/dao/store/order/SupplyStoreOrderProductDao.php @@ -0,0 +1,197 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\dao\store\order; + + +use app\common\dao\BaseDao; +use app\common\model\BaseModel; +use app\common\model\store\order\SupplyStoreOrderProduct; +use think\facade\Db; +use think\model\Relation; + +/** + * Class SupplyStoreOrderProductDao + * @package app\common\dao\store\order + * @author xaboy + * @day 2020/6/10 + */ +class SupplyStoreOrderProductDao extends BaseDao +{ + const ORDER_VERIFY_STATUS_ = 1; + const ORDER_VERIFY_STATUS_SUCCESS = 3; + /** + * @return string + * @author xaboy + * @day 2020/6/10 + */ + protected function getModel(): string + { + return SupplyStoreOrderProduct::class; + } + + /** + * @param $id + * @param $uid + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author xaboy + * @day 2020/6/10 + */ + public function userOrderProduct($id, $uid) + { + return SupplyStoreOrderProduct::getDB()->where('uid', $uid)->where('order_product_id', $id)->with(['orderInfo' => function (Relation $query) { + $query->field('order_id,order_sn,mer_id')->where('status', 2); + }])->find(); + } + + /** + * @param $orderId + * @return int + * @author xaboy + * @day 2020/6/12 + */ + public function noReplyProductCount($orderId) + { + return SupplyStoreOrderProduct::getDB()->where('order_id', $orderId)->where('is_refund','<>','3')->where('is_reply', 0) + ->count(); + } + + /** + * @param array $ids + * @param $uid + * @param null $orderId + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author xaboy + * @day 2020/6/12 + */ + public function userRefundProducts(array $ids, $uid, $orderId = null,$refund_switch = 1) + { + return SupplyStoreOrderProduct::getDB() + ->when($ids,function($query) use($ids){ + $query->whereIn('order_product_id', $ids); + }) + ->when($orderId, function ($query) use($orderId) { + $query->where('order_id', $orderId); + }) + ->when($uid, function ($query) use($uid) { + $query->where('uid', $uid); + }) + ->when($refund_switch, function ($query) use($refund_switch) { + $query->where('refund_switch', $refund_switch); + }) + ->where('refund_num', '>', 0)->select(); + } + + public function orderProductGroup($date, $merId = null, $limit = 7) + { + return SupplyStoreOrderProduct::getDB()->alias('A')->leftJoin('SupplyStoreOrder B', 'A.order_id = B.order_id') + ->field(Db::raw('sum(A.product_num) as total,A.product_id,cart_info')) + ->withAttr('cart_info', function ($val) { + return json_decode($val, true); + })->when($date, function ($query, $date) { + getModelTime($query, $date, 'B.pay_time'); + })->when($merId, function ($query, $merId) { + $query->where('B.mer_id', $merId); + })->where('B.paid', 1)->group('A.product_id')->limit($limit)->order('total DESC')->select(); + } + + public function dateProductNum($date) + { + return SupplyStoreOrderProduct::getDB()->alias('A')->leftJoin('SupplyStoreOrder B', 'A.order_id = B.order_id')->when($date, function ($query, $date) { + getModelTime($query, $date, 'B.pay_time'); + })->where('B.paid',1)->sum('A.product_num'); + } + + /** + * TODO 用户购买活动商品数量 + * @param int $activityId + * @param int $uid + * @param int $orderType + * @return int + * @author Qinii + * @day 2020-10-23 + */ + public function getUserPayCount(int $activityId,int $uid,int $productType) + { + $query = SupplyStoreOrderProduct::hasWhere('orderInfo',function($query){ + // 已支付/未支付 + $query->where('is_del',0)->whereOr(function($query){ + $query->where('paid',1)->where('is_del',1); + }); + }); + $query->where('uid',$uid)->where('product_type',$productType)->where('activity_id',$activityId); + $count = $query->count(); + return $count; + } + + + public function getUserPayProduct(?string $keyword, int $uid) + { + $query = SupplyStoreOrderProduct::hasWhere('spu',function($query) use($keyword){ + $query->when($keyword, function ($query) use($keyword) { + $query->whereLike('store_name',"%{$keyword}%"); + }); + $query->where('product_type',0); + }); + $query->where('uid', $uid)->where('SupplyStoreOrderProduct.product_type',0); + return $query; + } + + + /** + * 统计已支付的订单 商品相关信息 + * @param int $mer_id + * @param $type 统计类型 金额/数量/支付时间 + * @param $date 统计时间段 + * @param $limit + * @return mixed + * @author Qinii + * @day 2023/11/28 + */ + public function getProductRate(int $mer_id, $date = '', $type = 'number', $limit = 10, string $group = 'P.product_id') + { + $query = SupplyStoreOrderProduct::getDB()->alias('P')->leftJoin('SupplyStoreOrder O', 'O.order_id = P.order_id') + ->with(['product' => function ($query) { + $query->field('product_id,store_name,image'); + }])->where('O.paid', 1); + switch($type){ + case 'number': + $field = "P.product_id,O.pay_price as number,sum(P.product_num) as count,P.create_time, P.order_id,O.mer_id"; + break; + case 'count': + $field = "P.product_id,sum(P.product_num) as count,O.pay_price as number,P.create_time, P.order_id,O.mer_id"; + break; + case 'paytime': + $field = 'P.product_id,O.pay_time paytime,O.pay_price as number,P.create_time, P.order_id,O.mer_id'; + break; + default: + $field = 'P.*'; + break; + } + $query->when($mer_id, function ($query) use($mer_id) { + $query->where('O.mer_id', $mer_id); + })->when($date, function($query) use ($date) { + getModelTime($query, $date,'P.create_time'); + }); + + return $query->field($field)->when(!empty($group), function ($query) use ($group) { + $query->group($group); + })->order("$type DESC")->limit($limit)->select(); + } +} diff --git a/app/common/dao/store/parameter/SupplyParameterValueDao.php b/app/common/dao/store/parameter/SupplyParameterValueDao.php new file mode 100644 index 00000000..6ccb029e --- /dev/null +++ b/app/common/dao/store/parameter/SupplyParameterValueDao.php @@ -0,0 +1,32 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\dao\store\parameter; + +use app\common\dao\BaseDao; +use app\common\model\store\parameter\SupplyParameterValue; + +class SupplyParameterValueDao extends BaseDao +{ + + protected function getModel(): string + { + return SupplyParameterValue::class; + } + + public function clear($id,$field) + { + $this->getModel()::getDB()->where($field, $id)->delete(); + } + + +} diff --git a/app/common/dao/store/product/SupplyProductAttrValueDao.php b/app/common/dao/store/product/SupplyProductAttrValueDao.php new file mode 100644 index 00000000..974c2d53 --- /dev/null +++ b/app/common/dao/store/product/SupplyProductAttrValueDao.php @@ -0,0 +1,303 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\dao\store\product; + +use app\common\dao\BaseDao; +use app\common\model\store\product\SupplyProductAttrValue as model; +// use app\common\repositories\store\product\ProductCdkeyRepository; +use app\common\repositories\store\product\SupplyProductRepository; +use think\db\exception\DbException; +use think\facade\Db; + +/** + * Class SupplyProductAttrValueDao + * @package app\common\dao\store\product + * @author xaboy + * @day 2020/6/9 + */ +class SupplyProductAttrValueDao extends BaseDao +{ + /** + * @return string + * @author xaboy + * @day 2020/6/9 + */ + protected function getModel(): string + { + return model::class; + } + + public function add($data,$isType) + { + if ($isType == 2) { + foreach ($data as $datum) { + if (!isset($datum['cdkey'])){ + $this->insertAll($data); + break; + } + $cdkey = $datum['cdkey']; + unset($datum['cdkey']); + $sku = $this->create($datum); + $arr = array_chunk($cdkey, 30); + foreach ($arr as $item){ + $sku->productCdkey()->saveAll($item); + } + } + + } else { + $this->insertAll($data); + } + } + + /** + * @Author:Qinii + * @Date: 2020/5/9 + * @param int $productId + * @return mixed + */ + public function clearAttr(int $productId) + { + // ($this->getModel())::where('product_id', $productId)->delete(); + // app()->make(ProductCdkeyRepository::class)->clearAttr($productId); + } + + /** + * @Author:Qinii + * @Date: 2020/5/9 + * @param int $merId + * @param $field + * @param $value + * @param null $except + * @return mixed + */ + public function getFieldColumnt($key, $value, $field, $except = null) + { + return ($this->getModel()::getDB())->when($except, function ($query, $except) use ($field) { + $query->where($field, '<>', $except); + })->where($key, $value)->column($field); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param $key + * @param $value + * @param $field + * @param null $except + * @return mixed + */ + public function getFieldSum($key, $value, $field, $except = null) + { + return ($this->getModel()::getDB())->when($except, function ($query, $except) use ($field) { + $query->where($field, '<>', $except); + })->where($key, $value)->sum($field); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param array $data + * @return mixed + */ + public function insert(array $data) + { + return ($this->getModel()::getDB())->insertAll($data); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int|null $merId + * @param $field + * @param $value + * @param null $except + * @return bool + */ + public function merFieldExists(?int $merId, $field, $value, $except = null) + { + return ($this->getModel())::getDB()->when($except, function ($query, $except) use ($field) { + $query->where($field, '<>', $except); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->where($field, $value)->count() > 0; + } + + /** + * @param $id + * @return mixed + * @author xaboy + * @day 2020/6/9 + */ + public function getSku($id) + { + return ($this->getModel())::where('product_id', $id); + } + + /** + * @param int|null $merId + * @param $field + * @param $value + * @param null $except + * @return mixed + * @author xaboy + * @day 2020/6/9 + */ + public function getFieldExists(?int $merId, $field, $value, $except = null) + { + return ($this->getModel())::getDB()->when($except, function ($query, $except) use ($field) { + $query->where($field, '<>', $except); + })->when($merId, function ($query, $merId) { + $query->where('mer_id', $merId); + })->where($field, $value); + } + + /** + * @param int $productId + * @param string $unique + * @param int $desc + * @return int + * @throws DbException + * @author xaboy + * @day 2020/6/8 + */ + public function descStock(int $productId, string $unique, int $desc) + { + return model::getDB()->where('product_id', $productId)->where('unique', $unique)->update([ + 'stock' => Db::raw('stock-' . $desc), + 'sales' => Db::raw('sales+' . $desc) + ]); + } + + /** + * @param int $productId + * @param string $sku + * @param int $desc + * @return int + * @throws DbException + * @author xaboy + * @day 2020/6/8 + */ + public function descSkuStock(int $productId, string $sku, int $desc) + { + return model::getDB()->where('product_id', $productId)->where('sku', $sku)->update([ + 'stock' => Db::raw('stock-' . $desc), + 'sales' => Db::raw('sales+' . $desc) + ]); + } + + /** + * @param int $productId + * @param string $unique + * @param int $inc + * @throws DbException + * @author xaboy + * @day 2020/6/8 + */ + public function incStock(int $productId, string $unique, int $inc) + { + model::getDB()->where('product_id', $productId)->where('unique', $unique)->inc('stock', $inc)->update(); + model::getDB()->where('product_id', $productId)->where('unique', $unique)->where('sales', '>=', $inc)->dec('sales', $inc)->update(); + } + + /** + * @param int $productId + * @param string $sku + * @param int $inc + * @throws DbException + * @author xaboy + * @day 2020/6/8 + */ + public function incSkuStock(int $productId, string $sku, int $inc) + { + model::getDB()->where('product_id', $productId)->where('sku', $sku)->inc('stock', $inc)->update(); + model::getDB()->where('product_id', $productId)->where('sku', $sku)->where('sales', '>', $inc)->dec('sales', $inc)->update(); + } + + /** + * @param int $productId + * @param string $unique + * @return bool + * @author xaboy + * @day 2020/6/9 + */ + public function attrExists(int $productId, string $unique): bool + { + return model::getDB()->where('product_id', $productId)->where('unique', $unique)->count() > 0; + } + + /** + * @param int $productId + * @param string $sku + * @return bool + * @author xaboy + * @day 2020/6/9 + */ + public function skuExists(int $productId, string $sku): bool + { + return model::getDB()->where('product_id', $productId)->where('sku', $sku)->count() > 0; + } + + /** + * TODO 商品佣金是否大于设置佣金比例 + * @param $productId + * @return bool + * @author Qinii + * @day 2020-06-25 + */ + public function checkExtensionById($productId) + { + $extension_one_rate = systemConfig('extension_one_rate'); + $extension_two_rate = systemConfig('extension_two_rate'); + + $count = ($this->getModel()::getDb())->where(function($query)use($productId,$extension_one_rate){ + $query->where('product_id',$productId)->whereRaw('price * '.$extension_one_rate.' > extension_one'); + })->whereOr(function($query)use($productId,$extension_two_rate){ + $query->where('product_id',$productId)->whereRaw('price * '.$extension_two_rate.' > extension_two'); + })->count(); + return $count ? false : true; + } + + public function search(array $where) + { + $query = ($this->getModel()::getDb()) + ->when(isset($where['product_id']) && $where['product_id'] !== '',function($query)use($where){ + $query->where('product_id',$where['product_id']); + }) + ->when(isset($where['sku']) && $where['sku'] !== '',function($query)use($where){ + $query->where('sku',$where['sku']); + }) + ->when(isset($where['unique']) && $where['unique'] !== '',function($query)use($where){ + $query->where('unique',$where['unique']); + }); + return $query; + } + + public function updates(array $ids, array $data) + { + $this->getModel()::getDb()->whereIn('product_id',$ids)->update($data); + } + + public function updatesExtension(array $ids, array $data) + { + app()->make(SupplyProductRepository::class)->updates($ids,['extension_type' => 1]); + $query = $this->getModel()::getDb()->where('product_id','in',$ids); + $query->chunk(100, function($list) use($data){ + foreach ($list as $item) { + $arr['extension_one'] = bcmul($item->price,$data['extension_one'],2); + $arr['extension_two'] = bcmul($item->price,$data['extension_two'],2); + $this->getModel()::getDb()->where('unique',$item->unique)->update($arr); + } + },'product_id'); + } +} diff --git a/app/common/dao/store/product/SupplySpuDao.php b/app/common/dao/store/product/SupplySpuDao.php new file mode 100644 index 00000000..68a42e3a --- /dev/null +++ b/app/common/dao/store/product/SupplySpuDao.php @@ -0,0 +1,253 @@ + +// +---------------------------------------------------------------------- +namespace app\common\dao\store\product; + +use app\common\dao\BaseDao; +use app\common\model\store\product\SupplyProductCate; +use app\common\model\store\product\SupplySpu; +use app\common\model\store\SupplyStoreCategory; +use app\common\repositories\store\SupplyStoreCategoryRepository; +use app\common\repositories\system\supply\SupplyRepository; +use crmeb\services\VicWordService; + +class SupplySpuDao extends BaseDao +{ + public function getModel(): string + { + return SupplySpu::class; + } + + public function search($where) + { + $order = 'P.sort DESC'; + if(isset($where['order'])){ + if(in_array($where['order'], ['is_new', 'price_asc', 'price_desc', 'rate', 'sales','ot_price','ot_price_desc','ot_price_asc'])){ + switch ($where['order']) { + case 'price_asc': + $order = 'S.price ASC'; + break; + case 'price_desc': + $order = 'S.price DESC'; + break; + case 'ot_price_asc': + $order = 'S.ot_price ASC'; + break; + case 'ot_price_desc': + $order = 'S.ot_price DESC'; + break; + default: + $order = 'P.'.$where['order'] . ' DESC'; + break; + } + }elseif($where['order'] == 'star'){ + $order = 'S.star DESC,S.rank DESC'; + }else{ + $order = 'S.'. (($where['order'] !== '') ? $where['order']: 'star' ).' DESC'; + } + } + + $order .= ',S.create_time DESC'; + if(isset($where['order']) && $where['order'] === 'none'){ + $order = ''; + } + $query = SupplySpu::getDB()->alias('S')->join('StoreProduct P','S.product_id = P.product_id', 'left'); + $query->when(isset($where['is_del']) && $where['is_del'] !== '',function($query)use($where){ + $query->where('P.is_del',$where['is_del']); + }) + ->when(isset($where['mer_id']) && $where['mer_id'] !== '',function($query)use($where){ + $query->where('P.mer_id',$where['mer_id']); + }) + ->when(isset($where['mer_ids']) && $where['mer_ids'] !== '',function($query)use($where){ + $query->whereIn('P.mer_id',$where['mer_ids']); + }) + ->when(isset($where['product_ids']) && $where['product_ids'] !== '',function($query)use($where){ + $query->whereIn('P.product_id',$where['product_ids']); + }) + ->when(isset($where['keyword']) && $where['keyword'] !== '',function($query)use($where){ + if (is_numeric($where['keyword'])) { + $query->whereLike("S.store_name|S.keyword|S.product_id", "%{$where['keyword']}%"); + } else { + $word = app()->make(VicWordService::class)->getWord($where['keyword']); + $query->where(function ($query) use ($word) { + foreach ($word as $item) { + $query->whereOr('S.store_name|S.keyword', 'LIKE', "%$item%"); + } + }); + } + }) + ->when(isset($where['is_trader']) && $where['is_trader'] !== '',function($query)use($where){ + $merId = app()->make(SupplyRepository::class)->search([ + 'is_trader' => $where['is_trader'], + 'status' => 1, + 'mer_state' => 1, + 'is_del' => 1, + ])->column('mer_id'); + + $query->whereIn('P.mer_id',$merId); + }) + ->when(isset($where['mer_type_id']) && $where['mer_type_id'] !== '',function($query)use($where){ + $merId = app()->make(SupplyRepository::class)->search([ + 'type_id' => $where['mer_type_id'], + 'status' => 1, + 'mer_state' => 1, + 'is_del' => 1, + ])->column('mer_id'); + + $query->whereIn('P.mer_id',$merId); + }) + ->when(isset($where['cate_pid']) && $where['cate_pid'], function ($query) use ($where) { + $storeCategoryRepository = app()->make(SupplyStoreCategoryRepository::class); + if (is_array($where['cate_pid'])) { + $cateIds = $storeCategoryRepository->selectChildrenId($where['cate_pid']); + } else { + $cateIds = $storeCategoryRepository->findChildrenId((int)$where['cate_pid']); + $where['cate_pid'] = [$where['cate_pid']]; + } + $cate = array_merge($cateIds, $where['cate_pid']); + $query->whereIn('P.cate_id', $cate); + }) + ->when(isset($where['cate_id']) && $where['cate_id'] !== '', function ($query) use ($where) { + is_array($where['cate_id']) ? $query->whereIn('P.cate_id', $where['cate_id']) : $query->where('P.cate_id', $where['cate_id']); + }) + ->when(isset($where['spu_id']) && $where['spu_id'] !== '', function ($query) use ($where) { + $query->where('S.spu_id',$where['spu_id']); + }) + ->when(isset($where['spu_ids']) && $where['spu_ids'] !== '', function ($query) use ($where) { + $query->whereIn('S.spu_id',$where['spu_ids']); + }) + ->when(isset($where['product_ids']) && !empty($where['product_ids']), function ($query) use ($where) { + $query->whereIn('P.product_id',$where['product_ids']); + }) + ->when(isset($where['is_stock']) && !empty($where['is_stock']), function ($query) use ($where) { + $query->where('P.stock','>',0); + }) + ->when(isset($where['is_coupon']) && !empty($where['is_coupon']), function ($query) use ($where) { + $query->whereIn('P.product_type','0,2'); + }) + ->when(isset($where['common']) && $where['common'] !== '', function ($query) use ($where) { + $query->whereIn('S.product_type', [0, 1]); + }) + ->when(isset($where['price_on']) && $where['price_on'] !== '',function($query)use($where){ + $query->where('S.price','>=',$where['price_on']); + }) + ->when(isset($where['price_off']) && $where['price_off'] !== '',function($query)use($where){ + $query->where('S.price','<=',$where['price_off']); + }) + ->when(isset($where['brand_id']) && $where['brand_id'] !== '', function ($query) use ($where) { + $query->whereIn('P.brand_id', array_map('intval', explode(',', $where['brand_id']))); + }) + ->when(isset($where['is_gift_bag']) && $where['is_gift_bag'] !== '',function($query)use($where){ + $query->where('P.is_gift_bag',$where['is_gift_bag']); + }) + ->when(isset($where['product_type']) && $where['product_type'] !== '',function($query)use($where){ + $query->where('S.product_type',$where['product_type']); + }) + ->when(isset($where['not_type']) && $where['not_type'] !== '',function($query)use($where){ + $query->whereNotIn('S.product_type',$where['not_type']); + }) + ->when(isset($where['action']) && $where['action'] !== '',function($query)use($where){ + $query->where('S.product_type','>',0)->where('S.mer_id','<>',0); + }) + ->when(isset($where['mer_cate_id']) && $where['mer_cate_id'] !== '',function($query)use($where){ + $ids = (SupplyStoreCategory::where('path','like','%/'.$where['mer_cate_id'].'/%'))->column('store_category_id'); + $ids[] = intval($where['mer_cate_id']); + $ids = array_unique($ids); + $productId = SupplyProductCate::where('mer_cate_id', 'in', $ids)->column('product_id'); + $productId = array_unique($productId); + $query->where('P.product_id','in',$productId); + }) + ->when(isset($where['mer_status']) && $where['mer_status'] !== '',function($query)use($where){ + $query->where('mer_status',$where['mer_status']); + }) + ->when(isset($where['spu_status']) && $where['spu_status'] !== '',function($query)use($where){ + $query->where('S.status',$where['spu_status']); + }) + ->when(isset($where['sys_labels']) && $where['sys_labels'] !== '',function($query)use($where){ + $query->whereLike('S.sys_labels',"%,{$where['sys_labels']},%"); + }) + ->when(isset($where['mer_labels']) && $where['mer_labels'] !== '',function($query)use($where){ + $query->whereLike('S.mer_labels',"%,{$where['mer_labels']},%"); + }) + ->when(isset($where['pid']) && $where['pid'] !== '', function ($query) use ($where) { + $query->join('StoreCategory CT','P.cate_id = CT.store_category_id')->where('CT.pid',$where['pid']); + }) + ->when(isset($where['delivery_way']) && $where['delivery_way'] !== '', function ($query) use ($where) { + $query->whereLike('P.delivery_way',"%{$where['delivery_way']}%"); + }) + ->when(isset($where['scope']) && $where['scope'] !== '', function ($query) use ($where) { + $scope = explode(',', $where['scope']); + if ($scope[1] <= 0) { + $query->where('S.ot_price','<',$where['scope']); + } else { + $query->where('S.ot_price','between',$scope); + } + }) + ->when(isset($where['hot_type']) && $where['hot_type'] !== '', function ($query) use ($where) { + if ($where['hot_type'] == 'new') $query->where('P.is_new', 1); + else if ($where['hot_type'] == 'hot') $query->where('P.is_hot', 1); + else if ($where['hot_type'] == 'best') $query->where('P.is_best', 1); + else if ($where['hot_type'] == 'good') $query->where('P.is_benefit', 1); + }) + ->when(isset($where['svip']) && $where['svip'] !== '',function($query)use($where){ + $query->where('svip_price_type','>',0)->where('mer_svip_status',1); + }) + ; + return $query->order($order); + } + + public function findOrCreateAll(array $where) + { + foreach ($where as $item) { + $item['activity_id'] = $item['activity_id'] ?? 0; + $data = $this->getModel()::getDB()->where('product_id', $item['product_id']) + ->where('product_type', $item['product_type']) + ->where('activity_id', $item['activity_id']) + ->find(); + if (!$data) $this->create($item); + } + } + + public function delProduct($id, $isDel = 1) + { + $this->getModel()::getDb()->where('product_id', $id)->update(['is_del' => $isDel]); + } + + public function getActivecategory($type) + { + $query = SupplySpu::getDB()->alias('S')->join('StoreProduct P','S.product_id = P.product_id') + ->join('StoreCategory C','C.store_category_id = P.cate_id'); + + $query->where('S.status',1)->where('S.product_type',$type)->where('C.is_show',1); + return $query->group('S.product_id')->column('C.path'); + } + + /** + * TODO 软删除商户的所有商品 + * @param $merId + * @author Qinii + * @day 5/15/21 + */ + public function clearProduct($merId) + { + + $this->getModel()::getDb()->where('mer_id', $merId)->update(['is_del' => 1]); + } + + public function clear(int $id, string $field) + { + $this->getModel()::getDB()->where($field, $id)->delete(); + } + + public function updatePrice($mer_id, $product_id, $price) + { + return $this->getModel()::getDB()->where('mer_id', $mer_id)->where('product_id', $product_id)->where('product_type', 0)->update(['price' => $price]); + } +} diff --git a/app/common/model/store/SupplyStoreBrand.php b/app/common/model/store/SupplyStoreBrand.php new file mode 100644 index 00000000..844f3f3d --- /dev/null +++ b/app/common/model/store/SupplyStoreBrand.php @@ -0,0 +1,46 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store; + +use app\common\model\BaseModel; + +class SupplyStoreBrand extends BaseModel +{ + + /** + * @return string + * @author xaboy + * @day 2020-03-30 + */ + public static function tablePk(): string + { + return 'brand_id'; + } + + /** + * @return string + * @author xaboy + * @day 2020-03-30 + */ + public static function tableName(): string + { + return 'supply_store_brand'; + } + + public function brandCategory() + { + return $this->belongsTo(SupplyStoreBrandCategory::class,'brand_category_id','store_brand_category_id'); + } + +} diff --git a/app/common/model/store/SupplyStoreBrandCategory.php b/app/common/model/store/SupplyStoreBrandCategory.php new file mode 100644 index 00000000..c33b066f --- /dev/null +++ b/app/common/model/store/SupplyStoreBrandCategory.php @@ -0,0 +1,52 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store; + +use app\common\model\BaseModel; + +class SupplyStoreBrandCategory extends BaseModel +{ + + /** + * @return string + * @author xaboy + * @day 2020-03-30 + */ + public static function tablePk(): string + { + return 'store_brand_category_id'; + } + + /** + * @return string + * @author xaboy + * @day 2020-03-30 + */ + public static function tableName(): string + { + return 'supply_store_brand_category'; + } + + public function getAncestorsAttr($value) + { + $value = self::whereIn('store_brand_category_id',$this->path_ids)->order('level ASC')->column('cate_name'); + return implode('/',$value).'/'.$this->cate_name; + } + + public function getPathIdsAttr() + { + return explode('/',$this->path); + } + +} diff --git a/app/common/model/store/SupplyStoreCategory.php b/app/common/model/store/SupplyStoreCategory.php new file mode 100644 index 00000000..188a0815 --- /dev/null +++ b/app/common/model/store/SupplyStoreCategory.php @@ -0,0 +1,104 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store; + +use app\common\model\BaseModel; +use app\common\model\store\product\SupplyProduct; +use think\Model; + +class SupplyStoreCategory extends BaseModel +{ + + /** + * @return string + * @author xaboy + * @day 2020-03-30 + */ + public static function tablePk(): string + { + return 'store_category_id'; + } + + /** + * @return string + * @author xaboy + * @day 2020-03-30 + */ + public static function tableName(): string + { + return 'supply_store_category'; + } + + /** + * 获取父级名称 + * @Author:Qinii + * @Date: 2020/5/22 + * @param $value + * @return string + */ + public function getAncestorsAttr($value) + { + $value = self::whereIn('store_category_id',$this->path_ids)->order('level ASC')->column('cate_name'); + return implode('/',$value).'/'.$this->cate_name; + } + + /** + * 获取path的id + * @Author:Qinii + * @Date: 2020/5/22 + * @return array + */ + public function getPathIdsAttr() + { + return explode('/',$this->path); + } + public function getHasProductAttr() + { + return SupplyProduct::where('cate_id',$this->store_category_id)->count() > 0 ? 1 : 0; + } + + + /** + * 获取子集id + * @Author:Qinii + * @Date: 2020/5/22 + * @param $value + * @return array + */ + public function getChildIdsAttr($value) + { + return self::where('path','like','%/'.$this->store_category_id.'/%')->column('store_category_id'); + } + + public function searchIdAttr($query,$value) + { + $query->where('store_category_id',$value); + } + + public function searchIdsAttr($query,$value) + { + $query->whereIn('store_category_id',$value); + } + + public function searchStatusAttr($query,$value) + { + $query->where('is_show',$value); + } + + public function searchMerIdsAttr($query,$value) + { + $query->whereIn('mer_id',$value); + } + +} diff --git a/app/common/model/store/order/SupplyStoreCart.php b/app/common/model/store/order/SupplyStoreCart.php new file mode 100644 index 00000000..7f013137 --- /dev/null +++ b/app/common/model/store/order/SupplyStoreCart.php @@ -0,0 +1,334 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\order; + + +use app\common\model\BaseModel; +use app\common\model\store\product\SupplyProduct; +use app\common\model\store\product\SupplyProductAttr; +use app\common\model\store\product\SupplyProductAttrValue; +use app\common\model\store\product\SupplySpu; +use app\common\repositories\store\order\StoreOrderRepository; + +// use app\common\model\store\product\ProductAssistSet; +// use app\common\model\store\product\ProductPresell; + +// use app\common\model\store\product\StoreDiscounts; +use app\common\model\system\supply\Supply; +// use app\common\repositories\store\product\ProductAssistSkuRepository; +use app\common\repositories\store\product\SupplyProductAttrValueRepository; +// use app\common\repositories\store\product\ProductGroupSkuRepository; +// use app\common\repositories\store\product\ProductPresellSkuRepository; +// use app\common\repositories\store\product\ProductSkuRepository; + +class SupplyStoreCart extends BaseModel +{ + + public static function tablePk(): ?string + { + return 'cart_id'; + } + + public static function tableName(): string + { + return 'supply_store_cart'; + } + + public function searchCartIdAttr($query,$value) + { + $query->where('cart_id',$value); + } + + + public function product() + { + return $this->hasOne(SupplyProduct::class, 'product_id', 'product_id'); + } + + public function productAttr() + { + return $this->hasOne(SupplyProductAttrValue::class, 'unique', 'product_attr_unique'); + } + + public function attr() + { + return $this->hasMany(SupplyProductAttr::class,'product_id','product_id'); + } + + public function attrValue() + { + return $this->hasMany(SupplyProductAttrValue::class, 'product_id', 'product_id'); + } + + public function merchant() + { + return $this->hasOne(Supply::class, 'mer_id', 'mer_id'); + } + + + public function productPresell() + { + return ''; + // return $this->hasOne(ProductPresell::class,'product_presell_id','source_id'); + } + + public function productDiscount() + { + return ''; + // return $this->hasOne(StoreDiscounts::class, 'discount_id', 'source_id'); + } + + public function getProductDiscountAttrAttr() + { + return ''; + // return app()->make(ProductSkuRepository::class)->getSearch(['active_id' => $this->source_id, 'unique' => $this->product_attr_unique,'active_type'=> 10])->find(); + } + + public function productAssistSet() + { + return ''; + // return $this->hasOne(ProductAssistSet::class,'product_assist_set_id','source_id'); + } + + public function getProductPresellAttrAttr() + { + return ''; + // return app()->make(ProductPresellSkuRepository::class)->getSearch(['product_presell_id' => $this->source_id, 'unique' => $this->product_attr_unique])->find(); + } + + public function getProductAssistAttrAttr() + { + return ''; + // $make = app()->make(ProductAssistSkuRepository::class); + // $where = [ + // "product_assist_id" => $this->productAssistSet->product_assist_id, + // "unique" => $this->product_attr_unique + // ]; + // return $make->getSearch($where)->find(); + } + + + /** + * TODO 活动商品 SKU + * @return array|\think\Model|null + * @author Qinii + * @day 1/13/21 + */ + public function getActiveSkuAttr() + { + // switch ($this->product_type) + // { + // case 2: + // $make = app()->make(ProductPresellSkuRepository::class); + // $where['product_presell_id'] = $this->source_id; + // break; + // case 3: + // $make = app()->make(ProductAssistSkuRepository::class); + // $where['product_assist_id'] = $this->productAssistSet->product_assist_id; + // break; + // case 4: + // $make = app()->make(ProductGroupSkuRepository::class); + // $where['product_group_id'] = $this->product->productGroup->product_group_id; + // break; + // default: + $make = app()->make(SupplyProductAttrValueRepository::class); + $where['product_id'] = $this->product_id; + // break; + // } + $where['unique'] = $this->product_attr_unique; + return $make->getSearch($where)->find(); + } + + public function getSpuAttr() + { + if ($this->product_type) { + $where = [ + 'activity_id' => $this->source_id, + 'product_type' => $this->product_type, + ]; + } else { + $where = [ + 'product_id' => $this->product_id, + 'product_type' => $this->product_type, + ]; + } + return SupplySpu::where($where)->field('spu_id,store_name')->find(); + } + /** + * TODO 检测商品是否有效 + * @return bool + * @author Qinii + * @day 2020-10-29 + */ + public function getCheckCartProductAttr() + { + if($this->is_fail == 1) return false; + + if(is_null($this->product) || is_null($this->productAttr) || $this->product->status !== 1 || $this->product->mer_status !== 1 || $this->product->is_del !== 0) + {$this->is_fail = 1;$this->save();return false;} + + // switch ($this->product_type) + // { + // case 0: //普通商品 + if ($this->product->product_type !== 0 || $this->product->is_show !== 1 || $this->productAttr->stock < $this->cart_num || $this->product->is_used !== 1) { + return false; + } + // break; + // case 1: //秒杀商品 + // if ($this->product->product_type !== 1 || $this->product->is_show !== 1) return false; + // //结束时间 + // if ($this->product->end_time < time()) return false; + // //限量 + // $order_make = app()->make(StoreOrderRepository::class); + // $count = $order_make->seckillOrderCounut($this->product_id); + // if ($this->productAttr->stock <= $count) return false; + + // //原商品sku库存 + // $value_make = app()->make(ProductAttrValueRepository::class); + // $sku = $value_make->getWhere(['sku' => $this->productAttr->sku, 'product_id' => $this->product->old_product_id]); + // if (!$sku || $sku['stock'] <= 0) return false; + + // break; + + // case 2: //预售商品 + // if($this->source !== 2 || $this->product->product_type !== 2) return false; + // if($this->productPresell->status !== 1 || + // $this->productPresell->is_show !== 1 || + // $this->productPresell->is_del !== 0 || + // $this->productPresell->presell_status !== 1) + // {$this->is_fail = 1;$this->save();return false;} + + // $sku = $this->ActiveSku; + // if(!$sku || !$sku->sku()) {$this->is_fail = 1; $this->save(); return false; } + + // //库存不足 + // if($sku->stock < $this->cart_num || $sku->sku->stock < $this->cart_num) return false; + // break; + + // case 3: //助力商品 + // if($this->source !== 3 || $this->product->product_type !== 3 || ($this->productAssistSet->assist_count !== $this->productAssistSet->yet_assist_count)) return false; + // if( + // $this->productAssistSet->stop_time < time() || + // $this->productAssistSet->sataus === -1 || + // !$this->productAssistSet->assist->is_show || + // $this->productAssistSet->assist->is_del !== 0 || + // $this->productAssistSet->assist->status !== 1) + // {$this->is_fail = 1;$this->save();return false;} + // $sku = $this->ActiveSku; + // if(!$sku || !$sku->sku()) { $this->is_fail = 1; $this->save(); return false; } + // //库存不足 + // if($sku->stock < $this->cart_num || $sku->sku->stock < $this->cart_num) return false; + // break; + // case 4: + // if($this->source !== 4 || $this->product->product_type !== 4 ) return false; + // $sku = $this->ActiveSku; + // if(!$sku || !$sku->sku()) { $this->is_fail = 1; $this->save(); return false; } + // //库存不足 + // if($sku->stock < $this->cart_num || $sku->sku->stock < $this->cart_num) return false; + // break; + // } + return true; + } + + /** + * TODO + * @return bool + * @author Qinii + * @day 2020-10-29 + */ + public function getUserPayCountAttr() + { + // $make = app()->make(StoreOrderRepository::class); + // switch ($this->product_type) + // { + // case 1: //秒杀 + // if(!$make->getDayPayCount($this->uid,$this->product_id,$this->cart_num) || !$make->getPayCount($this->uid,$this->product_id,$this->cart_num)) + // return false; + // break; + // case 2: //预售 + // $count = $this->productPresell->pay_count; + // if($count == 0) return true; + // $tattend = [ + // 'activity_id' => $this->source_id, + // 'product_type' => 2, + // ]; + // $pay_count = $make->getTattendCount($tattend,$this->uid)->sum('total_num'); + // if($pay_count < $count) return false; + // if (($count - $pay_count) < $this->cart_num) return false; + // break; + // case 3: //助力 + // $tattend = [ + // 'activity_id' => $this->source_id, + // 'product_type' => 3, + // ]; + // $pay_count = $make->getTattendCount($tattend,$this->uid)->count(); + // if($pay_count) return false; + + // $count = $this->productAssistSet->assist->pay_count; + // if($count !== 0){ + // $_tattend = [ + // 'exsits_id' => $this->productAssistSet->assist->product_assist_id, + // 'product_type' => 3, + // ]; + // $_count = $make->getTattendCount($_tattend,$this->uid)->count(); + // if($_count >= $count) return false; + // } + // break; + // case 4: + // $tattend = [ + // 'exsits_id' => $this->product_id, + // 'product_type' => 4, + // ]; + // $pay_count = $make->getTattendCount($tattend,$this->uid)->count(); + // if($pay_count) return false; + // $count = $this->product->productGroup->pay_count; + // if($count !== 0){ + // $_tattend = [ + // 'exsits_id' => $this->product_id, + // 'product_type' => 34, + // ]; + // $_count = $make->getTattendCount($_tattend,$this->uid)->count(); + // if($_count >= $count) return false; + // } + // break; + // } + return true; + } + + public function searchProductIdAttr($query,$value) + { + $query->where('product_id',$value); + } + public function searchUidAttr($query,$value) + { + $query->where('uid',$value); + } + public function searchIsNewAttr($query,$value) + { + $query->where('is_new',$value); + } + public function searchIsPayAttr($query,$value) + { + $query->where('is_pay',$value); + } + public function searchIsDelAttr($query,$value) + { + $query->where('is_del',$value); + } + public function searchIsFailAttr($query,$value) + { + $query->where('is_fail',$value); + } + +} diff --git a/app/common/model/store/order/SupplyStoreGroupOrder.php b/app/common/model/store/order/SupplyStoreGroupOrder.php new file mode 100644 index 00000000..fdd1b228 --- /dev/null +++ b/app/common/model/store/order/SupplyStoreGroupOrder.php @@ -0,0 +1,107 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\order; + + +use app\common\model\BaseModel; +use app\common\model\user\User; +// use app\common\repositories\store\coupon\StoreCouponRepository; + +class SupplyStoreGroupOrder extends BaseModel +{ + + public static function tablePk(): ?string + { + return 'group_order_id'; + } + + public static function tableName(): string + { + return 'supply_store_group_order'; + } + + public function orderList() + { + return $this->hasMany(SupplyStoreOrder::class, 'group_order_id', 'group_order_id'); + } + + public function user() + { + return $this->hasOne(User::class, 'uid', 'uid'); + } + + public function getGiveCouponAttr() + { + // if (count($this->give_coupon_ids)) + // return app()->make(StoreCouponRepository::class)->getGiveCoupon($this->give_coupon_ids); + return []; + } + + public function getCancelTimeAttr() + { + $timer = ((int)systemConfig('auto_close_order_timer')) ?: 15; + return date('m-d H:i', strtotime("+ $timer minutes", strtotime($this->create_time))); + } + + public function getCancelUnixAttr() + { + $timer = ((int)systemConfig('auto_close_order_timer')) ?: 15; + return strtotime("+ $timer minutes", strtotime($this->create_time)); + } + + public function getGiveCouponIdsAttr($value) + { + return $value ? explode(',', $value) : []; + } + + public function setGiveCouponIdsAttr($value) + { + return $value ? implode(',', $value) : ''; + } + + public function getCombinePayParams() + { + $params = [ + 'order_sn' => $this->group_order_sn, + 'sub_orders' => [], + 'attach' => 'order', + 'body' => '订单支付', + ]; + foreach ($this->orderList as $order) { + if ($order->pay_price > 0) { + $subOrder = [ + 'pay_price' => $order->pay_price, + 'order_sn' => $order->order_sn, + 'sub_mchid' => $order->merchant->sub_mchid, + ]; + $params['sub_orders'][] = $subOrder; + } + } + return $params; + } + + public function getPayParams($return_url = '') + { + $params = [ + 'order_sn' => $this->group_order_sn, + 'pay_price' => $this->pay_price, + 'attach' => 'order', + 'body' => '订单支付' + ]; + if ($return_url) { + $params['return_url'] = $return_url; + } + return $params; + } +} diff --git a/app/common/model/store/order/SupplyStoreOrder.php b/app/common/model/store/order/SupplyStoreOrder.php new file mode 100644 index 00000000..3840a893 --- /dev/null +++ b/app/common/model/store/order/SupplyStoreOrder.php @@ -0,0 +1,208 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\order; + + +use app\common\model\BaseModel; +// use app\common\model\community\Community; +// use app\common\model\store\product\ProductGroupUser; +// use app\common\model\store\service\StoreService; +use app\common\model\store\shipping\Express; +use app\common\model\system\supply\Supply; +use app\common\model\user\User; +// use app\common\repositories\store\MerchantTakeRepository; + +class SupplyStoreOrder extends BaseModel +{ + + public static function tablePk(): ?string + { + return 'order_id'; + } + + public static function tableName(): string + { + return 'supply_store_order'; + } + + public function orderProduct() + { + return $this->hasMany(StoreOrderProduct::class, 'order_id', 'order_id'); + } + + public function refundProduct() + { + return $this->orderProduct()->where('refund_num', '>', 0); + } + + public function refundOrder() + { + return $this->hasMany(StoreRefundOrder::class,'order_id','order_id'); + } + + public function orderStatus() + { + return $this->hasMany(StoreOrderStatus::class,'order_id','order_id')->order('change_time DESC'); + } + + public function merchant() + { + return $this->hasOne(Supply::class, 'mer_id', 'mer_id'); + } + + public function user() + { + return $this->hasOne(User::class, 'uid', 'uid'); + } + public function receipt() + { + return $this->hasOne(StoreOrderReceipt::class, 'order_id', 'order_id'); + } + + public function spread() + { + return $this->hasOne(User::class, 'uid', 'spread_uid'); + } + + public function TopSpread() + { + return $this->hasOne(User::class, 'uid', 'top_uid'); + } + + public function getUserPhoneAttr($value) + { + if (env('SHOW_PHONE',false) && app('request')->hasMacro('adminInfo') && $value && is_numeric($value)){ + if (app('request')->userType() !== 2 || app('request')->adminInfo()['level'] != 0) { + return substr_replace($value, '****', 3, 4); + } + } + return $value; + } + + public function groupOrder() + { + return $this->hasOne(StoreGroupOrder::class, 'group_order_id', 'group_order_id'); + } + + public function verifyService() + { + return ''; + // return $this->hasOne(StoreService::class, 'service_id', 'verify_service_id'); + } + + public function getTakeAttr() + { + return 1; + // return app()->make(MerchantTakeRepository::class)->get($this->mer_id); + } + + public function searchDataAttr($query, $value) + { + return getModelTime($query, $value); + } + + public function presellOrder() + { + return $this->hasOne(PresellOrder::class, 'order_id', 'order_id'); + } + + public function finalOrder() + { + return $this->hasOne(PresellOrder::class,'order_id','order_id'); + } + + public function groupUser() + { + return ''; + // return $this->hasOne(ProductGroupUser::class,'order_id','order_id'); + } + + public function profitsharing() + { + return $this->hasMany(StoreOrderProfitsharing::class, 'order_id', 'order_id'); + } + + public function firstProfitsharing() + { + return $this->hasOne(StoreOrderProfitsharing::class, 'order_id', 'order_id')->where('type', 'order'); + } + + public function presellProfitsharing() + { + return $this->hasOne(StoreOrderProfitsharing::class, 'order_id', 'order_id')->where('type', 'presell'); + } + + // 核销订单的自订单列表 + public function takeOrderList() + { + return $this->hasMany(self::class,'main_id','order_id')->order('verify_time DESC'); + } + + public function searchMerIdAttr($query, $value) + { + return $query->where('mer_id', $value); + } + + public function getRefundStatusAttr() + { + $day = (int)systemConfig('sys_refund_timer') ?: 15; + return ($this->verify_time ? strtotime($this->verify_time) > strtotime('-' . $day . ' day') : true); + } + + public function getCancelTimeAttr() + { + if (!$this->apid) { + $timer = ((int)systemConfig('auto_close_order_timer')) ?: 15; + return date('m-d H:i', strtotime("+ $timer minutes", strtotime($this->groupOrder->create_time))); + } + return null; + } + + public function getOpenReceiptAttr() + { + return merchantConfig($this->mer_id,'mer_open_receipt') ?: 0; + } + + public function getOrderExtendAttr($val) + { + return $val ? json_decode($val, true) : null; + } + + public function getRefundExtensionOneAttr() + { + if ( $this->refundOrder ){ + return $this->refundOrder()->where('status',3)->sum('extension_one'); + } + return 0; + } + + public function getRefundExtensionTwoAttr() + { + if ( $this->refundOrder ){ + return $this->refundOrder()->where('status',3)->sum('extension_two'); + } + return 0; + } + + public function community() + { + return ''; + // return $this->hasOne(Community::class, 'order_id', 'order_id')->bind(['community_id']); + } + + public function getRefundPriceAttr() + { + return StoreRefundOrder::where('order_id',$this->order_id)->where('status',3)->sum('refund_price'); + } +} diff --git a/app/common/model/store/order/SupplyStoreOrderProduct.php b/app/common/model/store/order/SupplyStoreOrderProduct.php new file mode 100644 index 00000000..743ebb0f --- /dev/null +++ b/app/common/model/store/order/SupplyStoreOrderProduct.php @@ -0,0 +1,88 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\order; + + +use app\common\model\BaseModel; +use app\common\model\store\product\SupplyProduct; +use app\common\model\store\product\SupplySpu; +use app\common\model\user\User; + +class SupplyStoreOrderProduct extends BaseModel +{ + + public static function tablePk(): ?string + { + return 'order_product_id'; + } + + public static function tableName(): string + { + return 'supply_store_order_product'; + } + + public function getCartInfoAttr($value) + { + return json_decode($value, true); + } + + public function orderInfo() + { + return $this->hasOne(StoreOrder::class, 'order_id', 'order_id'); + } + + public function user() + { + return $this->hasOne(User::class,'uid','uid'); + } + + public function product() + { + return $this->hasOne(SupplyProduct::class,'product_id','product_id'); + } + + public function spu() + { + return $this->hasOne(SupplySpu::class,'product_id','product_id'); + } + + public function searchUidAttr($query ,$value) + { + $query->where('uid',$value); + } + public function searchActivitIidAttr($query,$value) + { + $query->where('activity_id',$value); + } + public function searchProductTypeAttr($query,$value) + { + $query->where('product_type',$value); + } + public function searchOrderIdAttr($query,$value) + { + $query->where('order_id',$value); + } + public function searchProductIdAttr($query,$value) + { + $query->where('product_id',$value); + } + public function searchRefundSwitchAttr($query,$value) + { + $query->where('refund_switch',$value); + } + public function searchRefundNumAttr($query,$value) + { + $query->where('refund_num', '>' ,$value); + } +} diff --git a/app/common/model/store/order/SupplyStoreOrderStatus.php b/app/common/model/store/order/SupplyStoreOrderStatus.php new file mode 100644 index 00000000..5158b5f3 --- /dev/null +++ b/app/common/model/store/order/SupplyStoreOrderStatus.php @@ -0,0 +1,47 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\order; + + +use app\common\model\BaseModel; + +/** + * Class SupplyStoreOrderStatus + * @package app\common\model\store\order + * @author xaboy + * @day 2020/6/12 + */ +class SupplyStoreOrderStatus extends BaseModel +{ + + /** + * @return string|null + * @author xaboy + * @day 2020/6/12 + */ + public static function tablePk(): ?string + { + return null; + } + + /** + * @return string + * @author xaboy + * @day 2020/6/12 + */ + public static function tableName(): string + { + return 'supply_store_order_status'; + } +} diff --git a/app/common/model/store/parameter/SupplyParameterValue.php b/app/common/model/store/parameter/SupplyParameterValue.php new file mode 100644 index 00000000..d30489a8 --- /dev/null +++ b/app/common/model/store/parameter/SupplyParameterValue.php @@ -0,0 +1,41 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\model\store\parameter; + +use app\common\model\BaseModel; + +class SupplyParameterValue extends BaseModel +{ + + + public static function tablePk(): string + { + return 'parameter_attr_id'; + } + + public static function tableName(): string + { + return 'supply_parameter_value'; + } + + public function parameter() + { + return $this->hasOne(Parameter::class,'parameter_id','parameter_id'); + } + + public function searchParameterIdAttr($query, $value) + { + if (!is_array($value)) $value = [$value]; + $query->whereIn('parameter_id', $value); + } +} diff --git a/app/common/model/store/product/SupplyProduct.php b/app/common/model/store/product/SupplyProduct.php new file mode 100644 index 00000000..c21d8cda --- /dev/null +++ b/app/common/model/store/product/SupplyProduct.php @@ -0,0 +1,675 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\model\store\product; + +use app\common\dao\store\StoreSeckillActiveDao; +use app\common\model\BaseModel; +use app\common\model\store\coupon\StoreCouponProduct; +use app\common\model\store\Guarantee; +use app\common\model\store\GuaranteeTemplate; +use app\common\model\store\GuaranteeValue; +use app\common\model\store\parameter\ParameterValue; +// use app\common\model\store\shipping\ShippingTemplate; +use app\common\model\store\StoreBrand; +use app\common\model\store\StoreCategory; +use app\common\model\store\StoreSeckillActive; +use app\common\model\system\form\Form; +use app\common\model\system\supply\Supply; +use app\common\repositories\store\StoreCategoryRepository; +use crmeb\services\VicWordService; +use think\db\BaseQuery; +use think\facade\Db; +use think\model\concern\SoftDelete; + +class SupplyProduct extends BaseModel +{ + use SoftDelete; + + protected $deleteTime = 'is_del'; + protected $defaultSoftDelete = 0; + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tablePk(): string + { + return 'product_id'; + } + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tableName(): string + { + return 'supply_store_product'; + } + + /* + * ----------------------------------------------------------------------------------------------------------------- + * 属性 + * ----------------------------------------------------------------------------------------------------------------- + */ + public function getSliderImageAttr($value) + { + return $value ? explode(',', $value) : []; + } + + public function getGiveCouponIdsAttr($value) + { + return $value ? explode(',', $value) : []; + } + + public function getMaxExtensionAttr($value) + { + if ($this->extension_type) { + $org_extension = ($this->attrValue()->order('extension_one DESC')->value('extension_one')); + } else { + $org_extension = bcmul(($this->attrValue()->order('price DESC')->value('price')), systemConfig('extension_one_rate'), 2); + } + $spreadUser = (request()->hasMacro('isLogin') && request()->isLogin() && request()->userType() == 1) ? request()->userInfo() : null; + if ($spreadUser && $spreadUser->brokerage_level > 0 && $spreadUser->brokerage && $spreadUser->brokerage->extension_one_rate > 0) { + $org_extension = bcmul($org_extension, 1 + $spreadUser->brokerage->extension_one_rate, 2); + } + return $org_extension; + } + + public function getMinExtensionAttr($value) + { + if ($this->extension_type) { + $org_extension = ($this->attrValue()->order('extension_two ASC')->value('extension_two')); + } else { + $org_extension = bcmul(($this->attrValue()->order('price ASC')->value('price')), systemConfig('extension_two_rate'), 2); + } + $spreadUser = (request()->hasMacro('isLogin') && request()->isLogin() && request()->userType() == 1) ? request()->userInfo() : null; + if ($spreadUser && $spreadUser->brokerage_level > 0 && $spreadUser->brokerage && $spreadUser->brokerage->extension_one_rate > 0) { + $org_extension = bcmul($org_extension, 1 + $spreadUser->brokerage->extension_one_rate, 2); + } + return $org_extension; + } + + public function check() + { + if (!$this || !$this->is_show || !$this->is_used || !$this->status || $this->is_del || !$this->mer_status) return false; + return true; + } + + /** + * TODO 秒杀商品结束时间 + * @return false|int + * @author Qinii + * @day 2020-08-15 + */ + public function getEndTimeAttr() + { + if ($this->product_type !== 1) return true; + $day = date('Y-m-d', time()); + $_day = strtotime($day); + $end_day = strtotime($this->seckillActive['end_day']); + if ($end_day >= $_day) + return strtotime($day . $this->seckillActive['end_time'] . ':00:00'); + if ($end_day < strtotime($day)) + return strtotime(date('Y-m-d', $end_day) . $this->seckillActive['end_time'] . ':00:00'); + } + + /** + * TODO 秒杀商品状态 + * @return array|int + * @author Qinii + * @day 2020-08-19 + */ + public function getSeckillStatusAttr() + { + if ($this->product_type !== 1) return true; + $day = strtotime(date('Y-m-d', time())); + $_h = date('H', time()); + if (!$this->seckillActive) return -1; + $start_day = strtotime($this->seckillActive['start_day']); + $end_day = strtotime($this->seckillActive['end_day']); + if ($this->seckillActive['status'] !== -1) { + //还未开始 + if ($start_day > time() || $this->is_show !== 1) return 0; + //已结束 + if ($end_day < $day) return -1; + //开始 - 结束 + if ($start_day <= $day && $day <= $end_day) { + //未开始 + if ($this->seckillActive['start_time'] > $_h) return 0; + //已结束 + if ($this->seckillActive['end_time'] <= $_h) return -1; + //进行中 + if ($this->seckillActive['start_time'] <= $_h && $this->seckillActive['end_time'] > $_h) return 1; + } + } + //已结束 + return -1; + } + + public function getImageAttr($value) + { + if (is_int(strpos($value, 'http'))) { + return $value; + } else { + return rtrim(systemConfig('site_url'), '/') . $value; + } + } + + public function getTopReplyAttr() + { + $res = []; + if (systemConfig('sys_reply_status')) { + $res = ProductReply::where('product_id', $this->product_id)->where('is_del', 0)->with(['orderProduct'])->field('reply_id,uid,nickname,merchant_reply_content,avatar,order_product_id,product_id,product_score,service_score,postage_score,comment,pics,rate,create_time') + ->order('sort DESC,create_time DESC')->limit(1)->find(); + if (!$res) return null; + if ($res['orderProduct']) + $res['sku'] = $res['orderProduct']['cart_info']['productAttr']['sku']; + unset($res['orderProduct']); + if (strlen($res['nickname']) > 1) { + $str = mb_substr($res['nickname'], 0, 1) . '*'; + if (strlen($res['nickname']) > 2) { + $str .= mb_substr($res['nickname'], -1, 1); + } + $res['nickname'] = $str; + } + } + return $res; + } + + public function getUsStatusAttr() + { + return ($this->status == 1) ? ($this->is_used == 1 ? ($this->mer_status == 1 && $this->is_show ? 1 : 0) : -1) : -1; + } + + public function getGuaranteeTemplateAttr() + { + $gua = GuaranteeTemplate::where('guarantee_template_id', $this->guarantee_template_id)->where('status', 1)->where('is_del', 0)->find(); + if (!$gua) return []; + $guarantee_id = GuaranteeValue::where('guarantee_template_id', $this->guarantee_template_id)->column('guarantee_id'); + return Guarantee::where('guarantee_id', 'in', $guarantee_id)->where('status', 1)->where('is_del', 0)->select(); + } + + public function getMaxIntegralAttr() + { + if (systemConfig('integral_status') && merchantConfig($this->mer_id, 'mer_integral_status')) { + $price = ($this->attrValue()->order('price DESC')->value('price')); + $rate = ($this->integral_rate < 0) ? merchantConfig($this->mer_id, 'mer_integral_rate') : $this->integral_rate; + $rate = $rate > 0 ? $rate / 100 : 0; + return bcmul($price, $rate, 2); + } + return '0'; + } + + public function getHotRankingAttr() + { + if ($this->product_type == 0) { + $where = [ + 'is_show' => 1, + 'status' => 1, + 'is_used' => 1, + 'product_type' => 0, + 'mer_status' => 1, + 'is_gift_bag' => 0, + 'cate_id' => $this->cate_id + ]; + self::where($where)->order('sales DESC'); + } + } + + public function getOtPriceAttr($value) + { + if ($this->product_type == 20) { + return (int)$value; + } + return $value; + } + + /** + * TODO 商品参数 + * @author Qinii + * @day 2022/11/24 + */ + public function getParamsAttr() + { + if (in_array($this->product_type, [0, 2])) { + $product_id = $this->product_id; + } else { + $product_id = $this->old_product_id; + } + return ParameterValue::where('product_id', $product_id)->order('parameter_value_id ASC')->select(); + } + + public function getParamTempIdAttr($value) + { + return $value ? explode(',', $value) : $value; + } + + /** + * TODO 是否是会员 + * @return bool + * @author Qinii + * @day 2023/1/4 + */ + public function getIsVipAttr() + { + if (request()->hasMacro('isLogin') && request()->isLogin()) { + if (request()->userType() == 1) { + $userInfo = request()->userInfo(); + return $userInfo->is_svip > 0 ? true : false; + } else { + return true; + } + } + return false; + } + + /** + * TODO 是否展示会员价 + * @return bool + * @author Qinii + * @day 2023/1/4 + */ + public function getShowSvipPriceAttr() + { + if ($this->mer_svip_status != 0 && (systemConfig('svip_show_price') != 1 || $this->is_vip) && $this->svip_price_type > 0) { + return true; + } + return false; + } + + + /** + * TODO 是否显示会员价等信息 + * @return array + * @author Qinii + * @day 2022/11/24 + */ + public function getShowSvipInfoAttr() + { + $res = [ + 'show_svip' => true, //是否展示会员入口 + 'is_svip' => false, //当前用户是否是会员 + 'show_svip_price' => false, //是否展示会员价 + 'save_money' => 0, //当前商品会员优化多少钱 + ]; + if ($this->product_type == 0) { + if (!systemConfig('svip_switch_status')) { + $res['show_svip'] = false; + } else { + $res['is_svip'] = $this->is_vip; + if ($this->show_svip_price) { + $res['show_svip_price'] = true; + $res['save_money'] = bcsub($this->price, $this->svip_price, 2); + } + } + } + return $res; + } + + /** + * TODO 获取会员价 + * @return int|string + * @author Qinii + * @day 2023/1/4 + */ + public function getSvipPriceAttr() + { + if ($this->product_type == 0 && $this->mer_svip_status != 0 && $this->show_svip_price) { + //默认比例 + if ($this->svip_price_type == 1) { + $rate = merchantConfig($this->mer_id, 'svip_store_rate'); + $svip_store_rate = $rate > 0 ? bcdiv($rate, 100, 2) : 0; + $price = $this->attrValue()->order('price ASC')->value('price'); + return bcmul($price, $svip_store_rate, 2); + } + //自定义 + if ($this->svip_price_type == 2) { + return $this->getData('svip_price'); + } + } + return 0; + } + + public function getIsSvipPriceAttr() + { + if ($this->product_type == 0 && $this->mer_svip_status != 0) { + //默认比例 + if ($this->svip_price_type == 1) { + $rate = merchantConfig($this->mer_id, 'svip_store_rate'); + $svip_store_rate = $rate > 0 ? bcdiv($rate, 100, 2) : 0; + $price = $this->attrValue()->order('price ASC')->value('price'); + return bcmul($price, $svip_store_rate, 2); + } + //自定义 + if ($this->svip_price_type == 2) { + return $this->getData('svip_price'); + } + } + return 0; + } + + public function getGoodIdsAttr($value, $data) + { + if (empty($value)) { + return []; + } + + return explode(',', $value); + } + + /* + * ----------------------------------------------------------------------------------------------------------------- + * 关联模型 + * ----------------------------------------------------------------------------------------------------------------- + */ + public function merCateId() + { + return $this->hasMany(ProductCate::class, 'product_id', 'product_id')->field('product_id,mer_cate_id'); + } + + public function attr() + { + return $this->hasMany(ProductAttr::class, 'product_id', 'product_id'); + } + + public function attrValue() + { + return $this->hasMany(ProductAttrValue::class, 'product_id', 'product_id'); + } + + public function oldAttrValue() + { + return $this->hasMany(ProductAttrValue::class, 'product_id', 'old_product_id'); + } + + public function content() + { + return $this->hasOne(ProductContent::class, 'product_id', 'product_id'); + } + + protected function temp() + { + return '';//$this->hasOne(ShippingTemplate::class, 'shipping_template_id', 'temp_id'); + } + + public function storeCategory() + { + return $this->hasOne(StoreCategory::class, 'store_category_id', 'cate_id')->field('store_category_id,cate_name'); + } + + public function merchant() + { + return $this->hasOne(Supply::class, 'mer_id', 'mer_id')->field('is_trader,type_id,mer_id,mer_name,mer_avatar,product_score,service_score,postage_score,service_phone,care_count,is_margin'); + } + + public function reply() + { + return $this->hasMany(ProductReply::class, 'product_id', 'product_id')->order('create_time DESC'); + } + + public function brand() + { + return $this->hasOne(StoreBrand::class, 'brand_id', 'brand_id')->field('brand_id,brand_name'); + } + + public function seckillActive() + { + return $this->hasOne(StoreSeckillActive::class, 'product_id', 'product_id'); + } + + public function issetCoupon() + { + return $this->hasOne(StoreCouponProduct::class, 'product_id', 'product_id')->alias('A') + ->rightJoin('StoreCoupon B', 'A.coupon_id = B.coupon_id')->where(function (BaseQuery $query) { + $query->where('B.is_limited', 0)->whereOr(function (BaseQuery $query) { + $query->where('B.is_limited', 1)->where('B.remain_count', '>', 0); + }); + })->where(function (BaseQuery $query) { + $query->where('B.is_timeout', 0)->whereOr(function (BaseQuery $query) { + $time = date('Y-m-d H:i:s'); + $query->where('B.is_timeout', 1)->where('B.start_time', '<', $time)->where('B.end_time', '>', $time); + }); + })->field('A.product_id,B.*')->where('status', 1)->where('type', 1)->where('send_type', 0)->where('is_del', 0) + ->order('sort DESC,coupon_id DESC')->hidden(['is_del', 'status']); + } + + public function assist() + { + return $this->hasOne(ProductAssist::class, 'product_id', 'product_id'); + } + + public function productGroup() + { + return $this->hasOne(ProductGroup::class, 'product_id', 'product_id'); + } + + public function guarantee() + { + return $this->hasOne(GuaranteeTemplate::class, 'guarantee_template_id', 'guarantee_template_id')->where('status', 1)->where('is_del', 0); + } + + public function getForm() + { + return $this->hasOne(Form::class, 'form_id', 'mer_form_id'); + } + + public function getFormName() + { + return $this->hasOne(Form::class, 'form_id', 'mer_form_id')->bind(['mer_form_name' => 'name']); + } + + + /* + * ----------------------------------------------------------------------------------------------------------------- + * 搜索器 + * ----------------------------------------------------------------------------------------------------------------- + */ + public function searchMerCateIdAttr($query, $value) + { + $cate_ids = (StoreCategory::where('path', 'like', '%/' . $value . '/%'))->column('store_category_id'); + $cate_ids[] = intval($value); + $product_id = ProductCate::whereIn('mer_cate_id', $cate_ids)->column('product_id'); + $query->whereIn('Product.product_id', $product_id); + } + + public function searchKeywordAttr($query, $value) + { + if (!$value) return; + if (is_numeric($value)) { + $query->whereLike("Product.store_name|Product.keyword|bar_code|Product.product_id", "%{$value}%"); + } else if (is_array($value)) { + $query->where(function ($query) use ($value) { + foreach ($value as $item) { + $query->whereOr('Product.store_name|Product.keyword', 'LIKE', "%$item%"); + } + }); + } else { + $word = app()->make(VicWordService::class)->getWord($value); + $query->where(function ($query) use ($word, $value) { + foreach ($word as $item) { + $query->whereOr('Product.store_name|Product.keyword', 'LIKE', "%$item%"); + } + $query->order(Db::raw('REPLACE(Product.store_name,\'' . $value . '\',\'\')')); + }); + } + } + + public function searchStatusAttr($query, $value) + { + if ($value === -1) { + $query->where('Product.status', 'in', [-1, -2]); + } else { + $query->where('Product.status', $value); + } + } + + public function searchCatePidAttr($query, $value) + { + $query->when($value, function ($query) use ($value) { + $storeCategoryRepository = app()->make(StoreCategoryRepository::class); + if (is_array($value)) { + $cateIds = $storeCategoryRepository->selectChildrenId($value); + } else { + $cateIds = $storeCategoryRepository->findChildrenId((int)$value); + $cateIds[] = $value; + } + $query->whereIn('cate_id', $cateIds); + }); + } + + public function searchCateIdAttr($query, $value) + { + $query->where('cate_id', $value); + } + + public function searchCateIdsAttr($query, $value) + { + $query->whereIn('cate_id', $value); + } + + public function searchIsShowAttr($query, $value) + { + $query->where('is_show', $value); + } + + public function searchPidAttr($query, $value) + { + $childrenId = app()->make(StoreCategoryRepository::class)->findChildrenId((int)$value); + $ids = array_merge($childrenId, [(int)$value]); + $query->whereIn('cate_id', $ids); + } + + public function searchStockAttr($query, $value) + { + $value ? $query->where('stock', '<=', $value) : $query->where('stock', $value); + } + + public function searchIsNewAttr($query, $value) + { + $query->where('is_new', $value); + } + + public function searchPriceAttr($query, $value) + { + if (empty($value[0]) && !empty($value[1])) + $query->where('price', '<', $value[1]); + if (!empty($value[0]) && empty($value[1])) + $query->where('price', '>', $value[0]); + if (!empty($value[0]) && !empty($value[1])) + $query->whereBetween('price', [$value[0], $value[1]]); + } + + public function searchBrandIdAttr($query, $value) + { + $query->whereIn('brand_id', $value); + } + + public function searchIsGiftBagAttr($query, $value) + { + $query->where('is_gift_bag', $value); + } + + public function searchIsGoodAttr($query, $value) + { + $query->where('is_good', $value); + } + + public function searchIsUsedAttr($query, $value) + { + $query->where('is_used', $value); + } + + public function searchProductTypeAttr($query, $value) + { + $query->where('Product.product_type', $value); + } + + public function searchSeckillStatusAttr($query, $value) + { + $product_id = (new StoreSeckillActiveDao())->getStatus($value)->column('product_id'); + $query->whereIn('Product.product_id', $product_id); + } + + public function searchStoreNameAttr($query, $value) + { + $query->where('Product.store_name', 'like', '%' . $value . '%'); + } + + public function searchMerStatusAttr($query, $value) + { + $query->where('mer_status', $value); + } + + public function searchProductIdAttr($query, $value) + { + $query->where('Product.product_id', $value); + } + + public function searchProductIdsAttr($query, $value) + { + $query->whereIn('Product.product_id', $value); + } + + public function searchNotProductIdAttr($query, $value) + { + if (!empty($value)) { + if (is_array($value)) { + $query->whereNotIn('Product.product_id', $value); + } else { + $query->where('Product.product_id', '<>', $value); + } + } + + } + + public function searchPriceOnAttr($query, $value) + { + $query->where('price', '>=', $value); + } + + public function searchPriceOffAttr($query, $value) + { + $query->where('price', '<=', $value); + } + + public function searchisFictiAttr($query, $value) + { + $query->where('type', $value); + } + + public function searchGuaranteeTemplateIdAttr($query, $value) + { + $query->whereIn('guarantee_template_id', $value); + } + + public function searchTempIdAttr($query, $value) + { + $query->whereIn('Product.temp_id', $value); + } + + public function searchDateAttr($query, $value) + { + getModelTime($query, $value, 'Product.create_time'); + } + + public function searchFormIdAttr($query, $value) + { + if ($value !== '') { + $query->whereIn('Product.mer_form_id', $value); + } + + } + +} diff --git a/app/common/model/store/product/SupplyProductAttr.php b/app/common/model/store/product/SupplyProductAttr.php new file mode 100644 index 00000000..0a48a0ba --- /dev/null +++ b/app/common/model/store/product/SupplyProductAttr.php @@ -0,0 +1,63 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\model\store\product; + +use app\common\model\BaseModel; + +class SupplyProductAttr extends BaseModel +{ + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tablePk(): string + { + return ''; + } + + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tableName(): string + { + return 'supply_store_product_attr'; + } + + /** + * @Author:Qinii + * @Date: 2020/5/9 + * @param $value + * @return array + */ + public function getAttrValuesAttr($value) + { + return explode('-!-',$value); + } + + /** + * @Author:Qinii + * @Date: 2020/5/9 + * @param $value + * @return string + */ + public function setAttrValuesAttr($value) + { + return implode('-!-',$value); + } + +} diff --git a/app/common/model/store/product/SupplyProductAttrValue.php b/app/common/model/store/product/SupplyProductAttrValue.php new file mode 100644 index 00000000..e57c1219 --- /dev/null +++ b/app/common/model/store/product/SupplyProductAttrValue.php @@ -0,0 +1,112 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\product; + +use app\common\model\BaseModel; + +class SupplyProductAttrValue extends BaseModel +{ + + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tablePk(): string + { + return 'value_id'; + } + + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tableName(): string + { + return 'supply_store_product_attr_value'; + } + + public function getDetailAttr($value) + { + return json_decode($value); + } + + public function product() + { + return $this->hasOne(Product::class, 'product_id','product_id'); + } + + public function getSvipPriceAttr() + { + if (isset($this->product->product_type) && $this->product->product_type == 0 && $this->product->show_svip_price && $this->product->svip_price_type == 1) { + $rate = merchantConfig($this->product->mer_id,'svip_store_rate'); + $svip_store_rate = $rate > 0 ? bcdiv($rate,100,2) : 0; + return bcmul($this->price, $svip_store_rate,2); + } + return $this->getData('svip_price'); + } + + public function getIsSvipPriceAttr() + { + if (isset($this->product->product_type) && $this->product->product_type == 0 && $this->product->svip_price_type == 1) { + $rate = merchantConfig($this->product->mer_id, 'svip_store_rate'); + $svip_store_rate = $rate > 0 ? bcdiv($rate, 100, 2) : 0; + return bcmul($this->price, $svip_store_rate, 2); + } + return '未设置'; + } + + public function getBcExtensionOneAttr() + { + if(!intval(systemConfig('extension_status'))) return 0; + if($this->product->extension_type == 1) return $this->extension_one; + return floatval(round(bcmul(systemConfig('extension_one_rate'), isset($this->org_price) ? $this->org_price : $this->price, 3),2)); + } + + public function getBcExtensionTwoAttr() + { + if(!intval(systemConfig('extension_status'))) return 0; + if($this->product->extension_type == 1) return $this->extension_two; + return floatval(round(bcmul(systemConfig('extension_two_rate'), isset($this->org_price) ? $this->org_price : $this->price, 3),2)); + } + + public function productSku() + { + return $this->hasOne(ProductSku::class, 'unique', 'unique'); + } + public function productCdkey() + { + return $this->hasMany(ProductCdkey::class,'value_id','value_id'); + } + + public function searchUniqueAttr($query,$value) + { + $query->where('unique',$value); + } + + public function searchSkuAttr($query,$value) + { + $query->where('sku',$value); + } + + public function searchProductIdAttr($query,$value) + { + $query->where('product_id',$value); + } + + +} diff --git a/app/common/model/store/product/SupplyProductCate.php b/app/common/model/store/product/SupplyProductCate.php new file mode 100644 index 00000000..fa6a45aa --- /dev/null +++ b/app/common/model/store/product/SupplyProductCate.php @@ -0,0 +1,51 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\model\store\product; + +use app\common\model\BaseModel; +use app\common\model\store\SupplyStoreCategory; + +class SupplyProductCate extends BaseModel +{ + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tablePk(): string + { + return ''; + } + + + /** + * @Author:Qinii + * @Date: 2020/5/8 + * @return string + */ + public static function tableName(): string + { + return 'supply_store_product_cate'; + } + + public function category() + { + return $this->hasOne(SupplyStoreCategory::class,'store_category_id','mer_cate_id')->field('store_category_id,cate_name'); + } + + public function searchProductIdAttr($query, $value) + { + $query->where('product_id',$value); + } +} diff --git a/app/common/model/store/product/SupplySpu.php b/app/common/model/store/product/SupplySpu.php new file mode 100644 index 00000000..230bf952 --- /dev/null +++ b/app/common/model/store/product/SupplySpu.php @@ -0,0 +1,240 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\model\store\product; + + +use app\common\model\BaseModel; +// use app\common\model\store\coupon\StoreCouponProduct; +// use app\common\model\store\StoreSeckillActive; +use app\common\model\system\supply\Supply; +// use think\db\BaseQuery; + +class SupplySpu extends BaseModel +{ + + /** + * TODO + * @return string + * @author Qinii + * @day 12/18/20 + */ + public static function tablePk(): string + { + return 'spu_id'; + } + + /** + * TODO + * @return string + * @author Qinii + * @day 12/18/20 + */ + public static function tableName(): string + { + return 'supply_store_spu'; + } + + + /* + * ----------------------------------------------------------------------------------------------------------------- + * 属性 + * ----------------------------------------------------------------------------------------------------------------- + */ + public function getMinExtensionAttr($value) + { + return isset($this->product) ? $this->product->min_extension : 0; + } + + public function getMaxExtensionAttr() + { + return isset($this->product) ? $this->product->max_extension : 0; + } + + public function getStopTimeAttr() + { + if($this->product_type == 1){ + if (is_null($this->seckillActive)) { + return date('Y-m-d H:i:s',strtotime("-1 day")); + } + $day = date('Y-m-d',time()); + $_day = strtotime($day); + $end_day = strtotime($this->seckillActive['end_day']); + if($end_day >= $_day) + return strtotime($day.$this->seckillActive['end_time'].':00:00'); + if($end_day < strtotime($day)) + return strtotime(date('Y-m-d',$end_day).$this->seckillActive['end_time'].':00:00'); + } + } + + public function setMerLabelsAttr($value) + { + if (!empty($value)) { + if (!is_array($value)) + return ','. $value .','; + return ','. implode(',', $value) .','; + } + return $value; + } + + public function getMerLabelsAttr($value) + { + if (!$value) return []; + return explode(',',rtrim(ltrim($value,','),',')); + } + + + public function setSysLabelsAttr($value) + { + if (!empty($value)) { + if (!is_array($value)) + return ','. $value .','; + return ','. implode(',', $value) .','; + } + return $value; + } + + public function getSysLabelsAttr($value) + { + if (!$value) return []; + return explode(',',rtrim(ltrim($value,','),',')); + } + + public function getImageAttr($value) + { + if (is_int(strpos($value, 'http'))) { + return $value; + } else { + return rtrim(systemConfig('site_url'), '/') . $value; + } + } + + public function getOtPriceAttr($value) + { + return (int)$value; + } + + /** + * TODO 是否展示会员价 + * @return array + * @author Qinii + * @day 2023/1/4 + */ + public function getShowSvipInfoAttr($value, $data) + { + if ($this->product_type == 0) return $this->product->show_svip_info; + } + + /** + * TODO 获取会员价 + * @return int|string + * @author Qinii + * @day 2023/1/4 + */ + public function getSvipPriceAttr() + { + if ($this->product_type == 0) return $this->product->svip_price; + } + + public function getIsSvipPriceAttr() + { + if ($this->product_type == 0) return $this->product->is_svip_price; + } + + public function getMerLabelsDataAttr() + { + return ProductLabel::whereIn('product_label_id',$this->mer_labels)->column('label_name'); + } + + public function getSysLabelsDataAttr() + { + return ProductLabel::whereIn('product_label_id',$this->sys_labels)->column('label_name'); + } + + /* + * ----------------------------------------------------------------------------------------------------------------- + * 关联表 + * ----------------------------------------------------------------------------------------------------------------- + */ + public function product() + { + return $this->hasOne(Product::class,'product_id','product_id'); + } + public function merchant() + { + return $this->hasOne(Supply::class,'mer_id','mer_id'); + } + public function issetCoupon() + { + return ''; + // return $this->hasOne(StoreCouponProduct::class, 'product_id', 'product_id')->alias('A') + // ->rightJoin('StoreCoupon B', 'A.coupon_id = B.coupon_id') + // ->where(function (BaseQuery $query) { + // $query->where('B.is_limited', 0)->whereOr(function (BaseQuery $query) { + // $query->where('B.is_limited', 1)->where('B.remain_count', '>', 0); + // }); + // })->where(function (BaseQuery $query) { + // $query->where('B.is_timeout', 0)->whereOr(function (BaseQuery $query) { + // $time = date('Y-m-d H:i:s'); + // $query->where('B.is_timeout', 1)->where('B.start_time', '<', $time)->where('B.end_time', '>', $time); + // }); + // })->field('A.product_id,B.*')->where('status', 1)->where('type', 1)->where('send_type', 0)->where('is_del', 0) + // ->order('sort DESC,coupon_id DESC')->hidden(['is_del', 'status']); + } + public function merCateId() + { + return $this->hasMany(ProductCate::class,'product_id','product_id')->field('product_id,mer_cate_id'); + } + public function seckillActive() + { + return ''; + // return $this->hasOne(StoreSeckillActive::class,'seckill_active_id','activity_id'); + } + + /* + * ----------------------------------------------------------------------------------------------------------------- + * 搜索器 + * ----------------------------------------------------------------------------------------------------------------- + */ + public function searchMerIdAttr($query,$value) + { + $query->where('mer_id',$value); + } + public function searchProductIdAttr($query,$value) + { + $query->where('product_id',$value); + } + public function searchProductTypeAttr($query,$value) + { + $query->where('product_type',$value); + } + public function searchActivityIdAttr($query,$value) + { + $query->where('activity_id',$value); + } + public function searchKeyworkAttr($query,$value) + { + $query->whereLike('store_name|keyword',$value); + } + public function searchPriceOnAttr($query, $value) + { + $query->where('price','>=',$value); + } + public function searchPriceOffAttr($query, $value) + { + $query->where('price','<=',$value); + } + public function searchSpuIdsAttr($query, $value) + { + $query->whereIn('spu_id',$value); + } +} diff --git a/app/common/repositories/store/SupplyStoreBrandRepository.php b/app/common/repositories/store/SupplyStoreBrandRepository.php new file mode 100644 index 00000000..ea61384f --- /dev/null +++ b/app/common/repositories/store/SupplyStoreBrandRepository.php @@ -0,0 +1,128 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\repositories\store; + +use app\common\repositories\BaseRepository; +use app\common\dao\store\SupplyStoreBrandDao as dao; +use app\common\repositories\store\product\SupplyProductRepository; +use FormBuilder\Factory\Elm; +use FormBuilder\Form; +use think\facade\Route; + +class SupplyStoreBrandRepository extends BaseRepository +{ + + public function __construct(dao $dao) + { + $this->dao = $dao; + } + + public function parentExists(int $id) + { + $make = app()->make(StoreBrandCategoryRepository::class); + return ($make->get($id)) ?? false; + } + + public function meExists($id) + { + return $this->dao->merFieldExists($this->dao->getPk(), $id); + } + + public function merExistsBrand(string $value) + { + return $this->dao->merFieldExists('brand_name', $value); + } + + public function getCategorySearch($where) + { + $make = app()->make(SupplyProductRepository::class); + $where = array_merge($where, $make->productShow()); + $brandIds = app()->make(SupplyProductRepository::class)->getBrandByCategory($where); + $count = 0; + $list = []; + if ($brandIds) { + $query = $this->dao->search(['ids' => $brandIds]); + $count = $query->count(); + $list = $query->select()->toArray(); + array_push($list, [ + "brand_id" => 0, + "brand_category_id" => 0, + "brand_name" => "其他", + "sort" => 999, + "pic" => "", + "is_show" => 1, + "create_time" => "", + ]); + } + return compact('count', 'list'); + } + + public function getList(array $where, $page, $limit) + { + $query = $this->dao->search($where) + ->with('brandCategory', function ($query) { + $query->field('store_brand_category_id,cate_name,path'); + }); + $count = $query->count(); + $list = $query->page($page, $limit)->select(); + return compact('count', 'list'); + } + + /** + * @Author:Qinii + * @Date: 2020/5/27 + * @param $id + * @return Form + */ + public function updateForm($id) + { + return $this->form($id, $this->dao->get($id)->toArray()); + } + + /** + * @Author:Qinii + * @Date: 2020/5/27 + * @param int|null $id + * @param array $formData + * @return Form + */ + public function form(?int $id = null, array $formData = []) + { + $form = Elm::createForm(is_null($id) ? Route::buildUrl('systemStoreBrandCreate')->build() : Route::buildUrl('systemStoreBrandUpdate', ['id' => $id])->build()); + $form->setRule([ + Elm::cascader('brand_category_id', '上级分类:')->options(function () use ($id) { + $menus = app()->make(StoreBrandCategoryRepository::class)->getAncestorsChildList(); + return $menus; + })->placeholder('请选择上级分类')->props(['props' => ['emitPath' => false]])->appendValidate(Elm::validateInt()->required()->message('请选择上级分类')), + Elm::input('brand_name', '品牌名称:')->placeholder('请输入品牌名称')->required(), + Elm::switches('is_show', '是否显示:', 1)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'), + Elm::number('sort', '排序:', 0)->precision(0)->max(99999), + ]); + return $form->setTitle(is_null($id) ? '添加品牌' : '编辑品牌')->formData($formData); + } + + /** + * TODO 品牌下是否存在商品 + * @param int $id + * @return bool + * @author Qinii + * @day 12/15/20 + */ + public function getBrandHasProduct(int $id) + { + $make = app()->make(SupplyProductRepository::class); + $count = $make->getSearch(['brand_id' => [$id]])->where('is_del', 0)->count(); + return $count ? true : false; + } +} diff --git a/app/common/repositories/store/SupplyStoreCategoryRepository.php b/app/common/repositories/store/SupplyStoreCategoryRepository.php new file mode 100644 index 00000000..9883f278 --- /dev/null +++ b/app/common/repositories/store/SupplyStoreCategoryRepository.php @@ -0,0 +1,188 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\repositories\store; + +use app\common\dao\store\SupplyStoreCategoryDao as dao; +use app\common\repositories\BaseRepository; +use FormBuilder\Exception\FormBuilderException; +use FormBuilder\Factory\Elm; +use FormBuilder\Form; +use think\db\exception\DataNotFoundException; +use think\db\exception\DbException; +use think\db\exception\ModelNotFoundException; +use think\facade\Route; +use crmeb\traits\CategoresRepository; + +/** + * @mixin dao + */ +class SupplyStoreCategoryRepository extends BaseRepository +{ + + use CategoresRepository; + + public function __construct(dao $dao) + { + $this->dao = $dao; + + } + + /** + * @param int $merId + * @param int|null $id + * @param array $formData + * @return Form + * @throws FormBuilderException + * @author xaboy + * @day 2020-04-20 + */ + public function form(int $merId, ?int $id = null, array $formData = []) + { + if ($merId) { + $form = Elm::createForm(is_null($id) ? Route::buildUrl('merchantStoreCategoryCreate')->build() : Route::buildUrl('merchantStoreCategoryUpdate', ['id' => $id])->build()); + $msg = ''; + } else { + $form = Elm::createForm(is_null($id) ? Route::buildUrl('systemStoreCategoryCreate')->build() : Route::buildUrl('systemStoreCategoryUpdate', ['id' => $id])->build()); + $msg = '注:平台商品分类请添加至三级分类,商户后台添加商品时才会展示该分类'; + } + //注:平台商品分类请添加至三级分类,商户后台添加商品时才会展示该分类。 + $form->setRule([ + Elm::cascader('pid', '上级分类:')->options(function () use ($id, $merId) { + $menus = $this->dao->getAllOptions($merId, 1, $this->dao->getMaxLevel($merId) - 1, 0); + if ($id && isset($menus[$id])) unset($menus[$id]); + $menus = formatCascaderData($menus, 'cate_name'); + array_unshift($menus, ['label' => '顶级分类', 'value' => 0]); + return $menus; + })->placeholder('请选择上级分类')->props(['props' => ['checkStrictly' => true, 'emitPath' => false]])->filterable(true)->appendValidate(Elm::validateInt()->required()->message('请选择上级分类'))->appendRule('suffix', [ + 'type' => 'div', + 'style' => ['color' => '#999999'], + 'domProps' => [ + 'innerHTML' => $msg, + ] + ]), + Elm::input('cate_name', '分类名称:')->placeholder('请输入分类名称')->required(), + Elm::frameImage('pic', '分类图片(110*110px):', '/' . config('admin.' . ($merId ? 'merchant' : 'admin') . '_prefix') . '/setting/uploadPicture?field=pic&type=1')->width('1000px')->height('600px')->icon('el-icon-camera')->props(['footer' => false])->modal(['modal' => false, 'custom-class' => 'suibian-modal']), + Elm::switches('is_show', '是否显示:', 1)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'), + Elm::number('sort', '排序:', 0)->precision(0)->max(99999), + ]); + + return $form->setTitle(is_null($id) ? '添加分类' : '编辑分类')->formData($formData); + } + + /** + * @param int $merId + * @param $id + * @return Form + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @throws FormBuilderException + * @author xaboy + * @day 2020-04-20 + */ + public function updateForm(int $merId, $id) + { + return $this->form($merId, $id, $this->dao->get($id, $merId)->toArray()); + } + + + /** + * @Author:Qinii + * @Date: 2020/5/16 + * @return mixed + */ + public function getList($status = null, $lv = null) + { + $menus = $this->dao->getAllOptions(0, $status, $lv, 0); + $menus = formatCascaderData($menus, 'cate_name', $lv ?: 3); + return $menus; + } + + /** + * @Author:Qinii + * @Date: 2020/5/18 + * @return mixed + */ + public function getBrandList() + { + return app()->make(StoreBrandRepository::class)->getAll(); + } + + /** + * 检测是否超过最低等级限制 + * @param int $id + * @param int $level + * @return bool + * @author Qinii + */ + public function checkLevel(int $id, int $level = 0, $merId = null) + { + $check = $this->getLevelById($id); + if ($level) + $check = $level; + return ($check < $this->dao->getMaxLevel($merId)) ? true : false; + } + + public function updateStatus($id, $data) + { + return $this->dao->update($id, $data); + } + + public function getHot($merId) + { + $hot = $this->dao->getSearch(['is_hot' => 1, 'mer_id' => $merId])->hidden(['path', 'level', 'mer_id', 'create_time'])->select(); + if ($hot) $hot->toArray(); + return compact('hot'); + } + + + public function pointsForm(?int $id) + { + $formData = []; + if ($id) { + $formData = $this->dao->get($id)->toArray(); + $form = Elm::createForm(Route::buildUrl('pointsCateUpdate', ['id' => $id])->build()); + } else { + $form = Elm::createForm(Route::buildUrl('pointsCateCreate')->build()); + } + $form->setRule([ + Elm::input('cate_name', '分类名称:')->required(), + Elm::switches('is_show', '是否显示:', 1)->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'), + Elm::number('sort', '排序:', 0)->precision(0)->max(99999), + Elm::number('type', '类型:', 1)->hiddenStatus(true), + ]); + return $form->setTitle(is_null($id) ? '添加分类' : '编辑分类')->formData($formData); + } + + public function getAllFatherName($id) + { + $info = $this->dao->get($id); + + if (empty($info)) { + return ' '; + } + + if ($info['pid'] > 0) { + $parentName = $this->getAllFatherName($info['pid']); + return $parentName . '/' . $info['cate_name']; + } else { + return $info['cate_name']; + } + } + + public function getCateName($cate_id) + { + return $this->dao->query([$this->dao->getPk() => $cate_id])->value('cate_name') ?? ''; + } +} diff --git a/app/common/repositories/store/order/SupplyStoreCartRepository.php b/app/common/repositories/store/order/SupplyStoreCartRepository.php new file mode 100644 index 00000000..fdc59393 --- /dev/null +++ b/app/common/repositories/store/order/SupplyStoreCartRepository.php @@ -0,0 +1,191 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\repositories\store\order; + + +use app\common\dao\store\order\SupplyStoreCartDao; +// use app\common\model\store\product\Product; +use app\common\repositories\BaseRepository; +// use app\common\repositories\store\coupon\StoreCouponProductRepository; +// use app\common\repositories\store\coupon\StoreCouponRepository; +use app\common\repositories\store\product\SupplyProductRepository; +// use app\common\repositories\user\MemberinterestsRepository; +use think\exception\ValidateException; +use think\facade\Db; + +/** + * Class SupplyStoreCartRepository + * @package app\common\repositories\store\order + * @author xaboy + * @day 2020/5/30 + * @mixin SupplyStoreCartDao + */ +class SupplyStoreCartRepository extends BaseRepository +{ + //购物车最大条数 + const CART_LIMIT_COUNT = 99; + + /** + * SupplyStoreCartRepository constructor. + * @param SupplyStoreCartDao $dao + */ + public function __construct(SupplyStoreCartDao $dao) + { + $this->dao = $dao; + } + + /** + * @param $uid + * @return array + * @author Qinii + */ + public function getList($user) + { + $res = $this->dao->getAll($user->uid)->append(['checkCartProduct', 'UserPayCount', 'ActiveSku','spu']); + return $this->checkCartList($res, $user->uid, $user); + } + + public function checkCartList($res, $hasCoupon = 0, $user = null) + { + $arr = $fail = []; + $product_make = app()->make(SupplyProductRepository::class); + $svip_status = ($user && $user->is_svip > 0 && systemConfig('svip_switch_status')) ? true : false; + foreach ($res as $item) { + if (!$item['checkCartProduct']) { + $item['product'] = $product_make->getFailProduct($item['product_id']); + $fail[] = $item; + } else { + //商户信息 + if ($item['merchant']){ + $merchantData = $item['merchant']->append(['openReceipt'])->toArray(); + } else { + $merchantData = ['mer_id' => 0]; + } + unset($item['merchant']); + // $coupon_make = app()->make(StoreCouponRepository::class); + // if (!isset($arr[$item['mer_id']])) { + // if ($hasCoupon) + // $merchantData['hasCoupon'] = $coupon_make->validMerCouponExists($item['mer_id'], $hasCoupon); + // $merchantData['hasCoupon']=0; + // $arr[$item['mer_id']] = $merchantData; + // } + // if ($hasCoupon && !$arr[$item['mer_id']]['hasCoupon']) { + // $couponIds = app()->make(StoreCouponProductRepository::class)->productByCouponId([$item['product']['product_id']]); + // $arr[$item['mer_id']]['hasCoupon'] = count($couponIds) ? $coupon_make->validProductCouponExists([$item['product']['product_id']], $hasCoupon) : 0; + // } + $arr[$item['mer_id']]['hasCoupon']=0; + if ($svip_status && $item['product']['show_svip_price']) { + $item['productAttr']['show_svip_price'] = true; + $item['productAttr']['org_price'] = $item['productAttr']['price']; + $item['productAttr']['price'] = $item['productAttr']['svip_price']; + } else { + $item['productAttr']['show_svip_price'] = false; + } + $arr[$item['mer_id']]['list'][] = $item; + } + } + $list = array_values($arr); + return compact('list', 'fail'); + } + + /** + * 获取单条购物车信息 + * @Author:Qinii + * @Date: 2020/5/30 + * @param int $id + * @return mixed + */ + public function getOne(int $id,int $uid) + { + $where = [$this->dao->getPk() => $id,'is_del'=>0,'is_fail'=>0,'is_new'=>0,'is_pay'=>0,'uid' => $uid]; + return ($this->dao->getWhere($where)); + } + + /** + * 查看相同商品的sku是存在 + * @param $sku + * @param $uid + * @author Qinii + */ + public function getCartByProductSku($sku,$uid) + { + $where = ['is_del'=>0,'is_fail'=>0,'is_new'=>0,'is_pay'=>0,'uid' => $uid,'product_type' => 0,'product_attr_unique' => $sku]; + return ($this->dao->getWhere($where)); + } + + + public function getProductById($productId) + { + $where = [ + 'is_del' =>0, + 'is_new'=>0, + 'is_pay'=>0, + 'product_id'=>$productId + ]; + return $this->dao->getWhereCount($where); + } + + public function checkPayCountByUser($ids,$uid,$productType,$cart_num) + { + $storeOrderRepository = app()->make(StoreOrderRepository::class); + $productRepository = app()->make(SupplyProductRepository::class); + switch ($productType) { + //普通商品 + case 0: + $products = $productRepository->getSearch([])->where('product_id',$ids)->select(); + foreach ($products as $product) { + if ($product['once_min_count'] > 0 && $product['once_min_count'] > $cart_num) + throw new ValidateException('[低于起购数:'.$product['once_min_count'].']'.mb_substr($product['store_name'],0,10).'...'); + if ($product['pay_limit'] == 1 && $product['once_max_count'] < $cart_num) + throw new ValidateException('[超出单次限购数:'.$product['once_max_count'].']'.mb_substr($product['store_name'],0,10).'...'); + if ($product['pay_limit'] == 2){ + //如果长期限购 + //已购买数量 + $count = $storeOrderRepository->getMaxCountNumber($uid,$product['product_id']); + if (($cart_num + $count) > $product['once_max_count']) + throw new ValidateException('[超出限购总数:'. $product['once_max_count'].']'.mb_substr($product['store_name'],0,10).'...'); + } + } + break; + case 1: + $products = $productRepository->getSearch([])->where('product_id',$ids)->select(); + foreach ($products as $product) { + if (!$storeOrderRepository->getDayPayCount($uid, $product['product_id'],$cart_num)) + throw new ValidateException('本次活动您购买数量已达到上限'); + if (!$storeOrderRepository->getPayCount($uid, $product['product_id'],$cart_num)) + throw new ValidateException('本次活动您该商品购买数量已达到上限'); + } + break; + } + return true; + } + + public function create(array $data) + { + return Db::transaction(function() use($data) { + if (!$data['is_new']) { + // 查询现有多少条数据 + $query = $this->dao->getSearch(['uid' => $data['uid'],'is_new' => 0,'is_pay' => 0,'is_fail' => 0 ])->order('create_time DESC'); + $count = $query->count(); + $limit = self::CART_LIMIT_COUNT; + //超过总限制的条数全部删除 + if ($count >= $limit) { + $cartId = $query->limit($limit,$count)->column('cart_id'); + $this->dao->updates($cartId,['is_del' => 1]); + } + } + return $this->dao->create($data); + }); + } +} diff --git a/app/common/repositories/store/order/SupplyStoreOrderProductRepository.php b/app/common/repositories/store/order/SupplyStoreOrderProductRepository.php new file mode 100644 index 00000000..ee230209 --- /dev/null +++ b/app/common/repositories/store/order/SupplyStoreOrderProductRepository.php @@ -0,0 +1,47 @@ + +// +---------------------------------------------------------------------- + + +namespace app\common\repositories\store\order; + + +use app\common\dao\store\order\SupplyStoreOrderProductDao; +use app\common\repositories\BaseRepository; + +/** + * Class SupplyStoreOrderProductRepository + * @package app\common\repositories\store\order + * @author xaboy + * @day 2020/6/8 + * @mixin StoreOrderProductDao + */ +class SupplyStoreOrderProductRepository extends BaseRepository +{ + /** + * SupplyStoreOrderProductRepository constructor. + * @param StoreOrderProductDao $dao + */ + public function __construct(SupplyStoreOrderProductDao $dao) + { + $this->dao = $dao; + } + + public function getUserPayProduct(?string $keyword, int $uid, int $page, int $limit) + { + $query = $this->dao->getUserPayProduct($keyword, $uid)->group('product_id'); + $count = $query->count(); + $list = $query->setOption('field',[])->field('SupplyStoreOrderProduct.uid,StoreOrderProduct.product_id,StoreOrderProduct.product_type,spu_id,image,store_name,price') + ->page($page, $limit)->select()->toArray(); + return compact('count', 'list'); + } + +} diff --git a/app/common/repositories/store/order/SupplyStoreOrderRepository.php b/app/common/repositories/store/order/SupplyStoreOrderRepository.php new file mode 100644 index 00000000..b5bca355 --- /dev/null +++ b/app/common/repositories/store/order/SupplyStoreOrderRepository.php @@ -0,0 +1,2456 @@ + +// +---------------------------------------------------------------------- +namespace app\common\repositories\store\order; + +use app\common\dao\store\order\SupplyStoreOrderDao; +use app\common\model\store\order\SupplyStoreGroupOrder; +use app\common\model\store\order\SupplyStoreOrder; +use app\common\model\user\User; +use app\common\repositories\BaseRepository; +// use app\common\repositories\delivery\DeliveryOrderRepository; +// use app\common\repositories\store\coupon\StoreCouponRepository; +// use app\common\repositories\store\coupon\StoreCouponUserRepository; +// use app\common\repositories\store\product\ProductAssistSetRepository; +use app\common\repositories\store\product\SupplyProductAttrValueRepository; +// use app\common\repositories\store\product\ProductCopyRepository; +// use app\common\repositories\store\product\ProductGroupBuyingRepository; +// use app\common\repositories\store\product\ProductPresellSkuRepository; +use app\common\repositories\store\product\SupplyProductRepository; +// use app\common\repositories\store\product\StoreDiscountRepository; +// use app\common\repositories\store\shipping\ExpressRepository; +// use app\common\repositories\store\StorePrinterRepository; +// use app\common\repositories\store\StoreSeckillActiveRepository; +use app\common\repositories\system\attachment\AttachmentRepository; +use app\common\repositories\system\supply\FinancialRecordRepository; +use app\common\repositories\system\supply\SupplyRepository; +use app\common\repositories\system\serve\ServeDumpRepository; +use app\common\repositories\user\UserBillRepository; +use app\common\repositories\user\UserBrokerageRepository; +use app\common\repositories\user\UserSupplyRepository; +use app\common\repositories\user\UserRepository; +// use crmeb\jobs\PayGiveCouponJob; +use crmeb\jobs\SendSmsJob; +use crmeb\jobs\UserBrokerageLevelJob; +use crmeb\services\CombinePayService; +use crmeb\services\CrmebServeServices; +use crmeb\services\ExpressService; +use crmeb\services\PayService; +use crmeb\services\printer\Printer; +use crmeb\services\QrcodeService; +use crmeb\services\SpreadsheetExcelService; +use crmeb\services\SwooleTaskService; +use Exception; +use FormBuilder\Factory\Elm; +use FormBuilder\Form; +use http\Exception\InvalidArgumentException; +use think\db\exception\DataNotFoundException; +use think\db\exception\DbException; +use think\db\exception\ModelNotFoundException; +use think\exception\ValidateException; +use think\facade\Config; +use think\facade\Db; +use think\facade\Log; +use think\facade\Queue; +use think\facade\Route; +use think\Model; +use think\model\Relation; + +/** + * Class SupplyStoreOrderRepository + * @package app\common\repositories\store\order + * @author xaboy + * @day 2020/6/9 + * @mixin SupplyStoreOrderDao + */ +class SupplyStoreOrderRepository extends BaseRepository +{ + /** + * 支付类型 0余额 1 微信 2 小程序 3 微信 4 支付宝 5 支付宝 6 微信 + */ + const PAY_TYPE = ['balance', 'weixin', 'routine', 'h5', 'alipay', 'alipayQr', 'weixinQr']; + const PAY_TYPE_FILTEER = [ + 0 => 0, + 1 => '1,2,3,6', + 2 => 4,5 + ]; + const TYPE_SN_ORDER = 'wxo'; + const TYPE_SN_PRESELL = 'wxp'; + const TYPE_SN_USER_ORDER = 'wxs'; + const TYPE_SN_USER_RECHARGE = 'wxu'; + const TYPE_SN_SERVER_ORDER = 'cs'; + const TYPE_SN_REFUND = 'rwx'; + /** + * SupplyStoreOrderRepository constructor. + * @param SupplyStoreOrderDao $dao + */ + public function __construct(SupplyStoreOrderDao $dao) + { + $this->dao = $dao; + } + + /** + * @param string $type + * @param User $user + * @param SupplyStoreGroupOrder $groupOrder + * @param string $return_url + * @return mixed + * @author xaboy + * @day 2020/10/22 + */ + public function pay(string $type, User $user, SupplyStoreGroupOrder $groupOrder, $return_url = '', $isApp = false) + { + + if ($type === 'balance') { + return $this->payBalance($user, $groupOrder); + } + + if (in_array($type, ['weixin', 'alipay'], true) && $isApp) { + $type .= 'App'; + } + event('order.pay.before', compact('groupOrder', 'type', 'isApp')); + if (in_array($type, ['weixin', 'weixinApp', 'routine', 'h5', 'weixinQr'], true) && systemConfig('open_wx_combine')) { + $service = new CombinePayService($type, $groupOrder->getCombinePayParams()); + } else { + $service = new PayService($type, $groupOrder->getPayParams($type === 'alipay' ? $return_url : '')); + } + $config = $service->pay($user); + return app('json')->status($type, $config + ['order_id' => $groupOrder['group_order_id']]); + } + + /** + * @param User $user + * @param SupplyStoreGroupOrder $groupOrder + * @return mixed + * @author xaboy + * @day 2020/6/9 + */ + public function payBalance(User $user, SupplyStoreGroupOrder $groupOrder) + { + if (!systemConfig('yue_pay_status')) + throw new ValidateException('未开启余额支付'); + if ($user['now_money'] < $groupOrder['pay_price']) + throw new ValidateException('余额不足,请更换支付方式'); + Db::transaction(function () use ($user, $groupOrder) { + $user->now_money = bcsub($user->now_money, $groupOrder['pay_price'], 2); + $user->save(); + $userBillRepository = app()->make(UserBillRepository::class); + $userBillRepository->decBill($user['uid'], 'now_money', 'pay_product', [ + 'link_id' => $groupOrder['group_order_id'], + 'status' => 1, + 'title' => '购买商品', + 'number' => $groupOrder['pay_price'], + 'mark' => '余额支付支付' . floatval($groupOrder['pay_price']) . '元购买商品', + 'balance' => $user->now_money + ]); + $this->paySuccess($groupOrder); + }); + return app('json')->status('success', '余额支付成功', ['order_id' => $groupOrder['group_order_id']]); + } + + public function changePayType(SupplyStoreGroupOrder $groupOrder, int $pay_type) + { + Db::transaction(function () use ($groupOrder, $pay_type) { + $groupOrder->pay_type = $pay_type; + foreach ($groupOrder->orderList as $order) { + $order->pay_type = $pay_type; + $order->save(); + } + $groupOrder->save(); + }); + } + + /** + * @return string + * @author xaboy + * @day 2020/8/3 + */ + public function verifyCode() + { + $code = substr(uniqid('', true), 15) . substr(microtime(), 2, 8); + if ($this->dao->existsWhere(['verify_code' => $code])) + return $this->verifyCode(); + else + return $code; + } + + /** + * //TODO 支付成功后 + * + * @param SupplyStoreGroupOrder $groupOrder + * @author xaboy + * @day 2020/6/9 + */ + public function paySuccess(SupplyStoreGroupOrder $groupOrder, $is_combine = 0, $subOrders = []) + { + $groupOrder->append(['user']); + //修改订单状态 + Db::transaction(function () use ($subOrders, $is_combine, $groupOrder) { + $time = date('Y-m-d H:i:s'); + $groupOrder->paid = 1; + $groupOrder->pay_time = $time; + $groupOrder->is_combine = $is_combine; + $orderStatus = []; + $groupOrder->append(['orderList.orderProduct']); + $flag = true; + $finance = []; + $profitsharing = []; + $financialRecordRepository = app()->make(FinancialRecordRepository::class); + $financeSn = $financialRecordRepository->getSn(); + $userMerchantRepository = app()->make(UserSupplyRepository::class); + $storeOrderProfitsharingRepository = app()->make(StoreOrderProfitsharingRepository::class); + $storeGroupOrderRepository = app()->make(StoreGroupOrderRepository::class); + $uid = $groupOrder->uid; + $i = 1; + $isVipCoupon = $storeGroupOrderRepository->isVipCoupon($groupOrder); + //验证是不是该用户的第一个订单 + $groupOrder->is_first = $storeGroupOrderRepository->validateOrderIsFirst((int)$groupOrder->uid); + //订单记录 + $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + $svipDiscount = 0; + $isPoints = false; + foreach ($groupOrder->orderList as $_k => $order) { + $order->paid = 1; + $order->pay_time = $time; + $svipDiscount = bcadd($order->svip_discount, $svipDiscount, 2); + if (isset($subOrders[$order->order_sn])) { + $order->transaction_id = $subOrders[$order->order_sn]['transaction_id']; + } + $presell = false; + //todo 等待付尾款 + // if ($order->activity_type == 2) { + // $_make = app()->make(ProductPresellSkuRepository::class); + // if ($order->orderProduct[0]['cart_info']['productPresell']['presell_type'] == 2) { + // $order->status = 10; + // $presell = true; + // } else { + // $_make->incCount($order->orderProduct[0]['activity_id'], $order->orderProduct[0]['product_sku'], 'two_pay'); + // } + // $_make->incCount($order->orderProduct[0]['activity_id'], $order->orderProduct[0]['product_sku'], 'one_pay'); + // } + // else if ($order->activity_type == 4) { + // $order->status = 9; + // $order->save(); + // $group_buying_id = app()->make(ProductGroupBuyingRepository::class)->create( + // $groupOrder->user, + // $order->orderProduct[0]['cart_info']['activeSku']['product_group_id'], + // $order->orderProduct[0]['activity_id'], + // $order->order_id + // ); + // $order->orderProduct[0]->activity_id = $group_buying_id; + // $order->orderProduct[0]->save(); + // } + // else if ($order->activity_type == 3) { + // //更新助力状态 + // app()->make(ProductAssistSetRepository::class)->changStatus($order->orderProduct[0]['activity_id']); + // } + if ($order->order_type == 1 && $order->status != 10) + $order->verify_code = $this->verifyCode(); + if ($order->orderProduct[0]->product->type == 2) { + $order->status = 2; + $order->delivery_type = 6; + $order->delivery_name = '自动发货'; + $order->delivery_id = $this->sendCdkey($order); + $isPoints = true; + } + $order->save(); + if ($isPoints) $this->takeAfter($order, $groupOrder->user); + $orderStatus[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $storeOrderStatusRepository::TYPE_ORDER, + 'change_message' => '订单支付成功', + 'change_type' => $storeOrderStatusRepository::ORDER_STATUS_PAY_SUCCCESS, + 'uid' => $order->uid, + 'nickname' => $order->user->nickname, + 'user_type' => $storeOrderStatusRepository::U_TYPE_USER, + ]; + + //TODO 成为推广员 + foreach ($order->orderProduct as $product) { + if ($flag && $product['cart_info']['product']['is_gift_bag']) { + app()->make(UserRepository::class)->promoter($order->uid); + $flag = false; + } + } + + $finance[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'user_info' => $groupOrder->user->nickname, + 'user_id' => $uid, + 'financial_type' => $presell ? 'order_presell' : 'order', + 'financial_pm' => 1, + 'type' => $presell ? 2 : 1, + 'number' => $order->pay_price, + 'mer_id' => $order->mer_id, + 'financial_record_sn' => $financeSn . ($i++) + ]; + + $_payPrice = bcsub($order->pay_price, bcadd($order['extension_one'], $order['extension_two'], 3), 2); + if ($presell) { + if (isset($order->orderProduct[0]['cart_info']['presell_extension_one']) && $order->orderProduct[0]['cart_info']['presell_extension_one'] > 0) { + $_payPrice = bcadd($_payPrice, $order->orderProduct[0]['cart_info']['presell_extension_one'], 2); + } + if (isset($order->orderProduct[0]['cart_info']['presell_extension_two']) && $order->orderProduct[0]['cart_info']['presell_extension_two'] > 0) { + $_payPrice = bcadd($_payPrice, $order->orderProduct[0]['cart_info']['presell_extension_two'], 2); + } + } + + $_order_rate = 0; + + if ($order['commission_rate'] > 0) { + $commission_rate = bcdiv((string)$order['commission_rate'],'100',6); + $_order_rate = bcmul($_payPrice, (string)$commission_rate, 2); + + $_payPrice = bcsub($_payPrice, $_order_rate, 2); + } + + if (!$presell) { + if ($order['extension_one'] > 0) { + $finance[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'user_info' => $groupOrder->user->nickname, + 'user_id' => $uid, + 'financial_type' => 'brokerage_one', + 'financial_pm' => 0, + 'type' => 1, + 'number' => $order['extension_one'], + 'mer_id' => $order->mer_id, + 'financial_record_sn' => $financeSn . ($i++) + ]; + } + + if ($order['extension_two'] > 0) { + $finance[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'user_info' => $groupOrder->user->nickname, + 'user_id' => $uid, + 'financial_type' => 'brokerage_two', + 'financial_pm' => 0, + 'type' => 1, + 'number' => $order['extension_two'], + 'mer_id' => $order->mer_id, + 'financial_record_sn' => $financeSn . ($i++) + ]; + } + if ($order['commission_rate'] > 0) { + $finance[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'user_info' => $groupOrder->user->nickname, + 'user_id' => $uid, + 'financial_type' => 'order_charge', + 'financial_pm' => 0, + 'type' => 1, + 'number' => $_order_rate, + 'mer_id' => $order->mer_id, + 'financial_record_sn' => $financeSn . ($i++) + ]; + } + $finance[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'user_info' => $groupOrder->user->nickname, + 'user_id' => $uid, + 'financial_type' => $order['activity_type'] ==20 ? 'points_order_true' : 'order_true', + 'financial_pm' => 0, + 'type' => 2, + 'number' => $_payPrice, + 'mer_id' => $order->mer_id, + 'financial_record_sn' => $financeSn . ($i++) + ]; + if ($order->platform_coupon_price > 0) { + $finance[] = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'user_info' => $groupOrder->user->nickname, + 'user_id' => $uid, + 'financial_type' => $isVipCoupon ? 'order_svip_coupon' : 'order_platform_coupon', + 'financial_pm' => 0, + 'type' => 1, + 'number' => $order->platform_coupon_price, + 'mer_id' => $order->mer_id, + 'financial_record_sn' => $financeSn . ($i++) + ]; + $_payPrice = bcadd($_payPrice, $order->platform_coupon_price, 2); + } + if (!$is_combine) { + app()->make(SupplyRepository::class)->addLockMoney($order->mer_id, 'order', $order->order_id, $_payPrice); + } + } + if ($is_combine) { + $profitsharing[] = [ + 'profitsharing_sn' => $storeOrderProfitsharingRepository->getOrderSn(), + 'order_id' => $order->order_id, + 'transaction_id' => $order->transaction_id ?? '', + 'mer_id' => $order->mer_id, + 'profitsharing_price' => $order->pay_price, + 'profitsharing_mer_price' => $_payPrice, + 'type' => $storeOrderProfitsharingRepository::PROFITSHARING_TYPE_ORDER, + ]; + } + $userMerchantRepository->updatePayTime($uid, $order->mer_id, $order->pay_price); + SwooleTaskService::merchant('notice', [ + 'type' => 'new_order', + 'data' => [ + 'title' => '新订单', + 'message' => '您有一个新的订单', + 'id' => $order->order_id + ] + ], $order->mer_id); + //自动打印订单 + $this->autoPrinter($order->order_id, $order->mer_id); + } + if ($groupOrder->user->spread_uid) { + Queue::push(UserBrokerageLevelJob::class, ['uid' => $groupOrder->user->spread_uid, 'type' => 'spread_pay_num', 'inc' => 1]); + Queue::push(UserBrokerageLevelJob::class, ['uid' => $groupOrder->user->spread_uid, 'type' => 'spread_money', 'inc' => $groupOrder->pay_price]); + } + app()->make(UserRepository::class)->update($groupOrder->uid, [ + 'pay_count' => Db::raw('pay_count+' . count($groupOrder->orderList)), + 'pay_price' => Db::raw('pay_price+' . $groupOrder->pay_price), + 'svip_save_money' => Db::raw('svip_save_money+' . $svipDiscount), + ]); + $this->giveIntegral($groupOrder); + if (count($profitsharing)) { + $storeOrderProfitsharingRepository->insertAll($profitsharing); + } + $financialRecordRepository->insertAll($finance); + $storeOrderStatusRepository->batchCreateLog($orderStatus); + // if (count($groupOrder['give_coupon_ids']) > 0) + // $groupOrder['give_coupon_ids'] = app()->make(StoreCouponRepository::class)->getGiveCoupon($groupOrder['give_coupon_ids'])->column('coupon_id'); + $groupOrder->save(); + }); + // if (count($groupOrder['give_coupon_ids']) > 0) { + // try { + // Queue::push(PayGiveCouponJob::class, ['ids' => $groupOrder['give_coupon_ids'], 'uid' => $groupOrder['uid']]); + // } catch (Exception $e) { + // } + // } + + Queue::push(SendSmsJob::class, ['tempId' => 'ORDER_PAY_SUCCESS', 'id' => $groupOrder->group_order_id]); + Queue::push(SendSmsJob::class, ['tempId' => 'ADMIN_PAY_SUCCESS_CODE', 'id' => $groupOrder->group_order_id]); + Queue::push(UserBrokerageLevelJob::class, ['uid' => $groupOrder->uid, 'type' => 'pay_money', 'inc' => $groupOrder->pay_price]); + Queue::push(UserBrokerageLevelJob::class, ['uid' => $groupOrder->uid, 'type' => 'pay_num', 'inc' => 1]); + app()->make(UserBrokerageRepository::class)->incMemberValue($groupOrder->uid, 'member_pay_num', $groupOrder->group_order_id); + event('order.paySuccess', compact('groupOrder')); + event('data.screen.send', []); + } + + /** + * TODO 自动发货卡密商品 + * @param $order + * @return mixed|string + * @author Qinii + * @day 2023/5/4 + */ + public function sendCdkey($order) + { + $productAttrValueRepository = app()->make(SupplyProductAttrValueRepository::class); + if (isset($order->orderProduct[0]['cart_info']['productAttr']['value_id'])){ + $where['value_id'] = $order->orderProduct[0]['cart_info']['productAttr']['value_id']; + } else { + $where['unique'] = $order->orderProduct[0]['cart_info']['productAttr']['unique']; + } + $rest = $productAttrValueRepository->getWhere($where,'*',['productCdkey' => function($query) {$query->where('status',1)->order('cdkey_id ASC')->withLimit(1);}]); + $cdkey = $rest['productCdkey'][0]; + if ($cdkey['is_type']) { + $msg = '卡号:'.$cdkey['key']; + if ($cdkey['pwd']) $msg .= ';卡密:'.$cdkey['pwd']; + $cdkey->status = -1; + $cdkey->save(); + } else { + $msg = $cdkey['key']; + } + return $msg; + } + + /** + * 自动打印 + * @Author:Qinii + * @Date: 2020/10/13 + * @param int $orderId + * @param int $merId + */ + public function autoPrinter(int $orderId, int $merId) + { + if (merchantConfig($merId, 'printing_auto_status')) { + try { + $this->batchPrinter($orderId, $merId); + } catch (Exception $exception) { + Log::info('自动打印小票报错:' . $exception); + } + } else { + Log::info('自动打印小票验证:商户ID【' . $merId . '】,自动打印状态未开启'); + } + } + + /** + * @return string + * @author xaboy + * @day 2020/6/9 + */ + public function getNewOrderId($type) + { + list($msec, $sec) = explode(' ', microtime()); + $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', ''); + $orderId = $type . $msectime . mt_rand(10000, max(intval($msec * 10000) + 10000, 98369)); + return $orderId; + } + + /** + * @param $cart + * @return string + * @author xaboy + * @day 2020/6/9 + */ + public function productByTempNumber($cart) + { + $type = $cart['product']['temp']['type']; + $cartNum = $cart['cart_num']; + if (!$type) + return $cartNum; + else if ($type == 2) { + return bcmul($cartNum, $cart['productAttr']['volume'], 2); + } else { + return bcmul($cartNum, $cart['productAttr']['weight'], 2); + } + } + + public function cartByPrice($cart) + { + if ($cart['product_type'] == '2') { + return $cart['productPresellAttr']['presell_price']; + } else if ($cart['product_type'] == '3') { + return $cart['productAssistAttr']['assist_price']; + } else if ($cart['product_type'] == '4') { + return $cart['activeSku']['active_price']; + } else { + return $cart['productAttr']['price']; + } + } + + public function cartByCouponPrice($cart) + { + if ($cart['product_type'] == '2') { + return $cart['productPresellAttr']['final_price']; + } else if ($cart['product_type'] == '1') { + return 0; + } else if ($cart['product_type'] == '3') { + return 0; + } else if ($cart['product_type'] == '4') { + return 0; + } else { + return $cart['productAttr']['price']; + } + } + + public function cartByDownPrice($cart) + { + if ($cart['product_type'] == '2') { + return $cart['productPresellAttr']['down_price']; + } else { + return 0; + } + } + + + /** + * @param int $uid + * @return array + * @author xaboy + * @day 2020/6/10 + */ + public function userOrderNumber(int $uid) + { + $noPay = app()->make(StoreGroupOrderRepository::class)->orderNumber($uid); + $noPostage = $this->dao->search(['uid' => $uid, 'status' => 0, 'paid' => 1,'is_user' => 1])->where('SupplyStoreOrder.is_del', 0)->count(); + $all = $this->dao->search(['uid' => $uid, 'status' => -2,'is_user' => 1])->where('SupplyStoreOrder.is_del', 0)->count(); + $noDeliver = $this->dao->search(['uid' => $uid, 'status' => 1, 'paid' => 1])->where('SupplyStoreOrder.is_del', 0)->count(); + $noComment = $this->dao->search(['uid' => $uid, 'status' => 2, 'paid' => 1,'is_user' => 1])->where('SupplyStoreOrder.is_del', 0)->count(); + $done = $this->dao->search(['uid' => $uid, 'status' => 3, 'paid' => 1,'is_user' => 1])->where('SupplyStoreOrder.is_del', 0)->count(); + $refund = app()->make(StoreRefundOrderRepository::class)->getWhereCount(['uid' => $uid, 'status' => [0, 1, 2]]); + //$orderPrice = $this->dao->search(['uid' => $uid, 'paid' => 1])->sum('pay_price'); + $orderCount = $this->dao->search(['uid' => $uid, 'paid' => 1,'is_user' => 1])->count(); + return compact('noComment', 'done', 'refund', 'noDeliver', 'noPay', 'noPostage', 'orderCount', 'all'); + } + + /** + * @param $id + * @param null $uid + * @return array|Model|null + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author xaboy + * @day 2020/6/10 + */ + public function getDetail($id, $uid = null) + { + $where = []; + $with = [ + 'orderProduct', + 'merchant' => function ($query) { + return $query->field('mer_id,mer_name,service_phone')->append(['services_type']); + }, + 'receipt' => function ($query) { + return $query->field('order_id,order_receipt_id'); + }, + 'takeOrderList.orderProduct' + ]; + if ($uid) { + $where['uid'] = $uid; + } else if (!$uid) { + $with['user'] = function ($query) { + return $query->field('uid,nickname'); + }; + } + $order = $this->dao->search($where)->where('order_id', $id)->where('SupplyStoreOrder.is_del', 0)->with($with)->append(['refund_status','open_receipt'])->find(); + if (!$order) { + return null; + } + if ($order->activity_type == 2) { + if ($order->presellOrder) { + $order->presellOrder->append(['activeStatus']); + $order->presell_price = bcadd($order->pay_price, $order->presellOrder->pay_price, 2); + } else { + $order->presell_price = $order->pay_price; + } + } + return $order; + } + + public function codeByDetail($code, $uid = null) + { + $where = []; + if ($uid) $where['uid'] = $uid; + $data = $this->dao->search($where)->where('verify_code', $code) + ->where('SupplyStoreOrder.is_del', 0) + ->with([ + 'orderProduct', + 'merchant' => function ($query) { + return $query->field('mer_id,mer_name'); + } + ]) + ->find(); + if (!$data) + throw new ValidateException('数据不存在'); + if ($data['status']) + throw new ValidateException('该订单已全部核销'); + return $data; + } + + public function giveIntegral($groupOrder) + { + if ($groupOrder->give_integral > 0) { + app()->make(UserBillRepository::class)->incBill($groupOrder->uid, 'integral', 'lock', [ + 'link_id' => $groupOrder['group_order_id'], + 'status' => 0, + 'title' => '下单赠送积分', + 'number' => $groupOrder->give_integral, + 'mark' => '成功消费' . floatval($groupOrder['pay_price']) . '元,赠送积分' . floatval($groupOrder->give_integral), + 'balance' => $groupOrder->user->integral + ]); + } + } + + /** + * @param SupplyStoreOrder $order + * @param User $user + * @author xaboy + * @day 2020/8/3 + */ + public function computed(SupplyStoreOrder $order, User $user) + { + $userBillRepository = app()->make(UserBillRepository::class); + if ($order->spread_uid) { + $spreadUid = $order->spread_uid; + $topUid = $order->top_uid; + } else if ($order->is_selfbuy) { + $spreadUid = $user->uid; + $topUid = $user->spread_uid; + } else { + $spreadUid = $user->spread_uid; + $topUid = $user->top_uid; + } + //TODO 添加冻结佣金 + if ($order->extension_one > 0 && $spreadUid) { + $userBillRepository->incBill($spreadUid, 'brokerage', 'order_one', [ + 'link_id' => $order['order_id'], + 'status' => 0, + 'title' => '获得推广佣金', + 'number' => $order->extension_one, + 'mark' => $user['nickname'] . '成功消费' . floatval($order['pay_price']) . '元,奖励推广佣金' . floatval($order->extension_one), + 'balance' => 0 + ]); + $userRepository = app()->make(UserRepository::class); + $userRepository->incBrokerage($spreadUid, $order->extension_one); + // app()->make(FinancialRecordRepository::class)->dec([ + // 'order_id' => $order->order_id, + // 'order_sn' => $order->order_sn, + // 'user_info' => $userRepository->getUsername($spreadUid), + // 'user_id' => $spreadUid, + // 'financial_type' => 'brokerage_one', + // 'number' => $order->extension_one, + // ], $order->mer_id); + } + if ($order->extension_two > 0 && $topUid) { + $userBillRepository->incBill($topUid, 'brokerage', 'order_two', [ + 'link_id' => $order['order_id'], + 'status' => 0, + 'title' => '获得推广佣金', + 'number' => $order->extension_two, + 'mark' => $user['nickname'] . '成功消费' . floatval($order['pay_price']) . '元,奖励推广佣金' . floatval($order->extension_two), + 'balance' => 0 + ]); + $userRepository = app()->make(UserRepository::class); + $userRepository->incBrokerage($topUid, $order->extension_two); + // app()->make(FinancialRecordRepository::class)->dec([ + // 'order_id' => $order->order_id, + // 'order_sn' => $order->order_sn, + // 'user_info' => $userRepository->getUsername($topUid), + // 'user_id' => $topUid, + // 'financial_type' => 'brokerage_two', + // 'number' => $order->extension_two, + // ], $order->mer_id); + } + } + + /** + * @param SupplyStoreOrder $order + * @param User $user + * @param string $type + * @author xaboy + * @day 2020/8/3 + */ + public function takeAfter(SupplyStoreOrder $order, ?User $user) + { + Db::transaction(function () use ($user, $order) { + if ($user) $this->computed($order, $user); + Queue::push(SendSmsJob::class, ['tempId' => 'ORDER_TAKE_SUCCESS', 'id' => $order->order_id]); + Queue::push(SendSmsJob::class, ['tempId' => 'ADMIN_TAKE_DELIVERY_CODE', 'id' => $order->order_id]); + app()->make(SupplyRepository::class)->computedLockMoney($order); + $order->save(); + }); + } + + /** + * @param $id + * @param User $user + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author xaboy + * @day 2020/6/17 + */ + public function takeOrder($id, ?User $user = null) + { + $order = $this->dao->searchAll(!$user ? [] : ['uid' => $user->uid])->where('order_id', $id)->where('SupplyStoreOrder.is_del', '<>',1)->find(); + if (!$order) + throw new ValidateException('订单不存在'); + if ($order['status'] != 1 || ($order['order_type'] && $order['order_type'] != 20)) + throw new ValidateException('订单状态有误'); + $func = 'createUserLog'; + if (!$user){ + $func = 'createSysLog'; + $user = $order->user; + } +// if (!$user) { +// throw new ValidateException('用户不存在'); +// } + //订单状态(0:待发货;1:待收货;2:待评价;3:已完成; 9: 拼团中 10: 待付尾款 11:尾款超时未付 -1:已退款) + $order->status = $order->activity_type == 20 ? 3 : 2; + $order->verify_time = date('Y-m-d H:i:s'); + event('order.take.before', compact('order')); + //订单记录 + $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $storeOrderStatusRepository::TYPE_ORDER, + 'change_message' => '已收货', + 'change_type' => $storeOrderStatusRepository::ORDER_STATUS_TAKE, + ]; + Db::transaction(function () use ($order, $user,$storeOrderStatusRepository,$orderStatus,$func) { + $this->takeAfter($order, $user); + $order->save(); + $storeOrderStatusRepository->{$func}($orderStatus); + }); + event('order.take', compact('order')); + } + + + /** + * 获取订单列表头部统计数据 + * @Author:Qinii + * @Date: 2020/9/12 + * @param int|null $merId + * @param int|null $orderType + * @return array + */ + public function OrderTitleNumber(?int $merId, ?int $orderType) + { + $where = []; + $sysDel = $merId ? 0 : null; //商户删除 + if ($merId) $where['mer_id'] = $merId; //商户订单 + if ($orderType === 0) $where['order_type'] = 0; //普通订单 + if ($orderType === 1) $where['take_order'] = 1; //已核销订单 + if ($orderType === 2) $where['is_spread'] = 1; //分销订单 + //1: 未支付 2: 未发货 3: 待收货 4: 待评价 5: 交易完成 6: 已退款 7: 已删除 + $all = $this->dao->search($where, $sysDel)->where($this->getOrderType(0))->count(); + $statusAll = $all; + $unpaid = $this->dao->search($where, $sysDel)->where($this->getOrderType(1))->count(); + $unshipped = $this->dao->search($where, $sysDel)->where($this->getOrderType(2))->count(); + $untake = $this->dao->search($where, $sysDel)->where($this->getOrderType(3))->count(); + $unevaluate = $this->dao->search($where, $sysDel)->where($this->getOrderType(4))->count(); + $complete = $this->dao->search($where, $sysDel)->where($this->getOrderType(5))->count(); + $refund = $this->dao->search($where, $sysDel)->where($this->getOrderType(6))->count(); + $del = $this->dao->search($where, $sysDel)->where($this->getOrderType(7))->count(); + + return compact('all', 'statusAll', 'unpaid', 'unshipped', 'untake', 'unevaluate', 'complete', 'refund', 'del'); + } + + public function orderType(array $where) + { + return [ + [ + 'count' => $this->dao->search($where)->count(), + 'title' => '全部', + 'order_type' => -1, + ], + [ + 'count' => $this->dao->search($where)->where('order_type', 0)->where('is_virtual', 0)->count(), + 'title' => '普通订单', + 'order_type' => 0, + ], + [ + 'count' => $this->dao->search($where)->where('order_type', 1)->count(), + 'title' => '核销订单', + 'order_type' => 1, + ], + [ + 'count' => $this->dao->search($where)->where('is_virtual', 1)->count(), + 'title' => '虚拟商品订单', + 'order_type' => 2, + ], + [ + 'count' => $this->dao->search(array_merge($where,['order_type' => 3]))->count(), + 'title' => '卡密商品订单', + 'order_type' => 3, + ], + ]; + } + + /** + * @param $status + * @return mixed + * @author Qinii + */ + public function getOrderType($status) + { + $param['SupplyStoreOrder.is_del'] = 0; + switch ($status) { + case 1: + $param['SupplyStoreOrder.paid'] = 0; + break; // 未支付 + case 2: + $param['SupplyStoreOrder.paid'] = 1; + $param['SupplyStoreOrder.status'] = 0; + break; // 待发货 + case 3: + $param['SupplyStoreOrder.status'] = 1; + break; // 待收货 + case 4: + $param['SupplyStoreOrder.status'] = 2; + break; // 待评价 + case 5: + $param['SupplyStoreOrder.status'] = 3; + break; // 交易完成 + case 6: + $param['SupplyStoreOrder.status'] = -1; + break; // 已退款 + case 7: + $param['SupplyStoreOrder.is_del'] = 1; + break; // 待核销 + default: + unset($param['SupplyStoreOrder.is_del']); + break; //全部 + } + return $param; + } + + /** + * @param int $id + * @param int|null $merId + * @return array|Model|null + * @author Qinii + */ + public function merDeliveryExists(int $id, ?int $merId, ?int $re = 0) + { + $where = ['order_id' => $id, 'is_del' => 0, 'paid' => 1]; + if ($re) $where['status'] = 0; + if ($merId) $where['mer_id'] = $merId; + return $this->dao->merFieldExists($where); + } + + /** + * TODO + * @param int $id + * @param int|null $merId + * @return bool + * @author Qinii + * @day 2020-06-11 + */ + public function merGetDeliveryExists(int $id, ?int $merId) + { + $where = ['order_id' => $id, 'is_del' => 0, 'paid' => 1, 'status' => 1]; + if ($merId) $where['mer_id'] = $merId; + return $this->dao->merFieldExists($where); + } + + /** + * @param int $id + * @param int|null $merId + * @return array|Model|null + * @author Qinii + */ + public function merStatusExists(int $id, ?int $merId) + { + $where = ['order_id' => $id, 'is_del' => 0, 'paid' => 0, 'status' => 0]; + if ($merId) $where['mer_id'] = $merId; + return $this->dao->merFieldExists($where); + } + + public function userDelExists(int $id, ?int $merId) + { + $where = ['order_id' => $id, 'is_del' => 1]; + if ($merId) $where['mer_id'] = $merId; + return $this->dao->merFieldExists($where); + } + + /** + * @param $id + * @return Form + * @author Qinii + */ + public function form($id) + { + $data = $this->dao->getWhere([$this->dao->getPk() => $id], 'total_price,pay_price,total_postage,pay_postage'); + $form = Elm::createForm(Route::buildUrl('merchantStoreOrderUpdate', ['id' => $id])->build()); + $form->setRule([ + Elm::number('total_price', '订单总价:', $data['total_price'])->required(), + Elm::number('total_postage', '订单邮费:', $data['total_postage'])->required(), + Elm::number('pay_price', '实际支付金额:', $data['pay_price'])->required(), + ]); + return $form->setTitle('修改订单'); + } + + /** + * TODO 修改订单价格 + * @param int $id + * @param array $data + * @author Qinii + * @day 12/15/20 + */ + public function eidt(int $id, array $data, $service_id = 0) + { + + /** + * 1 计算出新的实际支付价格 + * 1.1 计算邮费 + * 1.2 计算商品总价 + * 2 修改订单信息 + * 3 计算总单数据 + * 4 修改总单数据 + * 5 修改订单商品单价 + * + * pay_price = total_price - coupon_price + pay_postage + */ + $order = $this->dao->get($id); + if ($order->activity_type == 2) { + throw new ValidateException('预售订单不支持改价'); + } + $extension_total = (float)bcadd($order->extension_one, $order->extension_two, 2); + $data['pay_price'] = $this->bcmathPrice($data['total_price'], $order['coupon_price'], $data['pay_postage']); + if ($data['pay_price'] < 0) { + throw new ValidateException('实际支付金额不能小于0'); + } else if ($data['pay_price'] < $extension_total) { + throw new ValidateException('实际支付金额不能小于佣金' . $extension_total); + } + $make = app()->make(StoreGroupOrderRepository::class); + $orderGroup = $make->dao->getWhere(['group_order_id' => $order['group_order_id']]); + + //总单总价格 + $_group['total_price'] = $this->bcmathPrice($orderGroup['total_price'], $order['total_price'], $data['total_price']); + //总单实际支付价格 + $_group['pay_price'] = $this->bcmathPrice($orderGroup['pay_price'], $order['pay_price'], $data['pay_price']); + //总单实际支付邮费 + $_group['pay_postage'] = $this->bcmathPrice($orderGroup['pay_postage'], $order['pay_postage'], $data['pay_postage']); + event('order.changePrice.before', compact('order', 'data')); + //订单记录 + $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $storeOrderStatusRepository::TYPE_ORDER, + 'change_message' => '订单价格:'.$order['pay_price'].'修改为:'.$data['pay_price'], + 'change_type' => $storeOrderStatusRepository::ORDER_STATUS_CHANGE, + ]; + + Db::transaction(function () use ($id, $data, $orderGroup, $order, $_group,$storeOrderStatusRepository,$orderStatus,$service_id) { + $orderGroup->total_price = $_group['total_price']; + $orderGroup->pay_price = $_group['pay_price']; + $orderGroup->pay_postage = $_group['pay_postage']; + $orderGroup->group_order_sn = $this->getNewOrderId(SupplyStoreOrderRepository::TYPE_SN_ORDER) . '0'; + $orderGroup->save(); + + $this->dao->update($id, $data); + $this->changOrderProduct($id, $data); + + if ($service_id) { + $storeOrderStatusRepository->createServiceLog($service_id,$orderStatus); + } else { + $storeOrderStatusRepository->createAdminLog($orderStatus); + } + if ($data['pay_price'] != $order['pay_price']) Queue::push(SendSmsJob::class, ['tempId' => 'PRICE_REVISION_CODE', 'id' => $id]); + }); + event('order.changePrice', compact('order', 'data')); + } + + /** + * TODO 改价后重新计算每个商品的单价 + * @param int $orderId + * @param array $data + * @author Qinii + * @day 12/15/20 + */ + public function changOrderProduct(int $orderId, array $data) + { + $make = app()->make(StoreOrderSupplyProductRepository::class); + $ret = $make->getSearch(['order_id' => $orderId])->field('order_product_id,product_num,product_price')->select(); + $count = $make->getSearch(['order_id' => $orderId])->sum('product_price'); + $_count = (count($ret->toArray()) - 1); + $pay_price = $data['total_price']; + foreach ($ret as $k => $item) { + $_price = 0; + /** + * 比例 = 单个商品总价 / 订单原总价; + * + * 新的商品总价 = 比例 * 订单修改总价 + * + * 更新数据库 + */ + if ($k == $_count) { + $_price = $pay_price; + } else { + $_reta = bcdiv($item->product_price, $count, 3); + $_price = bcmul($_reta, $data['total_price'], 2); + } + + $item->product_price = $_price; + $item->save(); + + $pay_price = $this->bcmathPrice($pay_price, $_price, 0); + } + } + + /** + * TODO 计算的重复利用 + * @param $total + * @param $old + * @param $new + * @return int|string + * @author Qinii + * @day 12/15/20 + */ + public function bcmathPrice($total, $old, $new) + { + $_bcsub = bcsub($total, $old, 2); + $_count = (bccomp($_bcsub, 0, 2) == -1) ? 0 : $_bcsub; + $count = bcadd($_count, $new, 2); + return (bccomp($count, 0, 2) == -1) ? 0 : $count; + } + + /** + * @param $id + * @param $uid + * @return mixed + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author xaboy + * @day 2020/6/12 + */ + public function refundProduct($id, $uid) + { + $order = $this->dao->userOrder($id, $uid); + if (!$order) + throw new ValidateException('订单不存在'); + // 查找可退款商品 + $orderProduct = app()->make(StoreOrderSupplyProductRepository::class); + $orderList = $orderProduct->getSearch(['order_id' => $order['order_id'], 'refund_num' => 0, 'refund_switch' => 1])->select(); + if (!count($orderList)) + throw new ValidateException('没有可退款商品'); + return $orderList->toArray(); + } + + /** + * TODO + * @param $id + * @param $data + * @return mixed + * @author Qinii + * @day 7/26/21 + */ + public function orderDumpInfo($id, $data, $merId) + { + + if (!$data['temp_id']) + throw new ValidateException('请填写模板ID'); + if (!$data['from_name']) + throw new ValidateException('请填写发货人姓名'); + if (!$data['from_tel']) + throw new ValidateException('请填写发货电话'); + if (!$data['from_addr']) + throw new ValidateException('请填写发货地址'); + $orderInfo = $this->dao->getWhere(['order_id' => $id]); + if ($orderInfo['is_virtual']) + throw new ValidateException('虚拟商品只能虚拟发货'); + $cargo = ''; + $count = 0; + $weight = 0; + foreach ($orderInfo->orderProduct as $item) { + $cargo .= mb_substr($item['cart_info']['product']['store_name'],0,10). ' ' .$item['cart_info']['productAttr']['sku'] .' * ' .$item['product_num'].$item['cart_info']['product']['unit_name'].PHP_EOL; + $count += $item['product_num']; + $weight += $item['cart_info']['productAttr']['weight']; + } + $expData['com'] = $data['com']; + $expData['to_name'] = $orderInfo->real_name; + $expData['to_tel'] = $orderInfo->user_phone; + $expData['to_addr'] = $orderInfo->user_address; + $expData['from_name'] = $data['from_name']; + $expData['from_tel'] = $data['from_tel']; + $expData['from_addr'] = $data['from_addr']; + $expData['siid'] = merchantConfig($merId,'mer_config_siid'); + $expData['temp_id'] = $data['temp_id']; + $expData['count'] = $count; + $expData['weight'] = $weight; + $expData['cargo'] = $cargo; + $expData['order_id'] = $orderInfo->order_id; + return $expData; + } + + /** + * TODO 批量发货 + * @param int $merId + * @param array $params + * @author Qinii + * @day 7/26/21 + */ + public function batchDelivery(int $merId, array $params) + { + $import = app()->make(StoreImportRepository::class)->create($merId, 'delivery', $params['delivery_type']); + $make = app()->make(StoreImportDeliveryRepository::class); + $data = []; + $num = 0; + if ($params['select_type'] == 'all') { + $where = $params['where']; + $status = $where['status']; + unset($where['status']); + $where['mer_id'] = $merId; + $params['order_id'] = $this->dao->search($where)->where($this->getOrderType($status))->column('order_id'); + } + $count = count($params['order_id']); + + foreach ($params['order_id'] as $item) { + $ret = $this->dao->getWhere(['order_id' => $params['order_id']]); + $imp = [ + 'order_sn' => $ret['order_sn'] ?? $item, + 'delivery_id' => $params['delivery_id'], + 'delivery_type' => $params['delivery_type'], + 'delivery_name' => $params['delivery_name'], + 'import_id' => $import['import_id'], + 'mer_id' => $merId + ]; + if (!$ret || $ret['mer_id'] != $merId || $ret['is_del'] != 0 || $ret['paid'] != 1 || $ret['delivery_type'] || $ret['order_type'] == 1) { + $imp['status'] = 0; + $imp['mark'] = '订单信息不存在或状态错误'; + } else { + try { + if ($params['delivery_type'] == 4) { + $dump = [ + 'temp_id' => $params['temp_id'], + 'from_tel' => $params['from_tel'], + 'from_addr' => $params['from_addr'], + 'from_name' => $params['from_name'], + 'delivery_name' => $params['delivery_name'], + ]; + $dump = $this->orderDumpInfo($item, $dump, $merId); + $ret = $this->dump($item, $merId, $dump); + $imp['delivery_id'] = $ret['delivery_id']; + $imp['delivery_name'] = $ret['delivery_name']; + } else { + $this->delivery($item, $merId,[ + 'delivery_id' => $params['delivery_id'], + 'delivery_type' => $params['delivery_type'], + 'delivery_name' => $params['delivery_name'], + ]); + } + $num++; + $imp['status'] = 1; + } catch (Exception $exception) { + $imp['status'] = 0; + $imp['mark'] = $exception->getMessage(); + } + } + $data[] = $imp; + } + + $_status = ($num == 0) ? -1 : (($count == $num) ? 1 : 10); + $make->insertAll($data); + $arr = ['count' => $count, 'success' => $num, 'status' => $_status]; + app()->make(StoreImportRepository::class)->update($import['import_id'], $arr); + } + + + /** + * TODO 打印电子面单,组合参数 + * @param int $id + * @param int $merId + * @param array $data + * @return mixed + * @author Qinii + * @day 7/26/21 + */ + public function dump(int $id, int $merId, array $data, $service_id = 0) + { + $make = app()->make(SupplyRepository::class); + $make->checkCrmebNum($merId, 'dump'); + $data['com'] = $data['delivery_name']; + $data = $this->orderDumpInfo($id, $data, $merId); + $result = app()->make(CrmebServeServices::class)->express()->dump($merId, $data); + if (!isset($result['kuaidinum'])) throw new ValidateException('打印失败'); + $delivery = [ + 'delivery_type' => 4, + 'delivery_name' => $data['com'], + 'delivery_id' => $result['kuaidinum'], + 'remark' => $data['remark'] ?? '', + 'kuaidi_label' => $result['label'] ?? '', + ]; + $dump = [ + 'delivery_name' => $delivery['delivery_name'], + 'delivery_id' => $delivery['delivery_id'], + 'from_name' => $data['from_name'], + 'order_id' => $data['order_id'], + 'to_name' => $data['to_name'], + ]; + Db::transaction(function () use ($merId, $id, $delivery, $make, $dump, $service_id) { + $this->delivery($id, $merId, $delivery,$service_id); + // $arr = [ + // 'type' => 'mer_dump', + // 'num' => -1, + // 'message' => '电子面单', + // 'info' => $dump + // ]; + // app()->make(ProductCopyRepository::class)->add($arr, $merId); + }); + return $result; + } + + public function runDelivery($id, $merId, $data, $split, $method,$service_id = 0) + { + return Db::transaction(function () use ($id, $merId, $data, $split, $method,$service_id) { + if ($split['is_split'] && !empty($split['split'])) { + foreach ($split['split'] as $v) { + $splitData[$v['id']] = $v['num']; + } + $order = $this->dao->get($id); + $newOrder = app()->make(StoreOrderSplitRepository::class)->splitOrder($order, $splitData,$service_id); + if ($newOrder){ + $id = $newOrder->order_id; + } else { + throw new ValidateException('商品不能全部拆单'); + } + } + return $this->{$method}($id, $merId, $data, $service_id); + }); + } + + /** + * TODO 发货订单操作 + * @param $id + * @param $data + * @return mixed + * @author Qinii + * @day 7/26/21 + */ + public function delivery($id, $merId, $data, $service_id = 0) + { + $data['status'] = 1; + $order = $this->dao->get($id); + if ($order['is_virtual'] == 1 && $data['delivery_type'] != 3) + throw new ValidateException('虚拟商品只能虚拟发货'); + //订单记录 + /** @var StoreOrderStatusRepository $statusRepository */ + $statusRepository = app()->make(StoreOrderStatusRepository::class); + switch ($data['delivery_type']) { + // case 1: + // $exprss = app()->make(ExpressRepository::class)->getWhere(['code' => $data['delivery_name']]); + // if (!$exprss) throw new ValidateException('快递公司不存在'); + // $data['delivery_name'] = $exprss['name']; + // $change_type = $statusRepository::ORDER_DELIVERY_COURIER; + // $change_message = '订单已配送【快递名称】:' . $exprss['name'] . '; 【快递单号】:' . $data['delivery_id']; + // $temp_code = 'DELIVER_GOODS_CODE'; + // break; + case 2: + if (!preg_match("/^1[3456789]{1}\d{9}$/", $data['delivery_id'])) throw new ValidateException('手机号格式错误'); + $change_type = 'delivery_1'; + $change_message = '订单已配送【送货人姓名】:' . $data['delivery_name'] . '; 【手机号】:' . $data['delivery_id']; + $temp_code = 'ORDER_DELIVER_SUCCESS'; + break; + case 3: + $change_type = $statusRepository::ORDER_DELIVERY_NOTHING; + $change_message = '订单已配送【虚拟发货】'; + $data['status'] = 2; + break; + // case 4: + // $exprss = app()->make(ExpressRepository::class)->getWhere(['code' => $data['delivery_name']]); + // if (!$exprss) throw new ValidateException('快递公司不存在'); + // $data['delivery_name'] = $exprss['name']; + // $change_type = $statusRepository::ORDER_DELIVERY_COURIER; + // $change_message = '订单已配送【快递名称】:' . $exprss['name'] . '; 【快递单号】:' . $data['delivery_id']; + // $temp_code = 'DELIVER_GOODS_CODE'; + // break; + } + + event('order.delivery.before', compact('order', 'data')); + $this->dao->update($id, $data); + + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $statusRepository::TYPE_ORDER, + 'change_message' => $change_message, + 'change_type' => $change_type, + ]; + if ($service_id) { + $statusRepository->createServiceLog($service_id,$orderStatus); + } else { + $statusRepository->createAdminLog($orderStatus); + } + + //虚拟发货后用户直接确认收获 + if($data['status'] == 2){ + $user = app()->make(UserRepository::class)->get($order['uid']); + //订单记录 + $this->takeAfter($order,$user); + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $statusRepository::TYPE_ORDER, + 'change_message' => '虚拟发货后', + 'change_type' => $statusRepository::ORDER_STATUS_TAKE, + ]; + $statusRepository->createSysLog($orderStatus); + + } + if (isset($temp_code)) Queue::push(SendSmsJob::class, ['tempId' => $temp_code, 'id' => $order->order_id]); + + // 小程序发货管理 + event('mini_order_shipping', ['product', $order, $data['delivery_type'], $data['delivery_id'], $data['delivery_name']]); + + event('order.delivery', compact('order', 'data')); + return $data; + } + + /** + * TODO 同城配送 + * @param int $id + * @param int $merId + * @param array $data + * @author Qinii + * @day 2/16/22 + */ + public function cityDelivery(int $id, int $merId, array $data, $service_id) + { + // $make = app()->make(DeliveryOrderRepository::class); + // $order = $this->dao->get($id); + // if ($order['is_virtual']) + // throw new ValidateException('虚拟商品只能虚拟发货'); + // $make->create($id, $merId, $data, $order); + // //订单记录 + // $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + // $this->dao->update($id, ['delivery_type' => 5, 'status' => 1,'remark' => $data['remark']]); + + // $orderStatus = [ + // 'order_id' => $id, + // 'order_sn' => $order->order_sn, + // 'type' => $storeOrderStatusRepository::TYPE_ORDER, + // 'change_message' => '订单配送【同城配送】', + // 'change_type' => $storeOrderStatusRepository::ORDER_DELIVERY_SELF, + // ]; + // if ($service_id) { + // $storeOrderStatusRepository->createServiceLog($service_id,$orderStatus); + // } else { + // $storeOrderStatusRepository->createAdminLog($orderStatus); + // } + + // // 小程序发货管理 + // event('mini_order_shipping', ['product', $order, 5, '', '']); + + // Queue::push(SendSmsJob::class, ['tempId' => 'ORDER_DELIVER_SUCCESS', 'id' => $id]); + } + + + public function getOne($id, ?int $merId) + { + $where = [$this->getPk() => $id]; + if ($merId) { + $where['mer_id'] = $merId; + $where['is_system_del'] = 0; + } + $res = $this->dao->getWhere($where, '*', [ + 'orderProduct', + 'user' => function ($query) { + $query->field('uid,real_name,nickname,is_svip,svip_endtime,phone'); + }, + 'refundOrder' => function ($query) { + $query->field('order_id,extension_one,extension_two,refund_price,integral')->where('status', 3); + }, + 'finalOrder', + 'TopSpread' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + 'spread' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + 'merchant' => function (Relation $query) { + $query->field('mer_id,mer_name,mer_state,mer_avatar,delivery_way,commission_rate,category_id,type_id') + ->with(['merchantCategory','type_name']); + } + ] + ); + if (!$res) throw new ValidateException('数据不存在'); + $res['integral'] = (int)$res['integral']; + return $res->append(['refund_extension_one', 'refund_extension_two']); + } + + public function getOrderStatus($where, $page, $limit) + { + $where['type'] = StoreOrderStatusRepository::TYPE_ORDER; + return app()->make(StoreOrderStatusRepository::class)->search($where, $page, $limit); + } + + public function remarkForm($id) + { + $data = $this->dao->get($id); + $form = Elm::createForm(Route::buildUrl('merchantStoreOrderRemark', ['id' => $id])->build()); + $form->setRule([ + Elm::text('remark', '备注:', $data['remark'])->placeholder('请输入备注')->required(), + ]); + return $form->setTitle('订单备注'); + } + + public function adminMarkForm($id) + { + $data = $this->dao->get($id); + $form = Elm::createForm(Route::buildUrl('systemMerchantOrderMark', ['id' => $id])->build()); + $form->setRule([ + Elm::text('admin_mark', '备注:', $data['admin_mark'])->placeholder('请输入备注')->required(), + ]); + return $form->setTitle('订单备注'); + } + + public function pointsMarkForm($id) + { + $data = $this->dao->get($id); + $form = Elm::createForm(Route::buildUrl('pointsOrderMark', ['id' => $id])->build()); + $form->setRule([ + Elm::text('remark', '备注:', $data['remark'])->placeholder('请输入备注')->required(), + ]); + return $form->setTitle('订单备注'); + } + + + /** + * TODO 平台每个商户的订单列表 + * @param $where + * @param $page + * @param $limit + * @return array + * @author Qinii + * @day 2020-06-15 + */ + public function adminMerGetList($where, $page, $limit) + { + $where['paid'] = 1; + $query = $this->dao->search($where, null); + $count = $query->count(); + $list = $query->with([ + 'orderProduct', + 'merchant' => function ($query) { + $query->field('mer_id,mer_name,is_trader'); + }, + 'groupOrder' => function ($query) { + $query->field('group_order_id,group_order_sn'); + }, + 'finalOrder', + 'user' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + ])->page($page, $limit)->select()->append(['refund_extension_one', 'refund_extension_two']); + + return compact('count', 'list'); + } + + public function reconList($where, $page, $limit) + { + $ids = app()->make(MerchantReconciliationOrderRepository::class)->getIds($where); + $query = $this->dao->search([], null)->whereIn('order_id', $ids); + $count = $query->count(); + $list = $query->with(['orderProduct'])->page($page, $limit)->select()->each(function ($item) { + //(实付金额 - 一级佣金 - 二级佣金) * 抽成 + $commission_rate = ($item['commission_rate'] / 100); + //佣金 + $_order_extension = bcadd($item['extension_one'], $item['extension_two'], 3); + //手续费 = (实付金额 - 一级佣金 - 二级佣金) * 比例 + $_order_rate = bcmul(bcsub($item['pay_price'], $_order_extension, 3), $commission_rate, 3); + $item['order_extension'] = round($_order_extension, 2); + $item['order_rate'] = round($_order_rate, 2); + return $item; + }); + + return compact('count', 'list'); + } + + /** + * @param array $where + * @param $page + * @param $limit + * @return array + * @author Qinii + */ + public function merchantGetList(array $where, $page, $limit) + { + $status = $where['status']; + unset($where['status']); + $query = $this->dao->search($where)->where($this->getOrderType($status)) + ->with([ + 'orderProduct', + 'merchant' => function ($query) { + $query->field('mer_id,mer_name'); + }, + 'verifyService' => function ($query) { + $query->field('service_id,nickname'); + }, + 'finalOrder', + 'groupUser.groupBuying', + 'TopSpread' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + 'spread' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + ]); + $count = $query->count(); + $list = $query->page($page, $limit)->select()->append(['refund_extension_one', 'refund_extension_two']) + ->each(function($item){ + // 1:退款中 2:部分退款 3 = 全退 + $refunding = 0; + if ($item['orderProduct']) { + $is_refund = array_unique(array_column($item['orderProduct']->toArray(),'is_refund')); + if (count($is_refund) == 1) { + if (in_array(3,$is_refund)) $refunding = 3; + } else { + if (in_array(1,$is_refund)) { + $refunding = 1; + } else { + $refunding = 2; + } + } + } + $item['refunding'] = $refunding; + }); + + + return compact('count', 'list'); + } + + /** + * TODO 平台总的订单列表 + * @param array $where + * @param $page + * @param $limit + * @return array + * @author Qinii + * @day 2020-06-15 + */ + public function adminGetList(array $where, $page, $limit) + { + $status = $where['status']; + unset($where['status']); + $query = $this->dao->search($where, null)->where($this->getOrderType($status)) + ->with([ + 'orderProduct', + 'merchant' => function ($query) { + return $query->field('mer_id,mer_name,is_trader'); + }, + 'verifyService' => function ($query) { + return $query->field('service_id,nickname'); + }, + 'groupOrder' => function ($query) { + $query->field('group_order_id,group_order_sn'); + }, + 'finalOrder', + 'groupUser.groupBuying', + 'TopSpread' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + 'spread' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + 'user' => function ($query) { + $query->field('uid,nickname,avatar'); + }, + ]); + $count = $query->count(); + $list = $query->page($page, $limit)->select()->append(['refund_extension_one', 'refund_extension_two']); + + return compact('count', 'list'); + } + + public function getStat(array $where, $status) + { + + unset($where['status']); + $make = app()->make(StoreRefundOrderRepository::class); + $presellOrderRepository = app()->make(PresellOrderRepository::class); + + //退款订单id + $orderId = $this->dao->search($where)->where($this->getOrderType($status))->column('order_id'); + //退款金额 + $orderRefund = $make->refundPirceByOrder($orderId); + //实际支付订单数量 + $all = $this->dao->search($where)->where($this->getOrderType($status))->where('paid', 1)->count(); + //实际支付订单金额 + $countQuery = $this->dao->search($where)->where($this->getOrderType($status))->where('paid', 1); +// $countOrderId = $countQuery->column('order_id'); + $countPay1 = $countQuery->sum('SupplyStoreOrder.pay_price'); +// $countPay2 = $presellOrderRepository->search(['paid' => 1, 'order_ids' => $countOrderId])->sum('pay_price'); +// $countPay = bcadd($countPay1, $countPay2, 2); + $countPay = $countPay1; + + //余额支付 + $banclQuery = $this->dao->search(array_merge($where, ['paid' => 1, 'pay_type' => 0]))->where($this->getOrderType($status)); + + $banclOrderId = $banclQuery->column('order_id'); + $banclPay1 = $banclQuery->sum('SupplyStoreOrder.pay_price'); + $banclPay2 = $presellOrderRepository->search(['pay_type' => [0], 'paid' => 1, 'order_ids' => $banclOrderId])->sum('pay_price'); + $banclPay = bcadd($banclPay1, $banclPay2, 2); + + //微信金额 + $wechatQuery = $this->dao->search($where)->where($this->getOrderType($status))->where('paid', 1)->where('pay_type', 'in', [1, 2, 3, 6]); + $wechatOrderId = $wechatQuery->column('order_id'); + $wechatPay1 = $wechatQuery->sum('SupplyStoreOrder.pay_price'); + $wechatPay2 = $presellOrderRepository->search(['pay_type' => [1, 2, 3, 6], 'paid' => 1, 'order_ids' => $wechatOrderId])->sum('pay_price'); + $wechatPay = bcadd($wechatPay1, $wechatPay2, 2); + + //支付宝金额 + $aliQuery = $this->dao->search($where)->where($this->getOrderType($status))->where('paid', 1)->where('pay_type', 'in', [4, 5]); + $aliOrderId = $aliQuery->column('order_id'); + $aliPay1 = $aliQuery->sum('SupplyStoreOrder.pay_price'); + $aliPay2 = $presellOrderRepository->search(['pay_type' => [4, 5], 'paid' => 1, 'order_ids' => $aliOrderId])->sum('pay_price'); + $aliPay = bcadd($aliPay1, $aliPay2, 2); + + $stat = [ + [ + 'className' => 'el-icon-s-goods', + 'count' => $all, + 'field' => '件', + 'name' => '已支付订单数量' + ], + [ + 'className' => 'el-icon-s-order', + 'count' => (float)$countPay, + 'field' => '元', + 'name' => '实际支付金额' + ], + [ + 'className' => 'el-icon-s-cooperation', + 'count' => (float)$orderRefund, + 'field' => '元', + 'name' => '已退款金额' + ], + [ + 'className' => 'el-icon-s-cooperation', + 'count' => (float)$wechatPay, + 'field' => '元', + 'name' => '微信支付金额' + ], + [ + 'className' => 'el-icon-s-finance', + 'count' => (float)$banclPay, + 'field' => '元', + 'name' => '余额支付金额' + ], + [ + 'className' => 'el-icon-s-cooperation', + 'count' => (float)$aliPay, + 'field' => '元', + 'name' => '支付宝支付金额' + ], + ]; + return $stat; + } + + /** + * @param array $where + * @param $page + * @param $limit + * @return array + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author xaboy + * @day 2020/6/10 + */ + public function getList(array $where, $page, $limit) + { + $query = $this->dao->search($where)->where('SupplyStoreOrder.is_del', 0); + $count = $query->count(); + $list = $query->with([ + 'orderProduct', + 'presellOrder', + 'merchant' => function ($query) { + return $query->field('mer_id,mer_name'); + }, + 'community', + 'receipt' => function ($query) { + return $query->field('order_id,order_receipt_id'); + }, + ])->page($page, $limit)->order('pay_time DESC')->append(['refund_status','open_receipt'])->select(); + + foreach ($list as $order) { + if ($order->activity_type == 2) { + if ($order->presellOrder) { + $order->presellOrder->append(['activeStatus']); + $order->presell_price = bcadd($order->pay_price, $order->presellOrder->pay_price, 2); + } else { + $order->presell_price = $order->pay_price; + } + } + $order->takeOrderCount = count($order['takeOrderList']); + unset($order['takeOrderList']); + } + + return compact( 'count','list'); + } + + public function userList($uid, $page, $limit) + { + $query = $this->dao->search([ + 'uid' => $uid, + 'paid' => 1 + ]); + $count = $query->count(); + $list = $query->page($page, $limit)->select(); + return compact('count', 'list'); + } + + + public function userMerList($uid, $merId, $page, $limit) + { + $query = $this->dao->search([ + 'uid' => $uid, + 'mer_id' => $merId, + 'paid' => 1 + ]); + $count = $query->count(); + $list = $query->with(['presellOrder'])->page($page, $limit)->select(); + foreach ($list as $order) { + if ($order->activity_type == 2 && $order->status >= 0 && $order->status < 10 && $order->presellOrder) { + $order->pay_price = bcadd($order->pay_price, $order->presellOrder->pay_price, 2); + } + } + return compact('count', 'list'); + } + + public function express(int $orderId, ?int $merId) + { + $order = $this->dao->get($orderId); + if ($merId && $order['mer_id'] != $merId) throw new ValidateException('订单信息不存在'); + if (!in_array($order['delivery_type'], [1, 4])) throw new ValidateException('订单状态错误'); + return ExpressService::express($order->delivery_id, $order->delivery_name, $order->user_phone); + } + + public function checkPrinterConfig(int $merId) + { + if (!merchantConfig($merId, 'printing_status')) + throw new ValidateException('打印功能未开启'); + $config = [ + 'clientId' => merchantConfig($merId, 'printing_client_id'), + 'apiKey' => merchantConfig($merId, 'printing_api_key'), + 'partner' => merchantConfig($merId, 'develop_id'), + 'terminal' => merchantConfig($merId, 'terminal_number') + ]; + if (!$config['clientId'] || !$config['apiKey'] || !$config['partner'] || !$config['terminal']) + throw new ValidateException('打印机配置错误'); + return $config; + } + + /** + * TODO 打印机 -- 暂无使用 + * @param int $id + * @param int $merId + * @return bool|mixed|string + * @author Qinii + * @day 2020-07-30 + */ + public function printer(int $id, int $merId) + { + $order = $this->dao->getWhere(['order_id' => $id], '*', ['orderProduct', 'merchant' => function ($query) { + $query->field('mer_id,mer_name'); + }]); + foreach ($order['orderProduct'] as $item) { + $product[] = [ + 'store_name' => $item['cart_info']['product']['store_name'] . '【' . $item['cart_info']['productAttr']['sku'] . '】', + 'product_num' => $item['product_num'], + 'price' => bcdiv($item['product_price'], $item['product_num'], 2), + 'product_price' => $item['product_price'], + ]; + } + $data = [ + 'order_sn' => $order['order_sn'], + 'pay_time' => $order['pay_time'], + 'real_name' => $order['real_name'], + 'user_phone' => $order['user_phone'], + 'user_address' => $order['user_address'], + 'total_price' => $order['total_price'], + 'coupon_price' => $order['coupon_price'], + 'pay_price' => $order['pay_price'], + 'total_postage' => $order['total_postage'], + 'pay_postage' => $order['pay_postage'], + 'mark' => $order['mark'], + ]; + $config = $this->checkPrinterConfig($merId); + $printer = new Printer('yi_lian_yun', $config); + event('order.print.before', compact('order')); + + try{ + $res = $printer->setPrinterContent([ + 'name' => $order['merchant']['mer_name'], + 'orderInfo' => $data, + 'product' => $product + ])->startPrinter(); + }catch (Exception $exception) { + Log::error('打印失败:'.$exception->getMessage()); + } + + + event('order.print', compact('order', 'res')); + + return $res; + } + + public function batchPrinter(int $id, int $merId) + { + return false; + // $order = $this->dao->getWhere(['order_id' => $id], '*', ['orderProduct', 'merchant' => function ($query) { + // $query->field('mer_id,mer_name'); + // }]); + + // foreach ($order['orderProduct'] as $item) { + // $product[] = [ + // 'store_name' => $item['cart_info']['product']['store_name'] . '【' . $item['cart_info']['productAttr']['sku'] . '】', + // 'product_num' => $item['product_num'], + // 'price' => bcdiv($item['product_price'], $item['product_num'], 2), + // 'product_price' => $item['product_price'], + // ]; + // } + + // $data = [ + // 'order_sn' => $order['order_sn'], + // 'order_type' => $order['order_type'], + // 'pay_time' => $order['pay_time'], + // 'real_name' => $order['real_name'], + // 'user_phone' => $order['user_phone'], + // 'user_address' => $order['user_address'], + // 'total_price' => $order['total_price'], + // 'coupon_price' => bcadd(bcadd($order['coupon_price'], $order['svip_discount'], 2), $order['integral_price'], 2), + // 'pay_price' => $order['pay_price'], + // 'total_postage' => $order['total_postage'], + // 'pay_postage' => $order['pay_postage'], + // 'mark' => $order['mark'], + // 'give_integral' => $order['give_integral'], + // ]; + + // $printer = app()->make(StorePrinterRepository::class)->getPrinter($merId); + // event('order.print.before', compact('order')); + // $name = Config::get('printer.name'); + // foreach ($printer as $config) { + // try{ + // $printer = new Printer($name[$config['type'] ?? 0], $config); + // $res = $printer->setPrinterContent([ + // 'name' => $order['merchant']['mer_name'], + // 'orderInfo' => $data, + // 'product' => $product + // ])->startPrinter(); + // } catch (\think\Exception $exception) { + // Log::error('打印失败:'.$exception->getMessage()); + // } + // } + + // event('order.print', compact('order', 'res')); + } + + + public function verifyOrder(int $id, int $merId, array $data, $serviceId = 0) + { + $order = $this->dao->getWhere(['order_id' => $id, 'mer_id' => $merId,'verify_code' => $data['verify_code'],'order_type' => 1],'*',['orderProduct']); + if (!$order) throw new ValidateException('订单不存在'); + if (!$order->paid) throw new ValidateException('订单未支付'); + if ($order['status']) throw new ValidateException('订单已全部核销,请勿重复操作'); + foreach ($data['data'] as $v) { + $splitData[$v['id']] = $v['num']; + } + $spl = app()->make(StoreOrderSplitRepository::class)->splitOrder($order, $splitData, $serviceId, 1); + if ($spl) $order = $spl; + $order->status = 2; + $order->verify_time = date('Y-m-d H:i:s'); + $order->verify_service_id = $serviceId; + event('order.verify.before', compact('order')); + //订单记录 + $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + Db::transaction(function () use ($order,$storeOrderStatusRepository,$serviceId) { + $this->takeAfter($order, $order->user); + $order->save(); + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $storeOrderStatusRepository::TYPE_ORDER, + 'change_message' => '订单已核销', + 'change_type' => $storeOrderStatusRepository::ORDER_STATUS_TAKE, + ]; + if ($serviceId){ + $storeOrderStatusRepository->createServiceLog($serviceId,$orderStatus); + } else { + $storeOrderStatusRepository->createAdminLog($orderStatus); + } + + }); + + //小程序发货管理 + event('mini_order_shipping', ['product', $order, 7, '', '']); + + event('order.verify', compact('order')); + } + + public function wxQrcode($orderId, $order) + { + $verify_code = $order->verify_code; + $mer_id = $order->mer_id; + $siteUrl = systemConfig('site_url'); + $name = md5('owx' . $orderId . date('Ymd')) . '.jpg'; + $attachmentRepository = app()->make(AttachmentRepository::class); + $imageInfo = $attachmentRepository->getWhere(['attachment_name' => $name]); + + if (isset($imageInfo['attachment_src']) && strstr($imageInfo['attachment_src'], 'http') !== false && curl_file_exist($imageInfo['attachment_src']) === false) { + $imageInfo->delete(); + $imageInfo = null; + } + if (!$imageInfo) { + $codeUrl = set_http_type(rtrim($siteUrl, '/') . '/pages/admin/cancellate_result/index?cal_code=' . $verify_code . '&mer_id=' . $mer_id . '&is_jump=1', request()->isSsl() ? 0 : 1);//二维码链接 + $imageInfo = app()->make(QrcodeService::class)->getQRCodePath($codeUrl, $name); + if (is_string($imageInfo)) throw new ValidateException('二维码生成失败'); + + $imageInfo['dir'] = tidy_url($imageInfo['dir'], null, $siteUrl); + + $attachmentRepository->create(systemConfig('upload_type') ?: 1, -2, $orderId, [ + 'attachment_category_id' => 0, + 'attachment_name' => $imageInfo['name'], + 'attachment_src' => $imageInfo['dir'] + ]); + $urlCode = $imageInfo['dir']; + } else $urlCode = $imageInfo['attachment_src']; + return $urlCode; + } + + /** + * TODO 根据商品ID获取订单数 + * @param int $productId + * @return int + * @author Qinii + * @day 2020-08-05 + */ + public function seckillOrderCounut(int $productId) + { + $where = [ + 'activity_id' => $productId, + 'product_type' => 1, + 'day' => date('Y-m-d', time()) + ]; + $count = $this->dao->getTattendCount($where, null)->sum('product_num'); + $count_ = $this->dao->getSeckillRefundCount($where, 2); + $count__ = $this->dao->getSeckillRefundCount($where, 1); + return $count - $count_ - $count__; + } + + /** + * TODO 根据商品sku获取订单数 + * @param int $productId + * @return int + * @author Qinii + * @day 2020-08-05 + */ + public function seckillSkuOrderCounut(string $sku) + { + $where = [ + 'product_sku' => $sku, + 'product_type' => 1, + 'day' => date('Y-m-d', time()) + ]; + $count = $this->dao->getTattendCount($where, null)->sum('total_num'); + $count_ = $this->dao->getSeckillRefundCount($where, 2); + $count__ = $this->dao->getSeckillRefundCount($where, 1); + return $count - $count_ - $count__; + } + + /** + * TODO 获取sku的总销量 + * @param string $sku + * @return int|mixed + * @author Qinii + * @day 3/4/21 + */ + public function skuSalesCount(string $sku) + { + $where = [ + 'product_sku' => $sku, + 'product_type' => 1, + ]; + $count = $this->dao->getTattendSuccessCount($where, null)->count(); + $count_ = $this->dao->getSeckillRefundCount($where, 2); + $count__ = $this->dao->getSeckillRefundCount($where, 1); + return $count - $count_ - $count__; + } + + /** + * TODO 秒杀获取个人当天限购 + * @param int $uid + * @param int $productId + * @return int + * @author Qinii + * @day 2020-08-15 + */ + public function getDayPayCount(int $uid, int $productId, $cart_num) + { + // $make = app()->make(StoreSeckillActiveRepository::class); + // $active = $make->getWhere(['product_id' => $productId]); + // if ($active['once_pay_count'] == 0) return true; + + // $where = [ + // 'activity_id' => $productId, + // 'product_type' => 1, + // 'day' => date('Y-m-d', time()) + // ]; + + // $count = (int)$this->dao->getTattendCount($where, $uid)->sum('total_num'); + // if ($count >= $active['once_pay_count']) { + // return false; + // } else if (($count + $cart_num) > $active['once_pay_count']){ + // return false; + // } + return true; + } + + /** + * TODO 秒杀获取个人总限购 + * @param int $uid + * @param int $productId + * @return int + * @author Qinii + * @day 2020-08-15 + */ + public function getPayCount(int $uid, int $productId,$cart_num) + { + // $make = app()->make(StoreSeckillActiveRepository::class); + // $active = $make->getWhere(['product_id' => $productId]); + // if ($active['all_pay_count'] == 0) return true; + // $where = [ + // 'activity_id' => $productId, + // 'product_type' => 1, + // 'day' => date('Y-m-d', time()) + // ]; + // $count = (int)$this->dao->getTattendCount($where, $uid)->sum('total_num'); + // if ($count >= $active['all_pay_count']) { + // return false; + // } else if (($count + $cart_num) > $active['all_pay_count']){ + // return false; + // } + return true; + } + + /** + * 根据订单id查看是否全部退款 + * @Author:Qinii + * @Date: 2020/9/11 + * @param int $orderId + * @return bool + */ + public function checkRefundStatusById(int $orderId, int $refundId) + { + return Db::transaction(function () use ($orderId, $refundId) { + $res = $this->dao->search(['order_id' => $orderId])->with(['orderProduct'])->find(); + $refund = app()->make(StoreRefundOrderRepository::class)->getRefundCount($orderId, $refundId); + if ($refund) return false; + foreach ($res['orderProduct'] as $item) { + if ($item['refund_num'] !== 0) return false; + $item->is_refund = 3; + $item->save(); + } + $res->status = -1; + $res->save(); + $this->orderRefundAllAfter($res); + return true; + }); + } + + public function orderRefundAllAfter($order) + { + + // if ($order->activity_type == 10) { + // app()->make(StoreDiscountRepository::class)->incStock($order->orderProduct[0]['activity_id']); + // } + $mainId = $order->main_id ?: $order->order_id; + $count = $this->query([])->where('status', '<>', -1)->where(function ($query) use ($mainId) { + $query->where('order_id', $mainId)->whereOr('main_id', $mainId); + })->count(); + //拆单后完全退完 + if (!$count) { + if ($order->main_id) { + $order = $this->query(['order_id' => $mainId])->find(); + } + $couponId = []; + if ($order->coupon_id) { + $couponId = explode(',', $order->coupon_id); + } + app()->make(SupplyRepository::class)->computedLockMoney($order); + //总单所有订单全部退完 + if (!$this->query([])->where('status', '<>', -1)->where('group_order_id', $order->group_order_id)->count()) { + if ($order->groupOrder->coupon_id) { + $couponId[] = $order->groupOrder->coupon_id; + } + } + // if (count($couponId)) { + // app()->make(StoreCouponUserRepository::class)->updates($couponId, ['status' => 0]); + // } + + } + //订单记录 + $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $storeOrderStatusRepository::TYPE_ORDER, + 'change_message' => '订单已全部退款', + 'change_type' => $storeOrderStatusRepository::ORDER_STATUS_REFUND_ALL, + ]; + $storeOrderStatusRepository->createSysLog($orderStatus); + + event('order.refundAll', compact('order')); + } + + /** + * @param $id + * @param $uid + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author xaboy + * @day 2020/9/17 + */ + public function userDel($id, $uid) + { + $order = $this->dao->getWhere([['status', 'in', [0, 3, -1, 11]], ['order_id', '=', $id], ['uid', '=', $uid], ['is_del', '=', 0]]); + if (!$order || ($order->status == 0 && $order->paid == 1)) + throw new ValidateException('订单状态有误'); + event('order.userDel.before', compact('order')); + $this->delOrder($order, '订单删除'); + event('order.userDel', compact('order')); + } + + public function delOrder($order, $info = '订单删除') + { + //订单记录 + $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); + $orderStatus = [ + 'order_id' => $order->order_id, + 'order_sn' => $order->order_sn, + 'type' => $storeOrderStatusRepository::TYPE_ORDER, + 'change_message' => $info, + 'change_type' => $storeOrderStatusRepository::ORDER_STATUS_DELETE, + ]; + $productRepository = app()->make(SupplyProductRepository::class); + Db::transaction(function () use ($info, $order, $orderStatus, $storeOrderStatusRepository,$productRepository) { + $order->is_del = 1; + $order->save(); + $storeOrderStatusRepository->createUserLog($orderStatus); + if ($order->status != 3) { + foreach ($order->orderProduct as $cart) { + $productRepository->orderProductIncStock($order, $cart); + } + } + }); + } + + public function merDelete($id) + { + Db::transaction(function () use ($id) { + $data['is_system_del'] = 1; + $this->dao->update($id, $data); + app()->make(StoreOrderReceiptRepository::class)->deleteByOrderId($id); + }); + } + + /** + * @param $id + * @return \FormBuilder\Form + * @author Qinii + */ + public function sendProductForm($id, $data) + { + // $express = app()->make(ExpressRepository::class)->options(); + $form = Elm::createForm(Route::buildUrl('merchantStoreOrderDelivery', ['id' => $id])->build()); + + if (in_array($data['delivery_type'], [1, 2])) { + // if ($data['delivery_type'] == 1) { + // $form->setRule([ + // Elm::hidden('delivery_type', 1), + // [ + // 'type' => 'span', + // 'title' => '原快递名称', + // 'children' => [(string)$data['delivery_name']] + // ], + // [ + // 'type' => 'span', + // 'title' => '原快递单号', + // 'children' => [(string)$data['delivery_id']] + // ], + // Elm::select('delivery_name', '快递名称:')->options(function () use ($express) { + // return $express; + // })->placeholder('请选择快递名称'), + // Elm::input('delivery_id', '快递单号:')->placeholder('请输入快递单号')->required(), + // ]); + // } else { + $form->setRule([ + Elm::hidden('delivery_type', 2), + [ + 'type' => 'span', + 'title' => '原送货人姓名', + 'children' => [(string)$data['delivery_name']] + ], + [ + 'type' => 'span', + 'title' => '原手机号', + 'children' => [(string)$data['delivery_id']] + ], + Elm::input('delivery_name', '送货人姓名:')->placeholder('请输入送货人姓名')->required(), + Elm::input('delivery_id', '手机号:')->placeholder('请输入手机号')->required(), + ]); + // } + } + if ($data['delivery_type'] == 3) { + $form->setRule([ + Elm::hidden('delivery_type', 3), + [ + 'type' => 'span', + 'title' => '发货类型', + 'children' => ['无需配送'] + ] + ]); + } + if (!$data['delivery_type']) { + $form->setRule([ + Elm::radio('delivery_type', '发货类型:', 1) + ->setOptions([ + ['value' => 1, 'label' => '发货'], + ['value' => 2, 'label' => '送货'], + ['value' => 3, 'label' => '无需配送'], + ])->control([ + // [ + // 'value' => 1, + // 'rule' => [ + // Elm::select('delivery_name', '快递名称')->options(function () use ($express) { + // return $express; + // })->placeholder('请选择快递名称'), + // Elm::input('delivery_id', '快递单号')->placeholder('请输入快递单号')->required(), + // ] + // ], + [ + 'value' => 2, + 'rule' => [ + Elm::input('delivery_name', '送货人姓名:')->placeholder('请输入送货人姓名')->required(), + Elm::input('delivery_id', '手机号:')->placeholder('请输入手机号')->required(), + ] + ], + [ + 'value' => 3, + 'rule' => [] + ], + + ]), + ]); + } + + return $form->setTitle('发货信息'); + } + + /** + * TODO 导入发货信息 + * @param array $data + * @param $merId + * @author Qinii + * @day 3/16/21 + */ + public function setWhereDeliveryStatus(array $arrary, $merId) + { + //读取excel + $data = SpreadsheetExcelService::instance()->_import($arrary['path'], $arrary['sql'], $arrary['where'], 4); + if (!$data) return; + $import_id = $arrary['import_id']; + Db::transaction(function () use ($data, $merId, $import_id) { + $result = []; + $num = 0; + $count = 0; + $status = 0; + foreach ($data as $datum) { + $value = []; + $ret = []; + if ($datum['where']) { + $count = $count + 1; + if (empty($datum['value']['delivery_id'])) { + $mark = '发货单号为空'; + } else { + $ret = $this->getSearch([]) + ->where('status', 0) + ->where('paid', 1) + ->where('order_type', 0) + ->where('mer_id', $merId) + ->where($datum['where']) + ->find(); + $mark = '数据有误或已发货'; + } + if ($ret) { + try { + $value = array_merge($datum['value'], ['status' => 1]); + $value['delivery_type'] = 1; + $this->delivery($ret['order_id'], $merId, $value); + + $status = 1; + $mark = ''; + + $num = $num + 1; + } catch (\Exception $exception) { + $mark = $exception->getMessage(); + } + } + $datum['where']['mark'] = $mark; + $datum['where']['mer_id'] = $merId; + $datum['where']['status'] = $status; + $datum['where']['import_id'] = $import_id; + $result[] = array_merge($datum['where'], $datum['value']); + } + } + // 记录入库操作 + if (!empty($result)) app()->make(StoreImportDeliveryRepository::class)->insertAll($result); + $_status = ($count == $num) ? 1 : (($num < 1) ? -1 : 10); + app()->make(StoreImportRepository::class)->update($import_id, ['count' => $count, 'success' => $num, 'status' => $_status]); + }); + if (file_exists($arrary['path'])) unlink($arrary['path']); + } + + /** + * TODO 根据订单查询相关联的自订单 + * @param $id + * @param $merId + * @return \think\Collection + * @author Qinii + * @day 2023/2/22 + */ + public function childrenList($id,$merId) + { + $data = $this->dao->get($id); + $query = $this->dao->getSearch([])->with(['orderProduct'])->where('order_id','<>',$id); + if ($merId) $query->where('mer_id',$merId); + if ($data['main_id']) { + $query->where(function($query) use($data,$id){ + $query->where('main_id',$data['main_id'])->whereOr('order_id',$data['main_id']); + }); + } else { + $query->where('main_id',$id); + } + return $query->select(); + } + + public function pointsOrderList(array $where, int $page, int $limit) + { + $query = $this->dao->searchAll($where,0,1)->where('is_del', 0); + $count = $query->count(); + $list = $query->with(['orderProduct'])->page($page, $limit)->select(); + return compact('count','list'); + } + + public function pointsOrderAdminList(array $where, int $page, int $limit) + { + $query = $this->dao->searchAll($where,0,1); + $count = $query->count(); + $list = $query->with(['orderProduct'])->page($page, $limit)->select(); + return compact('count','list'); + } + + public function pointsDetail($id, $uid) + { + $where = []; + $with = ['orderProduct',]; + if ($uid) { + $where['uid'] = $uid; + } else if (!$uid) { + $with['user'] = function ($query) { + return $query->field('uid,nickname'); + }; + } + $order = $this->dao->searchAll($where,0,1)->where('order_id', $id)->where('SupplyStoreOrder.is_del', 0)->with($with)->append(['cancel_time'])->find(); + if (!$order) return null; + return $order; + } + + /** + * 判断该子订单是否有未发货的子订单 + * @param int $main_id + * @param int $order_id + * @return bool + * + * @date 2023/10/18 + * @author yyw + */ + public function checkSubOrderNotSend(int $group_order_id, int $order_id) + { + $order_count = $this->dao->getSubOrderNotSend($group_order_id, $order_id); + if ($order_count > 0) { + return false; + } else { + return true; + } + } +} diff --git a/app/common/repositories/store/parameter/SupplyParameterValueRepository.php b/app/common/repositories/store/parameter/SupplyParameterValueRepository.php new file mode 100644 index 00000000..e2267fd8 --- /dev/null +++ b/app/common/repositories/store/parameter/SupplyParameterValueRepository.php @@ -0,0 +1,105 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\repositories\store\parameter; + +use app\common\dao\store\parameter\SupplyParameterValueDao; +use app\common\repositories\BaseRepository; +use think\facade\Db; + +class SupplyParameterValueRepository extends BaseRepository +{ + /** + * @var ParameterValueDao + */ + protected $dao; + + + /** + * ParameterRepository constructor. + * @param ParameterValueDao $dao + */ + public function __construct(SupplyParameterValueDao $dao) + { + $this->dao = $dao; + } + + public function create($id, $data,$merId) + { + if (empty($data)) return ; + foreach ($data as $datum) { + if ($datum['name'] && $datum['value']) { + $create[] = [ + 'product_id' => $id, + 'name' => $datum['name'] , + 'value' => $datum['value'], + 'sort' => $datum['sort'], + 'parameter_id' => $datum['parameter_id'] ?? 0, + 'mer_id' => $datum['mer_id'] ?? $merId, + 'create_time' => date('Y-m-d H:i:s',time()) + ]; + } + } + if ($create) $this->dao->insertAll($create); + } + + + /** + * 获取所有参数的值,并合并所关联的商品ID + * @param $where + * @return array + * @author Qinii + * @day 2023/10/21 + */ + public function getOptions($where) + { + $data = $this->dao->getSearch($where)->column('parameter_id,name','value'); + return array_values($data); + } + + /** + * 根据筛选的参数,查询出商品ID + * @param $filter_params + * @param $page + * @param $limit + * @return array + * @author Qinii + * @day 2023/11/14 + */ + public function filter_params($filter_params) + { + $productId = []; + if (!empty($filter_params)) { + if (!is_array($filter_params)) $filter_params = json_decode($filter_params,true); + $value = []; + foreach ($filter_params as $k => $v) { + $id[] = $k; + $value = array_merge($value,$v); + } + if (empty($id) || empty($value)) return false; + $productData = $this->dao->getSearch([])->alias('P') + ->join('SupplyParameterValue V','P.product_id = V.product_id') + ->whereIn('P.parameter_id',$id)->whereIn('P.value',$value) + ->whereIn('V.parameter_id',$id)->whereIn('V.value',$value) + ->group('P.product_id') + ->field('P.product_id') + ->select(); + if ($productData) { + $productData = $productData->toArray(); + $productId = array_column($productData,'product_id'); + } + } + return $productId; + } + +} + diff --git a/app/common/repositories/store/product/SupplyProductAttrValueRepository.php b/app/common/repositories/store/product/SupplyProductAttrValueRepository.php new file mode 100644 index 00000000..06f6e201 --- /dev/null +++ b/app/common/repositories/store/product/SupplyProductAttrValueRepository.php @@ -0,0 +1,85 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\repositories\store\product; + +use app\common\repositories\BaseRepository; +use app\common\dao\store\product\SupplyProductAttrValueDao as dao; + +/** + * Class SupplyProductAttrValueRepository + * @package app\common\repositories\store\product + * @mixin dao + */ +class SupplyProductAttrValueRepository extends BaseRepository +{ + + protected $dao; + + /** + * ProductRepository constructor. + * @param dao $dao + */ + public function __construct(dao $dao) + { + $this->dao = $dao; + } + + /** + * @Author:Qinii + * @Date: 2020/5/30 + * @param int $id + * @return mixed + */ + public function priceCount(int $id) + { + return min($this->dao->getFieldColumnt('product_id',$id,'price')); + } + + /** + * @Author:Qinii + * @Date: 2020/5/30 + * @param int $id + * @return mixed + */ + public function stockCount(int $id) + { + return $this->dao->getFieldSum('product_id',$id,'stock'); + } + + /** + * @Author:Qinii + * @Date: 2020/5/30 + * @param int|null $merId + * @param string $value + * @return bool + */ + public function merUniqueExists(?int $merId,string $value) + { + return $this->dao->merFieldExists($merId,'unique',$value); + } + + /** + * TODO + * @param $unique + * @return mixed + * @author Qinii + * @day 2020-08-05 + */ + public function getOptionByUnique($unique) + { + return $this->dao->getFieldExists(null,'unique',$unique)->find(); + } + + + +} diff --git a/app/common/repositories/store/product/SupplyProductRepository.php b/app/common/repositories/store/product/SupplyProductRepository.php new file mode 100644 index 00000000..fb232d85 --- /dev/null +++ b/app/common/repositories/store/product/SupplyProductRepository.php @@ -0,0 +1,2587 @@ + +// +---------------------------------------------------------------------- + +namespace app\common\repositories\store\product; + +use app\common\dao\store\product\ProductDao as dao; +use app\common\model\user\User; +// use app\common\repositories\community\CommunityRepository; +// use app\common\repositories\store\coupon\StoreCouponRepository; +use app\common\repositories\store\GuaranteeRepository; +use app\common\repositories\store\GuaranteeTemplateRepository; +use app\common\repositories\store\GuaranteeValueRepository; + +use app\common\repositories\store\order\SupplyStoreCartRepository; +use app\common\repositories\store\order\SupplyStoreOrderProductRepository; +use app\common\repositories\store\order\SupplyStoreOrderRepository; + +use app\common\repositories\store\parameter\SupplyParameterValueRepository; +// use app\common\repositories\store\StoreActivityRepository; +// use app\common\repositories\store\StoreSeckillActiveRepository; +// use app\common\repositories\store\StoreSeckillTimeRepository; +use app\common\repositories\system\supply\SupplyRepository; + +use app\common\repositories\system\operate\OperateLogRepository; + +use app\common\repositories\user\UserRelationRepository; +use app\common\repositories\user\UserVisitRepository; + +use app\validate\supply\StoreProductValidate; + +use crmeb\jobs\ChangeSupplySpuStatusJob; +use crmeb\jobs\DownloadProductCopyImage; +use crmeb\jobs\SendSmsJob; + +use crmeb\services\QrcodeService; +use crmeb\services\RedisCacheService; +use crmeb\services\SwooleTaskService; +use FormBuilder\Factory\Elm; +use http\Exception\InvalidArgumentException; +use think\exception\ValidateException; +use think\facade\Cache; +use think\facade\Db; +use app\common\repositories\BaseRepository; +use app\common\repositories\store\SupplyStoreCategoryRepository; +// use app\common\repositories\store\shipping\ShippingTemplateRepository; +use app\common\repositories\store\SupplyStoreBrandRepository; +use think\facade\Queue; +use think\facade\Route; +use think\contract\Arrayable; + +/** + * Class SupplyProductRepository + * @package app\common\repositories\store\product + * @author xaboy + * @mixin dao + */ +class SupplyProductRepository extends BaseRepository +{ + + protected $dao; + const CREATE_PARAMS = [ + "is_copy", "image", "slider_image", "store_name", "store_info", "keyword", "bar_code", "guarantee_template_id", "cate_id", "unit_name", "sort", "is_show", "is_good", 'is_gift_bag', 'integral_rate', "video_link", "temp_id", "content", "spec_type", "extension_type", "attr", 'mer_labels', 'delivery_way', 'delivery_free', 'param_temp_id', 'extend', 'mer_form_id', + ["mer_cate_id", []], + ['refund_switch', 1], + ["brand_id", 0], + ['once_max_count', 0], + ['once_min_count', 0], + ['pay_limit', 0], + ["attrValue", []], + ['give_coupon_ids', []], + ['type', 0], + ['svip_price', 0], + ['svip_price_type', 0], + ['params', []], + ['product_type', 0], + ['good_ids', []], + ]; + protected $admin_filed = 'Product.product_id,Product.mer_id,brand_id,spec_type,unit_name,mer_status,rate,reply_count,store_info,cate_id,Product.image,slider_image,Product.store_name,Product.keyword,Product.sort,U.rank,Product.is_show,Product.sales,Product.price,extension_type,refusal,cost,Product.ot_price,stock,is_gift_bag,Product.care_count,Product.status,is_used,Product.create_time,Product.product_type,old_product_id,star,ficti,integral_total,integral_price_total,sys_labels,Product.param_temp_id,Product.mer_svip_status,Product.svip_price,Product.svip_price_type,Product.mer_form_id,Product.good_ids'; + protected $filed = 'Product.product_id,Product.mer_id,brand_id,unit_name,spec_type,mer_status,rate,reply_count,store_info,cate_id,Product.image,slider_image,Product.store_name,Product.keyword,Product.sort,Product.is_show,Product.sales,Product.price,extension_type,refusal,cost,Product.ot_price,stock,is_gift_bag,Product.care_count,Product.status,is_used,Product.create_time,Product.product_type,old_product_id,integral_total,integral_price_total,mer_labels,Product.is_good,Product.is_del,Product.type,Product.param_temp_id,Product.mer_svip_status,Product.svip_price,Product.svip_price_type,Product.mer_form_id,Product.good_ids'; + + const NOTIC_MSG = [ + 1 => [ + '0' => 'product_success', + '1' => 'product_seckill_success', + '2' => 'product_presell_success', + '3' => 'product_assist_success', + '4' => 'product_group_success', + 'msg' => '审核通过' + ], + -1 => [ + '0' => 'product_fail', + '1' => 'product_seckill_fail', + '2' => 'product_presell_fail', + '3' => 'product_assist_fail', + '4' => 'product_group_fail', + 'msg' => '审核失败' + ], + -2 => [ + '0' => 'product_fail', + '1' => 'product_seckill_fail', + '2' => 'product_presell_fail', + '3' => 'product_assist_fail', + '4' => 'product_group_fail', + 'msg' => '被下架' + ], + ]; + + /** + * ProductRepository constructor. + * @param dao $dao + */ + public function __construct(dao $dao) + { + $this->dao = $dao; + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $id + * @param int $merId + * @return mixed + */ + public function CatExists(int $id) + { + return (app()->make(SupplyStoreCategoryRepository::class))->merExists(0, $id); + } + + /** + * @Author:Qinii + * @Date: 2020/5/20 + * @param $ids + * @param int $merId + * @return bool + */ + public function merCatExists($ids, int $merId) + { + if (!is_array($ids ?? '')) return true; + foreach ($ids as $id) { + if (!(app()->make(SupplyStoreCategoryRepository::class))->merExists($merId, $id)) + return false; + } + return true; + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $merId + * @param int $id + * @return mixed + */ + public function merShippingExists(int $merId, int $id) + { + return 0; + // $make = app()->make(ShippingTemplateRepository::class); + // return $make->merExists($merId, $id); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $id + * @return mixed + */ + public function merBrandExists(int $id) + { + $make = app()->make(SupplyStoreBrandRepository::class); + return $make->meExists($id); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $merId + * @param int $id + * @return bool + */ + public function merExists(?int $merId, int $id) + { + return $this->dao->merFieldExists($merId, $this->getPk(), $id); + } + + public function merDeleteExists(int $merId, int $id) + { + return $this->dao->getDeleteExists($merId, $id); + } + + /** + * @Author:Qinii + * @Date: 2020/5/30 + * @param int $merId + * @param int $id + * @return bool + */ + public function apiExists(?int $merId, int $id) + { + return $this->dao->apiFieldExists($merId, $this->getPk(), $id); + } + + /** + * @param int $merId + * @param int $tempId + * @return bool + * @author Qinii + */ + public function merTempExists(int $merId, int $tempId) + { + return $this->dao->merFieldExists($merId, 'temp_id', $tempId); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param array $data + */ + public function create(array $data, int $productType = 0, $conType = 0) + { + if (!$data['spec_type']) { + $data['attr'] = []; + if (count($data['attrValue']) > 1) throw new ValidateException('单规格商品属性错误'); + } + $content = [ + 'content' => $conType ? json_encode($data['content']) : $data['content'], + 'type' => $conType + ]; + $admin_info = []; + if (isset($data['admin_info'])) { + $admin_info = $data['admin_info'] ?? []; + unset($data['admin_info']); + } + + $product = $this->setProduct($data); + event('product.create.before', compact('data', 'productType', 'conType')); + return Db::transaction(function () use ($data, $productType, $conType, $content, $product, $admin_info) { + $activity_id = 0; + $result = $this->dao->create($product); + $settleParams = $this->setAttrValue($data, $result->product_id, $productType, 0); + $settleParams['cate'] = $this->setMerCate($data['mer_cate_id'], $result->product_id, $data['mer_id']); + $settleParams['attr'] = $this->setAttr($data['attr'], $result->product_id); + if ($productType == 0) app()->make(SupplyParameterValueRepository::class)->create($result->product_id, $data['params'] ?? [], $data['mer_id']); + $this->save($result->product_id, $settleParams, $content, $product, $productType); + if (in_array($productType, [0, 1])) { + // if ($productType == 1) { //秒杀商品 + // $dat = $this->setSeckillProduct($data); + // $dat['product_id'] = $result->product_id; + // $seckill = app()->make(StoreSeckillActiveRepository::class)->create($dat); + // $activity_id = $seckill->seckill_active_id; + // } + $product['price'] = $settleParams['data']['price']; + $product['ot_price'] = $settleParams['data']['ot_price']; + $product['mer_labels'] = $data['mer_labels']; + app()->make(SpuRepository::class)->create($product, $result->product_id, $activity_id, $productType); + } + $product = $result; + event('product.create', compact('product')); + if (isset($data['is_copy']) && $data['is_copy']) Queue::push(DownloadProductCopyImage::class, ['id' => $result->product_id, 'data' => $data]); + // 添加操作日志 + if (!empty($admin_info)) { + event('create_operate_log', [ + 'category' => OperateLogRepository::MERCHANT_CREATE_PRODUCT, + 'data' => [ + 'product' => $result, + 'admin_info' => $admin_info, + ], + 'mer_id' => $product['mer_id'] ?? 0 + ]); + } + + return $result->product_id; + }); + } + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $id + * @param array $data + */ + public function edit(int $id, array $data, int $merId, int $productType, $conType = 0) + { + if (!$data['spec_type']) { + $data['attr'] = []; + if (count($data['attrValue']) > 1) throw new ValidateException('单规格商品属性错误'); + } + event('product.update.before', compact('id', 'data', 'merId', 'productType', 'conType')); + $spuData = $product = $this->setProduct($data); + $settleParams = $this->setAttrValue($data, $id, $productType, 1); + $settleParams['cate'] = $this->setMerCate($data['mer_cate_id'], $id, $merId); + $settleParams['attr'] = $this->setAttr($data['attr'], $id); + $content = [ + 'content' => $conType ? json_encode($data['content']) : $data['content'], + 'type' => $conType + ]; + $spuData['price'] = $settleParams['data']['price']; + $spuData['mer_id'] = $merId; + $spuData['mer_labels'] = $data['mer_labels']; + if (isset($data['admin_info'])) { + $product['admin_info'] = $data['admin_info']; + unset($data['admin_info']); + } + return Db::transaction(function () use ($id, $data, $productType, $settleParams, $content, $product, $spuData, $merId) { + $productData = $this->save($id, $settleParams, $content, $product, $productType); + // if ($productType == 1) { //秒杀商品 + // $dat = $this->setSeckillProduct($data); + // app()->make(StoreSeckillActiveRepository::class)->updateByProduct($id, $dat); + // } + if ($productType == 0) { + $make = app()->make(SupplyParameterValueRepository::class); + $make->clear($id, 'product_id'); + $make->create($id, $data['params'] ?? [], $merId); + } + app()->make(SpuRepository::class)->baseUpdate($spuData, $id, 0, $productType); + event('product.update', compact('id')); + app()->make(SpuRepository::class)->changeStatus($id, $productType); + return $productData; + }); + } + + public function freeTrial(int $id, array $data, int $merId, $admin_info = []) + { + if (!$data['spec_type']) { + $data['attr'] = []; + if (count($data['attrValue']) > 1) throw new ValidateException('单规格商品属性错误'); + } + $res = $this->dao->get($id); + $data['svip_price_type'] = $res['svip_price_type']; + $settleParams = $this->setAttrValue($data, $id, 0, 1); + $settleParams['cate'] = $this->setMerCate($data['mer_cate_id'], $id, $merId); + $settleParams['attr'] = $this->setAttr($data['attr'], $id); + $data['price'] = $settleParams['data']['price']; + unset($data['attrValue'], $data['attr'], $data['mer_cate_id']); + $ret = app()->make(SpuRepository::class)->getSearch(['product_id' => $id, 'product_type' => 0,])->find(); + Db::transaction(function () use ($id, $data, $settleParams, $ret, $admin_info) { + $this->save($id, $settleParams, null, ['admin_info' => $admin_info], 0); + app()->make(SpuRepository::class)->update($ret->spu_id, ['price' => $data['price']]); + Queue(SendSmsJob::class, ['tempId' => 'PRODUCT_INCREASE', 'id' => $id]); + }); + } + + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param $id + */ + public function destory($id) + { + (app()->make(ProductAttrRepository::class))->clearAttr($id); + (app()->make(ProductAttrValueRepository::class))->clearAttr($id); + (app()->make(ProductContentRepository::class))->clearAttr($id, null); + (app()->make(ProductCateRepository::class))->clearAttr($id); + $res = $this->dao->destory($id); + + } + + /** + * @Author:Qinii + * @Date: 2020/5/20 + * @param $id + * @param $spec_type + * @param $settleParams + * @param $content + * @return array|\think\Model|null + */ + public function save($id, $settleParams, $content, $data = [], $productType = 0) + { + $res = $this->dao->get($id); + + $productAttrRepository = app()->make(ProductAttrRepository::class); + $productAttrRepository->clearAttr($res->product_id); + if (isset($settleParams['attr'])) + $productAttrRepository->insert($settleParams['attr']); + + $productCateRepository = app()->make(ProductCateRepository::class); + $productCateRepository->clearAttr($res->product_id); + if (isset($settleParams['cate'])) + $productCateRepository->insert($settleParams['cate']); + + $productAttrValueRepository = app()->make(ProductAttrValueRepository::class); + $productAttrValueRepository->clearAttr($res->product_id); + if (isset($settleParams['attrValue'])) { + $arr = array_chunk($settleParams['attrValue'], 30); + foreach ($arr as $item) { + $productAttrValueRepository->add($item, $res->type); + } + } + if ($content) { + app()->make(ProductContentRepository::class)->clearAttr($res->product_id, $content['type']); + $this->dao->createContent($res->product_id, $content); + } + + if (isset($data['admin_info'])) { + $admin_info = $data['admin_info']; + unset($data['admin_info']); + } + $update_infos = $settleParams['update_infos'] ?? []; + + if (isset($settleParams['data'])) $data = array_merge($data, $settleParams['data']); + $this->dao->update($id, $data); + if (isset($data['status']) && $data['status'] !== 1) { + $message = '您有1个新的' . ($productType ? '秒杀商品' : ($data['is_gift_bag'] ? '礼包商品' : '商品')) . '待审核'; + $type = $productType ? 'new_seckill' : ($data['is_gift_bag'] ? 'new_bag' : 'new_product'); + SwooleTaskService::admin('notice', [ + 'type' => $type, + 'data' => [ + 'title' => '商品审核', + 'message' => $message, + 'id' => $id + ] + ]); + } + if (!empty($admin_info) && !empty($update_infos)) { + event('create_operate_log', [ + 'category' => OperateLogRepository::MERCHANT_EDIT_PRODUCT, + 'data' => [ + 'product' => $res, + 'admin_info' => $admin_info, + 'update_infos' => $update_infos, + ], + ]); + } + + return $res; + } + + /** + * @Author:Qinii + * @Date: 2020/5/18 + * @param int $id + * @param array $data + * @return int + */ + public function adminUpdate(int $id, array $data) + { + Db::transaction(function () use ($id, $data) { + app()->make(ProductContentRepository::class)->clearAttr($id, 0); + $this->dao->createContent($id, ['content' => $data['content']]); + unset($data['content']); + $res = $this->dao->getWhere(['product_id' => $id], '*', ['seckillActive']); + $activity_id = $res['seckillActive']['seckill_active_id'] ?? 0; + app()->make(SpuRepository::class)->changRank($activity_id, $id, $res['product_type'], $data); + unset($data['star']); + return $this->dao->update($id, $data); + }); + } + + /** + * 格式化秒杀商品活动时间 + * @Author:Qinii + * @Date: 2020/9/15 + * @param array $data + * @return array + */ + public function setSeckillProduct(array $data) + { + $dat = [ + 'start_day' => $data['start_day'], + 'end_day' => $data['end_day'], + 'start_time' => $data['start_time'], + 'end_time' => $data['end_time'], + 'status' => 1, + 'once_pay_count' => $data['once_pay_count'], + 'all_pay_count' => $data['all_pay_count'], + ]; + if (isset($data['mer_id'])) $dat['mer_id'] = $data['mer_id']; + return $dat; + } + + /** + * 格式商品主体信息 + * @Author:Qinii + * @Date: 2020/9/15 + * @param array $data + * @return array + */ + public function setProduct(array $data) + { + $give_coupon_ids = ''; + if (isset($data['give_coupon_ids']) && !empty($data['give_coupon_ids'])) { + $gcoupon_ids = array_unique($data['give_coupon_ids']); + $give_coupon_ids = implode(',', $gcoupon_ids); + } + + if (isset($data['integral_rate'])) { + $integral_rate = $data['integral_rate']; + if ($data['integral_rate'] < 0) $integral_rate = -1; + if ($data['integral_rate'] > 100) $integral_rate = 100; + + } + + $result = [ + 'store_name' => $data['store_name'], + 'image' => $data['image'], + 'slider_image' => is_array($data['slider_image']) ? implode(',', $data['slider_image']) : '', + 'store_info' => $data['store_info'] ?? '', + 'keyword' => $data['keyword'] ?? '', + 'brand_id' => $data['brand_id'] ?? 0, + 'cate_id' => $data['cate_id'] ?? 0, + 'unit_name' => $data['unit_name'] ?? '件', + 'sort' => $data['sort'] ?? 0, + 'is_show' => $data['is_show'] ?? 0, + 'is_used' => (isset($data['status']) && $data['status'] == 1) ? 1 : 0, + 'is_good' => $data['is_good'] ?? 0, + 'video_link' => $data['video_link'] ?? '', + 'temp_id' => $data['delivery_free'] ? 0 : ($data['temp_id'] ?? 0), + 'extension_type' => $data['extension_type'] ?? 0, + 'spec_type' => $data['spec_type'] ?? 0, + 'status' => $data['status'] ?? 0, + 'give_coupon_ids' => $give_coupon_ids, + 'mer_status' => $data['mer_status'], + 'guarantee_template_id' => $data['guarantee_template_id'] ?? 0, + 'is_gift_bag' => $data['is_gift_bag'] ?? 0, + 'integral_rate' => $integral_rate ?? 0, + 'delivery_way' => implode(',', $data['delivery_way']), + 'delivery_free' => $data['delivery_free'] ?? 0, + 'once_min_count' => $data['once_min_count'] ?? 0, + 'once_max_count' => $data['once_max_count'] ?? 0, + 'pay_limit' => $data['pay_limit'] ?? 0, + 'svip_price_type' => $data['svip_price_type'] ?? 0, + 'refund_switch' => $data['refund_switch'] ?? 0, + 'mer_form_id' => $data['mer_form_id'] ?? 0, + 'rate' => $data['rate'] ?? 5.0, + ]; + if (isset($data['extend'])) + $result['extend'] = $data['extend'] ? json_encode($data['extend'], JSON_UNESCAPED_UNICODE) : ''; + if (isset($data['mer_id'])) + $result['mer_id'] = $data['mer_id']; + if (isset($data['old_product_id'])) + $result['old_product_id'] = $data['old_product_id']; + if (isset($data['product_type'])) + $result['product_type'] = $data['product_type']; + if (isset($data['type']) && $data['type']) + $result['type'] = $data['type']; + if (isset($data['param_temp_id'])) + $result['param_temp_id'] = $data['param_temp_id']; + if (isset($data['good_ids'])) + $result['good_ids'] = $data['good_ids']; + return $result; + } + + /** + * 格式商品商户分类 + * @Author:Qinii + * @Date: 2020/9/15 + * @param array $data + * @param int $productId + * @param int $merId + * @return array + */ + public function setMerCate(array $data, int $productId, int $merId) + { + $result = []; + foreach ($data as $value) { + $result[] = [ + 'product_id' => $productId, + 'mer_cate_id' => $value, + 'mer_id' => $merId, + ]; + } + return $result; + } + + /** + * 格式商品规格 + * @Author:Qinii + * @Date: 2020/9/15 + * @param array $data + * @param int $productId + * @return array + */ + public function setAttr(array $data, int $productId) + { + $result = []; + try { + foreach ($data as $value) { + $result[] = [ + 'type' => 0, + 'product_id' => $productId, + "attr_name" => $value['value'] ?? $value['attr_name'], + 'attr_values' => implode('-!-', $value['detail']), + ]; + } + } catch (\Exception $exception) { + throw new ValidateException('商品规格格式错误'); + } + return $result; + } + + /** + * 格式商品SKU + * @Author:Qinii + * @Date: 2020/9/15 + * @param array $data + * @param int $productId + * @return mixed + */ + public function setAttrValue(array $data, int $productId, int $productType, int $isUpdate = 0) + { + $extension_status = systemConfig('extension_status'); + if ($isUpdate) { + $productAttrValue = app()->make(ProductAttrValueRepository::class)->search(['product_id' => $productId])->select()->toArray(); + $oldSku = $this->detailAttrValue($productAttrValue, null); + } + $price = $stock = $ot_price = $cost = $svip_price = 0; + try { + $update_infos = [ + OperateLogRepository::MERCHANT_INC_PRODUCT_PRICE => '', + OperateLogRepository::MERCHANT_DEC_PRODUCT_PRICE => '', + OperateLogRepository::MERCHANT_INC_PRODUCT_STOCK => '', + OperateLogRepository::MERCHANT_DEC_PRODUCT_STOCK => '', + ]; + foreach ($data['attrValue'] as $value) { + $_svip_price = 0; + $sku = ''; + if (isset($value['detail']) && !empty($value['detail']) && is_array($value['detail'])) + $sku = implode(',', $value['detail']); + + $ot_price_ = $value['price']; + if (isset($value['active_price'])) { + $sprice = $value['active_price'] < 0 ? 0 : $value['active_price']; + } elseif (isset($value['presell_price'])) { + $sprice = $value['presell_price'] < 0 ? 0 : $value['presell_price']; + } elseif (isset($value['assist_price'])) { + $sprice = $value['assist_price'] < 0 ? 0 : $value['assist_price']; + } else { + $ot_price_ = $value['ot_price']; + $sprice = ($value['price'] < 0) ? 0 : $value['price']; + } + if (isset($data['svip_price_type']) && $data['svip_price_type'] == 2) { + $_svip_price = $value['svip_price']; + $svip_price = !$svip_price ? $value['svip_price'] : (($svip_price > $value['svip_price']) ? $value['svip_price'] : $svip_price); + } + + $cost = !$cost ? $value['cost'] : (($cost > $value['cost']) ? $cost : $value['cost']); + $price = !$price ? $sprice : (($price > $sprice) ? $sprice : $price); + $ot_price = !$ot_price ? $ot_price_ : (($ot_price > $ot_price_) ? $ot_price : $ot_price_); + + $unique = $this->setUnique($productId, $sku, $productType); + if (isset($data['type']) && $data['type'] == 2) { + [$cdkey, $cdkeey_stock] = $this->setCdkey($value['cdkey'], $productId); + !$cdkeey_stock ?: $value['stock'] = $cdkeey_stock; + } + $new_price = $value['price'] ? (($value['price'] < 0) ? 0 : $value['price']) : 0; + $new_stock = $value['stock'] ? (($value['stock'] < 0) ? 0 : $value['stock']) : 0; + $array = [ + 'detail' => json_encode($value['detail'] ?? ''), + "bar_code" => $value["bar_code"] ?? '', + "image" => $value["image"] ?? '', + "cost" => $value['cost'] ? (($value['cost'] < 0) ? 0 : $value['cost']) : 0, + "price" => $new_price, + "volume" => isset($value['volume']) ? ($value['volume'] ? (($value['volume'] < 0) ? 0 : $value['volume']) : 0) : 0, + "weight" => isset($value['weight']) ? ($value['weight'] ? (($value['weight'] < 0) ? 0 : $value['weight']) : 0) : 0, + "stock" => $new_stock, + "ot_price" => $value['ot_price'] ? (($value['ot_price'] < 0) ? 0 : $value['ot_price']) : 0, + "extension_one" => $extension_status ? ($value['extension_one'] ?? 0) : 0, + "extension_two" => $extension_status ? ($value['extension_two'] ?? 0) : 0, + "product_id" => $productId, + "type" => 0, + "sku" => $sku, + "unique" => $unique, + 'sales' => $isUpdate ? ($oldSku[$sku]['sales'] ?? 0) : 0, + 'svip_price' => $_svip_price, + ]; + + if (isset($data['type']) && $data['type'] == 2) { + $array['cdkey'] = $cdkey; + } + + $result['attrValue'][] = $array; + $stock = $stock + intval($value['stock']); + + // 组合操作日志数据 + if ($isUpdate && isset($value['unique'])) { + foreach ($productAttrValue as $attrValue) { + if ($attrValue['unique'] == $value['unique']) { + if ($new_price > $attrValue['price']) { + $update_infos[OperateLogRepository::MERCHANT_INC_PRODUCT_PRICE] .= $attrValue['sku'] . '价格增加了' . bcsub($new_price, $attrValue['price'], 2) . ','; + } + if ($new_price < $attrValue['price']) { + $update_infos[OperateLogRepository::MERCHANT_DEC_PRODUCT_PRICE] .= $attrValue['sku'] . '价格增加了' . bcsub($attrValue['price'], $new_price, 2) . ','; + } + if ($new_stock > $attrValue['stock']) { + $update_infos[OperateLogRepository::MERCHANT_INC_PRODUCT_STOCK] .= $attrValue['sku'] . '库存增加了' . ($new_stock - $attrValue['stock']) . ','; + } + if ($new_stock < $attrValue['stock']) { + $update_infos[OperateLogRepository::MERCHANT_DEC_PRODUCT_STOCK] .= $attrValue['sku'] . '库存减少了' . ($attrValue['stock'] - $new_stock) . ','; + } + } + } + $result['update_infos'] = $update_infos; + } + } + $result['data'] = [ + 'price' => $price, + 'stock' => $stock, + 'ot_price' => $ot_price, + 'cost' => $cost, + 'svip_price' => $svip_price, + ]; + + + } catch (\Exception $exception) { + throw new ValidateException('规格错误 :' . $exception->getMessage() . $exception->getFile() . $exception->getLine()); + } + return $result; + } + + public function setCdkey($data, $productId) + { + if (!isset($data['is_type'])) throw new ValidateException('请选择添加卡密'); + $stock = 0; + if ($data['is_type']) { + $stock = count($data['list']); + foreach ($data['list'] as $datum) { + if (!isset($datum['key']) || !$datum['key']) throw new ValidateException('请添加卡密内容'); + $cdkey[] = [ + 'is_type' => $data['is_type'], + 'key' => $datum['key'], + 'pwd' => $datum['pwd'], + 'product_id' => $productId + ]; + } + } else { + $cdkey[] = [ + 'is_type' => $data['is_type'], + 'key' => $data['key'], + 'pwd' => '', + 'product_id' => $productId + ]; + } + return [$cdkey, $stock]; + } + + + /** + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $id + * @param string $sku + * @param int $type + * @return string + */ + public function setUnique(int $id, $sku, int $type) + { + return $unique = substr(md5($sku . $id), 12, 11) . $type; + // $has = (app()->make(ProductAttrValueRepository::class))->merUniqueExists(null, $unique); + // return $has ? false : $unique; + } + + + /** + * TODO 后台管理需要的商品详情 + * @param int $id + * @param int|null $activeId + * @return array|\think\Model|null + * @author Qinii + * @day 2020-11-24 + */ + public function getAdminOneProduct(int $id, ?int $activeId, $conType = 0) + { + $with = ['attr', 'attrValue.productCdkey', 'oldAttrValue', 'merCateId.category', 'storeCategory', 'brand', 'temp', 'seckillActive', + 'content' => function ($query) use ($conType) { + $query->where('type', $conType); + }, + 'merchant' => function ($query) { + $query->with(['typeName', 'categoryName'])->field('mer_id,category_id,type_id,mer_avatar,mer_name,is_trader'); + }, + 'guarantee.templateValue.value', 'getFormName' + ]; + + $data = $this->dao->geTrashedtProduct($id)->with($with)->find(); + + $data['delivery_way'] = empty($data['delivery_way']) ? [2] : explode(',', $data['delivery_way']); + $data['extend'] = empty($data['extend']) ? [] : json_decode($data['extend']); + // $make_order = app()->make(StoreCouponRepository::class); + // $where = [['coupon_id', 'in', $data['give_coupon_ids']]]; + // $data['coupon'] = $make_order->selectWhere($where, 'coupon_id,title')->toArray(); + $$data['coupon']=[]; + $spu_make = app()->make(SpuRepository::class); + + $append = []; + if ($data['product_type'] == 0) { + $append = ['us_status', 'params']; + $activeId = 0; + } + if ($data['product_type'] == 1) { + $activeId = $data->seckillActive->seckill_active_id; + $make = app()->make(SupplyStoreOrderRepository::class); + $append = ['us_status', 'seckill_status']; + } + if ($data['product_type'] == 2) $make = app()->make(ProductPresellSkuRepository::class); + if ($data['product_type'] == 3) $make = app()->make(ProductAssistSkuRepository::class); + if ($data['product_type'] == 4) $make = app()->make(ProductGroupSkuRepository::class); + + $spu_where = ['activity_id' => $activeId, 'product_type' => $data['product_type'], 'product_id' => $id]; + $spu = $spu_make->getSearch($spu_where)->find()->append(['mer_labels_data', 'sys_labels_data']); + $data['star'] = $spu['star'] ?? ''; + $data['mer_labels'] = $spu['mer_labels'] ?? ''; + $data['sys_labels'] = $spu['sys_labels'] ?? ''; + $data['mer_labels_data'] = $spu['mer_labels_data'] ?? []; + $data['sys_labels_data'] = $spu['sys_labels_data'] ?? []; + // 处理表单ID转换 兼容前端显示 + $data['mer_form_id'] = $data['mer_form_id'] ?: null; + + $data->append($append); + $mer_cat = []; + if (isset($data['merCateId'])) { + foreach ($data['merCateId'] as $i) { + $mer_cat[] = $i['mer_cate_id']; + } + } + $data['mer_cate_id'] = $mer_cat; + + foreach ($data['attr'] as $k => $v) { + $data['attr'][$k] = [ + 'value' => $v['attr_name'], + 'detail' => $v['attr_values'] + ]; + } + $attrValue = (in_array($data['product_type'], [3, 4])) ? $data['oldAttrValue'] : $data['attrValue']; + unset($data['oldAttrValue'], $data['attrValue']); + $arr = []; + if (in_array($data['product_type'], [1, 3])) $value_make = app()->make(ProductAttrValueRepository::class); + + foreach ($attrValue as $item) { + if ($data['product_type'] == 1) { + $value = $value_make->getSearch(['sku' => $item['sku'], 'product_id' => $data['old_product_id']])->find(); + if ($value) $old_stock = $value['stock']; + $item['sales'] = $make->skuSalesCount($item['unique']); + } + if ($data['product_type'] == 2) { + $item['presellSku'] = $make->getSearch(['product_presell_id' => $activeId, 'unique' => $item['unique']])->find(); + if (is_null($item['presellSku'])) continue; + } + if ($data['product_type'] == 3) { + $item['assistSku'] = $make->getSearch(['product_assist_id' => $activeId, 'unique' => $item['unique']])->find(); + if (is_null($item['assistSku'])) + continue; + } + if ($data['product_type'] == 4) { + $item['_sku'] = $make->getSearch(['product_group_id' => $activeId, 'unique' => $item['unique']])->find(); + if (is_null($item['_sku'])) + continue; + } + $sku = explode(',', $item['sku']); + $item['old_stock'] = $old_stock ?? $item['stock']; + if (isset($item['productCdkey']) && count($item['productCdkey'])) { + foreach ($item['productCdkey'] as $hasCdkey) { + if ($hasCdkey['is_type']) { + $cdkey['list'][] = $hasCdkey; + } else { + $cdkey['key'] = $hasCdkey['key']; + } + $cdkey['is_type'] = $hasCdkey['is_type']; + } + $item['cdkey'] = $cdkey; + } + unset($item['productCdkey']); + foreach ($sku as $k => $v) { + $item['value' . $k] = $v; + } + $arr[] = $item; + } + $data['attrValue'] = $arr; + $content = $data['content']['content'] ?? ''; + if ($conType) $content = json_decode($content); + unset($data['content']); + $data['content'] = $content; + + // 查找该商品积分抵扣比例 + if (!empty($data['merchant'])) { + $data['merchant']['mer_integral_status'] = merchantConfig($data['merchant']['mer_id'], 'mer_integral_status'); + $data['merchant']['mer_integral_rate'] = merchantConfig($data['merchant']['mer_id'], 'mer_integral_rate'); + } + + // 拼接商品分类 + if (!empty($data['storeCategory'])) { + $cate_name = app()->make(SupplyStoreCategoryRepository::class)->getAllFatherName($data['storeCategory']['store_category_id']); + $data['storeCategory']['cate_name'] = $cate_name; + } + + // 拼接商品推荐商品 + if (!empty($data['good_ids'])) { + $data['goodList'] = $this->dao->getGoodList($data['good_ids'], $data['mer_id'],false); + } + return $data; + } + + /** + * @Author:Qinii + * @Date: 2020/5/18 + * @param $type + * @param int|null $merId + * @return array + */ + public function switchType($type, ?int $merId = 0, $productType = 0) + { +// 1 出售中 2 仓库中 3 已售罄 4 警戒库存 5 回收站 6 待审核 7 审核未通过 + $stock = 0; + if ($merId) $stock = merchantConfig($merId, 'mer_store_stock'); + switch ($type) { + case 1: + $where = ['is_show' => 1, 'status' => 1,]; + break; + case 2: + $where = ['is_show' => 0, 'status' => 1]; + break; + case 3: + $where = ['is_show' => 1, 'stock' => 0, 'status' => 1]; + break; + case 4: + $where = ['stock' => $stock ? $stock : 0, 'status' => 1]; + break; + case 5: + $where = ['soft' => true]; + break; + case 6: + $where = ['status' => 0]; + break; + case 7: + $where = ['status' => -1]; + break; + case 20: + $where = ['status' => 1]; + break; + default: + // $where = ['is_show' => 1, 'status' => 1]; + break; + } + if ($productType == 0) { + $where['product_type'] = $productType; + if (!$merId) $where['is_gift_bag'] = 0; + } + if ($productType == 1) { + $where['product_type'] = $productType; + } + if ($productType == 10) { + $where['is_gift_bag'] = 1; + } + if (!$merId) $where['star'] = ''; + return $where; + } + + /** + * @Author:Qinii + * @Date: 2020/5/18 + * @param int|null $merId + * @return array + */ + public function getFilter(?int $merId, $name = '', $productType = 0) + { + $result = []; + $result[] = [ + 'type' => 1, + 'name' => '出售中' . $name, + 'count' => $this->dao->search($merId, $this->switchType(1, $merId, $productType))->count() + ]; + $result[] = [ + 'type' => 2, + 'name' => '仓库中' . $name, + 'count' => $this->dao->search($merId, $this->switchType(2, $merId, $productType))->count() + ]; + if ($merId) { + $result[] = [ + 'type' => 3, + 'name' => '已售罄' . $name, + 'count' => $this->dao->search($merId, $this->switchType(3, $merId, $productType))->count() + ]; + $result[] = [ + 'type' => 4, + 'name' => '警戒库存', + 'count' => $this->dao->search($merId, $this->switchType(4, $merId, $productType))->count() + ]; + } + $result[] = [ + 'type' => 6, + 'name' => '待审核' . $name, + 'count' => $this->dao->search($merId, $this->switchType(6, $merId, $productType))->count() + ]; + $result[] = [ + 'type' => 7, + 'name' => '审核未通过' . $name, + 'count' => $this->dao->search($merId, $this->switchType(7, $merId, $productType))->count() + ]; + if ($merId) { + $result[] = [ + 'type' => 5, + 'name' => '回收站' . $name, + 'count' => $this->dao->search($merId, $this->switchType(5, $merId, $productType))->count() + ]; + } + return $result; + } + + /** + * TODO 商户商品列表 + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $merId + * @param array $where + * @param int $page + * @param int $limit + * @return array + */ + public function getList(?int $merId, array $where, int $page, int $limit) + { + $query = $this->dao->search($merId, $where)->with(['merCateId.category', 'storeCategory', 'brand']); + $count = $query->count(); + $list = $query->page($page, $limit)->setOption('field', [])->field($this->filed)->select() + ->each(function ($item) { + if (!$item->mer_labels) { + $item->mer_labels = []; + } else { + $item->mer_labels = explode(',', rtrim(ltrim($item->mer_labels, ','), ',')); + } + })->append(['us_status']); + return compact('count', 'list'); + } + + /** + * TODO 商户秒杀商品列表 + * @param int|null $merId + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @author Qinii + * @day 2020-08-04 + */ + public function getSeckillList(?int $merId, array $where, int $page, int $limit) + { + $make = app()->make(SupplyStoreOrderRepository::class); + $query = $this->dao->search($merId, $where)->with(['merCateId.category', 'storeCategory', 'brand', 'attrValue ', 'seckillActive']); + $count = $query->count(); + $list = $query->page($page, $limit)->setOption('field', [])->field($this->filed)->order('sort DESC')->select() + ->each(function ($item) { + if (!$item->mer_labels) { + $item->mer_labels = []; + } else { + $item->mer_labels = explode(',', rtrim(ltrim($item->mer_labels, ','), ',')); + } + })->append(['seckill_status', 'us_status']); + return compact('count', 'list'); + } + + /** + * TODO 平台商品列表 + * @Author:Qinii + * @Date: 2020/5/11 + * @param int $merId + * @param array $where + * @param int $page + * @param int $limit + * @return array + */ + public function getAdminList(?int $merId, array $where, int $page, int $limit) + { + $query = $this->dao->search($merId, $where)->with([ + 'merCateId.category', + 'storeCategory', + 'brand', + 'merchant', + ]); + $count = $query->count(); + $list = $query->page($page, $limit)->setOption('field', [])->field($this->admin_filed)->select() + ->each(function ($item) { + if (!$item->sys_labels) { + $item->sys_labels = []; + } else { + $item->sys_labels = explode(',', rtrim(ltrim($item->sys_labels, ','), ',')); + } + })->append(['us_status']); + return compact('count', 'list'); + } + + /** + * TODO 平台秒杀商品列表 + * @param int|null $merId + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @author Qinii + * @day 2020-08-04 + */ + public function getAdminSeckillList(?int $merId, array $where, int $page, int $limit) + { + $query = $this->dao->search($merId, $where)->with([ + 'merCateId.category', + 'storeCategory', + 'brand', + 'merchant', + 'seckillActive', + 'attrValue', + ]); + $count = $query->count(); + $list = $query->page($page, $limit) + ->field('Product.*,U.star,U.rank,U.sys_labels')->select() + ->each(function ($item) { + if (!$item->sys_labels) { + $item->sys_labels = []; + } else { + $item->sys_labels = explode(',', rtrim(ltrim($item->sys_labels, ','), ',')); + } + })->append(['seckill_status', 'us_status']); + return compact('count', 'list'); + } + + /** + * @Author:Qinii + * @Date: 2020/5/28 + * @param array $where + * @param int $page + * @param int $limit + * @param $userInfo + * @return array + */ + public function getApiSearch($merId, array $where, int $page, int $limit, $userInfo) + { + $where = array_merge($where, $this->dao->productShow()); + //搜索记录 + if (isset($where['keyword']) && !empty($where['keyword'])) + app()->make(UserVisitRepository::class)->searchProduct( + $userInfo ? $userInfo['uid'] : 0, + $where['keyword'], + (int)($where['mer_id'] ?? 0) + ); + $query = $this->dao->search($merId, $where)->with(['merchant', 'issetCoupon']); + $count = $query->count(); + $list = $query->page($page, $limit)->setOption('field', [])->field($this->admin_filed)->select(); + $append[] = 'max_extension'; + if ($this->getUserIsPromoter($userInfo)) $list->append($append); + return compact('count', 'list'); + } + + /** + * TODO 秒杀列表 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @author Qinii + * @day 2020-08-04 + */ + public function getApiSeckill(array $where, int $page, int $limit) + { + $count = 0; + $list = []; + return compact('count', 'list'); + + // $field = 'Product.product_id,Product.mer_id,is_new,U.keyword,brand_id,U.image,U.product_type,U.store_name,U.sort,U.rank,star,rate,reply_count,sales,U.price,cost,Product.ot_price,stock,extension_type,care_count,unit_name,U.create_time'; + // $make = app()->make(StoreOrderRepository::class); + // $res = app()->make(StoreSeckillTimeRepository::class)->getBginTime($where); + + + // if ($res) { + // $where = [ + // 'start_time' => $res['start_time'], + // 'end_time' => $res['end_time'], + // 'day' => date('Y-m-d', time()), + // 'star' => '', + // 'mer_id' => $where['mer_id'] + // ]; + // $h = date('H', time()); + + // if ($h < $where['start_time']) { + // $skill_status = 0; + // } else if ($h < $where['end_time']) { + // $skill_status = 1; + // } else { + // $skill_status = -1; + // } + + // $query = $this->dao->seckillSearch($where)->with(['seckillActive']); + // $count = $query->count(); + // $list = $query->page($page, $limit)->setOption('field', [])->field($field)->select() + // ->each(function ($item) use ($make, $skill_status) { + // $item['sales'] = $make->seckillOrderCounut($item['product_id']); + // $item['stop'] = $item->end_time; + // $item['skill_status'] = $skill_status; + // return $item; + // }); + // } + // return compact('count', 'list'); + } + + /** + * TODO 平台礼包列表 + * @param array $where + * @param int $page + * @param int $limit + * @return array + * @author Qinii + * @day 2020-06-01 + */ + public function getBagList(array $where, int $page, int $limit) + { + $query = $this->dao->search(null, $where)->with(['merCateId.category', 'storeCategory', 'brand', 'merchant' => function ($query) { + $query->field('mer_id,mer_avatar,mer_name,product_score,service_score,postage_score,status,care_count,is_trader'); + }]); + $count = $query->count($this->dao->getPk()); + $list = $query->page($page, $limit)->setOption('field', [])->field($this->filed)->select(); + + return compact('count', 'list'); + } + + /** + * @Author:Qinii + * @Date: 2020/5/28 + * @param array $where + * @return mixed + */ + public function getBrandByCategory(array $where) + { + $mer_id = $where['mer_id'] ? $where['mer_id'] : null; + unset($where['mer_id']); + $query = $this->dao->search($mer_id, $where); + return $query->group('brand_id')->column('brand_id'); + } + + public function getCateIdByCategory(array $where) + { + $mer_id = $where['mer_id'] ? $where['mer_id'] : null; + unset($where['mer_id']); + $query = $this->dao->search($mer_id, $where); + return $query->group('cate_id')->column('cate_id'); + } + + /** + * api 获取商品详情 + * @Author:Qinii + * @Date: 2020/5/30 + * @param $id + * @param $userInfo + */ + public function detail(int $id, $userInfo) + { + $where = [ + 'is_show' => 1, + 'status' => 1, + 'is_used' => 1, + 'mer_status' => 1, + 'product_id' => $id + ]; + return $this->apiProductDetail($where, 0, null, $userInfo); + } + + + /** + * TODO api秒杀商品详情 + * @param int $id + * @author Qinii + * @day 2020-08-05 + */ + public function seckillDetail(int $id, $userInfo) + { + $where = $this->seckillShow(); + $where['product_id'] = $id; + return $this->apiProductDetail($where, 1, null, $userInfo); + } + + /** + * TODO 移动端商品详情 + * @param $productId + * @param $cache_unique + * @return array|mixed + * @author Qinii + * @day 2023/8/23 + */ + public function getContent($productId) + { + $key = '_get_content' . $productId; + $res = Cache::get($key); + if ($res) return json_decode($res, true); + $res = app()->make(ProductContentRepository::class)->getWhere(['product_id' => $productId]); + if ($res['content'] && $res['type'] == 1) { + $res['content'] = json_decode($res['content']); + } + Cache::set($key, json_encode($res), 1500); + return $res; + } + + + /** + * TODO 移动端商品详情查询店铺信息 + * @param $merId + * @param $good_ids + * @param $uid + * @return array|mixed + * @author Qinii + * @day 2023/8/23 + */ + public function getMerchant($merId, $good_ids, $uid) + { + $merchantRepository = app()->make(SupplyRepository::class); + $care = false; + if ($uid) $care = $merchantRepository->getCareByUser($merId, $uid); + $merchant = $merchantRepository->search(['mer_id' => $merId])->with(['type_name']) + ->field('mer_id,mer_name,real_name,mer_address,mer_keyword,mer_avatar,mer_banner,mini_banner,product_score,service_score,postage_score,service_phone,care_count,type_id')->find() + ->append(['isset_certificate', 'services_type'])->toArray(); + $merchant['top_banner'] = merchantConfig($merId, 'mer_pc_top'); + $merchant['care'] = $care; +// $merchant['recommend'] = $this->getRecommend($productId, $merId); + $merchant['recommend'] = $this->dao->getGoodList($good_ids,$merId); + + return $merchant; + } + + /** + * 获取商品店铺推荐 + * @param int $productId + * @param int $uid + * @return array|mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGoodList(int $productId, int $uid) + { + // 查询商品详情 + $product = $this->dao->get($productId); + if (empty($product)) { + throw new ValidateException('商品异常'); + } + return $this->getMerchant($product['mer_id'], $product['good_ids'], $uid); + } + + public function apiProductDetail($where, int $productType, ?int $activityId, $userInfo = null) + { + $field = 'is_show,product_id,mer_id,image,slider_image,store_name,store_info,unit_name,price,cost,ot_price,stock,sales,video_link,product_type,extension_type,old_product_id,rate,guarantee_template_id,temp_id,once_max_count,pay_limit,once_min_count,integral_rate,delivery_way,delivery_free,type,cate_id,svip_price_type,svip_price,mer_svip_status,mer_form_id'; + $with = [ + 'attr', + 'attrValue', + ]; + $append = ['topReply']; + switch ($productType) { + case 1: + $with['seckillActive'] = function ($query) { + $query->field('start_day,end_day,start_time,end_time,product_id,once_pay_count,all_pay_count'); + }; + $append[] = 'seckill_status'; + break; + case 2: + break; + case 3: + //notbreak; + case 4: + $with[] = 'oldAttrValue'; + break; + default: + if ($userInfo && $this->getUserIsPromoter($userInfo) && $productType == 0) { + $append[] = 'max_extension'; + $append[] = 'min_extension'; + } + $append[] = 'max_integral'; + $append[] = 'show_svip_info'; + break; + } + $product = $this->dao->getWhere($where, $field, $with); + if (!$product) throw new ValidateException('商品已下架'); + if ($productType == 1) { + $result = $this->getSeckillAttrValue($product['attrValue'], $product['old_product_id']); + $product['attrValue'] = $result['item']; + $product['stock'] = $result['stock']; + $product['stop'] = strtotime(date('Y-m-d', time()) . $product['seckillActive']['end_time'] . ':00:00'); + $product['sales'] = app()->make(SupplyStoreOrderRepository::class)->seckillOrderCounut($where['product_id']); +// $product['quota'] = $this->seckillStock($where['product_id']); + $product['once_pay_count'] = $product['seckillActive']['once_pay_count']; + $product['all_pay_count'] = $product['seckillActive']['all_pay_count']; + unset($product['seckillActive']); + } + + $isRelation = false; + if ($userInfo) { + $isRelation = app()->make(UserRelationRepository::class)->getUserRelation([ + 'type_id' => $activityId ?? $where['product_id'], + 'type' => $productType + ], + $userInfo['uid'] + ); + } + + if (systemConfig('sys_reply_status')) { + $product['replayData'] = app()->make(ProductReplyRepository::class)->getReplyRate($product['product_id']); + } + $attr = $this->detailAttr($product['attr']); + $attrValue = (in_array($product['product_type'], [3, 4])) ? $product['oldAttrValue'] : $product['attrValue']; + $sku = $this->detailAttrValue($attrValue, $userInfo, $productType, $activityId); + unset($product['attr'], $product['attrValue'], $product['oldAttrValue']); + if (count($attr) > 1) { + $firstSku = []; + foreach ($attr as $item) { + $firstSku[] = $item['attr_values'][0]; + } + $firstSkuKey = implode(',', $firstSku); + if (isset($sku[$firstSkuKey])) { + $sku = array_merge([$firstSkuKey => $sku[$firstSkuKey]], $sku); + } + } + $product = $product->append($append); + $product['attr'] = $attr; + $product['sku'] = $sku; + $product['isRelation'] = $isRelation; + return $product; + } + + /** + * TODO 商品详情部分缓存 + * @param $productId + * @param $product + * @param $activityId + * @param $uid + * @return mixed + * @author Qinii + * @day 2023/8/24 + */ + public function getProductShow($productId, $product, $activityId, $uid) + { + if (empty($product)) { + $productData = $this->dao->get($productId); + if (!$productData) throw new InvalidArgumentException('数据不存在'); + $product = $productData->toArray(); + } + ksort($product); + $cache_unique = 'get_product_show_' . $productId . '_' . md5(json_encode($product)); + if (!env('APP_DEBUG', false)) { + $res = Cache::get($cache_unique); + } + if (!isset($res) || !$res) { + $productType = $product['product_type']; + $res['content'] = $this->getContent($product['product_id']); + $res['temp'] =0;// app()->make(ShippingTemplateRepository::class)->getSearch([])->where('shipping_template_id', $product['temp_id'])->find(); + if (in_array($product['product_type'], [0, 2])) { + $product_id = $product['product_id']; + } else { + $product_id = $product['old_product_id']; + } + $res['params'] = app()->make(SupplyParameterValueRepository::class)->getSearch([])->where('product_id', $product_id)->order('parameter_value_id ASC')->select(); + $guaranteeTemplateRepository = app()->make(GuaranteeTemplateRepository::class); + $guaranteeTemplate = $guaranteeTemplateRepository->getSearch([])->where('guarantee_template_id', $product['guarantee_template_id'])->where('status', 1)->where('is_del', 0)->find(); + if ($guaranteeTemplate) { + $guaranteeValueRepository = app()->make(GuaranteeValueRepository::class); + $guaranteeRepository = app()->make(GuaranteeRepository::class); + $guarantee_id = $guaranteeValueRepository->getSearch([])->where('guarantee_template_id', $guaranteeTemplate['guarantee_template_id'])->column('guarantee_id'); + $res['guarantee'] = $guaranteeRepository->getSearch([])->where('guarantee_id', 'in', $guarantee_id)->where('status', 1)->where('is_del', 0)->select()->toArray(); + } + $spu = app()->make(SpuRepository::class)->getSpuData($activityId ?: $product['product_id'], $productType, 0); + $res['spu_id'] = $spu['spu_id']; + // if (systemConfig('community_status')) { + // $res['community'] = app()->make(CommunityRepository::class)->getDataBySpu($spu['spu_id']); + // } + //热卖排行 + if (systemConfig('hot_ranking_switch') && $res['spu_id']) { + $hot = $this->getHotRanking($res['spu_id'], $product['cate_id']); + $res['top_name'] = $hot['top_name'] ?? ''; + $res['top_num'] = $hot['top_num'] ?? 0; + $res['top_pid'] = $hot['top_pid'] ?? 0; + } + //活动氛围图 + // if (in_array($product['product_type'], [0, 2, 4])) { + // $storeActivityRepository = app()->make(StoreActivityRepository::class); + // $active = $storeActivityRepository->getActivityBySpu(StoreActivityRepository::ACTIVITY_TYPE_ATMOSPHERE, $res['spu_id'], $product['cate_id'], $product['mer_id'], $spu['sys_labels']); + // if (!empty($active)) $res['atmosphere_pic'] = $active['pic']; + // } + Cache::tag('get_product')->set($cache_unique, json_encode($res), 1500); + } else { + $res = json_decode($res, true); + } + $res['merchant'] = $this->getMerchant($product['mer_id'], $product['good_ids'] ?? [], $uid); + return $res; + } + + /** + * TODO 热卖排行 + * @param int $spuId + * @param int $cateId + * @return array + * @author Qinii + */ + public function getHotRanking(int $spuId, int $cateId) + { + $cache_unique = md5('get_hot_ranking_' . json_encode([$spuId, $cateId])); + $res = Cache::get($cache_unique); + if ($res) return json_decode($res, true); + $data = []; + //热卖排行 + $lv = systemConfig('hot_ranking_lv') ?: 0; + $categoryMake = app()->make(SupplyStoreCategoryRepository::class); + $cate = $categoryMake->getWhere(['store_category_id' => $cateId]); + if ($lv != 2 && $cate) $cateId = $lv == 1 ? $cate->pathIds[2] : $cate->pathIds[1]; + $RedisCacheService = app()->make(RedisCacheService::class); + $prefix = env('QUEUE_NAME', 'merchant') . '_hot_ranking_'; + $key = ($prefix . 'top_item_' . $cateId . '_' . $spuId); + $k1 = $RedisCacheService->keys($key); + if ($k1) { + $top = $RedisCacheService->handler()->get($key); + $top = json_decode($top); + $data['top_name'] = $top[0]; + $data['top_num'] = $top[1]; + $data['top_pid'] = $cateId; + } + Cache::set($cache_unique, json_encode($data), 1500); + return $data; + } + + /** + * TODO 商户下的推荐 + * @param $productId + * @param $merId + * @return array + * @author Qinii + * @day 12/7/21 + */ + public function getRecommend($productId, $merId) + { + $cache_unique = 'get_product_recommend_' . $productId . '_' . $merId; + $res = Cache::get($cache_unique); + if ($res) return json_decode($res, true); + + $field = 'mer_id,product_id,store_name,image,price,is_show,status,is_gift_bag,is_good,sales,create_time'; + $make = app()->make(ProductCateRepository::class); + $product_id = []; + if ($productId) { + $catId = $make->getSearch(['product_id' => $productId])->column('mer_cate_id'); + $product_id = $make->getSearch([])->whereIn('mer_cate_id', $catId)->column('product_id'); + } + $res = $this->dao->getSearch([]) + ->where($this->dao->productShow()) + ->when($productId, function ($query) use ($productId) { + $query->where('product_id', '<>', $productId); + }) + ->when($product_id, function ($query) use ($product_id) { + $query->whereIn('product_id', $product_id); + }) + ->where('mer_id', $merId)->setOption('field', [])->field($field)->limit(3)->select(); + $data = $res ? $res->toArray() : []; + $count = count($res); + if ($count < 3) { + $productIds[] = $productId; + $res = $this->dao->getSearch([]) + ->where($this->dao->productShow()) + ->whereNotIn('product_id', $productIds) + ->where('is_good', 1) + ->where('mer_id', $merId) + ->field('mer_id,product_id,store_name,image,price,is_show,status,is_gift_bag,is_good,sales,sort,create_time') + ->order('sort DESC,create_time DESC') + ->limit((3 - $count)) + ->select()->toArray(); + $data = array_merge($data, $res); + } + Cache::tag('get_product')->set($cache_unique, json_encode($data), 1500); + return $data; + } + + + /** + * TODO 单商品属性 + * @param $data + * @return array + * @author Qinii + * @day 2020-08-05 + */ + public function detailAttr($data, $preview = 0, $user = null) + { + $attr = []; + foreach ($data as $key => $item) { + if ($item instanceof Arrayable) { + $attr[$key] = $item->toArray(); + } + $arr = []; + if ($preview) { + $item['attr_values'] = explode('-!-', $item['attr_values']); + $attr[$key]['attr_values'] = $item['attr_values']; + } + $values = $item['attr_values']; + foreach ($values as $i => $value) { + $arr[] = [ + 'attr' => $value, + 'check' => false + ]; + } + $attr[$key]['product_id'] = $item['product_id']; + $attr[$key]['attr_name'] = $item['attr_name']; + $attr[$key]['attr_value'] = $arr; + $attr[$key]['attr_values'] = $values; + } + return $attr; + } + + /** + * TODO 获取秒杀商品的库存数 + * @param array $data + * @param int $oldProductId + * @return array + * @author Qinii + * @day 2020-11-12 + */ + public function getSeckillAttrValue($data, $oldProductId) + { + /** + * 秒杀商品限购数量 + * 原商品库存 > 限购数 + * 销量 = 订单总数 - 退款退货 - (未发货且仅退款) + * 限购数 = 限购数 - 销量 + * 原商品库存 < 限购数 + * 限购数 = 原商品库存 + */ + $productAttrValueRepository = app()->make(ProductAttrValueRepository::class); + $storeOrderProductRepository = app()->make(SupplyStoreOrderProductRepository::class); + $orderCount = $storeOrderProductRepository->getSearch([]) + ->where('product_sku', 'in', array_column($data->toArray(), 'unique')) + ->where('is_refund', 'in', '0,1,2') + ->whereDay('create_time') + ->column('refund_num', 'product_sku'); + + $stock = 0; + $item = []; + $oldAttrValue = $productAttrValueRepository->search(['product_id' => $oldProductId])->select(); + foreach ($data as $value) { + foreach ($oldAttrValue as $attr) { + if ($value['sku'] == $attr['sku'] && ($attr['stock'] > $value['stock']) && isset($value['unique'])) { + $value['stock'] = $value['stock'] - ($orderCount[$value['unique']] ?? 0); + } + } + $stock = $stock + $value['stock']; + $item[] = $value; + } + + return compact('item', 'stock'); + } + + /** + * TODO 单商品sku + * @param $data + * @param $userInfo + * @return array + * @author Qinii + * @day 2020-08-05 + */ + public function detailAttrValue($data, $userInfo, $productType = 0, $artiveId = null, $svipInfo = []) + { + $sku = []; + $make_presll = app()->make(ProductPresellSkuRepository::class); + $make_assist = app()->make(ProductAssistSkuRepository::class); + $make_group = app()->make(ProductGroupSkuRepository::class); + foreach ($data as $value) { + $_value = [ + 'sku' => $value['sku'], + 'price' => $value['price'], + 'stock' => $value['stock'], + 'image' => $value['image'], + 'weight' => $value['weight'], + 'volume' => $value['volume'], + 'sales' => $value['sales'], + 'unique' => $value['unique'], + 'bar_code' => $value['bar_code'], + ]; + if ($productType == 0) { + $_value['ot_price'] = $value['ot_price']; + $_value['svip_price'] = $value['svip_price']; + } + if ($productType == 2) { + $_sku = $make_presll->getSearch(['product_presell_id' => $artiveId, 'unique' => $value['unique']])->find(); + if (!$_sku) continue; + $_value['price'] = $_sku['presell_price']; + $_value['stock'] = $_sku['stock']; + $_value['down_price'] = $_sku['down_price']; + } + //助力 + if ($productType == 3) { + $_sku = $make_assist->getSearch(['product_assist_id' => $artiveId, 'unique' => $value['unique']])->find(); + if (!$_sku) continue; + $_value['price'] = $_sku['assist_price']; + $_value['stock'] = $_sku['stock']; + } + //拼团 + if ($productType == 4) { + $_sku = $make_group->getSearch(['product_group_id' => $artiveId, 'unique' => $value['unique']])->find(); + if (!$_sku) continue; + $_value['price'] = $_sku['active_price']; + $_value['stock'] = $_sku['stock']; + } + //推广员 + if ($this->getUserIsPromoter($userInfo)) { + $_value['extension_one'] = $value->bc_extension_one; + $_value['extension_two'] = $value->bc_extension_two; + } + $sku[$value['sku']] = $_value; + } + return $sku; + } + + + /** + * TODO 秒杀商品库存检测 + * @param int $productId + * @return bool|int + * @author Qinii + * @day 2020-08-05 + */ + public function seckillStock(int $productId) + { + $product = $this->dao->getWhere(['product_id' => $productId], '*', ['attrValue']); + $count = app()->make(SupplyStoreOrderRepository::class)->seckillOrderCounut($productId); + if ($product['stock'] > $count) { + $make = app()->make(ProductAttrValueRepository::class); + foreach ($product['attrValue'] as $item) { + $attr = [ + ['sku', '=', $item['sku']], + ['product_id', '=', $product['old_product_id']], + ['stock', '>', 0], + ]; + if ($make->getWhereCount($attr)) return true; + } + } + return false; + } + + + /** + * @Author:Qinii + * @Date: 2020/5/30 + * @param $userInfo + * @return bool + */ + public function getUserIsPromoter($userInfo) + { + return (isset($userInfo['is_promoter']) && $userInfo['is_promoter'] && systemConfig('extension_status')) ? true : false; + } + + /** + * @Author:Qinii + * @Date: 2020/5/30 + * @param $userInfo + * @param int|null $merId + * @param $page + * @param $limit + * @return array + */ + public function recommend($userInfo, ?int $merId, $page, $limit) + { + $where = ['order' => 'sales']; + if (!is_null($userInfo)) { + $cate_ids = app()->make(UserVisitRepository::class)->getRecommend($userInfo['uid']); + if ($cate_ids) $where = ['cate_ids' => $cate_ids]; + } + $where = array_merge($where, $this->switchType(1, $merId, 0), $this->dao->productShow()); + $query = $this->dao->search($merId, $where); + $count = $query->count(); + $list = $query->page($page, $limit)->setOption('field', [])->with(['issetCoupon', 'merchant'])->select(); + + return compact('count', 'list'); + } + + /** + * 检测是否有效 + * @Author:Qinii + * @Date: 2020/6/1 + * @param $id + * @return mixed + */ + public function getOne($id) + { + $data = ($this->dao->getWhere([$this->dao->getPk() => $id])); + if (!is_null($data) && $data->check()) return $data; + return false; + } + + /** + * TODO 上下架 / 显示 + * @param $id + * @param $status + * @author Qinii + * @day 2022/11/12 + */ + public function switchShow($id, $status, $field, $merId = 0, $admin_info = []) + { + $where['product_id'] = $id; + if ($merId) $where['mer_id'] = $merId; + $product = $this->dao->getWhere($where); + if (!$product) throw new ValidateException('数据不存在'); + if ($status == 1 && $product['product_type'] == 2) + throw new ValidateException('商品正在参与预售活动'); + if ($status == 1 && $product['product_type'] == 3) + throw new ValidateException('商品正在参与助力活动'); + $this->dao->update($id, [$field => $status]); + app()->make(SpuRepository::class)->changeStatus($id, $product->product_type); + + //记录操作日志 + if (!empty($admin_info)) { + $this->addChangeStatusLog($field, $status, $admin_info, $product); + } + } + + public function batchSwitchShow($id, $status, $field, $merId = 0, $admin_info = []) + { + $where['product_id'] = $id; + if ($merId) $where['mer_id'] = $merId; + $products = $this->dao->getSearch([])->where('product_id', 'in', $id)->select(); + if (!$products) + throw new ValidateException('数据不存在'); + foreach ($products as $product) { + $product_type = $product['product_type']; + if ($merId && $product['mer_id'] !== $merId) + throw new ValidateException('商品不属于您'); + if ($status == 1 && $product['product_type'] == 2) + throw new ValidateException('ID:' . $product->product_id . ' 商品正在参与预售活动'); + if ($status == 1 && $product['product_type'] == 3) + throw new ValidateException('ID:' . $product->product_id . ' 商品正在参与助力活动'); + } + $this->dao->updates($id, [$field => $status]); + $operate_data = []; + if (!empty($admin_info)) { + $operate_data = [ + 'field' => $field, + 'status' => $status, + 'admin_info' => $admin_info, + ]; + } + Queue::push(ChangeSupplySpuStatusJob::class, ['id' => $id, 'product_type' => $product_type, 'operate_data' => $operate_data]); + } + + /** + * TODO 商品审核 + * @param $id + * @param $data + * @author Qinii + * @day 2022/11/14 + */ + public function switchStatus($id, $data, $admin_info = []) + { + $product = $this->getSearch([])->find($id); + $this->dao->update($id, $data); + $status = $data['status']; + $type = self::NOTIC_MSG[$data['status']][$product['product_type']]; + $message = '您有1个' . ($product['product_type'] ? '秒杀商品' : '商品') . self::NOTIC_MSG[$data['status']]['msg']; + SwooleTaskService::merchant('notice', [ + 'type' => $type, + 'data' => [ + 'title' => $status == -2 ? '下架提醒' : '审核结果', + 'message' => $message, + 'id' => $product['product_id'] + ] + ], $product['mer_id']); + app()->make(SpuRepository::class)->changeStatus($id, $product->product_type); + + //记录操作日志 + if (!empty($admin_info)) { + $this->addChangeStatusLog('status', $status, $admin_info, $product); + } + + } + + /** + * TODO 审核操作 + * @param array $id + * @param array $data + * @param $product_type + * @author Qinii + * @day 2022/9/6 + */ + public function batchSwitchStatus(array $id, array $data, $admin_info = []) + { + $productData = $this->getSearch([])->where('product_id', 'in', $id)->select(); + foreach ($productData as $product) { + $product_type = $product['product_type']; + $type = self::NOTIC_MSG[$data['status']][$product['product_type']]; + $message = '您有1个' . ($product['product_type'] ? '秒杀商品' : '商品') . self::NOTIC_MSG[$data['status']]['msg']; + SwooleTaskService::merchant('notice', [ + 'type' => $type, + 'data' => [ + 'title' => $data['status'] == -2 ? '下架提醒' : '审核结果', + 'message' => $message, + 'id' => $product['product_id'] + ] + ], $product['mer_id']); + } + $this->dao->updates($id, $data); + $operate_data = []; + if (!empty($admin_info)) { + $operate_data = [ + 'field' => 'status', + 'status' => $data['status'], + 'admin_info' => $admin_info, + ]; + } + Queue(ChangeSupplySpuStatusJob::class, ['id' => $id, 'product_type' => $product_type, 'operate_data' => $operate_data]); + event('product.status', compact('id', 'data')); + } + + + public function wxQrCode(int $productId, int $productType, User $user) + { + $name = md5('pwx' . $productId . $productType . $user->uid . $user['is_promoter'] . date('Ymd')) . '.jpg'; + $make = app()->make(QrcodeService::class); + $link = ''; + switch ($productType) { + case 0: //普通商品 + $link = '/pages/goods_details/index'; + break; + case 1: //秒杀商品 + $link = '/pages/activity/goods_seckill_details/index'; + break; + case 2: //预售商品 + $link = '/pages/activity/presell_details/index'; + break; + case 3: //助力商品 + $link = 'pages/activity/assist_detail/index'; + break; + case 4: //拼团商品 + $link = '/pages/activity/combination_details/index'; + break; + case 40: //拼团商品2 + $link = '/pages/activity/combination_status/index'; + break; + default: + return false; + } + $link = $link . '?id=' . $productId . '&spid=' . $user['uid']; + $key = 'p' . $productType . '_' . $productId . '_' . $user['uid']; + return $make->getWechatQrcodePath($name, $link, false, $key); + } + + public function routineQrCode(int $productId, int $productType, User $user) + { + //小程序 + $name = md5('sprt' . $productId . $productType . $user->uid . $user['is_promoter'] . date('Ymd')) . '.jpg'; + $make = app()->make(QrcodeService::class); + $params = 'id=' . $productId . '&spid=' . $user['uid']; + $link = ''; + switch ($productType) { + case 0: //普通商品 + $link = 'pages/goods_details/index'; + break; + case 1: //秒杀商品 + $link = 'pages/activity/goods_seckill_details/index'; + break; + case 2: //预售商品 + $link = 'pages/activity/presell_details/index'; + break; + case 4: //拼团商品 + $link = 'pages/activity/combination_details/index'; + break; + case 40: //拼团商品2 + $link = 'pages/activity/combination_status/index'; + break; + } + + return $make->getRoutineQrcodePath($name, $link, $params); + } + + /** + * TODO 礼包是否超过数量限制 + * @param $merId + * @return bool + * @author Qinii + * @day 2020-06-25 + */ + public function checkMerchantBagNumber($merId) + { + $where = ['is_gift_bag' => 1]; + $promoter_bag_number = systemConfig('max_bag_number'); + $count = $this->dao->search($merId, $where)->count(); + if (is_null($promoter_bag_number) || ($promoter_bag_number > $count)) return true; + return false; + } + + public function orderProductIncStock($order, $cart, $productNum = null) + { + $productNum = $productNum ?? $cart['product_num']; + Db::transaction(function () use ($order, $cart, $productNum) { + $productAttrValueRepository = app()->make(ProductAttrValueRepository::class); + if ($cart['product_type'] == '1') { + $oldId = $cart['cart_info']['product']['old_product_id']; + $productAttrValueRepository->incSkuStock($oldId, $cart['cart_info']['productAttr']['sku'], $productNum); + $this->dao->incStock($oldId, $productNum); + $this->dao->descSales($cart['cart_info']['product']['product_id'], $productNum); + } else if ($cart['product_type'] == '2') { + $presellSku = app()->make(ProductPresellSkuRepository::class); + $presellSku->incStock($cart['cart_info']['productPresellAttr']['product_presell_id'], $cart['cart_info']['productPresellAttr']['unique'], $productNum); + $productAttrValueRepository->incStock($cart['product_id'], $cart['cart_info']['productAttr']['unique'], $productNum); + $this->dao->incStock($cart['product_id'], $productNum); + } else if ($cart['product_type'] == '3') { + app()->make(ProductAssistSkuRepository::class)->incStock($cart['cart_info']['productAssistAttr']['product_assist_id'], $cart['cart_info']['productAssistAttr']['unique'], $productNum); + $productAttrValueRepository->incStock($cart['cart_info']['product']['old_product_id'], $cart['cart_info']['productAttr']['unique'], $productNum); + $this->dao->incStock($cart['cart_info']['product']['old_product_id'], $productNum); + } else if ($cart['product_type'] == '4') { + app()->make(ProductGroupSkuRepository::class)->incStock($cart['cart_info']['activeSku']['product_group_id'], $cart['cart_info']['activeSku']['unique'], $productNum); + $this->dao->incStock($cart['cart_info']['product']['old_product_id'], $productNum); + $productAttrValueRepository->incStock($cart['cart_info']['product']['old_product_id'], $cart['cart_info']['productAttr']['unique'], $productNum); + } else { + if (isset($cart['cart_info']['product']['old_product_id']) && $cart['cart_info']['product']['old_product_id'] > 0) { + $oldId = $cart['cart_info']['product']['old_product_id']; + $productAttrValueRepository->incSkuStock($oldId, $cart['cart_info']['productAttr']['sku'], $productNum); + $this->dao->incStock($oldId, $productNum); + } else { + $productAttrValueRepository->incStock($cart['product_id'], $cart['cart_info']['productAttr']['unique'], $productNum); + $this->dao->incStock($cart['product_id'], $productNum); + } + if ($cart->integral > 0) { + $totalIntegral = bcmul($productNum, $cart->integral, 0); + $this->dao->descIntegral($cart->product_id, $totalIntegral, bcmul(bcdiv($totalIntegral, $order->integral, 2), $order->integral_price, 2)); + } + } + }); + } + + + public function fictiForm(int $id) + { + $form = Elm::createForm(Route::buildUrl('systemStoreProductAddFicti', ['id' => $id])->build()); + $res = $this->dao->getWhere(['product_id' => $id], 'ficti,sales'); + $form->setRule([ + Elm::input('number', '现有已售数量:', $res['ficti'])->readonly(true), + Elm::radio('type', '修改类型:', 1) + ->setOptions([ + ['value' => 1, 'label' => '增加'], + ['value' => 2, 'label' => '减少'], + ]), + Elm::number('ficti', '修改已售数量:', 0), + ]); + return $form->setTitle('修改已售数量'); + } + + /** + * TODO 普通商品加入购物车检测 + * @param int $prodcutId + * @param string $unique + * @param int $cartNum + * @author Qinii + * @day 2020-10-20 + */ + public function cartCheck(array $data, $userInfo) + { + $cart = null; + $where = $this->dao->productShow(); + $where['product_id'] = $data['product_id']; + unset($where['is_gift_bag']); + $product = $this->dao->search(null, $where)->find(); + + if (!$product) throw new ValidateException('商品已下架'); + if ($product['once_min_count'] > 0 && $product['once_min_count'] > $data['cart_num']) + throw new ValidateException('[低于起购数:' . $product['once_min_count'] . ']' . mb_substr($product['store_name'], 0, 10) . '...'); + if ($product['pay_limit'] == 1 && $product['once_max_count'] < $data['cart_num']) + throw new ValidateException('[超出单次限购数:' . $product['once_max_count'] . ']' . mb_substr($product['store_name'], 0, 10) . '...'); + if ($product['pay_limit'] == 2) { + //如果长期限购 + //已购买数量 + $storeOrderRepository = app()->make(SupplyStoreOrderRepository::class); + $count = $storeOrderRepository->getMaxCountNumber($userInfo->uid, $product['product_id']); + if (($data['cart_num'] + $count) > $product['once_max_count']) + throw new ValidateException('[超出限购总数:' . $product['once_max_count'] . ']' . mb_substr($product['store_name'], 0, 10) . '...'); + } + if ($product['type'] && !$data['is_new']) throw new ValidateException('虚拟商品不可加入购物车'); + $value_make = app()->make(ProductAttrValueRepository::class); + $sku = $value_make->getOptionByUnique($data['product_attr_unique']); + if (!$sku) throw new ValidateException('SKU不存在'); + //分销礼包 + if ($product['is_gift_bag']) { + if (!systemConfig('extension_status')) throw new ValidateException('分销功能未开启'); + if (!$data['is_new']) throw new ValidateException('礼包商品不可加入购物车'); + if ($data['cart_num'] !== 1) throw new ValidateException('礼包商品只能购买一个'); + if ($userInfo->is_promoter) throw new ValidateException('您已经是分销员了'); + } + //立即购买 限购 + if ($data['is_new']) { + $cart_num = $data['cart_num']; + } else { + //加入购物车 + //购物车现有 + $_num = $this->productOnceCountCart($where['product_id'], $data['product_attr_unique'], $userInfo->uid); + $cart_num = $_num + $data['cart_num']; + } + if ($sku['stock'] < $cart_num) throw new ValidateException('库存不足'); + //添加购物车 + if (!$data['is_new']) { + $cart = app()->make(SupplyStoreCartRepository::class)->getCartByProductSku($data['product_attr_unique'], $userInfo->uid); + } + + return compact('product', 'sku', 'cart'); + } + + /** + * TODO 购物车单商品数量 + * @param $productId + * @param $uid + * @param $num + * @author Qinii + * @day 5/26/21 + */ + public function productOnceCountCart($productId, $product_attr_unique, $uid) + { + $make = app()->make(SupplyStoreCartRepository::class); + $where = [ + 'is_pay' => 0, + 'is_del' => 0, + 'is_new' => 0, + 'is_fail' => 0, + 'product_type' => 0, + 'product_id' => $productId, + 'uid' => $uid, + 'product_attr_unique' => $product_attr_unique, + ]; + $cart_num = $make->getSearch($where)->sum('cart_num'); + return $cart_num; + } + + /** + * TODO 秒杀商品加入购物车检测 + * @param array $data + * @param int $userInfo + * @return array + * @author Qinii + * @day 2020-10-21 + */ + public function cartSeckillCheck(array $data, $userInfo) + { + if ($data['is_new'] !== 1) throw new ValidateException('秒杀商品不能加入购物车'); +// if ($data['cart_num'] !== 1) throw new ValidateException('秒杀商品只能购买一个'); + + $where = $this->dao->seckillShow(); + $where['product_id'] = $data['product_id']; + $product = $this->dao->search(null, $where)->find(); + if (!$product) throw new ValidateException('商品已下架'); + $storeOrderRepository = app()->make(SupplyStoreOrderRepository::class); + if (!$storeOrderRepository->getDayPayCount($userInfo->uid, $product['product_id'], $data['cart_num'])) + throw new ValidateException('本次活动您购买数量已达到上限'); + if (!$storeOrderRepository->getPayCount($userInfo->uid, $product['product_id'], $data['cart_num'])) + throw new ValidateException('本次活动您该商品购买数量已达到上限'); + if ($product->seckill_status !== 1) throw new ValidateException('该商品不在秒杀时间段内'); + $order_make = app()->make(SupplyStoreOrderRepository::class); + $count = $order_make->seckillOrderCounut($data['product_id']); + + $value_make = app()->make(ProductAttrValueRepository::class); + $sku = $value_make->getOptionByUnique($data['product_attr_unique']); + + if ($sku['stock'] <= $count) throw new ValidateException('限购数量不足'); + $_sku = $value_make->getWhere(['sku' => $sku['sku'], 'product_id' => $product['old_product_id']]); + if (!$_sku) throw new ValidateException('原商品SKU不存在'); + if ($_sku['stock'] <= 0) throw new ValidateException('原库存不足'); + $cart = null; + return compact('product', 'sku', 'cart'); + } + + /** + * TODO 复制一条商品 + * @param int $productId + * @param array $data + * @return mixed + * @author Qinii + * @day 2020-11-19 + */ + public function productCopy(int $productId, array $data, $productType = 0) + { + $product = $this->getAdminOneProduct($productId, null); + $product = $product->toArray(); + if ($data) { + foreach ($data as $k => $v) { + $product[$k] = $v; + } + } + return $this->create($product, $productType); + } + + public function existsProduct(int $id, $productType) + { + switch ($productType) { + case 2: + $make = app()->make(ProductPresellRepository::class); + break; + case 3: + $make = app()->make(ProductAssistSetRepository::class); + break; + case 4: + $make = app()->make(ProductGroupRepository::class); + break; + case 40: + $make = app()->make(ProductGroupBuyingRepository::class); + break; + default: + $make = $this->dao; + break; + } + $where = [ + $make->getPk() => $id, + 'is_del' => 0 + ]; + return $make->getWhereCount($where); + } + + public function updateSort(int $id, ?int $merId, array $data) + { + $where[$this->dao->getPk()] = $id; + if ($merId) $where['mer_id'] = $merId; + $ret = $this->dao->getWhere($where); + if (!$ret) throw new ValidateException('数据不存在'); + app()->make(ProductRepository::class)->update($ret['product_id'], $data); + $make = app()->make(SpuRepository::class); + $activityId = $ret['product_type'] ? $ret->seckillActive->seckill_active_id : 0; + return $make->updateSort($ret['product_id'], $activityId, $ret['product_type'], $data); + } + + /** + * TODO 删除商户所有的 + * @param int $merId + * @author Qinii + * @day 5/15/21 + */ + public function clearMerchantProduct($merId) + { + //普通 秒杀 + $this->dao->clearProduct($merId); + //助理 + app()->make(ProductAssistRepository::class)->clearProduct($merId); + //拼团 + app()->make(ProductGroupRepository::class)->clearProduct($merId); + //预售 + app()->make(ProductPresellRepository::class)->clearProduct($merId); + //spu + app()->make(SpuRepository::class)->clearProduct($merId); + } + + /** + * TODO 保障服务 + * @param $where + * @return mixed + * @author Qinii + * @day 5/20/21 + */ + public function GuaranteeTemplate($where) + { + $data = app()->make(GuaranteeTemplateRepository::class)->getSearch($where)->with( + [ + 'templateValue' => [ + 'value' => function ($query) { + $query->field('guarantee_id,guarantee_name,guarantee_info'); + } + ], + ])->find(); + return $data ?? []; + } + + /** + * TODO 添加到货通知 + * @param int $uid + * @param string $unique + * @param int $type + * @author Qinii + * @day 5/24/21 + */ + public function increaseTake(int $uid, string $unique, int $type, int $product_id) + { + $status = systemConfig('procudt_increase_status'); + if (!$status) throw new ValidateException('未开启到货通知'); + $make = app()->make(ProductTakeRepository::class); + $where['product_id'] = $product_id; + if ($unique) $where['unique'] = $unique; + $sku = app()->make(ProductAttrValueRepository::class)->getWhere($where); + if (!$sku) throw new ValidateException('商品不存在'); + $data = [ + 'product_id' => $sku['product_id'], + 'unique' => $unique ?: 1, + 'uid' => $uid, + 'status' => 0, + 'type' => $type + ]; + $make->findOrCreate($data); + } + + /** + * TODO 添加 编辑 预览商品 + * @param array $data + * @param int $productType + * @return array + * @author Qinii + * @day 6/15/21 + */ + public function preview(array $data) + { + if (!isset($data['attrValue']) || !$data['attrValue']) { + throw new ValidateException('缺少商品规格'); + } + $productType = 0; + $product = $this->setProduct($data); + if (isset($data['start_day'])) { //秒杀 + $product['stop'] = time() + 3600; + $productType = 1; + } + if (isset($data['presell_type'])) { //预售 + $product['start_time'] = $data['start_time']; + $product['end_time'] = $data['end_time']; + $product['presell_type'] = $data['presell_type']; + $product['delivery_type'] = $data['delivery_type']; + $product['delivery_day'] = $data['delivery_day']; + $product['p_end_time'] = $data['end_time']; + $product['final_start_time'] = $data['final_start_time']; + $product['final_end_time'] = $data['final_end_time']; + $productType = 2; + } + if (isset($data['params'])) + $product['params'] = $data['params']; + if (isset($data['assist_count'])) { + //助力 + $product['assist_count'] = $data['assist_count']; + $product['assist_user_count'] = $data['assist_user_count']; + $product['price'] = $data['attrValue'][0]['assist_price']; + $productType = 3; + } + + if (isset($data['buying_count_num'])) { + // + $product['buying_count_num'] = $data['buying_count_num']; + $product['pay_count'] = $data['pay_count']; + $productType = 4; + } + + $product['slider_image'] = explode(',', $product['slider_image']); + $product['merchant'] = $data['merchant']; + $product['content'] = ['content' => $data['content']]; + $settleParams = $this->setAttrValue($data, 0, $productType, 0); + $settleParams['attr'] = $this->setAttr($data['attr'], 0); + + $product['price'] = $settleParams['data']['price']; + $product['stock'] = $settleParams['data']['stock']; + $product['cost'] = $settleParams['data']['cost']; + $product['ot_price'] = $settleParams['data']['ot_price']; + $product['product_type'] = $productType; + foreach ($settleParams['attrValue'] as $k => $value) { + $_value = [ + 'sku' => $value['sku'], + 'price' => $value['price'], + 'stock' => $value['stock'], + 'image' => $value['image'], + 'weight' => $value['weight'], + 'volume' => $value['volume'], + 'sales' => $value['sales'], + 'unique' => $value['unique'], + 'bar_code' => $value['bar_code'], + ]; + $sku[$value['sku']] = $_value; + } + $preview_key = 'preview' . $data['mer_id'] . $productType . '_' . time(); + unset($settleParams['data'], $settleParams['attrValue']); + $settleParams['sku'] = $sku; + $settleParams['attr'] = $this->detailAttr($settleParams['attr'], 1); + + if (isset($data['guarantee_template_id'])) { + $guarantee_id = app()->make(GuaranteeValueRepository::class)->getSearch(['guarantee_template_id' => $data['guarantee_template_id']])->column('guarantee_id'); + $product['guaranteeTemplate'] = app()->make(GuaranteeRepository::class)->getSearch(['status' => 1, 'is_del' => 0])->where('guarantee_id', 'in', $guarantee_id)->select(); + } + // if (isset($data['temp_id'])) { + // $product['temp'] = app()->make(ShippingTemplateRepository::class)->getSearch(['shipping_template_id' => $data['temp_id']])->find(); + // } + $product['temp']=0; + $ret = array_merge($product, $settleParams); + + Cache::set($preview_key, $ret); + + return compact('preview_key', 'ret'); + } + + + /** + * TODO 列表查看预览 + * @param array $data + * @return array|\think\Model|null + * @author Qinii + * @day 7/9/21 + */ + public function getPreview(array $data) + { + switch ($data['product_type']) { + case 0: + $product = $this->apiProductDetail(['product_id' => $data['id']], 0, 0)->toArray(); + $res = $this->getProductShow($data['id'], $product, null, 0); + $ret = array_merge($product, $res); + break; + case 1: + $product = $this->apiProductDetail(['product_id' => $data['id']], 1, 0)->toArray(); + $res = $this->getProductShow($data['id'], $product, null, 0); + $ret = array_merge($product, $res); + $ret['stop'] = time() + 3600; + break; + case 2: + $make = app()->make(ProductPresellRepository::class); + $res = $make->getWhere([$make->getPk() => $data['id']])->toArray(); + $ret = $this->apiProductDetail(['product_id' => $res['product_id']], 2, $data['id'])->toArray(); + $ret['ot_price'] = $ret['price']; + $ret['start_time'] = $res['start_time']; + $ret['p_end_time'] = $res['end_time']; + $show = $this->getProductShow($res['product_id'], $ret, $res['product_presell_id'], 2); + $ret = array_merge($ret, $show); + break; + case 3: + $make = app()->make(ProductAssistRepository::class); + $res = $make->getWhere([$make->getPk() => $data['id']])->toArray(); + $ret = $this->apiProductDetail(['product_id' => $res['product_id']], 3, $data['id'])->toArray(); + $show = $this->getProductShow($res['product_id'], $ret, $res['product_assist_id'], 3); + $ret = array_merge($ret, $show); + foreach ($ret['sku'] as $value) { + $ret['price'] = $value['price']; + $ret['stock'] = $value['stock']; + } + break; + case 4: + $make = app()->make(ProductGroupRepository::class); + $res = $make->get($data['id'])->toArray(); + $ret = $this->apiProductDetail(['product_id' => $res['product_id']], 4, $data['id'])->toArray(); + $ret['ot_price'] = $ret['price']; + $show = $this->getProductShow($res['product_id'], $ret, $res['product_group_id'], 4); + $ret = array_merge($ret, $show); + break; + default: + break; + } + return $ret; + } + + public function setLabels($id, $data, $merId = 0) + { + $where['product_id'] = $id; + $field = isset($data['sys_labels']) ? 'sys_labels' : 'mer_labels'; + if ($merId) $where['mer_id'] = $merId; + app()->make(ProductLabelRepository::class)->checkHas($merId, $data[$field]); + $ret = $this->dao->getWhere($where); + + $activeId = $ret->seckillActive->seckill_active_id ?? 0; + + $spu = ['activity_id' => $activeId, 'product_type' => $ret['product_type'], 'product_id' => $id]; + $ret = app()->make(SpuRepository::class)->getWhere($spu); + if (!$ret) throw new ValidateException('数据不存在'); + $ret->$field = $data[$field]; + $ret->save(); + } + + public function getAttrValue(int $id, int $merId) + { + $data = $this->dao->getWhere(['product_id' => $id, 'mer_id' => $merId]); + if (!$data) throw new ValidateException('数据不存在'); + return app()->make(ProductAttrValueRepository::class)->getSearch(['product_id' => $id])->select()->append(['is_svip_price']); + } + + public function checkParams($data, $merId, $id = null) + { + if (!$data['pay_limit']) $data['once_max_count'] = 0; + if ($data['brand_id'] > 0 && !$this->merBrandExists($data['brand_id'])) + throw new ValidateException('品牌不存在'); + if (!$data['cate_id'] || !$this->CatExists($data['cate_id'])) + throw new ValidateException('平台分类不存在'); + if (isset($data['mer_cate_id']) && !$this->merCatExists($data['mer_cate_id'], $merId)) + throw new ValidateException('不存在的商户分类'); + if ($data['delivery_way'] == 2 && !$this->merShippingExists($merId, $data['temp_id'])) + throw new ValidateException('运费模板不存在'); + if (isset($data['type']) && $data['type'] == 1 && $data['extend']) { + $key = ['email', 'text', 'number', 'date', 'time', 'idCard', 'mobile', 'image']; + if (count($data['extend']) > 10) throw new ValidateException('附加表单不能超过10条'); + $title = []; + foreach ($data['extend'] as $item) { + if (empty($item['title'])) + throw new ValidateException('表单名称不能为空:' . $item['key']); + if (in_array($item['title'], $title)) + throw new ValidateException('表单名称不能重复:' . $item['title']); + $title[] = $item['title']; + if (!in_array($item['key'], $key)) + throw new ValidateException('表单类型错误:' . $item['key']); + $extend[] = [ + 'title' => $item['title'], + 'key' => $item['key'], + 'require' => $item['require'], + ]; + } + } + app()->make(ProductLabelRepository::class)->checkHas($merId, $data['mer_labels']); + $count = app()->make(SupplyStoreCategoryRepository::class)->getWhereCount(['store_category_id' => $data['cate_id'], 'is_show' => 1]); + if (!$count) throw new ValidateException('平台分类不存在或不可用'); + app()->make(StoreProductValidate::class)->check($data); + $data['extend'] = $extend ?? []; + // 保存推荐商品 + if (!empty($data['good_ids'])) { + if (30 < count($data['good_ids'])) throw new ValidateException('关联商品不得超过30个'); + $data['good_ids'] = implode(',', $data['good_ids']); + } + return $data; + } + + + public function isFormatAttr(array $data, int $productId, $skuValue = []) + { + if ($productId) { + $make = app()->make(ProductAttrValueRepository::class); + $_sukValue = $make->search(['product_id' => $productId])->with(['productCdkey'])->select()->toArray(); + foreach ($_sukValue as $value) { + $value['cdkey'] = $value['productCdkey'] ?? []; + unset($value['productCdkey']); + $skuValue[$value['sku']] = $value; + } + } + $valueNew = []; + $count = 0; + [$attr, $head] = attr_format($data); + foreach ($attr as $suk) { + $detail = explode(',', $suk); + foreach ($detail as $k => $v) { + $valueNew[$count]['value' . ($k + 1)] = $v; + } + $valueNew[$count]['sku'] = $suk; + $valueNew[$count]['cost'] = $skuValue[$suk]['cost'] ?? 0; + $valueNew[$count]['image'] = $skuValue[$suk]['image'] ?? ''; + $valueNew[$count]['price'] = $skuValue[$suk]['price'] ?? 0; + $valueNew[$count]['stock'] = $skuValue[$suk]['stock'] ?? 0; + $valueNew[$count]['cdkey'] = $skuValue[$suk]['cdkey'] ?? []; + $valueNew[$count]['weight'] = $skuValue[$suk]['weight'] ?? 0; + $valueNew[$count]['volume'] = $skuValue[$suk]['volume'] ?? 0; + $valueNew[$count]['unique'] = $skuValue[$suk]['unique'] ?? 0; + $valueNew[$count]['detail'] = array_combine($head, $detail); + $valueNew[$count]['bar_code'] = $skuValue[$suk]['bar_code'] ?? ''; + $valueNew[$count]['ot_price'] = $skuValue[$suk]['ot_price'] ?? 0; + $valueNew[$count]['svip_price'] = $skuValue[$suk]['svip_price'] ?? 0; + $valueNew[$count]['extension_one'] = $skuValue[$suk]['extension_one'] ?? 0; + $valueNew[$count]['extension_two'] = $skuValue[$suk]['extension_two'] ?? 0; + $count++; + } + return ['attr' => $data, 'value' => $valueNew]; + } + + public function getHotSearchList($where) + { + $where = array_merge($where, $this->dao->productShow()); + $where['star'] = ''; + //搜索记录 + $query = $this->dao->search(null, $where); + $list = $query->limit(10)->select()->toArray(); + // 判断商品数量是否足够,不足补齐 + if (count($list) < 10) { + $list2 = $this->dao->query([])->orderRaw('RAND()')->limit(10 - count($list))->select()->toArray(); + $list = array_merge($list, $list2); + } + return $list; + } + + /** + * 状态操作日志 + * @param $field + * @param $status + * @param $admin_info + * @param $product + * @return void + */ + public function addChangeStatusLog($field, $status, $admin_info, $product) + { + $fieldMappings = [ + 'status' => [ + 1 => OperateLogRepository::PLATFORM_AUDIT_PRODUCT_PASS, + -1 => OperateLogRepository::PLATFORM_AUDIT_PRODUCT_REFUSE, + -2 => OperateLogRepository::PLATFORM_AUDIT_PRODUCT_OFF_SALE, + ], + 'is_show' => [ + 1 => OperateLogRepository::MERCHANT_EDIT_PRODUCT_ON_SALE, + 0 => OperateLogRepository::MERCHANT_EDIT_PRODUCT_OFF_SALE, + ], + 'is_used' => [ + 1 => OperateLogRepository::PLATFORM_EDIT_PRODUCT_SHOW, + 0 => OperateLogRepository::PLATFORM_EDIT_PRODUCT_HIDE, + ], + ]; + $category = $fieldMappings[$field][$status] ?? ''; + if ($category !== '') { + event('create_operate_log', [ + 'category' => $category, + 'data' => [ + 'product' => $product, + 'admin_info' => $admin_info, + ], + ]); + } + } +} diff --git a/app/common/repositories/store/product/SupplySpuRepository.php b/app/common/repositories/store/product/SupplySpuRepository.php new file mode 100644 index 00000000..61792c6f --- /dev/null +++ b/app/common/repositories/store/product/SupplySpuRepository.php @@ -0,0 +1,582 @@ + +// +---------------------------------------------------------------------- +namespace app\common\repositories\store\product; + +// use app\common\repositories\store\coupon\StoreCouponProductRepository; +// use app\common\repositories\store\coupon\StoreCouponRepository; +use app\common\repositories\store\parameter\SupplyParameterValueRepository; +// use app\common\repositories\store\pionts\PointsProductRepository; +// use app\common\repositories\store\StoreActivityRepository; +use app\common\repositories\user\UserRepository; +use crmeb\jobs\SendSmsJob; +use crmeb\jobs\SyncSupplyProductTopJob; +use crmeb\services\CopyCommand; +use crmeb\services\RedisCacheService; +use think\exception\ValidateException; +use think\facade\Cache; +use think\facade\Log; +use app\common\repositories\BaseRepository; +use app\common\dao\store\product\SupplySpuDao; +use app\common\repositories\store\SupplyStoreCategoryRepository; +// use app\common\repositories\store\StoreSeckillActiveRepository; +use app\common\repositories\user\UserVisitRepository; +use think\facade\Queue; + +class SupplySpuRepository extends BaseRepository +{ + public $dao; + public $merchantFiled = 'mer_id,mer_name,mer_avatar,is_trader,mer_info,mer_keyword,type_id'; + public $productFiled = 'S.product_id,S.store_name,S.image,activity_id,S.keyword,S.price,S.mer_id,spu_id,S.status,store_info,brand_id,cate_id,unit_name,S.star,S.rank,S.sort,sales,S.product_type,rate,reply_count,extension_type,S.sys_labels,S.mer_labels,P.delivery_way,P.delivery_free,S.ot_price,svip_price_type,stock,mer_svip_status'; + public function __construct(SupplySpuDao $dao) + { + $this->dao = $dao; + } + + public function create(array $param, int $productId, int $activityId, $productType = 0) + { + $data = $this->setparam($param, $productId, $activityId, $productType); + return $this->dao->create($data); + } + + public function baseUpdate(array $param, int $productId, int $activityId, $productType = 0) + { + // if ($productType == 1) { + // $make = app()->make(StoreSeckillActiveRepository::class); + // $activityId = $make->getSearch(['product_id' => $productId])->value('seckill_active_id'); + // } + $where = [ + 'product_id' => $productId, + 'activity_id' => $activityId, + 'product_type' => $productType, + ]; + $ret = $this->dao->getSearch($where)->find(); + if (!$ret) { + return $this->create($param, $productId, $activityId, $productType); + } else { + $data = $this->setparam($param, $productId, $activityId, $productType); + + $value = $data['mer_labels']; + if (!empty($value)) { + if (!is_array($value)) { + $data['mer_labels'] = ',' . $value . ','; + } else { + $data['mer_labels'] = ',' . implode(',', $value) . ','; + } + } + return $this->dao->update($ret->spu_id, $data); + } + } + + public function setparam(array $param, $productId, $activityId, $productType) + { + $data = [ + 'product_id' => $productId, + 'product_type' => $productType ?? 0, + 'activity_id' => $activityId, + 'store_name' => $param['store_name'], + 'keyword' => $param['keyword'] ?? '', + 'image' => $param['image'], + 'ot_price' => $param['ot_price'] ?? 0, + 'price' => $param['price'], + 'status' => 0,//$productType == PointsProductRepository::PRODUCT_TYPE_POINTS ? 1 : 0, + 'rank' => $param['rank'] ?? 0, + 'temp_id' => $param['temp_id'], + 'sort' => $param['sort'] ?? 0, + 'mer_labels' => $param['mer_labels'] ?? '', + ]; + if (isset($param['mer_id'])) $data['mer_id'] = $param['mer_id']; + return $data; + } + + /** + * TODO 修改排序 + * @param $productId + * @param $activityId + * @param $productType + * @param $data + * @author Qinii + * @day 1/19/21 + */ + public function updateSort($productId, $activityId, $productType, $data) + { + $where = [ + 'product_id' => $productId, + 'activity_id' => $activityId, + 'product_type' => $productType, + ]; + $ret = $this->dao->getSearch($where)->find(); + if ($ret) $this->dao->update($ret['spu_id'], $data); + } + /** + * TODO 移动端列表 + * @param $where + * @param $page + * @param $limit + * @param $userInfo + * @return array + * @author Qinii + * @day 12/18/20 + */ + public function getApiSearch($where, $page, $limit, $userInfo = null) + { + if (isset($where['keyword']) && !empty($where['keyword'])) { + if (preg_match('/^(\/@[1-9]{1}).*\*\//', $where['keyword'])) { + $command = app()->make(CopyCommand::class)->getMassage($where['keyword']); + if (!$command || in_array($command['type'], [30, 40])) return ['count' => 0, 'list' => []]; + if ($userInfo && $command['uid']) app()->make(UserRepository::class)->bindSpread($userInfo, $command['uid']); + $where['spu_id'] = $command['id']; + unset($where['keyword']); + } else { + app()->make(UserVisitRepository::class)->searchProduct($userInfo ? $userInfo['uid'] : 0, $where['keyword'], (int)($where['mer_id'] ?? 0)); + } + } + $count = 0; + $list = []; + if (isset($where['filter_params']) && $where['filter_params']){ + $productIds = app()->make(SupplyParameterValueRepository::class)->filter_params($where['filter_params']); + if (is_array($productIds)) { + if (empty($productIds)) return compact('count', 'list'); + $where['product_ids'] = $productIds; + } + } + + $where['spu_status'] = 1; + $where['mer_status'] = 1; + $where['not_type'] = [20]; + $query = $this->dao->search($where); + $query->with([ + 'merchant' => function ($query) { + $query->field($this->merchantFiled)->with(['type_name']); + }, + 'issetCoupon', + ]); + $productMake = app()->make(ProductRepository::class); + $count = $query->count(); + + $list = $query->page($page, $limit)->setOption('field', [])->field($this->productFiled)->select(); + $append = ['stop_time','svip_price','show_svip_info','is_svip_price']; + if ($productMake->getUserIsPromoter($userInfo)) + $append[] = 'max_extension'; + $list->append($append); + $list = $this->getBorderList($list); + return compact('count', 'list'); + } + + + + public function getBorderList($list) + { + // $make = app()->make(StoreActivityRepository::class); + // foreach ($list as $item) { + // $act = $make->getActivityBySpu(StoreActivityRepository::ACTIVITY_TYPE_BORDER,$item['spu_id'],$item['cate_id'],$item['mer_id'],$item['sys_labels']); + // $item['border_pic'] = $act['pic'] ?? ''; + // } + return $list; + } + + + /** + * TODO 修改状态 + * @param array $data + * @author Qinii + * @day 12/18/20 + */ + public function changeStatus(int $id, int $productType, array $operate_data = []) + { + $make = app()->make(ProductRepository::class); + $status = 1; + try { + // switch ($productType) { + // case 0: + // $where = [ + // 'activity_id' => 0, + // 'product_id' => $id, + // 'product_type' => $productType, + // ]; + // break; + // case 1: + // $_make = app()->make(StoreSeckillActiveRepository::class); + // $res = $_make->getSearch(['product_id' => $id])->find(); + // $endday = strtotime($res['end_day']); + // if ($res['status'] == -1 || $endday < time()) $status = 0; + // $where = [ + // 'activity_id' => $res['seckill_active_id'], + // 'product_id' => $id, + // 'product_type' => $productType, + // ]; + // break; + // case 2: + // $_make = app()->make(ProductPresellRepository::class); + // $res = $_make->getWhere([$_make->getPk() => $id]); + + // $endttime = strtotime($res['end_time']); + // if ($endttime <= time()) { + // $status = 0; + // } else { + // if ( + // $res['product_status'] !== 1 || + // $res['status'] !== 1 || + // $res['action_status'] !== 1 || + // $res['is_del'] !== 0 || + // $res['is_show'] !== 1 + // ) { + // $status = 0; + // } + // } + // $where = [ + // 'activity_id' => $id, + // 'product_id' => $res['product_id'], + // 'product_type' => $productType, + // ]; + // break; + // case 3: + // $_make = app()->make(ProductAssistRepository::class); + // $res = $_make->getWhere([$_make->getPk() => $id]); + + // $endttime = strtotime($res['end_time']); + // if ($endttime <= time()) { + // $status = 0; + // } else { + // if ( + // $res['product_status'] !== 1 || + // $res['status'] !== 1 || + // $res['is_show'] !== 1 || + // $res['action_status'] !== 1 || + // $res['is_del'] !== 0 + // ) { + // $status = 0; + // } + // } + + // $where = [ + // 'activity_id' => $id, + // 'product_id' => $res['product_id'], + // 'product_type' => $productType, + // ]; + // break; + // case 4: + // $_make = app()->make(ProductGroupRepository::class); + // $wher = $_make->actionShow(); + // $wher[$_make->getPk()] = $id; + + // $res = $_make->getWhere([$_make->getPk() => $id]); + // $endttime = strtotime($res['end_time']); + // if ($endttime <= time()) { + // $status = 0; + // } else { + // if ( + // $res['product_status'] !== 1 || + // $res['status'] !== 1 || + // $res['is_show'] !== 1 || + // $res['action_status'] !== 1 || + // $res['is_del'] !== 0 + // ) { + // $status = 0; + // } + // } + + // $where = [ + // 'activity_id' => $id, + // 'product_id' => $res['product_id'], + // 'product_type' => $productType, + // ]; + // break; + // default: + // $where = [ + // 'activity_id' => 0, + // 'product_id' => $id, + // 'product_type' => $productType, + // ]; + // break; + // } + $where = [ + 'activity_id' => 0, + 'product_id' => $id, + 'product_type' => $productType, + ]; + if (empty($where)) return ; + $ret = $make->getWhere(['product_id' => $where['product_id'],'product_type' => $productType]); + if ( + !$ret || + $ret['status'] !== 1 || + $ret['mer_status'] !== 1 || + $ret['is_del'] || + (in_array($productType, [0, 1,20]) && ($ret['is_show'] !== 1 || $ret['is_used'] !== 1)) + ) { + $status = 0; + } + $result = $this->dao->getSearch($where)->find(); + if (!$result && $ret){ + $result = $this->create($ret->toArray(), $where['product_id'], $where['activity_id'], $productType); + } + if ($result) $this->dao->update($result['spu_id'], ['status' => $status]); + if ($productType == 0) { + Queue::push(SyncSupplyProductTopJob::class,[]); + if ($status == 1) Queue(SendSmsJob::class, ['tempId' => 'PRODUCT_INCREASE', 'id' => $id]); + // 记录操作日志 + if (!empty($operate_data)) { + $make->addChangeStatusLog($operate_data['field'], $operate_data['status'], $operate_data['admin_info'], $ret); + } + } + } catch (\Exception $exception) { + Log::info($exception->getMessage()); + } + } + + /** + * TODO 平台编辑商品同步修改 + * @param int $id + * @param int $productId + * @param int $productType + * @param array $data + * @author Qinii + * @day 12/18/20 + */ + public function changRank(int $id, int $productId, int $productType, array $data) + { + $where = [ + 'product_id' => $productId, + 'product_type' => $productType, + 'activity_id' => $id, + ]; + $res = $this->dao->getWhere($where); + if (!$res && $id) $this->changeStatus($id, $productType); + $res = $this->dao->getWhere($where); + if ($res) { + $res->store_name = $data['store_name']; + $res->rank = $data['rank']; + $res->star = $data['star'] ?? 1; + $res->save(); + } + } + + /** + * TODO 同步各类商品到spu表 + * @param array|null $productType + * @author Qinii + * @day 12/25/20 + */ + public function updateSpu(?array $productType) + { + if (!$productType) $productType = [0, 1, 2, 3, 4, 20]; + $_product_make = app()->make(ProductRepository::class); + foreach ($productType as $value) { + $_product_make->activitSearch($value)->chunk(100, function ($product) use ($_product_make) { + $data = $_product_make->commandChangeProductStatus($product->toArray()); + $this->dao->findOrCreateAll($data); + echo count($data) . '条数据处理成功' . PHP_EOL; + }, 'P.product_id'); + } + } + + /** + * TODO 获取活动商品的一级分类 + * @param $type + * @return mixed + * @author Qinii +0 + * @day 1/12/21 + */ + public function getActiveCategory($type) + { + $pathArr = $this->dao->getActivecategory($type); + $path = []; + foreach ($pathArr as $item) { + $path[] = explode('/', $item)[1]; + } + $path = array_unique($path); + $cat = app()->make(SupplyStoreCategoryRepository::class)->getSearch(['ids' => $path])->field('store_category_id,cate_name')->select(); + return $cat; + } + + public function getSpuData($id, $productType, $merId) + { + // try { + // switch ($productType) { + // case 0: + // $where = [ + // 'activity_id' => 0, + // 'product_id' => $id, + // 'product_type' => $productType, + // ]; + // break; + // case 1: + // $_make = app()->make(StoreSeckillActiveRepository::class); + // $res = $_make->getSearch(['product_id' => $id])->find(); + // $where = [ + // 'activity_id' => $res['seckill_active_id'], + // 'product_id' => $id, + // 'product_type' => $productType, + // ]; + // break; + // case 2: + // $_make = app()->make(ProductPresellRepository::class); + // $res = $_make->getWhere([$_make->getPk() => $id]); + // $where = [ + // 'activity_id' => $id, + // 'product_id' => $res['product_id'], + // 'product_type' => $productType, + // ]; + // break; + // case 3: + // $_make = app()->make(ProductAssistRepository::class); + // $res = $_make->getWhere([$_make->getPk() => $id]); + // $where = [ + // 'activity_id' => $id, + // 'product_id' => $res['product_id'], + // 'product_type' => $productType, + // ]; + // break; + // case 4: + // $_make = app()->make(ProductGroupRepository::class); + // $where[$_make->getPk()] = $id; + // $res = $_make->getWhere([$_make->getPk() => $id]); + // $where = [ + // 'activity_id' => $id, + // 'product_id' => $res['product_id'], + // 'product_type' => $productType, + // ]; + // break; + // default: + // $where = [ + // 'activity_id' => 0, + // 'product_id' => $id, + // 'product_type' => 0, + // ]; + // break; + // } + // } catch (\Exception $e) { + // throw new ValidateException('数据不存在'); + // } + $where = [ + 'activity_id' => 0, + 'product_id' => $id, + 'product_type' => $productType, + ]; + if ($merId) $where['mer_id'] = $merId; + $result = $this->dao->getSearch($where)->find(); + if (!$result) throw new ValidateException('数据不存在'); + return $result; + } + + public function setLabels($id, $productType, $data, $merId = 0) + { + $field = isset($data['sys_labels']) ? 'sys_labels' : 'mer_labels'; + if ($data[$field]) app()->make(ProductLabelRepository::class)->checkHas($merId, $data[$field]); + $ret = $this->getSpuData($id, $productType, $merId); + $value = $data[$field] ? $data[$field] : ''; + $ret->$field = $value; + $ret->save(); + } + + public function batchLabels($ids, $data,$merId) + { + $ids = is_array($ids) ? $ids : explode(',',$ids); + foreach ($ids as $id) { + $this->setLabels($id,0,$data,$merId); + } + } + + + public function getApiSearchByCoupon($where, $page, $limit, $userInfo) + { +// $coupon = app()->make(StoreCouponRepository::class)->search(null, [ +// 'status' => 1, +// 'coupon_id' => $where['coupon_id'] +// ])->find(); +// $data['coupon'] = $coupon; +// if ($coupon) { +// switch ($coupon['type']) { +// case 0: +// case 2: +// $where['mer_id'] = $coupon['mer_id']; +// break; +// case 1: +// $where['product_ids'] = app()->make(StoreCouponProductRepository::class)->search([ +// 'coupon_id' => $where['coupon_id'] +// ])->column('product_id'); +// break; +// case 11: +// $ids = app()->make(StoreCouponProductRepository::class)->search([ +// 'coupon_id' => $where['coupon_id'] +// ])->column('product_id'); +// $where['cate_pid'] = $ids; +// break; +// case 10: +// case 13: +// break; +// case 12: +// $ids = app()->make(StoreCouponProductRepository::class)->search([ +// 'coupon_id' => $where['coupon_id'] +// ])->column('product_id'); +// $where['mer_ids'] = $ids; +// break; +// } +// $where['is_coupon'] = 1; +// $where['order'] = 'star'; +// $where['common'] = 1; +// // $where['svip'] = ($coupon['send_type'] == StoreCouponRepository::GET_COUPON_TYPE_SVIP) ? 1 : ''; +// $product = $this->getApiSearch($where, $page, $limit, $userInfo); +// } + + $data['count'] = 0;//$product['count'] ?? 0; + $data['list'] =[];// $product['list'] ?? []; + return $data; + } + + public function getHotRanking(int $cateId, $limit = 15) + { + $RedisCacheService = app()->make(RedisCacheService::class); + $prefix = env('queue_name','merchant').'_hot_ranking_'; + $ids = $RedisCacheService->handler()->get($prefix.'top_' . intval($cateId)); + $ids = $ids ? explode(',', $ids) : []; + if (!count($ids)) { + return []; + } + $ids = array_map('intval', $ids); + $where['mer_status'] = 1; + $where['status'] = 1; + $where['is_del'] = 0; + $where['product_type'] = 0; + $where['order'] = 'sales'; + $where['spu_ids'] = $ids; + $list = $this->dao->search($where)->setOption('field',[])->field('spu_id,S.image,S.price,S.product_type,P.product_id,P.sales,S.status,S.store_name,P.ot_price,P.cost')->limit($limit)->select(); + if ($list) $list = $list->toArray(); + return $list; + } + + /** + * TODO + * @param $where + * @param $page + * @param $limit + * @return array + * @author Qinii + * @day 2022/9/22 + */ + public function makinList($where,$page, $limit) + { + $where['spu_status'] = 1; + $where['mer_status'] = 1; + $query = $this->dao->search($where); + $query->with([ + 'merchant' , + 'issetCoupon', + ]); + $count = $query->count(); + $list = $query->page($page, $limit)->setOption('field', [])->field($this->productFiled)->select(); + return compact('count','list'); + } + + public function updatePrice($mer_id, $product_id, $price) + { + return $this->dao->updatePrice($mer_id, $product_id, $price); + } +} diff --git a/app/controller/supply/store/product/Product.php b/app/controller/supply/store/product/Product.php index c312fdf8..eb85dec7 100644 --- a/app/controller/supply/store/product/Product.php +++ b/app/controller/supply/store/product/Product.php @@ -23,7 +23,7 @@ use crmeb\services\UploadService; use think\App; use crmeb\basic\BaseController; use app\validate\supply\StoreProductValidate as validate; -use app\common\repositories\store\product\ProductRepository as repository; +use app\common\repositories\store\product\SupplyProductRepository as repository; use think\exception\ValidateException; use think\facade\Cache; diff --git a/crmeb/jobs/ChangeSupplySpuStatusJob.php b/crmeb/jobs/ChangeSupplySpuStatusJob.php new file mode 100644 index 00000000..0fede812 --- /dev/null +++ b/crmeb/jobs/ChangeSupplySpuStatusJob.php @@ -0,0 +1,44 @@ + +// +---------------------------------------------------------------------- + + +namespace crmeb\jobs; + +use app\common\repositories\store\product\SupplySpuRepository; +use crmeb\interfaces\JobInterface; +use think\facade\Log; + +class ChangeSupplySpuStatusJob implements JobInterface +{ + + public function fire($job, $data) + { + try{ + $make = app()->make(SupplySpuRepository::class); + if (is_array($data['id'])){ + foreach ($data['id'] as $i) { + $make->changeStatus($i, $data['product_type'], $data['operate_data'] ?? []); + } + } else if(is_numeric($data['id'])){ + $make->changeStatus($data['id'], $data['product_type'], $data['operate_data'] ?? []); + } + }catch (\Exception $exception){ + Log::info($exception->getMessage()); + } + $job->delete(); + } + + public function failed($data) + { + // TODO: Implement failed() method. + } +} diff --git a/crmeb/jobs/SyncSupplyProductTopJob.php b/crmeb/jobs/SyncSupplyProductTopJob.php new file mode 100644 index 00000000..26b4104f --- /dev/null +++ b/crmeb/jobs/SyncSupplyProductTopJob.php @@ -0,0 +1,76 @@ +delete(); + + $SpuRepository = app()->make(SupplySpuRepository::class); + $RedisCacheService = app()->make(RedisCacheService::class); + $prefix = env('queue_name','merchant').'_hot_ranking_'; + $oldKeys1 = $RedisCacheService->keys($prefix.'top_*') ?: []; + $oldKeys1 = array_combine($oldKeys1, $oldKeys1); + $mset = []; + $where = ['product_type' => 0, 'spu_status' => 1, 'mer_status' => 1, 'order' => 'sales']; + $ids = $SpuRepository->search($where)->limit(15)->column('spu_id'); + $mset[$prefix.'top_0'] = implode(',', $ids); + unset($oldKeys1[$prefix.'top_0']); + $make = app()->make(SupplyStoreCategoryRepository::class); + foreach ([1,2,3] as $level) { + $cateList = $make->getSearch(['status' => 1, 'mer_id' => 0, 'type' => 0]) + ->where('level','<',$level)->column('store_category_id,cate_name,pic'); + foreach ($cateList as $item) { + $id = $item['store_category_id']; + $ids = $make->findChildrenId($id); + $ids[] = $id; + $where['cate_id'] = $ids; + $spuList = $SpuRepository->search($where)->limit(15)->select(); + if (count($spuList)) { + foreach ($spuList as $i => $spu) { + $key = $prefix.'top_item_' . $id . '_' . $spu['spu_id']; + $mset[$key] = json_encode([$item['cate_name'], $i + 1, $id], JSON_UNESCAPED_UNICODE); + unset($oldKeys1[$key]); + } + $_key = $prefix.'top_' . $id; + $mset[$_key] = implode(',', $spuList->column('spu_id')); + unset($oldKeys1[$_key]); + } + } + Cache::set($prefix.'topCate', implode(',', array_column($cateList, 'store_category_id'))); + } + if (count($mset)) { + $RedisCacheService->mSet($mset); + } + if (count($oldKeys1)) { + $RedisCacheService->handler()->del(...array_values($oldKeys1)); + } + }catch (\Exception $e){ + Log::info('热卖排行统计:' . $e->getMessage()); + } + $job->delete(); + } + + public function failed($data) + { + // TODO: Implement failed() method. + } + + public function work() + { + + } +} diff --git a/route/merchant/system.php b/route/merchant/system.php index a79550f3..f36852d5 100644 --- a/route/merchant/system.php +++ b/route/merchant/system.php @@ -122,7 +122,7 @@ Route::group(function () { //配置 Route::group( function () { Route::get('config', 'merchant.Common/config'); - Route::get('menus', 'admin.system.auth.Menu/merchantMenus')->append(['merchant' => 1]); + Route::get('menus', 'admin.system.auth.Menu/merchantMenus')->append(['merchant' => 2]); Route::get('logout', 'merchant.system.admin.Login/logout'); //获取版本号 Route::get('version', 'admin.Common/version');