POS & 庫存管理系統

一個全面的銷售點(POS)與庫存管理系統,支持暗黑模式/亮色模式及英語/中文語系。前端使用 Nuxt3 結合 TailwindCSS、Element-Plus 和 Tabulator-table 構建,後端採用 Python Django REST 框架配合 Maria DB 和 Django ORM。確保資料庫交易遵循 ACID 屬性。

功能

  • 暗黑模式 / 亮色模式:用戶可切換暗黑和亮色主題,以提升使用體驗。
  • 英語 / 中文語系:支持多種語言,包括英語和繁體中文。
  • 庫存與銷售摘要圖表和表格:以視覺化和表格形式展示庫存和銷售數據摘要。
  • 產品欄目無限拓展:使用 JSON 來保存和處理產品數據,根據不同的客戶端提供靈活的列結構。
  • POS 功能
    • 創建發票:生成銷售交易的發票。
    • 寄售管理:管理寄售庫存。
    • 發票退款:處理發票的退款。
    • 發票列表:查看和管理所有發票。
    • 展示設置頁面:配置展示設置。
    • 發票 PDF 打印:以 PDF 格式打印發票。
  • 庫存管理
    • 進貨 / 出貨 / 轉移 / 折舊操作:高效管理庫存動態。
    • 帶歷史記錄的庫存表格:跟蹤庫存隨時間的變化。
    • 使用 Django 批量導入的 Excel 匯入:利用 Django 的批量導入功能快速上傳大量數據。
    • 多圖像支持的產品表格:管理具有多張圖片的產品。
    • 詳細表格(位置、分類、材質、顏色等):使用附加細節組織庫存。
    • 盤點頁面和盤點後調整:執行庫存盤點並相應調整庫存。
  • 系統設置
    • 用戶帳戶管理:管理用戶帳戶和角色。
    • 權限設置:定義權限,如限制某些用戶訪問銷售報告和查看成本。
    • 系統日誌:維護系統活動日誌。
  • 標籤打印支持:整合第三方工具如 QZ-Tray,使用 ZPL 直接從網頁界面選擇產品並點擊按鈕打印標籤。

技術

  • 前端:Nuxt3、TailwindCSS、Element-Plus、Tabulator-table
  • 後端:Python Django REST 框架、Maria DB、Django ORM
  • 資料庫:使用 Django ORM 的 Maria DB,確保 ACID 合規性
  • 標籤打印:使用 QZ-Tray 直接打印 ZPL 標籤

開發見解

  • 專案框架決策:最初考慮使用 Nitro(Nuxt3 的默認伺服器端伺服器),但基於先前專案經驗決定不使用。之前使用 Nitro 搭配 Prisma 時,由於 Prisma 無法進行多表聯接,難以滿足銷售摘要和庫存日誌的需求。最後選擇 Django ORM,因其提供優秀的多表聯接和交易處理能力。

    • 解決方案:選擇 Django ORM 因其能更有效地處理複雜的資料庫關係和交易。
  • 靈活欄位處理:不同的行業可能會在產品庫存中使用不同的欄位。例如,珠寶行業的庫存可能包含 CTSkarat,而時尚行業可能包括 sizecolormaterial。類似地,電子行業可能會有 warranty_periodvoltagebrand 等欄位。為了避免每次遷移數據庫結構的麻煩,我設計了使用 JSON 來存儲數據,同時仍然需要適配關係型數據庫。首先,我會提取所有必需的欄位以及一個可為空的 JSON 欄位作為產品主表。接著,我會創建一個新表,用於存儲額外欄位的名稱、類型、是否可為空等信息。然後,我會使用序列化工具從產品主表中提取 JSON 欄位,並根據額外欄位表的數據將其轉換為結構化的 JSON 格式。

class ProductMain(models.Model):
    # ...
    extraData = models.JSONField(null=True, blank=True)

class ProductExtraDetails(models.Model):
    field_name = models.CharField(max_length=255, unique=True)
    field_label = models.CharField(max_length=255)
    field_type = models.CharField(max_length=255)  # Type : string , int, float, date
    field_required = models.BooleanField(default=False)

    class Meta:
        db_table = "product_extra_details"
class ProductListSerializer(serializers.Serializer):
    # ...
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        extra_fields = ProductExtraDetails.objects.all()

        field_type_mapping = {
            'char': serializers.CharField,
            'float': serializers.FloatField,
            'integer': serializers.IntegerField,
            'boolean': serializers.BooleanField,
        }

        # Dynamically add the extra fields to the serializer
        for extra_field in extra_fields:
            field_class = field_type_mapping.get(
                extra_field.field_type, serializers.CharField)
            field_kwargs = {
                'required': False,
                'allow_null': True,
                'allow_blank': True if extra_field.field_type == 'char' else None,
                'max_length': 255 if extra_field.field_type == 'char' else None
            }
            self.fields[extra_field.field_name] = field_class(**field_kwargs)

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        extra_data = instance.extraData or {}

        for key, value in extra_data.items():
            if key in self.fields:
                representation[key] = value

        return representation
  • 中介軟體與代理處理:將伺服器分離到 Django 時,需創建中介軟體來處理代理。發現 Nuxt3 在生產環境構建後使用反向代理效果不佳。

    • 解決方案:手動在 Nitro 上創建反向代理伺服器,將 API 重定向到 Django 伺服器。處理不同伺服器間的認證更為複雜,需使用 Cookies 和 session 以確保代理期間認證數據不丟失。此外,更新代理代碼以支持 FormData,因涉及圖片和文件上傳。
  • 暗黑主題穩定性:在 Nuxt3 中未遇到暗黑主題閃爍問題。發現 Nuxt3 在這方面有優化,因為色彩數據也包含在 Cookies 中,確保主題在伺服器端正確渲染。

    • 優勢:無縫的主題切換,無視覺閃爍。
  • Windows IIS 上的部署挑戰:在 Windows IIS 伺服器上部署此類新技術遇到重大困難。

    • 遇到的問題

      • 缺少套件:在執行 npx nuxi build --preset=iis_node 時,某些必要的 Node 模組缺失。通過手動將開發環境的 node_modules 複製到伺服器上解決。
      • 版本衝突:某些套件需要特定的庫,且相同名稱由不同作者的套件造成衝突,導致下載錯誤版本。
      • Nuxt3 文檔與錯誤:發現 Nuxt3 文檔不夠完善且存在錯誤,尤其是在 SSR 資料抓取時返回 null,儘管在 Postman 和 Curl 中正常工作。通過將 Node.js 版本從 16 升級到 18 解決問題。
      • 社群支持:相比 Next.js,Nuxt3 的社群較小,難以找到解決方案。Next.js 提供更廣泛的資源和社群支持。
    • 結論:雖然 Vue3 的組件通信(emit / ref)非常出色,但 Nuxt3 在部署和支持方面相比 Next.js 存在挑戰。