Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28a8c1e63d | ||
|
|
9ccc26455e | ||
|
|
8ad64a986d | ||
|
|
3895c43a68 | ||
|
|
63c85ce2c7 | ||
|
|
3b618c6747 | ||
|
|
5580b53bfd | ||
| ee12b9c8d8 | |||
| 6c1f5b4edc | |||
|
|
0bbbba4a11 | ||
|
|
d55399ed55 | ||
|
|
a37102c3ae | ||
|
|
9e7ef1b825 | ||
|
|
3809b295a5 | ||
|
|
48ffd8ac57 | ||
|
|
178c09c3c4 | ||
|
|
b186e7ca23 | ||
|
|
f957cf4e5a | ||
|
|
98a8096725 | ||
|
|
65e1bdd116 | ||
|
|
f2b1ba34a7 | ||
|
|
e82c4c6d91 | ||
|
|
7cd3e54402 | ||
|
|
d48ec1a1fd | ||
|
|
4d1bebc6a6 | ||
|
|
945cea3b4c | ||
|
|
b44eb2cdc3 | ||
|
|
42de65fc6b | ||
|
|
0dc0cb365f | ||
|
|
06ec582ffb | ||
|
|
d442e2e691 | ||
|
|
878e652630 | ||
|
|
bab572e2ca | ||
|
|
6a42f15822 | ||
|
|
508d636675 | ||
|
|
a0100af842 | ||
|
|
271a1e3660 | ||
|
|
065c21e07c | ||
|
|
ecc9385c28 | ||
|
|
e1639109c8 | ||
|
|
e54a021b98 | ||
|
|
8665584567 | ||
|
|
c8559d63df | ||
|
|
e226faf08a | ||
|
|
43e058fe6f | ||
|
|
899a81c709 |
169
.dockerignore
169
.dockerignore
@ -1,74 +1,32 @@
|
|||||||
# ========================================
|
# Dependencies
|
||||||
# Docker Ignore File
|
node_modules/
|
||||||
# ========================================
|
vendor/
|
||||||
|
|
||||||
# Git
|
# Build artifacts
|
||||||
.git
|
/public/build
|
||||||
.gitignore
|
/public/hot
|
||||||
.gitattributes
|
/public/storage
|
||||||
|
/storage/*.key
|
||||||
|
|
||||||
# Documentation
|
# Environment files
|
||||||
README.md
|
.env
|
||||||
CHANGELOG.md
|
.env.backup
|
||||||
Documentation/
|
.env.production
|
||||||
*.md
|
|
||||||
|
|
||||||
# Tests
|
# IDE files
|
||||||
tests/
|
|
||||||
phpunit.xml
|
|
||||||
.phpunit.cache
|
|
||||||
.phpunit.result.cache
|
|
||||||
|
|
||||||
# IDE & Editors
|
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
.fleet/
|
|
||||||
.nova/
|
|
||||||
.zed/
|
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
*~
|
|
||||||
|
# OS generated files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.phpactor.json
|
|
||||||
|
|
||||||
# Docker files (tidak perlu di-copy ke image)
|
|
||||||
Dockerfile
|
|
||||||
docker-compose*.yml
|
|
||||||
.dockerignore
|
|
||||||
|
|
||||||
# Environment files (akan di-set via environment variables)
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
!.env.example
|
|
||||||
|
|
||||||
# Dependencies (akan di-install via composer & npm)
|
|
||||||
/vendor/
|
|
||||||
/node_modules/
|
|
||||||
|
|
||||||
# Build artifacts (akan di-build di stage terpisah)
|
|
||||||
/public/hot
|
|
||||||
/public/build
|
|
||||||
|
|
||||||
# Storage & Cache (akan di-mount sebagai volume)
|
|
||||||
/storage/*.key
|
|
||||||
/storage/logs/*
|
|
||||||
/storage/framework/cache/*
|
|
||||||
/storage/framework/sessions/*
|
|
||||||
/storage/framework/views/*
|
|
||||||
/storage/pail
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
/public/storage
|
|
||||||
/bootstrap/cache/*
|
|
||||||
|
|
||||||
# Local development files
|
|
||||||
Homestead.json
|
|
||||||
Homestead.yaml
|
|
||||||
auth.json
|
|
||||||
.vagrant
|
|
||||||
.phpstorm.meta.php
|
|
||||||
_ide_helper.php
|
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
*.log
|
*.log
|
||||||
@ -76,7 +34,86 @@ npm-debug.log*
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# OS Files
|
# Runtime data
|
||||||
.DS_Store
|
pids
|
||||||
Thumbs.db
|
*.pid
|
||||||
desktop.ini
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Laravel specific
|
||||||
|
/bootstrap/cache/*.php
|
||||||
|
/storage/app/*
|
||||||
|
!/storage/app/.gitignore
|
||||||
|
/storage/framework/cache/*
|
||||||
|
!/storage/framework/cache/.gitignore
|
||||||
|
/storage/framework/sessions/*
|
||||||
|
!/storage/framework/sessions/.gitignore
|
||||||
|
/storage/framework/testing/*
|
||||||
|
!/storage/framework/testing/.gitignore
|
||||||
|
/storage/framework/views/*
|
||||||
|
!/storage/framework/views/.gitignore
|
||||||
|
/storage/logs/*
|
||||||
|
!/storage/logs/.gitignore
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
/coverage
|
||||||
|
/.phpunit.result.cache
|
||||||
|
/phpunit.xml
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*.bak
|
||||||
|
*.backup
|
||||||
|
*.sql
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
README.md
|
||||||
|
Documentation/
|
||||||
|
|||||||
79
.env.docker
79
.env.docker
@ -1,86 +1,65 @@
|
|||||||
# ========================================
|
|
||||||
# Abbauf Kasir - Docker Environment Configuration
|
|
||||||
# ========================================
|
|
||||||
# Copy file ini ke .env sebelum deployment
|
|
||||||
# Ganti semua placeholder dengan nilai yang sesuai
|
|
||||||
|
|
||||||
# Application
|
|
||||||
APP_NAME=Abbauf-Kasir
|
APP_NAME=Abbauf-Kasir
|
||||||
APP_ENV=production
|
APP_ENV=local
|
||||||
APP_KEY= # Generate dengan: php artisan key:generate
|
APP_KEY=
|
||||||
APP_DEBUG=false
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost # Ganti dengan domain production
|
APP_URL=http://localhost
|
||||||
|
|
||||||
APP_LOCALE=id
|
APP_LOCALE=en
|
||||||
APP_FALLBACK_LOCALE=en
|
APP_FALLBACK_LOCALE=en
|
||||||
APP_FAKER_LOCALE=id_ID
|
APP_FAKER_LOCALE=en_US
|
||||||
|
|
||||||
APP_MAINTENANCE_DRIVER=file
|
APP_MAINTENANCE_DRIVER=file
|
||||||
|
# APP_MAINTENANCE_STORE=database
|
||||||
|
|
||||||
PHP_CLI_SERVER_WORKERS=4
|
PHP_CLI_SERVER_WORKERS=4
|
||||||
|
|
||||||
BCRYPT_ROUNDS=12
|
BCRYPT_ROUNDS=12
|
||||||
|
|
||||||
# Logging
|
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
LOG_STACK=daily
|
LOG_STACK=single
|
||||||
LOG_DEPRECATIONS_CHANNEL=null
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
LOG_LEVEL=error
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
# Database Configuration
|
DB_CONNECTION=sqlite
|
||||||
DB_CONNECTION=mysql
|
# DB_HOST=127.0.0.1
|
||||||
DB_HOST=mysql # Nama service di docker-compose
|
# DB_PORT=3306
|
||||||
DB_PORT=3306
|
# DB_DATABASE=laravel
|
||||||
DB_DATABASE=kasir_db # Nama database
|
# DB_USERNAME=root
|
||||||
DB_USERNAME=kasir_user # Username database
|
# DB_PASSWORD=
|
||||||
DB_PASSWORD=strong_password_here # GANTI dengan password kuat!
|
|
||||||
|
|
||||||
# MySQL Root Password (untuk docker-compose)
|
SESSION_DRIVER=database
|
||||||
MYSQL_ROOT_PASSWORD=root_strong_password # GANTI dengan password root yang kuat!
|
|
||||||
|
|
||||||
# Cache & Session
|
|
||||||
CACHE_STORE=redis
|
|
||||||
SESSION_DRIVER=redis
|
|
||||||
SESSION_LIFETIME=120
|
SESSION_LIFETIME=120
|
||||||
SESSION_ENCRYPT=false
|
SESSION_ENCRYPT=false
|
||||||
SESSION_PATH=/
|
SESSION_PATH=/
|
||||||
SESSION_DOMAIN=null
|
SESSION_DOMAIN=null
|
||||||
|
|
||||||
# Redis Configuration
|
BROADCAST_CONNECTION=log
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
QUEUE_CONNECTION=database
|
||||||
|
|
||||||
|
CACHE_STORE=database
|
||||||
|
# CACHE_PREFIX=
|
||||||
|
|
||||||
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
REDIS_CLIENT=phpredis
|
REDIS_CLIENT=phpredis
|
||||||
REDIS_HOST=redis
|
REDIS_HOST=127.0.0.1
|
||||||
REDIS_PASSWORD=null
|
REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
# Queue
|
|
||||||
QUEUE_CONNECTION=redis
|
|
||||||
|
|
||||||
# Broadcasting
|
|
||||||
BROADCAST_CONNECTION=log
|
|
||||||
|
|
||||||
# Filesystem
|
|
||||||
FILESYSTEM_DISK=local
|
|
||||||
|
|
||||||
# Mail Configuration (opsional)
|
|
||||||
MAIL_MAILER=log
|
MAIL_MAILER=log
|
||||||
MAIL_SCHEME=null
|
MAIL_SCHEME=null
|
||||||
MAIL_HOST=127.0.0.1
|
MAIL_HOST=127.0.0.1
|
||||||
MAIL_PORT=2525
|
MAIL_PORT=2525
|
||||||
MAIL_USERNAME=null
|
MAIL_USERNAME=null
|
||||||
MAIL_PASSWORD=null
|
MAIL_PASSWORD=null
|
||||||
MAIL_FROM_ADDRESS="noreply@abbauf-kasir.local"
|
MAIL_FROM_ADDRESS="hello@example.com"
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
# AWS (jika menggunakan S3 untuk storage)
|
|
||||||
AWS_ACCESS_KEY_ID=
|
AWS_ACCESS_KEY_ID=
|
||||||
AWS_SECRET_ACCESS_KEY=
|
AWS_SECRET_ACCESS_KEY=
|
||||||
AWS_DEFAULT_REGION=us-east-1
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
AWS_BUCKET=
|
AWS_BUCKET=
|
||||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
# Ports (untuk docker-compose)
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
APP_PORT=80 # Port untuk akses aplikasi
|
|
||||||
# DB_PORT=3306 # Uncomment jika ingin expose DB port
|
|
||||||
# REDIS_PORT=6379 # Uncomment jika ingin expose Redis port
|
|
||||||
|
|
||||||
# Vite
|
|
||||||
VITE_APP_NAME="${APP_NAME}"
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
APP_NAME=Abbauf-Kasir
|
APP_NAME=Abbauf-Kasir
|
||||||
APP_ENV=production
|
APP_ENV=local
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=false
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
|
|
||||||
APP_LOCALE=en
|
APP_LOCALE=en
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -24,6 +24,5 @@ Homestead.yaml
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
# Docker - Database Backups (exclude backups from git)
|
# Docker - Database Backups (exclude backups from git)
|
||||||
/docker/mysql/backups/*.sql
|
/docker
|
||||||
/docker/mysql/backups/*.sql.gz
|
deploy-kasir.sh
|
||||||
!/docker/mysql/backups/README.md
|
|
||||||
126
Dockerfile
126
Dockerfile
@ -1,91 +1,57 @@
|
|||||||
# ========================================
|
# Use PHP 8.2 with Apache
|
||||||
# Stage 1: Build Frontend Assets (Vue.js)
|
FROM php:8.2-apache
|
||||||
# ========================================
|
|
||||||
FROM node:20-alpine as node_builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy package files untuk caching layer
|
|
||||||
COPY package*.json ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN npm ci --legacy-peer-deps
|
|
||||||
|
|
||||||
# Copy seluruh source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build production assets
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# Stage 2: Laravel Application
|
|
||||||
# ========================================
|
|
||||||
FROM php:8.3-fpm-alpine
|
|
||||||
|
|
||||||
# Install system dependencies dan PHP extensions
|
|
||||||
RUN apk update && apk add --no-cache \
|
|
||||||
git \
|
|
||||||
unzip \
|
|
||||||
libzip-dev \
|
|
||||||
libpng-dev \
|
|
||||||
oniguruma-dev \
|
|
||||||
libxml2-dev \
|
|
||||||
curl \
|
|
||||||
mysql-client \
|
|
||||||
autoconf \
|
|
||||||
g++ \
|
|
||||||
make \
|
|
||||||
&& docker-php-ext-install \
|
|
||||||
pdo_mysql \
|
|
||||||
zip \
|
|
||||||
gd \
|
|
||||||
mbstring \
|
|
||||||
exif \
|
|
||||||
pcntl \
|
|
||||||
bcmath \
|
|
||||||
&& pecl install redis \
|
|
||||||
&& docker-php-ext-enable redis \
|
|
||||||
&& apk del autoconf g++ make \
|
|
||||||
&& rm -rf /var/cache/apk/* /tmp/*
|
|
||||||
|
|
||||||
# Install Composer
|
|
||||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
|
||||||
|
|
||||||
# Set working directory
|
# Set working directory
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
# Copy composer files untuk caching layer
|
# Install system dependencies
|
||||||
COPY composer.json composer.lock ./
|
RUN apt-get update && apt-get install -y \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
libpng-dev \
|
||||||
|
libonig-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
libzip-dev \
|
||||||
|
zip \
|
||||||
|
unzip \
|
||||||
|
nodejs \
|
||||||
|
npm \
|
||||||
|
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip
|
||||||
|
|
||||||
|
# Install Redis extension
|
||||||
|
RUN pecl install redis && docker-php-ext-enable redis
|
||||||
|
|
||||||
|
# Install Composer
|
||||||
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
# Enable Apache mod_rewrite
|
||||||
|
RUN a2enmod rewrite
|
||||||
|
|
||||||
|
# Copy Apache configuration
|
||||||
|
COPY docker/apache/000-default.conf /etc/apache2/sites-available/000-default.conf
|
||||||
|
|
||||||
|
# Copy application files
|
||||||
|
COPY . /var/www/html
|
||||||
|
|
||||||
|
# Set proper permissions
|
||||||
|
RUN chown -R www-data:www-data /var/www/html \
|
||||||
|
&& chmod -R 755 /var/www/html/storage \
|
||||||
|
&& chmod -R 755 /var/www/html/bootstrap/cache
|
||||||
|
|
||||||
# Install PHP dependencies
|
# Install PHP dependencies
|
||||||
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
|
RUN composer install --no-dev --optimize-autoloader
|
||||||
|
|
||||||
# Copy application source code
|
# Install Node.js dependencies and build assets
|
||||||
COPY . .
|
RUN npm install && npm run build
|
||||||
|
|
||||||
# Copy hasil build Vue dari stage 1
|
# Create .env file if it doesn't exist
|
||||||
COPY --from=node_builder /app/public/build /var/www/html/public/build
|
RUN if [ ! -f .env ]; then cp .env.example .env; fi
|
||||||
|
|
||||||
# Generate autoload files dengan optimasi
|
# Generate application key
|
||||||
RUN composer dump-autoload --optimize --classmap-authoritative
|
RUN php artisan key:generate
|
||||||
|
|
||||||
# Create required directories dan set permissions
|
# Expose port 80
|
||||||
RUN mkdir -p \
|
EXPOSE 80
|
||||||
storage/framework/cache \
|
|
||||||
storage/framework/sessions \
|
|
||||||
storage/framework/views \
|
|
||||||
storage/logs \
|
|
||||||
bootstrap/cache \
|
|
||||||
&& chown -R www-data:www-data \
|
|
||||||
/var/www/html/storage \
|
|
||||||
/var/www/html/bootstrap/cache \
|
|
||||||
&& chmod -R 775 \
|
|
||||||
/var/www/html/storage \
|
|
||||||
/var/www/html/bootstrap/cache
|
|
||||||
|
|
||||||
# Switch ke user non-root untuk keamanan
|
# Start Apache
|
||||||
USER www-data
|
CMD ["apache2-foreground"]
|
||||||
|
|
||||||
EXPOSE 9000
|
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
|
||||||
|
|||||||
717
Documentation/NiimbotPrinter-FlowChart.md
Normal file
717
Documentation/NiimbotPrinter-FlowChart.md
Normal file
@ -0,0 +1,717 @@
|
|||||||
|
# 📊 Diagram Alur Kerja Printer Niimbot
|
||||||
|
|
||||||
|
## 🔄 Alur Lengkap: Dari UI ke Printer
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[User buka halaman Brankas] --> B{Printer sudah<br/>terhubung?}
|
||||||
|
B -->|Tidak| C[Klik 'Hubungkan Printer']
|
||||||
|
B -->|Ya| D[Status: Terhubung]
|
||||||
|
|
||||||
|
C --> E[Modal NiimbotConnector muncul]
|
||||||
|
E --> F{Pilih metode koneksi}
|
||||||
|
F -->|Bluetooth| G[Klik 'Hubungkan Printer']
|
||||||
|
F -->|USB/Serial| G
|
||||||
|
|
||||||
|
G --> H[Browser: Dialog pairing muncul]
|
||||||
|
H --> I[User pilih Niimbot device]
|
||||||
|
I --> J[Library: initClient & connect]
|
||||||
|
|
||||||
|
J --> K{Koneksi<br/>berhasil?}
|
||||||
|
K -->|Tidak| L[Tampilkan error]
|
||||||
|
K -->|Ya| M[Fetch printer info]
|
||||||
|
|
||||||
|
M --> N[Status: Terhubung ✓]
|
||||||
|
N --> D
|
||||||
|
|
||||||
|
D --> O[User klik item di Brankas]
|
||||||
|
O --> P[Modal item muncul]
|
||||||
|
P --> Q[Generate QR Code URL]
|
||||||
|
Q --> R[Tampilkan preview QR]
|
||||||
|
|
||||||
|
R --> S[User klik 'Cetak ke Niimbot']
|
||||||
|
S --> T{Printer<br/>terhubung?}
|
||||||
|
|
||||||
|
T -->|Tidak| U[Alert: Hubungkan printer]
|
||||||
|
U --> C
|
||||||
|
|
||||||
|
T -->|Ya| V[createQRLabelCanvas]
|
||||||
|
V --> W[Load QR image]
|
||||||
|
W --> X[Draw ke canvas:<br/>QR + Kode + Nama + Berat]
|
||||||
|
X --> Y[Convert canvas to DataURL]
|
||||||
|
|
||||||
|
Y --> Z[printQRCode composable]
|
||||||
|
Z --> AA[Stop heartbeat]
|
||||||
|
AA --> AB[Create PrintTask]
|
||||||
|
AB --> AC[ImageEncoder.encodeCanvas]
|
||||||
|
AC --> AD[printTask.printInit]
|
||||||
|
AD --> AE[printTask.printPage]
|
||||||
|
|
||||||
|
AE --> AF{Print<br/>sukses?}
|
||||||
|
AF -->|Tidak| AG[Tampilkan error]
|
||||||
|
AF -->|Ya| AH[printTask.printEnd]
|
||||||
|
|
||||||
|
AH --> AI[Start heartbeat]
|
||||||
|
AI --> AJ[Alert: Berhasil dicetak!]
|
||||||
|
AJ --> AK[Printer cetak label]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Arsitektur Komponen
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ BrankasList.vue │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ UI Layer │ │
|
||||||
|
│ │ - Tombol "Hubungkan Printer" │ │
|
||||||
|
│ │ - Tombol "Cetak ke Niimbot" │ │
|
||||||
|
│ │ - Modal item dengan QR Code │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Logic Layer │ │
|
||||||
|
│ │ - printQR() → Trigger print │ │
|
||||||
|
│ │ - createQRLabelCanvas() → Generate canvas dengan QR │ │
|
||||||
|
│ │ - handlePrinterConnected() → Event handler │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
└───────────────────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ useNiimbotPrinter.js (Composable) │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ State Management │ │
|
||||||
|
│ │ - printerClient (reactive) │ │
|
||||||
|
│ │ - connectionState │ │
|
||||||
|
│ │ - isPrinting, printProgress │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Methods │ │
|
||||||
|
│ │ - initClient() → Buat NiimbotClient │ │
|
||||||
|
│ │ - connect() → Hubungkan ke printer │ │
|
||||||
|
│ │ - disconnect() → Putuskan koneksi │ │
|
||||||
|
│ │ - printQRCode() → Print image ke printer │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
└───────────────────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ @mmote/niimbluelib (Library) │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ NiimbotBluetoothClient / NiimbotSerialClient │ │
|
||||||
|
│ │ - connect() → Web Bluetooth/Serial API │ │
|
||||||
|
│ │ - fetchPrinterInfo() → Get printer metadata │ │
|
||||||
|
│ │ - startHeartbeat() → Maintain connection │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ PrintTask │ │
|
||||||
|
│ │ - newPrintTask() → Buat task print │ │
|
||||||
|
│ │ - printInit() → Inisialisasi print │ │
|
||||||
|
│ │ - printPage() → Kirim data gambar │ │
|
||||||
|
│ │ - waitForFinished() → Tunggu selesai │ │
|
||||||
|
│ │ - printEnd() → Akhiri print │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ┌────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ ImageEncoder │ │
|
||||||
|
│ │ - encodeCanvas() → Encode canvas ke binary │ │
|
||||||
|
│ └────────────────────────────────────────────────────────┘ │
|
||||||
|
└───────────────────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Browser Web APIs │
|
||||||
|
│ - Web Bluetooth API (navigator.bluetooth) │
|
||||||
|
│ - Web Serial API (navigator.serial) │
|
||||||
|
└───────────────────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Printer Niimbot (Hardware) │
|
||||||
|
│ - Terima perintah via BLE/USB │
|
||||||
|
│ - Decode binary image data │
|
||||||
|
│ - Print ke label thermal │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📡 Sequence Diagram: Proses Print
|
||||||
|
|
||||||
|
```
|
||||||
|
User BrankasList useNiimbot niimbluelib Browser API Printer
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ Klik item │ │ │ │ │
|
||||||
|
├───────────────>│ │ │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ Modal muncul │ │ │ │ │
|
||||||
|
│<───────────────┤ │ │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ Klik 'Cetak' │ │ │ │ │
|
||||||
|
├───────────────>│ │ │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ printQRCode()│ │ │ │
|
||||||
|
│ ├─────────────>│ │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ stopHeartbeat() │ │
|
||||||
|
│ │ ├─────────────>│ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ newPrintTask() │ │
|
||||||
|
│ │ ├─────────────>│ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ encodeCanvas() │ │
|
||||||
|
│ │ ├─────────────>│ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ │ BLE/Serial │ │
|
||||||
|
│ │ │ │ Write Data │ │
|
||||||
|
│ │ │ ├─────────────>│ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ │ │ Send Data │
|
||||||
|
│ │ │ │ ├───────────>│
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ │ │ Printing │
|
||||||
|
│ │ │ │ │ ........ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ │ Status ACK │ │
|
||||||
|
│ │ │ │<─────────────┤ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ printEnd() │ │ │
|
||||||
|
│ │ ├─────────────>│ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ startHeartbeat() │ │
|
||||||
|
│ │ ├─────────────>│ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ Alert sukses │ │ │ │
|
||||||
|
│ │<─────────────┤ │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ Label tercetak│ │ │ │ │
|
||||||
|
│<───────────────┴──────────────┴──────────────┴──────────────┴────────────┤
|
||||||
|
│ │
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔌 Connection Flow Detail
|
||||||
|
|
||||||
|
### Bluetooth Connection
|
||||||
|
```
|
||||||
|
1. User Action
|
||||||
|
└─> Klik "Hubungkan Printer"
|
||||||
|
|
||||||
|
2. initClient('bluetooth')
|
||||||
|
└─> new NiimbotBluetoothClient()
|
||||||
|
|
||||||
|
3. connect()
|
||||||
|
└─> navigator.bluetooth.requestDevice({
|
||||||
|
filters: [{ namePrefix: 'Niimbot' }],
|
||||||
|
optionalServices: [SERVICE_UUID]
|
||||||
|
})
|
||||||
|
|
||||||
|
4. Browser Dialog
|
||||||
|
└─> User pilih device "Niimbot-XXXX"
|
||||||
|
|
||||||
|
5. device.gatt.connect()
|
||||||
|
└─> Establish BLE connection
|
||||||
|
|
||||||
|
6. getPrimaryService(SERVICE_UUID)
|
||||||
|
└─> getCharacteristic(TX_CHAR, RX_CHAR)
|
||||||
|
|
||||||
|
7. Event: 'connect' triggered
|
||||||
|
└─> connectionState = 'connected'
|
||||||
|
|
||||||
|
8. fetchPrinterInfo()
|
||||||
|
└─> Send command: GET_INFO
|
||||||
|
└─> Receive: model, serial, firmware version
|
||||||
|
|
||||||
|
9. startHeartbeat()
|
||||||
|
└─> Kirim ping setiap 1 detik
|
||||||
|
└─> Cek printer masih hidup
|
||||||
|
```
|
||||||
|
|
||||||
|
### USB/Serial Connection
|
||||||
|
```
|
||||||
|
1. User Action
|
||||||
|
└─> Klik "Hubungkan Printer"
|
||||||
|
|
||||||
|
2. initClient('serial')
|
||||||
|
└─> new NiimbotSerialClient()
|
||||||
|
|
||||||
|
3. connect()
|
||||||
|
└─> navigator.serial.requestPort({
|
||||||
|
filters: [{ usbVendorId: 0xXXXX }]
|
||||||
|
})
|
||||||
|
|
||||||
|
4. Browser Dialog
|
||||||
|
└─> User pilih USB device
|
||||||
|
|
||||||
|
5. port.open({ baudRate: 9600 })
|
||||||
|
└─> Establish serial connection
|
||||||
|
|
||||||
|
6. Setup reader/writer streams
|
||||||
|
└─> readable.getReader()
|
||||||
|
└─> writable.getWriter()
|
||||||
|
|
||||||
|
7. Event: 'connect' triggered
|
||||||
|
└─> connectionState = 'connected'
|
||||||
|
|
||||||
|
8. fetchPrinterInfo() & startHeartbeat()
|
||||||
|
└─> (sama dengan Bluetooth)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🖼️ Image Processing Pipeline
|
||||||
|
|
||||||
|
```
|
||||||
|
QR Code URL (dari API)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
new Image()
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
img.onload
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Create Canvas (384x384)
|
||||||
|
│
|
||||||
|
├─> Fill white background
|
||||||
|
│
|
||||||
|
├─> drawImage(qr, x, y, size, size)
|
||||||
|
│
|
||||||
|
├─> fillText(kode_item)
|
||||||
|
│
|
||||||
|
├─> fillText(nama_produk)
|
||||||
|
│
|
||||||
|
├─> fillText(berat)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
canvas.toDataURL('image/png')
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
loadImageToCanvas(dataUrl)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[Optional] applyThreshold(canvas, 140)
|
||||||
|
│
|
||||||
|
├─> getImageData()
|
||||||
|
│
|
||||||
|
├─> for each pixel:
|
||||||
|
│ avg = (r+g+b)/3
|
||||||
|
│ if avg < 140: black
|
||||||
|
│ else: white
|
||||||
|
│
|
||||||
|
├─> putImageData()
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
ImageEncoder.encodeCanvas(canvas, 'top')
|
||||||
|
│
|
||||||
|
├─> Convert to 1-bit bitmap
|
||||||
|
│
|
||||||
|
├─> Rotate if needed (printDirection)
|
||||||
|
│
|
||||||
|
├─> Pack bits: 8 pixels = 1 byte
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Binary Data (EncodedImage)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
printTask.printPage(encoded, quantity)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Send to Printer via BLE/Serial
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 State Machine Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐
|
||||||
|
│ DISCONNECTED │◄────────┐
|
||||||
|
└────────┬────────┘ │
|
||||||
|
│ │
|
||||||
|
│ connect() │ disconnect()
|
||||||
|
│ │
|
||||||
|
▼ │
|
||||||
|
┌─────────────────┐ │
|
||||||
|
│ CONNECTING │ │
|
||||||
|
└────────┬────────┘ │
|
||||||
|
│ │
|
||||||
|
│ success │ error
|
||||||
|
│ │
|
||||||
|
▼ │
|
||||||
|
┌─────────────────┐ │
|
||||||
|
│ CONNECTED │─────────┤
|
||||||
|
└────────┬────────┘ │
|
||||||
|
│ │
|
||||||
|
│ printQRCode() │
|
||||||
|
│ │
|
||||||
|
▼ │
|
||||||
|
┌─────────────────┐ │
|
||||||
|
│ PRINTING │ │
|
||||||
|
│ [progress: X%] │ │
|
||||||
|
└────────┬────────┘ │
|
||||||
|
│ │
|
||||||
|
│ finished │
|
||||||
|
│ │
|
||||||
|
▼ │
|
||||||
|
┌─────────────────┐ │
|
||||||
|
│ CONNECTED │─────────┘
|
||||||
|
│ (heartbeat) │
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Data Flow: QR Code → Printed Label
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ 1. DATA SOURCE │
|
||||||
|
│ ─────────────────────────────────────────────────────────│
|
||||||
|
│ selectedItem = { │
|
||||||
|
│ kode_item: "BRN-001", │
|
||||||
|
│ produk: { │
|
||||||
|
│ nama: "Cincin Emas 24K", │
|
||||||
|
│ berat: 5.2 │
|
||||||
|
│ } │
|
||||||
|
│ } │
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ 2. QR CODE GENERATION (External API) │
|
||||||
|
│ ─────────────────────────────────────────────────────────│
|
||||||
|
│ URL: https://api.qrserver.com/v1/create-qr-code/ │
|
||||||
|
│ ?size=150x150&data=BRN-001 │
|
||||||
|
│ │
|
||||||
|
│ Returns: image/png (base64 or URL) │
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ 3. CANVAS CREATION │
|
||||||
|
│ ─────────────────────────────────────────────────────────│
|
||||||
|
│ createQRLabelCanvas(qrUrl, item) │
|
||||||
|
│ │
|
||||||
|
│ Canvas 384x384px: │
|
||||||
|
│ ┌──────────────────────┐ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ ┌──────────┐ │ ← QR Code (200x200) │
|
||||||
|
│ │ │ ▓▓ ▓▓▓▓│ │ │
|
||||||
|
│ │ │▓ ▓▓ ▓ │ │ │
|
||||||
|
│ │ │ ▓▓▓ ▓▓▓│ │ │
|
||||||
|
│ │ └──────────┘ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ BRN-001 │ ← Kode Item (bold 18px) │
|
||||||
|
│ │ Cincin Emas 24K │ ← Nama Produk (14px) │
|
||||||
|
│ │ 5.2g │ ← Berat (12px) │
|
||||||
|
│ │ │ │
|
||||||
|
│ └──────────────────────┘ │
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ 4. IMAGE ENCODING │
|
||||||
|
│ ─────────────────────────────────────────────────────────│
|
||||||
|
│ ImageEncoder.encodeCanvas(canvas, 'top') │
|
||||||
|
│ │
|
||||||
|
│ Process: │
|
||||||
|
│ - Convert RGB to grayscale │
|
||||||
|
│ - Apply threshold (< 140 = black, >= 140 = white) │
|
||||||
|
│ - Pack 8 pixels into 1 byte (1-bit bitmap) │
|
||||||
|
│ - Width: 384px = 48 bytes per row │
|
||||||
|
│ - Height: 384 rows │
|
||||||
|
│ - Total: 48 × 384 = 18,432 bytes │
|
||||||
|
│ │
|
||||||
|
│ Output: Uint8Array(18432) │
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ 5. PRINT PROTOCOL │
|
||||||
|
│ ─────────────────────────────────────────────────────────│
|
||||||
|
│ printTask.printInit() │
|
||||||
|
│ └─> Send: [CMD_INIT, density, labelType, ...] │
|
||||||
|
│ │
|
||||||
|
│ printTask.printPage(encoded, quantity) │
|
||||||
|
│ └─> Send in chunks: │
|
||||||
|
│ [CMD_IMAGE_HEADER, width, height] │
|
||||||
|
│ [CMD_IMAGE_DATA, chunk1...] │
|
||||||
|
│ [CMD_IMAGE_DATA, chunk2...] │
|
||||||
|
│ ... │
|
||||||
|
│ [CMD_IMAGE_END] │
|
||||||
|
│ │
|
||||||
|
│ printTask.waitForFinished() │
|
||||||
|
│ └─> Poll status every 100ms │
|
||||||
|
│ until status = FINISHED │
|
||||||
|
│ │
|
||||||
|
│ printTask.printEnd() │
|
||||||
|
│ └─> Send: [CMD_PRINT_END] │
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ 6. PHYSICAL OUTPUT │
|
||||||
|
│ ─────────────────────────────────────────────────────────│
|
||||||
|
│ Printer Niimbot: │
|
||||||
|
│ - Receives binary data via BLE/USB │
|
||||||
|
│ - Thermal head heats selected pixels │
|
||||||
|
│ - Paper feeds forward │
|
||||||
|
│ - Label printed with QR + text │
|
||||||
|
│ - Cut (automatic or manual) │
|
||||||
|
│ │
|
||||||
|
│ Result: Physical label 40x40mm dengan QR code │
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Component Interaction Map
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────┐
|
||||||
|
│ App.vue / Router │
|
||||||
|
└──────────┬───────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────────┐
|
||||||
|
│ BrankasList.vue │
|
||||||
|
│ │
|
||||||
|
│ ┌────────────────┐ │
|
||||||
|
│ │ Header │ │
|
||||||
|
│ │ - Printer Btn │──┼──┐
|
||||||
|
│ └────────────────┘ │ │
|
||||||
|
│ │ │
|
||||||
|
│ ┌────────────────┐ │ │
|
||||||
|
│ │ Item List │ │ │
|
||||||
|
│ │ - Click item │──┼──┼──┐
|
||||||
|
│ └────────────────┘ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ┌────────────────┐ │ │ │
|
||||||
|
│ │ Item Modal │ │ │ │
|
||||||
|
│ │ - QR Preview │ │ │ │
|
||||||
|
│ │ - Print Btn │──┼──┼──┼──┐
|
||||||
|
│ └────────────────┘ │ │ │ │
|
||||||
|
└──────────────────────┘ │ │ │
|
||||||
|
│ │ │
|
||||||
|
┌─────────────────────────────────────┘ │ │
|
||||||
|
│ │ │
|
||||||
|
▼ │ │
|
||||||
|
┌──────────────────┐ │ │
|
||||||
|
│ NiimbotConnector │ │ │
|
||||||
|
│ .vue │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ - Connect UI │◄───────────────────────────┘ │
|
||||||
|
│ - Status display │ │
|
||||||
|
│ - Printer info │ │
|
||||||
|
└────────┬─────────┘ │
|
||||||
|
│ │
|
||||||
|
│ uses │
|
||||||
|
│ │
|
||||||
|
▼ │
|
||||||
|
┌──────────────────────────────────────────────────┼───┐
|
||||||
|
│ useNiimbotPrinter.js (Composable) │ │
|
||||||
|
│ │ │
|
||||||
|
│ - State: printerClient, connectionState, etc │◄──┘
|
||||||
|
│ - Methods: connect(), disconnect(), printQR() │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────┐ │
|
||||||
|
│ │ Event Listeners Setup │ │
|
||||||
|
│ │ - on('connect') │ │
|
||||||
|
│ │ - on('disconnect') │ │
|
||||||
|
│ │ - on('printprogress') │ │
|
||||||
|
│ │ - on('heartbeat') │ │
|
||||||
|
│ └─────────────────────────────────────────────┘ │
|
||||||
|
└──────────────────┬───────────────────────────────┘
|
||||||
|
│ imports
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────┐
|
||||||
|
│ @mmote/niimbluelib │
|
||||||
|
│ │
|
||||||
|
│ - NiimbotBluetoothClient │
|
||||||
|
│ - NiimbotSerialClient │
|
||||||
|
│ - ImageEncoder │
|
||||||
|
│ - PrintTask abstraction │
|
||||||
|
│ - Utils │
|
||||||
|
└──────────────────┬─────────────────────────────────┘
|
||||||
|
│ uses
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────┐
|
||||||
|
│ Browser APIs │
|
||||||
|
│ - navigator.bluetooth (Web Bluetooth API) │
|
||||||
|
│ - navigator.serial (Web Serial API) │
|
||||||
|
└────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚡ Performance Timeline
|
||||||
|
|
||||||
|
```
|
||||||
|
Event Timeline (typical print job):
|
||||||
|
|
||||||
|
0ms │ User clicks "Cetak ke Niimbot"
|
||||||
|
│
|
||||||
|
10ms │ Check printer connection
|
||||||
|
│ └─> Already connected ✓
|
||||||
|
│
|
||||||
|
20ms │ createQRLabelCanvas() start
|
||||||
|
│ └─> Load QR image
|
||||||
|
│
|
||||||
|
150ms │ Image loaded, draw to canvas
|
||||||
|
│ └─> Draw QR, text, etc
|
||||||
|
│
|
||||||
|
170ms │ canvas.toDataURL()
|
||||||
|
│
|
||||||
|
200ms │ printQRCode() called
|
||||||
|
│ └─> stopHeartbeat()
|
||||||
|
│
|
||||||
|
220ms │ newPrintTask()
|
||||||
|
│
|
||||||
|
240ms │ ImageEncoder.encodeCanvas()
|
||||||
|
│ └─> RGB → grayscale
|
||||||
|
│ └─> Threshold
|
||||||
|
│ └─> Pack to 1-bit
|
||||||
|
│
|
||||||
|
450ms │ Encoding complete (18KB data)
|
||||||
|
│
|
||||||
|
470ms │ printTask.printInit()
|
||||||
|
│ └─> Send init command
|
||||||
|
│
|
||||||
|
490ms │ ACK received
|
||||||
|
│
|
||||||
|
500ms │ printTask.printPage()
|
||||||
|
│ └─> Send image header
|
||||||
|
│
|
||||||
|
520ms │ Send data chunk 1/10
|
||||||
|
540ms │ Send data chunk 2/10
|
||||||
|
... │ ...
|
||||||
|
740ms │ Send data chunk 10/10
|
||||||
|
│
|
||||||
|
750ms │ All data sent
|
||||||
|
│
|
||||||
|
780ms │ waitForFinished() polling start
|
||||||
|
│
|
||||||
|
800ms │ Status: PRINTING (0%)
|
||||||
|
900ms │ Status: PRINTING (25%)
|
||||||
|
1000ms │ Status: PRINTING (50%)
|
||||||
|
1100ms │ Status: PRINTING (75%)
|
||||||
|
1200ms │ Status: PRINTING (100%)
|
||||||
|
│
|
||||||
|
1220ms │ Status: FINISHED
|
||||||
|
│
|
||||||
|
1230ms │ printTask.printEnd()
|
||||||
|
│
|
||||||
|
1250ms │ startHeartbeat()
|
||||||
|
│
|
||||||
|
1260ms │ Alert: "QR Code berhasil dicetak!"
|
||||||
|
│
|
||||||
|
Total: ~1.3 seconds dari klik hingga selesai
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Security & Privacy
|
||||||
|
|
||||||
|
```
|
||||||
|
Data Flow Security:
|
||||||
|
|
||||||
|
┌──────────────────┐
|
||||||
|
│ User's Browser │
|
||||||
|
└────────┬─────────┘
|
||||||
|
│
|
||||||
|
│ HTTPS (encrypted)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────┐
|
||||||
|
│ QR API Server │ ← External: api.qrserver.com
|
||||||
|
└────────┬─────────┘ (Kirim kode_item only)
|
||||||
|
│
|
||||||
|
│ Returns image URL
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────┐
|
||||||
|
│ User's Browser │
|
||||||
|
│ - Generate │
|
||||||
|
│ canvas │
|
||||||
|
│ - Encode image │
|
||||||
|
└────────┬─────────┘
|
||||||
|
│
|
||||||
|
│ BLE/USB (direct, tidak via internet)
|
||||||
|
│ Encrypted jika BLE
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────┐
|
||||||
|
│ Niimbot Printer │ ← Local device, tidak terkoneksi internet
|
||||||
|
└──────────────────┘
|
||||||
|
|
||||||
|
Privacy Notes:
|
||||||
|
- Data tidak lewat server backend aplikasi
|
||||||
|
- QR Code dibuat real-time di browser
|
||||||
|
- Gambar langsung dikirim ke printer lokal
|
||||||
|
- Tidak ada logging data item ke cloud
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 Error Handling Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────┐
|
||||||
|
│ User Action │
|
||||||
|
└────────┬─────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────┐
|
||||||
|
│ Try: connect() │
|
||||||
|
└────────┬─────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────┐
|
||||||
|
│ │
|
||||||
|
┌──────▼──────┐ ┌──────▼──────┐
|
||||||
|
│ Success │ │ Error │
|
||||||
|
└──────┬──────┘ └──────┬──────┘
|
||||||
|
│ │
|
||||||
|
│ ▼
|
||||||
|
│ ┌────────────────┐
|
||||||
|
│ │ Catch error │
|
||||||
|
│ │ - Log to │
|
||||||
|
│ │ console │
|
||||||
|
│ │ - Set error │
|
||||||
|
│ │ message │
|
||||||
|
│ │ - Alert user │
|
||||||
|
│ └────────┬───────┘
|
||||||
|
│ │
|
||||||
|
│ ▼
|
||||||
|
│ ┌────────────────┐
|
||||||
|
│ │ connectionState│
|
||||||
|
│ │ = 'disconnected│
|
||||||
|
│ └────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────┐
|
||||||
|
│ fetchPrinterInfo│
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
┌──────┴──────┐
|
||||||
|
│ │
|
||||||
|
┌─────▼─────┐ ┌────▼────┐
|
||||||
|
│ Success │ │ Error │
|
||||||
|
└─────┬─────┘ └────┬────┘
|
||||||
|
│ │
|
||||||
|
│ └──> Log & continue (non-critical)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ startHeartbeat()│
|
||||||
|
└─────────┬───────┘
|
||||||
|
│
|
||||||
|
└──> Connected & Ready
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Semua diagram ini membantu memahami bagaimana sistem bekerja end-to-end! 🎉
|
||||||
373
Documentation/NiimbotPrinter.md
Normal file
373
Documentation/NiimbotPrinter.md
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
# 🖨️ Dokumentasi Integrasi Printer Niimbot
|
||||||
|
|
||||||
|
## 📋 Ringkasan
|
||||||
|
|
||||||
|
Aplikasi kasir sekarang mendukung pencetakan QR Code langsung ke printer Niimbot menggunakan library `@mmote/niimbluelib` yang diadaptasi dari proyek niimblue.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Teknologi & Library
|
||||||
|
|
||||||
|
### Library Utama
|
||||||
|
- **@mmote/niimbluelib** - Library JavaScript untuk komunikasi dengan printer Niimbot
|
||||||
|
- Mendukung Web Bluetooth API
|
||||||
|
- Mendukung Web Serial API (USB)
|
||||||
|
- Encoding gambar ke format printer
|
||||||
|
|
||||||
|
### Browser Support
|
||||||
|
| Browser | Bluetooth | USB (Serial) |
|
||||||
|
|---------|-----------|--------------|
|
||||||
|
| Chrome/Edge (Desktop) | ✅ | ✅ |
|
||||||
|
| Chrome (Android) | ✅ | ❌ |
|
||||||
|
| Firefox | ❌ | ❌ |
|
||||||
|
| Safari | ❌ | ❌ |
|
||||||
|
|
||||||
|
**Rekomendasi:** Gunakan Chrome atau Edge versi terbaru
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Struktur File
|
||||||
|
|
||||||
|
```
|
||||||
|
Kasir/resources/js/
|
||||||
|
├── composables/
|
||||||
|
│ └── useNiimbotPrinter.js # Composable untuk koneksi & print
|
||||||
|
├── components/
|
||||||
|
│ ├── NiimbotConnector.vue # Modal untuk koneksi printer
|
||||||
|
│ └── BrankasList.vue # Modifikasi: tambah fitur print Niimbot
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Cara Kerja
|
||||||
|
|
||||||
|
### 1️⃣ Alur Koneksi Printer
|
||||||
|
|
||||||
|
```
|
||||||
|
User klik "Hubungkan Printer"
|
||||||
|
→ Modal NiimbotConnector muncul
|
||||||
|
→ Pilih metode: Bluetooth / USB
|
||||||
|
→ Browser munculkan dialog pairing
|
||||||
|
→ User pilih printer Niimbot
|
||||||
|
→ Koneksi terjalin
|
||||||
|
→ Fetch info printer
|
||||||
|
→ Status: "Terhubung"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2️⃣ Alur Print QR Code
|
||||||
|
|
||||||
|
```
|
||||||
|
User klik item di Brankas
|
||||||
|
→ Modal popup dengan QR Code
|
||||||
|
→ User klik "Cetak ke Niimbot"
|
||||||
|
→ Cek koneksi printer:
|
||||||
|
- Jika belum terhubung → tampilkan modal koneksi
|
||||||
|
- Jika sudah terhubung → lanjut
|
||||||
|
→ Generate canvas dengan QR + info item
|
||||||
|
→ Encode canvas ke format printer
|
||||||
|
→ Kirim ke printer via library
|
||||||
|
→ Status: "Mencetak... X%"
|
||||||
|
→ Selesai
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3️⃣ Komponen Kunci
|
||||||
|
|
||||||
|
#### `useNiimbotPrinter.js` (Composable)
|
||||||
|
```javascript
|
||||||
|
// State management
|
||||||
|
- printerClient // Instance NiimbotClient
|
||||||
|
- connectionState // 'disconnected' | 'connecting' | 'connected'
|
||||||
|
- connectedPrinterName // Nama printer yang terhubung
|
||||||
|
- printerInfo // Info printer (model, serial, dll)
|
||||||
|
- isPrinting // Status sedang print
|
||||||
|
- printProgress // Progress print (0-100)
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
- initClient(type) // Init client (bluetooth/serial)
|
||||||
|
- connect() // Hubungkan ke printer
|
||||||
|
- disconnect() // Putuskan koneksi
|
||||||
|
- printQRCode(dataUrl, options) // Print QR code image
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `NiimbotConnector.vue` (Component)
|
||||||
|
- Modal untuk koneksi/disconnect printer
|
||||||
|
- Pilih metode: Bluetooth atau USB
|
||||||
|
- Tampilkan status koneksi
|
||||||
|
- Tampilkan info printer detail
|
||||||
|
|
||||||
|
#### `BrankasList.vue` (Modified)
|
||||||
|
- Tombol "Hubungkan Printer" di header
|
||||||
|
- Tombol "Cetak ke Niimbot" di modal item
|
||||||
|
- Tombol "Browser" sebagai fallback
|
||||||
|
- Alert sukses/error
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Instalasi
|
||||||
|
|
||||||
|
### 1. Install Library
|
||||||
|
```bash
|
||||||
|
cd "c:\Data\Magang\Toko perhiasan\Kasir"
|
||||||
|
npm install @mmote/niimbluelib
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Files Sudah Dibuat
|
||||||
|
- ✅ `resources/js/composables/useNiimbotPrinter.js`
|
||||||
|
- ✅ `resources/js/components/NiimbotConnector.vue`
|
||||||
|
- ✅ `resources/js/components/BrankasList.vue` (modified)
|
||||||
|
|
||||||
|
### 3. Build Assets
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
# atau untuk development
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Cara Penggunaan
|
||||||
|
|
||||||
|
### A. Menghubungkan Printer
|
||||||
|
|
||||||
|
1. **Persiapan Printer:**
|
||||||
|
- Nyalakan printer Niimbot
|
||||||
|
- Pastikan kertas label sudah terpasang
|
||||||
|
- Untuk Bluetooth: Aktifkan mode pairing (biasanya tahan tombol power)
|
||||||
|
|
||||||
|
2. **Di Aplikasi:**
|
||||||
|
- Buka halaman Brankas
|
||||||
|
- Klik tombol "Hubungkan Printer" (di kanan atas)
|
||||||
|
- Pilih metode koneksi (Bluetooth/USB)
|
||||||
|
- Klik "Hubungkan Printer"
|
||||||
|
- Browser akan menampilkan dialog - pilih printer Niimbot Anda
|
||||||
|
- Tunggu hingga status berubah "Terhubung"
|
||||||
|
|
||||||
|
### B. Mencetak QR Code
|
||||||
|
|
||||||
|
1. **Pilih Item:**
|
||||||
|
- Klik item yang ingin dicetak QR-nya
|
||||||
|
- Modal akan muncul dengan QR Code
|
||||||
|
|
||||||
|
2. **Cetak:**
|
||||||
|
- Klik tombol "Cetak ke Niimbot"
|
||||||
|
- Jika printer belum terhubung, akan muncul peringatan
|
||||||
|
- Progress print akan ditampilkan (Mencetak... X%)
|
||||||
|
- Tunggu hingga selesai
|
||||||
|
|
||||||
|
3. **Alternatif:**
|
||||||
|
- Klik tombol "Browser" untuk print menggunakan printer biasa
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Konfigurasi Print
|
||||||
|
|
||||||
|
Di file `BrankasList.vue`, fungsi `printQR()`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await printQRCode(imageDataUrl, {
|
||||||
|
density: 3, // Kepadatan tinta (1-5, default: 3)
|
||||||
|
quantity: 1, // Jumlah cetakan (default: 1)
|
||||||
|
labelType: 1, // Tipe label:
|
||||||
|
// 1 = WithGaps (label dengan jarak)
|
||||||
|
// 2 = Continuous (tanpa jarak)
|
||||||
|
// 3 = WithHoles (dengan lubang)
|
||||||
|
printTaskName: 'D110' // Model printer (D110, B21, B1, dll)
|
||||||
|
// Auto-detect jika tidak cocok
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ukuran Label
|
||||||
|
Di fungsi `createQRLabelCanvas()`:
|
||||||
|
```javascript
|
||||||
|
const labelWidth = 384; // pixel (40mm @ 240dpi)
|
||||||
|
const labelHeight = 384; // pixel
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sesuaikan dengan ukuran label Anda:**
|
||||||
|
- 30mm x 30mm ≈ 288 x 288 px
|
||||||
|
- 40mm x 40mm ≈ 384 x 384 px
|
||||||
|
- 50mm x 30mm ≈ 480 x 288 px
|
||||||
|
|
||||||
|
Rumus: `mm × (dpi / 25.4)`
|
||||||
|
- DPI printer Niimbot umumnya: 203 atau 240
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Troubleshooting
|
||||||
|
|
||||||
|
### 1. "Browser tidak mendukung koneksi printer"
|
||||||
|
**Solusi:**
|
||||||
|
- Gunakan Chrome atau Edge versi terbaru
|
||||||
|
- Update browser ke versi terkini
|
||||||
|
- Pastikan menggunakan HTTPS (Web Bluetooth hanya jalan di HTTPS)
|
||||||
|
|
||||||
|
### 2. "Gagal terhubung ke printer"
|
||||||
|
**Solusi:**
|
||||||
|
- Pastikan printer sudah dinyalakan
|
||||||
|
- Pastikan Bluetooth/USB aktif
|
||||||
|
- Coba matikan dan nyalakan ulang printer
|
||||||
|
- Untuk Bluetooth: pastikan tidak paired ke device lain
|
||||||
|
- Coba refresh halaman dan ulangi koneksi
|
||||||
|
|
||||||
|
### 3. "Printer terhubung tapi tidak print"
|
||||||
|
**Solusi:**
|
||||||
|
- Periksa kertas label sudah terpasang dengan benar
|
||||||
|
- Coba disconnect dan connect ulang
|
||||||
|
- Periksa battery printer (untuk model portable)
|
||||||
|
- Cek ukuran canvas sesuai dengan ukuran label
|
||||||
|
|
||||||
|
### 4. "Print hasil blur/tidak jelas"
|
||||||
|
**Solusi:**
|
||||||
|
- Tingkatkan `density` (misal dari 3 ke 4)
|
||||||
|
- Pastikan threshold image sudah optimal
|
||||||
|
- Ukuran QR Code jangan terlalu kecil (min 150x150px)
|
||||||
|
|
||||||
|
### 5. "Error: printTaskName not compatible"
|
||||||
|
**Solusi:**
|
||||||
|
- Ganti `printTaskName` sesuai model printer:
|
||||||
|
- D110: `'D110'`
|
||||||
|
- B21: `'B21'`
|
||||||
|
- B1: `'B1'`
|
||||||
|
- Atau hapus parameter, biarkan auto-detect
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Debugging
|
||||||
|
|
||||||
|
### Enable Console Logs
|
||||||
|
Library sudah dilengkapi logging:
|
||||||
|
```javascript
|
||||||
|
// Di browser console akan muncul:
|
||||||
|
>> Packet sent: [hex bytes]
|
||||||
|
<< Packet received: [hex bytes]
|
||||||
|
Printer connected: { deviceName: "Niimbot-XXXX" }
|
||||||
|
Printer info fetched: { model: "D110", ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Print Canvas
|
||||||
|
Tambahkan debug preview sebelum print:
|
||||||
|
```javascript
|
||||||
|
// Di createQRLabelCanvas, sebelum resolve(canvas):
|
||||||
|
document.body.appendChild(canvas); // Tampilkan canvas di halaman
|
||||||
|
canvas.style.border = '1px solid red';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Referensi API
|
||||||
|
|
||||||
|
### useNiimbotPrinter Composable
|
||||||
|
|
||||||
|
#### State (Reactive)
|
||||||
|
```javascript
|
||||||
|
const {
|
||||||
|
printerClient, // NiimbotClient instance
|
||||||
|
connectionState, // 'disconnected' | 'connecting' | 'connected'
|
||||||
|
connectedPrinterName, // string
|
||||||
|
printerInfo, // object { model, serial, ... }
|
||||||
|
printerMeta, // object { densityMin, densityMax, ... }
|
||||||
|
heartbeatData, // object { powerLevel, ... }
|
||||||
|
isPrinting, // boolean
|
||||||
|
printProgress, // number (0-100)
|
||||||
|
|
||||||
|
// Computed
|
||||||
|
isConnected, // boolean
|
||||||
|
isDisconnected, // boolean
|
||||||
|
featureSupport, // { webBluetooth, webSerial, ... }
|
||||||
|
} = useNiimbotPrinter();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
```javascript
|
||||||
|
// Init client
|
||||||
|
initClient(type: 'bluetooth' | 'serial'): void
|
||||||
|
|
||||||
|
// Connect/Disconnect
|
||||||
|
connect(): Promise<void>
|
||||||
|
disconnect(): void
|
||||||
|
|
||||||
|
// Print
|
||||||
|
printQRCode(
|
||||||
|
imageDataUrl: string,
|
||||||
|
options?: {
|
||||||
|
density?: number, // 1-5
|
||||||
|
quantity?: number, // jumlah print
|
||||||
|
labelType?: number, // 1=WithGaps, 2=Continuous, 3=WithHoles
|
||||||
|
printTaskName?: string // 'D110', 'B21', dll
|
||||||
|
}
|
||||||
|
): Promise<{ success: boolean, message: string }>
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
loadImageToCanvas(dataUrl: string): Promise<HTMLCanvasElement>
|
||||||
|
applyThreshold(canvas: HTMLCanvasElement, threshold?: number): HTMLCanvasElement
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Customization
|
||||||
|
|
||||||
|
### Ubah Desain Label
|
||||||
|
Edit fungsi `createQRLabelCanvas()` di `BrankasList.vue`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Contoh: Tambah logo toko
|
||||||
|
const logo = new Image();
|
||||||
|
logo.src = '/path/to/logo.png';
|
||||||
|
logo.onload = () => {
|
||||||
|
ctx.drawImage(logo, 10, 10, 50, 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Contoh: Tambah border
|
||||||
|
ctx.strokeStyle = 'black';
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.strokeRect(5, 5, labelWidth - 10, labelHeight - 10);
|
||||||
|
|
||||||
|
// Contoh: Font custom
|
||||||
|
ctx.font = 'bold 20px "Courier New"';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tambah Barcode
|
||||||
|
Install library barcode:
|
||||||
|
```bash
|
||||||
|
npm install jsbarcode
|
||||||
|
```
|
||||||
|
|
||||||
|
Implementasi:
|
||||||
|
```javascript
|
||||||
|
import JsBarcode from 'jsbarcode';
|
||||||
|
|
||||||
|
const barcodeCanvas = document.createElement('canvas');
|
||||||
|
JsBarcode(barcodeCanvas, item.kode_item, {
|
||||||
|
format: 'CODE128',
|
||||||
|
width: 2,
|
||||||
|
height: 40,
|
||||||
|
});
|
||||||
|
ctx.drawImage(barcodeCanvas, x, y);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Catatan Penting
|
||||||
|
|
||||||
|
1. **HTTPS Required**: Web Bluetooth & Web Serial hanya bekerja di HTTPS (kecuali localhost)
|
||||||
|
2. **User Gesture**: Koneksi harus dipicu oleh user action (klik button), tidak bisa otomatis on load
|
||||||
|
3. **One Printer**: Satu browser session hanya bisa terhubung ke 1 printer
|
||||||
|
4. **Battery**: Printer portable akan disconnect otomatis jika battery rendah
|
||||||
|
5. **Label Size**: Sesuaikan ukuran canvas dengan ukuran label fisik untuk hasil optimal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Support
|
||||||
|
|
||||||
|
Jika ada masalah:
|
||||||
|
1. Periksa console browser (F12 → Console)
|
||||||
|
2. Periksa kompatibilitas browser
|
||||||
|
3. Periksa dokumentasi printer Niimbot Anda
|
||||||
|
4. Issue library: https://github.com/MultiMote/niimbluelib
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
Menggunakan library `@mmote/niimbluelib` yang bersifat open-source.
|
||||||
|
Pastikan mematuhi lisensi library saat deploy production.
|
||||||
192
README.md
192
README.md
@ -66,50 +66,7 @@ Semuah sistem Point of Sale (POS) yang dirancang khusus untuk kebutuhan toko per
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## <20> Docker Installation (Recommended)
|
## Installation
|
||||||
|
|
||||||
### Quick Start dengan Docker
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Clone repository
|
|
||||||
git clone https://git.abbauf.com/Magang-2025/Kasir.git
|
|
||||||
cd Kasir
|
|
||||||
|
|
||||||
# 2. Setup environment
|
|
||||||
copy .env.docker .env # Windows
|
|
||||||
# atau
|
|
||||||
cp .env.docker .env # Linux/Mac
|
|
||||||
|
|
||||||
# 3. Edit .env (PENTING: ganti password!)
|
|
||||||
notepad .env # Windows
|
|
||||||
nano .env # Linux/Mac
|
|
||||||
|
|
||||||
# 4. Deploy dengan satu command
|
|
||||||
docker-deploy.bat # Windows
|
|
||||||
# atau
|
|
||||||
./docker-deploy.sh # Linux/Mac
|
|
||||||
|
|
||||||
# 5. Akses aplikasi
|
|
||||||
# http://localhost
|
|
||||||
```
|
|
||||||
|
|
||||||
**Dokumentasi Docker Lengkap:**
|
|
||||||
- 📖 Quick Start: [README-DOCKER.md](README-DOCKER.md)
|
|
||||||
- 📚 Full Guide: [DOCKER-DEPLOYMENT.md](DOCKER-DEPLOYMENT.md)
|
|
||||||
- 📋 Checklist: [DEPLOYMENT-CHECKLIST.md](DEPLOYMENT-CHECKLIST.md)
|
|
||||||
- 🎯 Quick Reference: [QUICK-REFERENCE.txt](QUICK-REFERENCE.txt)
|
|
||||||
|
|
||||||
**Management Commands:**
|
|
||||||
```bash
|
|
||||||
docker-helper.bat status # Cek status containers
|
|
||||||
docker-helper.bat logs # Lihat logs
|
|
||||||
docker-helper.bat backup # Backup database
|
|
||||||
docker-helper.bat restart # Restart containers
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## <20>🔧 Manual Installation
|
|
||||||
|
|
||||||
### 1. Clone Repository
|
### 1. Clone Repository
|
||||||
|
|
||||||
@ -151,8 +108,6 @@ DB_USERNAME=root
|
|||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. Setup Database
|
### 5. Setup Database
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -177,6 +132,44 @@ php artisan storage:link
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Production Mode
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pastikan env production sudah tersedia
|
||||||
|
docker compose --env-file .env.production up -d --build
|
||||||
|
|
||||||
|
# Siapkan database
|
||||||
|
docker exec -it abbauf_kasir_app php artisan migrate --seed
|
||||||
|
|
||||||
|
# Atau import database secara manual
|
||||||
|
docker exec -i abbauf_kasir_db mysql -u kasir_user -pkasir_password kasir_db < ./storage/toko_emas.sql
|
||||||
|
|
||||||
|
# Periksa database (opsional)
|
||||||
|
docker exec -it abbauf_kasir_db bash
|
||||||
|
mysql -u kasir_user -pkasir_password kasir_db
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Print Label
|
||||||
|
|
||||||
|
- Install driver, ada pada folder `./driver/NiimbotPrinterDriverInstall_3.0.0.5.exe` untuk windows 64bit.
|
||||||
|
- Pilih `NIIMBOT B3S_P` pada saat install driver.
|
||||||
|
- Sambungkan printer ke komputer via USB.
|
||||||
|
- Nyalakan printer.
|
||||||
|
- Temukan kode qr yang akan diprint (misalnya pada halaman brankas)
|
||||||
|
- Klik tombol print pada halaman tersebut
|
||||||
|
- Pilih printer `NIIMBOT B3S_P` dan atur kertas ke ukuran kertas `40mm x 30mm`, margin `Default`, scale `Default`
|
||||||
|
- Klik print
|
||||||
|
|
||||||
|
### 9. Print Nota
|
||||||
|
|
||||||
|
- Pastikan printer terhubung dengan komputer via USB.
|
||||||
|
- Nyalakan printer.
|
||||||
|
- Install driver, ada pada folder `./driver/L120_x64_213UsHomeExportAsiaML.exe`.
|
||||||
|
- Lakukan transaksi penjualan pada aplikasi, atau pilih nota yang akan diprint di `Laporan > Riwayat transaksi`.
|
||||||
|
- Klik tombol print pada halaman tersebut
|
||||||
|
- Pilih ukuran kertas A4, margin `Minimum`, scale `95`
|
||||||
|
- Klik print
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🌐 Akses Aplikasi
|
## 🌐 Akses Aplikasi
|
||||||
@ -184,19 +177,18 @@ npm run dev
|
|||||||
Setelah instalasi berhasil, akses aplikasi melalui:
|
Setelah instalasi berhasil, akses aplikasi melalui:
|
||||||
|
|
||||||
- **URL**: http://localhost:8000
|
- **URL**: http://localhost:8000
|
||||||
- **Admin Panel**: http://localhost:8000/admin (jika tersedia)
|
|
||||||
|
|
||||||
### 👤 Default Login
|
### 👤 Default Login
|
||||||
|
|
||||||
**Owner Account:**
|
**Owner Account:**
|
||||||
|
|
||||||
- Email: `owner@tokoperhiasan.com`
|
- Username: `admin`
|
||||||
- Password: `password123`
|
- Password: `123123`
|
||||||
|
|
||||||
**Kasir Account:**
|
**Kasir Account:**
|
||||||
|
|
||||||
- Email: `kasir@tokoperhiasan.com`
|
- Username: `kasir`
|
||||||
- Password: `password123`
|
- Password: `123123`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -229,10 +221,6 @@ kasir-toko-perhiasan/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Oke, jadi penjelasan “📊 Fitur Database” yang kamu tulis nggak sepenuhnya sesuai sama struktur tabel yang udah kamu definisikan di awal. Ada tabel yang salah nama, ada juga relasi yang kebalik. Gue rapihin biar konsisten dengan skema yang udah kamu kasih:
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Fitur Database (Revisi)
|
## 📊 Fitur Database (Revisi)
|
||||||
|
|
||||||
### Tabel Utama
|
### Tabel Utama
|
||||||
@ -275,100 +263,6 @@ ItemTransaksi -> belongsTo -> Item
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Development
|
|
||||||
|
|
||||||
### Code Quality
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Management
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Reset database dan re-seed
|
|
||||||
php artisan migrate:fresh --seed
|
|
||||||
|
|
||||||
# Backup database
|
|
||||||
php artisan backup:run
|
|
||||||
|
|
||||||
# Generate model dengan migration
|
|
||||||
php artisan make:model ProductCategory -m
|
|
||||||
```
|
|
||||||
|
|
||||||
### Production Deployment
|
|
||||||
|
|
||||||
**Dengan Docker (Recommended):**
|
|
||||||
```bash
|
|
||||||
# 1. Setup .env untuk production
|
|
||||||
copy .env.docker .env
|
|
||||||
# Edit: APP_ENV=production, APP_DEBUG=false, set password kuat
|
|
||||||
|
|
||||||
# 2. Deploy
|
|
||||||
docker-deploy.bat
|
|
||||||
|
|
||||||
# 3. Monitor
|
|
||||||
docker-helper.bat status
|
|
||||||
docker-helper.bat logs
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manual Deployment:**
|
|
||||||
```bash
|
|
||||||
# Build assets
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# Optimize Laravel
|
|
||||||
php artisan config:cache
|
|
||||||
php artisan route:cache
|
|
||||||
php artisan view:cache
|
|
||||||
|
|
||||||
# Set permissions
|
|
||||||
chmod -R 775 storage bootstrap/cache
|
|
||||||
```
|
|
||||||
|
|
||||||
**Dokumentasi lengkap:** [DOCKER-DEPLOYMENT.md](DOCKER-DEPLOYMENT.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Update Aplikasi
|
|
||||||
|
|
||||||
**Dengan Docker:**
|
|
||||||
```bash
|
|
||||||
docker-helper.bat update # Otomatis: pull, rebuild, migrate, cache
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manual:**
|
|
||||||
```bash
|
|
||||||
git pull origin main
|
|
||||||
composer install --no-dev
|
|
||||||
npm install && npm run build
|
|
||||||
php artisan migrate --force
|
|
||||||
php artisan config:cache
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💾 Backup & Restore
|
|
||||||
|
|
||||||
**Backup Database (Docker):**
|
|
||||||
```bash
|
|
||||||
docker-helper.bat backup
|
|
||||||
# File tersimpan di: docker/mysql/backups/
|
|
||||||
```
|
|
||||||
|
|
||||||
**Restore Database (Docker):**
|
|
||||||
```bash
|
|
||||||
docker-helper.bat restore
|
|
||||||
# Pilih file backup yang tersedia
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manual Backup:**
|
|
||||||
```bash
|
|
||||||
mysqldump -u root -p toko_emas > backup.sql
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 License
|
## 📄 License
|
||||||
|
|
||||||
Lisensi dan kepemilikan atascource code adalah milik PT Teknologi Mulia Sejahtera Cemerlang.
|
Lisensi dan kepemilikan atascource code adalah milik PT Teknologi Mulia Sejahtera Cemerlang.
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class AuthController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// cari user berdasarkan nama
|
// cari user berdasarkan nama
|
||||||
$user = User::where('nama', $request->nama)->first();
|
$user = User::whereRaw('BINARY nama = ?', [$request->nama])->first();
|
||||||
|
|
||||||
if (!$user || !Hash::check($request->password, $user->password)) {
|
if (!$user || !Hash::check($request->password, $user->password)) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Item;
|
use App\Models\Item;
|
||||||
|
use App\Models\Nampan;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ItemController extends Controller
|
class ItemController extends Controller
|
||||||
@ -66,13 +67,20 @@ class ItemController extends Controller
|
|||||||
{
|
{
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'id_produk' => 'required|exists:produks,id',
|
'id_produk' => 'required|exists:produks,id',
|
||||||
'id_nampan' => 'nullable|exists:nampans,id'
|
'id_nampan' => 'required',
|
||||||
],[
|
],[
|
||||||
'id_produk' => 'Id produk tidak valid.',
|
'id_produk' => 'Id produk tidak valid.',
|
||||||
'id_nampan' => 'Id nampan tidak valid'
|
'id_nampan' => 'Id nampan tidak valid'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$item = Item::findOrFail($id)->update($validated);
|
if ($validated['id_nampan'] == 0) {
|
||||||
|
$item = Item::findOrFail($id)->update([
|
||||||
|
'id_produk' => $validated['id_produk'],
|
||||||
|
'id_nampan' => null
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$item = Item::findOrFail($id)->update($validated);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Item berhasil diubah',
|
'message' => 'Item berhasil diubah',
|
||||||
|
|||||||
@ -75,6 +75,7 @@ class TransaksiController extends Controller
|
|||||||
'kasir',
|
'kasir',
|
||||||
'sales',
|
'sales',
|
||||||
'itemTransaksi.produk',
|
'itemTransaksi.produk',
|
||||||
|
'itemTransaksi.produk.foto',
|
||||||
'itemTransaksi' => function ($query) {
|
'itemTransaksi' => function ($query) {
|
||||||
$query->orderBy('created_at', 'asc');
|
$query->orderBy('created_at', 'asc');
|
||||||
}
|
}
|
||||||
@ -103,7 +104,7 @@ class TransaksiController extends Controller
|
|||||||
'ongkos_bikin' => 'nullable|numeric|min:0',
|
'ongkos_bikin' => 'nullable|numeric|min:0',
|
||||||
'total_harga' => 'required|numeric',
|
'total_harga' => 'required|numeric',
|
||||||
'items' => 'required|array',
|
'items' => 'required|array',
|
||||||
'items.*.kode_item' => 'required|exists:items,id|numeric',
|
'items.*.kode_item' => 'required',
|
||||||
'items.*.harga_deal' => 'required|numeric',
|
'items.*.harga_deal' => 'required|numeric',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@ -23,24 +23,15 @@ class Item extends Model
|
|||||||
{
|
{
|
||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
static::creating(function ($item) {
|
static::created(function ($item) {
|
||||||
$prefix = 'TMJC';
|
if (!$item->kode_item || $item->kode_item === 'belum pak') {
|
||||||
$date = now()->format('Ymd');
|
$prefix = "TMJC";
|
||||||
|
$date = $item->created_at->format('Ymd');
|
||||||
|
$number = str_pad($item->id, 4, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
// Cari item terakhir yg dibuat hari ini
|
$item->kode_item = $prefix . $date . $number;
|
||||||
$lastItem = self::whereDate('created_at', now()->toDateString())
|
$item->save();
|
||||||
->orderBy('id', 'desc')
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$number = 1;
|
|
||||||
if ($lastItem && $lastItem->kode_item) {
|
|
||||||
// Ambil 4 digit terakhir dari kode_item
|
|
||||||
$lastNumber = intval(substr($lastItem->kode_item, -4));
|
|
||||||
$number = $lastNumber + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format: ITM202509090001
|
|
||||||
$item->kode_item = $prefix . $date . str_pad($number, 4, '0', STR_PAD_LEFT);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
bootstrap/cache/.gitignore
vendored
Normal file → Executable file
0
bootstrap/cache/.gitignore
vendored
Normal file → Executable file
@ -12,10 +12,10 @@ return new class extends Migration
|
|||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::table('items', function (Blueprint $table) {
|
Schema::table('items', function (Blueprint $table) {
|
||||||
$table->string('kode_item')->unique()->after('id');
|
$table->string('kode_item')->unique()->default('belum pak')->after('id');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::table('items', function (Blueprint $table) {
|
Schema::table('items', function (Blueprint $table) {
|
||||||
|
|||||||
@ -5,7 +5,6 @@ namespace Database\Seeders;
|
|||||||
use App\Models\Kategori;
|
use App\Models\Kategori;
|
||||||
use App\Models\Nampan;
|
use App\Models\Nampan;
|
||||||
use App\Models\Produk;
|
use App\Models\Produk;
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
class DataSeeder extends Seeder
|
class DataSeeder extends Seeder
|
||||||
@ -16,47 +15,60 @@ class DataSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
// Nampan
|
// Nampan
|
||||||
for ($i=0; $i < 30; $i++) {
|
for ($i = 0; $i < 30; $i++) {
|
||||||
if ($i != 12) {
|
if ($i != 12) {
|
||||||
Nampan::factory()->create([
|
Nampan::create([
|
||||||
'nama' => 'A' . ($i + 1)
|
'nama' => 'A' . ($i + 1),
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kategori
|
// Kategori
|
||||||
$kategoriList = ['Cincin', 'Gelang Rantai', 'Gelang Bulat', 'Kalung', 'Liontin', 'Anting', 'Giwang'];
|
$kategoriList = ['Cincin', 'Gelang Rantai', 'Gelang Bulat', 'Kalung', 'Liontin', 'Anting', 'Giwang'];
|
||||||
foreach ($kategoriList as $kategori) {
|
foreach ($kategoriList as $index => $kategori) {
|
||||||
Kategori::factory()->create([
|
Kategori::create([
|
||||||
'nama' => $kategori
|
'nama' => $kategori,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produk
|
// Produk 1
|
||||||
$produk1 = Produk::factory()->create([
|
$produk1 = Produk::create([
|
||||||
'nama'=>'Gelang serut daun shimmer mp (mas putih)',
|
'nama' => 'Gelang serut daun shimmer mp (mas putih)',
|
||||||
'id_kategori'=>Kategori::find(2),
|
'id_kategori' => Kategori::where('nama', 'Gelang Rantai')->first()->id,
|
||||||
'berat'=>1.4,
|
'berat' => 1.4,
|
||||||
'kadar'=>8,
|
'kadar' => 8,
|
||||||
'harga_per_gram'=>900000,
|
'harga_per_gram' => 900000,
|
||||||
'harga_jual'=>1260000,
|
'harga_jual' => 1260000,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
$produk1->foto()->create([
|
$produk1->foto()->create([
|
||||||
'id_produk'=>$produk1->id,
|
'id_produk' => $produk1->id,
|
||||||
'url'=>'https://i.imgur.com/eGYHzvw.jpeg'
|
'url' => 'https://i.imgur.com/eGYHzvw.jpeg',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$produk2 = Produk::factory()->create([
|
// Produk 2
|
||||||
'nama'=>'Gelang rantai 5 buah clover merah',
|
$produk2 = Produk::create([
|
||||||
'id_kategori'=>Kategori::find(2),
|
'nama' => 'Gelang rantai 5 buah clover merah',
|
||||||
'berat'=>3.6,
|
'id_kategori' => Kategori::where('nama', 'Gelang Rantai')->first()->id,
|
||||||
'kadar'=>8,
|
'berat' => 3.6,
|
||||||
'harga_per_gram'=>850000,
|
'kadar' => 8,
|
||||||
'harga_jual'=>3060000,
|
'harga_per_gram' => 850000,
|
||||||
|
'harga_jual' => 3060000,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
$produk2->foto()->create([
|
$produk2->foto()->create([
|
||||||
'id_produk'=>$produk2->id,
|
'id_produk' => $produk2->id,
|
||||||
'url'=>'https://i.imgur.com/UjQzYoE.jpeg'
|
'url' => 'https://i.imgur.com/UjQzYoE.jpeg',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@ use App\Models\Produk;
|
|||||||
use App\Models\Sales;
|
use App\Models\Sales;
|
||||||
use App\Models\Transaksi;
|
use App\Models\Transaksi;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
class DatabaseSeeder extends Seeder
|
class DatabaseSeeder extends Seeder
|
||||||
{
|
{
|
||||||
@ -19,24 +19,27 @@ class DatabaseSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
User::factory()->create([
|
// Create admin user
|
||||||
|
User::create([
|
||||||
'nama' => 'admin',
|
'nama' => 'admin',
|
||||||
'role' => 'owner',
|
'role' => 'owner',
|
||||||
'password' => bcrypt('123123'),
|
'password' => Hash::make('123123'),
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
]);
|
]);
|
||||||
User::factory()->create([
|
|
||||||
|
// Create kasir user
|
||||||
|
User::create([
|
||||||
'nama' => 'kasir',
|
'nama' => 'kasir',
|
||||||
'role' => 'kasir',
|
'role' => 'kasir',
|
||||||
'password' => bcrypt('123123'),
|
'password' => Hash::make('123123'),
|
||||||
]);
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
Sales::factory()->create([
|
|
||||||
'nama' => 'Umum',
|
|
||||||
'no_hp' => '-',
|
|
||||||
'alamat' => '-',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
// Call other seeders
|
||||||
$this->call(DataSeeder::class);
|
$this->call(DataSeeder::class);
|
||||||
// $this->call(DummySeeder::class);
|
$this->call(DummySeeder::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,176 +1,79 @@
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# ========================================
|
app:
|
||||||
# Laravel PHP-FPM Application
|
|
||||||
# ========================================
|
|
||||||
laravel:
|
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: abbauf_kasir_app
|
container_name: kasir-app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
working_dir: /var/www/html
|
working_dir: /var/www/html
|
||||||
volumes:
|
volumes:
|
||||||
# Mount storage untuk uploads dan logs (persistent)
|
- ./:/var/www/html
|
||||||
- ./storage:/var/www/html/storage
|
- ./docker/mysql/backups:/var/www/html/docker/mysql/backups
|
||||||
# Mount public build assets (read-only)
|
|
||||||
- ./public/build:/var/www/html/public/build:ro
|
|
||||||
environment:
|
|
||||||
# Application
|
|
||||||
APP_NAME: ${APP_NAME:-Abbauf-Kasir}
|
|
||||||
APP_ENV: ${APP_ENV:-production}
|
|
||||||
APP_KEY: ${APP_KEY}
|
|
||||||
APP_DEBUG: ${APP_DEBUG:-false}
|
|
||||||
APP_URL: ${APP_URL:-http://localhost}
|
|
||||||
|
|
||||||
# Database
|
|
||||||
DB_CONNECTION: mysql
|
|
||||||
DB_HOST: mysql
|
|
||||||
DB_PORT: 3306
|
|
||||||
DB_DATABASE: ${DB_DATABASE:-kasir_db}
|
|
||||||
DB_USERNAME: ${DB_USERNAME:-kasir_user}
|
|
||||||
DB_PASSWORD: ${DB_PASSWORD}
|
|
||||||
|
|
||||||
# Cache & Session
|
|
||||||
CACHE_STORE: redis
|
|
||||||
SESSION_DRIVER: redis
|
|
||||||
REDIS_HOST: redis
|
|
||||||
REDIS_PORT: 6379
|
|
||||||
|
|
||||||
# Queue
|
|
||||||
QUEUE_CONNECTION: redis
|
|
||||||
depends_on:
|
|
||||||
mysql:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
networks:
|
|
||||||
- kasir_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "php-fpm", "-t"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# Nginx Web Server
|
|
||||||
# ========================================
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: abbauf_kasir_nginx
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
ports:
|
||||||
- "${APP_PORT:-80}:80"
|
- "8000:80"
|
||||||
volumes:
|
environment:
|
||||||
# Nginx configuration
|
- APP_ENV=local
|
||||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
- APP_DEBUG=true
|
||||||
# Laravel public directory (untuk static assets)
|
- DB_HOST=mysql
|
||||||
- ./public:/var/www/html/public:ro
|
- DB_PORT=3306
|
||||||
# Storage symlink untuk file uploads
|
- DB_DATABASE=kasir_db
|
||||||
- ./storage/app/public:/var/www/html/public/storage:ro
|
- DB_USERNAME=kasir_user
|
||||||
|
- DB_PASSWORD=kasir_password
|
||||||
|
- REDIS_HOST=redis
|
||||||
|
- REDIS_PORT=6379
|
||||||
depends_on:
|
depends_on:
|
||||||
- laravel
|
- mysql
|
||||||
networks:
|
- redis
|
||||||
- kasir_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# MySQL Database
|
|
||||||
# ========================================
|
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql:8.4
|
image: mysql:5.7
|
||||||
container_name: abbauf_kasir_db
|
container_name: kasir-mysql
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root_secret_password}
|
MYSQL_DATABASE: kasir_db
|
||||||
MYSQL_DATABASE: ${DB_DATABASE:-kasir_db}
|
MYSQL_ROOT_PASSWORD: kasir_password
|
||||||
MYSQL_USER: ${DB_USERNAME:-kasir_user}
|
MYSQL_USER: kasir_user
|
||||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
MYSQL_PASSWORD: kasir_password
|
||||||
MYSQL_CHARACTER_SET_SERVER: utf8mb4
|
|
||||||
MYSQL_COLLATION_SERVER: utf8mb4_unicode_ci
|
|
||||||
ports:
|
|
||||||
- "${DB_PORT:-3306}:3306"
|
|
||||||
volumes:
|
volumes:
|
||||||
- mysql_data:/var/lib/mysql
|
- ./docker/mysql/mysql_data:/var/lib/mysql
|
||||||
# Optional: backup folder
|
|
||||||
- ./docker/mysql/backups:/backups
|
- ./docker/mysql/backups:/backups
|
||||||
networks:
|
ports:
|
||||||
- kasir_network
|
- "3308:3306"
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-root_secret_password}"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# Redis Cache & Session Store
|
|
||||||
# ========================================
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
container_name: abbauf_kasir_redis
|
container_name: kasir-redis
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "${REDIS_PORT:-6379}:6379"
|
- "6380:6379"
|
||||||
volumes:
|
volumes:
|
||||||
- redis_data:/data
|
- ./docker/redis/redis_data:/data
|
||||||
networks:
|
|
||||||
- kasir_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
command: redis-server --appendonly yes
|
|
||||||
|
|
||||||
# ========================================
|
# phpmyadmin:
|
||||||
# Queue Worker (Optional - untuk background jobs)
|
# image: phpmyadmin/phpmyadmin
|
||||||
# ========================================
|
# container_name: kasir-phpmyadmin
|
||||||
queue:
|
# restart: unless-stopped
|
||||||
build:
|
# environment:
|
||||||
context: .
|
# PMA_HOST: mysql
|
||||||
dockerfile: Dockerfile
|
# PMA_PORT: 3306
|
||||||
container_name: abbauf_kasir_queue
|
# PMA_USER: ${DB_USERNAME}
|
||||||
restart: unless-stopped
|
# PMA_PASSWORD: ${DB_PASSWORD}
|
||||||
working_dir: /var/www/html
|
# ports:
|
||||||
volumes:
|
# - "8080:80"
|
||||||
- ./storage:/var/www/html/storage
|
# depends_on:
|
||||||
environment:
|
# - mysql
|
||||||
APP_ENV: ${APP_ENV:-production}
|
# networks:
|
||||||
APP_KEY: ${APP_KEY}
|
# - kasir-network
|
||||||
DB_CONNECTION: mysql
|
|
||||||
DB_HOST: mysql
|
# volumes:
|
||||||
DB_PORT: 3306
|
# mysql_data:
|
||||||
DB_DATABASE: ${DB_DATABASE:-kasir_db}
|
# driver: local
|
||||||
DB_USERNAME: ${DB_USERNAME:-kasir_user}
|
# redis_data:
|
||||||
DB_PASSWORD: ${DB_PASSWORD}
|
# driver: local
|
||||||
REDIS_HOST: redis
|
|
||||||
QUEUE_CONNECTION: redis
|
|
||||||
depends_on:
|
|
||||||
- laravel
|
|
||||||
- redis
|
|
||||||
- mysql
|
|
||||||
networks:
|
|
||||||
- kasir_network
|
|
||||||
command: php artisan queue:work --tries=3 --timeout=90
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# Networks
|
|
||||||
# ========================================
|
|
||||||
networks:
|
networks:
|
||||||
kasir_network:
|
default:
|
||||||
driver: bridge
|
external: true
|
||||||
|
name: kasir_kasir_network
|
||||||
# ========================================
|
|
||||||
# Persistent Volumes
|
|
||||||
# ========================================
|
|
||||||
volumes:
|
|
||||||
mysql_data:
|
|
||||||
driver: local
|
|
||||||
redis_data:
|
|
||||||
driver: local
|
|
||||||
|
|||||||
12
docker/apache/000-default.conf
Normal file
12
docker/apache/000-default.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<VirtualHost *:80>
|
||||||
|
ServerAdmin webmaster@localhost
|
||||||
|
DocumentRoot /var/www/html/public
|
||||||
|
|
||||||
|
<Directory /var/www/html/public>
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||||
|
</VirtualHost>
|
||||||
2
docker/mysql/mysql_data/auto.cnf
Normal file
2
docker/mysql/mysql_data/auto.cnf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[auto]
|
||||||
|
server-uuid=79710a58-aeaa-11f0-a626-0242ac150002
|
||||||
BIN
docker/mysql/mysql_data/ca-key.pem
Normal file
BIN
docker/mysql/mysql_data/ca-key.pem
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/ca.pem
Normal file
BIN
docker/mysql/mysql_data/ca.pem
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/client-cert.pem
Normal file
BIN
docker/mysql/mysql_data/client-cert.pem
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/client-key.pem
Normal file
BIN
docker/mysql/mysql_data/client-key.pem
Normal file
Binary file not shown.
135
docker/mysql/mysql_data/ib_buffer_pool
Normal file
135
docker/mysql/mysql_data/ib_buffer_pool
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
10,69
|
||||||
|
10,29
|
||||||
|
10,93
|
||||||
|
10,2
|
||||||
|
10,3
|
||||||
|
11,13
|
||||||
|
11,4
|
||||||
|
11,8
|
||||||
|
11,17
|
||||||
|
11,15
|
||||||
|
11,16
|
||||||
|
11,7
|
||||||
|
11,2
|
||||||
|
11,3
|
||||||
|
9,5
|
||||||
|
9,2
|
||||||
|
9,3
|
||||||
|
8,7
|
||||||
|
8,5
|
||||||
|
8,2
|
||||||
|
8,3
|
||||||
|
0,457
|
||||||
|
12,2
|
||||||
|
12,1
|
||||||
|
12,3
|
||||||
|
20,2
|
||||||
|
20,1
|
||||||
|
20,3
|
||||||
|
19,2
|
||||||
|
19,1
|
||||||
|
19,3
|
||||||
|
18,1
|
||||||
|
18,3
|
||||||
|
14,1
|
||||||
|
11,28
|
||||||
|
11,27
|
||||||
|
11,26
|
||||||
|
14,5
|
||||||
|
11,25
|
||||||
|
11,24
|
||||||
|
14,3
|
||||||
|
13,1
|
||||||
|
11,23
|
||||||
|
11,22
|
||||||
|
13,3
|
||||||
|
11,21
|
||||||
|
11,20
|
||||||
|
11,1
|
||||||
|
11,19
|
||||||
|
10,303
|
||||||
|
10,302
|
||||||
|
10,301
|
||||||
|
10,300
|
||||||
|
10,299
|
||||||
|
10,298
|
||||||
|
10,297
|
||||||
|
10,296
|
||||||
|
2,2
|
||||||
|
10,295
|
||||||
|
2,1
|
||||||
|
10,294
|
||||||
|
10,293
|
||||||
|
10,292
|
||||||
|
2,3
|
||||||
|
10,291
|
||||||
|
10,290
|
||||||
|
10,289
|
||||||
|
10,288
|
||||||
|
10,287
|
||||||
|
10,286
|
||||||
|
10,285
|
||||||
|
10,284
|
||||||
|
10,283
|
||||||
|
10,282
|
||||||
|
10,281
|
||||||
|
10,280
|
||||||
|
10,279
|
||||||
|
10,278
|
||||||
|
10,277
|
||||||
|
10,276
|
||||||
|
10,275
|
||||||
|
10,274
|
||||||
|
10,273
|
||||||
|
10,272
|
||||||
|
10,271
|
||||||
|
10,270
|
||||||
|
10,269
|
||||||
|
10,268
|
||||||
|
10,267
|
||||||
|
10,266
|
||||||
|
10,265
|
||||||
|
10,264
|
||||||
|
10,263
|
||||||
|
10,262
|
||||||
|
10,261
|
||||||
|
10,260
|
||||||
|
10,259
|
||||||
|
10,258
|
||||||
|
10,257
|
||||||
|
10,256
|
||||||
|
10,255
|
||||||
|
10,254
|
||||||
|
10,253
|
||||||
|
10,252
|
||||||
|
10,251
|
||||||
|
10,250
|
||||||
|
10,249
|
||||||
|
10,248
|
||||||
|
10,247
|
||||||
|
10,246
|
||||||
|
10,245
|
||||||
|
10,244
|
||||||
|
10,243
|
||||||
|
10,242
|
||||||
|
10,241
|
||||||
|
10,240
|
||||||
|
10,239
|
||||||
|
10,238
|
||||||
|
10,237
|
||||||
|
10,236
|
||||||
|
10,235
|
||||||
|
10,234
|
||||||
|
10,233
|
||||||
|
10,232
|
||||||
|
10,231
|
||||||
|
10,230
|
||||||
|
10,229
|
||||||
|
10,228
|
||||||
|
10,227
|
||||||
|
10,226
|
||||||
|
10,225
|
||||||
|
10,224
|
||||||
|
10,223
|
||||||
|
10,222
|
||||||
|
10,221
|
||||||
BIN
docker/mysql/mysql_data/ib_logfile0
Normal file
BIN
docker/mysql/mysql_data/ib_logfile0
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/ib_logfile1
Normal file
BIN
docker/mysql/mysql_data/ib_logfile1
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/ibdata1
Normal file
BIN
docker/mysql/mysql_data/ibdata1
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/ibtmp1
Normal file
BIN
docker/mysql/mysql_data/ibtmp1
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/cache.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/cache.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/cache.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/cache.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/cache_locks.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/cache_locks.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/cache_locks.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/cache_locks.ibd
Normal file
Binary file not shown.
2
docker/mysql/mysql_data/kasir_db/db.opt
Normal file
2
docker/mysql/mysql_data/kasir_db/db.opt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
default-character-set=latin1
|
||||||
|
default-collation=latin1_swedish_ci
|
||||||
BIN
docker/mysql/mysql_data/kasir_db/failed_jobs.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/failed_jobs.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/failed_jobs.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/failed_jobs.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/foto_sementaras.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/foto_sementaras.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/foto_sementaras.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/foto_sementaras.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/fotos.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/fotos.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/fotos.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/fotos.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/item_transaksis.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/item_transaksis.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/item_transaksis.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/item_transaksis.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/items.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/items.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/items.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/items.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/job_batches.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/job_batches.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/job_batches.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/job_batches.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/jobs.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/jobs.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/jobs.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/jobs.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/kategoris.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/kategoris.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/kategoris.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/kategoris.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/migrations.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/migrations.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/migrations.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/migrations.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/nampans.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/nampans.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/nampans.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/nampans.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/password_reset_tokens.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/password_reset_tokens.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/password_reset_tokens.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/password_reset_tokens.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/personal_access_tokens.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/personal_access_tokens.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/personal_access_tokens.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/personal_access_tokens.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/produks.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/produks.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/produks.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/produks.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/sales.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/sales.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/sales.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/sales.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/sessions.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/sessions.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/sessions.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/sessions.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/transaksis.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/transaksis.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/transaksis.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/transaksis.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/users.frm
Normal file
BIN
docker/mysql/mysql_data/kasir_db/users.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/kasir_db/users.ibd
Normal file
BIN
docker/mysql/mysql_data/kasir_db/users.ibd
Normal file
Binary file not shown.
1
docker/mysql/mysql_data/mysql.sock
Symbolic link
1
docker/mysql/mysql_data/mysql.sock
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/var/run/mysqld/mysqld.sock
|
||||||
0
docker/mysql/mysql_data/mysql/columns_priv.MYD
Normal file
0
docker/mysql/mysql_data/mysql/columns_priv.MYD
Normal file
BIN
docker/mysql/mysql_data/mysql/columns_priv.MYI
Normal file
BIN
docker/mysql/mysql_data/mysql/columns_priv.MYI
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/columns_priv.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/columns_priv.frm
Normal file
Binary file not shown.
1
docker/mysql/mysql_data/mysql/db.MYD
Normal file
1
docker/mysql/mysql_data/mysql/db.MYD
Normal file
@ -0,0 +1 @@
|
|||||||
|
ÿlocalhost performance_schema mysql.session ÿlocalhost sys mysql.sys ÿ% kasir\_db kasir_user
|
||||||
BIN
docker/mysql/mysql_data/mysql/db.MYI
Normal file
BIN
docker/mysql/mysql_data/mysql/db.MYI
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/db.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/db.frm
Normal file
Binary file not shown.
2
docker/mysql/mysql_data/mysql/db.opt
Normal file
2
docker/mysql/mysql_data/mysql/db.opt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
default-character-set=latin1
|
||||||
|
default-collation=latin1_swedish_ci
|
||||||
BIN
docker/mysql/mysql_data/mysql/engine_cost.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/engine_cost.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/engine_cost.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/engine_cost.ibd
Normal file
Binary file not shown.
0
docker/mysql/mysql_data/mysql/event.MYD
Normal file
0
docker/mysql/mysql_data/mysql/event.MYD
Normal file
BIN
docker/mysql/mysql_data/mysql/event.MYI
Normal file
BIN
docker/mysql/mysql_data/mysql/event.MYI
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/event.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/event.frm
Normal file
Binary file not shown.
0
docker/mysql/mysql_data/mysql/func.MYD
Normal file
0
docker/mysql/mysql_data/mysql/func.MYD
Normal file
BIN
docker/mysql/mysql_data/mysql/func.MYI
Normal file
BIN
docker/mysql/mysql_data/mysql/func.MYI
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/func.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/func.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/general_log.CSM
Normal file
BIN
docker/mysql/mysql_data/mysql/general_log.CSM
Normal file
Binary file not shown.
0
docker/mysql/mysql_data/mysql/general_log.CSV
Normal file
0
docker/mysql/mysql_data/mysql/general_log.CSV
Normal file
|
|
BIN
docker/mysql/mysql_data/mysql/general_log.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/general_log.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/gtid_executed.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/gtid_executed.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/gtid_executed.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/gtid_executed.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_category.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/help_category.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_category.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/help_category.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_keyword.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/help_keyword.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_keyword.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/help_keyword.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_relation.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/help_relation.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_relation.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/help_relation.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_topic.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/help_topic.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/help_topic.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/help_topic.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/innodb_index_stats.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/innodb_index_stats.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/innodb_index_stats.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/innodb_index_stats.ibd
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/innodb_table_stats.frm
Normal file
BIN
docker/mysql/mysql_data/mysql/innodb_table_stats.frm
Normal file
Binary file not shown.
BIN
docker/mysql/mysql_data/mysql/innodb_table_stats.ibd
Normal file
BIN
docker/mysql/mysql_data/mysql/innodb_table_stats.ibd
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user