POS & Inventory System

A comprehensive Point of Sale (POS) and Inventory Management system supporting dark/light modes and English/Chinese locales. Built with Nuxt3 on the frontend using TailwindCSS, Element-Plus, and Tabulator-table, and Python Django REST framework with Maria DB and Django ORM on the backend. Ensures database transactions adhere to ACID properties.

Features

  • Dark / Light Mode: Users can toggle between dark and light themes for an enhanced user experience.
  • English / Chinese Locales: Supports multiple languages, including English and Traditional Chinese.
  • Inventory & Sales Summary Charts and Tables: Visual and tabular summaries of inventory and sales data.
  • Product Columns Unlimited Expands: Using JSON to save and handle the product data, provide flexible columns structure based on different client.
  • POS Functions:
    • Create Invoice: Generate invoices for sales transactions.
    • Consignment: Manage consigned inventory.
    • Invoice Refund: Process refunds for invoices.
    • Invoice List: View and manage a list of all invoices.
    • Showcase Setting Page: Configure showcase display settings.
    • PDF Invoice Printing: Print invoices in PDF format.
  • Inventory Management:
    • Stock In / Out / Transfer / Write-off Actions: Efficiently manage stock movements.
    • Stock Inventory Table with History Reading Support: Track inventory changes over time.
    • Excel Import with Django Bulk Import: Fast bulk data upload using Django's bulk import capabilities.
    • Product Table with Multi-Image Support: Manage products with multiple images.
    • Detailed Tables (Location, Category, Material, Color, etc.): Organize inventory with additional details.
    • Stock Take Page and Stock Adjustment: Perform stock counts and adjust inventory accordingly.
  • System Settings:
    • User Account Management: Manage user accounts and roles.
    • Permission Settings: Define permissions, such as restricting access to sales reports and cost views.
    • System Logs: Maintain logs for system activities.
  • Label Printing Support: Integrates with third-party tools like QZ-Tray to print labels directly from the web interface using ZPL.

Technology

  • Frontend: Nuxt3, TailwindCSS, Element-Plus, Tabulator-table
  • Backend: Python Django REST Framework, Maria DB, Django ORM
  • Database: Maria DB with Django ORM ensuring ACID compliance
  • Label Printing: QZ-Tray for direct ZPL label printing

Development Insights

  • Project Framework Decision: Initially considered using Nitro (Nuxt3's default server-side server) but reverted to Django due to better ORM capabilities. Django ORM supports deep table joins required for sales summaries and inventory logs, which Prisma in Nitro could not efficiently handle.

  • Flexible Columns Handling: As different industries may have different columns in their product inventory. For example, the Jewelry Industry inventory may contain CTS and karat, while the Fashion Industry might include size, color, and material. Similarly, the Electronics Industry may have fields such as warranty_period, voltage, and brand. Besides migrate the Database structure each time, I design to use JSON to store the data as I still need to fit in Relational Database. First, I will extract all must required columns and a nullable json field as a product main table. And i will create a new table for storing the extra columns' name, type, isNullable etc. Then, I will use serializer to extract the json field from the product main table and convert it to structured json format based on the extra columns table data.

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
  • Middleware and Proxy Handling: Faced challenges in separating the server to Django, requiring the creation of middleware to handle proxy. Discovered that using a reverse proxy on Nuxt3 did not work in production builds. Manually created a reverse proxy server on Nitro to redirect APIs to the Django server. Managed complex authentication using Cookies and sessions to maintain auth data during proxying. Updated proxy code to support FormData for image and file uploads.

  • Dark Theme Stability: Did not encounter flickering issues with the dark theme in Nuxt3. Nuxt3 optimizes theme rendering by including color data in cookies, ensuring correct server-side rendering of themes. Seamless theme switching without visual glitches.

  • Hosting Challenges on Windows IIS: Encountered significant difficulties deploying the application on a Windows IIS server.

    • Issues Faced:

      • Missing Packages: During npx nuxi build --preset=iis_node, some required Node modules were missing. Resolved by manually copying node_modules from development to the server.
      • Version Conflicts: Some packages required specific libraries, and identical package names by different authors caused conflicts. Packages downloaded the wrong versions, leading to runtime issues.
      • Nuxt3 Documentation and Bugs: Found Nuxt3 documentation lacking and faced bugs, especially with SSR data fetching returning null despite working in Postman and Curl. Resolved by updating Node.js from version 16 to 18.
      • Community Support: Compared to Next.js, Nuxt3 has a smaller community, making it harder to find solutions. Next.js offers more extensive resources and community support.
    • Conclusion: While Vue3's component communication is excellent, Nuxt3 presents deployment and support challenges compared to Next.js.