new \Where(\Where::_and([ \Where::_operator(self::$ARCHIVE,'=',ESoftSubscribeStatus::ACTIVE), \Where::_operator(self::$PROFILE,'=',$pid), \Where::_operator(self::$SUPER,'=',1), ])), \Query::COUNT => 1, ]); return boolval(\DB::numRows($r)); } static function payForSoft($soft_id,$pid = PID){ // 1. Проверяем, есть ли бесплатные дни доступа // 1.1. Если есть, то начинаем списываем один бесплатный день // 1.2. Есть нет, то списываем первый платёж. $subscribe = self::getByProfileAndSoft($soft_id,$pid); if(!$subscribe) return; // Получаем информацию о софте и сколько всего бесплатных дней есть. $soft = Soft::getByID($soft_id); $free_days = $soft[Soft::$FREE_DAYS]; // Теперь надо выяснить, сколько дней мы ужи списали $subscribe_id = $subscribe[Subscribe::$ID]; $r = Free::select([ \Query::SELECT => ['COUNT('.Subscribe::$ID.') as cc'], \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(Free::$SOFT,'=',$soft_id), \Where::_operator(Free::$PROFILE,'=',$pid), ])) ]); $l = \DB::fetch($r); $used = intval($l['cc']); // Если бесплатных дней использовано меньше, чем доступно, то списываем их if($used < $free_days) { Free::insert([ Free::$DATE => date('Y-m-d'), Free::$SOFT => $soft_id, Free::$SUBSCRIBE => $subscribe_id, Free::$PROFILE => $pid, ]); // Иначе списываем деньги с баланса } else { Payment::add([ Payment::$PROFILE => $pid, Payment::$VALUE => -$subscribe[Subscribe::$PRICE], Payment::$SUBSCRIBE => $subscribe_id, Payment::$SOFT => $soft_id, Payment::$DATE => date('Y-m-d'), ]); } } static function startSoftSubscribe($soft_id,$pid = PID):bool{ // 1. Надо определить, нет ли уже супер подписки // 2. Надо определить, нет ли уже такой подписки // 3. Если всё нормально, стартуем подписку // 4. Осуществляем первый платёж $soft_id = intval($soft_id); $pid = intval($pid); if(!$soft_id || !$pid) return false; $isSuper = self::hasSuperSubscribe($pid); if($isSuper) return false; $subscribe = self::getByProfileAndSoft($soft_id,$pid); if($subscribe) return false; $soft = soft::getByID($soft_id); // Если подписки нет, то стартуем подписку Subscribe::insert([ self::$SOFT => $soft_id, self::$PROFILE => $pid, self::$PRICE => $soft[Soft::$PRICE], ]); // Теперь производим оплату за первый день self::payForSoft($soft_id,$pid); return true; } static function startGroupSoftSubscribe($group_id,$pid=PID):bool{ // А этой функцией стартуем групповую подписку // 1. Сначала надо определить, нет ли супер подписки // 2. Если такой нет. То ищем группу и проверяем, активна ли она // 3. Если активна, то отменяем все подписки на софт, которые есть в этой группе и уже есть у этого пользователя // 4. Создаём новые подписки на софт из группы по стоимости из группы. $group_id = intval($group_id); $pid = intval($pid); if(!$group_id || !$pid) return false; $isSuper = self::hasSuperSubscribe($pid); if($isSuper) return false; $group = Group::getByID($group_id); if(!$group || !$group[Group::$ACTIVE]) return false; // Получаем список программ на которые подписываемся $a = GroupSoft::select([ \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(GroupSoft::$GROUP,'=',$group_id), ])) ],true); $soft_ids = []; foreach ($a as $v){ $soft_ids[] = $v[GroupSoft::$SOFT]; } if(!$soft_ids) return false; // Отменяем текущие подписки Subscribe::update(new \Where(\Where::_and([ \Where::_operator(Subscribe::$PROFILE,'=',$pid), \Where::_operator(Subscribe::$ARCHIVE,'=',ESoftSubscribeStatus::ACTIVE), \Where::_in(Subscribe::$SOFT,$soft_ids), ])),[ Subscribe::$ARCHIVE=>ESoftSubscribeStatus::PAUSE , ]); // Создаём новые подписки // И берём за них первый платёж foreach ($a as $v){ $price = $v[GroupSoft::$PRICE]; $soft_id = $v[GroupSoft::$SOFT]; $r = Subscribe::insert([ self::$SOFT => $soft_id, self::$PROFILE => $pid, self::$GROUP => $group_id, self::$PRICE => $price, ]); Payment::add([ Payment::$PROFILE => $pid, Payment::$VALUE => -$price, Payment::$SUBSCRIBE => $r->id, Payment::$SOFT => $soft_id, Payment::$DATE => date('Y-m-d'), ]); } return true; } static function startSuperSubscribe($group_id,$pid = PID):bool{ // 1. Находим выбранную подписку // 2. Проверяем, активная ли она и является ли супер подпиской. // 3. Если да, то отменяем все остальные подписки и начинаем супер подписку. // 4. Ну и списываем первый платёж $group_id = intval($group_id); $pid = intval($pid); $group = Group::getByID($group_id); if($group[Group::$ACTIVE] and $group[Group::$SUPER]){ // Отменяем текущие подписки Subscribe::update(new \Where(\Where::_and([ \Where::_operator(Subscribe::$PROFILE,'=',$pid), ])),[ Subscribe::$ARCHIVE=>ESoftSubscribeStatus::ARCHIVE, ]); $price = $group[Group::$TOTAL]; $r = Subscribe::insert([ self::$PROFILE => $pid, self::$GROUP => $group_id, self::$PRICE => $price, self::$SUPER => 1, ]); $subscribe_id = $r->id; $date = date('Y-m-d'); $a =Payment::select([ \Query::LEFT_JOINS =>[ [Subscribe::$table_name,Subscribe::$ID,Payment::$SUBSCRIBE] ], \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(Payment::$PROFILE,'=',$pid), \Where::_operator(Payment::$SOFT,'=',0), \Where::_operator(Payment::$DATE,'=',$date), \Where::_operator(Subscribe::$GROUP,'=',$group_id), ])), \Query::COUNT => 1, ],true); if(!$a) { Payment::add([ Payment::$PROFILE => $pid, Payment::$VALUE => -$price, Payment::$SUBSCRIBE => $subscribe_id, Payment::$SOFT => 0, Payment::$DATE => $date, ]); } return true; } return false; } static function cancelSuperSubscribe($subscribe_id,$pid=PID):bool{ // 1. Получаем информацию о подписке // 2. Проверяем, принадлежит ли пользователю и активна ли она и является ли она супер подпиской // 3. Если всё норм, то отменяем $subscribe_id = intval($subscribe_id); $pid = intval($pid); $subscribe = Subscribe::getByID($subscribe_id); if($subscribe[Subscribe::$PROFILE]==$pid and $subscribe[Subscribe::$SUPER] and $subscribe[Subscribe::$ARCHIVE]==ESoftSubscribeStatus::ACTIVE){ Subscribe::updateById($subscribe_id,[ Subscribe::$ARCHIVE => ESoftSubscribeStatus::ARCHIVE, ]); return true; } return false; } static function cancelSoftSubscribe($subscribe_id,$pid=PID):bool{ // 1. Получаем информацию о подписке // 2. Проверяем, принадлежит ли пользователю и активна ли она и не является ли она групповой // 3. Если всё норм, то отменяем $subscribe_id = intval($subscribe_id); $pid = intval($pid); $subscribe = Subscribe::getByID($subscribe_id); if($subscribe[Subscribe::$PROFILE]==$pid and !$subscribe[Subscribe::$GROUP]) {//} and $subscribe[Subscribe::$ARCHIVE]==ESoftSubscribeStatus::ACTIVE){ Subscribe::updateById($subscribe_id,[ Subscribe::$ARCHIVE => ESoftSubscribeStatus::ARCHIVE, ]); return true; } return false; } static function cancelGroupSubscribe($group_id,$pid=PID):bool{ // 1. Сначала получаем информацию о группе // 2. Затем получаем список подписок пользователя в этой группе // 3. Надо запомнить программы в этих подписках // 4. Затем эти подписки отменить // 5. Проверить все остальные активные групповые подписки пользователя // 6. И если там есть такая программа, с отменённой подпиской, то включить её // 7. Но только по одной подписка на программу $group_id = intval($group_id); $pid = intval($pid); $group = Group::getByID($group_id); /* $group_soft = GroupSoft::getByGroup($group_id); $soft_ids = []; foreach ($group_soft as $v){ $soft_ids[] = $v[GroupSoft::$SOFT]; } //*/ $soft_ids = []; $r = Subscribe::select([ \Query::SELECT => [Subscribe::$SOFT], \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(Subscribe::$GROUP,'=',$group_id), \Where::_operator(Subscribe::$ARCHIVE,'=',ESoftSubscribeStatus::ACTIVE), \Where::_operator(Subscribe::$PROFILE,'=',$pid), ])) ]); while($l = \DB::fetch($r)){ $soft_ids[] = $l[Subscribe::$SOFT]; } // Список программ получен, теперь отменяем подписки в этой группе у этого пользователя Subscribe::update(new \Where(\Where::_and([ \Where::_operator(Subscribe::$GROUP,'=',$group_id), \Where::_operator(Subscribe::$PROFILE,'=',$pid), ])),[ Subscribe::$ARCHIVE=>ESoftSubscribeStatus::ARCHIVE, ]); if($soft_ids) { $r = Subscribe::select([ \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(Subscribe::$PROFILE, '=', $pid), \Where::_operator(Subscribe::$ARCHIVE, '=', ESoftSubscribeStatus::PAUSE), \Where::_operator(Subscribe::$GROUP, '<>', $group_id), \Where::_in(Subscribe::$SOFT, $soft_ids), ])), //\Query::GROUP_BY => Subscribe::$GROUP, \Query::SORT => [Subscribe::$PRICE=>'ASC'], //\Query::COUNT => 1, ]); $groups = []; $subscribe_ids = []; while ($l = \DB::fetch($r)) { $soft_id = $l[Subscribe::$SOFT]; $subscribe_id = $l[Subscribe::$ID]; if (!$subscribe_ids[$soft_id]) { $subscribe_ids[$soft_id] = $subscribe_id; } } foreach ($subscribe_ids as $subscribe_id){ Subscribe::updateById($subscribe_id,[ Subscribe::$ARCHIVE => ESoftSubscribeStatus::ACTIVE, ]); } } return true; } static public function format($v){ return [ 'id' => intval($v[self::$ID]), 'soft' => intval($v[self::$SOFT]), 'group_id' => intval($v[self::$GROUP]), 'archive' => boolval($v[self::$ARCHIVE]), 'group' => boolval($v[self::$GROUP]), 'super' => boolval($v[self::$SUPER]), 'price' => cfloatval($v[self::$PRICE]), 'status' => intval($v[self::$ARCHIVE]), 'status_name' => ESoftSubscribeStatus::getName($v[self::$ARCHIVE]), ]; } static public function getActiveByProfileFormatted($profile_id = PID){ $res = []; $a = self::getActiveByProfile($profile_id); foreach ($a as $v){ $res[$v[self::$SOFT]] = self::format($v); } return $res; } static public function getByProfileAndSoft($soft_id,$profile_id = PID){ $res = null; $soft_id = intval($soft_id); $profile_id = intval($profile_id); if($profile_id and $soft_id) { $r = self::select([ \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(self::$PROFILE,'=',$profile_id), \Where::_operator(self::$SOFT,'=',$soft_id), \Where::_operator(self::$ARCHIVE,'=',ESoftSubscribeStatus::ACTIVE), ])), \Query::COUNT => 1, ]); if(\DB::numRows($r)){ $res = \DB::fetch($r); } } return $res; } static public function getFormattedByProfileAndSoft($soft_id,$profile_id = PID){ $res = self::getByProfileAndSoft($soft_id,$profile_id); return self::format($res); } static public function getActiveByProfile($profile_id = PID,$isAssoc = true){ $res = null; $profile_id = intval($profile_id); if($profile_id) { $res = self::select([ \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(self::$PROFILE, '=', $profile_id), \Where::_operator(self::$ARCHIVE, '=', ESoftSubscribeStatus::ACTIVE), ])) ], $isAssoc); } return $res; } static public function getForListByProfile($profile_id = PID,$isAssoc = true){ $res = null; $profile_id = intval($profile_id); if($profile_id) { $res = self::select([ \Query::WHERE => new \Where(\Where::_and([ \Where::_operator(self::$PROFILE, '=', $profile_id), \Where::_in(self::$ARCHIVE, [ ESoftSubscribeStatus::ACTIVE, ESoftSubscribeStatus::PAUSE]), ])) ], $isAssoc); } return $res; } static function columnInfo() : array { return [ new C([ C::VAR_NAME =>&self::$ID, C::TYPE =>eColumnType::INT, C::AUTO_INCREMENT =>true, C::PRIMARY =>true, C::DEFAULT =>0, C::HIDDEN =>true, C::TH =>V::get(Vars::$ID), ]), new C([ C::VAR_NAME => &self::$SOFT, C::TYPE => eColumnType::INT, ]), new C([ C::VAR_NAME => &self::$PROFILE, C::TYPE => eColumnType::INT, ]), new C([ C::VAR_NAME => &self::$PRICE, C::TYPE => eColumnType::DOUBLE, C::LENGTH => '10,2' ]), new C([ C::VAR_NAME => &self::$GROUP, C::TYPE => eColumnType::INT, ]), new C([ C::VAR_NAME => &self::$ARCHIVE, C::TYPE => eColumnType::INT, C::DEFAULT => 0, ]), new C([ C::VAR_NAME => &self::$SUPER, C::TYPE => eColumnType::INT, C::DEFAULT => 0, ]), new C([ C::VAR_NAME => &self::$BEGIN, C::TYPE => eColumnType::DATE, C::DEFAULT => date('Y-m-d'), ]), new C([ C::VAR_NAME => &self::$END, C::TYPE => eColumnType::DATE, C::DEFAULT => '0000-00-00', ]), new C([ C::VAR_NAME => &self::$ACCOUNT, C::TYPE => eColumnType::INT, C::LENGTH => 11, C::TH => V::get(Vars::$ACCOUNT), C::DEFAULT => intval(\Site::$owner_id), c::HIDDEN=>true, c::FUNC_VALUE => function($v){ if($id = $v[self::$ACCOUNT]) { return \Account::getName( \Account::getByID($id) ); } else return '-'; }, ]), new C([ C::VAR_NAME => &self::$CREATED, C::TYPE => eColumnType::INT, C::LENGTH => 11, C::TH => V::get(Vars::$CREATED), C::DEFAULT => time(), c::FUNC_VALUE => function($v){return self::formatDate($v[self::$CREATED]);}, c::HIDDEN=>true, ]), new C([ C::VAR_NAME => &self::$UPDATED, C::TYPE => eColumnType::INT, C::DEFAULT => time(), C::TH => V::get(Vars::$UPDATED), c::FUNC_VALUE => function($v){return self::formatDate($v[self::$UPDATED]);}, c::HIDDEN=>true, ]), ]; } } new Subscribe();