diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php new file mode 100644 index 0000000..c778be8 --- /dev/null +++ b/app/Http/Controllers/CategoryController.php @@ -0,0 +1,18 @@ + + * + * @version 1.0.0 + */ +class CategoryController extends Controller +{ + // +} diff --git a/app/Http/Controllers/InventoryController.php b/app/Http/Controllers/InventoryController.php new file mode 100644 index 0000000..5650b39 --- /dev/null +++ b/app/Http/Controllers/InventoryController.php @@ -0,0 +1,18 @@ + + * + * @version 1.0.0 + */ +class InventoryController extends Controller +{ + // +} diff --git a/app/Http/Controllers/PriceController.php b/app/Http/Controllers/PriceController.php new file mode 100644 index 0000000..1d7413f --- /dev/null +++ b/app/Http/Controllers/PriceController.php @@ -0,0 +1,18 @@ + + * + * @version 1.0.0 + */ +class PriceController extends Controller +{ + // +} diff --git a/app/Http/Controllers/SaleController.php b/app/Http/Controllers/SaleController.php new file mode 100644 index 0000000..7e99e5b --- /dev/null +++ b/app/Http/Controllers/SaleController.php @@ -0,0 +1,18 @@ + + * + * @version 1.0.0 + */ +class SaleController extends Controller +{ + // +} diff --git a/app/Http/Controllers/SaleDetailController.php b/app/Http/Controllers/SaleDetailController.php new file mode 100644 index 0000000..ccdb732 --- /dev/null +++ b/app/Http/Controllers/SaleDetailController.php @@ -0,0 +1,18 @@ + + * + * @version 1.0.0 + */ +class SaleDetailController extends Controller +{ + // +} diff --git a/app/Models/Category.php b/app/Models/Category.php new file mode 100644 index 0000000..51f9bb1 --- /dev/null +++ b/app/Models/Category.php @@ -0,0 +1,27 @@ + + * + * @version 1.0.0 + */ +class Category extends Model +{ + protected $fillable = [ + 'name', + 'description', + 'is_active', + ]; + + protected $casts = [ + 'is_active' => 'boolean', + ]; +} diff --git a/app/Models/Inventory.php b/app/Models/Inventory.php new file mode 100644 index 0000000..a29630e --- /dev/null +++ b/app/Models/Inventory.php @@ -0,0 +1,29 @@ + + * + * @version 1.0.0 + */ +class Inventory extends Model +{ + protected $fillable = [ + 'category_id', + 'name', + 'sku', + 'stock', + 'is_active', + ]; + + protected $casts = [ + 'is_active' => 'boolean', + ]; +} diff --git a/app/Models/Price.php b/app/Models/Price.php new file mode 100644 index 0000000..b807606 --- /dev/null +++ b/app/Models/Price.php @@ -0,0 +1,30 @@ + + * + * @version 1.0.0 + */ +class Price extends Model +{ + protected $fillable = [ + 'inventory_id', + 'cost', + 'retail_price', + 'tax', + ]; + + protected $casts = [ + 'cost' => 'decimal:2', + 'retail_price' => 'decimal:2', + 'tax' => 'decimal:2', + ]; +} diff --git a/app/Models/Sale.php b/app/Models/Sale.php new file mode 100644 index 0000000..094dc40 --- /dev/null +++ b/app/Models/Sale.php @@ -0,0 +1,33 @@ + + * + * @version 1.0.0 + */ +class Sale extends Model +{ + protected $fillable = [ + 'user_id', + 'invoice_number', + 'subtotal', + 'tax', + 'total', + 'payment_method', + 'status', + ]; + + protected $casts = [ + 'subtotal' => 'decimal:2', + 'tax' => 'decimal:2', + 'total' => 'decimal:2', + ]; +} diff --git a/app/Models/SaleDetail.php b/app/Models/SaleDetail.php new file mode 100644 index 0000000..83fbe73 --- /dev/null +++ b/app/Models/SaleDetail.php @@ -0,0 +1,31 @@ + + * + * @version 1.0.0 + */ +class SaleDetail extends Model +{ + protected $fillable = [ + 'sale_id', + 'inventory_id', + 'product_name', + 'quantity', + 'unit_price', + 'subtotal', + ]; + + protected $casts = [ + 'unit_price' => 'decimal:2', + 'subtotal' => 'decimal:2', + ]; +} diff --git a/database/migrations/2025_12_30_140000_create_categories_table.php b/database/migrations/2025_12_30_140000_create_categories_table.php new file mode 100644 index 0000000..8e6d958 --- /dev/null +++ b/database/migrations/2025_12_30_140000_create_categories_table.php @@ -0,0 +1,31 @@ +id(); + $table->string('name'); + $table->text('description')->nullable(); + $table->boolean('is_active')->default(true); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('categories'); + } +}; diff --git a/database/migrations/2025_12_30_140233_create_inventories_table.php b/database/migrations/2025_12_30_140233_create_inventories_table.php new file mode 100644 index 0000000..655e684 --- /dev/null +++ b/database/migrations/2025_12_30_140233_create_inventories_table.php @@ -0,0 +1,33 @@ +id(); + $table->foreignId('category_id')->constrained()->onDelete('cascade'); + $table->string('name'); + $table->string('sku')->unique(); + $table->integer('stock')->default(0); + $table->boolean('is_active')->default(true); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('inventories'); + } +}; diff --git a/database/migrations/2025_12_30_140534_create_prices_table.php b/database/migrations/2025_12_30_140534_create_prices_table.php new file mode 100644 index 0000000..e877d72 --- /dev/null +++ b/database/migrations/2025_12_30_140534_create_prices_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('inventory_id')->constrained()->onDelete('cascade'); + $table->decimal('cost', 10, 2); + $table->decimal('retail_price', 10, 2); + $table->decimal('tax', 5, 2); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('prices'); + } +}; diff --git a/database/migrations/2025_12_30_151443_create_sales_table.php b/database/migrations/2025_12_30_151443_create_sales_table.php new file mode 100644 index 0000000..12648b5 --- /dev/null +++ b/database/migrations/2025_12_30_151443_create_sales_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('invoice_number')->unique(); + $table->decimal('subtotal', 10, 2); + $table->decimal('tax', 10, 2); + $table->decimal('total', 10, 2); + $table->enum('payment_method', ['cash', 'credit_card', 'debit_card']); + $table->enum('status', ['pending', 'completed', 'cancelled'])->default('pending'); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sales'); + } +}; diff --git a/database/migrations/2025_12_30_151510_create_sale_details_table.php b/database/migrations/2025_12_30_151510_create_sale_details_table.php new file mode 100644 index 0000000..4d5d331 --- /dev/null +++ b/database/migrations/2025_12_30_151510_create_sale_details_table.php @@ -0,0 +1,33 @@ +id(); + $table->foreignId('sale_id')->constrained()->onDelete('cascade'); + $table->foreignId('inventory_id')->constrained()->onDelete('cascade'); + $table->string('product_name'); + $table->integer('quantity'); + $table->decimal('unit_price', 10, 2); + $table->decimal('subtotal', 10, 2); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sale_details'); + } +}; diff --git a/docker-compose.yml b/docker-compose.yml index 9c76aa0..2540720 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,16 +3,20 @@ services: build: context: . dockerfile: dockerfile + args: + USER_ID: 1000 + GROUP_ID: 1000 working_dir: /var/www/pdv.backend + user: "1000:1000" environment: - DB_HOST=mysql - DB_USERNAME=${DB_USERNAME} - DB_PASSWORD=${DB_PASSWORD} - DB_DATABASE=${DB_DATABASE} - DB_PORT=${DB_PORT} + - HOME=/tmp volumes: - ./:/var/www/pdv.backend - - /var/www/pdv.backend/vendor networks: - pdv-network depends_on: diff --git a/dockerfile b/dockerfile index 380cb05..efb022a 100644 --- a/dockerfile +++ b/dockerfile @@ -34,6 +34,11 @@ RUN mkdir -p storage/app/keys storage/logs bootstrap/cache RUN chown -R www-data:www-data /var/www/pdv.backend/storage /var/www/pdv.backend/bootstrap/cache RUN chmod -R 775 /var/www/pdv.backend/storage /var/www/pdv.backend/bootstrap/cache +# Configurar usuario para evitar problemas de permisos +ARG USER_ID=1000 +ARG GROUP_ID=1000 +RUN usermod -u ${USER_ID} www-data && groupmod -g ${GROUP_ID} www-data + EXPOSE 9000 ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh index 607b6b8..8c8edda 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,13 +1,12 @@ #!/bin/bash set -e +# Configurar Git sin necesidad de permisos globales +export GIT_CONFIG_GLOBAL=/tmp/.gitconfig git config --global --add safe.directory /var/www/pdv.backend echo "=== Iniciando entrypoint DESARROLLO ===" -chown -R www-data:www-data /var/www/pdv.backend/storage /var/www/pdv.backend/bootstrap/cache -chmod -R 775 /var/www/pdv.backend/storage /var/www/pdv.backend/bootstrap/cache - # Variables desde Docker environment DB_HOST=${DB_HOST:-mysql} DB_USERNAME=${DB_USERNAME:-root} @@ -82,7 +81,6 @@ fi # Establecer permisos correctos para las claves chmod 600 storage/app/keys/oauth-private.key chmod 644 storage/app/keys/oauth-public.key -chown www-data:www-data storage/app/keys/oauth-*.key echo "✓ Claves de Passport verificadas"