Разработка краудлендинговой платформы

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка краудлендинговой платформы
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Разработка краудлендинговой платформы

Краудлендинг — это P2P-кредитование: заёмщики получают деньги от пула частных инвесторов, платформа организует процесс, скоринг, управление выплатами и резервным фондом. В отличие от краудфандинга, здесь деньги возвращаются с процентами — что создаёт принципиально другую финансовую механику и регуляторные требования.

Ключевые отличия от краудфандинга

Краудлендинг работает с финансовыми инструментами. В России деятельность платформ краудлендинга регулируется Федеральным законом № 259-ФЗ «О привлечении инвестиций с использованием инвестиционных платформ». Платформа должна включить в реестр Банка России. Это влияет на архитектуру: все транзакции обязаны проходить через номинальные счета, данные хранятся с учётом требований регулятора.

Схема данных

-- Заявки на займ
CREATE TABLE loan_requests (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    borrower_id     UUID NOT NULL REFERENCES users(id),
    amount          NUMERIC(15,2) NOT NULL,
    currency        CHAR(3) NOT NULL DEFAULT 'RUB',
    term_months     INTEGER NOT NULL,
    rate_annual     NUMERIC(5,2) NOT NULL,   -- годовая ставка %
    purpose         TEXT NOT NULL,
    status          VARCHAR(30) NOT NULL DEFAULT 'pending'
                    CHECK (status IN (
                        'pending','scoring','approved','funding',
                        'funded','active','repaid','defaulted','rejected'
                    )),
    funded_amount   NUMERIC(15,2) NOT NULL DEFAULT 0,
    risk_grade      CHAR(1),                -- A,B,C,D после скоринга
    scoring_score   INTEGER,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Инвестиции
CREATE TABLE investments (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    investor_id     UUID NOT NULL REFERENCES users(id),
    loan_id         UUID NOT NULL REFERENCES loan_requests(id),
    amount          NUMERIC(15,2) NOT NULL,
    status          VARCHAR(20) NOT NULL DEFAULT 'pending'
                    CHECK (status IN ('pending','active','repaid','defaulted')),
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- График погашения
CREATE TABLE repayment_schedule (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    loan_id         UUID NOT NULL REFERENCES loan_requests(id),
    payment_num     INTEGER NOT NULL,
    due_date        DATE NOT NULL,
    principal       NUMERIC(15,2) NOT NULL,
    interest        NUMERIC(15,2) NOT NULL,
    status          VARCHAR(20) NOT NULL DEFAULT 'pending'
                    CHECK (status IN ('pending','paid','overdue','written_off')),
    paid_at         TIMESTAMPTZ,
    UNIQUE (loan_id, payment_num)
);

-- Кошельки (номинальные счета)
CREATE TABLE wallets (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         UUID NOT NULL REFERENCES users(id),
    type            VARCHAR(20) NOT NULL CHECK (type IN ('investor','borrower')),
    balance         NUMERIC(15,2) NOT NULL DEFAULT 0,
    reserved        NUMERIC(15,2) NOT NULL DEFAULT 0,  -- зарезервировано под инвестиции
    UNIQUE (user_id, type)
);

-- Транзакции кошелька (полный аудит-лог)
CREATE TABLE wallet_transactions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    wallet_id       UUID NOT NULL REFERENCES wallets(id),
    type            VARCHAR(30) NOT NULL,
    amount          NUMERIC(15,2) NOT NULL,
    balance_after   NUMERIC(15,2) NOT NULL,
    reference_id    UUID,   -- loan_id, investment_id или payment_id
    description     TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Аннуитетный расчёт графика платежей

from decimal import Decimal, ROUND_HALF_UP
from datetime import date
from dateutil.relativedelta import relativedelta


def calculate_annuity_schedule(
    loan_amount: Decimal,
    annual_rate: Decimal,
    term_months: int,
    start_date: date
) -> list[dict]:
    """Аннуитетный график погашения"""
    monthly_rate = annual_rate / 100 / 12

    # Аннуитетный коэффициент
    k = monthly_rate * (1 + monthly_rate) ** term_months / \
        ((1 + monthly_rate) ** term_months - 1)

    monthly_payment = (loan_amount * k).quantize(Decimal('0.01'), ROUND_HALF_UP)

    schedule = []
    balance = loan_amount
    payment_date = start_date

    for num in range(1, term_months + 1):
        payment_date = payment_date + relativedelta(months=1)
        interest = (balance * monthly_rate).quantize(Decimal('0.01'), ROUND_HALF_UP)

        if num < term_months:
            principal = monthly_payment - interest
        else:
            # Последний платёж — гасим остаток
            principal = balance

        balance -= principal

        schedule.append({
            'payment_num': num,
            'due_date': payment_date,
            'principal': principal,
            'interest': interest,
            'total': principal + interest,
            'balance_after': max(balance, Decimal('0')),
        })

    return schedule

Автоинвестирование

Ключевая функция для удержания инвесторов — автоматическое распределение средств по займам согласно настроенным критериям:

class AutoInvestRule(models.Model):
    investor = models.OneToOneField(User, on_delete=models.CASCADE)
    is_active = models.BooleanField(default=True)
    max_amount_per_loan = models.DecimalField(max_digits=15, decimal_places=2)
    min_loan_amount = models.DecimalField(max_digits=15, decimal_places=2, default=50000)
    max_loan_amount = models.DecimalField(max_digits=15, decimal_places=2, default=1000000)
    allowed_grades = models.JSONField(default=list)   # ['A', 'B']
    min_rate = models.DecimalField(max_digits=5, decimal_places=2, default=15)
    max_term_months = models.IntegerField(default=24)
    reinvest_returns = models.BooleanField(default=True)


@shared_task
def run_auto_invest():
    """Запускается каждые 15 минут"""
    new_loans = LoanRequest.objects.filter(
        status='funding',
        funded_amount__lt=models.F('amount')
    )

    for loan in new_loans:
        rules = AutoInvestRule.objects.filter(
            is_active=True,
            allowed_grades__contains=loan.risk_grade,
            min_rate__lte=loan.rate_annual,
            max_term_months__gte=loan.term_months,
            min_loan_amount__lte=loan.amount,
            max_loan_amount__gte=loan.amount,
        )

        for rule in rules:
            wallet = Wallet.objects.select_for_update().get(
                user=rule.investor, type='investor'
            )
            available = wallet.balance - wallet.reserved
            invest_amount = min(rule.max_amount_per_loan, available)

            if invest_amount >= Decimal('1000'):  # минимальная сумма
                create_investment(rule.investor, loan, invest_amount, wallet)

Начисление процентов и списание платежей

@shared_task
def process_due_payments():
    """Запускается ежедневно"""
    today = date.today()
    due_payments = RepaymentSchedule.objects.filter(
        due_date=today,
        status='pending',
        loan__status='active'
    ).select_related('loan__borrower__wallet')

    for payment in due_payments:
        borrower_wallet = payment.loan.borrower.wallet

        if borrower_wallet.balance >= payment.principal + payment.interest:
            # Достаточно средств — списываем
            process_payment(payment)
        else:
            # Недостаточно — отмечаем как просроченный
            payment.status = 'overdue'
            payment.save()
            send_overdue_notification.delay(payment.id)
            # Начисляем штрафные проценты
            accrue_late_fee.delay(payment.id)


def process_payment(payment):
    total = payment.principal + payment.interest
    with transaction.atomic():
        # Списываем с заёмщика
        debit_wallet(payment.loan.borrower, total, 'loan_payment', payment.loan_id)
        # Распределяем по инвесторам пропорционально их доле
        distribute_to_investors(payment)
        payment.status = 'paid'
        payment.paid_at = timezone.now()
        payment.save()
        # Проверяем, полностью ли погашен займ
        check_loan_completion(payment.loan)

Резервный фонд

Защита инвесторов при дефолте заёмщика:

RESERVE_FUND_RATE = Decimal('0.02')  # 2% от каждого займа

def fund_reserve_on_disbursement(loan):
    reserve_amount = (loan.amount * RESERVE_FUND_RATE).quantize(Decimal('0.01'))
    ReserveFund.objects.create(
        loan=loan,
        amount=reserve_amount,
        status='active'
    )

def cover_default_from_reserve(loan):
    """При дефолте — компенсируем инвесторам из резервного фонда"""
    outstanding = loan.investments.filter(
        status='active'
    ).aggregate(total=Sum('amount'))['total'] or 0

    reserve = ReserveFund.objects.filter(status='active').aggregate(
        total=Sum('amount')
    )['total'] or 0

    coverage = min(outstanding, reserve)
    # Распределяем покрытие пропорционально инвестициям
    distribute_reserve_coverage(loan, coverage)

Документация и договоры

Каждая инвестиция сопровождается документом. Генерация через шаблон:

from reportlab.pdfgen import canvas
from jinja2 import Environment, FileSystemLoader


def generate_loan_agreement(loan, investor, investment):
    env = Environment(loader=FileSystemLoader('templates/legal'))
    template = env.get_template('loan_agreement.html')

    html = template.render(
        loan=loan,
        investor=investor,
        investment=investment,
        schedule=loan.repayment_schedule.all(),
        generated_at=timezone.now(),
    )

    # Конвертируем HTML → PDF через WeasyPrint
    from weasyprint import HTML
    pdf = HTML(string=html).write_pdf()

    path = f'documents/agreements/{loan.id}/{investor.id}.pdf'
    default_storage.save(path, ContentFile(pdf))
    return path

Сроки

MVP P2P-платформы с базовым скорингом, кошельками, графиком платежей и личными кабинетами заёмщика и инвестора: 4–5 месяцев. Это минимум для запуска в регулируемой среде — с номинальными счетами, аудит-логом всех транзакций и базовой документацией. Полная платформа с автоинвестированием, резервным фондом и вторичным рынком: 8–12 месяцев.