프로그래밍 방식으로 CSV에서 Magento로 주문 가져 오기


17

우리는 오래되고 오래된 구식 POS 시스템에서 POS로 Magento 1.7을 사용하는 것으로 전환하고 있습니다. 당연히 우리가 겪고있는 과제 중 하나는 기존 시스템에서 20 년 동안 거의 재앙없이 Mage에 기록을 얻는 방법입니다.

고객 레코드를 마이그레이션하는 문제를 해결하면서이 질문에서 중점을 둔 문제는 이전 주문 데이터를 이전 POS에서 Mage로 마이그레이션하는 방법입니다. 많은 주문 기록을 말할 때 정확한 숫자를 100 % 확신 할 수는 없지만 적어도 백만 개를 말할 것입니다.

여기에 접근하는 방법에 대한 생각은 다음과 같습니다.

  1. Magento가 데이터를 제대로 재생하기 위해 데이터를 어떻게 포맷해야하는지 정확히 파악하십시오. 작동하는 형식으로 이전 POS에서 가져올 수 있는지 여부는 의문의 여지가 있지만 잠시 동안 잘 진행된다고 가정합시다 ...
  2. 멋진 형식의 기록 데이터가 포함 된 .CSV 파일 만들기
  3. .CSV를 Magento의 $order객체 로 읽는 방법을 찾으십시오 -> save ()
  4. 이익!

내 문제는 포인트 2 & 3에 접근하는 방법에 대해 조금 모호하다는 것입니다. 이전 POS에서 나오는 데이터를 포맷 할 수는 있지만 매우 번거롭고 Perl과 관련되어 있어도 필요합니다.하지만 일단 .CSV 파일 (또는 실제로이 프로세스에 사용할 수있는 파일 유형)이 있으면 명확하지 않습니다. 어떻게 Magento의 주문 객체에 그것을 공급할 것입니다.

나는 인터넷 검색을 수행했으며 Mage의 주문 객체를 사용하여 프로그래밍 방식으로 주문을 가져 오는 사람들의 예제를 생각해 냈지만 프런트 엔드 카트 이외의 데이터 소스를 해당 객체에 연결하는 방법에 대해서는 거의 논의하지 않았습니다. 주문 객체의 버전을 연구하고 있습니다.

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

구체적인 질문은 다음과 같습니다.

  1. 이것은이 문제에 대한 원격 감각적 인 접근 방식처럼 보입니까? 그렇지 않다면 어떻게하면 바보처럼 덜이 문제에 접근 할 수 있다고 생각하십니까?
  2. 이것이 감각적 인 접근이라면, 주문 프로세스에 의해 호출 된 각 모델마다 다른 .CSV가 필요합니까? 즉 Mage :: getModel ( 'sales / order'), Mage :: getModel ( 'sales / order_address') 등?
  3. .CSV도 갈 수 있습니까?
  4. 데이터가 .CSV에 포함되어 있거나 무엇을 포함하는지에 관계없이이 개체에 데이터를 어떻게 제공합니까?
  5. 오버 헤드 제한에 대해 어떻게 생각하십니까?

내가 완전히 바보 같은 방식으로 생각하고 당신이 나에게 많은 것을 말해도, 나는 모든 의견을 정말로 고맙게 생각합니다.

감사합니다 감사합니다


1
실제로 귀하의 경우에는 중요하지 않지만 Magento에서 CSV를 구문 분석하고 유용 할 수있는 나의 이전 질문과 @ BenMarks의 답변을 살펴보십시오. magento.stackexchange.com/questions/232/…
pspahn

1
: 당신은 영감이보고 할 수 있습니다 github.com/avstudnitz/AvS_FastSimpleImport 그것은 주로 제품과 고객을 수입에 집중한다, 그러나 빠른 수입 시스템입니다. 수백만 개의 레코드에 대해 이야기 할 때 아마도 빠른 것을 원할 것입니다. 제품 CSV 파일을 가져 오기 위해 이것을 사용했습니다. CSV 파일을 읽고 데이터를 배열로 변환하면됩니다. 주문을 사용하기 위해이 모듈을 확장하려고하지 않았습니다. 그래서 어떻게 작동하는지 모르겠습니다. 행운을 빕니다.
Vicky

따라서 데이터 흐름 자동화-주문을 가져 오기위한 가져 오기가 나쁜 생각입니까? 내가 읽은 것에서, 그것은 매우 일반적인 해결책 인 것 같습니다.
스페어 사이클

답변:


9

너무 많은 투표 / 의견으로 답변이 없으므로 놀랐습니다.

  1. 이것은 이전 POS 시스템에 따라 다르며 가져 오는 동안 데이터를 마사지합니다.
  2. Varien_Io특히 자신을 숙지하십시오 Varien_Io_File. 이러한 대량의 데이터를 처리 할 가능성이 높으므로 StreamReadCsvand 등의 스트림을 사용해야합니다 StreamWriteCsv. 는 "스트림"에 대한 자세한 내용 . 스트림 또는 선형 읽기 / 쓰기가 없으면 다른로드 / 쓰기 방법에서 메모리 문제가 발생할 수 있습니다.

위의 예는 다음과 같습니다. (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
            );
        }
    }
}

주문 가져 오기와 관련하여이 예제는 대부분 도움이되었습니다. (출처 : 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());

이 예제를 사용하면 나쁜 습관Mage::getModel(... 이 될 foreach 루프에 대한 호출 이 있고 시간 초과 또는 메모리를 빨리 채울 수 있으므로 리소스 가 많이 사용됩니다. 특히 이것을 다른 foreach / while에 싸인 경우.

이...

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

다음과 같아야합니다.

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

모든 CSV 비트 데이터를 Magento 개체 와 관련 시키려고 시도하지는 않습니다 . 광기와 약간의 과잉 일 것입니다.의 자원 모델 진입 점을 유지하십시오 $model->load(EntityId).

또한 100k + 이상의 주문 을 가져 오려고 시도하는 경우 MySQL을 이러한 대량을 처리하도록 조정하는 데 필요한 대량 수입 후 성능에 관심이 있습니다. 판매 객체가 여전히 EAV 기반이라고 잘못 생각하지 않으면 언급하지 않아도됩니다. 트래픽이 많거나 트래픽이 많은 환경에서는 제대로 작동하지 않습니다. Magento Enterprise에 주문을 처리하는 데 필요하지 않은 부풀어 오른 데이터를 방지하기 위해 "트랜잭션"판매 주문 테이블에서 오래된 데이터를 가져 오는 판매 주문 아카이브 모듈이있는 이유가 있습니다.

요약 : 순전히보고하면 Magento보다 더 나은 대안이 있다면 비즈니스의 요구 사항과 요구를 제기 할 것입니다.



3

이러한 과거 주문이 magento / mysql 성능에 미칠 영향과 중단 된 모든 제품 라인을 가져와야한다는 사실을 생각하면 고객 및 제품과 함께 역사적인 주문을 무언가에 저장하는 것이 좋습니다. Elasticsearch 색인과 같이 주문형 검색을 수행합니다. 즉, 고객 주문 내역 페이지.


1

견적을 작성하고 주문을 작성하는 데 많은 양의 주문 가져 오기 데이터를 작성하는 데 너무 많은 시간이 걸립니다.

따라서 mysql 쿼리를 사용하여 대량 주문 가져 오기 데이터의 결론을 연구하고 발견했습니다.

  1. 주문 테이블에만 데이터를 삽입했습니다.

  2. 업데이트 increment_id마지막 순서가 있음을 마 젠토 1.x에서 인식하는 increment_id이입니다

  3. 이 쿼리는 견적, 송장 및 배송을 생성하지 않습니다.

    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;

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.