Tag: magento

  • AmazonPayments is removed from Magento 1.4

    最近留意到一件奇怪的事:Magento 1.3 里还在的 AmazonPayments module 整个儿从 1.4 版拿掉了。

    虽然 AmazonPayments 跟大部分英国公司没关系,但它还是造成一点小麻烦。因为它在 Magento 1.3 出现过,所以数据库里 system config 里留有 AmazonPayments 的一些配置信息;但是 Magento 1.3 升级到 1.4 时,为了减少麻烦,我把整个 1.3 源码目录删掉后再替换入 1.4 源码(而不是通常的 merge and replace),这样一来的现状是:数据库里有 AmazonPayments config data,但源码里没有 AmazonPayment module。这时,如果要新建一条基于 payment method 的 promotion rule (比如想鼓励大家使用 GoogleCheckout,给 GoogleCheckout 用户额外 10% 折扣),一点选择 payment method 就出错。

    定位了一下出错的语句,原来是 getAllMethods() 不妥,因为它会根据 config data 去或取 payment methods,结果连源码都不存在的 AmazonPayments 成了返回数组里的一员,不出错都难。(我还用过一个 payment module ProtxDirect,后来有更好的 module 以后,把 ProtxDirect源码也给删了,这也是出错的原因。)

    
    class Mage_Adminhtml_Model_System_Config_Source_Payment_Allmethods
    {
    protected function _getPaymentMethods()
    {
    return Mage::getSingleton('payment/config')->getActiveMethods();
    }
    }
    
    

    我尝试地把 getAllMethods() 改成 getActiveMethods() 就不再有错误。但是我不喜欢因为这么点事去 override class——这个方法治标,我更喜欢在数据库中找出跟 AmazonPayments 和 ProtxDirect 有关的垃圾信息(既然用不到就是垃圾)直接删除——治本。

    同时我挺奇怪 Magento 1.4 为什么不考虑一下向下兼容,即使 AmazonPayments 失效了也应该在发布时保留源码目录啊?或者,在升级之际执行一遍 config data clean up?

  • Magento 1.4.1.0 is released

    经历了好几个月沉寂之后,今天终于看到 Magento 一个新版 1.4.1.0。虽然我没去试用新版,但还是在第一时间关心了一下 Release Notes。我第一次逐行读完了 Release Notes,以前最多 scam it,这就是亲身体验者和旁观者的区别。

    Improvements

    * Added ability to use static URLs for media in WYSIWYG or image browser. Added ability to enable parsing store, skin and media directives on catalog frontend. (这个功能我已经实现了,就是在 description output 上再套一个cms filter,我称之为 text engine。当然 magento core 实现得肯定比我好,以后我就删了我的 text engine)
    * URL rewrites history: ability to auto-generate custom rewrite with redirect from old to new URL when changing product URL-key (这个问题我也想过,我没 magento core 那么能干,能做 auto-generated redirect,不过我觉得即使有 auto-generated redirect,把 url key 改来改去也不是回事,所以我建议取名需谨慎,定下的 url key不要改)
    * Added ability to exclude a category from navigation menu (这个功能我也实现了,不光能控制 exclude from top navigation,还能控制 exclude from sitemap)
    * Various improvements in system configuration UI. Introduced ability to make actual configuration structure to be independent on the system.xml structure
    * Added “Only X left” inventory feature
    * Implemented Centinel functionality in iphone theme
    * Upgraded TinyMCE to v.3.3.2 (不知是否有了 auto-save?)
    * Improved PayPal integration, includes:
    * Recurring payment profiles entity and purchasing of “subscription” products. In checkout they are treated as “nominal” items.
    * Billing agreements
    * “Pending Review” order state, “Pending Review” and “Suspected Fraud” order statuses and logic related with this. Triggers by PayPal IPR, FMF and Unilateral payments.
    * Functionality of transactions listing/searching and fetching from gateway
    * Fetching PayPal settlement reports via SFTP
    * Various improvements of PayPal integration on the frontend and admin UI
    * Added notice about creating offline creditmemo from order view page.
    * Added getter for recurring payment methods in payment helper.
    * Implemented abstract block ability to have arbitrary groups of child blocks and a method that returns such a group. Implemented a method that fetches data from child block by specified alias.
    * Implemented ability to specify “sort_order” instead of “before” and “after” in the totals declaration. All nominal totals declaration utilize “sort_order”
    * Added getter for specified object data by key in core/template block: method getObjectData()
    * Defined payment methods grouping, implemented getter for payment method list (with option to group them). Added ability to render grouped options in the “select” grid filter.
    * Moneybookers: utilized the payment methods grouping for all its methods; removed redundant “translate” attribute in the methods definition in config.
    * Utilized payment methods grouping for PayPal peyment methods.
    * Added more verbosity to PayPal NVP and IPN debugging

    Changes

    * Sales module database structure changed from EAV into flat tables (没觉得 eav 有多慢,不过 magento 这么改肯定有它道理)

    * Product custom URL rewrites redirect to SEF URL, rather than to catalog/product/view/id/ (这也是我考虑得比较多的问题,不过如果一个 product 归属多个 category,此改进后的 SEF URL 时能否正确显示 main category breadcrumb,能否配合 rel=”canonical” 使用?)
    * Reimplemented frontend top menu rendering logic (cross-browser and usability improvements)
    * Reviewed logic of the sales reports: Orders, Tax, Invoiced, Shipping, Refunds, Coupons
    * Reimplemented bestsellers report
    * Implemented 3D Secure validation for Maestro International and JCB cards
    * Changed Shopping cart methods output (top + bottom): removed

  • -dependance from templates in other modules \-> moved to Checkout module
    * Moved the Payflow Pro payment method to PayPal module
    * Refactored sales/service_quote model: instead of submit() method the submitAll() should be used. It can submit nominal items separately from the order. The methods for submitting nominal items and order separately – are available as well.
    * Refactored onepage checkout model to use the new method sales/service_quote::submitAll(), added recurring profiles and billing agreements passing through the process until the success page
    * Utilized child blocks grouping to improve flexibility of rendering additional information in catalog/product/view template. The group is called “detailed_info”; any block from layout may insert itself to this group.
    * Removed redundant wrappers hard-coded into some catalog templates. Template of parent block is responsible for wrapping.
    * Refactored onepage checkout success block and template: simplified fetching related checkout information, added ability to render billing agreement and recurring profiles that might be created with the payment placement.

    Fixes

    * Fixed read/write connection issue during new customer order place. See http://www.magentocommerce.com/boards/viewthread/19363/P0/
    * Fixed tax rule ZIP range matching (numeric values were matched as strings)
    * Various tax fixes
    * Optimized search reindex process

    Known Issues

    * PayPal and Payflow pro modules are officially backwards incompatible.
    * The `sales_order_aggregated_created` table was re-created with new columns, it is not backwards compatible.

    Upgrade Path

    * Once upgraded, go to system configuration section and re-enter all PayPal-related settings carefully. Make sure to specify the proper merchant country and email.
    * To avoid fatal errors with Payflow Pro and Amazonpayments modules, before upgrading cleanup their settings from database:
    DELETE FROM `core_config_data` WHERE `path` LIKE ‘payment/verisign%’;
    DELETE FROM `core_config_data` WHERE `path` LIKE ‘payment/amazonpayments%’;

    (之前我已经亲自动手把 Amazonpayments 删出了数据库,倒没发现 Payflow Pro 的问题)

  • How to improve Magento speed

    How to improve Magento speed 作标题,似乎合适又不合适。因为大凡讨论 Magento 速度优化,总是谈怎么配置数据库、apc、缓存、负载之类,今天我想谈点别的。

    目前我碰到的实际情况是:启用各种缓存并尽可能地将缓存数据保存在内存中,访问cms page / category page / product page 的速度都很理想,但 shopping cart page 是瓶颈,cart item 越多越慢,生成时间超过 2 秒都是不可接受的。所以我一直在想怎么让 shopping cart 生成得快一些。

    上周无意中发现,如果 after add product to cart, redirect to shopping cart,那么 shopping cart 其实在 add to cart 时已经生成了一次,然后 redirect to checkout/cart/index 又生成了一次。生成 shopping cart,最耗时间的是针对每个 cart item,去检验每条 sale rule,每个 sale rule 再来若干个 conditions and actions,不慢才怪,何况又执行了两遍!

    目前我还没有找到一个干净利落的让 shopping cart 只生成一遍的办法。不过另有一个服务器计划(跟 shopping cart 速度无关)已经在进行中,希望光靠服务器升级就能让 shopping cart 在两秒内生成。

  • Make an offer of getting Y quantity of any products for free in Magento

    最近我还写了一个程序,是为了一个非常特殊的促销模型写的:买 X 送 Y。具体是这样:从产品 A 组里每买 X 件,可以从另一堆产品 B 组里任选 Y 件,白送。但 B 组产品同时也是独立销售的,如果有人买了 X 件 A 组里的产品,同时买了 Y+1 件 B 组里的产品,那么其中 1 件 B 组产品不白送,该卖多少价就是多少价。

    我认为 Magento 自带的促销模型已然非常强大,能用一个非常好用的 GUI 组装出千变万化的规则。无奈 my client 脑子更强大,总是想一些 Magento 天然功能以外的点子。我研究了 Magento 天然的 Buy X get Y,发现它是针对 X 和 Y 是同个产品而作的规则。论坛上也有人变通作出 buy X of product A, get Y of product B,但我这个难点是 get Y of any product from B group,meanwhile all products from B group are for sale,我想是不可能通过 Magento 自带的促销模型完成的。

    设想一下,顾客购物车里有三项产品

    • product A1 from group A: Quantity X
    • product B1 from group B: Quantity Y
    • product B2 from group B: Quantity Y

    因为 Magento 是逐条套用规则,再逐条套用 quote item,所以上述情况下,product B1 和 product B2 都满足规则,统统赠送。为了解决不该送的数量被送掉了的问题,必须抛弃 GUI 了,动手编程吧。还好,这个特殊规则并不难写,我写了两个小时,搞掂。

    附注:不编程的话,还有一个不是办法的办法——turn product group B into a configurable product, and all the products become options。然后告诉用户,如果想得到免费赠品的话,add this configurable product to cart。但这样生添了一个 configurable product,其实这是 product group B 里产品的同质产品,同质产品却不同效应?这会给用户带来困惑,所以不可取。

  • Magento product model is read only to frontend controller

    最近我写了一个小程序:Deal of the day for Magento。

    它主要有以下功能:
    每天定时按预设权重随机抽取一个产品作为 deal of the day;在产品名称前加上 “Deal of the day:” 字样;设定它的 is_deal_of_the_day 为 true;设定一个 special price;归类到一个 sales category 下;同时把昨天的已过时的 deal 重置为原先状态。

    Magento 支持 cronjob 我是知道的,但测试的第一个环节倒不是这个程序能否定时启动,而是程序能否完成独立完成这一系列的操作。为求简单,我把整个过程写在一个 frontend controller 的 indexAction 里,然后用访问 url 的方式去触发这个过程。我没有用 backend controller,因为我考虑到 Magento wiki 上介绍的 cronjob 万一不管用(之前我没有用过 Magento conjob),我还可以用 curl + linux crontab (这个我很熟)去触发这个过程。当然我会把这个 url 做得谁都猜不到,以策安全。

    但是,在 frontend controller 里一运行到 $product->save() 或 $productCollection->save(),就抛出以下错误:

    Warning: Invalid argument supplied for foreach() in /path/to/magento/app/code/core/Mage/Eav/Model/Entity/Abstract.php on line 995

    初看这个错误,我总以为是 product EAV 某个 attribute 损坏了,因为我经常修改 product attributes,一不小心,改坏了哪个不该改的 attribute 也不奇怪。可难就难在 attributes 那么多,我无法知道哪个坏了啊。我围绕着 Abstract.php 995 行左看右看,没有头绪整整一个下午,最后发现,如果把同样代码放在 backend controller 里,product 就可以 save 了。

    整整一个下午的时间只给我一个启示:product model 在 frontend 是只读的,估计又属于 Magento 安全机制范畴。联想到以前碰到的一个问题:如果用户在 Magento backend 已登录,能否在 frontend 探知,以便针对 backend 用户访问 frontend 时显示不对外人开放的内容(就像 wordpress 那样会在每个 post 显示 edit link)。但 Magento 把 backend 和 frontend 严格地分开,我研究好久,也没有让 frontend 访问到 backend session。

    我想,打破 Magento 苦心经营的安全机制去做一些事是不可取的。比如 deal of the day 定时切换的功能,就用 magento 鼓励的 cron.php 去启动,非常的方便,也非常的安全。只是我空下来还是想钻牛角尖: Magento 是怎么把 backend 和 frontend 严格地分开的?只有知道了原理,如果、万一、假如、倘若我要 frontend 执行 backend 操作,也能做到了。

  • Magento 1.4 is not showing out of stock items in product list

    我用过 Magento 1.3。在 Magento 1.3 里,某产品脱销了,仍在前台出现,只是提示 out of stock。

    这其实很好,符合我的 business logic: 脱销总是暂时的,我不希望顾客在这段时间找不到这个产品而误以为该产品 discontinued。如果真遇到产品 discontinued,由 admin 在后台 disable product。Enable / disable 一个产品很方便,这样 admin 会感觉 everything is in control。

    可是 Magento 1.4 起,自动把脱销的产品从前台产品列表里过滤了。这个逻辑搞得我莫名其妙,一开始还以为是我搞错了设置或被我改动过的代码写错了,最后才发现 Magento 1.4 把 getLoadedProductCollection() 的返回值修改了。

    其实这个修改很糟糕,显然 Magento 1.4 在这点上考虑不成熟:如果顾客都找不到这个产品了,那 wishlist 还有用吗?再看 list.phtml 里

    
    <?php $_productCollection=$this->getLoadedProductCollection() ?>
    <?php if(!$_productCollection->count()): ?>
    <p><?php echo $this->__('There are no products matching the selection.') ?></p>
    <?php else: ?>
    <div>
    <?php echo $this->getToolbarHtml() ?>
    <?php // List mode ?>
    <?php if($this->getMode()!='grid'): ?>
    <?php $_iterator = 0; ?>
    <ol id="products-list">
    <?php foreach ($_productCollection as $_product): ?>
    
    ...
    
    <?php if($_product->isSaleable()): ?>
    <p><button type="button" title="<?php echo $this->__('Add to Cart') ?>" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><?php echo $this->__('Add to Cart') ?></span></span></button></p>
    <?php else: ?>
    <p><span><?php echo $this->__('Out of stock') ?></span></p>
    <?php endif; ?>
    
    

    $_productCollection 都过滤了脱销的产品,后面的 $_product->isSaleable() 岂不是多此一举?

    我还是得把 getLoadedProductCollection() 按 Magento 1.3 修改回去。

    2010 年 5 月 25 日更新:当我发现 Magento 把显示产品的逻辑从“默认包括 out of stock” 改为 “默认不包括 out of stock”,我想 Magento 应该会在后台提供一个修改默认值的地方。前几天我找了,没找到,所以抱怨说 Magento 自说自话地修改逻辑,其实我冤枉 Magento 了。

    今天我无意中发现这个默认值是可以被修改的,在 System configuration 的 Inventory tab。Inventory 的设置在全局生效,当选择 storeview 时是看不到 Inventory tab 的,所以当时我没发现它。

    Display out of stock products in Magento 1.4
    Display out of stock products in Magento 1.4
  • What happens when an order is cancelled in Magento?

    Order Status

    When you click Cancel button in an order view, order status changes to Cancelled if payment is not received (i.e. invoice is not raised).

    If payment is received before you click Cancel button, order status changes to Complete. You must raise a credit note to offset the payment, then the status changes to Closed. However, this order still counts in dashboard. This statistical result is not what I am expecting, but I think there is a reason inside.

    See table as summary

    Is payment received? No Yes
    Order status changes to >>>Cancelled >>>Complete (before credit note is raised)

    >>>Closed (after credit note is raised)

    What is order status when payment or credit is partially done?

    If an order is cancelled when payment is partially received, the status changes to Complete immediately as if full payment is received.

    If a Complete order is partially refunded, the status remains Complete. The status changes to Closed when customer is credited in full.

    See table as summary

    Payment is partially received >>>Complete (before credit note is raised)

    >>>Complete (credit noted is raised but partially)

    >>>Closed (after full refund)

    Will inventory level reverse itself when an order is cancelled? It depends.

    Reversal only happens if this order is not shipped AND payment is not received.

    See table as summary

    Order is not shipped

    AND

    payment is not received

    Order is shipped

    OR

    payment is received

    Inventory level Reversal No reversal on cancelling

    Will inventory level reverse itself when an order is cancelled after it is partially fulfilled? And how much is the reversed inventory?

    If an order is partially fulfilled (payment is partially received or shipment is partial), there are 3 types of quantity, Qty Ordered, Qty Invoiced, Qty Shipped, showing at order view. Then you click Cancel button, you get –

    Qty Cancelled = Qty Ordered – max (Qty Invoiced, Qty Shipped)

    Qty Cancelled is the quantity automatically reserved to inventory.

  • Understanding layout.xml syntax in Magento

    I write this article about my understanding of layout.xml up to now. I use it to show you

    • How to add buttons in order/invoice/shipment/creditmemo without override Block class?
    • How to define an array as a parameter in layout.xml using <action method=”addButton”><param>array</param></action>?
    • How to assign any type of variables in layout.xml?
    • How to avoid overriding controller class but still get the result you want on a specific url?

    as well.

    All my understanding was inspired by the task: adding buttons in order view at backend to offer administrators extra order process facilities.

    add-buttons-to-backend-order-view

    I love Magento class overriding architecture, but as I have learned the downside of overriding (Basically, there is only one chance of overriding for each class among all extension classes. Therefore, the more classes overridden, the greater chance of conflict between extensions.), I create a principle for my programming in Magento – do not override Magento class unless there is no other way around it.

    So, back to the task. It would be very easy to add the button if I had overridden Mage_Adminhtml_Block_Sales_Order_View. It could be

    public function __construct() {
    parent::__construct();
    $this->_addButton('new_button', array(
    'label'    => Mage::helper('sales')->__('New Button'),
    'onclick'  => "window.open('{$this->getUrlForNewButton()}')",
    ))
    ;
    }
    

    However, I do not want to override Mage_Adminhtml_Block_Sales_Order_View. How about firing addButton method in layout.xml? I see an example of addTab at the left side

    <block type="adminhtml/sales_order_view_tabs" name="sales_order_tabs">
    <action method="addTab"><name>order_info</name><block>order_tab_info</block></action>
    <action method="addTab"><name>order_invoices</name><block>adminhtml/sales_order_view_tab_invoices</block></action>
    <action method="addTab"><name>order_creditmemos</name><block>adminhtml/sales_order_view_tab_creditmemos</block></action>
    <action method="addTab"><name>order_shipments</name><block>adminhtml/sales_order_view_tab_shipments</block></action>
    <action method="addTab"><name>order_history</name><block>adminhtml/sales_order_view_tab_history</block></action>
    </block>
    
    

    In the example, addTab method takes two parameters, one for tab name and the other for block name. Inside addTab method, it creates a block object from the block name, which is passed in as a string. In fact, the tag name <name> or <block> is not significant in layout.xml. It does not represent parameter name in method. But the position is significant – the first tag is passed into method as the first parameter, and ditto the followings.

    Back to addButton method in Mage_Adminhtml_Block_Widget_Container. It takes at least two parameters, one as string and the second as associated array. So the layout.xml can be something like this:

    
    <reference name="sales_order_edit">
    <action method="addButton" translate="label">
    <name>new_button</name>
    <button_array><!-- this tag name is not significant -->
    <label>New Button</label>
    <onclick>window.open('{$this->getUrlForNewButton()}')</onclick>
    </button_array>
    </action>
    </reference>
    
    

    The difficult part is in <onclick> – it requires a variable of current order id. After some digging, I find another example:

    
    <reference name="footer_links">
    <action method="addLink" translate="label title" module="catalog" ifconfig="catalog/seo/site_map"><label>Site Map</label><url helper="catalog/map/getCategoryUrl" /><title>Site Map</title></action>
    </reference>
    

    So, I create a helper method to return url for new button and modify layout.xml to

    
    <reference name="sales_order_edit">
    <action method="addButton" translate="label">
    <name>new_button</name>
    <button_array><!-- this tag name is not significant -->
    <label>New Button</label>
    <onclick helper="mymodule/getUrlForNewButton"/>
    </button_array>
    </action>
    </reference>
    

    Unfortunately, it did not work. I assume the helper callback does not work if it is in the array. So I change the helper method to return an associated array directly as the second parameter for layout.xml and the final layout.xml is

    
    <reference name="sales_order_edit">
    <action method="addButton" translate="label">
    <name>new_button</name>
    <button helper="mymodule/getNewButtonSecondParam"/>
    </action>
    </reference>
    
    

    It works perfectly. I am very proud of myself.

    Some while ago, I overrode Mage_Catalog_ProductController just to register a variable in viewAction

    
    public function viewAction() {
    Mage::register('my_var', $value);
    parent::viewAction();
    }
    
    

    Now I reviewing that approach stupid. I could register a variable using layout.xml without any class overriding!

  • Magento 1.3 cannot work with memcached 1.4

    今天我注意到一个还未来得及升级的 Magento 1.3.2.3 的安装 down 了,原因是 Magento 1.3.2.3 无法和 memcached 1.4.4.2 协同工作(memcached 1.4.4.2 服务器环境自动升级带来的)。

    错误提示如下

    Notice: MemcachePool::delete() [memcachepool.delete]: Server 127.0.0.1 (tcp 11211, udp 0) failed with: CLIENT_ERROR bad command line format. Usage: delete [noreply]
    (0) in /……/magento/app/code/core/Zend/Cache/Backend/Memcached.php on line 271

    我按提示找到 Memcached.php 把第271行改为

    return $this->_memcache->delete($id, 0);
    

    仍旧无效。

    尝试着升级安装到 Magento 1.4.0.1,能支持 memcached 1.4.4.2 了。

    但网站布局变得乱七八糟,需要调整很多 template, layout 及 css 文件,这不是一时半会能完成的,只好暂用备份文件降级到 Magento 1.3.2.3,改用 apc backend cache。还好网站在单台服务器上运行,没涉及到分布式缓存,memcached 不是必需的。我装了 memcached 也没怎么玩它,缺乏掌控,暂时先搁置。

  • Customise Magento order number

    After I put a lot of test orders into Magento, now I want to delete them for a clean start. I also want to shorten the length of order number, and the order number from various stores share the global increment. I want the similar settings on Matgento invoice, shipment, and creditmemo.

    I have concluded these steps after some trials and errors.

    Firstly, empty orders, invoices, shipments, and creditmemo by executing mysql commands:

    
    TRUNCATE `magento_sales_flat_order_item`;
    TRUNCATE `magento_sales_flat_quote`;
    TRUNCATE `magento_sales_flat_quote_address`;
    TRUNCATE `magento_sales_flat_quote_address_item`;
    TRUNCATE `magento_sales_flat_quote_item`;
    TRUNCATE `magento_sales_flat_quote_item_option`;
    TRUNCATE `magento_sales_flat_quote_payment`;
    TRUNCATE `magento_sales_flat_quote_shipping_rate`;
    TRUNCATE `magento_sales_invoiced_aggregated`;
    TRUNCATE `magento_sales_invoiced_aggregated_order`;
    TRUNCATE `magento_sales_order`;
    TRUNCATE `magento_sales_order_aggregated_created`;
    TRUNCATE `magento_sales_order_datetime`;
    TRUNCATE `magento_sales_order_decimal`;
    TRUNCATE `magento_sales_order_entity`;
    TRUNCATE `magento_sales_order_entity_datetime`;
    TRUNCATE `magento_sales_order_entity_decimal`;
    TRUNCATE `magento_sales_order_entity_int`;
    TRUNCATE `magento_sales_order_entity_text`;
    TRUNCATE `magento_sales_order_entity_varchar`;
    TRUNCATE `magento_sales_order_int`;
    TRUNCATE `magento_sales_order_tax`;
    TRUNCATE `magento_sales_order_text`;
    TRUNCATE `magento_sales_order_varchar`;
    TRUNCATE `magento_sales_payment_transaction`;
    TRUNCATE `magento_sales_refunded_aggregated`;
    TRUNCATE `magento_sales_refunded_aggregated_order`;
    TRUNCATE `magento_sales_shipping_aggregated`;
    TRUNCATE `magento_sales_shipping_aggregated_order`;
    

    Then, go to table magento_eav_entity_type, find entity order, invoice, shipment, creditmemo, change increment_per_store to or not to share global increment (default is 1 which means each store has its own increment), change increment_pad_length to shorten or longer numbers (increment_pad_length does not include prefix: 1 digit by default).

    Then, empty table magento_eav_entity_store by executing:

    
    TRUNCATE `magento_eav_entity_store`;
    

    With an empty table, Magento generate default increment_prefix which is store id (with global increment setting, it is 0), and increment starts from 0.

    I want the first order, invoice, shipment, creditmemo number look like 100001, I set magento_eav_entity_type.increment_pad_length at 5, and insert 4 records into magento_eav_entity_store.

    Customise order, invoice, shipment, creditmemo number in Magento
    Customise order, invoice, shipment, creditmemo number in Magento

    And that’s it.

    2010年6月22日更新:我想提醒一下,光有几个 store_id = 0 的记录不够保险。因为几天后,我发现每个 storeview 都有了各自的记录,显然 storeview 的记录优先于 default (store_id = 0)。increment_prefix 默认为 store_id,这让每个 storeview 有了不同的前缀,与我初衷(所有 storeview 统一使用 “1” 为前缀)相悖。我不清楚后来这些自动添加的记录是由什么事件引发的。既然 increment_prefix 被改了,我只好接受这个事实,改来改后会让后台订单号看起来没有连续性。

    More data added to eav_entity_store
    More data added to eav_entity_store