feat: улучшения UI компонентов, документации и сервисов интеграций

## 🎯 Основные изменения:

###  Обновление документации интеграций
- Расширена документация DaData API integration
- Добавлены результаты тестирования и примеры использования
- Обновлена информация о статусе интеграций

###  Улучшения UI компонентов
- Обновлены market компоненты для корректной работы с GraphQL
- Исправлены параметры передачи данных в counterparties/logistics/sellers/suppliers
- Улучшен registration flow и confirmation step
- Обновлен dashboard home с новой функциональностью

###  Улучшения GraphQL резолверов
- Обновлен seller-consumables.ts с улучшенной обработкой данных
- Исправлены методы создания и обновления поставок
- Добавлена лучшая обработка ошибок и валидация

###  Обновление сервисов интеграций
- Улучшен wildberries-service.ts с новыми методами API
- Добавлена лучшая обработка ответов и ошибок
- Обновлены методы работы с маркетплейсами

## 🧪 Результат:
-  UI компоненты работают стабильнее
-  Документация актуализирована
-  Интеграции функционируют корректно
-  GraphQL запросы оптимизированы

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Veronika Smirnova
2025-09-12 15:50:23 +03:00
parent b78eb5eea8
commit 8e43df4d1d
10 changed files with 362 additions and 51 deletions

View File

@ -956,6 +956,224 @@ export class SMSService {
### 1. DaData Integration
**Статус:****ПОЛНОСТЬЮ АКТИВНА** (обновлено 10.09.2025)
DaData API успешно интегрирован и используется для валидации ИНН при регистрации организаций. Включает полную валидацию контрольных сумм и проверку активности организаций.
#### Реализация в проекте
**Основной сервис:** `/src/services/dadata-service.ts`
**GraphQL интеграция:** `/src/graphql/resolvers/domains/user-management.ts`
```typescript
// src/services/dadata-service.ts
export class DaDataService {
private apiKey: string
private apiUrl: string
constructor() {
const apiKey = process.env.DADATA_API_KEY
const apiUrl = process.env.DADATA_API_URL
if (!apiKey || !apiUrl) {
throw new Error('DaData API credentials not configured')
}
this.apiKey = apiKey
this.apiUrl = apiUrl
}
// Получает информацию об организации по ИНН с полной валидацией
async getOrganizationByInn(inn: string): Promise<OrganizationData | null> {
try {
const response = await axios.post<DaDataResponse>(
`${this.apiUrl}/findById/party`,
{
query: inn,
count: 1,
},
{
headers: {
Authorization: `Token ${this.apiKey}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
},
)
if (!response.data?.suggestions?.length) {
return null
}
const company = response.data.suggestions[0]
const organizationType = this.determineOrganizationType(company)
return {
inn: company.data.inn,
kpp: company.data.kpp || undefined,
name: company.data.name.short || company.data.name.full || 'Название не указано',
fullName: company.data.name.full_with_opf || '',
address: company.data.address?.value || '',
addressFull: company.data.address?.unrestricted_value || undefined,
ogrn: company.data.ogrn || undefined,
ogrnDate: this.parseDate(company.data.ogrn_date),
// Статус организации
status: company.data.state?.status,
actualityDate: this.parseDate(company.data.state?.actuality_date),
registrationDate: this.parseDate(company.data.state?.registration_date),
liquidationDate: this.parseDate(company.data.state?.liquidation_date),
// Руководитель
managementName: company.data.management?.name,
managementPost: company.data.management?.post,
// ОПФ
opfCode: company.data.opf?.code,
opfFull: company.data.opf?.full,
opfShort: company.data.opf?.short,
// Коды статистики
okato: company.data.okato,
oktmo: company.data.oktmo,
okpo: company.data.okpo,
okved: company.data.okved,
// Контакты
phones: company.data.phones || undefined,
emails: company.data.emails || undefined,
// Финансовые данные
employeeCount: company.data.employee_count || undefined,
revenue: company.data.finance?.revenue ? BigInt(company.data.finance.revenue) : undefined,
taxSystem: company.data.finance?.tax_system || undefined,
isActive: company.data.state?.status === 'ACTIVE',
type: organizationType,
rawData: company,
}
} catch (error) {
console.error('Error fetching organization data from DaData:', error)
return null
}
}
// Валидирует ИНН по контрольной сумме (математическая проверка)
validateInn(inn: string): boolean {
const digits = inn.replace(/\D/g, '')
if (digits.length !== 10 && digits.length !== 12) {
return false
}
// Проверяем контрольную сумму для 10-значного ИНН (юридические лица)
if (digits.length === 10) {
const checksum = this.calculateInn10Checksum(digits)
return checksum === parseInt(digits[9])
}
// Проверяем контрольную сумму для 12-значного ИНН (ИП)
if (digits.length === 12) {
const checksum1 = this.calculateInn12Checksum1(digits)
const checksum2 = this.calculateInn12Checksum2(digits)
return checksum1 === parseInt(digits[10]) && checksum2 === parseInt(digits[11])
}
return false
}
}
```
#### GraphQL Integration
```typescript
// src/graphql/resolvers/domains/user-management.ts
verifyInn: async (_: unknown, args: { inn: string }) => {
console.log('🔍 VERIFY_INN STARTED:', { inn: args.inn })
// Базовая проверка длины ИНН
if (!args.inn || (args.inn.length !== 10 && args.inn.length !== 12)) {
return {
success: false,
message: 'Некорректный ИНН. ИНН должен содержать 10 или 12 цифр',
organization: null,
}
}
try {
// Валидация ИНН по контрольной сумме
if (!dadataService.validateInn(args.inn)) {
return {
success: false,
message: 'Некорректный ИНН. Проверьте правильность введенных цифр',
organization: null,
}
}
// Получение данных из DaData
const organizationData = await dadataService.getOrganizationByInn(args.inn)
if (!organizationData) {
return {
success: false,
message: 'Организация с таким ИНН не найдена',
organization: null,
}
}
// Проверка активности организации
if (!organizationData.isActive) {
return {
success: false,
message: 'Организация не активна или ликвидирована',
organization: null,
}
}
return {
success: true,
message: 'ИНН верифицирован успешно',
organization: {
name: organizationData.name,
fullName: organizationData.fullName,
address: organizationData.address,
isActive: organizationData.isActive,
},
}
} catch (error) {
console.error('💥 VERIFY_INN ERROR:', error)
return {
success: false,
message: 'Ошибка при проверке ИНН. Попробуйте позже',
organization: null,
}
}
}
```
#### Результаты тестирования (10.09.2025)
**✅ Успешно протестированные ИНН:**
- `7743291031` → "А-Я ЛОГИСТИКА" (активная организация)
- `7736207543` → "ЯНДЕКС" (активная организация)
- `7702070139` → "БАНК ВТБ" (активная организация)
**✅ Валидация ошибок:**
- `1234567890` → "Некорректный ИНН. Проверьте правильность введенных цифр" (не прошел контрольную сумму)
**✅ End-to-End тестирование:**
- Полный цикл регистрации организации работает: SMS → Phone Verification → INN Validation → Organization Creation
#### Конфигурация
```bash
# .env
DADATA_API_KEY="5de23c9479b903317b1e76cfa7e8eba7ab24385b"
DADATA_API_URL="https://suggestions.dadata.ru/suggestions/api/4_1/rs"
```
#### Legacy DaData API класс (для справки)
```typescript
// src/lib/integrations/dadata.ts
export class DaDataAPI {