| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414 |
- <?php
- namespace app\common\service;
- use think\facade\Db;
- use think\facade\Log;
- class CompanyPackageService
- {
- /**
- * 验证企业套餐购买资格
- */
- public function validateCompanyPurchase($userId, $packagePriceId, $quantity)
- {
- try {
- // 1. 获取套餐信息
- $package = Db::table('ba_package_price')
- ->alias('pp')
- ->leftJoin('ba_package p', 'p.id = pp.package_id')
- ->where('pp.id', $packagePriceId)
- ->field('pp.*, p.name as package_name')
- ->find();
- if (!$package) {
- throw new \Exception('套餐不存在');
- }
- // 2. 如果是企业套餐,检查用户是否属于企业
- if ($package['type'] == 2) { // 企业套餐
- $companyInfo = $this->getUserCompany($userId);
- if (!$companyInfo) {
- throw new \Exception('只有企业成员才能购买企业套餐');
- }
- // 3. 检查日期卡的最低购买数量
- if ($package['is_date_card'] == 1 && $quantity < $package['min_quantity']) {
- throw new \Exception('企业日期卡至少需要购买' . $package['min_quantity'] . '份');
- }
- return [
- 'valid' => true,
- 'company_id' => $companyInfo['id'],
- 'company_name' => $companyInfo['name'],
- 'min_quantity' => $package['min_quantity']
- ];
- }
- return ['valid' => true, 'company_id' => null];
- } catch (\Throwable $e) {
- Log::error('验证企业套餐购买资格失败: ' . $e->getMessage());
- throw $e;
- }
- }
- /**
- * 获取用户所在企业
- */
- public function getUserCompany($userId)
- {
- // 检查用户是否是企业创建人或成员
- $company = Db::table('ba_company')
- ->where('creator_id', $userId)
- ->where('status', 1)
- ->field('id, name,creator_id')
- ->find();
- if ($company) {
- return $company;
- }
- // 检查是否是成员
- $member = Db::table('ba_company_member')
- ->alias('cm')
- ->leftJoin('ba_company c', 'c.id = cm.company_id')
- ->where('cm.user_id', $userId)
- ->where('cm.status', 1)
- ->where('c.status', 1)
- ->field('c.id, c.name')
- ->find();
- return $member;
- }
- /**
- * 处理企业套餐购买(创建席位记录)
- */
- public function processCompanyPackagePurchase($orderId, $companyId, $packagePriceId, $quantity, $cardType, $unitValue, $pointsValue)
- {
- Db::startTrans();
- try {
- // 1. 获取或创建企业套餐席位记录
- $seatsRecord = Db::table('ba_company_package_seats')
- ->where('company_id', $companyId)
- ->where('package_price_id', $packagePriceId)
- ->find();
- if ($seatsRecord) {
- // 更新现有记录
- $updateData = [
- 'total_seats' => Db::raw('total_seats + ' . $quantity),
- 'available_seats' => Db::raw('available_seats + ' . $quantity),
- 'is_shared' => $cardType < 3 ? 1 : 0, // 次卡/积分卡为共享资源
- 'update_time' => date('Y-m-d H:i:s')
- ];
- // 如果是次卡,累加次数
- if ($cardType == 1) {
- $updateData['total_times'] = Db::raw('total_times + ' . ($unitValue * $quantity));
- $updateData['remaining_times'] = Db::raw('remaining_times + ' . ($unitValue * $quantity));
- }
- // 如果是积分卡,累加积分
- if ($cardType == 2) {
- $updateData['total_points'] = Db::raw('total_points + ' . ($pointsValue * $quantity));
- $updateData['remaining_points'] = Db::raw('remaining_points + ' . ($pointsValue * $quantity));
- }
- Db::table('ba_company_package_seats')
- ->where('id', $seatsRecord['id'])
- ->update($updateData);
- $seatsId = $seatsRecord['id'];
- } else {
- // 创建新记录
- $seatsData = [
- 'company_id' => $companyId,
- 'package_price_id' => $packagePriceId,
- 'product_id' => $this->getProductIdByPackage($packagePriceId),
- 'total_seats' => $quantity,
- 'assigned_seats' => 0,
- 'available_seats' => $quantity,
- 'is_shared' => $cardType < 3 ? 1 : 0, // 次卡/积分卡为共享资源
- 'card_type' => $cardType,
- 'total_times' => $cardType == 1 ? $unitValue * $quantity : 0,
- 'remaining_times' => $cardType == 1 ? $unitValue * $quantity : 0,
- 'total_points' => $cardType == 2 ? $pointsValue * $quantity : 0,
- 'remaining_points' => $cardType == 2 ? $pointsValue * $quantity : 0,
- 'status' => 1,
- 'create_time' => date('Y-m-d H:i:s'),
- 'update_time' => date('Y-m-d H:i:s')
- ];
- $seatsId = Db::table('ba_company_package_seats')->insertGetId($seatsData);
- }
- // 2. 获取购买者ID
- $buyerId = $this->getOrderBuyerId($orderId);
- // 3. 查询订单商品
- $orderItems = Db::table('ba_order_item')
- ->where('order_id', $orderId)
- ->where('package_price_id', $packagePriceId)
- ->select();
- foreach ($orderItems as $item) {
- if ($cardType >= 3) {
- // 日期卡:为每个购买的数量创建独立的分配记录
- for ($i = 0; $i < $quantity; $i++) {
- $allocationData = [
- 'order_item_id' => $item['id'],
- 'order_id' => $orderId,
- 'package_price_id' => $packagePriceId,
- 'product_id' => $item['product_id'],
- 'buyer_id' => $buyerId,
- 'company_id' => $companyId,
- 'assigned_to_user_id' => null, // 初始不分配
- 'assigned_by_user_id' => $buyerId,
- 'record_type' => 2, // 购买记录
- 'is_general' => 0,
- 'seat_index' => $i + 1, // 席位索引
- 'allocation_status' => 0, // 未分配
- 'allocation_time' => null,
- 'start_time' => null,
- 'end_time' => null,
- 'expire_time' => $this->calculateEndTime($cardType, date('Y-m-d H:i:s')), // 冗余字段
- 'remaining_times' => 0, // 日期卡没有次数
- 'remaining_points' => 0, // 日期卡没有积分
- 'is_used' => 0,
- 'create_time' => date('Y-m-d H:i:s'),
- 'update_time' => date('Y-m-d H:i:s')
- ];
- $allocationId = Db::table('ba_company_package_allocation')->insertGetId($allocationData);
- }
- } else {
- // 次卡和积分卡:
- // 1. 创建通用记录(用于管理总资源)
- $generalAllocationData = [
- 'order_item_id' => $item['id'],
- 'order_id' => $orderId,
- 'package_price_id' => $packagePriceId,
- 'product_id' => $item['product_id'],
- 'buyer_id' => $buyerId,
- 'company_id' => $companyId,
- 'assigned_to_user_id' => null, // 通用记录不分配
- 'assigned_by_user_id' => $buyerId,
- 'record_type' => 0, // 通用记录
- 'is_general' => 1, // 是通用记录
- 'seat_index' => 0,
- 'allocation_status' => 0, // 状态:通用记录
- 'allocation_time' => null,
- 'start_time' => null,
- 'end_time' => null,
- 'expire_time' => null,
- 'remaining_times' => $cardType == 1 ? $unitValue * $quantity : 0,
- 'remaining_points' => $cardType == 2 ? $pointsValue * $quantity : 0,
- 'is_used' => 0,
- 'create_time' => date('Y-m-d H:i:s'),
- 'update_time' => date('Y-m-d H:i:s')
- ];
- $generalAllocationId = Db::table('ba_company_package_allocation')->insertGetId($generalAllocationData);
- // 2. 为购买者创建独立的分配记录
- $buyerAllocationData = [
- 'order_item_id' => $item['id'],
- 'order_id' => $orderId,
- 'package_price_id' => $packagePriceId,
- 'product_id' => $item['product_id'],
- 'buyer_id' => $buyerId,
- 'company_id' => $companyId,
- 'assigned_to_user_id' => $buyerId,
- 'assigned_by_user_id' => $buyerId,
- 'record_type' => 1, // 用户分配记录
- 'is_general' => 0,
- 'seat_index' => 0,
- 'parent_id' => $generalAllocationId, // 关联通用记录
- 'allocation_status' => 1, // 已分配
- 'allocation_time' => date('Y-m-d H:i:s'),
- 'start_time' => date('Y-m-d H:i:s'),
- 'end_time' => null,
- 'expire_time' => null,
- 'remaining_times' => $cardType == 1 ? $unitValue : 0,
- 'remaining_points' => $cardType == 2 ? $pointsValue : 0,
- 'is_used' => 0,
- 'create_time' => date('Y-m-d H:i:s'),
- 'update_time' => date('Y-m-d H:i:s')
- ];
- $buyerAllocationId = Db::table('ba_company_package_allocation')->insertGetId($buyerAllocationData);
- // 3. 将购买者添加到授权列表
- $seats = Db::table('ba_company_package_seats')
- ->where('id', $seatsId)
- ->find();
- $authorizedUsers = json_decode($seats['authorized_users'] ?? '[]', true);
- if (!in_array($buyerId, $authorizedUsers)) {
- $authorizedUsers[] = $buyerId;
- Db::table('ba_company_package_seats')
- ->where('id', $seatsId)
- ->update([
- 'authorized_users' => json_encode($authorizedUsers),
- 'assigned_member_count' => Db::raw('assigned_member_count + 1')
- ]);
- }
- }
- // 更新订单商品的分配记录ID(对于日期卡,记录第一个分配记录的ID)
- if ($cardType >= 3) {
- // 获取第一个分配记录ID
- $firstAllocation = Db::table('ba_company_package_allocation')
- ->where('order_item_id', $item['id'])
- ->where('record_type', 2)
- ->order('seat_index', 'asc')
- ->find();
- if ($firstAllocation) {
- Db::table('ba_order_item')
- ->where('id', $item['id'])
- ->update(['allocation_id' => $firstAllocation['id']]);
- }
- } else {
- // 次卡/积分卡使用购买者分配记录ID
- Db::table('ba_order_item')
- ->where('id', $item['id'])
- ->update(['allocation_id' => $buyerAllocationId]);
- }
- }
- Db::commit();
- return true;
- } catch (\Throwable $e) {
- Db::rollback();
- Log::error('处理企业套餐购买失败: ' . $e->getMessage());
- throw $e;
- }
- }
- /**
- * 获取可分配的企业套餐列表(区分类型)
- */
- public function getAvailableCompanyPackages($companyId, $operatorId)
- {
- try {
- // 获取用户角色(创建者或成员)
- $isCreator = Db::table('ba_company')
- ->where('id', $companyId)
- ->where('creator_id', $operatorId)
- ->count() > 0;
- // 获取企业所有套餐席位
- $seats = Db::table('ba_company_package_seats')
- ->alias('cs')
- ->leftJoin('ba_package_price pp', 'pp.id = cs.package_price_id')
- ->leftJoin('ba_product p', 'p.id = cs.product_id')
- ->where('cs.company_id', $companyId)
- ->where('cs.available_seats', '>', 0)
- ->where('cs.status', 1)
- ->field('cs.*, pp.spec_name, pp.card_type, pp.type as package_type, p.name as product_name, p.type as product_type, p.link,pp.image')
- ->select();
- // 获取企业所有成员(包括创建者)
- $allMembers = $this->getAllCompanyMembers($companyId);
- // 处理数据
- $result = [];
- foreach ($seats as $seat) {
- // 获取该套餐已分配的成员
- $allocatedMembers = $this->getAllocatedMembersForPackage($companyId, $seat['package_price_id']);
- // 获取该套餐已分配的成员ID列表
- $allocatedMemberIds = array_column($allocatedMembers, 'user_id');
- // 筛选未分配的成员
- $unallocatedMembers = [];
- foreach ($allMembers as $member) {
- if (!in_array($member['user_id'], $allocatedMemberIds)) {
- $unallocatedMembers[] = $member;
- }
- }
- // 组织返回数据
- $seatItem = [
- 'seats_id' => $seat['id'],
- 'product_id' => $seat['product_id'],
- 'product_name' => $seat['product_name'],
- 'product_type' => $seat['product_type'], // 1:网页,2:软件
- 'product_link' => $seat['link'],
- 'product_image' => $seat['image'],
- 'package_price_id' => $seat['package_price_id'],
- 'spec_name' => $seat['spec_name'],
- 'card_type' => $seat['card_type'],
- 'card_type_text' => $this->getCardTypeText($seat['card_type']),
- 'package_type' => $seat['package_type'], // 1个人,2企业
- 'total_seats' => $seat['total_seats'],
- 'assigned_seats' => $seat['assigned_seats'],
- 'available_seats' => $seat['available_seats'],
- // 次卡和积分卡相关
- 'total_times' => $seat['total_times'],
- 'remaining_times' => $seat['remaining_times'],
- 'total_points' => $seat['total_points'],
- 'remaining_points' => $seat['remaining_points'],
- 'end_time' => $seat['end_time'],
- // 已分配成员信息
- 'allocated_members' => $allocatedMembers,
- // 未分配成员信息
- 'unallocated_members' => $unallocatedMembers,
- // 统计信息
- 'allocated_count' => count($allocatedMembers),
- 'unallocated_count' => count($unallocatedMembers),
- 'total_members' => count($allMembers)
- ];
- $result[] = $seatItem;
- }
- return [
- 'packages' => $result,
- 'is_creator' => $isCreator,
- 'total_members' => count($allMembers)
- ];
- } catch (\Throwable $e) {
- Log::error('获取可分配企业套餐失败: ' . $e->getMessage());
- return [
- 'packages' => [],
- 'is_creator' => false,
- 'total_members' => 0
- ];
- }
- }
- /**
- * 获取企业所有成员(包括创建者)
- */
- private function getAllCompanyMembers($companyId)
- {
- $members = [];
- // 1. 获取企业创建者
- $company = Db::table('ba_company')
- ->where('id', $companyId)
- ->field('id, name as company_name, creator_id')
- ->find();
- if ($company && $company['creator_id']) {
- // 获取创建者用户信息
- $creator = Db::table('ba_user')
- ->where('id', $company['creator_id'])
- ->field('id as user_id, nickname as member_name, avatar, email, mobile')
- ->find();
- if ($creator) {
- $creator['is_creator'] = 1;
- $creator['role'] = 1; // 创建者/管理员
- $members[] = $creator;
- }
- }
- // 2. 获取企业成员表中的成员
- $companyMembers = Db::table('ba_company_member')
- ->alias('cm')
- ->leftJoin('ba_user u', 'u.id = cm.user_id')
- ->where('cm.company_id', $companyId)
- ->where('cm.status', 1)
- ->field('
- cm.id as member_id,
- cm.user_id,
- COALESCE(cm.name, u.nickname) as member_name,
- COALESCE(cm.email, u.email) as email,
- u.avatar,
- u.mobile,
- cm.role
- ')
- ->select()
- ->toArray();
- // 过滤掉重复的成员(创建者可能也在成员表中)
- foreach ($companyMembers as $member) {
- // 检查是否已经是创建者
- $isCreator = false;
- foreach ($members as $existingMember) {
- if ($existingMember['user_id'] == $member['user_id']) {
- $isCreator = true;
- break;
- }
- }
- if (!$isCreator) {
- $member['is_creator'] = 0;
- $members[] = $member;
- }
- }
- return $members;
- }
- /**
- * 获取指定套餐已分配的成员
- */
- private function getAllocatedMembersForPackage($companyId, $packagePriceId)
- {
- // 获取套餐信息,判断卡类型
- $package = Db::table('ba_package_price')
- ->where('id', $packagePriceId)
- ->field('card_type')
- ->find();
- if (!$package) {
- return [];
- }
- $cardType = $package['card_type'];
- if ($cardType >= 3) {
- // 日期卡:从分配记录中获取已分配成员
- return Db::table('ba_company_package_allocation')
- ->alias('cpa')
- ->leftJoin('ba_user u', 'u.id = cpa.assigned_to_user_id')
- ->leftJoin('ba_company_member cm', 'cm.user_id = cpa.assigned_to_user_id AND cm.company_id = cpa.company_id')
- ->where('cpa.company_id', $companyId)
- ->where('cpa.package_price_id', $packagePriceId)
- ->where('cpa.allocation_status', 1) // 已分配
- ->whereNotNull('cpa.assigned_to_user_id')
- ->field('
- cpa.assigned_to_user_id as user_id,
- COALESCE(cm.name, u.nickname) as member_name,
- COALESCE(cm.email, u.email) as email,
- u.avatar,
- u.mobile,
- cpa.allocation_time,
- cpa.start_time,
- cpa.end_time,
- cpa.remaining_times,
- cpa.remaining_points
- ')
- ->select()
- ->toArray();
- } else {
- // 次卡/积分卡:从席位表的授权用户列表中获取
- $seats = Db::table('ba_company_package_seats')
- ->where('company_id', $companyId)
- ->where('package_price_id', $packagePriceId)
- ->field('authorized_users')
- ->find();
- if (!$seats || empty($seats['authorized_users'])) {
- return [];
- }
- $authorizedUserIds = json_decode($seats['authorized_users'], true);
- if (empty($authorizedUserIds)) {
- return [];
- }
- // 获取授权用户的详细信息
- $user=Db::table('ba_user')
- ->alias('u')
- // 使用字符串条件替代闭包
- ->leftJoin('ba_company_member cm', 'cm.user_id = u.id AND cm.company_id = ' . $companyId)
- ->whereIn('u.id', $authorizedUserIds)
- ->field('
- u.id as user_id,
- COALESCE(cm.name, u.nickname) as member_name,
- COALESCE(cm.email, u.email) as email,
- u.avatar,
- u.mobile,
- cm.role
- ')
- ->select()
- ->toArray();
- return $user;
- }
- }
- /**
- * 分配套餐给企业成员
- */
- public function allocatePackage($seatsId, $assignedToUserId, $operatorId, $remark = '')
- {
- Db::startTrans();
- try {
- // 1. 获取席位信息
- $seats = Db::table('ba_company_package_seats')
- ->where('id', $seatsId)
- ->lock(true)
- ->find();
- if (!$seats || $seats['available_seats'] <= 0) {
- throw new \Exception('没有可用席位');
- }
- // 2. 检查是否是日期卡
- if ($seats['card_type'] < 3) {
- throw new \Exception('非日期卡类型,请使用assignPackagePermission方法');
- }
- // 3. 检查权限(只有创建者可以分配其他人的,成员只能分配自己的)
- $isCreator = Db::table('ba_company')
- ->where('id', $seats['company_id'])
- ->where('creator_id', $operatorId)
- ->count() > 0;
- // 4. 获取一个未分配的购买记录
- $availableAllocation = Db::table('ba_company_package_allocation')
- ->where('company_id', $seats['company_id'])
- ->where('package_price_id', $seats['package_price_id'])
- ->where('record_type', 2) // 购买记录
- ->where('allocation_status', 0) // 未分配
- ->where('assigned_to_user_id', null) // 未指定用户
- ->lock(true)
- ->order('seat_index', 'asc') // 按席位索引排序
- ->find();
- if (!$availableAllocation) {
- throw new \Exception('没有可分配的套餐记录');
- }
- // 如果不是创建者,检查是否是购买者
- if (!$isCreator && $availableAllocation['buyer_id'] != $operatorId) {
- throw new \Exception('您只能分配自己购买的套餐');
- }
- // 5. 检查成员是否属于该企业
- $isMember = Db::table('ba_company_member')
- ->where('company_id', $seats['company_id'])
- ->where('user_id', $assignedToUserId)
- ->where('status', 1)
- ->count() > 0;
- if (!$isMember) {
- throw new \Exception('该用户不是企业成员');
- }
- // 6. 检查该成员是否已分配此套餐(日期卡只能分配给一个成员)
- if ($seats['card_type'] >= 3) { // 日期卡
- $alreadyAllocated = Db::table('ba_company_package_allocation')
- ->where('company_id', $seats['company_id'])
- ->where('package_price_id', $seats['package_price_id'])
- ->where('assigned_to_user_id', $assignedToUserId)
- ->where('allocation_status', 1)
- ->count();
- if ($alreadyAllocated > 0) {
- throw new \Exception('该成员已分配此套餐,如需再次分配请重新购买');
- }
- }
- // 7. 执行分配
- $now = date('Y-m-d H:i:s');
- // 计算到期时间
- $endTime = $this->calculateEndTime($seats['card_type'], $now);
- // 更新分配记录
- Db::table('ba_company_package_allocation')
- ->where('id', $availableAllocation['id'])
- ->update([
- 'assigned_to_user_id' => $assignedToUserId,
- 'assigned_by_user_id' => $operatorId,
- 'allocation_status' => 1,
- 'allocation_time' => $now,
- 'start_time' => $now,
- 'end_time' => $endTime,
- 'expire_time' => $endTime, // 更新冗余字段
- 'update_time' => $now
- ]);
- // 8.更新席位表
- Db::table('ba_company_package_seats')
- ->where('id', $seatsId)
- ->update([
- 'assigned_seats' => Db::raw('assigned_seats + 1'),
- 'available_seats' => Db::raw('available_seats - 1'),
- 'update_time' => $now
- ]);
- // 9. 检查是否所有席位都已分配
- $unallocatedCount = Db::table('ba_company_package_allocation')
- ->where('order_item_id', $availableAllocation['order_item_id'])
- ->where('allocation_status', 0)
- ->where('record_type', 2)
- ->count();
- if ($unallocatedCount == 0) {
- // 所有席位都已分配,更新订单商品
- Db::table('ba_order_item')
- ->where('id', $availableAllocation['order_item_id'])
- ->update([
- 'is_allocated' => 1,
- 'company_id' => $seats['company_id']
- ]);
- }
- // 10. 为用户创建产品使用记录
- $userProductService = new UserProductService();
- $userProductService->createCompanyProductUsage($availableAllocation, $assignedToUserId, $seats['card_type']);
- // 11. 记录分配日志
- Db::table('ba_allocation_log')->insert([
- 'allocation_id' => $availableAllocation['id'],
- 'action' => 1, // 分配
- 'operator_id' => $operatorId,
- 'to_user_id' => $assignedToUserId,
- 'remark' => $remark,
- 'create_time' => $now
- ]);
- Db::commit();
- return [
- 'success' => true,
- 'allocation_id' => $availableAllocation['id'],
- 'message' => '分配成功'
- ];
- } catch (\Throwable $e) {
- Db::rollback();
- Log::error('分配套餐失败: ' . $e->getMessage());
- throw $e;
- }
- }
- /**
- * 取消分配(日期卡独占席位模式)
- */
- public function cancelAllocation($allocationId, $operatorId, $remark = '')
- {
- Db::startTrans();
- try {
- // 1. 获取分配记录
- $allocation = Db::table('ba_company_package_allocation')
- ->where('id', $allocationId)
- ->where('record_type', 2) // 购买记录
- ->where('allocation_status', 1) // 已分配
- ->lock(true)
- ->find();
- if (!$allocation) {
- throw new \Exception('分配记录不存在或未分配');
- }
- // 2. 检查权限
- $isCreator = Db::table('ba_company')
- ->where('id', $allocation['company_id'])
- ->where('creator_id', $operatorId)
- ->count() > 0;
- if (!$isCreator && $allocation['assigned_by_user_id'] != $operatorId) {
- throw new \Exception('您没有取消分配的权限');
- }
- // 3. 获取席位信息
- $seats = Db::table('ba_company_package_seats')
- ->where('company_id', $allocation['company_id'])
- ->where('package_price_id', $allocation['package_price_id'])
- ->find();
- if (!$seats) {
- throw new \Exception('企业套餐席位不存在');
- }
- // 4. 执行取消分配
- $now = date('Y-m-d H:i:s');
- // 更新分配记录状态
- Db::table('ba_company_package_allocation')
- ->where('id', $allocationId)
- ->update([
- 'assigned_to_user_id' => null,
- 'allocation_status' => 2,
- 'cancel_allocation_time' => $now,
- 'update_time' => $now
- ]);
- // 5. 更新席位表
- Db::table('ba_company_package_seats')
- ->where('id', $seats['id'])
- ->update([
- 'assigned_seats' => Db::raw('assigned_seats - 1'),
- 'available_seats' => Db::raw('available_seats + 1'),
- 'update_time' => $now
- ]);
- // 6. 检查是否还有已分配的记录
- $allocatedCount = Db::table('ba_company_package_allocation')
- ->where('order_item_id', $allocation['order_item_id'])
- ->where('allocation_status', 1)
- ->count();
- if ($allocatedCount == 0) {
- // 没有已分配的记录,更新订单商品
- Db::table('ba_order_item')
- ->where('id', $allocation['order_item_id'])
- ->update([
- 'is_allocated' => 0,
- 'allocation_id' => null
- ]);
- }
- // 7. 删除对应的用户产品使用记录
- Db::table('ba_user_product_usage')
- ->where('user_id', $allocation['assigned_to_user_id'])
- ->where('package_price_id', $allocation['package_price_id'])
- ->where('company_id', $allocation['company_id'])
- ->where('package_type', 2) // 企业套餐
- ->delete();
- // 8. 记录取消分配日志
- Db::table('ba_allocation_log')->insert([
- 'allocation_id' => $allocationId,
- 'action' => 2, // 取消分配
- 'operator_id' => $operatorId,
- 'from_user_id' => $allocation['assigned_to_user_id'],
- 'remark' => $remark,
- 'create_time' => $now
- ]);
- Db::commit();
- return true;
- } catch (\Throwable $e) {
- Db::rollback();
- Log::error('取消分配失败: ' . $e->getMessage());
- throw $e;
- }
- }
- /**
- * 分配次卡/积分卡使用权限给成员(授权访问共享资源池)
- */
- public function assignPackagePermission($seatsId, $memberUserId, $allocatorId, $remark = '')
- {
- Db::startTrans();
- try {
- // 1. 获取席位信息
- $seats = Db::table('ba_company_package_seats')
- ->where('id', $seatsId)
- ->lock(true)
- ->find();
- if (!$seats) {
- throw new \Exception('企业套餐不存在');
- }
- // 2. 检查权限(只有企业创建者或购买者可以分配)
- $canAssign = $this->checkAssignPermission($allocatorId, $seats['company_id'], $seatsId);
- if (!$canAssign) {
- throw new \Exception('没有分配权限');
- }
- // 3. 检查成员是否属于企业
- if (!$this->isCompanyMember($memberUserId, $seats['company_id'])) {
- throw new \Exception('该用户不是企业成员');
- }
- // 4. 检查是否已经是次卡或积分卡
- if (!in_array($seats['card_type'], [1, 2])) {
- throw new \Exception('只有次卡和积分卡支持权限分配');
- }
- // 5. 检查该成员是否已被授权
- $authorizedUsers = json_decode($seats['authorized_users'] ?? '[]', true);
- if (in_array($memberUserId, $authorizedUsers)) {
- throw new \Exception('该成员已被授权使用此套餐');
- }
- // 6. 查找通用记录
- $generalRecord = Db::table('ba_company_package_allocation')
- ->where('company_id', $seats['company_id'])
- ->where('package_price_id', $seats['package_price_id'])
- ->where('record_type', 0) // 通用记录
- ->where('is_general', 1) // 是通用记录
- ->order('id', 'asc')
- ->find();
- if (!$generalRecord) {
- throw new \Exception('未找到套餐购买记录');
- }
- // 7. 将成员添加到授权列表
- $authorizedUsers[] = $memberUserId;
- Db::table('ba_company_package_seats')
- ->where('id', $seatsId)
- ->update([
- 'authorized_users' => json_encode($authorizedUsers),
- 'assigned_member_count' => Db::raw('assigned_member_count + 1'),
- 'update_time' => date('Y-m-d H:i:s')
- ]);
- // 8. 创建新的分配记录
- $now = date('Y-m-d H:i:s');
- $newAllocationData = [
- 'order_item_id' => $generalRecord['order_item_id'],
- 'order_id' => $generalRecord['order_id'],
- 'package_price_id' => $seats['package_price_id'],
- 'product_id' => $seats['product_id'],
- 'buyer_id' => $generalRecord['buyer_id'],
- 'company_id' => $seats['company_id'],
- 'assigned_to_user_id' => $memberUserId,
- 'assigned_by_user_id' => $allocatorId,
- 'record_type' => 1, // 用户分配记录
- 'is_general' => 0,
- 'seat_index' => 0,
- 'parent_id' => $generalRecord['id'], // 关联通用记录
- 'allocation_status' => 1, // 已分配
- 'allocation_time' => $now,
- 'start_time' => $now,
- 'end_time' => null,
- 'expire_time' => null,
- 'remaining_times' => $seats['remaining_times'],
- 'remaining_points' => $seats['remaining_points'],
- 'is_used' => 0,
- 'create_time' => $now,
- 'update_time' => $now
- ];
- $allocationId = Db::table('ba_company_package_allocation')->insertGetId($newAllocationData);
- // 9. 为用户创建产品使用记录
- $userProductService = new UserProductService();
- $orderItem = Db::table('ba_order_item')->where('id', $generalRecord['order_item_id'])->find();
- if ($orderItem) {
- $package = Db::table('ba_package_price')->where('id', $seats['package_price_id'])->find();
- if ($package) {
- $userProductService->createUserProductRecord($memberUserId, $orderItem, $package);
- }
- }
- // 10. 记录分配日志
- Db::table('ba_allocation_log')->insert([
- 'allocation_id' => $allocationId,
- 'action' => 1, // 分配
- 'operator_id' => $allocatorId,
- 'to_user_id' => $memberUserId,
- 'remark' => $remark ?: '分配次卡/积分卡使用权限',
- 'create_time' => $now
- ]);
- Db::commit();
- return [
- 'success' => true,
- 'allocation_id' => $allocationId,
- 'message' => '分配成功'
- ];
- } catch (\Throwable $e) {
- Db::rollback();
- throw $e;
- }
- }
- /**
- * 检查分配权限
- */
- private function checkAssignPermission($userId, $companyId, $seatsId = null)
- {
- // 1. 检查是否是公司创建者
- $isCreator = Db::table('ba_company')
- ->where('id', $companyId)
- ->where('creator_id', $userId)
- ->count() > 0;
- if ($isCreator) {
- return true;
- }
- // 2. 检查是否是购买者(对于该套餐)
- if ($seatsId) {
- $isBuyer = Db::table('ba_company_package_allocation')
- ->where('seats_id', $seatsId)
- ->where('buyer_id', $userId)
- ->count() > 0;
- if ($isBuyer) {
- return true;
- }
- }
- // 3. 检查是否是管理员(根据企业成员表)
- $isAdmin = Db::table('ba_company_member')
- ->where('company_id', $companyId)
- ->where('user_id', $userId)
- ->where('role', 1) // 1=管理员
- ->where('status', 1)
- ->count() > 0;
- return $isAdmin;
- }
- /**
- * 检查用户是否是企业成员
- */
- private function isCompanyMember($userId, $companyId)
- {
- // 检查是否是创建者
- $isCreator = Db::table('ba_company')
- ->where('id', $companyId)
- ->where('creator_id', $userId)
- ->count() > 0;
- if ($isCreator) {
- return true;
- }
- // 检查是否是成员
- $isMember = Db::table('ba_company_member')
- ->where('company_id', $companyId)
- ->where('user_id', $userId)
- ->where('status', 1)
- ->count() > 0;
- return $isMember;
- }
- /**
- * 自动分配席位给购买者
- */
- public function autoAllocateToBuyer($buyerId, $companyId, $packagePriceId, $orderId)
- {
- try {
- Log::info('开始自动分配席位给购买者', [
- 'buyer_id' => $buyerId,
- 'company_id' => $companyId,
- 'package_price_id' => $packagePriceId,
- 'order_id' => $orderId
- ]);
- // 1. 检查购买者是否已分配此套餐
- $alreadyAllocated = Db::table('ba_company_package_allocation')
- ->where('company_id', $companyId)
- ->where('package_price_id', $packagePriceId)
- ->where('assigned_to_user_id', $buyerId)
- ->where('allocation_status', 1) // 已分配
- ->count();
- Log::info('检查购买者是否已分配此套餐结果', [
- 'already_allocated' => $alreadyAllocated
- ]);
- if ($alreadyAllocated > 0) {
- Log::info('购买者已分配此套餐,跳过自动分配', [
- 'buyer_id' => $buyerId,
- 'company_id' => $companyId,
- 'package_price_id' => $packagePriceId
- ]);
- return false; // 已分配,跳过
- }
- // 2. 获取可用的席位ID(从席位表中获取)
- $seats = Db::table('ba_company_package_seats')
- ->where('company_id', $companyId)
- ->where('package_price_id', $packagePriceId)
- ->where('available_seats', '>', 0)
- ->find();
- Log::info('查询可用席位结果', [
- 'seats' => $seats ? $seats['id'] : null,
- 'available_seats' => $seats ? $seats['available_seats'] : 0
- ]);
- if (!$seats) {
- Log::error('没有可用席位进行自动分配', [
- 'company_id' => $companyId,
- 'package_price_id' => $packagePriceId
- ]);
- return false;
- }
- // 3. 获取一个未分配的分配记录
- $allocation = Db::table('ba_company_package_allocation')
- ->where('order_id', $orderId)
- ->where('company_id', $companyId)
- ->where('package_price_id', $packagePriceId)
- ->where('allocation_status', 0) // 未分配
- ->order('id', 'asc')
- ->find();
- Log::info('查询未分配记录结果', [
- 'allocation' => $allocation ? $allocation['id'] : null,
- 'order_id' => $orderId
- ]);
- if (!$allocation) {
- // 尝试查找任何属于该订单的未分配记录
- $allocation = Db::table('ba_company_package_allocation')
- ->where('order_id', $orderId)
- ->where('allocation_status', 0)
- ->order('id', 'asc')
- ->find();
- Log::info('二次查询未分配记录结果', [
- 'allocation' => $allocation ? $allocation['id'] : null
- ]);
- if (!$allocation) {
- Log::error('没有找到未分配的分配记录', [
- 'order_id' => $orderId,
- 'company_id' => $companyId,
- 'package_price_id' => $packagePriceId
- ]);
- return false;
- }
- }
- // 4. 获取套餐信息(用于卡类型判断)
- $package = Db::table('ba_package_price')
- ->where('id', $packagePriceId)
- ->find();
- if (!$package) {
- Log::error('套餐信息不存在', ['package_price_id' => $packagePriceId]);
- return false;
- }
- Db::startTrans();
- try {
- // 5. 执行分配
- $now = date('Y-m-d H:i:s');
- // 更新分配记录
- Db::table('ba_company_package_allocation')
- ->where('id', $allocation['id'])
- ->update([
- 'assigned_to_user_id' => $buyerId,
- 'assigned_by_user_id' => $buyerId,
- 'allocation_status' => 1,
- 'allocation_time' => $now,
- 'start_time' => $now,
- 'end_time' => $this->calculateEndTime($package['card_type'], $now),
- 'update_time' => $now
- ]);
- // 更新席位表
- Db::table('ba_company_package_seats')
- ->where('id', $seats['id'])
- ->update([
- 'assigned_seats' => Db::raw('assigned_seats + 1'),
- 'available_seats' => Db::raw('available_seats - 1'),
- 'update_time' => $now
- ]);
- // 更新订单商品
- Db::table('ba_order_item')
- ->where('id', $allocation['order_item_id'])
- ->update([
- 'is_allocated' => 1,
- 'company_id' => $companyId
- ]);
- // 6. 记录分配日志
- Db::table('ba_allocation_log')->insert([
- 'allocation_id' => $allocation['id'],
- 'action' => 1, // 分配
- 'operator_id' => $buyerId,
- 'to_user_id' => $buyerId,
- 'remark' => '购买后自动分配给购买者',
- 'create_time' => $now
- ]);
- // 7. 根据卡类型创建用户产品记录
- $userProductService = new UserProductService();
- // 所有卡类型都需要创建使用记录
- if ($package['card_type'] >= 3) { // 日期卡
- // 日期卡分配时创建使用记录
- $userProductService->createCompanyProductUsage($allocation, $buyerId, $package['card_type']);
- } else { // 次卡(1)和积分卡(2)
- // 获取订单商品信息
- $orderItem = Db::table('ba_order_item')
- ->where('id', $allocation['order_item_id'])
- ->find();
- if ($orderItem) {
- // 创建用户产品记录(次卡/积分卡)
- $userProductService->createUserProductRecord($buyerId, $orderItem, $package);
- }
- }
- Db::commit();
- Log::info('企业套餐自动分配给购买者成功', [
- 'buyer_id' => $buyerId,
- 'company_id' => $companyId,
- 'package_price_id' => $packagePriceId,
- 'allocation_id' => $allocation['id']
- ]);
- return true;
- } catch (\Throwable $e) {
- Db::rollback();
- Log::error('企业套餐自动分配给购买者失败: ' . $e->getMessage());
- throw $e;
- }
- } catch (\Throwable $e) {
- Log::error('自动分配企业套餐给购买者失败: ' . $e->getMessage());
- return false;
- }
- }
- /**
- * 计算到期时间
- */
- private function calculateEndTime($cardType, $startTime)
- {
- $start = strtotime($startTime);
- switch ($cardType) {
- case 3: // 日卡
- return date('Y-m-d 23:59:59', strtotime('+1 day', $start));
- case 4: // 周卡
- return date('Y-m-d 23:59:59', strtotime('+7 days', $start));
- case 5: // 季卡
- return date('Y-m-d 23:59:59', strtotime('+90 days', $start));
- case 6: // 月卡
- return date('Y-m-d 23:59:59', strtotime('+30 days', $start));
- case 7: // 年卡
- return date('Y-m-d 23:59:59', strtotime('+365 days', $start));
- default:
- return null; // 次卡和积分卡没有固定到期时间
- }
- }
- /**
- * 获取卡类型文本
- */
- private function getCardTypeText($type)
- {
- $map = [
- 1 => '次卡',
- 2 => '积分卡',
- 3 => '日卡',
- 4 => '周卡',
- 5 => '季卡',
- 6 => '月卡',
- 7 => '年卡'
- ];
- return $map[$type] ?? '其他';
- }
- private function getProductIdByPackage($packagePriceId) {
- // 实现获取产品ID的逻辑
- $package = Db::table('ba_package_price')->where('id', $packagePriceId)->find();
- $product = Db::table('ba_product')->where('package_id', $package['package_id'])->find();
- return $product ? $product['id'] : 0;
- }
- private function getOrderBuyerId($orderId) {
- $order = Db::table('ba_order')->where('id', $orderId)->find();
- return $order ? $order['user_id'] : 0;
- }
- /**
- * 取消次卡/积分卡权限分配
- */
- public function cancelPackagePermission($allocationId, $operatorId, $remark = '')
- {
- Db::startTrans();
- try {
- // 1. 获取分配记录
- $allocation = Db::table('ba_company_package_allocation')
- ->where('id', $allocationId)
- ->where('record_type', 1) // 用户分配记录
- ->where('allocation_status', 1) // 已分配
- ->lock(true)
- ->find();
- if (!$allocation) {
- throw new \Exception('分配记录不存在或未分配');
- }
- // 2. 检查权限
- $canCancel = $this->checkAssignPermission($operatorId, $allocation['company_id']);
- if (!$canCancel) {
- throw new \Exception('您没有取消分配的权限');
- }
- // 3. 获取席位信息
- $seats = Db::table('ba_company_package_seats')
- ->where('company_id', $allocation['company_id'])
- ->where('package_price_id', $allocation['package_price_id'])
- ->find();
- if (!$seats) {
- throw new \Exception('企业套餐席位不存在');
- }
- // 4. 从授权列表中移除用户
- $authorizedUsers = json_decode($seats['authorized_users'] ?? '[]', true);
- $key = array_search($allocation['assigned_to_user_id'], $authorizedUsers);
- if ($key !== false) {
- unset($authorizedUsers[$key]);
- $authorizedUsers = array_values($authorizedUsers); // 重新索引数组
- // 更新席位表
- Db::table('ba_company_package_seats')
- ->where('id', $seats['id'])
- ->update([
- 'authorized_users' => json_encode($authorizedUsers),
- 'assigned_member_count' => Db::raw('assigned_member_count - 1'),
- 'update_time' => date('Y-m-d H:i:s')
- ]);
- }
- // 5. 更新分配记录状态
- $now = date('Y-m-d H:i:s');
- Db::table('ba_company_package_allocation')
- ->where('id', $allocationId)
- ->update([
- 'allocation_status' => 2, // 已取消
- 'cancel_allocation_time' => $now,
- 'update_time' => $now
- ]);
- // 6. 删除对应的用户产品使用记录
- Db::table('ba_user_product_usage')
- ->where('user_id', $allocation['assigned_to_user_id'])
- ->where('package_price_id', $allocation['package_price_id'])
- ->where('company_id', $allocation['company_id'])
- ->where('package_type', 2) // 企业套餐
- ->delete();
- // 7. 记录取消分配日志
- Db::table('ba_allocation_log')->insert([
- 'allocation_id' => $allocationId,
- 'action' => 2, // 取消分配
- 'operator_id' => $operatorId,
- 'from_user_id' => $allocation['assigned_to_user_id'],
- 'remark' => $remark ?: '取消次卡/积分卡使用权限',
- 'create_time' => $now
- ]);
- Db::commit();
- return true;
- } catch (\Throwable $e) {
- Db::rollback();
- Log::error('取消次卡/积分卡权限失败: ' . $e->getMessage());
- throw $e;
- }
- }
- /**
- * 使用企业次卡/积分卡(从共享资源池扣除)
- */
- public function useSharedCompanyPackage($userId, $packagePriceId, $useQuantity, $productId = null, $remark = '')
- {
- Db::startTrans();
- try {
- // 1. 获取用户所在企业
- $companyInfo = $this->getUserCompany($userId);
- if (!$companyInfo) {
- throw new \Exception('您不属于任何企业');
- }
- // 2. 获取套餐信息
- $package = Db::table('ba_package_price')
- ->where('id', $packagePriceId)
- ->find();
- if (!$package) {
- throw new \Exception('套餐不存在');
- }
- // 3. 检查卡类型是否为次卡或积分卡
- if (!in_array($package['card_type'], [1, 2])) {
- throw new \Exception('只有次卡和积分卡支持此使用方式');
- }
- // 4. 获取企业套餐席位信息,检查用户是否被授权
- $seats = Db::table('ba_company_package_seats')
- ->where('company_id', $companyInfo['id'])
- ->where('package_price_id', $packagePriceId)
- ->lock(true)
- ->find();
- if (!$seats) {
- throw new \Exception('企业套餐不存在');
- }
- // 检查用户是否在授权列表中
- $authorizedUsers = json_decode($seats['authorized_users'] ?? '[]', true);
- if (!in_array($userId, $authorizedUsers)) {
- throw new \Exception('您未被授权使用此套餐');
- }
- // 5. 检查共享资源池是否足够
- if ($package['card_type'] == 1) { // 次卡
- if ($seats['remaining_times'] < $useQuantity) {
- throw new \Exception('剩余次数不足,剩余:' . $seats['remaining_times'] . '次');
- }
- } elseif ($package['card_type'] == 2) { // 积分卡
- if ($seats['remaining_points'] < $useQuantity) {
- throw new \Exception('剩余积分不足,剩余:' . $seats['remaining_points'] . '积分');
- }
- }
- // 6. 获取用户的分配记录
- $userAllocation = Db::table('ba_company_package_allocation')
- ->where('company_id', $companyInfo['id'])
- ->where('package_price_id', $packagePriceId)
- ->where('assigned_to_user_id', $userId)
- ->where('allocation_status', 1)
- ->order('id', 'asc')
- ->find();
- if (!$userAllocation) {
- throw new \Exception('未找到您的分配记录');
- }
- // 7. 扣减共享池资源
- if ($package['card_type'] == 1) { // 次卡
- Db::table('ba_company_package_seats')
- ->where('id', $seats['id'])
- ->dec('remaining_times', $useQuantity)
- ->update();
- $remainingTimesAfter = $seats['remaining_times'] - $useQuantity;
- $remainingPointsAfter = $seats['remaining_points'];
- } else { // 积分卡
- Db::table('ba_company_package_seats')
- ->where('id', $seats['id'])
- ->dec('remaining_points', $useQuantity)
- ->update();
- $remainingTimesAfter = $seats['remaining_times'];
- $remainingPointsAfter = $seats['remaining_points'] - $useQuantity;
- }
- // 8. 更新分配记录的使用状态
- Db::table('ba_company_package_allocation')
- ->where('id', $userAllocation['id'])
- ->update([
- 'is_used' => 1,
- 'usage_count' => Db::raw('usage_count + ' . $useQuantity),
- 'update_time' => date('Y-m-d H:i:s')
- ]);
- // 9. 记录使用明细
- $usageData = [
- 'allocation_id' => $userAllocation['id'],
- 'company_id' => $companyInfo['id'],
- 'package_price_id' => $packagePriceId,
- 'user_id' => $userId,
- 'card_type' => $package['card_type'],
- 'used_quantity' => $useQuantity,
- 'remaining_times_after' => $remainingTimesAfter,
- 'remaining_points_after' => $remainingPointsAfter,
- 'product_id' => $productId,
- 'usage_time' => date('Y-m-d H:i:s'),
- 'remark' => $remark,
- 'create_time' => date('Y-m-d H:i:s')
- ];
- $usageId = Db::table('ba_company_package_usage')->insertGetId($usageData);
- Db::commit();
- return [
- 'success' => true,
- 'usage_id' => $usageId,
- 'remaining_times' => $remainingTimesAfter,
- 'remaining_points' => $remainingPointsAfter,
- 'message' => '使用成功'
- ];
- } catch (\Throwable $e) {
- Db::rollback();
- Log::error('使用企业次卡/积分卡失败: ' . $e->getMessage());
- throw $e;
- }
- }
- }
|