コード例 #1
0
class RoleModel(BasicModel):
    name = Fields.StringProperty(required=True, verbose_name=u'識別名稱')
    title = Fields.StringProperty(required=True, verbose_name=u'角色名稱')
    prohibited_actions = Fields.TextProperty(verbose_name=u'禁止的操作', default='')
    level = Fields.IntegerProperty(verbose_name=u'權限等級', default=0)

    @classmethod
    def create_role(cls, name, title, level, prohibited_actions):
        n = cls()
        n.name = name
        n.title = title
        n.level = level
        n.prohibited_actions = prohibited_actions
        n.put()
        return n

    @classmethod
    def get_role(cls, name):
        a = cls.query(cls.name == name).get()
        return a

    @classmethod
    def get_list(cls):
        return cls.query(cls.level < 1000).order(cls.level, -cls.sort)

    @classmethod
    def find_lowest_level(cls):
        return cls.query().order(cls.level).get()
コード例 #2
0
class PageTrackerModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    title = Fields.StringProperty(verbose_name=u'標題')
    content = Fields.RichTextProperty(verbose_name=u'內容')
    image = Fields.ImageProperty(verbose_name=u'圖片')
    is_enable = Fields.BooleanProperty(verbose_name=u'顯示於前台', default=True)

    @classmethod
    def all_enable(cls, category=None, *args, **kwargs):
        return cls.query(cls.is_enable==True).order(-cls.sort)

    @classmethod
    def insert(cls, name, title, content=u'', is_enable=True, image=u''):
        item = cls.get_by_name(name)
        if item is not None:
            return
        if content == u'':
            content = title
        item = cls()
        item.name = name
        item.title = title
        item.content = content
        item.is_enable = is_enable
        item.image = image
        item.put()
        return item
コード例 #3
0
ファイル: themes_model.py プロジェクト: argeweb/plugin-themes
class ThemesModel(BasicModel):
    theme_title = Fields.StringProperty(required=True, verbose_name=u'樣式名稱')
    theme_name = Fields.StringProperty(required=True, verbose_name=u'識別名稱')
    exclusive = Fields.StringProperty(verbose_name=u'專屬項目', default='all')
    is_enable = Fields.BooleanProperty(verbose_name=u'顯示於前台', default=True)
    author = Fields.StringProperty(verbose_name=u'作者')
    using = Fields.TextProperty(verbose_name=u'使用的欄位')
    thumbnail = Fields.StringProperty(verbose_name=u'縮圖位置')
    in_datastore = Fields.BooleanProperty(verbose_name=u'是否位於 DataStore', default=False)

    @classmethod
    def find_by_theme_name(cls, theme_name):
        return cls.query(cls.theme_name == theme_name).get()

    @classmethod
    def get_list(cls, identifier_name):
        return cls.query(
            cls.exclusive.IN([identifier_name, u'all'])
        ).order(-cls.sort, -cls._key)

    @classmethod
    def check_in_list(cls, identifier_name, theme_name):
        item = cls.query(
            ndb.AND(
                cls.exclusive.IN([identifier_name, u'all']),
                cls.theme_name == theme_name
            )
        ).order(-cls.sort, -cls._key).get()
        if item:
            return True
        else:
            return False
コード例 #4
0
class WarehouseModel(BasicModel):
    title = Fields.StringProperty(verbose_name=u'倉庫名稱')
    address = Fields.StringProperty(verbose_name=u'地址')
    telephone = Fields.StringProperty(verbose_name=u'電話')

    def stock_in(self, sku, quantity, history, detail_remark):
        from stock_keeping_unit_in_warehouse_model import StockKeepingUnitInWarehouseModel
        from ..models.stock_history_detail_model import create_history_detail
        create_history_detail(history, sku, detail_remark, quantity, self)
        return StockKeepingUnitInWarehouseModel.stock_in(self, sku, quantity)

    def stock_out(self,
                  sku,
                  quantity,
                  history,
                  detail_remark,
                  auto_fill=False):
        from stock_keeping_unit_in_warehouse_model import StockKeepingUnitInWarehouseModel
        from ..models.stock_history_detail_model import create_history_detail
        create_history_detail(history, sku, detail_remark, quantity, self)
        return StockKeepingUnitInWarehouseModel.stock_out(
            self, sku, quantity, auto_fill)

    def stock_out_check(self, sku, quantity, auto_fill=False):
        from stock_keeping_unit_in_warehouse_model import StockKeepingUnitInWarehouseModel
        return StockKeepingUnitInWarehouseModel.stock_out_check(
            self, sku, quantity, auto_fill)
コード例 #5
0
class StockHistoryDetailModel(BasicModel):
    class Meta:
        label_name = {
            'is_enable': u'啟用',
            'title': u'完整規格名稱',
        }

    history = Fields.KeyProperty(verbose_name=u'歷史記錄', kind=StockHistoryModel)
    product_name = Fields.StringProperty(verbose_name=u'產品名稱')
    product_image = Fields.StringProperty(verbose_name=u'產品圖片')
    sku_object = Fields.KeyProperty(verbose_name=u'SKU 對象')
    spec_full_name = Fields.SearchingHelperProperty(verbose_name=u'完整規格名稱', target='sku_object', target_field_name='spec_full_name')
    sku_full_name = Fields.SearchingHelperProperty(verbose_name=u'sku 編號', target='sku_object', target_field_name='sku_full_name')
    operation_type = Fields.StringProperty(verbose_name=u'操作類型')  # 出庫、入庫、轉倉
    warehouse = Fields.StringProperty(verbose_name=u'倉庫')
    warehouse_target = Fields.StringProperty(verbose_name=u'目標倉庫')
    quantity = Fields.IntegerProperty(verbose_name=u'數量')

    @classmethod
    def all_with_history(cls, history):
        return cls.query(cls.history == history.key).order(-cls.sort)

    @property
    def sku_instance(self):
        if not hasattr(self, '_sku'):
            self._sku = self.sku_object.get()
        return self._sku
コード例 #6
0
class UserShopPointProductModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    title = Fields.StringProperty(verbose_name=u'標題', default=u'50點')
    price = Fields.FloatProperty(verbose_name=u'價格', default=50.0)
    point = Fields.FloatProperty(verbose_name=u'獲得點數', default=50.0)
    is_enable = Fields.BooleanProperty(verbose_name=u'啟用', default=True)
    remark = Fields.TextProperty(verbose_name=u'說明', default=u'')
コード例 #7
0
class ConfigModel(BasicConfigModel):
    title = Fields.HiddenProperty(verbose_name=u'設定名稱',
                                  default=u'Line Bot 相關設定')
    channel_secret = Fields.StringProperty(verbose_name=u'channel_secret',
                                           default=u'')
    channel_access_token = Fields.StringProperty(
        verbose_name=u'channel_access_token', default=u'')
    unknown_message = Fields.StringProperty(verbose_name=u'無法判斷時', default=u'')
    onerror_message = Fields.StringProperty(verbose_name=u'發生錯誤時', default=u'')
コード例 #8
0
ファイル: config_model.py プロジェクト: argeweb/plugin-mail
class ConfigModel(BasicConfigModel):
    class Meta:
        tab_pages = [
            u'系統收件人',
            u'Google App Engine',
            u'MailGun',
            # u'SendGrid', u'other'
        ]

    title = Fields.HiddenProperty(verbose_name=u'設定名稱', default=u'郵件相關設定')
    use = Fields.IntegerProperty(verbose_name=u'服務類型', default=0)

    system_recipient_1 = Fields.StringProperty(verbose_name=u'系統收件人 1',
                                               tab_page=0,
                                               default=u'*****@*****.**')
    system_recipient_2 = Fields.StringProperty(verbose_name=u'系統收件人 2',
                                               tab_page=0,
                                               default=u'*****@*****.**')
    system_recipient_3 = Fields.StringProperty(verbose_name=u'系統收件人 3',
                                               tab_page=0,
                                               default=u'*****@*****.**')
    system_recipient_4 = Fields.StringProperty(verbose_name=u'系統收件人 4',
                                               tab_page=0,
                                               default=u'*****@*****.**')

    gae_sender_mail = Fields.StringProperty(verbose_name=u'寄件者 E-Mail',
                                            tab_page=1,
                                            default=u'*****@*****.**')
    gae_sender_name = Fields.StringProperty(verbose_name=u'寄件者名稱',
                                            tab_page=1,
                                            default=u'王小華')
    gae_helper = Fields.HtmlProperty(
        verbose_name=u'說明',
        tab_page=1,
        html=
        u'Google App Engine 每日可寄送 100 封(收件人),需至 <a href="https://console.cloud.google.com/appengine/settings?project" target="_blank">Google Cloud</a> 設定為 Email API 授權的寄件者。'
    )

    mg_sender_mail = Fields.StringProperty(verbose_name=u'寄件者 E-Mail',
                                           tab_page=2,
                                           default=u'*****@*****.**')
    mg_sender_name = Fields.StringProperty(verbose_name=u'寄件者名稱',
                                           tab_page=2,
                                           default=u'王小華')
    mg_domain = Fields.StringProperty(verbose_name=u'網域名稱',
                                      tab_page=2,
                                      default=u'domain.com')
    mg_api_key = Fields.StringProperty(verbose_name=u'Api Key',
                                       tab_page=2,
                                       default=u'key-as23XVCBDfg43sfgs')
    mg_helper = Fields.HtmlProperty(
        verbose_name=u'說明',
        tab_page=2,
        html=
        u'Mial Gun 每月可免費寄送 10,000 封信件,請至 <a href="https://www.mailgun.com/" target="_blank">Mial Gun</a> 申請相關 Api Key。'
    )
コード例 #9
0
class LineBotInputModel(BasicModel):
    next_step = Fields.StringProperty(verbose_name=u'下一步', default=u'')
    user_message = Fields.StringProperty(verbose_name=u'訊息暫存', default=u'')
    need_delete = Fields.BooleanProperty(verbose_name=u'需要刪除', default=False)

    @classmethod
    def get_or_create_by_name(cls, name, next_step):
        item = cls.get_by_name(name)
        if item is None:
            item = cls()
            item.name = name
            item.next_step = next_step
            item.put()
        return item
コード例 #10
0
class ConfigModel(BasicConfigModel):
    class Meta:
        tab_pages = [u'購物時折抵', u'購物時獲得', u'點數購買']

    title = Fields.HiddenProperty(verbose_name=u'設定名稱', default=u'購物金設定')
    max_use_point_for_order = Fields.RangeProperty(
        verbose_name=u'每筆訂單可折抵最大購物金',
        unit='%',
        default=5,
        step=0.1,
        multiple=True)
    discount_ratio = Fields.RangeProperty(verbose_name=u'貨幣折換比率',
                                          unit='%',
                                          default=100,
                                          step=0.1)
    is_must_use = Fields.BooleanProperty(verbose_name=u'強制使用', default=False)
    min_amount = Fields.FloatProperty(verbose_name=u'金額閥值', default=0.0)
    available_point = Fields.RangeProperty(verbose_name=u'每訂單可獲得的購物金',
                                           tab_page=1,
                                           unit='%',
                                           default=0.5,
                                           step=0.1)
    can_buy = Fields.BooleanProperty(verbose_name=u'是否可以直接購買點數',
                                     default=False,
                                     tab_page=2)
    give_time = Fields.StringProperty(verbose_name=u'發放時間',
                                      default=u'after_order_checkout',
                                      choices=[
                                          'after_order_checkout',
                                          'after_order_close',
                                      ],
                                      choices_text={
                                          'after_order_checkout': u'訂單建立後',
                                          'after_order_close': u'訂單完成後',
                                      })
コード例 #11
0
class UserShopPointHistoryModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    shop_point_target = Fields.KeyProperty(verbose_name=u'所屬單位',
                                           kind=UserShopPointModel)
    order_no = Fields.StringProperty(verbose_name=u'訂單編號', default=u'')
    order_amount = Fields.StringProperty(verbose_name=u'訂單金額', default=u'')
    decrease_point = Fields.FloatProperty(verbose_name=u'點數减少', default=0)
    increase_point = Fields.FloatProperty(verbose_name=u'點數增加', default=0)
    point = Fields.FloatProperty(verbose_name=u'剩餘點數', default=0)
    remark = Fields.TextProperty(verbose_name=u'說明', default=u'')

    @classmethod
    def all_enable(cls, target=None, *args, **kwargs):
        if target:
            return cls.query(
                cls.shop_point_target == target.key).order(-cls.sort)
        return cls.query().order(-cls.sort)
コード例 #12
0
class LineBotModel(BasicModel):
    title = Fields.TextProperty(verbose_name=u'檢查的字串', default=u'')
    py_code = Fields.TextProperty(verbose_name=u'PyCode', default=u'')
    source_type = Fields.StringProperty(verbose_name=u'要處理的訊息來源',
                                        default=u'user',
                                        choices=(
                                            u'user',
                                            u'group',
                                            u'room',
                                            u'input',
                                            u'all',
                                        ))
    message_type = Fields.StringProperty(verbose_name=u'要處理的訊息類型',
                                         default=u'text',
                                         choices=(
                                             u'text',
                                             u'image',
                                             u'video',
                                             u'audio',
                                             u'location',
                                             u'sticker',
                                             u'follow',
                                             u'unfollow',
                                             u'join',
                                             u'leave',
                                             u'postback',
                                         ))
    return_message_type = Fields.StringProperty(verbose_name=u'回傳的訊息類型',
                                                default=u'TextSendMessage',
                                                choices=(
                                                    u'TextSendMessage',
                                                    u'ImageSendMessage',
                                                    u'TemplateSendMessage',
                                                ))
    weights = Fields.FloatProperty(verbose_name=u'權重', default=0.0)

    @classmethod
    def get_or_create_by_name(cls, name):
        item = cls.get_by_name(name)
        if item is None:
            import time
            item = cls()
            item.name = name
            item.weights = time.time()
            item.put()
        return item
コード例 #13
0
class CurrencyModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    title = Fields.StringProperty(verbose_name=u'幣值名稱')
    short_name = Fields.StringProperty(verbose_name=u'簡短的名稱', default=u'')
    unit_name = Fields.StringProperty(verbose_name=u'單位名稱', default=u'元')
    exchange_rate = Fields.FloatProperty(verbose_name=u'匯率', default=1.0)
    is_enable = Fields.BooleanProperty(verbose_name=u'顯示於前台', default=True)
    is_main = Fields.BooleanProperty(verbose_name=u'是否為基準貨幣', default=False)

    @classmethod
    def all_enable(cls, category=None, *args, **kwargs):
        return cls.query(cls.is_enable == True).order(-cls.sort)

    @classmethod
    def get_or_create_main_currency(cls):
        main = cls.get_by_name('main')
        if main is None:
            main = cls()
            main.name = 'main'
            main.is_main = True
            main.title = '基準貨幣'
            main.short_name = u'Main'
            main.unit_name = u'元'
            main.is_enable = False
            main.exchange_rate = 1
            main.put()
        return main

    @classmethod
    def get_current_or_main_currency(cls, currency_name):
        current_currency = cls.get_by_name(currency_name)
        if current_currency is None:
            current_currency = CurrencyModel.get_or_create_main_currency()
        return current_currency

    @classmethod
    def get_current_or_main_currency_with_controller(cls, controller):
        use_currency_name = ''
        if 'use_currency' in controller.session:
            use_currency_name = controller.session['use_currency']
        if use_currency_name is '':
            use_currency_name = 'main'
        return cls.get_current_or_main_currency(use_currency_name)

    def calc(self, target, places=2):
        return exchange(self.exchange_rate, target, places)
コード例 #14
0
class MailRecordModel(BasicModel):
    title = Fields.StringProperty(verbose_name=u'標題', default=u'')
    send_to = Fields.StringProperty(verbose_name=u'發送對象', default=u'')
    cc = Fields.StringProperty(verbose_name=u'發送對象 cc', default=u'')
    content = Fields.RichTextProperty(verbose_name=u'信件內容', default=u'')
    send_date = Fields.DateTimeProperty(verbose_name=u'發送時間',
                                        auto_now_add=True)
    send_system = Fields.HiddenProperty(verbose_name=u'發送的系統', default=u'')

    @classmethod
    def replace_context(cls, name, title=None, content=None):
        record = cls.get_or_create_by_name(name)
        record.name = name
        if title:
            record.title = title
        if content:
            record.content = content
        record.put()
コード例 #15
0
class StockHistoryModel(BasicModel):
    user = Fields.KeyProperty(verbose_name=u'使用者', kind=ApplicationUserModel)
    user_name = Fields.StringProperty(verbose_name=u'使用者名稱')
    status = Fields.BooleanProperty(verbose_name=u'狀態')  # True 成功, False 失敗
    result = Fields.StringProperty(verbose_name=u'結果訊息')
    operation = Fields.StringProperty(verbose_name=u'操作類型')  # 產品出入庫、訂單出貨、日常調動
    remake = Fields.StringProperty(verbose_name=u'摘要')
    order = Fields.KeyProperty(verbose_name=u'所屬訂單', kind=OrderModel)
    temporary_key = Fields.StringProperty(verbose_name=u'訂單暫存序號')
    temporary_items = Fields.SidePanelProperty(
        verbose_name=u'相關項目',
        text=u'點擊此處查看 相關項目',
        auto_open=True,
        uri='admin:product_stock:stock:side_panel_for_order')

    @property
    def details(self):
        from stock_history_detail_model import StockHistoryDetailModel
        return StockHistoryDetailModel.all_with_history(self)
コード例 #16
0
ファイル: mail_model.py プロジェクト: argeweb/plugin-mail
class MailModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    title = Fields.StringProperty(verbose_name=u'樣版名稱')
    mail_title = Fields.StringProperty(verbose_name=u'信件標題')
    mail_content = Fields.RichTextProperty(verbose_name=u'信件內容')
    touch_event = Fields.StringProperty(verbose_name=u'觸發時機', default=u'after_user_signup', choices=[
        'after_user_signup',
        'after_order_checkout',
        'after_user_verified_email',
        'after_user_verified_mobile',
        'after_user_verified_both',
        'user_request_verified_email',
        'user_request_email_reset',
        'other',
    ], choices_text={
        'after_user_signup': u'使用者註冊後',
        'after_order_checkout': u'訂單建立後',
        'after_user_verified_email': u'使用者驗証信箱後',
        'after_user_verified_mobile': u'使用者驗証手機後',
        'after_user_verified_both': u'使用者驗証信箱、手機後',
        'user_request_verified_email': u'使用者請求驗証信箱',
        'user_request_email_reset': u'使用者請求重設密碼',
        'other': u'由其它程序處理',
    })
    is_enable = Fields.BooleanProperty(verbose_name=u'啟用觸發', default=True)
    send_to_admin = Fields.BooleanProperty(verbose_name=u'寄送給管理者', default=False)
    other_event = Fields.StringProperty(verbose_name=u'其它觸發時機名稱', default=u'')

    @classmethod
    def replace_context(cls, name, touch_event=None, title=None, mail_title=None, mail_content=None):
        record = cls.get_or_create_by_name(name)
        record.name = name
        if title:
            record.title = title
        if mail_title:
            record.mail_title = mail_title
        if mail_content:
            record.mail_content = mail_content
        if touch_event:
            record.touch_event = touch_event
        record.put()
コード例 #17
0
class ConfigModel(BasicConfigModel):
    class Meta:
        tab_pages = [u'後台設定', u'Manifest 相關設定']

    name = Fields.StringProperty(verbose_name=u'識別名稱')
    style = Fields.StringProperty(default='material',
                                  verbose_name=u'後台樣式',
                                  choices=('default', 'material'))

    start_url = Fields.StringProperty(verbose_name=u'manifest start_url',
                                      default='/admin#/admin/welcome',
                                      tab_page=1)
    display = Fields.StringProperty(verbose_name=u'manifest display',
                                    default='fullscreen',
                                    tab_page=1)
    background_color = Fields.StringProperty(
        verbose_name=u'manifest background_color',
        default='#1C5D87',
        tab_page=1)
    theme_color = Fields.StringProperty(verbose_name=u'manifest theme_color',
                                        default='#1C5D87',
                                        tab_page=1)
    icon_128 = Fields.ImageProperty(verbose_name=u'manifest icon_128',
                                    default='',
                                    tab_page=1)
    icon_256 = Fields.ImageProperty(verbose_name=u'manifest icon_256',
                                    default='',
                                    tab_page=1)
コード例 #18
0
ファイル: album_model.py プロジェクト: argeweb/plugin-album
class AlbumModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    title = Fields.StringProperty(verbose_name=u'相簿名稱')
    creator = Fields.ApplicationUserProperty(verbose_name=u'建立者')
    count = Fields.IntegerProperty(verbose_name=u'相片數量', default=0)

    @property
    def get_first_img(self):
        return '/plugins/album/static/empty-album.png'

    def insert_photo(self, ndb_item):
        from ..models.album_relation_model import AlbumRelationModel
        if ndb_item is None:
            return
        n = AlbumRelationModel()
        n.album = self.key
        n.file = ndb_item.key
        n.put()
        self.count += 1
        self.put()

    def all_photo(self):
        from ..models.album_relation_model import get_all_file_with_album
        return get_all_file_with_album(self.key)
コード例 #19
0
class UserShopPointModel(BasicModel):
    class Meta:
        label_name = {
            'modified': u'最後變動時間',
        }

    name = Fields.StringProperty(verbose_name=u'識別名稱')
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    user_name_proxy = Fields.StringProperty(verbose_name=u'使用者名稱')
    user_email_proxy = Fields.StringProperty(verbose_name=u'E-Mail')
    point = Fields.FloatProperty(verbose_name=u'現餘點數', default=0.0)
    used_point = Fields.FloatProperty(verbose_name=u'已使用點數', default=0.0)

    @classmethod
    def get_or_create(cls, user):
        r = cls.query(cls.user == user.key).get()
        if r is None:
            r = cls(user=user.key)
            r._user = user
            r.user_name_proxy = r._user.name
            r.user_email_proxy = r._user.email
            r.put()
        r.user_name_proxy = user.name
        r.user_email_proxy = user.email
        return r

    @classmethod
    def after_get(cls, key, item):
        super(UserShopPointModel, cls).after_get(key, item)
        item._user = item.user.get()
        if item._user:
            item.user_name_proxy = item._user.name
            item.user_email_proxy = item._user.email
        else:
            item.user_name_proxy = u'該帳號已被刪除'

    def increase_point(self,
                       point,
                       remark=u'',
                       order_no=u'',
                       order_amount=None):
        from user_shop_point_history_model import UserShopPointHistoryModel
        point = int(point)
        history = UserShopPointHistoryModel()
        history.shop_point_target = self.key
        history.remark = remark
        history.increase_point = point
        history.order_no = order_no
        if order_amount is not None:
            history.order_amount = str(order_amount)
        if self.point is None:
            self.point = 0.0
        history.point = self.point + point
        history.put()
        self.point += point

    def decrease_point(self, point, remark, order_no=u'', order_amount=None):
        from user_shop_point_history_model import UserShopPointHistoryModel
        point = point
        history = UserShopPointHistoryModel()
        history.shop_point_target = self.key
        history.remark = remark
        history.decrease_point = point
        history.order_no = order_no
        if order_amount is not None:
            history.order_amount = str(order_amount)
        if self.point is None:
            self.point = 0.0
        history.point = self.point - point
        history.put()
        self.point -= point
        self.used_point += point

    def get_max_usable_point(self, total):
        from ..models.config_model import ConfigModel
        config = ConfigModel.get_config()
        if total > config.min_amount:
            n = total * (config.max_use_point_for_order /
                         100.0) * (config.discount_ratio / 100.0) // 1.0
            if n > self.point:
                return self.point
            return n
        else:
            return 0.0
コード例 #20
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
コード例 #21
0
ファイル: config_model.py プロジェクト: argeweb/plugin-allpay
class ConfigModel(BasicConfigModel):
    class Meta:
        tab_pages = [u'串接參數', u'正式環境', u'測試環境']

    title = Fields.HiddenProperty(verbose_name=u'設定名稱', default=u'AllPay 相關設定')
    is_sandbox = Fields.BooleanProperty(verbose_name=u'使用測試伺服器', default=True)
    return_url = Fields.StringProperty(verbose_name=u'Return Url',
                                       tab_page=0,
                                       default=u'')
    client_back_url = Fields.StringProperty(verbose_name=u'Client Back Url',
                                            tab_page=0,
                                            default=u'')
    payment_info_url = Fields.StringProperty(verbose_name=u'Payment Info Url',
                                             tab_page=0,
                                             default=u'')

    formal_merchant_id = Fields.StringProperty(verbose_name=u'Merchant ID',
                                               tab_page=1,
                                               default=u'')
    formal_hash_key = Fields.StringProperty(verbose_name=u'Hash KEY',
                                            tab_page=1,
                                            default=u'')
    formal_hash_iv = Fields.StringProperty(verbose_name=u'Hash IV',
                                           tab_page=1,
                                           default=u'')
    formal_service_url = Fields.StringProperty(
        verbose_name=u'正式伺服器網址',
        tab_page=1,
        default=u'https://payment.allpay.com.tw/Cashier/AioCheckOut')

    sandbox_merchant_id = Fields.StringProperty(verbose_name=u'Merchant ID',
                                                tab_page=2,
                                                default=u'2000132')
    sandbox_hash_key = Fields.StringProperty(verbose_name=u'Hash KEY',
                                             tab_page=2,
                                             default=u'5294y06JbISpM5x9')
    sandbox_hash_iv = Fields.StringProperty(verbose_name=u'Hash IV',
                                            tab_page=2,
                                            default=u'v77hoKGq4kWxNNIS')
    sandbox_service_url = Fields.StringProperty(
        verbose_name=u'測試伺服器網址',
        tab_page=2,
        default=u'http://payment-stage.allpay.com.tw/Cashier/AioCheckOut')

    @property
    def merchant_id(self):
        if self.is_sandbox:
            return self.sandbox_merchant_id
        return self.formal_merchant_id

    @property
    def hash_key(self):
        if self.is_sandbox:
            return self.sandbox_hash_key
        return self.formal_hash_key

    @property
    def hash_iv(self):
        if self.is_sandbox:
            return self.sandbox_hash_iv
        return self.formal_hash_iv

    @property
    def service_url(self):
        if self.is_sandbox:
            return self.sandbox_service_url
        return self.formal_service_url
コード例 #22
0
class UserContactDataModel(BasicModel):
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者', is_lock=True)
    user_name_proxy = Fields.StringProperty(verbose_name=u'使用者名稱')
    user_email_proxy = Fields.StringProperty(verbose_name=u'E-Mail')
    user_avatar_proxy = Fields.ImageProperty(verbose_name=u'頭像')
    telephone = Fields.StringProperty(verbose_name=u'電話', default=u'')
    mobile = Fields.StringProperty(verbose_name=u'手機', default=u'')
    sex = Fields.StringProperty(verbose_name=u'性別', default=u'保密')
    address_country = Fields.StringProperty(verbose_name=u'國家', default=u'')
    address_city = Fields.StringProperty(verbose_name=u'縣市', default=u'')
    address_district = Fields.StringProperty(verbose_name=u'鄉鎮', default=u'')
    address_detail = Fields.StringProperty(verbose_name=u'地址', default=u'')
    address_zip = Fields.StringProperty(verbose_name=u'郵遞區號', default=u'')

    birthday_year = Fields.IntegerProperty(verbose_name=u'出生年', default=0)
    birthday_month = Fields.IntegerProperty(verbose_name=u'出生月', default=0)
    birthday_day = Fields.IntegerProperty(verbose_name=u'出生日', default=0)
    referrals = Fields.StringProperty(verbose_name=u'推薦人', default=u'')
    is_referrals_change = Fields.BooleanProperty(verbose_name=u'推薦人已修改', default=False)

    mobile_verification_code = Fields.HiddenProperty(verbose_name=u'手機驗証碼', default=u'')
    is_mobile_verified = Fields.BooleanProperty(verbose_name=u'手機是否已驗証', default=False)
    need_verification_mobile = Fields.HiddenProperty(verbose_name=u'需驗証的手機', default=u'')
    last_verified_mobile = Fields.HiddenProperty(verbose_name=u'最後驗証成功的手機', default=u'')

    email_verification_code = Fields.HiddenProperty(verbose_name=u'信箱驗証碼', default=u'')
    is_email_verified_proxy = Fields.BooleanProperty(verbose_name=u'信箱是否已驗証', default=False)
    need_verification_email = Fields.HiddenProperty(verbose_name=u'需驗証的信箱', default=u'')
    last_verified_email = Fields.HiddenProperty(verbose_name=u'最後驗証成功的信箱', default=u'')

    address_verification_code = Fields.HiddenProperty(verbose_name=u'地址驗証碼', default=u'')
    is_address_verified = Fields.BooleanProperty(verbose_name=u'地址是否已驗証', default=False)

    @classmethod
    def get_or_create(cls, user):
        r = cls.query(cls.user==user.key).get()
        if r is None:
            r = cls(user=user.key)
            r.user_name_proxy = user.name
            r.user_email_proxy = user.email
            r.user_avatar_proxy = user.avatar
            r.is_email_verified_proxy = user.is_email_verified
            r.put()
        r._user = user
        r.password = r._user.password
        r.old_password = r._user.password
        return r

    @property
    def user_instance(self):
        if not hasattr(self, '_user'):
            self._user = self.user.get()
        return self._user

    def update_user(self, user=None):
        if user is None:
            user = self.user_instance
        if user is None:
            return

        if hasattr(self, 'old_password') and self.old_password != self.password:
            user.password = self.password
            user.bycrypt_password()
            self.password = user.password
            self.old_password = user.password
        try:
            user.name = self.user_name_proxy
            user.email = self.user_email_proxy
            user.avatar = self.user_avatar_proxy
            user.is_email_verified = self.is_email_verified_proxy
        except:
            pass
        user.put()

    @property
    def user_name(self):
        if self.user_instance:
            return self.user_instance.name
        return u'該帳號已被刪除'

    @user_name.setter
    def user_name(self, value):
        self.user_name_proxy = value

    @property
    def email(self):
        if self.user_instance:
            return self.user_instance.email
        return u''

    @email.setter
    def email(self, value):
        self.user_email_proxy = value

    @property
    def avatar(self):
        if self.user_instance:
            return self.user_instance.avatar
        return u''

    @avatar.setter
    def avatar(self, value):
        self.user_avatar_proxy = value

    @property
    def is_email_verified(self):
        if self.user_instance:
            return self.user_instance.is_email_verified
        return False

    @is_email_verified.setter
    def is_email_verified(self, value):
        self.is_email_verified_proxy = value

    @classmethod
    def after_get(cls, key, item):
        if item.user_instance:
            item.user_name_proxy = item.user_instance.name
            item.user_email_proxy = item.user_instance.email
            item.user_avatar_proxy = item.user_instance.avatar
            item.is_email_verified_proxy = item.user_instance.is_email_verified
        else:
            item.user_name_proxy = u'該帳號已被刪除'

    def gen_email_verification_code(self, email):
        import random, string
        r = ''.join(random.choice(string.lowercase) for i in range(25))
        self.need_verification_email = email
        self.email_verification_code = u'%s-%s-%s-%s' % (r[0:4], r[5:9], r[10:14], r[15:19])

    def gen_mobile_verification_code(self, mobile):
        import random
        self.need_verification_mobile = mobile
        self.mobile_verification_code = u'%s' % (random.randint(100000, 999999))

    def verify_email(self, code):
        if self.email_verification_code == code:
            self.last_verified_email = self.need_verification_email
            self.is_email_verified_proxy = True
            self.user_email_proxy = self.last_verified_email
            self.user_instance.email = self.last_verified_email
            self.user_instance.is_email_verified = True
            self.user_instance.put()
            self.email_verification_code = ''
            self.put()
            return True
        return False

    def verify_mobile(self, code):
        if self.mobile_verification_code == code:
            self.last_verified_mobile = self.need_verification_mobile
            self.is_mobile_verified = True
            self.mobile_verification_code = ''
            self.put()
            return True
        return False

    @property
    def birthday(self):
        return '%d-%02d-%02d' % (self.birthday_year, self.birthday_month, self.birthday_day)
コード例 #23
0
class AlbumRelationModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    file = Fields.KeyProperty(verbose_name=u'檔案', kind=FileModel)
    album = Fields.KeyProperty(verbose_name=u'相簿', kind=AlbumModel)
コード例 #24
0
class ApplicationUserModel(UserModel):
    name = Fields.StringProperty(required=True, verbose_name=u'名稱')
    account = Fields.StringProperty(required=True, verbose_name=u'帳號')
    password = Fields.StringProperty(required=True, verbose_name=u'密碼')
    email = Fields.StringProperty(verbose_name=u'E-Mail', default=u'')
    is_email_verified = Fields.BooleanProperty(verbose_name=u'信箱是否已驗証', default=False)
    avatar = Fields.ImageProperty(verbose_name=u'頭像')
    is_enable = Fields.BooleanProperty(verbose_name=u'啟用', default=True)
    rest_password_token = Fields.StringProperty(verbose_name=u'重設密碼令牌', default=u'')
    need_check_old_password = Fields.BooleanProperty(verbose_name=u'可設定新密碼', default=True)
    role = Fields.HiddenProperty(verbose_name=u'角色', default=u'user')
    provider = Fields.HiddenProperty(verbose_name=u'provider', default=u'website')
    federated_id = Fields.HiddenProperty(verbose_name=u'federated id', default=u'')

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

    @classmethod
    def get_user(cls, account, password, is_enable=True):
        a = cls.query(
            cls.account == account,
            cls.is_enable == is_enable).get()
        if a is None:
            return None
        if bcrypt.hashpw(password, a.password) != a.password:
            return None
        return a

    @classmethod
    def get_user_by_account(cls, account, check_is_enable=False):
        if check_is_enable:
            return cls.query(cls.account == account, cls.is_enable==True).get()
        return cls.query(cls.account == account).get()

    @classmethod
    def get_user_by_email(cls, email, check_is_enable=False):
        if check_is_enable:
            return cls.query(cls.email == email, cls.is_enable==True).get()
        return cls.query(cls.email == email).get()

    @classmethod
    def get_user_by_rest_password_token(cls, token, check_is_enable=True):
        if check_is_enable:
            return cls.query(cls.rest_password_token == token, cls.is_enable==True).get()
        return cls.query(cls.rest_password_token == token).get()

    @classmethod
    def get_user_by_email_and_password(cls, email, password, check_is_enable=True):
        a = cls.get_user_by_email(email, check_is_enable)
        if a is None:
            return None
        if bcrypt.hashpw(password, a.password) != a.password:
            return None
        return a

    def check_password(self, check):
        if bcrypt.hashpw(check, self.password) != self.password:
            return False
        return True

    @classmethod
    def create_account(cls, name, account, password, avatar=None, email=None):
        n = cls()
        n.name = name
        n.account = account
        n.password = bcrypt.hashpw(password, bcrypt.gensalt())
        n.avatar = avatar
        if email:
            n.email = email
        n.put()
        return n

    @classmethod
    def create_account_by_email(cls, email, password, role=None, avatar=None, account=None, user_name=None):
        if account is None:
            account = str(email).split('@')[0]
        if role is None:
            role = RoleModel.find_lowest_level()
        if user_name is None:
            user_name = account
        user = cls.create_account(user_name, account, password, '/plugins/backend_ui_material/static/images/users/avatar-001.jpg', email)
        from ..models.user_role_model import UserRoleModel
        UserRoleModel.set_role(user, role)
        return user

    @classmethod
    def get_list(cls):
        return cls.query(cls.account != 'super_user').order(cls.account, -cls.sort, -cls._key)

    def bycrypt_password_with_old_password(self):
        if self.old_password != self.new_password:
            self.password = u'' + bcrypt.hashpw(u'' + self.new_password, bcrypt.gensalt())
            self.put()

    def bycrypt_password(self):
        self.password = u'' + bcrypt.hashpw(u'' + self.password, bcrypt.gensalt())
        self.put()

    def before_put(self):
        n = []
        try:
            for r in self.roles:
                n.append(r.role_name)
            self.role = ','.join(n)
        except (BadValueError, AttributeError):
            self.role = ''

    @property
    def roles(self):
        if not hasattr(self, '_roles'):
            from user_role_model import UserRoleModel
            self._roles = UserRoleModel.get_user_roles(self).fetch()
        return self._roles

    @property
    def role_list(self):
        roles = []
        for r in self.roles:
            roles.append(r.role.get().name)
        return roles

    def get_role_level(self, highest=True):
        if not hasattr(self, '_level'):
            level = 0
            for r in self.roles:
                r_level = r.role.get().level
                if r_level > level:
                    level = r_level
            setattr(self, '_level', level)
        else:
            level = getattr(self, '_level')
        return level

    def has_role(self, role):
        from user_role_model import UserRoleModel
        return UserRoleModel.has_role(self, role)

    def set_role(self, role):
        from user_role_model import UserRoleModel
        return UserRoleModel.set_role(self, role)

    def remove_role(self, role):
        from user_role_model import UserRoleModel
        return UserRoleModel.remove_role(self, role)

    def check_and_get_role(self, role):
        from user_role_model import UserRoleModel
        role = UserRoleModel.get_role(role)
        if len(self.roles) > 0:
            for item in self.roles:
                if item.key == role.key:
                    return role
            return None
        else:
            if UserRoleModel.has_role(self, role):
                return role
            return None

    def has_permission(self, action_full_name, strict=False):
        if len(self.roles) == 0:
            return False
        not_in_count = 0
        if not hasattr(self, '_roles_object'):
            self._roles_object = []
            for item in self.roles:
                r = item.role.get()
                if r:
                    self._roles_object.append(r)
        for item in self._roles_object:
            if action_full_name not in item.prohibited_actions:
                not_in_count += 1
                if strict is False:
                    break
        if strict:
            return (not_in_count > 0) and (len(self.roles) == not_in_count)
        return not_in_count > 0

    def gen_password_token(self):
        from argeweb.core.random_util import gen_random_code
        self.rest_password_token = gen_random_code()

    @classmethod
    def after_delete(cls, key):
        from user_role_model import UserRoleModel
        from google.appengine.ext import ndb
        keys = []
        for i in UserRoleModel.query(UserRoleModel.user == key).fetch():
            keys.append(i.key)
        ndb.delete_multi(keys)

    @classmethod
    def all_count(cls, *args, **kwargs):
        """ 回傳目前的總使用者人數
        :return: 人數
        """
        return cls.query().count(keys_only=True)

    @classmethod
    def all_count_with_date(cls, date=None, *args, **kwargs):
        """ 回傳特定日期加入的使用者人數
        :return: 人數
        """
        from datetime import timedelta
        if date is None:
            from datetime import datetime
            date = datetime.today()
        date_start = date + timedelta(days=-1)
        date_end = date + timedelta(days=+1)
        return cls.query(cls.created > date_start, cls.created < date_end).count(keys_only=True)
コード例 #25
0
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
コード例 #26
0
class StockKeepingUnitModel(BasicModel):
    class Meta:
        label_name = {
            'is_enable': u'啟用',
            'title': u'完整規格名稱',
            'sku_full_name': u'sku 完整編號'
        }

    name = Fields.StringProperty(verbose_name=u'識別名稱')
    product_no = Fields.StringProperty(verbose_name=u'產品編號')
    sku_no = Fields.StringProperty(verbose_name=u'sku 編號')
    spec_full_name = Fields.StringProperty(verbose_name=u'完整規格名稱')
    image = Fields.ImageProperty(verbose_name=u'圖片')
    use_price = Fields.BooleanProperty(verbose_name=u'使用獨立銷售價格', default=False)
    price = Fields.FloatProperty(verbose_name=u'獨立銷售價格', default=-1)
    use_cost = Fields.BooleanProperty(verbose_name=u'使用成本', default=False)
    cost = Fields.FloatProperty(verbose_name=u'成本', default=0.0)
    quantity = Fields.IntegerProperty(verbose_name=u'現存數量', default=0)
    estimate = Fields.IntegerProperty(verbose_name=u'預估數量', default=0)
    in_order_quantity = Fields.IntegerProperty(verbose_name=u'在訂單中的數量',
                                               default=0)
    pre_order_quantity = Fields.IntegerProperty(verbose_name=u'在預購中的數量',
                                                default=0)
    low_stock_quantity = Fields.IntegerProperty(verbose_name=u'庫存警戒線',
                                                default=-1)
    last_in_quantity = Fields.IntegerProperty(verbose_name=u'最後入庫數量',
                                              default=0)
    last_in_datetime = Fields.DateTimeProperty(verbose_name=u'最後入庫時間',
                                               auto_now_add=True)
    last_out_quantity = Fields.IntegerProperty(verbose_name=u'最後出庫數量',
                                               default=0)
    last_out_datetime = Fields.DateTimeProperty(verbose_name=u'最後入庫時間',
                                                auto_now_add=True)

    is_enable = Fields.BooleanProperty(verbose_name=u'顯示於前台', default=True)
    can_be_purchased = Fields.BooleanProperty(verbose_name=u'可購買',
                                              default=True)

    use_automatic_increment = Fields.BooleanProperty(verbose_name=u'自動增量',
                                                     default=False)
    automatic_increment_quantity = Fields.IntegerProperty(
        verbose_name=u'增量的數量', default=0)
    product = Fields.SearchingHelperProperty(verbose_name=u'所屬產品',
                                             target='product_object',
                                             target_field_name='title')
    product_object = Fields.KeyProperty(verbose_name=u'所屬產品',
                                        kind=ProductModel)
    spec_name_1 = Fields.HiddenProperty(verbose_name=u'規格名稱 1')
    spec_name_2 = Fields.HiddenProperty(verbose_name=u'規格名稱 2')
    spec_name_3 = Fields.HiddenProperty(verbose_name=u'規格名稱 3')
    spec_name_4 = Fields.HiddenProperty(verbose_name=u'規格名稱 4')
    spec_name_5 = Fields.HiddenProperty(verbose_name=u'規格名稱 5')
    spec_value_1 = Fields.HiddenProperty(verbose_name=u'規格值 1')
    spec_value_2 = Fields.HiddenProperty(verbose_name=u'規格值 2')
    spec_value_3 = Fields.HiddenProperty(verbose_name=u'規格值 3')
    spec_value_4 = Fields.HiddenProperty(verbose_name=u'規格值 4')
    spec_value_5 = Fields.HiddenProperty(verbose_name=u'規格值 5')

    @property
    def sku_full_name(self):
        product_no = u''
        if self.product_no is not u'' and self.product_no is not None:
            product_no = '%s' % self.product_no
        sku_post_name = u''
        if self.name is not u'' and self.name is not None:
            sku_post_name = self.name
        if self.sku_no is not u'' and self.sku_no is not None:
            sku_post_name = self.sku_no
        if product_no is not u'' and sku_post_name is not u'':
            return '%s-%s' % (product_no, sku_post_name)
        return '%s%s' % (product_no, sku_post_name)

    def before_put(self):
        super(StockKeepingUnitModel, self).before_put()
        product_no = u''
        cat = self.product_object
        if cat is not None:
            try:
                cat = cat.get()
                product_no = cat.product_no
            except:
                pass
        spec_list = (u'%s' % self.spec_full_name).split(u',')
        i = 0
        setattr(self, 'product_no', product_no)
        for index in range(0, len(spec_list)):
            spec = spec_list[index].split(u':')
            setattr(self, 'spec_name_%s' % (index + 1), spec[0])
            setattr(self, 'spec_value_%s' % (index + 1), spec[1])

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

    @property
    def quantity_percent(self):
        quantity = self.quantity if self.quantity is not None else 0
        last_in_quantity = self.last_in_quantity if self.last_in_quantity is not None else 0
        if last_in_quantity == 0:
            return 0
        if last_in_quantity < self.low_stock_quantity:
            last_in_quantity = self.low_stock_quantity
        return int((float(quantity) / float(last_in_quantity)) * 10000) / 100.0

    @property
    def is_low_stock_level(self):
        quantity = self.quantity if self.quantity is not None else 0
        low_stock_quantity = self.low_stock_quantity if self.low_stock_quantity is not None else -1
        return quantity <= low_stock_quantity

    @classmethod
    def all_enable(cls, product=None, *args, **kwargs):
        cat = None
        if product:
            cat = ProductModel.get_by_name(product)
        if cat is None:
            return cls.query(cls.is_enable == True).order(-cls.sort)
        else:
            return cls.query(cls.product_object == cat.key,
                             cls.is_enable == True).order(-cls.sort)

    @classmethod
    def find_by_product(cls, product):
        return cls.query(cls.product_object == product.key).order(
            cls.spec_full_name)

    def change_estimate_quantity(self, sub_quantity=0, add_quantity=0):
        self.estimate = self.estimate - abs(sub_quantity) + abs(add_quantity)
        if self.estimate < 0:
            self.estimate = 0

    def change_pre_order_quantity(self, sub_quantity=0, add_quantity=0):
        self.pre_order_quantity = self.pre_order_quantity - abs(
            sub_quantity) + abs(add_quantity)
        if self.pre_order_quantity < 0:
            self.pre_order_quantity = 0

    def change_in_order_quantity(self, sub_quantity=0, add_quantity=0):
        self.in_order_quantity = self.in_order_quantity - abs(
            sub_quantity) + abs(add_quantity)
        if self.in_order_quantity < 0:
            self.in_order_quantity = 0

    @property
    def quantity_can_be_used(self):
        n = self.quantity - self.in_order_quantity - self.estimate
        if n < 0:
            return 0
        return n
コード例 #27
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()