2024年12月25日 星期三

採購、訂單 交貨時間/Purchase lead times

每個商品的採購頁籤中可設定多個供應商,每個供應商的供貨價格及交貨時間,如下:


也可設定對客戶訂單的前置時間:

如此在 "報價單" 中便可自動推算廠商到貨時間:


及對客戶的訂單交貨時間:


2024年12月23日 星期一

Dropshipping

賣家不囤貨、不經手商品物流,只當中間人賺取差價。

每當客人下單,賣家就把訂單和發貨細節轉交批發商,直接發送給客戶。

啟用 Dropshipping

設定 Dropshipping 產品

可有多個供應商,清單順序在前面的優先供貨。





2022年5月18日 星期三

CKAN Route(2.9): add_ckan_admin_tab

https://github.com/ckan/ckan/blob/2.9/ckanext/example_iconfigurer/plugin.py

參考 CKAN Extensions Tutorial(v2.9):一個空的 CKAN extension,建立 ckanext-example_iconfigurer 擴充套件。

建立:ckanext-example_iconfigurer  

  1. 進入Python Virtual Environment:
    . /usr/lib/ckan/default/bin/activate
  2. 切換目錄
    cd /usr/lib/ckan/default/src 
  3. 執行 ckan generate extension,輸入:ckanext-example_iconfigurer

撰寫 plugin 類別:ExampleIConfigurerPlugin

修改 ckanext-example_iconfigurer/ckanext/example_iconfigurer/plugin.py。參考完整程式,主要內容如下:

略...
import ckanext.example_iconfigurer.blueprint as blueprint

class ExampleIConfigurerPlugin(plugins.SingletonPlugin):
    略...

    plugins.implements(plugins.IConfigurer)
    plugins.implements(plugins.IBlueprint)

    # IConfigurer

    def update_config(self, config):
        # Add extension templates directory

        toolkit.add_template_directory(config, u'templates')
        # Add a new ckan-admin tabs for our extension
        toolkit.add_ckan_admin_tab(
            config, u'example_iconfigurer.config_one',
            u'My First Custom Config Tab'
        )
        toolkit.add_ckan_admin_tab(
            config, u'example_iconfigurer.config_two',
            u'My Second Custom Config Tab'
        )

撰寫 blueprint.py

參考完整程式,主要內容如下:

# encoding: utf-8

import ckan.lib.base as base
import ckan.lib.helpers as helpers
from flask import Blueprint
render = base.render

example_iconfigurer = Blueprint(u'example_iconfigurer', __name__)


def config_one():
    u'''Render the config template with the first custom title.'''

    return render(
        u'admin/myext_config.html',
        extra_vars={u'title': u'Custom Config Page A'}
    )


def config_two():
    u'''Render the config template with the second custom title.'''
    return render(
        u'admin/myext_config.html',
        extra_vars={u'title': u'Custom Config Page B'}
    )


def build_extra_admin_nav():
    u'''Return results of helpers.build_extra_admin_nav for testing.'''
    return helpers.build_extra_admin_nav()


example_iconfigurer.add_url_rule(
    u'/ckan-admin/myext_config_one', view_func=config_one
)
example_iconfigurer.add_url_rule(
    u'/ckan-admin/myext_config_two', view_func=config_two
)
example_iconfigurer.add_url_rule(
    u'/build_extra_admin_nav', view_func=build_extra_admin_nav
)

修改 setup.py:設定 entry_points

修改 ckanext-example_iconfigurer/setup.py 的 entry_points:

entry_points='''
        [ckan.plugins] 
        example_iconfigurer=ckanext.example_iconfigurer.plugin:ExampleIConfigurerPlugin

修改 ckan.ini:啟用 plugin

修改 /etc/ckan/default/ckan.ini。CKAN 的 extension plugins 必須加到 CKAN 設定檔的 ckan.plugins 中,CKAN 才會呼叫。

ckan.plugins = stats text_view 略... example_iconfigurer

安裝

  1. 進入Python Virtual Environment: 
    . /usr/lib/ckan/default/bin/activate
  2. 切換目錄:
    cd /usr/lib/ckan/default/src/example_iconfigurer
  3. 安裝 Plugin: 
    python setup.py develop
  4. 重啟 CKAN 服務:
    sudo supervisorctl restart ckan-uwsgi:*

測試

瀏覽 http://CKAN web site]/ckan-admin/ 可看到兩個新增的管理頁籤。




2022年5月17日 星期二

CKAN Route(2.9): Flask IBlueprint

參考 CKAN Extensions Tutorial(v2.9):一個空的 CKAN extension,建立 ckanext-example_flask_iblueprint 擴充套件。

建立:ckanext-example_flask_iblueprint  

  1. 進入Python Virtual Environment:
    . /usr/lib/ckan/default/bin/activate
  2. 切換目錄
    cd /usr/lib/ckan/default/src 
  3. 執行 ckan generate extension,輸入:ckanext-example_flask_iblueprint

撰寫 plugin 類別:ExampleFlaskIBlueprintPlugin

修改 ckanext-example_flask_iblueprint/ckanext/example_flask_iblueprint/plugin.py。參考完整程式,主要內容如下:

class ExampleFlaskIBlueprintPlugin(p.SingletonPlugin):
    u'''
    An example IBlueprint plugin to demonstrate Flask routing from an
    extension.
    '''
    p.implements(p.IBlueprint)
    p.implements(p.IConfigurer)

    # IConfigurer

    def update_config(self, config):
        # Add extension templates directory
        p.toolkit.add_template_directory(config, u'templates')

    def get_blueprint(self):
        u'''Return a Flask Blueprint object to be registered by the app.'''

        # Create Blueprint for plugin
        blueprint = Blueprint(self.name, self.__module__)
        blueprint.template_folder = u'templates'
        # Add plugin url rules to Blueprint object
        rules = [
            (u'/hello_plugin', u'hello_plugin', hello_plugin),
            (u'/', u'home', override_flask_home),
            (u'/helper_not_here', u'helper_not_here', helper_not_here),
            (u'/helper', u'helper_here', helper_here),
            (u'/flask_request', u'flask_request', flask_request),
        ]
        for rule in rules:
            blueprint.add_url_rule(*rule)

        return blueprint

修改 setup.py:設定 entry_points

修改 ckanext-example_flask_iblueprint/setup.py 的 entry_points:

entry_points='''
        [ckan.plugins] 
        example_flask_iblueprint=ckanext.example_flask_iblueprint.plugin:ExampleFlaskIBlueprintPlugin

修改 ckan.ini:啟用 plugin

修改 /etc/ckan/default/ckan.ini。CKAN 的 extension plugins 必須加到 CKAN 設定檔的 ckan.plugins 中,CKAN 才會呼叫。

ckan.plugins = stats text_view 略... example_flask_iblueprint

安裝

  1. 進入Python Virtual Environment: 
    . /usr/lib/ckan/default/bin/activate
  2. 切換目錄:
    cd /usr/lib/ckan/default/src/example_flask_iblueprint
  3. 安裝 Plugin: 
    python setup.py develop
  4. 重啟 CKAN 服務:
    sudo supervisorctl restart ckan-uwsgi:*

測試

瀏覽 http://[CKAN web site] 下的 /, /hello_plugin, /helper, /helper_not_here, /flask_request 可看到對應的程式內容。

2022年5月12日 星期四

CKAN JavaScript Tutorial 2(v2.9): Webassets

http://docs.ckan.org/en/2.9/theming/webassets.html

CSS 檔等靜態檔案有兩種方式加入:簡單的 extra_public_paths 作法或是 Webassets。但 JavaScript module 就只能透過 Webassets。

Webasset 的好處是在 production 版中會自動最小化檔案、快取並打包/bundling,以減少下載時間,載入指定相依檔⋯⋯。

CKAN 只有 *.js、*.css 會以 Webasset 資源處理,其它的靜態檔(圖檔、PDF)要透過 extra_public_paths 方式處理。

建立: ckanext-example_theme

延續 CKAN Theming Tutorial 1(v2.9): 靜態檔案(圖片與CSS) 往下做。

建立 assets 目錄

把 example_theme.css 改放到 assets 目錄下:

ckanext-example_theme/
  ckanext/
    example_theme/
      public/
        promoted-image.jpg
      assets/
        example_theme.css
        webassets.yml

另外再加一個 webassets.yml ,內容如下:

example_theme:
  output: example_theme/example_theme.css
  contents:
    - example_theme.css

修改 plugin.py

編輯 ckanext-example_theme/ckanext/example_theme/plugin.py ,在 update_config() 中呼叫 add_resource() 向 CKAN 註冊 assets 目錄,如下:

# encoding: utf-8

import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit

def most_popular_groups():
    略⋯⋯

class ExampleThemePlugin(plugins.SingletonPlugin):
    略⋯⋯

    def update_config(self, config):
        略⋯⋯

        # Register this plugin's assets directory with CKAN.
        # Here, 'assets' is the path to the webassets directory
        # (relative to this plugin.py file), and 'example_theme' is the name
        # that we'll use to refer to this assets directory from CKAN
        # templates.
        toolkit.add_resource('assets', 'example_theme')
  • toolkit.add_resource 的兩個參數:
    • assets: webassets 所在目錄(相對於plugin.py的路徑)
    • example_theme: 在 CKAN template 中存取此 assets 目錄的名稱

在 templates 中使用 {% asset %}

編輯 ckanext-example_theme/ckanext/example_theme/templates/base.html,在其中以 Jinja2 的{% asset %} 取代<link>  匯入檔案,如下:

{% ckan_extends %}

{% block styles %}
  {{ super() }}

  {# Import example_theme.css using Webassets.  'example_theme/' is
    the name that the example_theme/fanstatic directory was registered
    with when the toolkit.add_resource() function was called.
    'example_theme' is the name to the Webassets bundle file,
    registered inside webassets.yml file. #}
  {% asset 'example_theme/example_theme' %}

{% endblock %}

所有 template 都可用 {% asset %},Webassets 會加入需要的 <style> 、 <script>  來 include CSS 及JavaScript檔案,但最好把他們集中在 Jinja2 的  styles、scripts block.

Assets 不會在 {% asset %} 出現那行被 include。

用一個設定檔設定 Webassets 如何處理每個 asset 檔(是否打包/bundle,include的順序,include 檔要放在網頁的最前面還是最後面,檔案間的相依性...),參考:Assets

安裝

  1. 進入Python Virtual Environment: 
    . /usr/lib/ckan/default/bin/activate
  2. 切換目錄:
    cd /usr/lib/ckan/default/src/ckanext-example_theme
  3. 安裝 Plugin: 
    python setup.py develop
  4. 重啟 CKAN 服務:
    (production版) sudo supervisorctl restart ckan-uwsgi:*
    (develop版) ckan -c /etc/ckan/default/ckan.ini run

測試

檢視 http://[CKAN Website IP] 的網頁原始碼,在HTML的 <head>...</head> 可發現:

<link href="/webassets/webassets-external/2dce0ddda2882168f0c12c639a912e24_example_theme.css" rel="stylesheet"/>

2022年5月8日 星期日

CAKN 偵錯: flask_debugtoolbar

  1. 啟動 Python 虛擬環境
    . /usr/lib/ckan/default/bin/activate
  2. 安裝 flask_debugtoolbar
    pip install flask_debugtoolbar
  3. 開啟偵錯模式
    vi /etc/ckan/default/ckan.ini
    debug = true
  4. 重啟 CKAN
    sudo supervisorctl restart ckan-uwsgi:*
  • 若有錯檢視 uwsgi.ERR
    cat /etc/ckan/default/uwsgi.ERR


2022年5月6日 星期五

CKAN Templates Tutorial 9(v2.9): 存取自訂的 config 設定

http://docs.ckan.org/en/2.9/theming/templates.html#accessing-custom-config-settings-from-templates

template 裡的 app_globals 不是所有 CKAN config 設定都能存取,自訂的 config 設定無法取得,但透過 helper function 就可以。

參考:Using custom config settings in extensions

延續 上個 CKAN templates CSS tutorial

新增自訂 config 設定

如下 show_most_popular_groups 設定,決定首頁是否顯示最受歡迎群組。

修改 extension 根目錄下的 plugin.py,新增 helper function 存取自訂的 show_most_popular_groups 設定:

# encoding: utf-8


import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit
from ckan.common import config


def show_most_popular_groups():
    '''Return the value of the most_popular_groups config setting.

    To enable showing the most popular groups, add this line to the
    [app:main] section of your CKAN config file::

      ckan.example_theme.show_most_popular_groups = True

    Returns ``False`` by default, if the setting is not in the config file.

    :rtype: bool

    '''
    value = config.get('ckan.example_theme.show_most_popular_groups', False)
    value = toolkit.asbool(value)
    return value

略⋯⋯

class ExampleThemePlugin(plugins.SingletonPlugin):
    略⋯⋯

    def get_helpers(self):
        '''Register the most_popular_groups() function above as a template
        helper function.

        '''
        # Template helper function names should begin with the name of the
        # extension they belong to, to avoid clashing with functions from
        # other extensions.
        return {'example_theme_most_popular_groups': most_popular_groups,
                'example_theme_show_most_popular_groups':
                show_most_popular_groups,
                }

extension 加入的 config 設定名稱要以 extension 名稱開頭,以避免與其他 extension 或 CKAN 內建設定衝突(參考 Avoid name clashes)。

在 layout1.html 中呼叫自訂 helper function

修改 templates/home/layout1.html 如下:

{% ckan_extends %}

略⋯⋯

{# Show the most popular groups if the show_most_popular_groups config setting
   is True, otherwise call the super block. #}
{% block featured_organization %}
<p>example_theme_show_most_popular_groups: [{{h.example_theme_show_most_popular_groups()}}]</p>
  {% if h.example_theme_show_most_popular_groups() %}
    {% snippet 'snippets/example_theme_most_popular_groups.html' %}
  {% else %}
    {{ super() }}
  {% endif %}
{% endblock %}

修改 ckan.ini 設定

/etc/ckan/default/ckan.ini

[app:main]
## example_theme
ckan.example_theme.show_most_popular_groups = False

安裝

  1. 進入Python Virtual Environment: 
    . /usr/lib/ckan/default/bin/activate
  2. 切換目錄:
    cd /usr/lib/ckan/default/src/ckanext-example_theme
  3. 安裝 Plugin: 
    python setup.py develop
  4. 重啟 CKAN 服務:
    (production版) sudo supervisorctl restart ckan-uwsgi:*
    (develop版) ckan -c /etc/ckan/default/ckan.ini run