¿Cómo puedo resolver la restricción de la clave del extranjero 'sqlstate [23000]: violación de la restricción de integridad:

magento.stackexchange https://magento.stackexchange.com/questions/10937

Pregunta

He estado tratando de crear un módulo simple para habilitar los comentarios de pedido al finalizar la compra. Sé que hay una serie de extensiones gratuitas que hacen esto, pero necesito agregar funcionalidad adicional, así que decidí escribirla desde cero.

En el momento en que guardo el comentario usando un observador, obtengo una alerta de JavaScript y busco en el archivo de excepción.

exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`musicstore`.`checkout_comments`, CONSTRAINT `FK_CHECKOUT_COMMENTS_ORDER_ID_SALES_FLAT_ORDER_ENTITY_ID` FOREIGN KEY (`order_id`) REFERENCES `sales_flat_order` (`entity_id`) ON DELETE CASCADE O)'

Aquí está mi script install-0.0.1

<?php

/* @var $installer Mage_Core_Model_Resource_Setup */
$installer = $this;

$installer->startSetup();

$table = $installer->getConnection()
    ->newTable($installer->getTable('checkoutcomments/comments_table'))
    ->addColumn('comment_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'identity' => true,
        'unsigned' => true,
        'nullable' => false,
        'primary'  => true,
    ),  'Comment ID')
    ->addColumn('order_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned' => true,
        'nullable' => false,
    ),  'Real Order ID')
    ->addColumn('comment', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array(
    ), 'Comment')
    ->addForeignKey(
        $installer->getFkName(
        'checkoutcomments/comments_table',
        'order_id',
        'sales/order',
        'entity_id'
    ),
        'order_id', $installer->getTable('sales/order'), 'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
        ->setComment('Checkout Comments');
$installer->getConnection()->createTable($table);
$installer->endSetup();

Tabla de comprobación_comments:

mysql> describe checkout_comments;                                  
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| comment_id | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| order_id   | int(10) unsigned | NO   | MUL | NULL    |                |
| comment    | text             | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
3 rows in set (0.07 sec)

config.xml

<events>
    <controller_action_predispatch_checkout_onepage_saveOrder>
        <observers>
            <save_checkout_comments>
                <class>checkoutcomments/observer</class>
                <method>prepareCheckoutComment</method>
            </save_checkout_comments>
        </observers>
    </controller_action_predispatch_checkout_onepage_saveOrder>

    <sales_order_place_after>
        <observers>
            <save_checkout_comments>
                <class>checkoutcomments/observer</class>
                <method>saveCheckoutComment</method>
            </save_checkout_comments>
        </observers>
    </sales_order_place_after>
</events>

Observador.php

public function prepareCheckoutComment($observer){

    $message = $observer->getControllerAction()
                        ->getRequest()
                        ->getPost('checkoutcomments');
    Mage::getSingleton('core/session')->setCheckoutComment($message);
}

public function saveCheckoutComment($observer){

    $order = $observer->getOrder();
    $message = Mage::getSingleton('core/session')->getCheckoutComment(true);

    if (!$order || empty ($message)) {
        return;
    }

    $commentModel = Mage::getModel('checkoutcomments/comment');
    $commentModel->setOdrderId($order->getId())
                 ->setComment($message)
                 ->save();
}

He probado con diferentes eventos

  <sales_model_service_quote_submit_after>
        <observers>
            <save_checkout_comments>
                <class>checkoutcomments/observer</class>
                <method>saveCheckoutComment</method>
            </save_checkout_comments>
        </observers>
    </sales_model_service_quote_submit_after>

    <sales_model_service_quote_submit_success>
        <observers>
            <save_checkout_comments>
                <class>checkoutcomments/observer</class>
                <method>saveCheckoutComment</method>
            </save_checkout_comments>
        </observers>
    </sales_model_service_quote_submit_success>

    <checkout_submit_all_after>
        <observers>
            <save_checkout_comments>
                <class>checkoutcomments/observer</class>
                <method>saveCheckoutComment</method>
            </save_checkout_comments>
        </observers>
    </checkout_submit_all_after>

Matriz de depuración

2013-11-20T19:28:08+00:00 DEBUG (7): Array
(
    [increment_id] => 100000043
    [store_id] => 1
    [quote_id] => 55
    [quote (Mage_Sales_Model_Quote)] => Array
        (
            [entity_id] => 55
            [store_id] => 1
            [created_at] => 2013-11-20 19:21:20
            [updated_at] => 2013-11-20 19:28:08
            [is_active] => 1
            [is_virtual] => 0
            [is_multi_shipping] => 0
            [items_count] => 1
            [items_qty] => 1
            [orig_order_id] => 0
            [store_to_base_rate] => 1
            [store_to_quote_rate] => 1
            [base_to_global_rate] => 1
            [base_to_quote_rate] => 1
            [global_currency_code] => GBP
            [base_currency_code] => GBP
            [store_currency_code] => GBP
            [quote_currency_code] => GBP
            [grand_total] => 20
            [base_grand_total] => 20
            [customer_id] => 2
            [customer_tax_class_id] => 3
            [customer_group_id] => 1
            [customer_email] => *************
            [customer_firstname] => *************
            [customer_lastname] => ************
            [customer_note_notify] => 1
            [customer_is_guest] => 0
            [remote_ip] => ::1
            [applied_rule_ids] => 
            [reserved_order_id] => 100000043
            [subtotal] => 15
            [base_subtotal] => 15
            [subtotal_with_discount] => 15
            [base_subtotal_with_discount] => 15
            [is_changed] => 1
            [trigger_recollect] => 0
            [is_persistent] => 0
            [virtual_items_qty] => 0
            [taxes_for_items] => Array
                (
                )

            [can_apply_msrp] => 
            [totals_collected_flag] => 1
            [inventory_processed] => 1
        )

    [customer (Mage_Customer_Model_Customer)] => Array
        (
            [website_id] => 1
            [entity_id] => 2
            [entity_type_id] => 1
            [attribute_set_id] => 0
            [email] => ***************
            [group_id] => 1
            [store_id] => 1
            [created_at] => 2013-11-17 10:40:11
            [updated_at] => 2013-11-20 19:28:08
            [is_active] => 1
            [disable_auto_group_change] => 0
            [firstname] => ******
            [lastname] => *******
            [password_hash] => 456731650daade64aa54e0d4ea97c69a:OrJLah1fNeeX0lNEUmyoU9n1DAQ8sGyC
            [created_in] => English
            [mcd_meeting12_avatar] => logo.png
            [default_billing] => 1
            [default_shipping] => 1
            [tax_class_id] => 3
            [parent_id] => 0
            [_profile_picture_dir_cache] => /Applications/MAMP/htdocs/Developer/media/mcd/images/customer/2
        )

    [remote_ip] => ::1
    [customer_id] => 2
    [customer_email] => *********
    [customer_firstname] => **********
    [customer_lastname] => *************
    [customer_group_id] => 1
    [customer_tax_class_id] => 3
    [customer_note_notify] => 1
    [customer_is_guest] => 0
    [quote_base_grand_total] => 20
    [global_currency_code] => GBP
    [base_currency_code] => GBP
    [store_currency_code] => GBP
    [order_currency_code] => GBP
    [store_to_base_rate] => 1.0000
    [store_to_order_rate] => 1.0000
    [base_to_global_rate] => 1.0000
    [base_to_order_rate] => 1.0000
    [is_virtual] => 0
    [applied_rule_ids] => 
    [total_qty_ordered] => 1
    [weight] => 0.5
    [shipping_method] => flatrate_flatrate
    [shipping_description] => Flat Rate - Fixed
    [subtotal] => 15
    [tax_amount] => 0
    [discount_amount] => 0
    [shipping_amount] => 5
    [shipping_incl_tax] => 5
    [shipping_tax_amount] => 0
    [grand_total] => 20
    [base_subtotal] => 15
    [base_tax_amount] => 0
    [base_discount_amount] => 0
    [base_shipping_amount] => 5
    [base_shipping_incl_tax] => 5
    [base_shipping_tax_amount] => 0
    [base_grand_total] => 20
    [hidden_tax_amount] => 0
    [base_hidden_tax_amount] => 0
    [shipping_hidden_tax_amount] => 0
    [base_shipping_hidden_tax_amount] => 0
    [base_shipping_hidden_tax_amnt] => 0
    [discount_description] => 
    [shipping_discount_amount] => 0
    [base_shipping_discount_amount] => 0
    [subtotal_incl_tax] => 15
    [base_subtotal_incl_tax] => 15
    [payment_surcharge_amount] => 0
    [base_payment_surcharge_amount] => 0
    [applied_taxes] => Array
        (
        )

    [converting_from_quote] => 1
    [store_name] => Main Website
Main Store
English
    [total_item_count] => 1
    [protect_code] => b599b9
    [created_at] => 2013-11-20 19:28:08
    [updated_at] => 2013-11-20 19:28:08
    [entity_id] => 80
    [billing_address_id] => 71
    [shipping_address_id] => 72
    [applied_tax_is_saved] => 1
    [state] => pending
    [status] => 
)

No tengo idea de cómo resolver esto o por qué está sucediendo y me gustaría pedirle a Mo alguna orientación, por favor.

¿Fue útil?

Solución

Primero retire el error tipográfico:

$commentModel->setOrderId($order->getId())
                 ->setComment($message)
                 ->save();

Además, sugeriría usar

$commentModel = Mage::getModel('checkoutcomments/comment')->load($order->getId(), 'order_id');

Lo que se aseguraría de que esté actualizando el mismo comentario en caso de que su código se ejecute dos veces.

Otros consejos

El problema (como se sospecha en los comentarios) es el evento que está utilizando. sales_order_place_after. Ese evento se envía después del pago es colocado. El pedido aún no se guarda en ese punto.
Puedes probar con sales_model_service_quote_submit_success o sales_model_service_quote_submit_after. Recomiendo el primero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a magento.stackexchange
scroll top