Importazione di ordini da un CSV in Magento a livello di codice


17

Stiamo passando da un vecchio sistema di punti vendita obsoleto all'utilizzo esclusivo di Magento 1.7 come nostro POS. Non inaspettatamente, una delle sfide che stiamo affrontando è come ottenere quasi 20 anni di registrazioni dal vecchio sistema a Mage senza catastrofe.

Mettendo da parte la sfida della migrazione anche dei record dei clienti, il problema su cui mi sto concentrando in questa domanda è come migrerò i dati storici degli ordini dal vecchio POS a Mage. Non sono sicuro al 100% sui numeri esatti quando parliamo di molti record di ordini, ma direi almeno un milione.

Ecco cosa sto pensando in termini di come affrontare questo:

  1. Scopri esattamente come i dati devono essere formattati affinché Magento funzioni bene. Se possiamo tirarlo fuori dal vecchio POS in un formato che funziona è discutibile, ma supponiamo per un momento che questo vada bene ...
  2. Crea un file .CSV con dati storici ben formattati
  3. Trova un modo per leggere quel. CSV $ordernell'oggetto Magento riga per riga -> save ()
  4. Profitto!

Il mio problema è che sono un po 'confuso su come affrontare i punti 2 e 3, vai a capire. Posso formattare i dati che escono dal vecchio POS di cui ho bisogno, anche se è molto ingombrante e coinvolge Perl, ma una volta che ho il file .CSV (o qualunque tipo di file funzionerebbe effettivamente per questo processo) Non sono abbastanza chiaro come lo darei all'oggetto ordine di Magento.

Ho fatto un po 'di ricerche su Google e ho trovato esempi di persone che usano l'oggetto ordine di Mage per importare gli ordini a livello di codice, ma poca discussione su come stanno collegando origini dati diverse dal carrello front-end a detto oggetto. Ho studiato una versione dell'oggetto ordine:

$id=1; // get Customer Id
$customer = Mage::getModel('customer/customer')->load($id);

$transaction = Mage::getModel('core/resource_transaction');
$storeId = $customer->getStoreId();
$reservedOrderId = Mage::getSingleton('eav/config')->getEntityType('order')->fetchNewIncrementId($storeId);

$order = Mage::getModel('sales/order')
  ->setIncrementId($reservedOrderId)
  ->setStoreId($storeId)
  ->setQuoteId(0)
  ->setGlobal_currency_code('USD')
  ->setBase_currency_code('USD')
  ->setStore_currency_code('USD')
  ->setOrder_currency_code('USD');

// set Customer data
$order->setCustomer_email($customer->getEmail())
  ->setCustomerFirstname($customer->getFirstname())
  ->setCustomerLastname($customer->getLastname())
  ->setCustomerGroupId($customer->getGroupId())
  ->setCustomer_is_guest(0)
  ->setCustomer($customer);

// set Billing Address
$billing = $customer->getDefaultBillingAddress();
$billingAddress = Mage::getModel('sales/order_address')
  ->setStoreId($storeId)
  ->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_BILLING)
  ->setCustomerId($customer->getId())
  ->setCustomerAddressId($customer->getDefaultBilling())
  ->setCustomer_address_id($billing->getEntityId())
  ->setPrefix($billing->getPrefix())
  ->setFirstname($billing->getFirstname())
  ->setMiddlename($billing->getMiddlename())
  ->setLastname($billing->getLastname())
  ->setSuffix($billing->getSuffix())
  ->setCompany($billing->getCompany())
  ->setStreet($billing->getStreet())
  ->setCity($billing->getCity())
  ->setCountry_id($billing->getCountryId())
  ->setRegion($billing->getRegion())
  ->setRegion_id($billing->getRegionId())
  ->setPostcode($billing->getPostcode())
  ->setTelephone($billing->getTelephone())
  ->setFax($billing->getFax());
$order->setBillingAddress($billingAddress);

$shipping = $customer->getDefaultShippingAddress();
$shippingAddress = Mage::getModel('sales/order_address')
  ->setStoreId($storeId)
  ->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_SHIPPING)
  ->setCustomerId($customer->getId())
  ->setCustomerAddressId($customer->getDefaultShipping())
  ->setCustomer_address_id($shipping->getEntityId())
  ->setPrefix($shipping->getPrefix())
  ->setFirstname($shipping->getFirstname())
  ->setMiddlename($shipping->getMiddlename())
  ->setLastname($shipping->getLastname())
  ->setSuffix($shipping->getSuffix())
  ->setCompany($shipping->getCompany())
  ->setStreet($shipping->getStreet())
  ->setCity($shipping->getCity())
  ->setCountry_id($shipping->getCountryId())
  ->setRegion($shipping->getRegion())
  ->setRegion_id($shipping->getRegionId())
  ->setPostcode($shipping->getPostcode())
  ->setTelephone($shipping->getTelephone())
->setFax($shipping->getFax());

$order->setShippingAddress($shippingAddress)
  ->setShipping_method('flatrate_flatrate')
  ->setShippingDescription($this->getCarrierName('flatrate'));

$orderPayment = Mage::getModel('sales/order_payment')
  ->setStoreId($storeId)
  ->setCustomerPaymentId(0)
  ->setMethod('purchaseorder')
  ->setPo_number(' - ');
$order->setPayment($orderPayment);

// let say, we have 2 products
$subTotal = 0;
  $products = array(
  '1001' => array(
  'qty' => 1
  ),
  '1002' ->array(
  'qty' => 3
  ),
);
foreach ($products as $productId=>$product) {
  $_product = Mage::getModel('catalog/product')->load($productId);
  $rowTotal = $_product->getPrice() * $product['qty'];
  $orderItem = Mage::getModel('sales/order_item')
    ->setStoreId($storeId)
    ->setQuoteItemId(0)
    ->setQuoteParentItemId(NULL)
    ->setProductId($productId)
    ->setProductType($_product->getTypeId())
    ->setQtyBackordered(NULL)
    ->setTotalQtyOrdered($product['rqty'])
    ->setQtyOrdered($product['qty'])
    ->setName($_product->getName())
    ->setSku($_product->getSku())
    ->setPrice($_product->getPrice())
    ->setBasePrice($_product->getPrice())
    ->setOriginalPrice($_product->getPrice())
    ->setRowTotal($rowTotal)
    ->setBaseRowTotal($rowTotal);

  $subTotal += $rowTotal;
  $order->addItem($orderItem);
}

$order->setSubtotal($subTotal)
  ->setBaseSubtotal($subTotal)
  ->setGrandTotal($subTotal)
  ->setBaseGrandTotal($subTotal);

$transaction->addObject($order);
$transaction->addCommitCallback(array($order, 'place'));
$transaction->addCommitCallback(array($order, 'save'));
$transaction->save();

Quindi, ecco le mie domande specifiche:

  1. Sembra un approccio sensibilmente remoto anche a questo problema? E, in caso contrario, come pensi che potrei affrontare questo problema come meno di un idiota?
  2. Se questo è un approccio sensato, ho bisogno di un .CSV diverso per ogni modello richiamato dal processo di ordine? cioè Mage :: getModel ('sales / order'), Mage :: getModel ('sales / order_address'), ecc.?
  3. Un CSV è anche la strada da percorrere?
  4. Come potrei fornire i miei dati a questo oggetto, sia che siano contenuti in un .CSV o che cosa hai?
  5. Come faresti a limitare le spese generali?

Anche se ci sto pensando in modo totalmente idiota e tu mi dici altrettanto, apprezzo davvero qualsiasi input.

Grazie, grazie, grazie!


1
Non significativo per il tuo caso, ma dai un'occhiata a una mia precedente domanda e alla risposta di @BenMarks, che prevede l'analisi del CSV in Magento e potrebbe essere utile. magento.stackexchange.com/questions/232/…
pspahn

1
Potresti dare un'occhiata a questo per ispirazione: github.com/avstudnitz/AvS_FastSimpleImport Si concentra principalmente sull'importazione di prodotti e clienti, ma è un sistema di importazione veloce. Mentre parli di milioni di dischi, probabilmente vuoi qualcosa di veloce. L'ho usato prima per importare file CSV del prodotto. Basta leggere il file CSV e convertire i dati in array. Non ho provato a estendere questo modulo per utilizzare gli ordini però. Quindi non ho idea di come funzionerà. In bocca al lupo.
Vicky,

Quindi, automatizzare il flusso di dati - Le importazioni per l'importazione di ordini sarebbero una cattiva idea? Da quello che ho letto, sembra essere una soluzione abbastanza comune.
sparecycle

Risposte:


9

Sorpreso nessuna risposta con così tanti voti / opinioni, quindi morderò:

  1. Ciò dipende dal vecchio sistema POS, massaggia i dati durante l'importazione.
  2. Familiarizzare con te Varien_Io, in particolare Varien_Io_File. Dato che molto probabilmente avrai a che fare con una raccolta di dati così ampia, tieni presente di utilizzare flussi come StreamReadCsve StreamWriteCsv. Maggiori dettagli su uno "stream" . Senza un flusso o lettura / scrittura lineare è possibile riscontrare problemi di memoria con altri metodi di caricamento / scrittura.

Con quanto sopra detto qui è un esempio: (fonte Atwix.com )

/**
 * Generates CSV file with product's list according to the collection in the $this->_list
 * @return array
 */
public function generateMlnList()
{
    if (!is_null($this->_list)) {
        $items = $this->_list->getItems();
        if (count($items) > 0) {

            $io = new Varien_Io_File();
            $path = Mage::getBaseDir('var') . DS . 'export' . DS;
            $name = md5(microtime());
            $file = $path . DS . $name . '.csv';
            $io->setAllowCreateFolders(true);
            $io->open(array('path' => $path));
            $io->streamOpen($file, 'w+');
            $io->streamLock(true);

            $io->streamWriteCsv($this->_getCsvHeaders($items));
            foreach ($items as $product) {
                $io->streamWriteCsv($product->getData());
            }

            return array(
                'type'  => 'filename',
                'value' => $file,
                'rm'    => true // can delete file after use
            );
        }
    }
}

Per quanto riguarda l'importazione di ordini, questo esempio ha aiutato di più: (Fonte: pastebin )

<?php

require_once 'app/Mage.php';

Mage::app();

$quote = Mage::getModel('sales/quote')
    ->setStoreId(Mage::app()->getStore('default')->getId());

if ('do customer orders') {
    // for customer orders:
    $customer = Mage::getModel('customer/customer')
        ->setWebsiteId(1)
        ->loadByEmail('customer@example.com');
    $quote->assignCustomer($customer);
} else {
    // for guesr orders only:
    $quote->setCustomerEmail('customer@example.com');
}

// add product(s)
$product = Mage::getModel('catalog/product')->load(8);
$buyInfo = array(
    'qty' => 1,
    // custom option id => value id
    // or
    // configurable attribute id => value id
);
$quote->addProduct($product, new Varien_Object($buyInfo));

$addressData = array(
    'firstname' => 'Test',
    'lastname' => 'Test',
    'street' => 'Sample Street 10',
    'city' => 'Somewhere',
    'postcode' => '123456',
    'telephone' => '123456',
    'country_id' => 'US',
    'region_id' => 12, // id from directory_country_region table
);

$billingAddress = $quote->getBillingAddress()->addData($addressData);
$shippingAddress = $quote->getShippingAddress()->addData($addressData);

$shippingAddress->setCollectShippingRates(true)->collectShippingRates()
        ->setShippingMethod('flatrate_flatrate')
        ->setPaymentMethod('checkmo');

$quote->getPayment()->importData(array('method' => 'checkmo'));

$quote->collectTotals()->save();

$service = Mage::getModel('sales/service_quote', $quote);
$service->submitAll();
$order = $service->getOrder();

printf("Created order %s\n", $order->getIncrementId());

Con l'esempio che hai ora sarà pieno di risorse, poiché ci sono Mage::getModel(...chiamate nei cicli foreach che sono cattive pratiche e molto probabilmente o timeout o riempiranno la memoria piuttosto rapidamente. Soprattutto se lo hai avvolto in un altro foreach / while.

Questo...

foreach ($products as $productId=>$product) {
  $_product = Mage::getModel('catalog/product')->load($productId);

Dovrebbe apparire come:

$_product = Mage::getModel('catalog/product');
foreach ($products as $productId=>$product) {
  $_product->load($productId);

Non tenterei di provare a mettere in relazione tutti i bit di dati CSV con oggetti Magento. Sarebbe una follia e un po 'eccessivo, tenere con i punti di ingresso del modello di risorsa di $model->load(EntityId).

Inoltre, se stai tentando di importare oltre 100.000 ordini, sarei preoccupato per le prestazioni dopo le grandi importazioni poiché è necessario per mantenere MySQL sintonizzato per gestire volumi così grandi, per non parlare anche se non sbaglio gli oggetti di vendita sono ancora basati su EAV, e non funziona bene con volume / traffico elevati. C'è una ragione per cui Magento Enterprise ha un modulo Archivio ordini di vendita per estrarre i vecchi dati dalle tabelle "transazionali" degli ordini di vendita per prevenire dati gonfi / stantii che non sono necessari per prendere gli ordini.

In conclusione: vorrei sollevare i requisiti e le esigenze dell'azienda per archiviare dati così grandi, se solo riferendo che ci sono alternative migliori per gestire questo rispetto a Magento.



3

Pensando all'impatto che questi ordini storici avrebbero sulle prestazioni di magento / mysql oltre al fatto che qualsiasi linea di prodotto che era stata interrotta avrebbe dovuto essere importata troppo, quindi potrebbe valere la pena considerare di archiviare gli ordini storici insieme al cliente e ai prodotti in qualcosa come un indice elasticsearch ed eseguire una ricerca su richiesta. cioè la pagina della cronologia degli ordini dei clienti.


1

Dalla creazione del preventivo e dalla creazione di un ordine è necessario troppo tempo per enormi dati di importazione dell'ordine.

Quindi, ho studiato e trovato la conclusione di enormi dati di importazione degli ordini con query mysql:

  1. Ho inserito i dati solo nelle tabelle degli ordini.

  2. Aggiorna il increment_idper riconoscere magento 1.x, l'ultimo ordine increment_idè questo

  3. Questa query non sta creando alcun preventivo, fattura e spedizione:

    Query SQL: -

    1. INSERT INTO `sales_flat_order` (state, status, shipping_description, store_id, customer_id, base_discount_invoiced, base_grand_total, base_shipping_amount, base_shipping_invoiced, base_subtotal, base_subtotal_invoiced, base_tax_amount, base_tax_invoiced, base_total_invoiced, base_total_invoiced_cost, base_total_paid, discount_invoiced, grand_total, shipping_amount, shipping_invoiced, subtotal, subtotal_invoiced, tax_amount, tax_invoiced, total_invoiced, total_paid, customer_group_id, increment_id, base_currency_code, global_currency_code, customer_email, customer_firstname, customer_lastname, customer_middlename, order_currency_code, shipping_method, store_currency_code, store_name, created_at, updated_at, total_item_count, hidden_tax_invoiced, base_hidden_tax_invoiced, is_valid) VALUES ("complete", "complete", "Flat Rate - Fixed", 1, 38322,0,225.7,0,0,214.95,214.95,10.75,10.75,225.7, 0,225.7, 0,225.7,0,0,214.95,214.95,10.75,10.75,225.7,225.7, 1,100026111,"CAD","CAD","abc@gmail.com","abc","abc","", "CAD", "flatrate_flatrate", "CAD", "Main Website\nMain Website Store\nOnline Catalog","2012-01-17 00:00:00","2012-01-17 00:00:00",5,0,0,0);

    2. INSERT INTO `sales_flat_order_grid` (entity_id, status, shipping_description, shipping_method, store_id, customer_id, customer_email, total_qty_ordered, base_grand_total, base_total_paid, grand_total, total_paid, increment_id, base_currency_code, order_currency_code, store_name, created_at, updated_at, payment_validated, billing_name, shipping_name) VALUES (5, "complete", "Flat Rate - Fixed", "flatrate_flatrate", 1, 38322,"abc@gmail.com",5,225.7,225.7,225.7,225.7,100026111,"CAD", "CAD", "Main Website\nMain Website Store\nOnline Catalog","2012-01-17 00:00:00","2012-01-17 00:00:00",1,"abc abc","abc abc");

    3. INSERT INTO `sales_flat_order_address` (parent_id, region_id, customer_id, email, region, postcode, lastname, street, city, telephone, country_id, firstname, address_type, middlename, nick_name) VALUES (5,68,38322,"alicjakeller@gmail.com","Manitoba","R3W 1G9","abc","1607 Concordia Ave E","Winnipeg","204 667-5540","CA","abc","billing","","")

    4. INSERT INTO `sales_flat_order_address` (parent_id, region_id, customer_id, email, region, postcode, lastname, street, city, telephone, country_id, firstname, address_type, middlename, nick_name) VALUES (5,68,38322,"alicjakeller@gmail.com","Manitoba","R3W 1G9","abc","1607 Concordia Ave E","Winnipeg","204 667-5540","CA","abc","shipping","","");

    5. INSERT INTO `sales_flat_order_item` (order_id, store_id, created_at, updated_at, product_id, product_type, sku, name, qty_ordered, price, base_price, original_price, base_original_price, row_total, base_row_total, price_incl_tax, base_price_incl_tax, row_total_incl_tax, base_row_total_incl_tax) VALUES (5,1,"2012-01-17 00:00:00","2012-01-17 00:00:00",4134,"simple","MET2240","ULTRA FLORA IB - 30 CAPS",4,44.99,44.99,44.99,44.99,179.96,179.96,44.99,44.99,179.96,179.96);

    6. INSERT INTO `sales_flat_order_item` (order_id, store_id, created_at, updated_at, product_id, product_type, sku, name, qty_ordered, price, base_price, original_price, base_original_price, row_total, base_row_total, price_incl_tax, base_price_incl_tax, row_total_incl_tax, base_row_total_incl_tax) VALUES (5,1,"2012-01-17 00:00:00","2012-01-17 00:00:00",3198,"simple","WS1600","THYROSENSE - 180 VCAPS + 60 VCAPS FREE",1,34.99,34.99,34.99,34.99,34.99,34.99,34.99,34.99,34.99,34.99);

    7. INSERT INTO `sales_flat_order_payment` (parent_id, base_shipping_amount, shipping_amount, base_amount_paid, amount_paid, base_amount_ordered, amount_ordered, method) VALUES (5,0,0,225.7,225.7,225.7,225.7, "cashondelivery");

    8. UPDATE `eav_entity_store` SET increment_last_id = 100026111 WHERE `entity_type_id` = 5 AND `store_id` = 1;

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.