Importer des commandes d'un CSV dans Magento par programmation

17

Nous passons d'un ancien système de point de vente obsolète à l'utilisation exclusive de Magento 1.7 comme point de vente. Sans surprise, l'un des défis auxquels nous sommes confrontés est de savoir comment obtenir presque 20 ans d'enregistrements de l'ancien système vers Mage sans catastrophe.

Mis à part le défi de même migrer les enregistrements clients, le problème sur lequel je me concentre dans cette question est de savoir comment je vais migrer les données de commande historiques de l'ancien POS vers Mage. Je ne suis pas sûr à 100% des chiffres exacts quand il s'agit de nombreux enregistrements de commandes, mais je dirais au moins un million.

Voici ce que je pense en termes d'approche:

  1. Découvrez exactement comment les données doivent être formatées pour que Magento fonctionne correctement. La question de savoir si nous pouvons le retirer de l'ancien POS dans un format qui fonctionne, mais supposons un instant que cela se passe bien ...
  2. Créez un fichier .CSV avec des données historiques bien formatées
  3. Trouvez un moyen de lire ce fichier .CSV dans l' $orderobjet de Magento ligne par ligne -> save ()
  4. Profit!

Mon problème est que je suis un peu flou sur la façon d'approcher les points 2 et 3, allez comprendre. Je peux formater les données provenant de l'ancien point de vente comme je le souhaite, même si elles sont très lourdes et impliquent Perl, mais une fois que j'ai le fichier .CSV (ou quel que soit le type de fichier qui fonctionnerait réellement pour ce processus), je ne suis pas assez clair sur comment je l'introduirais dans l'objet de commande de Magento.

J'ai fait quelques recherches sur Google, et j'ai trouvé des exemples de personnes utilisant l'objet de commande de Mage pour importer des commandes par programme, mais peu de discussion sur la façon dont ils connectent des sources de données autres que le chariot frontal à cet objet. J'ai étudié une version de l'objet de commande:

$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();

Voici donc mes questions spécifiques:

  1. Cela semble-t-il être une approche même à distance sensible à ce problème? Et sinon, comment pensez-vous que je pourrais aborder cette question comme moins idiote?
  2. S'il s'agit d'une approche sensée, ai-je besoin d'un .CSV différent pour chaque modèle appelé par le processus de commande? c'est-à-dire Mage :: getModel ('sales / order'), Mage :: getModel ('sales / order_address'), etc?
  3. Un .CSV est-il même le chemin à parcourir?
  4. Comment pourrais-je introduire mes données dans cet objet, que ces données soient contenues dans un .CSV ou qu'avez-vous?
  5. Comment feriez-vous pour limiter les frais généraux?

Même si j'y pense de manière totalement idiote et que vous me le dites, j'apprécie vraiment tout commentaire.

Merci merci merci!

chou frisé
la source
1
Pas vraiment significatif pour votre cas, mais jetez un oeil à une question précédente et à la réponse de @BenMarks, qui implique l'analyse de CSV dans Magento et pourrait être utile. magento.stackexchange.com/questions/232/…
pspahn
1
Vous voudrez peut-être y jeter un œil: github.com/avstudnitz/AvS_FastSimpleImport Il se concentre principalement sur l'importation de produits et de clients, mais c'est un système d'importation rapide. Comme vous parlez de millions d'enregistrements, vous voulez probablement quelque chose de rapide. J'ai déjà utilisé cela pour importer des fichiers CSV de produit. Vous venez de lire le fichier CSV et de convertir les données en tableaux. Je n'ai cependant pas essayé d'étendre ce module pour utiliser les commandes. Je ne sais donc pas comment cela fonctionnera. Bonne chance.
Vicky
Alors, automatiser Dataflow - Importations pour importer des commandes serait-il une mauvaise idée? D'après ce que j'ai lu, il semble que ce soit une solution assez courante.
sparecycle

Réponses:

9

Surpris aucune réponse avec autant de votes / vues, donc je vais mordre:

  1. Cela dépendrait de l'ancien système POS, masser les données lors de l'importation.
  2. Familiarisez-vous avec Varien_Io, en particulier Varien_Io_File. Étant donné que vous aurez très probablement affaire à une si grande collection de données, n'oubliez pas d'utiliser des flux tels que StreamReadCsvet StreamWriteCsv. Plus de détails sur un "stream" . Sans flux ou lecture / écriture linéaire, vous pouvez rencontrer des problèmes de mémoire avec d'autres méthodes de chargement / écriture.

Avec ce qui précède, voici un exemple: (source 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
            );
        }
    }
}

Quant à l'importation de commandes, cet exemple a le plus aidé: (Source: 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('[email protected]');
    $quote->assignCustomer($customer);
} else {
    // for guesr orders only:
    $quote->setCustomerEmail('[email protected]');
}

// 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());

Avec l'exemple que vous avez maintenant, les ressources seront lourdes, car il y a des Mage::getModel(...appels dans les boucles foreach, ce qui est une mauvaise pratique et entraînera probablement une temporisation ou remplira la mémoire assez rapidement. Surtout si vous l'avez enveloppé dans un autre foreach / while.

Cette...

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

Devrait ressembler à:

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

Je n'essaierais pas d'essayer de relier tous les bits de données CSV aux objets Magento. Ce serait de la folie et un peu de surpuissance, respectez les points d'entrée du modèle de ressource $model->load(EntityId).

Notez également si vous essayez d' importer plus de 100k + commandes, je serais préoccupé par les performances après les importations importantes, car il est nécessaire de garder MySQL réglé pour gérer de tels volumes, sans trop mentionner si je ne me trompe pas, les objets de vente sont toujours basés sur l'EAV, et ne fonctionnent pas bien sous un volume / trafic élevé. Il y a une raison pour laquelle Magento Enterprise dispose d'un module Archive des commandes client pour extraire les anciennes données des tables de commandes client "transactionnelles" pour éviter les données gonflées / périmées qui ne sont pas nécessaires pour prendre des commandes.

Pour conclure: j'évoquerais les exigences et les besoins de l'entreprise pour stocker des données aussi volumineuses, s'il s'agit uniquement de rapports, il existe de meilleures alternatives à la suite que Magento.

B00MER
la source
3

En pensant à l'impact que ces commandes historiques auraient sur les performances de magento / mysql et du fait que toutes les gammes de produits qui ont été abandonnées devraient également être importées, il pourrait être utile d'envisager de stocker les commandes historiques avec le client et les produits dans quelque chose comme un index elasticsearch et effectuez une recherche à la demande. c'est-à-dire la page d'historique de commande client.

Jamie
la source
1

De la création d'un devis puis de la création d'une commande, il faut trop de temps pour d'importantes données d'importation de commande.

Donc, j'ai recherché et trouvé la conclusion d'énormes données d'importation de commandes avec la requête mysql:

  1. J'ai inséré les données uniquement dans les tables de commande.

  2. Mettre à jour le increment_id à pour reconnaître magento 1.x, cette dernière commande increment_idest la suivante

  3. Cette requête ne crée aucun devis, facture et expédition:

    Requêtes 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","[email protected]","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,"[email protected]",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,"[email protected]","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,"[email protected]","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;

sushant kumar
la source