# app/design/site.coffee class SiteDesignDocuments constructor: -> @designDocs = { products: @getProductsDesignDoc() categories: @getCategoriesDesignDoc() orders: @getOrdersDesignDoc() validation: @getValidationDesignDoc() domains: @getDomainsDesignDoc() } getProductsDesignDoc: -> { _id: '_design/products' views: # Все активные товары all_active: map: """ function(doc) { if (doc.type === 'product' && doc.active !== false) { emit(doc._id, null); } } """ # Товары по категориям by_category: map: """ function(doc) { if (doc.type === 'product' && doc.active !== false && doc.category) { emit([doc.category, doc.name], { name: doc.name, price: doc.price, brand: doc.brand, inStock: doc.inStock, images: doc.images }); } } """ # Товары по брендам by_brand: map: """ function(doc) { if (doc.type === 'product' && doc.active !== false && doc.brand) { emit([doc.brand, doc.name], null); } } """ # Поиск по SKU by_sku: map: """ function(doc) { if (doc.type === 'product' && doc.sku) { emit(doc.sku, null); } } """ # Товары по доменам by_domain: map: """ function(doc) { if (doc.type === 'product' && doc.active !== false && doc.domains) { doc.domains.forEach(function(domain) { emit(domain, null); }); } } """ language: "javascript" } getCategoriesDesignDoc: -> { _id: '_design/categories' views: # Все активные категории all_active: map: """ function(doc) { if (doc.type === 'category' && doc.active !== false) { emit(doc._id, null); } } """ # Категории по slug by_slug: map: """ function(doc) { if (doc.type === 'category' && doc.slug) { emit(doc.slug, null); } } """ # Иерархия категорий hierarchical: map: """ function(doc) { if (doc.type === 'category' && doc.active !== false) { var path = doc.parent ? [doc.parent, doc._id] : [doc._id]; emit(path, { name: doc.name, parent: doc.parent, order: doc.order }); } } """ # Категории по доменам by_domain: map: """ function(doc) { if (doc.type === 'category' && doc.active !== false && doc.domains) { doc.domains.forEach(function(domain) { emit(domain, null); }); } } """ language: "javascript" } getOrdersDesignDoc: -> { _id: '_design/orders' views: # Заказы по пользователю by_user: map: """ function(doc) { if (doc.type === 'order' && doc.userId) { emit([doc.userId, doc.createdAt], null); } } """ # Заказы по статусу by_status: map: """ function(doc) { if (doc.type === 'order' && doc.status) { emit([doc.status, doc.createdAt], null); } } """ language: "javascript" } getDomainsDesignDoc: -> { _id: '_design/domains' views: # Настройки по доменам settings_by_domain: map: """ function(doc) { if (doc.type === 'domain_settings' && doc.domain) { emit(doc.domain, null); } } """ language: "javascript" } getValidationDesignDoc: -> { _id: '_design/validation' validate_doc_update: """ function(newDoc, oldDoc, userCtx, secObj) { // Базовые проверки для всех документов if (!newDoc.type) { throw({forbidden: 'Document must have a type'}); } // Разрешенные типы документов var validTypes = [ 'product', 'category', 'order', 'user', 'domain_settings', 'hero_slide', 'blog_article' ]; if (validTypes.indexOf(newDoc.type) === -1) { throw({forbidden: 'Invalid document type: ' + newDoc.type}); } // Проверка товаров if (newDoc.type === 'product') { if (!newDoc.name || newDoc.name.trim() === '') { throw({forbidden: 'Product must have a name'}); } if (!newDoc.sku || newDoc.sku.trim() === '') { throw({forbidden: 'Product must have SKU'}); } if (typeof newDoc.price !== 'number' || newDoc.price < 0) { throw({forbidden: 'Product must have valid price'}); } } // Проверка категорий if (newDoc.type === 'category') { if (!newDoc.name || newDoc.name.trim() === '') { throw({forbidden: 'Category must have a name'}); } if (!newDoc.slug || newDoc.slug.trim() === '') { throw({forbidden: 'Category must have a slug'}); } } // Проверка заказов if (newDoc.type === 'order') { if (!newDoc.userId) { throw({forbidden: 'Order must have user ID'}); } if (!Array.isArray(newDoc.items) || newDoc.items.length === 0) { throw({forbidden: 'Order must have items'}); } } // Запрет изменения типа документа if (oldDoc && oldDoc.type !== newDoc.type) { throw({forbidden: 'Document type cannot be changed'}); } } """ language: "javascript" } module.exports = new SiteDesignDocuments()