示例#1
0
class FileModel(BasicModel):
    class Meta:
        label_name = {
            'title': u'顯示名稱',
            'display_name': u'顯示名稱',
            'children': u'子項目',
            'path_as_url': u'URL'
        }

    name = Fields.StringProperty(verbose_name=u'名稱')
    path = Fields.StringProperty(verbose_name=u'檔案路徑')
    content_length = Fields.IntegerProperty(verbose_name=u'檔案大小', default=0)
    content_type = Fields.StringProperty(verbose_name=u'檔案類型', default='blob')
    content_language = Fields.StringProperty(verbose_name=u'語系')
    parent_resource = Fields.CategoryProperty(kind=selfReferentialModel,
                                              verbose_name=u'所屬目錄')
    is_collection = Fields.BooleanProperty(verbose_name=u'是否為目錄',
                                           default=False)
    is_root = Fields.BooleanProperty(verbose_name=u'是否為根目錄', default=False)
    created = Fields.DateTimeProperty(auto_now_add=True)
    modified = Fields.DateTimeProperty(auto_now=True)
    etag = Fields.StringProperty(verbose_name=u'ETag')
    resource_data = Fields.CategoryProperty(kind=FileDataModel,
                                            verbose_name=u'檔案實體')
    last_version = Fields.IntegerProperty(verbose_name=u'最新的版本', default=0)
    last_md5 = Fields.StringProperty(verbose_name=u'MD5', default=u'')
    file = Fields.BlobKeyProperty(verbose_name=u'BlobKey')
    theme = Fields.StringProperty(verbose_name=u'所屬樣式', default=u'')

    @property
    def abs_path(self):
        if self.is_collection is False:
            if str(self.path).startswith('themes/'):
                return '/assets/' + self.path
        return '/' + self.path

    @property
    def children(self):
        if self.is_collection:
            logging.info(self.key)
            return FileModel().all().filter(
                FileModel.parent_resource == self.key)
        else:
            return []

    @property
    def title(self):
        return self.name

    @property
    def display_name(self):
        return os.path.basename('%s' % self.path)

    @property
    def path_as_url(self):
        return pathname2url(self.path)

    @property
    def content_type_or_default(self):
        if self.is_collection:
            return 'httpd/unix-directory'
        else:
            mimetype = mimetypes.guess_type(self.path, strict=False)[0]
            return mimetype if mimetype else 'application/octet-stream'

    @property
    def is_code_file(self):
        return self.content_type in ([
            'css', 'js', 'javascript', 'html', 'text/css', 'text/html',
            'text/javascript'
        ])

    @classmethod
    def all_without_root(cls):
        return cls.query(cls.is_root == False).order(-cls.sort)

    @classmethod
    def code_files(cls):
        return cls.query(
            cls.content_type.IN([
                'css', 'js', 'javascript', 'html', 'text/css', 'text/html',
                'text/javascript'
            ]), ).order(-cls.sort, -cls.key)

    def make_directory(self):
        path = u'' + self.path
        if path[0:1] is u'/':
            path = path[1:]
        paths = path.split(u'/')
        last_parent = FileModel.root()
        if len(paths) > 1:
            for i in xrange(1, len(paths)):
                path_str = u'/'.join(paths[:i])
                if path_str is not u'':
                    collection = FileModel.get_by_path(path_str)
                    if collection is None:
                        collection = FileModel()
                        collection.name = paths[i]
                        collection.path = path_str
                        collection.parent_resource = last_parent.key
                        collection.is_collection = True
                        collection.put()
                    if collection != self and collection.is_collection is True:
                        last_parent = collection
        self.parent_resource = last_parent.key
        self.put()

    @classmethod
    def root(cls):
        root = cls.all().filter(cls.is_root == True).get()
        if not root:
            root = cls(path='', is_collection=True)
            root.name = '-Root-'
            root.is_root = True
            root.put()
        return root

    @classmethod
    def all_by_path(cls, path=''):
        query = cls.all().filter(cls.path == path + '%')
        return query

    @classmethod
    def get_by_path(cls, path=None):
        return cls.all().filter(cls.path == path).get() if path else cls.root()

    @classmethod
    def exists_with_path(cls, path='', is_collection=None):
        query = cls.all().filter(cls.path == path)
        if is_collection is not None:
            query = query.filter(cls.is_collection == True)
        return query.get(keys_only=True) is not None

    @classmethod
    def content_type_sort_by_name(cls, content_type):
        """ get record with content-type and sort by title """
        return cls.query(cls.content_type == content_type).order(cls.name)

    @classmethod
    def get_or_create(cls, path, content_type):
        n = cls.get_by_path(path)
        if n is None:
            n = cls()
            n.name = os.path.basename('%s' % path)
            n.path = path
            n.content_type = content_type
            n.put()
        return n

    def move_to_path(self, destination_path):
        """Moves this resource and all its children (if applicable) to a new path.
           Assumes that the new path is free and clear."""

        if self.is_collection:
            for child in self.children:
                child_name = os.path.basename(child.path)
                child_path = os.path.join(destination_path, child_name)
                child.move_to_path(child_path)

        self.path = destination_path
        self.put()

    def put(self):
        # type: () -> object
        # workaround for general non-solveable issue of no UNIQUE constraint concept in app engine datastore.
        # anytime we save, we look for the possibility of other duplicate Resources with the same path and delete them.

        try:
            for duped_resource in FileModel.all().filter(
                    FileModel.path == self.path):
                if self.key().id() != duped_resource.key().id():
                    logging.info(
                        'Deleting duplicate resource %s with path %s.' %
                        (duped_resource, duped_resource.path))
                    duped_resource.delete()
            if self.name != '-Root-':
                self.name = self.display_name
        except:
            pass
        paths = self.path.split('/')
        theme = ''
        if len(paths) >= 2 and paths[0] == 'themes':
            theme = paths[1]
        self.theme = theme
        super(FileModel, self).put()

    def delete(self):
        """Override delete to delete our associated ResourceData entity automatically."""
        if self.resource_data:
            n = self.resource_data.get()
            if n:
                n.key.delete()
        if self.last_version > 0:
            try:
                from plugins.code.models.code_model import CodeModel
                CodeModel.delete_with_target(self.key)
            except:
                pass
        self.key.delete()

    def delete_recursive(self):
        """Deletes this entity plus all of its children and other descendants."""
        if self.is_collection:
            for child in self.children:
                child.delete_recursive()
        self.delete()

    def export_response(self, href=None):
        datetime_format = '%Y-%m-%dT%H:%M:%SZ'

        response = ET.Element('D:response', {'xmlns:D': 'DAV:'})
        ET.SubElement(response, 'D:href').text = href
        propstat = ET.SubElement(response, 'D:propstat')
        prop = ET.SubElement(propstat, 'D:prop')

        if self.created:
            ET.SubElement(
                prop,
                'D:creationdate').text = self.created.strftime(datetime_format)

        ET.SubElement(prop, 'D:displayname').text = self.display_name

        if self.content_language:
            ET.SubElement(prop, 'D:getcontentlanguage').text = str(
                self.content_language)

        ET.SubElement(prop,
                      'D:getcontentlength').text = str(self.content_length)
        ET.SubElement(prop, 'D:getcontenttype').text = str(
            self.content_type_or_default)

        if self.modified:
            ET.SubElement(prop,
                          'D:getlastmodified').text = self.modified.strftime(
                              datetime_format)

        resourcetype = ET.SubElement(prop, 'D:resourcetype')

        if self.is_collection:
            ET.SubElement(resourcetype, 'D:collection')

        ET.SubElement(propstat, 'D:status').text = 'HTTP/1.1 200 OK'
        return response
class ShoppingCartItemModel(BasicModel):
    cart = Fields.KeyProperty(verbose_name=u'購物車', kind=ShoppingCartModel)
    spec = Fields.KeyProperty(verbose_name=u'產品規格',
                              kind=ProductSpecificationModel)
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    product_object = Fields.KeyProperty(verbose_name=u'所屬產品',
                                        kind=ProductModel)
    title = Fields.StringProperty(verbose_name=u'產品名稱', default=u'')
    product_name = Fields.StringProperty(verbose_name=u'產品名稱(系統)', default=u'')
    product_no = Fields.StringProperty(verbose_name=u'產品型號', default=u'')
    product_image = Fields.StringProperty(verbose_name=u'產品圖片', default=u'')
    price = Fields.FloatProperty(verbose_name=u'銷售價格', default=-1)
    cost = Fields.FloatProperty(verbose_name=u'成本', default=0.0)
    spec_full_name = Fields.StringProperty(verbose_name=u'完整規格名稱', default=u'')

    # 庫存相關
    try:
        from plugins.product_stock.models.stock_keeping_unit_model import StockKeepingUnitModel
    except ImportError:

        class StockKeepingUnitModel(BasicModel):
            pass

    sku = Fields.KeyProperty(verbose_name=u'最小庫存單位',
                             kind=StockKeepingUnitModel)
    sku_full_name = Fields.StringProperty(verbose_name=u'產品最小庫存名稱')
    expired_time = Fields.FloatProperty(verbose_name=u'庫存回收時間')
    quantity = Fields.IntegerProperty(verbose_name=u'數量', default=0)
    quantity_has_count = Fields.IntegerProperty(verbose_name=u'已計入庫存的數量',
                                                default=0)
    can_add_to_order = Fields.BooleanProperty(verbose_name=u'加至訂單中',
                                              default=False)

    try:
        from plugins.supplier.models.supplier_model import SupplierModel
    except ImportError:

        class SupplierModel(BasicModel):
            pass

    supplier = Fields.CategoryProperty(kind=SupplierModel, verbose_name=u'供應商')

    #  0=訂購(無庫存), 1=現貨, 2預購
    order_type = Fields.StringProperty(verbose_name=u'訂購方式')
    order_type_value = Fields.IntegerProperty(verbose_name=u'訂購方式(值)')

    size_1 = Fields.FloatProperty(verbose_name=u'長度(公分)', default=10.0)
    size_2 = Fields.FloatProperty(verbose_name=u'寬度(公分)', default=10.0)
    size_3 = Fields.FloatProperty(verbose_name=u'高度(公分)', default=10.0)
    weight = Fields.FloatProperty(verbose_name=u'重量(公斤)', default=10.0)

    @classmethod
    def get_or_create(cls, cart, user, product, spec, order_type=0):
        try:
            user_key = user.key
        except AttributeError:
            user_key = user
        item = cls.query(cls.cart == cart.key, cls.user == user_key,
                         cls.product_object == product.key,
                         cls.spec == spec.key,
                         cls.order_type_value == order_type).get()
        need_put = False
        if item is None:
            item = cls()
            item.cart = cart.key
            item.user = user_key
            item.product_object = product.key
            item.spec = spec.key
            item.order_type_value = order_type
            item.order_type = [u'訂購', u'現貨', u'預購'][order_type]
            item.spec_full_name = spec.full_name
            item.product_name = product.name
            item.product_image = product.image
            need_put = True
            if order_type == 0:
                item.can_add_to_order = True
        for field_name in [
                'title', 'product_no', 'price', 'cost', 'size_1', 'size_2',
                'size_3', 'weight'
        ]:
            if getattr(item, field_name) != getattr(product, field_name):
                setattr(item, field_name, getattr(product, field_name))
                need_put = True
        if need_put:
            item.put()
        return item

    @classmethod
    def get(cls, user, sku, order_type_value=0):
        return cls.query(cls.sku == sku.key, cls.user == user.key,
                         cls.order_type_value == order_type_value).get()

    @classmethod
    def get_or_create_with_spec(cls,
                                user,
                                spec,
                                quantity=0,
                                order_type_value=0):
        product = spec.product_object.get()
        item = cls.query(cls.sku == spec.key, cls.user == user.key,
                         cls.order_type_value == order_type_value).get()
        if item is None:
            item = cls()
            item.spec = spec.key
            item.user = user.key
            item.order_type_value = order_type_value
            item.product_object = product.key
            try:
                item.supplier = product.supplier.get().key
            except:
                pass
            if order_type_value == 0:
                item.order_type = u'訂購'
            else:
                item.order_type = u'預購'
        item._spec = spec
        item._product = product
        item.title = product.title
        item.product_no = product.product_no
        item.product_image = product.image
        item.spec_full_name = spec.spec_full_name
        item.change_quantity(quantity)
        item.put()
        return item

    @classmethod
    def all_with_user(cls, user):
        key = None
        if user is not None:
            key = user.key
        return cls.query(cls.user == key).order(-cls.sort)

    @classmethod
    def before_delete(cls, key):
        item = key.get()
        if item.order_type_value == 0:
            if item.quantity > 0:
                try:
                    sku = item.sku_instance
                    sku.change_estimate_quantity(item.quantity_has_count)
                    sku.put()
                except:
                    pass

    def volumetric_weight(self, divisor=6000.0):
        n = self.size_1 * self.size_2 * self.size_3 / float(divisor)
        return n

    @property
    def spec_instance(self):
        if not hasattr(self, '_spec'):
            self._spec = self.spec.get()
        return self._spec

    @property
    def sku_instance(self):
        if not hasattr(self, '_sku'):
            self._sku = self.sku.get()
        return self._sku

    @property
    def product_instance(self):
        if not hasattr(self, '_product'):
            self._product = self.spec_instance.product_object.get()
        return self._product

    def change_quantity(self, quantity):
        spec = self.spec_instance
        product = self.product_instance
        if self.order_type_value == 0:
            config = ConfigModel.get_config()
            if config.stock_recover:
                self.expired_time = time() + config.stock_recover_time
            else:
                self.expired_time = time() + 525600
            can_use_quantity = spec.quantity_can_be_used + int(
                self.quantity_has_count)
            old_quantity_has_count = self.quantity_has_count
            if can_use_quantity >= quantity and product.can_order:
                self.can_add_to_order = True
                self.quantity = quantity
                self.quantity_has_count = quantity
            else:
                self.can_add_to_order = False
                self.quantity = 0
                self.quantity_has_count = 0
            spec.change_estimate_quantity(sub_quantity=old_quantity_has_count,
                                          add_quantity=self.quantity)
            spec.put()
        else:
            if product.can_pre_order:
                self.can_add_to_order = True
                self.quantity = quantity
            else:
                self.can_add_to_order = False
                self.quantity = 0
            spec.change_pre_order_quantity(sub_quantity=int(
                self.quantity_has_count),
                                           add_quantity=self.quantity)
            spec.put()

    def quantity_can_be_order(self, user=None, sku=None):
        if sku is None:
            sku = self.sku.get()
        if self.order_type_value > 0:
            return 999
        if user and self.quantity is not None:
            c = sku.quantity_can_be_used + self.quantity
            if c > 0:
                return c
        return sku.quantity_can_be_used
示例#3
0
class ShoppingCartModel(BasicModel):
    title = Fields.StringProperty(verbose_name=u'購物車名稱', default=u'預設')
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    total_size = Fields.FloatProperty(verbose_name=u'尺寸合計', default=0.0)
    total_volume = Fields.FloatProperty(verbose_name=u'體積合計', default=0.0)
    total_price = Fields.FloatProperty(verbose_name=u'金額合計', default=0.0)
    total_weight = Fields.FloatProperty(verbose_name=u'重量總重', default=0.0)
    total_volumetric_weight = Fields.FloatProperty(verbose_name=u'材積總重',
                                                   default=0.0)
    cost_for_items = Fields.FloatProperty(verbose_name=u'成本(項目)',
                                          default=0.0,
                                          tab_page=4)
    freight = Fields.FloatProperty(verbose_name=u'運費', default=0.0)
    freight_type = Fields.KeyProperty(verbose_name=u'運送方式',
                                      kind=FreightTypeModel)

    try:
        from plugins.supplier.models.supplier_model import SupplierModel
    except ImportError:

        class SupplierModel(BasicModel):
            pass

    supplier = Fields.CategoryProperty(verbose_name=u'供應商', kind=SupplierModel)

    @classmethod
    def get_or_create(cls, user, supplier=None, supplier_key=None):
        if supplier is not None and supplier_key is None:
            supplier_key = supplier.key
        cart = cls.query(cls.user == user.key,
                         cls.supplier == supplier_key).get()
        if cart is None:
            cart = cls()
            cart.user = user.key
            if supplier_key:
                cart.supplier = supplier_key
            cart.put()
        return cart

    def get_shopping_cart_item(self, product, spec, item_order_type):
        from shopping_cart_item_model import ShoppingCartItemModel
        return ShoppingCartItemModel.get_or_create(self, self.user, product,
                                                   spec, item_order_type)

    @property
    def items(self):
        from shopping_cart_item_model import ShoppingCartItemModel
        return ShoppingCartItemModel.query(
            ShoppingCartItemModel.cart == self.key).fetch()

    def clean(self):
        if len(self.items) == 0:
            self.key.delete()

    def calc_size_weight_price_and_put(self, items=None):
        if items is None:
            items = self.items
        total_volume = 0.0
        total_size = 0.0
        total_price = 0.0
        total_weight = 0.0
        total_volumetric_weight = 0.0
        total_cost_for_items = 0.0
        for cart_item in items:
            total_size += cart_item.quantity * (
                cart_item.size_1 + cart_item.size_2 + cart_item.size_3)
            total_volume += cart_item.quantity * cart_item.size_1 * cart_item.size_2 * cart_item.size_3
            total_price += cart_item.quantity * cart_item.price
            total_weight += cart_item.quantity * cart_item.weight
            total_volumetric_weight += cart_item.quantity * cart_item.volumetric_weight(
            )
            total_cost_for_items += cart_item.quantity * cart_item.cost
        self.total_volume = total_volume
        self.total_size = total_size
        self.total_price = total_price
        self.total_weight = total_weight
        self.total_volumetric_weight = total_volumetric_weight
        self.cost_for_items = total_cost_for_items
        self.put()