first commit

This commit is contained in:
2025-03-27 14:47:40 -06:00
commit ca72d4492a
19 changed files with 765 additions and 0 deletions

View File

@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('product_store_prices', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedMediumInteger('product_id')->index();
$table->unsignedSmallInteger('store_id')->index();
$table->decimal('price', 9, 2)->unsigned()->default(0);
$table->char('currency', 3)->charset('ascii')->collation('ascii_general_ci');
$table->boolean('is_discounted')->index();
$table->decimal('discount_price', 9, 2)->unsigned()->nullable();
$table->date('discount_start')->nullable();
$table->date('discount_end')->nullable();
// Auditoría
$table->timestamps();
// Relaciones
$table->foreign('product_id')->references('id')->on('products')->onUpdate('restrict')->onDelete('cascade');
$table->foreign('store_id')->references('id')->on('stores')->onUpdate('restrict')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('product_store_prices');
Schema::dropIfExists('product_property');
}
};

View File

@ -0,0 +1,76 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('price_lists', function (Blueprint $table) {
$table->smallIncrements('id');
$table->string('name')->index();
$table->unsignedTinyInteger('type')->index();
$table->char('c_currency', 3)->charset('ascii')->collation('ascii_general_ci')->nullable(); // Moneda
$table->timestamps();
$table->unsignedTinyInteger('status');
});
Schema::create('product_prices', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedMediumInteger('product_id')->index(); // products.id
$table->unsignedSmallInteger('pricelist_id')->index(); // price_lists.id
$table->decimal('unit_price', 13, 6)->unsigned()->nullable(); // Precio unitario
$table->decimal('discount_percentage', 5, 2)->unsigned()->nullable(); // Descuento %
$table->decimal('final_price', 13, 6)->unsigned()->nullable(); // Precio después del descuento
$table->decimal('taxes_transferred', 13, 6)->unsigned()->nullable(); // Impuestos trasladados
$table->decimal('taxes_retained', 13, 6)->unsigned()->nullable(); // Impuestos retenidos
$table->decimal('total_amount', 13, 6)->unsigned()->nullable(); // Importe final
$table->date('valid_from')->nullable(); // Fecha de inicio de validez
$table->date('valid_to')->nullable(); // Fecha de fin de validez
$table->unsignedInteger('min_quantity')->nullable(); // Cantidad mínima para este precio
$table->unsignedInteger('max_quantity')->nullable(); // Cantidad máxima para este precio
// Auditoría
$table->timestamps();
// Índices y restricciones
$table->unique(['product_id', 'pricelist_id', 'valid_from', 'valid_to', 'min_quantity', 'max_quantity'])->name('product_pricelist_valid_from_to_min_max_quantity');
// Relaciones
$table->foreign('product_id')
->references('id')
->on('products')
->onUpdate('restrict')
->onDelete('cascade');
$table->foreign('pricelist_id')
->references('id')
->on('price_lists')
->onUpdate('restrict')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('price_lists');
Schema::dropIfExists('product_prices');
}
};

View File

@ -0,0 +1,192 @@
<?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');
}
};

View File

@ -0,0 +1,62 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('stores', function (Blueprint $table) {
// Series de documentos
$table->string('serie_ordenes_compra', 50)->nullable()->after('domicilio_fiscal');
$table->string('serie_compras', 50)->nullable()->after('serie_ordenes_compra');
$table->string('serie_gastos', 50)->nullable()->after('serie_compras');
$table->string('serie_cotizaciones', 50)->nullable()->after('serie_gastos');
$table->string('serie_ventas', 50)->nullable()->after('serie_cotizaciones');
$table->string('serie_remisiones', 50)->nullable()->after('serie_ventas');
$table->string('serie_notas_credito', 50)->nullable()->after('serie_remisiones');
$table->string('serie_pagos', 50)->nullable()->after('serie_notas_credito');
$table->string('serie_traspasos', 50)->nullable()->after('serie_pagos');
$table->string('serie_ajustes_inventario', 50)->nullable()->after('serie_traspasos');
// Configuración del ticket
$table->unsignedTinyInteger('ticket_digital')->nullable()->after('serie_ajustes_inventario');
$table->boolean('ticket_digital_show_customer')->nullable()->after('ticket_digital');
$table->boolean('ticket_digital_show_email')->nullable()->after('ticket_digital_show_customer');
$table->boolean('ticket_digital_show_address')->nullable()->after('ticket_digital_show_email');
$table->boolean('ticket_digital_show_unit_price')->nullable()->after('ticket_digital_show_address');
$table->boolean('ticket_digital_show_taxes')->nullable()->after('ticket_digital_show_unit_price');
$table->boolean('ticket_digital_show_import')->nullable()->after('ticket_digital_show_taxes');
$table->unsignedTinyInteger('ticket_printed')->nullable()->after('ticket_digital_show_import');
$table->boolean('ticket_show_customer')->nullable()->after('ticket_printed');
$table->boolean('ticket_show_email')->nullable()->after('ticket_show_customer');
$table->boolean('ticket_show_address')->nullable()->after('ticket_show_email');
$table->boolean('ticket_show_unit_price')->nullable()->after('ticket_show_address');
$table->boolean('ticket_show_taxes')->nullable()->after('ticket_show_unit_price');
$table->boolean('ticket_show_import')->nullable()->after('ticket_show_taxes');
$table->string('ticket_image_path', 255)->nullable()->after('ticket_show_import');
$table->mediumText('ticket_image_base64', 255)->nullable()->after('ticket_image_path');
$table->string('ticket_header', 255)->nullable()->after('ticket_image_base64');
$table->string('ticket_footer', 255)->nullable()->after('ticket_header');
$table->string('ticket_footer_2', 255)->nullable()->after('ticket_footer');
$table->boolean('ticket_enable_cash_register')->nullable()->after('ticket_footer_2');
$table->unsignedTinyInteger('ticket_cash_register')->nullable()->after('ticket_enable_cash_register');
$table->boolean('ticket_enable_warehouse')->nullable()->after('ticket_cash_register');
$table->unsignedTinyInteger('ticket_warehouse')->nullable()->after('ticket_enable_warehouse');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
}
};