diff --git a/models/Team.php b/models/Team.php
new file mode 100644
index 0000000..e8eea29
--- /dev/null
+++ b/models/Team.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace app\models;
+
+use Yii;
+use yii\db\ActiveRecord;
+use GuzzleHttp\Client;
+
+class Team extends ActiveRecord
+{
+    public const SCENARIO_DEFAULT = 'default';
+
+    public function rules()
+    {
+        return [
+            [['name', 'chat_link'], 'required'],
+            [['access_key'], 'string', 'max' => 255],
+            [['min_balance', 'min_balance_milk', 'min_balance_ironsource'], 'number'],
+            [['notes'], 'string'],
+            [['chat_link'], 'url'],
+        ];
+    }
+
+    public static function tableName()
+    {
+        return 'teams';
+    }
+
+    public function getAccounts()
+    {
+        return $this->hasMany(Account::class, ['team_id' => 'id']);
+    }
+
+    public function getTransactions()
+    {
+        return $this->hasMany(Transaction::class, ['team_id' => 'id']);
+    }
+
+    public function getClients()
+    {
+        return $this->hasMany(Client::class, ['team_id' => 'id']);
+    }
+
+    public function getBalance()
+    {
+        return (float)$this->getTransactions()->sum('amount');
+    }
+
+    public function getBalanceByType($type)
+    {
+        return (float)$this->getAccounts()->andWhere(['type' => $type])->sum('balance');
+    }
+
+    public function getPositiveTransactions()
+    {
+        return $this->getTransactions()
+            ->andWhere(['>', 'amount', 0])
+            ->orderBy(['created_at' => SORT_DESC])
+            ->all();
+    }
+
+    public function getFormattedBalance()
+    {
+        return number_format($this->balance, 2, ',', ' ');
+    }
+
+    public function beforeSave($insert)
+    {
+        if ($insert && empty($this->access_key)) {
+            $this->access_key = Yii::$app->security->generateRandomString(32);
+        }
+        return parent::beforeSave($insert);
+    }
+
+    public function scenarios()
+    {
+        $scenarios = parent::scenarios();
+        $scenarios[self::SCENARIO_DEFAULT] = [
+            'name', 'chat_link', 'min_balance', 'min_balance_milk',
+            'min_balance_ironsource', 'notes', 'access_key'
+        ];
+        return $scenarios;
+    }
+
+    public function getLatestTransactionDates()
+    {
+        return [
+            'moloco' => $this->getTransactions()
+                ->andWhere(['account_type' => 'moloco'])
+                ->max('spend_date'),
+            'ironsource' => $this->getTransactions()
+                ->andWhere(['account_type' => 'ironsource'])
+                ->max('spend_date'),
+        ];
+    }
+
+    public function checkAndSendNotifications()
+    {
+        foreach ($this->accounts as $account) {
+            foreach ($account->thresholds as $threshold) {
+                if ($account->balance < $threshold->threshold_value) {
+                    $this->sendTelegramAlert($threshold);
+                }
+            }
+        }
+    }
+
+    private function sendTelegramAlert($threshold)
+    {
+        $message = "<b>⚠️ Внимание!</b>\n"
+            ."Баланс <i>{$threshold->account->name}</i> опустился до <code>"
+            .number_format($threshold->account->balance, 2, ',', ' ')." $</code>";
+
+        foreach ($this->clients as $client) {
+            try {
+                $httpClient = new Client();
+                $httpClient->post(
+                    "https://api.telegram.org/bot".Yii::$app->params['telegram.bot_token']."/sendMessage",
+                    [
+                        'form_params' => [
+                            'chat_id' => $client->chat_id,
+                            'text' => $message,
+                            'parse_mode' => 'HTML'
+                        ]
+                    ]
+                );
+            } catch (\Exception $e) {
+                Yii::error("Telegram error: {$e->getMessage()}");
+            }
+        }
+    }
+}
\ No newline at end of file