- Portfolio CRUD: добавление, редактирование, удаление, переключение публикации - Services CRUD: полное управление услугами с возможностью активации/деактивации - Banner system: новая модель Banner с CRUD операциями и аналитикой кликов - Telegram integration: расширенные настройки бота, обнаружение чатов, отправка сообщений - Media management: улучшенная загрузка файлов с оптимизацией изображений и превью - UI improvements: обновлённые админ-панели с rich-text редактором и drag&drop загрузкой - Database: добавлена таблица banners с полями для баннеров и аналитики
108 lines
2.3 KiB
JavaScript
108 lines
2.3 KiB
JavaScript
const { DataTypes } = require('sequelize');
|
|
const { sequelize } = require('../config/database');
|
|
|
|
const Contact = sequelize.define('Contact', {
|
|
id: {
|
|
type: DataTypes.UUID,
|
|
defaultValue: DataTypes.UUIDV4,
|
|
primaryKey: true
|
|
},
|
|
name: {
|
|
type: DataTypes.STRING,
|
|
allowNull: false,
|
|
set(value) {
|
|
this.setDataValue('name', value.trim());
|
|
}
|
|
},
|
|
email: {
|
|
type: DataTypes.STRING,
|
|
allowNull: false,
|
|
validate: {
|
|
isEmail: true
|
|
},
|
|
set(value) {
|
|
this.setDataValue('email', value.toLowerCase().trim());
|
|
}
|
|
},
|
|
phone: {
|
|
type: DataTypes.STRING,
|
|
allowNull: true,
|
|
set(value) {
|
|
this.setDataValue('phone', value ? value.trim() : null);
|
|
}
|
|
},
|
|
company: {
|
|
type: DataTypes.STRING,
|
|
allowNull: true,
|
|
set(value) {
|
|
this.setDataValue('company', value ? value.trim() : null);
|
|
}
|
|
},
|
|
subject: {
|
|
type: DataTypes.STRING,
|
|
allowNull: false,
|
|
set(value) {
|
|
this.setDataValue('subject', value.trim());
|
|
}
|
|
},
|
|
message: {
|
|
type: DataTypes.TEXT,
|
|
allowNull: false
|
|
},
|
|
serviceInterest: {
|
|
type: DataTypes.ENUM('web-development', 'mobile-app', 'ui-ux-design', 'branding', 'consulting', 'other'),
|
|
allowNull: true
|
|
},
|
|
budget: {
|
|
type: DataTypes.ENUM('under-1m', '1m-5m', '5m-10m', '10m-20m', '20m-50m', 'over-50m'),
|
|
allowNull: true
|
|
},
|
|
timeline: {
|
|
type: DataTypes.ENUM('asap', '1-month', '1-3-months', '3-6-months', 'flexible'),
|
|
allowNull: true
|
|
},
|
|
status: {
|
|
type: DataTypes.ENUM('new', 'in-progress', 'replied', 'closed'),
|
|
defaultValue: 'new'
|
|
},
|
|
priority: {
|
|
type: DataTypes.ENUM('low', 'medium', 'high', 'urgent'),
|
|
defaultValue: 'medium'
|
|
},
|
|
source: {
|
|
type: DataTypes.ENUM('website', 'telegram', 'email', 'phone', 'referral'),
|
|
defaultValue: 'website'
|
|
},
|
|
isRead: {
|
|
type: DataTypes.BOOLEAN,
|
|
defaultValue: false
|
|
},
|
|
adminNotes: {
|
|
type: DataTypes.TEXT,
|
|
allowNull: true
|
|
},
|
|
ipAddress: {
|
|
type: DataTypes.STRING,
|
|
allowNull: true
|
|
},
|
|
userAgent: {
|
|
type: DataTypes.TEXT,
|
|
allowNull: true
|
|
}
|
|
}, {
|
|
tableName: 'contacts',
|
|
timestamps: true,
|
|
indexes: [
|
|
{
|
|
fields: ['status', 'createdAt']
|
|
},
|
|
{
|
|
fields: ['isRead', 'createdAt']
|
|
},
|
|
{
|
|
fields: ['email']
|
|
}
|
|
]
|
|
});
|
|
|
|
module.exports = Contact; |