# 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._deleted || newDoc.deleted) { // Проверяем права пользователя на удаление if (userCtx.roles.indexOf('_admin') === -1) { throw({forbidden: 'Only admins can delete documents'}); } return; // Разрешаем удаление } // Проверка типа документа if (newDoc.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) { throw({forbidden: 'Product must have a name'}); } if (!newDoc.sku) { 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.deleted) { throw({forbidden: 'Category must have a name'}); } } // Проверка неизменяемых полей if (oldDoc) { if (oldDoc.type !== newDoc.type) { throw({forbidden: 'Document type cannot be changed'}); } if (oldDoc.createdAt !== newDoc.createdAt) { throw({forbidden: 'Creation date cannot be changed'}); } } } """ language: "javascript" } module.exports = new SiteDesignDocuments()