123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- namespace app\services\product\sku;
- use app\dao\product\sku\StoreProductAttrValueDao;
- use app\jobs\product\ProductStockTips;
- use app\jobs\product\ProductStockValueTips;
- use app\services\activity\bargain\StoreBargainServices;
- use app\services\activity\combination\StoreCombinationServices;
- use app\services\activity\discounts\StoreDiscountsServices;
- use app\services\activity\integral\StoreIntegralServices;
- use app\services\activity\seckill\StoreSeckillServices;
- use app\services\BaseServices;
- use app\services\product\branch\StoreBranchProductAttrValueServices;
- use app\services\product\product\StoreProductStockRecordServices;
- use app\webscoket\SocketPush;
- use crmeb\exceptions\AdminException;
- use app\services\product\product\StoreProductServices;
- use crmeb\services\CacheService;
- use crmeb\traits\ServicesTrait;
- use think\exception\ValidateException;
- /**
- * Class StoreProductAttrValueService
- * @package app\services\product\sku
- * @mixin StoreProductAttrValueDao
- */
- class StoreProductAttrValueServices extends BaseServices
- {
- use ServicesTrait;
- /**
- * StoreProductAttrValueServices constructor.
- * @param StoreProductAttrValueDao $dao
- */
- public function __construct(StoreProductAttrValueDao $dao)
- {
- $this->dao = $dao;
- }
- /**
- * 获取单规格规格
- * @param array $where
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getOne(array $where)
- {
- return $this->dao->getOne($where);
- }
- /**
- * 根据活动商品unique查看原商品unique
- * @param string $unique
- * @param int $activity_id
- * @param int $type
- * @param array|string[] $field
- * @return array|mixed|string|\think\Model|null
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getUniqueByActivityUnique(string $unique, int $activity_id, int $type = 1, array $field = ['unique'])
- {
- if ($type == 0) return $unique;
- $attrValue = $this->dao->get(['unique' => $unique, 'product_id' => $activity_id, 'type' => $type], ['id', 'suk', 'product_id']);
- if (!$attrValue) {
- return '';
- }
- switch ($type) {
- case 1://秒杀
- /** @var StoreSeckillServices $activityServices */
- $activityServices = app()->make(StoreSeckillServices::class);
- break;
- case 2://砍价
- /** @var StoreBargainServices $activityServices */
- $activityServices = app()->make(StoreBargainServices::class);
- break;
- case 3://拼团
- /** @var StoreCombinationServices $activityServices */
- $activityServices = app()->make(StoreCombinationServices::class);
- break;
- case 4://积分
- /** @var StoreIntegralServices $activityServices */
- $activityServices = app()->make(StoreIntegralServices::class);
- break;
- case 5://套餐
- /** @var StoreDiscountsServices $activityServices */
- $activityServices = app()->make(StoreDiscountsServices::class);
- break;
- default:
- /** @var StoreProductServices $activityServices */
- $activityServices = app()->make(StoreProductServices::class);
- break;
- }
- $product_id = $activityServices->value(['id' => $activity_id], 'product_id');
- if (!$product_id) {
- return '';
- }
- if (count($field) == 1) {
- return $this->dao->value(['suk' => $attrValue['suk'], 'product_id' => $product_id, 'type' => 0], $field[0] ?? 'unique');
- } else {
- return $this->dao->get(['suk' => $attrValue['suk'], 'product_id' => $product_id, 'type' => 0], $field);
- }
- }
- /**
- * 删除一条数据
- * @param int $id
- * @param int $type
- * @param array $suk
- * @return bool
- */
- public function del(int $id, int $type, array $suk = [])
- {
- return $this->dao->del($id, $type, $suk);
- }
- /**
- * 批量保存
- * @param array $data
- */
- public function saveAll(array $data)
- {
- $res = $this->dao->saveAll($data);
- if (!$res) throw new AdminException('规格保存失败');
- return $res;
- }
- /**
- * 获取sku
- * @param array $where
- * @param string $field
- * @param string $key
- * @return array
- */
- public function getSkuArray(array $where, string $field = 'unique,bar_code,cost,price,ot_price,stock,image as pic,weight,volume,brokerage,brokerage_two,quota,product_id,code', string $key = 'suk')
- {
- return $this->dao->getColumn($where, $field, $key);
- }
- /**
- * 交易排行榜
- * @return array
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function purchaseRanking()
- {
- $dlist = $this->dao->attrValue();
- /** @var StoreProductServices $proServices */
- $proServices = app()->make(StoreProductServices::class);
- $slist = $proServices->getProductLimit(['is_del' => 0], $limit = 20, 'id as product_id,store_name,sales * price as val');
- $data = array_merge($dlist, $slist);
- $last_names = array_column($data, 'val');
- array_multisort($last_names, SORT_DESC, $data);
- $list = array_splice($data, 0, 20);
- return $list;
- }
- /**
- * 获取商品的属性数量
- * @param $product_id
- * @param $unique
- * @param $type
- * @return int
- */
- public function getAttrvalueCount($product_id, $unique, $type)
- {
- return $this->dao->count(['product_id' => $product_id, 'unique' => $unique, 'type' => $type]);
- }
- /**
- * 获取唯一值下的库存
- * @param string $unique
- * @return int
- */
- public function uniqueByStock(string $unique)
- {
- if (!$unique) return 0;
- return $this->dao->uniqueByStock($unique);
- }
- /**
- * 减销量,加库存
- * @param $productId
- * @param $unique
- * @param $num
- * @param int $type
- * @return mixed
- */
- public function decProductAttrStock($productId, $unique, $num, $type = 0)
- {
- $res = $this->dao->decStockIncSales([
- 'product_id' => $productId,
- 'unique' => $unique,
- 'type' => $type
- ], $num);
- if ($res) {
- $this->workSendStock($productId, $unique, $type);
- }
- return $res;
- }
- /**
- * 减少销量增加库存
- * @param $productId
- * @param $unique
- * @param $num
- * @return bool
- */
- public function incProductAttrStock(int $productId, string $unique, int $num, int $type = 0)
- {
- return $this->dao->incStockDecSales(['unique' => $unique, 'product_id' => $productId, 'type' => $type], $num);
- }
- /**
- * 库存预警消息提醒
- * @param int $productId
- * @param string $unique
- * @param int $type
- */
- public function workSendStock(int $productId, string $unique, int $type)
- {
- ProductStockValueTips::dispatch([$productId, $unique, $type]);
- }
- /**
- * 获取秒杀库存
- * @param int $productId
- * @param string $unique
- * @param bool $isNew
- * @return array|mixed|\think\Model|null
- * @throws \Psr\SimpleCache\InvalidArgumentException
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function getSeckillAttrStock(int $productId, string $unique, bool $isNew = false)
- {
- $key = md5('seclkill_attr_stock_' . $productId . '_' . $unique);
- $stock = CacheService::redisHandler()->get($key);
- if (!$stock || $isNew) {
- $stock = $this->dao->getOne(['product_id' => $productId, 'unique' => $unique, 'type' => 1], 'suk,quota');
- if ($stock) {
- CacheService::redisHandler()->set($key, $stock, 60);
- }
- }
- return $stock;
- }
- /**
- * @param $product_id
- * @param string $suk
- * @param string $unique
- * @param bool $is_new
- * @return int|mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function getProductAttrStock(int $productId, string $suk = '', string $unique = '', $isNew = false)
- {
- if (!$suk && !$unique) return 0;
- $key = md5('product_attr_stock_' . $productId . '_' . $suk . '_' . $unique);
- $stock = CacheService::redisHandler()->get($key);
- if (!$stock || $isNew) {
- $where = ['product_id' => $productId, 'type' => 0];
- if ($suk) {
- $where['suk'] = $suk;
- }
- if ($unique) {
- $where['unique'] = $unique;
- }
- $stock = $this->dao->value($where, 'stock');
- CacheService::redisHandler()->set($key, $stock, 60);
- }
- return $stock;
- }
- /**
- * 根据商品id获取对应规格库存
- * @param int $productId
- * @param int $type
- * @return float
- */
- public function pidBuStock(int $productId, int $type = 0)
- {
- return $this->dao->pidBuStock($productId, $type);
- }
- /**
- * 更新sum_stock
- * @param array $uniques
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function updateSumStock(array $uniques)
- {
- /** @var StoreBranchProductAttrValueServices $storeValueService */
- $storeValueService = app()->make(StoreBranchProductAttrValueServices::class);
- $stockSumData = $storeValueService->getProductAttrValueStockSum($uniques ?? []);
- $this->dao->getList(['unique' => $uniques])->map(function ($item) use ($stockSumData) {
- if (isset($stockSumData[$item->unique])) {
- $data['sum_stock'] = $item->stock + $stockSumData[$item->unique];
- } else {
- $data['sum_stock'] = $item->stock;
- }
- $this->dao->update(['product_id' => $item['product_id'], 'unique' => $item['unique'], 'type' => $item['type']], $data);
- });
- }
- /**
- * 批量快速修改商品规格库存
- * @param int $id
- * @param array $data
- * @return int|string
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function saveProductAttrsStock(int $id, array $data)
- {
- /** @var StoreProductServices $productServices */
- $productServices = app()->make(StoreProductServices::class);
- $product = $productServices->get($id);
- if (!$product) {
- throw new ValidateException('商品不存在');
- }
- $attrs = $this->dao->getProductAttrValue(['product_id' => $id, 'type' => 0]);
- if ($attrs) $attrs = array_combine(array_column($attrs, 'unique'), $attrs);
- $dataAll = $update = [];
- $stock = 0;
- $time = time();
- foreach ($data as $attr) {
- if (!isset($attrs[$attr['unique']])) continue;
- if ($attr['pm']) {
- $stock = bcadd((string)$stock, (string)$attr['stock'], 0);
- $update['stock'] = bcadd((string)$attrs[$attr['unique']]['stock'], (string)$attr['stock'], 0);
- $update['sum_stock'] = bcadd((string)$attrs[$attr['unique']]['sum_stock'], (string)$attr['stock'], 0);
- } else {
- $stock = bcsub((string)$stock, (string)$attr['stock'], 0);
- $update['stock'] = bcsub((string)$attrs[$attr['unique']]['stock'], (string)$attr['stock'], 0);
- $update['sum_stock'] = bcsub((string)$attrs[$attr['unique']]['sum_stock'], (string)$attr['stock'], 0);
- }
- $update['stock'] = $update['stock'] > 0 ? $update['stock'] : 0;
- $this->dao->update(['id' => $attrs[$attr['unique']]['id']], $update);
- $dataAll[] = [
- 'product_id' => $id,
- 'unique' => $attr['unique'],
- 'cost_price' => $attrs[$attr['unique']]['cost'] ?? 0,
- 'number' => $attr['stock'],
- 'pm' => $attr['pm'] ? 1 : 0,
- 'add_time' => $time,
- ];
- }
- $product_stock = $stock ? bcadd((string)$product['stock'], (string)$stock, 0) : bcsub((string)$product['stock'], (string)$stock, 0);
- $product_stock = $product_stock > 0 ? $product_stock : 0;
- //修改商品库存
- $productServices->update($id, ['stock' => $product_stock]);
- //检测库存警戒和检测是否售罄
- ProductStockTips::dispatch([$id, 0]);
- //添加库存记录$product_stock
- if ($dataAll) {
- /** @var StoreProductStockRecordServices $storeProductStockRecordServces */
- $storeProductStockRecordServces = app()->make(StoreProductStockRecordServices::class);
- $storeProductStockRecordServces->saveAll($dataAll);
- }
- //清除缓存
- $productServices->cacheTag()->clear();
- /** @var StoreProductAttrServices $attrService */
- $attrService = app()->make(StoreProductAttrServices::class);
- $attrService->cacheTag()->clear();
- return $product_stock;
- }
- /**
- * 查询库存预警产品ids
- * @param array $where
- * @return array
- */
- public function getGroupId(array $where)
- {
- $res1 = [];
- $res2 = $this->dao->getGroupData('product_id', 'product_id', $where);
- foreach ($res2 as $id) {
- $res1[] = $id['product_id'];
- }
- return $res1;
- }
- }
|