class SideBarCrossSellingBox(Folder): class_id = 'vertical-item-sidebar-cross-selling-box' class_version = '20090122' class_title = MSG(u'Vertical item cross selling') class_views = ['edit', 'configure'] order_path = 'order-products' order_class = CrossSellingTable __fixed_handlers__ = [order_path] edit_schema = {} edit_widgets = [] item_widgets = [] edit = AutomaticEditView() view = SideBarCrossSellingBox_View() configure = GoToSpecificDocument(title=MSG(u'Configurer'), specific_document=order_path) @staticmethod def _make_resource(cls, folder, name, **kw): Folder._make_resource(cls, folder, name, **kw) order_class = cls.order_class order_class._make_resource(order_class, folder, '%s/%s' % (name, cls.order_path)) @classmethod def get_metadata_schema(cls): return merge_dicts(Folder.get_metadata_schema(), CrossSellingTable.get_metadata_schema())
class Supplier(Folder): class_id = 'supplier' class_title = MSG(u'Supplier') class_views = ['edit'] edit = AutomaticEditView() add_image = CurrentFolder_AddImage() # Edit views edit_schema = { 'address': Unicode(mandatory=True), 'phone': String, 'fax': String, 'email': Email, 'description': Unicode(multilingual=True) } edit_widgets = [ MultilineWidget('address', title=MSG(u'Address')), TextWidget('phone', title=MSG(u'Phone')), TextWidget('fax', title=MSG(u'Fax')), TextWidget('email', title=MSG(u'Email')), MultilineWidget('description', title=MSG(u'Description')) ] @classmethod def get_metadata_schema(cls): return merge_dicts(Folder.get_metadata_schema(), cls.edit_schema)
class Manufacturer(Folder): class_id = 'manufacturer' class_title = MSG(u'Manufacturer') class_views = ['view', 'edit'] view = Manufacturer_View() edit = AutomaticEditView() add_image = CurrentFolder_AddImage() # Edit configuration edit_show_meta = True edit_schema = { 'data': XHTMLBody(mandatory=True, multilingual=True), 'photo': PathDataType(mandatory=True) } edit_widgets = [ ImageSelectorWidget('photo', title=MSG(u'Photo')), RTEWidget('data', title=MSG(u'Data')) ] @classmethod def get_metadata_schema(cls): return merge_dicts(Folder.get_metadata_schema(), data=XHTMLBody(multilingual=True), photo=PathDataType)
class ShopModule_Advertising_Ad(ShopFolder): class_id = 'shop_module_advertising_ad' class_title = MSG(u'Advertising, an Ad') class_views = ['edit'] edit = AutomaticEditView() edit_schema = {'code': XHTMLBody(sanitize_html=False)} edit_widgets = [MultilineWidget('code', title=MSG(u'Code'))] @classmethod def get_metadata_schema(cls): return merge_dicts(ShopFolder.get_metadata_schema(), cls.edit_schema)
class CrossSelling_Section(Folder): """ XXX That should be a section_view on 0.62 """ class_id = 'section-cross-selling' class_title = MSG(u'Cross Selling Section') class_views = ['view', 'edit'] view = CrossSelling_Section_View() edit = AutomaticEditView() # Edit views edit_schema = {'product_model': ProductModelsEnumerate} edit_widgets = [ SelectWidget('product_model', title=MSG(u'Product model')), ]
class ShopForm(OrderedTable): class_id = 'shop-form' class_title = MSG(u'Shop form') class_version = '20090609' class_handler = ShopFormTable class_views = ['display', 'edit', 'view', 'add_record'] display = ShopForm_Display() view = OrderedTable_View(search_template=None, access='is_admin') edit = AutomaticEditView() add_product = AddProduct_View() form = [ TextWidget('name', title=MSG(u'Name')), TextWidget('title', title=MSG(u'Title')), BooleanCheckBox('mandatory', title=MSG(u'Mandatory')), BooleanCheckBox('multiple', title=MSG(u'Multiple')), SelectWidget('datatype', title=MSG(u'Data Type')), SelectWidget('widget', title=MSG(u'Widget')), ] edit_widgets = [ TextWidget('submit_value', title=MSG(u'Submit value')), TextWidget('to_addr', title=MSG(u'To addr')), RTEWidget('introduction', title=MSG(u'Introduction')), RTEWidget('final_message', title=MSG(u'Final message')), BooleanRadio('must_be_authentificated', title=MSG(u'Must be authentificated to see form')) ] edit_schema = { 'submit_value': Unicode(multilingual=True, mandatory=True), 'to_addr': Email(mandatory=True), 'introduction': XHTMLBody(multilingual=True), 'final_message': XHTMLBody(multilingual=True), 'must_be_authentificated': Boolean } @classmethod def get_metadata_schema(cls): return merge_dicts(OrderedTable.get_metadata_schema(), cls.edit_schema)
class Filter_Criterium_Categorie(Folder): class_id = 'sidebar-item-filter-box-criterium-categorie' class_title = MSG(u'Catégorie criterium') class_views = ['edit'] edit = AutomaticEditView(access='is_admin') edit_show_meta = False edit_schema = {'base_abspath': CategoriesEnumerate(mandatory=True)} edit_widgets = [SelectWidget('base_abspath', title=MSG(u'Base Abspath'))] @classmethod def get_metadata_schema(cls): return merge_dicts(Folder.get_metadata_schema(), base_abspath=CategoriesEnumerate) def get_items(self, context): options = [] root = get_context().root base_abspath = self.get_property('base_abspath') base_resource = root.get_resource(base_abspath) search = root.search(format='category', parent_paths=base_abspath) items_list = [base_resource] for brain in search.get_documents(sort_by='abspath'): items_list.append(root.get_resource(brain.abspath)) for resource in items_list: abspath = str(resource.get_abspath()) selected = context.resource.get_abspath() == abspath uri = get_reference(context.get_link(resource)) uri.query = context.uri.query title = resource.get_title() if abspath == base_abspath: title = MSG(u'All') options.append({ 'name': abspath, 'criterium': 'category', 'query': PhraseQuery('parent_paths', abspath), 'selected': selected, 'uri': uri, 'css': 'selected' if selected else None, 'title': title }) return options
class Filter_Criterium(Folder): class_id = 'sidebar-item-filter-box-criterium' class_title = MSG(u'Criterium') class_views = ['edit'] @classmethod def get_metadata_schema(cls): return merge_dicts(Folder.get_metadata_schema(), criterium=Filter_DFT_Enumerate) edit = AutomaticEditView(access='is_admin') edit_show_meta = False edit_schema = {'criterium': Filter_DFT_Enumerate(mandatory=True)} edit_widgets = [SelectWidget('criterium', title=MSG(u'Criterium'))] def get_items(self, context): options = [] uri = deepcopy(context.uri) criterium = self.get_property('criterium') criterium_name = 'DFT-%s' % criterium enum = EnumerateTable_to_Enumerate(enumerate_name=criterium) options = [] for option in [{ 'name': None, 'value': MSG(u'All') }] + enum.get_options(): selected = context.query.get(criterium_name) == option['name'] option['criterium'] = criterium kw = {criterium_name: option['name'], 'batch_start': 0} option['uri'] = uri.replace(**kw) option['query'] = None if option['name']: option['query'] = PhraseQuery(criterium_name, option['name']) option['selected'] = selected option['title'] = option['value'] option['css'] = 'selected' if selected else None options.append(option) return options
class ShopUser_Group(ShopFolder): class_id = 'user-group' class_views = ['edit', 'goto_categories', 'register', 'schema', 'welcome'] class_version = '20100719' class_title = MSG(u'User group') edit = AutomaticEditView() schema = GoToSpecificDocument(specific_document='schema', title=MSG(u'Schema')) welcome = GoToSpecificDocument(specific_document='welcome', title=MSG(u'Edit welcome page')) goto_categories = GoToSpecificDocument( specific_document='../../../categories', title=MSG(u'Revenir aux catégories')) register = Group_Register() edit_schema = {'register_title': Unicode(multilingual=True), 'register_body': XHTMLBody(multilingual=True), 'register_mail_subject': Unicode(multilingual=True), 'register_mail_body': Unicode(multilingual=True), 'validation_mail_subject': Unicode(multilingual=True), 'validation_mail_body': Unicode(multilingual=True), 'invalidation_mail_subject': Unicode(multilingual=True), 'invalidation_mail_body': Unicode(multilingual=True), 'hide_address_on_registration': Boolean, 'user_is_enabled_when_register': Boolean, 'use_default_price': Boolean, 'show_ht_price': Boolean, 'phone_is_mandatory_on_registration': Boolean, 'lastname_is_mandatory_on_registration': Boolean} edit_widgets = [TextWidget('register_title', title=MSG(u'Register view title ?')), RTEWidget('register_body', title=MSG(u'Register body')), TextWidget('register_mail_subject', title=MSG(u'Register mail subject')), MultilineWidget('register_mail_body', title=MSG(u'Register mail body')), TextWidget('validation_mail_subject', title=MSG(u'Validation mail subject')), MultilineWidget('validation_mail_body', title=MSG(u'Validation mail body')), TextWidget('invalidation_mail_subject', title=MSG(u'Invalidation mail subject')), MultilineWidget('invalidation_mail_body', title=MSG(u'Invalidation mail body')), BooleanRadio('hide_address_on_registration', title=MSG(u'Hide address on registration')), BooleanRadio('user_is_enabled_when_register', title=MSG(u'User is enabled ?')), BooleanRadio('use_default_price', title=MSG(u'Use default price ?')), BooleanRadio('show_ht_price', title=MSG(u'Show HT price ?')), BooleanRadio('lastname_is_mandatory_on_registration', title=MSG(u'Lastname is mandatory on registration ?')), BooleanRadio('phone_is_mandatory_on_registration', title=MSG(u'Phone is mandatory on registration ?'))] __fixed_handlers__ = ShopFolder.__fixed_handlers__ + ['welcome'] @staticmethod def _make_resource(cls, folder, name, *args, **kw): # Create group ShopFolder._make_resource(cls, folder, name, *args, **kw) # Group schema cls = CustomerSchema cls._make_resource(cls, folder, '%s/schema' % name) # Welcome Page cls = WebPage cls._make_resource(cls, folder, '%s/welcome' % name, title={'en': u'Welcome'}, state='public') @classmethod def get_metadata_schema(cls): return merge_dicts(ShopFolder.get_metadata_schema(), cls.edit_schema) def get_dynamic_schema(self): schema = self.get_resource('schema') return schema.get_model_schema() def get_dynamic_widgets(self): schema = self.get_resource('schema') return schema.get_model_widgets() def get_register_mail_subject(self): subject = self.get_property('register_mail_subject') if subject: return subject return MSG(u"Inscription confirmation.").gettext() def get_register_mail_body(self): body = self.get_property('register_mail_body') if body: return body return MSG(u"Your inscription has been validated").gettext() def get_prefix(self): # Price prefix # XXX for future we should add group property to price if self.name == 'default': return '' return '%s-' % self.name
class ShopModule_AReview(WorkflowAware, Folder): class_id = 'shop_module_a_review' class_title = MSG(u'A review') class_views = ['view'] view = ShopModule_AReview_View() viewbox = Review_Viewbox() add_report = ShopModule_AReport_NewInstance() # Edition edit = AutomaticEditView(access='is_admin') edit_show_meta = False display_title = False edit_schema = { 'title': Unicode, 'note': NoteEnumerate, 'advantages': Unicode, 'disadvantages': Unicode, 'description': Unicode, 'recommended': RecommandationEnumerate } edit_widgets = [ TextWidget('title', title=MSG(u'Title')), NoteWidget('note', title=MSG(u'Note'), has_empty_option=False), TextWidget('advantages', title=MSG(u'Advantages')), TextWidget('disadvantages', title=MSG(u'Disadvantages')), MultilineWidget('description', title=MSG(u'Your review')), SelectRadio('recommended', title=MSG(u'Recommendation'), has_empty_option=False, is_inline=True) ] @classmethod def get_metadata_schema(cls): return merge_dicts(Folder.get_metadata_schema(), WorkflowAware.get_metadata_schema(), ctime=DateTime, note=Integer(default=0), remote_ip=String, author=String, advantages=Unicode, disadvantages=Unicode, images=String, recommended=RecommandationEnumerate) def _get_catalog_values(self): values = Folder._get_catalog_values(self) values['ctime'] = self.get_property('ctime') values['shop_module_review_author'] = self.get_property('author') values['shop_module_review_note'] = self.get_property('note') # XXX description is multilingual in the DB (xml:lang=xx) values['shop_module_review_description'] = self.get_property( 'description') return values def get_namespace(self, context): # Build namespace namespace = { 'author': self.get_namespace_author(context), 'href': context.get_link(self), 'images': self.get_images(context) } for key in ['title', 'note', 'advantages', 'disadvantages']: namespace[key] = self.get_property(key) # Add informations about product product = self.parent.parent namespace['product'] = { 'link': context.get_link(product), 'title': product.get_title() } # Context here = context.resource namespace['is_on_user_view'] = here.class_id == 'user' namespace['is_on_product_view'] = here.class_id == 'product' # Description description = self.get_property('description').encode('utf-8') description = XMLContent.encode(description) namespace['description'] = XMLParser(description.replace( '\n', '<br/>')) # ctime ctime = self.get_property('ctime') accept = context.accept_language namespace['ctime'] = format_datetime(ctime, accept) # Recommendation recommended = self.get_property('recommended') or 0 namespace['recommendation'] = bool(int(recommended)) return namespace def get_namespace_author(self, context): if self.get_property('author') is None: return None from shop.utils import ResourceDynamicProperty author = self.get_property('author') author_resource = context.root.get_resource('/users/%s' % author) dynamic_user_value = ResourceDynamicProperty() dynamic_user_value.resource = author_resource return { 'title': author_resource.get_title(), 'public_title': author_resource.get_public_title(), 'dynamic_user_value': dynamic_user_value, 'href': context.get_link(author_resource) } def get_images(self, context, nb_images=None): path = self.get_property('images') if not path: return [] image = self.get_resource(path, soft=True) if image is None: return [] images = [] images.append({'src': context.get_link(image)}) return images
def set_value(self, resource, context, name, form): if name == 'update_now': resource.update_rss() return return AutomaticEditView.set_value(self, resource, context, name, form)
def get_value(self, resource, context, name, datatype): if name == 'update_now': return False return AutomaticEditView.get_value(self, resource, context, name, datatype)
class Category(ShopFolder): class_id = 'category' class_title = MSG(u'Category') # Edit configuration edit_show_meta = True edit_schema = { 'data': XHTMLBody(multilingual=True), 'breadcrumb_title': Unicode(multilingual=True), 'image_category': ImagePathDataType(multilingual=True), 'default_product_cover': ImagePathDataType(multilingual=True) } edit_widgets = [ TextWidget('breadcrumb_title', title=MSG(u'Breadcrumb title')), ImageSelectorWidget('image_category', title=MSG(u'Category image')), ImageSelectorWidget('default_product_cover', title=MSG(u'Default cover for products')), RTEWidget('data', title=MSG(u"Description")) ] # Views view = Category_View() browse_content = Products_View() view_categories = Category_BackofficeView() edit = AutomaticEditView() batch_edition = Category_BatchEdition() new_product = Product_NewProduct() new_category = NewCategory_Form() comparator = Category_Comparator() @property def class_views(self): context = get_context() # Back-Office hostname = context.uri.authority if hostname[:6] == 'admin.': return [ 'browse_content', 'new_product', 'view_categories', 'new_category', 'edit' ] return ['view', 'edit'] @classmethod def get_metadata_schema(cls): return merge_dicts( ShopFolder.get_metadata_schema(), data=XHTMLBody(multilingual=True), breadcrumb_title=Unicode(multilingual=True), image_category=ImagePathDataType(multilingual=True), default_product_cover=ImagePathDataType(multilingual=True)) def _get_catalog_values(self): # Get the languages site_root = self.get_site_root() languages = site_root.get_property('website_languages') # Titles m_title = {} m_breadcrumb_title = {} for language in languages: value = self.get_property('title', language=language) if value: m_title[language] = value value = self.get_property('breadcrumb_title', language=language) if value: m_breadcrumb_title[language] = value # Data data = self.get_property('data') if data is not None: data = xml_to_text(data) return merge_dicts( super(Category, self)._get_catalog_values(), data=data, # XXX Hack to be on sitemap workflow_state='public', m_title=m_title, m_breadcrumb_title=m_breadcrumb_title) def get_document_types(self): return [Product, Category] #################################### # Computed fields #################################### computed_schema = { 'nb_products': Integer(title=MSG(u'Nb products')), 'nb_categories': Integer(title=MSG(u'Nb sub categories')) } def get_nb_products(self, only_public=False): root = self.get_root() shop = get_shop(self) abspath = self.get_canonical_path() query = [ PhraseQuery('parent_paths', str(abspath)), PhraseQuery('format', shop.product_class.class_id) ] if shop.get_property('hide_not_buyable_products') is True: context = get_context() group_name = get_group_name(shop, context) query.append( NotQuery(PhraseQuery('not_buyable_by_groups', group_name))) if only_public is True: query.append(PhraseQuery('workflow_state', 'public')) return len(root.search(AndQuery(*query))) def get_nb_categories(self): root = self.get_root() abspath = self.get_canonical_path() query = AndQuery(PhraseQuery('parent_paths', str(abspath)), PhraseQuery('format', 'category')) return len(root.search(query)) @property def nb_products(self): return self.get_nb_products() @property def nb_categories(self): return self.get_nb_categories() ############################# # Export ############################# export = Export(export_resource=Product, access='is_allowed_to_edit', file_columns=[ 'reference', 'state', 'frontoffice_uri', 'cover_uri', 'manufacturer', 'price_with_tax', 'description' ])
class FilterRange_Table(Table): class_id = 'table-filter-by-price' # XXX We can change name class_title = MSG(u'Filter by range') class_handler = FilterRange_BaseTable form = [ TextWidget('min', title=MSG(u'Min')), TextWidget('max', title=MSG(u'Max')) ] edit = AutomaticEditView(access='is_admin') edit_show_meta = False edit_schema = { 'unit': Unicode, 'criterium': FilterRange_Enumerate(mandatory=True) } edit_widgets = [ SelectWidget('criterium', title=MSG(u'Criterirum')), TextWidget('unit', title=MSG(u'Unit')) ] @classmethod def get_metadata_schema(cls): return merge_dicts(Table.get_metadata_schema(), criterium=FilterRange_Enumerate, unit=Unicode) def get_items(self, context): unit = self.get_property('unit') criterium = self.get_property('criterium') uri = context.uri options = [] get_record_value = self.handler.get_record_value # Get values values = [(None, None)] for record in self.handler.get_records(): min_value = get_record_value(record, 'min') max_value = get_record_value(record, 'max') values.append((min_value, max_value)) for value in values: min_value, max_value = value min_value_q = int(min_value * 100) if min_value else None max_value_q = int(max_value * 100) if max_value else None value = (min_value_q, max_value_q) name = IntegerRange.encode(value) if min_value is None and max_value: title = MSG(u'Less than {max_value} {unit}') elif min_value and max_value: title = MSG(u'From {min_value} to {max_value} {unit}') elif max_value is None and min_value: title = MSG(u'More than {min_value} {unit}') else: title = MSG(u'All') name = None value = None selected = context.query.get(criterium) == value kw = {criterium: name, 'batch_start': 0} uri = uri.replace(**kw) title = title.gettext(min_value=min_value, max_value=max_value, unit=unit) options.append({ 'name': name, 'criterium': criterium, 'query': RangeQuery(criterium, min_value_q, max_value_q), 'selected': selected, 'uri': uri, 'css': 'selected' if selected else None, 'title': title }) return options
def action(self, resource, context, form): AutomaticEditView.action(self, resource, context, form) if not context.edit_conflict and form['force_update']: resource._update_data()