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'); } };