feature/worker #111

Merged
primakov merged 190 commits from feature/worker into master 2025-12-05 16:59:42 +03:00
7 changed files with 1346 additions and 1 deletions
Showing only changes of commit f65fd175ca - Show all commits

View File

@@ -20,6 +20,7 @@ import gamehubRouter from './routers/gamehub'
import escRouter from './routers/esc'
import connectmeRouter from './routers/connectme'
import questioneerRouter from './routers/questioneer'
import procurementRouter from './routers/procurement'
import { setIo } from './io'
export const app = express()
@@ -105,7 +106,7 @@ const initServer = async () => {
app.use("/esc", escRouter)
app.use('/connectme', connectmeRouter)
app.use('/questioneer', questioneerRouter)
app.use('/procurement', procurementRouter)
app.use(errorHandler)
// Создаем обычный HTTP сервер

View File

@@ -0,0 +1,575 @@
const router = require('express').Router();
const fs = require('fs');
const path = require('path');
const timer = (time = 300) => (req, res, next) => setTimeout(next, time);
// Настройка кодировки UTF-8
router.use((req, res, next) => {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
router.use(timer());
// Загружаем моки из JSON файлов
const loadMockData = (filename) => {
try {
const filePath = path.join(__dirname, '..', 'mocks', filename);
const data = fs.readFileSync(filePath, 'utf8');
return JSON.parse(data);
} catch (error) {
console.error(`Ошибка загрузки ${filename}:`, error);
return {};
}
};
// Загружаем все моки
const userMocks = loadMockData('user.json');
const companyMocks = loadMockData('companies.json');
const productMocks = loadMockData('products.json');
const searchMocks = loadMockData('search.json');
const authMocks = loadMockData('auth.json');
// Логируем загруженные данные для отладки
console.log('SearchMocks loaded:', searchMocks);
console.log('Suggestions:', searchMocks.suggestions);
// Вспомогательные функции для генерации динамических данных
const generateTimestamp = () => Date.now();
const generateDate = (daysAgo) => new Date(Date.now() - 86400000 * daysAgo).toISOString();
// Функция для замены плейсхолдеров в данных
const processMockData = (data) => {
const timestamp = generateTimestamp();
const processedData = JSON.stringify(data)
.replace(/{{timestamp}}/g, timestamp)
.replace(/{{date-(\d+)-days?}}/g, (match, days) => generateDate(parseInt(days)))
.replace(/{{date-1-day}}/g, generateDate(1))
.replace(/{{date-2-days}}/g, generateDate(2))
.replace(/{{date-3-days}}/g, generateDate(3))
.replace(/{{date-4-days}}/g, generateDate(4))
.replace(/{{date-5-days}}/g, generateDate(5))
.replace(/{{date-6-days}}/g, generateDate(6))
.replace(/{{date-7-days}}/g, generateDate(7))
.replace(/{{date-8-days}}/g, generateDate(8))
.replace(/{{date-10-days}}/g, generateDate(10))
.replace(/{{date-12-days}}/g, generateDate(12))
.replace(/{{date-15-days}}/g, generateDate(15))
.replace(/{{date-18-days}}/g, generateDate(18))
.replace(/{{date-20-days}}/g, generateDate(20))
.replace(/{{date-21-days}}/g, generateDate(21))
.replace(/{{date-25-days}}/g, generateDate(25))
.replace(/{{date-28-days}}/g, generateDate(28))
.replace(/{{date-30-days}}/g, generateDate(30))
.replace(/{{date-35-days}}/g, generateDate(35));
return JSON.parse(processedData);
};
// Auth endpoints
router.post('/auth/login', (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({
error: 'Validation failed',
message: authMocks.errorMessages?.validationFailed || 'Email и пароль обязательны'
});
}
// Имитация неверных учетных данных
if (password === 'wrong') {
return res.status(401).json({
error: 'Unauthorized',
message: authMocks.errorMessages?.invalidCredentials || 'Неверный email или пароль'
});
}
const authResponse = processMockData(authMocks.mockAuthResponse);
res.status(200).json(authResponse);
});
router.post('/auth/register', (req, res) => {
const { email, password, inn, agreeToTerms } = req.body;
if (!email || !password || !inn) {
return res.status(400).json({
error: 'Validation failed',
message: authMocks.errorMessages?.validationFailed || 'Заполните все обязательные поля'
});
}
if (!agreeToTerms) {
return res.status(400).json({
error: 'Validation failed',
message: authMocks.errorMessages?.termsRequired || 'Необходимо принять условия использования'
});
}
// Создаем нового пользователя с данными из регистрации
const newUser = {
id: 'user-' + generateTimestamp(),
email: email,
firstName: req.body.firstName || 'Иван',
lastName: req.body.lastName || 'Петров',
position: req.body.position || 'Директор'
};
const newCompany = {
id: 'company-' + generateTimestamp(),
name: req.body.fullName || companyMocks.mockCompany?.name,
inn: req.body.inn,
ogrn: req.body.ogrn || companyMocks.mockCompany?.ogrn,
fullName: req.body.fullName || companyMocks.mockCompany?.fullName,
shortName: req.body.shortName,
legalForm: req.body.legalForm || 'ООО',
industry: req.body.industry || 'Другое',
companySize: req.body.companySize || '1-10',
website: req.body.website || '',
verified: false,
rating: 0
};
res.status(201).json({
user: newUser,
company: newCompany,
tokens: {
accessToken: 'mock-access-token-' + generateTimestamp(),
refreshToken: 'mock-refresh-token-' + generateTimestamp()
}
});
});
router.post('/auth/logout', (req, res) => {
res.status(200).json({
message: authMocks.successMessages?.logoutSuccess || 'Успешный выход'
});
});
router.post('/auth/refresh', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(401).json({
error: 'Unauthorized',
message: authMocks.errorMessages?.refreshTokenRequired || 'Refresh token обязателен'
});
}
res.status(200).json({
accessToken: 'mock-access-token-refreshed-' + generateTimestamp(),
refreshToken: 'mock-refresh-token-refreshed-' + generateTimestamp()
});
});
router.get('/auth/verify-email/:token', (req, res) => {
res.status(200).json({
message: authMocks.successMessages?.emailVerified || 'Email успешно подтвержден'
});
});
router.post('/auth/request-password-reset', (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({
error: 'Validation failed',
message: authMocks.errorMessages?.emailRequired || 'Email обязателен'
});
}
res.status(200).json({
message: authMocks.successMessages?.passwordResetSent || 'Письмо для восстановления пароля отправлено'
});
});
router.post('/auth/reset-password', (req, res) => {
const { token, newPassword } = req.body;
if (!token || !newPassword) {
return res.status(400).json({
error: 'Validation failed',
message: authMocks.errorMessages?.validationFailed || 'Token и новый пароль обязательны'
});
}
res.status(200).json({
message: authMocks.successMessages?.passwordResetSuccess || 'Пароль успешно изменен'
});
});
// Companies endpoints
router.get('/companies/my/stats', (req, res) => {
res.status(200).json({
profileViews: 142,
profileViewsChange: 12,
sentRequests: 8,
sentRequestsChange: 2,
receivedRequests: 15,
receivedRequestsChange: 5,
newMessages: 3,
rating: 4.5
});
});
router.get('/companies/:id', (req, res) => {
const company = processMockData(companyMocks.mockCompany);
res.status(200).json(company);
});
router.patch('/companies/:id', (req, res) => {
const updatedCompany = {
...processMockData(companyMocks.mockCompany),
...req.body,
id: req.params.id
};
res.status(200).json(updatedCompany);
});
router.get('/companies/:id/stats', (req, res) => {
res.status(200).json({
profileViews: 142,
profileViewsChange: 12,
sentRequests: 8,
sentRequestsChange: 2,
receivedRequests: 15,
receivedRequestsChange: 5,
newMessages: 3,
rating: 4.5
});
});
router.post('/companies/:id/logo', (req, res) => {
res.status(200).json({
logoUrl: 'https://via.placeholder.com/200x200/4299E1/FFFFFF?text=Logo'
});
});
router.get('/companies/check-inn/:inn', (req, res) => {
const inn = req.params.inn;
// Имитация проверки ИНН
if (inn.length !== 10 && inn.length !== 12) {
return res.status(400).json({
error: 'Validation failed',
message: authMocks.errorMessages?.innValidation || 'ИНН должен содержать 10 или 12 цифр'
});
}
const mockINNData = companyMocks.mockINNData || {};
const companyData = mockINNData[inn] || {
name: 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ "ТЕСТОВАЯ КОМПАНИЯ ' + inn + '"',
ogrn: '10277' + inn,
legal_form: 'ООО'
};
res.status(200).json({ data: companyData });
});
// Products endpoints
router.get('/products/my', (req, res) => {
const products = processMockData(productMocks.mockProducts);
res.status(200).json(products);
});
router.get('/products', (req, res) => {
const products = processMockData(productMocks.mockProducts);
res.status(200).json({
items: products,
total: products.length,
page: 1,
pageSize: 20
});
});
router.post('/products', (req, res) => {
const newProduct = {
id: 'prod-' + generateTimestamp(),
...req.body,
companyId: 'company-123',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
res.status(201).json(newProduct);
});
router.get('/products/:id', (req, res) => {
const products = processMockData(productMocks.mockProducts);
const product = products.find(p => p.id === req.params.id);
if (product) {
res.status(200).json(product);
} else {
res.status(200).json({
id: req.params.id,
name: 'Продукт ' + req.params.id,
description: 'Описание продукта',
category: 'Категория',
type: 'sell',
companyId: 'company-123',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
});
}
});
router.patch('/products/:id', (req, res) => {
const products = processMockData(productMocks.mockProducts);
const product = products.find(p => p.id === req.params.id);
const updatedProduct = {
...(product || {}),
...req.body,
id: req.params.id,
updatedAt: new Date().toISOString()
};
res.status(200).json(updatedProduct);
});
router.delete('/products/:id', (req, res) => {
res.status(204).send();
});
// Тестовый endpoint для проверки данных
router.get('/test-data', (req, res) => {
res.status(200).json({
companiesCount: companyMocks.mockCompanies?.length || 0,
suggestionsCount: searchMocks.suggestions?.length || 0,
firstCompany: companyMocks.mockCompanies?.[0] || null,
firstSuggestion: searchMocks.suggestions?.[0] || null,
allSuggestions: searchMocks.suggestions || []
});
});
router.get('/search', (req, res) => {
const {
query,
industries,
companySize,
geography,
minRating,
type,
sortBy = 'relevance',
sortOrder = 'desc',
page = 1,
limit = 20
} = req.query;
console.log('Search query:', query);
console.log('Search params:', req.query);
const companies = processMockData(companyMocks.mockCompanies);
console.log('Companies loaded:', companies.length);
console.log('First company:', companies[0]);
let filtered = [...companies];
// Поиск по тексту
if (query) {
const q = query.toLowerCase().trim();
console.log('Searching for:', q);
filtered = filtered.filter(c => {
const fullName = (c.fullName || '').toLowerCase();
const shortName = (c.shortName || '').toLowerCase();
const industry = (c.industry || '').toLowerCase();
const slogan = (c.slogan || '').toLowerCase();
const legalAddress = (c.legalAddress || '').toLowerCase();
const matches = fullName.includes(q) ||
shortName.includes(q) ||
industry.includes(q) ||
slogan.includes(q) ||
legalAddress.includes(q);
if (matches) {
console.log('Found match:', c.shortName, 'in', { fullName, shortName, industry, slogan, legalAddress });
}
return matches;
});
console.log('Filtered results:', filtered.length);
}
// Фильтр по отраслям
if (industries && industries.length > 0) {
const industriesArray = Array.isArray(industries) ? industries : [industries];
filtered = filtered.filter(c => industriesArray.includes(c.industry));
}
// Фильтр по размеру компании
if (companySize && companySize.length > 0) {
const sizeArray = Array.isArray(companySize) ? companySize : [companySize];
filtered = filtered.filter(c => sizeArray.includes(c.companySize));
}
// Фильтр по рейтингу
if (minRating) {
filtered = filtered.filter(c => c.rating >= parseFloat(minRating));
}
// Сортировка
filtered.sort((a, b) => {
let comparison = 0;
switch (sortBy) {
case 'rating':
comparison = a.rating - b.rating;
break;
case 'name':
comparison = (a.shortName || a.fullName).localeCompare(b.shortName || b.fullName);
break;
case 'relevance':
default:
// Для релевантности используем рейтинг как основной критерий
comparison = a.rating - b.rating;
break;
}
return sortOrder === 'asc' ? comparison : -comparison;
});
const total = filtered.length;
const totalPages = Math.ceil(total / limit);
const startIndex = (page - 1) * limit;
const endIndex = startIndex + parseInt(limit);
const paginatedResults = filtered.slice(startIndex, endIndex);
res.status(200).json({
companies: paginatedResults,
total,
page: parseInt(page),
totalPages
});
});
router.post('/search/ai', (req, res) => {
const { query } = req.body;
// Простая логика AI поиска на основе ключевых слов
const companies = processMockData(companyMocks.mockCompanies);
let aiResults = [...companies];
const q = query.toLowerCase();
// Определяем приоритетные отрасли на основе запроса
if (q.includes('строитель') || q.includes('строй') || q.includes('дом') || q.includes('здание')) {
aiResults = aiResults.filter(c => c.industry === 'Строительство');
} else if (q.includes('металл') || q.includes('сталь') || q.includes('производств') || q.includes('завод')) {
aiResults = aiResults.filter(c => c.industry === 'Производство');
} else if (q.includes('логистик') || q.includes('доставк') || q.includes('транспорт')) {
aiResults = aiResults.filter(c => c.industry === 'Логистика');
} else if (q.includes('торговл') || q.includes('продаж') || q.includes('снабжени')) {
aiResults = aiResults.filter(c => c.industry === 'Торговля');
} else if (q.includes('it') || q.includes('программ') || q.includes('технолог') || q.includes('софт')) {
aiResults = aiResults.filter(c => c.industry === 'IT');
} else if (q.includes('услуг') || q.includes('консалт') || q.includes('помощь')) {
aiResults = aiResults.filter(c => c.industry === 'Услуги');
}
// Сортируем по рейтингу и берем топ-5
aiResults.sort((a, b) => b.rating - a.rating);
const topResults = aiResults.slice(0, 5);
// Генерируем AI предложение
let aiSuggestion = `На основе вашего запроса "${query}" мы нашли ${topResults.length} подходящих партнеров. `;
if (topResults.length > 0) {
const industries = [...new Set(topResults.map(c => c.industry))];
aiSuggestion += `Рекомендуем обратить внимание на компании в сфере ${industries.join(', ')}. `;
aiSuggestion += `Все предложенные партнеры имеют высокий рейтинг (от ${Math.min(...topResults.map(c => c.rating)).toFixed(1)} до ${Math.max(...topResults.map(c => c.rating)).toFixed(1)}) и подтвержденный статус.`;
} else {
aiSuggestion += 'Попробуйте изменить формулировку запроса или использовать фильтры для более точного поиска.';
}
res.status(200).json({
companies: topResults,
total: topResults.length,
page: 1,
totalPages: 1,
aiSuggestion
});
});
router.get('/search/suggestions', (req, res) => {
const { q } = req.query;
const suggestions = searchMocks.suggestions || [];
console.log('Suggestions loaded:', suggestions);
console.log('Query:', q);
const filtered = q
? suggestions.filter(s => s.toLowerCase().includes(q.toLowerCase()))
: suggestions.slice(0, 10); // Показываем только первые 10 если нет запроса
console.log('Filtered suggestions:', filtered);
res.status(200).json(filtered);
});
router.get('/search/recommendations', (req, res) => {
// Динамически генерируем рекомендации на основе топовых компаний
const companies = processMockData(companyMocks.mockCompanies);
const topCompanies = companies
.filter(c => c.verified && c.rating >= 4.5)
.sort((a, b) => b.rating - a.rating)
.slice(0, 6);
const recommendations = topCompanies.map(company => ({
id: company.id,
name: company.shortName || company.fullName,
industry: company.industry,
logo: company.logo,
matchScore: Math.floor(company.rating * 20), // Конвертируем рейтинг в проценты
reason: getRecommendationReason(company, searchMocks.recommendationReasons)
}));
res.status(200).json(recommendations);
});
// Вспомогательная функция для генерации причин рекомендаций
function getRecommendationReason(company, reasons) {
return reasons?.[company.industry] || 'Проверенный партнер с высоким рейтингом';
}
router.get('/search/history', (req, res) => {
const history = processMockData(searchMocks.searchHistory);
res.status(200).json(history);
});
router.get('/search/saved', (req, res) => {
const savedSearches = processMockData(searchMocks.savedSearches);
res.status(200).json(savedSearches);
});
router.post('/search/saved', (req, res) => {
const { name, params } = req.body;
res.status(201).json({
id: 'saved-' + generateTimestamp(),
name,
params,
createdAt: new Date().toISOString()
});
});
router.delete('/search/saved/:id', (req, res) => {
res.status(204).send();
});
router.post('/search/favorites/:companyId', (req, res) => {
res.status(200).json({
message: authMocks.successMessages?.addedToFavorites || 'Добавлено в избранное'
});
});
router.delete('/search/favorites/:companyId', (req, res) => {
res.status(204).send();
});
module.exports = router;

View File

@@ -0,0 +1,46 @@
{
"mockAuthResponse": {
"user": {
"id": "user-123",
"email": "test@company.com",
"firstName": "Иван",
"lastName": "Петров",
"position": "Генеральный директор"
},
"company": {
"id": "company-123",
"name": "ООО \"Тестовая Компания\"",
"inn": "7707083893",
"ogrn": "1027700132195",
"fullName": "Общество с ограниченной ответственностью \"Тестовая Компания\"",
"shortName": "ООО \"Тест\"",
"legalForm": "ООО",
"industry": "Производство",
"companySize": "50-100",
"website": "https://test-company.ru",
"verified": true,
"rating": 4.5
},
"tokens": {
"accessToken": "mock-access-token-{{timestamp}}",
"refreshToken": "mock-refresh-token-{{timestamp}}"
}
},
"errorMessages": {
"validationFailed": "Заполните все обязательные поля",
"emailRequired": "Email обязателен",
"passwordRequired": "Пароль обязателен",
"termsRequired": "Необходимо принять условия использования",
"invalidCredentials": "Неверный email или пароль",
"refreshTokenRequired": "Refresh token обязателен",
"innValidation": "ИНН должен содержать 10 или 12 цифр"
},
"successMessages": {
"logoutSuccess": "Успешный выход",
"emailVerified": "Email успешно подтвержден",
"passwordResetSent": "Письмо для восстановления пароля отправлено",
"passwordResetSuccess": "Пароль успешно изменен",
"logoUploaded": "Логотип успешно загружен",
"addedToFavorites": "Добавлено в избранное"
}
}

View File

@@ -0,0 +1,430 @@
{
"mockCompany": {
"id": "company-123",
"name": "ООО \"Тестовая Компания\"",
"inn": "7707083893",
"ogrn": "1027700132195",
"fullName": "Общество с ограниченной ответственностью \"Тестовая Компания\"",
"shortName": "ООО \"Тест\"",
"legalForm": "ООО",
"industry": "Производство",
"companySize": "50-100",
"website": "https://test-company.ru",
"verified": true,
"rating": 4.5
},
"mockINNData": {
"7707083893": {
"name": "ПУБЛИЧНОЕ АКЦИОНЕРНОЕ ОБЩЕСТВО \"СБЕРБАНК РОССИИ\"",
"ogrn": "1027700132195",
"legal_form": "ПАО"
},
"7730048036": {
"name": "ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ \"КОМПАНИЯ\"",
"ogrn": "1047730048036",
"legal_form": "ООО"
}
},
"mockCompanies": [
{
"id": "company-1",
"inn": "7707083893",
"ogrn": "1027700132195",
"fullName": "Общество с ограниченной ответственностью \"СтройКомплект\"",
"shortName": "ООО \"СтройКомплект\"",
"legalForm": "ООО",
"industry": "Строительство",
"companySize": "100-250",
"website": "https://stroykomplekt.ru",
"logo": "https://via.placeholder.com/100x100/2B6CB0/FFFFFF?text=SK",
"slogan": "Строим будущее вместе",
"rating": 4.8,
"verified": true,
"phone": "+7 (495) 123-45-67",
"email": "info@stroykomplekt.ru",
"legalAddress": "г. Москва, ул. Строительная, д. 15",
"foundedYear": 2010,
"employeeCount": "150 сотрудников"
},
{
"id": "company-6",
"inn": "7707083894",
"ogrn": "1027700132196",
"fullName": "Акционерное общество \"Московский Строй\"",
"shortName": "АО \"Московский Строй\"",
"legalForm": "АО",
"industry": "Строительство",
"companySize": "500+",
"website": "https://moscow-stroy.ru",
"logo": "https://via.placeholder.com/100x100/1A365D/FFFFFF?text=MS",
"slogan": "Качество и надежность с 1995 года",
"rating": 4.9,
"verified": true,
"phone": "+7 (495) 987-65-43",
"email": "info@moscow-stroy.ru",
"legalAddress": "г. Москва, пр. Мира, д. 100",
"foundedYear": 1995,
"employeeCount": "800+ сотрудников"
},
{
"id": "company-7",
"inn": "7707083895",
"ogrn": "1027700132197",
"fullName": "Общество с ограниченной ответственностью \"ДомСтрой\"",
"shortName": "ООО \"ДомСтрой\"",
"legalForm": "ООО",
"industry": "Строительство",
"companySize": "50-100",
"website": "https://domstroy.ru",
"logo": "https://via.placeholder.com/100x100/2D3748/FFFFFF?text=DS",
"slogan": "Строим дома мечты",
"rating": 4.3,
"verified": true,
"phone": "+7 (495) 555-12-34",
"email": "info@domstroy.ru",
"legalAddress": "г. Москва, ул. Жилстроительная, д. 25",
"foundedYear": 2015,
"employeeCount": "75 сотрудников"
},
{
"id": "company-4",
"inn": "7730048038",
"ogrn": "1047730048038",
"fullName": "Общество с ограниченной ответственностью \"МеталлПром\"",
"shortName": "ООО \"МеталлПром\"",
"legalForm": "ООО",
"industry": "Производство",
"companySize": "250-500",
"website": "https://metallprom.ru",
"logo": "https://via.placeholder.com/100x100/E53E3E/FFFFFF?text=MP",
"slogan": "Металл высшего качества",
"rating": 4.7,
"verified": true,
"phone": "+7 (495) 456-78-90",
"email": "info@metallprom.ru",
"legalAddress": "г. Москва, ул. Промышленная, д. 50",
"foundedYear": 2008,
"employeeCount": "300 сотрудников"
},
{
"id": "company-8",
"inn": "7730048040",
"ogrn": "1047730048040",
"fullName": "Общество с ограниченной ответственностью \"СтальМет\"",
"shortName": "ООО \"СтальМет\"",
"legalForm": "ООО",
"industry": "Производство",
"companySize": "100-250",
"website": "https://stalmet.ru",
"logo": "https://via.placeholder.com/100x100/9C4221/FFFFFF?text=SM",
"slogan": "Сталь для промышленности",
"rating": 4.6,
"verified": true,
"phone": "+7 (495) 777-88-99",
"email": "sales@stalmet.ru",
"legalAddress": "г. Москва, ул. Металлургическая, д. 30",
"foundedYear": 2012,
"employeeCount": "180 сотрудников"
},
{
"id": "company-9",
"inn": "7730048041",
"ogrn": "1047730048041",
"fullName": "Общество с ограниченной ответственностью \"ПластМаш\"",
"shortName": "ООО \"ПластМаш\"",
"legalForm": "ООО",
"industry": "Производство",
"companySize": "50-100",
"website": "https://plastmash.ru",
"logo": "https://via.placeholder.com/100x100/38A169/FFFFFF?text=PM",
"slogan": "Пластиковые изделия для всех отраслей",
"rating": 4.4,
"verified": true,
"phone": "+7 (495) 333-44-55",
"email": "info@plastmash.ru",
"legalAddress": "г. Москва, ул. Пластиковая, д. 12",
"foundedYear": 2018,
"employeeCount": "80 сотрудников"
},
{
"id": "company-2",
"inn": "7730048036",
"ogrn": "1047730048036",
"fullName": "Общество с ограниченной ответственностью \"ТехСнаб\"",
"shortName": "ООО \"ТехСнаб\"",
"legalForm": "ООО",
"industry": "Торговля",
"companySize": "50-100",
"website": "https://techsnab.ru",
"logo": "https://via.placeholder.com/100x100/38A169/FFFFFF?text=TS",
"slogan": "Снабжение для профессионалов",
"rating": 4.5,
"verified": true,
"phone": "+7 (495) 234-56-78",
"email": "sales@techsnab.ru",
"legalAddress": "г. Москва, ул. Торговая, д. 8",
"foundedYear": 2010,
"employeeCount": "90 сотрудников"
},
{
"id": "company-10",
"inn": "7730048042",
"ogrn": "1047730048042",
"fullName": "Общество с ограниченной ответственностью \"ОптТорг\"",
"shortName": "ООО \"ОптТорг\"",
"legalForm": "ООО",
"industry": "Торговля",
"companySize": "100-250",
"website": "https://opttorg.ru",
"logo": "https://via.placeholder.com/100x100/805AD5/FFFFFF?text=OT",
"slogan": "Оптовые поставки по всей России",
"rating": 4.2,
"verified": true,
"phone": "+7 (495) 111-22-33",
"email": "info@opttorg.ru",
"legalAddress": "г. Москва, ул. Оптовая, д. 45",
"foundedYear": 2005,
"employeeCount": "200 сотрудников"
},
{
"id": "company-5",
"inn": "7730048039",
"ogrn": "1047730048039",
"fullName": "Общество с ограниченной ответственностью \"ЛогистикПлюс\"",
"shortName": "ООО \"ЛогистикПлюс\"",
"legalForm": "ООО",
"industry": "Логистика",
"companySize": "100-250",
"website": "https://logistikplus.ru",
"logo": "https://via.placeholder.com/100x100/805AD5/FFFFFF?text=LP",
"slogan": "Доставляем быстро и надежно",
"rating": 4.6,
"verified": true,
"phone": "+7 (495) 567-89-01",
"email": "info@logistikplus.ru",
"legalAddress": "г. Москва, ул. Логистическая, д. 20",
"foundedYear": 2013,
"employeeCount": "150 сотрудников"
},
{
"id": "company-11",
"inn": "7730048043",
"ogrn": "1047730048043",
"fullName": "Общество с ограниченной ответственностью \"ТрансЛогист\"",
"shortName": "ООО \"ТрансЛогист\"",
"legalForm": "ООО",
"industry": "Логистика",
"companySize": "250-500",
"website": "https://translogist.ru",
"logo": "https://via.placeholder.com/100x100/2B6CB0/FFFFFF?text=TL",
"slogan": "Транспортные решения для бизнеса",
"rating": 4.8,
"verified": true,
"phone": "+7 (495) 999-88-77",
"email": "info@translogist.ru",
"legalAddress": "г. Москва, ул. Транспортная, д. 60",
"foundedYear": 2007,
"employeeCount": "350 сотрудников"
},
{
"id": "company-12",
"inn": "7730048044",
"ogrn": "1047730048044",
"fullName": "Общество с ограниченной ответственностью \"ТехСофт\"",
"shortName": "ООО \"ТехСофт\"",
"legalForm": "ООО",
"industry": "IT",
"companySize": "50-100",
"website": "https://techsoft.ru",
"logo": "https://via.placeholder.com/100x100/3182CE/FFFFFF?text=TS",
"slogan": "IT-решения для бизнеса",
"rating": 4.7,
"verified": true,
"phone": "+7 (495) 444-55-66",
"email": "info@techsoft.ru",
"legalAddress": "г. Москва, ул. Программистов, д. 10",
"foundedYear": 2016,
"employeeCount": "85 сотрудников"
},
{
"id": "company-13",
"inn": "7730048045",
"ogrn": "1047730048045",
"fullName": "Общество с ограниченной ответственностью \"КиберТех\"",
"shortName": "ООО \"КиберТех\"",
"legalForm": "ООО",
"industry": "IT",
"companySize": "100-250",
"website": "https://cybertech.ru",
"logo": "https://via.placeholder.com/100x100/553C9A/FFFFFF?text=CT",
"slogan": "Кибербезопасность и автоматизация",
"rating": 4.9,
"verified": true,
"phone": "+7 (495) 666-77-88",
"email": "info@cybertech.ru",
"legalAddress": "г. Москва, ул. Кибернетическая, д. 5",
"foundedYear": 2014,
"employeeCount": "120 сотрудников"
},
{
"id": "company-3",
"inn": "7730048037",
"ogrn": "1047730048037",
"fullName": "Индивидуальный предприниматель Сидоров Петр Иванович",
"shortName": "ИП Сидоров П.И.",
"legalForm": "ИП",
"industry": "Услуги",
"companySize": "1-10",
"website": "https://sidorov-service.ru",
"logo": "https://via.placeholder.com/100x100/D69E2E/FFFFFF?text=SI",
"slogan": "Качественные услуги для малого бизнеса",
"rating": 4.2,
"verified": false,
"phone": "+7 (495) 345-67-89",
"email": "info@sidorov-service.ru",
"legalAddress": "г. Москва, ул. Сервисная, д. 3",
"foundedYear": 2020,
"employeeCount": "5 сотрудников"
},
{
"id": "company-14",
"inn": "7730048046",
"ogrn": "1047730048046",
"fullName": "Общество с ограниченной ответственностью \"КонсалтПро\"",
"shortName": "ООО \"КонсалтПро\"",
"legalForm": "ООО",
"industry": "Услуги",
"companySize": "10-50",
"website": "https://konsultpro.ru",
"logo": "https://via.placeholder.com/100x100/38A169/FFFFFF?text=KP",
"slogan": "Консалтинг для роста бизнеса",
"rating": 4.5,
"verified": true,
"phone": "+7 (495) 222-33-44",
"email": "info@konsultpro.ru",
"legalAddress": "г. Москва, ул. Консультационная, д. 15",
"foundedYear": 2017,
"employeeCount": "25 сотрудников"
},
{
"id": "company-15",
"inn": "7730048047",
"ogrn": "1047730048047",
"fullName": "Общество с ограниченной ответственностью \"ПищеПром\"",
"shortName": "ООО \"ПищеПром\"",
"legalForm": "ООО",
"industry": "Пищевая промышленность",
"companySize": "100-250",
"website": "https://pishcheprom.ru",
"logo": "https://via.placeholder.com/100x100/38A169/FFFFFF?text=PP",
"slogan": "Качественные продукты питания",
"rating": 4.4,
"verified": true,
"phone": "+7 (495) 888-99-00",
"email": "info@pishcheprom.ru",
"legalAddress": "г. Москва, ул. Пищевая, д. 40",
"foundedYear": 2011,
"employeeCount": "180 сотрудников"
},
{
"id": "company-16",
"inn": "7730048048",
"ogrn": "1047730048048",
"fullName": "Общество с ограниченной ответственностью \"ЭнергоСервис\"",
"shortName": "ООО \"ЭнергоСервис\"",
"legalForm": "ООО",
"industry": "Энергетика",
"companySize": "50-100",
"website": "https://energoservice.ru",
"logo": "https://via.placeholder.com/100x100/F6AD55/FFFFFF?text=ES",
"slogan": "Энергетические решения",
"rating": 4.6,
"verified": true,
"phone": "+7 (495) 555-66-77",
"email": "info@energoservice.ru",
"legalAddress": "г. Москва, ул. Энергетическая, д. 25",
"foundedYear": 2013,
"employeeCount": "70 сотрудников"
},
{
"id": "company-17",
"inn": "7730048049",
"ogrn": "1047730048049",
"fullName": "Общество с ограниченной ответственностью \"МедТех\"",
"shortName": "ООО \"МедТех\"",
"legalForm": "ООО",
"industry": "Медицина",
"companySize": "100-250",
"website": "https://medtech.ru",
"logo": "https://via.placeholder.com/100x100/E53E3E/FFFFFF?text=MT",
"slogan": "Медицинские технологии будущего",
"rating": 4.8,
"verified": true,
"phone": "+7 (495) 777-00-11",
"email": "info@medtech.ru",
"legalAddress": "г. Москва, ул. Медицинская, д. 35",
"foundedYear": 2015,
"employeeCount": "200 сотрудников"
},
{
"id": "company-18",
"inn": "7730048050",
"ogrn": "1047730048050",
"fullName": "Общество с ограниченной ответственностью \"ОбразЦентр\"",
"shortName": "ООО \"ОбразЦентр\"",
"legalForm": "ООО",
"industry": "Образование",
"companySize": "50-100",
"website": "https://obrazcentr.ru",
"logo": "https://via.placeholder.com/100x100/38A169/FFFFFF?text=OC",
"slogan": "Образование и развитие персонала",
"rating": 4.3,
"verified": true,
"phone": "+7 (495) 333-00-22",
"email": "info@obrazcentr.ru",
"legalAddress": "г. Москва, ул. Образовательная, д. 18",
"foundedYear": 2018,
"employeeCount": "60 сотрудников"
},
{
"id": "company-19",
"inn": "7730048051",
"ogrn": "1047730048051",
"fullName": "Общество с ограниченной ответственностью \"ФинКонсалт\"",
"shortName": "ООО \"ФинКонсалт\"",
"legalForm": "ООО",
"industry": "Финансы",
"companySize": "10-50",
"website": "https://finkonsalt.ru",
"logo": "https://via.placeholder.com/100x100/2B6CB0/FFFFFF?text=FK",
"slogan": "Финансовое консультирование",
"rating": 4.7,
"verified": true,
"phone": "+7 (495) 444-00-33",
"email": "info@finkonsalt.ru",
"legalAddress": "г. Москва, ул. Финансовая, д. 12",
"foundedYear": 2016,
"employeeCount": "35 сотрудников"
},
{
"id": "company-20",
"inn": "7730048052",
"ogrn": "1047730048052",
"fullName": "Общество с ограниченной ответственностью \"АгроТех\"",
"shortName": "ООО \"АгроТех\"",
"legalForm": "ООО",
"industry": "Сельское хозяйство",
"companySize": "100-250",
"website": "https://agrotech.ru",
"logo": "https://via.placeholder.com/100x100/38A169/FFFFFF?text=AT",
"slogan": "Современные технологии в сельском хозяйстве",
"rating": 4.5,
"verified": true,
"phone": "+7 (495) 666-00-44",
"email": "info@agrotech.ru",
"legalAddress": "г. Москва, ул. Аграрная, д. 28",
"foundedYear": 2012,
"employeeCount": "160 сотрудников"
}
]
}

View File

@@ -0,0 +1,158 @@
{
"mockProducts": [
{
"id": "prod-1",
"name": "Металлические конструкции",
"description": "Производство и поставка металлических конструкций любой сложности для строительства",
"category": "Строительные материалы",
"type": "sell",
"companyId": "company-4",
"price": "от 50 000 руб/тонна",
"createdAt": "{{date-10-days}}",
"updatedAt": "{{date-2-days}}"
},
{
"id": "prod-2",
"name": "Стальные балки и профили",
"description": "Высококачественные стальные балки и профили для промышленного строительства",
"category": "Металлопрокат",
"type": "sell",
"companyId": "company-8",
"price": "от 45 000 руб/тонна",
"createdAt": "{{date-8-days}}",
"updatedAt": "{{date-1-day}}"
},
{
"id": "prod-3",
"name": "Пластиковые изделия",
"description": "Производство пластиковых изделий для различных отраслей промышленности",
"category": "Пластик",
"type": "sell",
"companyId": "company-9",
"price": "от 200 руб/кг",
"createdAt": "{{date-15-days}}",
"updatedAt": "{{date-3-days}}"
},
{
"id": "prod-4",
"name": "Строительные материалы",
"description": "Полный спектр строительных материалов для жилого и коммерческого строительства",
"category": "Строительные материалы",
"type": "sell",
"companyId": "company-1",
"price": "по запросу",
"createdAt": "{{date-20-days}}",
"updatedAt": "{{date-5-days}}"
},
{
"id": "prod-5",
"name": "IT-решения для бизнеса",
"description": "Разработка программного обеспечения и IT-консалтинг для предприятий",
"category": "IT-услуги",
"type": "sell",
"companyId": "company-12",
"price": "от 100 000 руб/проект",
"createdAt": "{{date-12-days}}",
"updatedAt": "{{date-2-days}}"
},
{
"id": "prod-6",
"name": "Логистические услуги",
"description": "Комплексные логистические услуги по всей России и СНГ",
"category": "Логистика",
"type": "sell",
"companyId": "company-5",
"price": "от 15 руб/км",
"createdAt": "{{date-18-days}}",
"updatedAt": "{{date-4-days}}"
},
{
"id": "prod-7",
"name": "Пищевая продукция",
"description": "Производство качественных продуктов питания для HoReCa и розничной торговли",
"category": "Пищевая продукция",
"type": "sell",
"companyId": "company-15",
"price": "по прайс-листу",
"createdAt": "{{date-25-days}}",
"updatedAt": "{{date-7-days}}"
},
{
"id": "prod-8",
"name": "Медицинское оборудование",
"description": "Поставка современного медицинского оборудования и расходных материалов",
"category": "Медицинское оборудование",
"type": "sell",
"companyId": "company-17",
"price": "по запросу",
"createdAt": "{{date-30-days}}",
"updatedAt": "{{date-10-days}}"
},
{
"id": "prod-9",
"name": "Запчасти для спецтехники",
"description": "Ищем надежного поставщика запчастей для строительной техники Caterpillar, Komatsu",
"category": "Запчасти",
"type": "buy",
"companyId": "company-2",
"budget": "до 500 000 руб",
"createdAt": "{{date-5-days}}",
"updatedAt": "{{date-1-day}}"
},
{
"id": "prod-10",
"name": "Сырье для производства",
"description": "Требуется качественное сырье для производства пластиковых изделий",
"category": "Сырье",
"type": "buy",
"companyId": "company-9",
"budget": "до 1 000 000 руб",
"createdAt": "{{date-7-days}}",
"updatedAt": "{{date-2-days}}"
},
{
"id": "prod-11",
"name": "IT-оборудование",
"description": "Закупка серверного оборудования и сетевого оборудования для офиса",
"category": "IT-оборудование",
"type": "buy",
"companyId": "company-13",
"budget": "до 2 000 000 руб",
"createdAt": "{{date-3-days}}",
"updatedAt": "{{date-1-day}}"
},
{
"id": "prod-12",
"name": "Консалтинговые услуги",
"description": "Требуется консультация по оптимизации бизнес-процессов",
"category": "Консалтинг",
"type": "buy",
"companyId": "company-14",
"budget": "до 300 000 руб",
"createdAt": "{{date-4-days}}",
"updatedAt": "{{date-1-day}}"
},
{
"id": "prod-13",
"name": "Образовательные программы",
"description": "Поиск поставщика корпоративного обучения для сотрудников",
"category": "Образование",
"type": "buy",
"companyId": "company-18",
"budget": "до 200 000 руб",
"createdAt": "{{date-6-days}}",
"updatedAt": "{{date-2-days}}"
},
{
"id": "prod-14",
"name": "Финансовые услуги",
"description": "Требуется консультация по инвестиционному планированию",
"category": "Финансовые услуги",
"type": "buy",
"companyId": "company-19",
"budget": "до 150 000 руб",
"createdAt": "{{date-2-days}}",
"updatedAt": "{{date-1-day}}"
}
]
}

View File

@@ -0,0 +1,122 @@
{
"suggestions": [
"Строительные материалы",
"Металлоконструкции",
"Логистические услуги",
"Промышленное оборудование",
"Запчасти для спецтехники",
"IT-решения",
"Консалтинговые услуги",
"Пищевая продукция",
"Энергетическое оборудование",
"Медицинские технологии",
"Образовательные услуги",
"Финансовые услуги",
"Сельскохозяйственная техника",
"Торговое оборудование",
"Производственные услуги"
],
"searchHistory": [
{
"query": "строительные материалы",
"timestamp": "{{date-1-day}}"
},
{
"query": "металлоконструкции",
"timestamp": "{{date-2-days}}"
},
{
"query": "логистические услуги",
"timestamp": "{{date-3-days}}"
},
{
"query": "IT-решения",
"timestamp": "{{date-5-days}}"
},
{
"query": "консалтинг",
"timestamp": "{{date-7-days}}"
},
{
"query": "пищевая продукция",
"timestamp": "{{date-10-days}}"
},
{
"query": "медицинское оборудование",
"timestamp": "{{date-12-days}}"
},
{
"query": "образовательные услуги",
"timestamp": "{{date-15-days}}"
},
{
"query": "финансовые услуги",
"timestamp": "{{date-18-days}}"
},
{
"query": "сельскохозяйственная техника",
"timestamp": "{{date-20-days}}"
}
],
"savedSearches": [
{
"id": "saved-1",
"name": "Строительные компании",
"params": {
"industries": ["Строительство"],
"minRating": 4.5
},
"createdAt": "{{date-7-days}}"
},
{
"id": "saved-2",
"name": "Поставщики металла",
"params": {
"query": "металл",
"industries": ["Производство"]
},
"createdAt": "{{date-14-days}}"
},
{
"id": "saved-3",
"name": "IT-компании",
"params": {
"industries": ["IT"],
"minRating": 4.0
},
"createdAt": "{{date-21-days}}"
},
{
"id": "saved-4",
"name": "Логистические услуги",
"params": {
"industries": ["Логистика"],
"companySize": ["100-250", "250-500"]
},
"createdAt": "{{date-28-days}}"
},
{
"id": "saved-5",
"name": "Консалтинговые услуги",
"params": {
"industries": ["Услуги"],
"minRating": 4.3
},
"createdAt": "{{date-35-days}}"
}
],
"recommendationReasons": {
"Строительство": "Отличная репутация в строительной сфере",
"Производство": "Высокое качество производимой продукции",
"Логистика": "Надежные логистические решения",
"Торговля": "Широкий ассортимент и быстрые поставки",
"IT": "Инновационные IT-решения",
"Услуги": "Профессиональные консалтинговые услуги",
"Пищевая промышленность": "Качественная пищевая продукция",
"Энергетика": "Энергоэффективные решения",
"Медицина": "Современные медицинские технологии",
"Образование": "Эффективные образовательные программы",
"Финансы": "Надежные финансовые услуги",
"Сельское хозяйство": "Современные агротехнологии"
}
}

View File

@@ -0,0 +1,13 @@
{
"mockUser": {
"id": "user-123",
"email": "test@company.com",
"firstName": "Иван",
"lastName": "Петров",
"position": "Генеральный директор"
},
"mockTokens": {
"accessToken": "mock-access-token-{{timestamp}}",
"refreshToken": "mock-refresh-token-{{timestamp}}"
}
}