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:
@ -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 {
|
||||
|
Reference in New Issue
Block a user