laravel-vuexy-pos/database/migrations/2024_12_19_112507_create_pos_tables.php
2025-03-27 14:47:40 -06:00

193 lines
7.8 KiB
PHP

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('sales_transactions', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedSmallInteger('store_id')->index();
$table->unsignedTinyInteger('document_type')->index(); // Tipo de documento (venta, cotización, Remisión, Nota de credito)
$table->unsignedMediumInteger('document_id')->nullable(); // UID específico por tienda
$table->unsignedMediumInteger('seller_id')->index(); // ID del vendedor
$table->unsignedMediumInteger('customer_id')->nullable(); // ID del cliente
$table->unsignedMediumInteger('customer_tax_id')->nullable(); // ID del cliente para impuestos
$table->decimal('quantity', 13, 6)->unsigned()->nullable();
$table->datetime('transaction_date')->index(); // Fecha de la transacción
$table->date('date_to_pay')->nullable()->index();
$table->char('moneda', 3)->index();
$table->decimal('tipo_de_cambio', 12, 4)->nullable(); // Sin unsigned para permitir valores negativos si es necesario
$table->char('c_uso_cfdi', 4)->charset('ascii')->collation('ascii_general_ci')->nullable()->index();
$table->char('c_metodo_pago', 3)->nullable()->index(); // c_metodo_pago.c_metodo_pago
$table->string('condiciones_de_pago', 512)->nullable()->index();
$table->decimal('subtotal', 9, 2)->unsigned()->default(0);
$table->decimal('impuestos_trasladados', 9, 2)->unsigned()->default(0);
$table->decimal('impuestos_retenidos', 9, 2)->unsigned()->default(0);
$table->decimal('amount', 9, 2)->unsigned()->default(0);
$table->decimal('paid_amount', 9, 2)->unsigned()->default(0);
$table->mediumText('document_notes')->nullable(); // Notas adicionales
$table->json('internal_notes')->nullable();
$table->boolean('should_send_ticket')->nullable(); //
$table->boolean('should_send_invoice')->nullable(); //
$table->boolean('print_ticket')->nullable();
$table->boolean('print_invoice')->nullable();
$table->boolean('print_payment_peceipt')->nullable(); //
$table->unsignedTinyInteger('transaction_status')->index(); // Estatus de la orden ('pending', 'approved', 'received', 'cancelled')
$table->unsignedTinyInteger('payment_status')->nullable()->index();
$table->unsignedTinyInteger('billing_status')->nullable()->index();
$table->unsignedTinyInteger('delivery_status')->nullable()->index(); // 'pending', 'processing', 'shipped', 'delivered', 'canceled', no requiere envio, cliente recoge
$table->softDeletes();
$table->timestamps();
$table->index(['store_id', 'document_type', 'document_id']);
$table->index(['store_id', 'document_type', 'date_to_pay']);
$table->index(['store_id', 'document_type', 'transaction_date'])->name('purchase_transactions_store_document_date_index');
$table->index(['store_id', 'document_type', 'transaction_date', 'seller_id'])->name('purchase_transactions_store_document_date_seller_index');
$table->index(['store_id', 'document_type', 'transaction_date', 'customer_id'])->name('purchase_transactions_store_document_date_customer_index');
$table->index(['store_id', 'document_type', 'transaction_date', 'customer_tax_id'])->name('purchase_transactions_store_document_date_customer_tax_index');
$table->foreign('store_id')
->references('id')
->on('stores')
->onDelete('restrict');
$table->foreign('seller_id')
->references('id')
->on('users')
->onDelete('restrict');
$table->foreign('customer_id')
->references('id')
->on('users')
->onDelete('restrict');
$table->foreign('customer_tax_id')
->references('id')
->on('users')
->onDelete('restrict');
$table->foreign('c_uso_cfdi')
->references('c_uso_cfdi')
->on('sat_uso_cfdi')
->onDelete('restrict');
});
Schema::create('sales_transactions_concepts', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedMediumInteger('sales_transaction_id')->index(); // sales.id
$table->decimal('cantidad', 13, 6)->unsigned();
$table->unsignedMediumInteger('product_id')->index(); // products.id
$table->string('no_identificacion', 100)->nullable()->index();
$table->string('descripcion');
$table->string('c_clave_unidad', 3)->nullable()->index(); // sat_clave_unidad.c_clave_unidad
$table->decimal('cost', 13, 6)->unsigned()->default(0);
$table->mediumText('observations')->nullable();
$table->decimal('valorunitario', 13, 6)->unsigned();
$table->decimal('importe', 13, 6)->unsigned();
$table->unsignedTinyInteger('c_objeto_imp')->nullable()->index(); // sat_objeto_imp.c_objeto_imp
$table->json('impuestos')->nullable();
$table->decimal('impuestos_trasladados', 13, 6)->unsigned()->default(0);
$table->decimal('impuestos_retenidos', 13, 6)->unsigned()->default(0);
// Indices
$table->foreign('sales_transaction_id')
->references('id')
->on('sales_transactions')
->onUpdate('restrict')
->onDelete('cascade');
$table->foreign('product_id')
->references('id')
->on('products')
->onUpdate('restrict')
->onDelete('restrict');
$table->foreign('c_clave_unidad')
->references('c_clave_unidad')
->on('sat_clave_unidad')
->onUpdate('restrict')
->onDelete('restrict');
});
Schema::table('users', function (Blueprint $table) {
$table->unsignedSmallInteger('pricelist_id') // dropdown_lists.id
->after('c_uso_cfdi')
->nullable();
$table->unsignedTinyInteger('enable_credit')
->after('pricelist_id')
->nullable();
$table->unsignedSmallInteger('credit_days')
->after('enable_credit')
->nullable();
$table->decimal('credit_limit', 14, 2)
->after('credit_days')
->nullable();
// Indices
$table->foreign('pricelist_id')
->references('id')
->on('price_lists')
->onUpdate('restrict')
->onDelete('restrict');
});
/*
DB::unprepared('CREATE TRIGGER prevent_pricelist_delete
BEFORE DELETE ON dropdown_lists
FOR EACH ROW
BEGIN
IF EXISTS (SELECT 1 FROM users WHERE pricelist_id = OLD.id) THEN
SIGNAL SQLSTATE "45000" SET MESSAGE_TEXT = "No se puede eliminar la lista de precios porque está en uso por un usuario";
END IF;
END;');
*/
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('sales_transactions');
DB::unprepared('DROP TRIGGER IF EXISTS sales_transactions_before_insert');
Schema::dropIfExists('sales_transactions_concepts');
DB::unprepared('DROP TRIGGER IF EXISTS prevent_pricelist_delete');
}
};