{"id":345069,"date":"2026-08-01T20:00:17","date_gmt":"2026-08-01T20:00:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/store-migration-toolkit-for-fluentcart\/"},"modified":"2026-08-02T01:05:49","modified_gmt":"2026-08-02T01:05:49","slug":"pxelcode-migration-toolkit-for-fluentcart","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/pxelcode-migration-toolkit-for-fluentcart\/","author":20728874,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.1","stable_tag":"1.1.1","tested":"7.0.2","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Pxel Migration Toolkit for FluentCart","header_author":"esratpopy","header_description":"Migrates products, customers, orders, coupons and subscriptions from a WooCommerce store into FluentCart. Read-only against WooCommerce \u2014 your WooCommerce store stays untouched.","assets_banners_color":"f7f8fd","last_updated":"2026-08-02 01:05:49","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":33,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.7":{"tag":"1.0.7","author":"esratpopy","date":"2026-08-01 20:00:10"},"1.0.8":{"tag":"1.0.8","author":"esratpopy","date":"2026-08-01 20:03:44"},"1.1.1":{"tag":"1.1.1","author":"esratpopy","date":"2026-08-02 01:05:49"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3631275,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3631275,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3631275,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3631275,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.7","1.0.8","1.1.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3631275,"resolution":"1","location":"assets","locale":"","width":800,"height":708}},"screenshots":{"1":"Pre-flight Check tab, showing a read-only scan of WooCommerce data before migrating.","2":"Migration tab, with each step's progress and record counts."}},"plugin_section":[],"plugin_tags":[282,250438,87,4155,286],"plugin_category":[45,59],"plugin_contributors":[215229,208745],"plugin_business_model":[],"class_list":["post-345069","plugin","type-plugin","status-publish","hentry","plugin_tags-ecommerce","plugin_tags-fluentcart","plugin_tags-import","plugin_tags-migration","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_category-utilities-and-tools","plugin_contributors-esratpopy","plugin_contributors-pxelcode","plugin_committers-esratpopy"],"banners":{"banner":"https:\/\/ps.w.org\/pxelcode-migration-toolkit-for-fluentcart\/assets\/banner-772x250.png?rev=3631275","banner_2x":"https:\/\/ps.w.org\/pxelcode-migration-toolkit-for-fluentcart\/assets\/banner-1544x500.png?rev=3631275","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/pxelcode-migration-toolkit-for-fluentcart\/assets\/icon-128x128.png?rev=3631275","icon_2x":"https:\/\/ps.w.org\/pxelcode-migration-toolkit-for-fluentcart\/assets\/icon-256x256.png?rev=3631275","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/pxelcode-migration-toolkit-for-fluentcart\/assets\/screenshot-1.png?rev=3631275","caption":"Pre-flight Check tab, showing a read-only scan of WooCommerce data before migrating."}],"raw_content":"<!--section=description-->\n<p>This plugin moves your store data from WooCommerce into FluentCart, one entity at a time, in small AJAX batches so large catalogs don't hit PHP timeouts.<\/p>\n\n<p><strong>What gets migrated<\/strong><\/p>\n\n<ul>\n<li>Customers \u2014 deduplicated by email, from orders and registered users, with billing\/shipping addresses.<\/li>\n<li>Products \u2014 simple and variable, with variations, pricing, stock, and featured image.<\/li>\n<li>Orders \u2014 line items, billing\/shipping addresses, transactions, refunds, applied coupon codes.<\/li>\n<li>Coupons \u2014 code, type, amount, usage limits, expiry, product restrictions.<\/li>\n<li>Subscriptions \u2014 only if WooCommerce Subscriptions is active. Renewal orders are linked back to the subscription's parent order.<\/li>\n<li>Recount &amp; Verify \u2014 rebuilds customer lifetime value \/ purchase counts and coupon use counts from the orders actually migrated.<\/li>\n<\/ul>\n\n<p><strong>What does NOT get migrated (do these manually afterward)<\/strong><\/p>\n\n<ul>\n<li>Product categories and tags \u2014 FluentCart's category model differs structurally.<\/li>\n<li>Downloadable file attachments \u2014 re-attach under each product's Downloadable Asset(s). The Pre-flight Check tab has a \"Downloadable Files\" report listing every downloadable product\/variation with its file name and Media Library URL, so you're not hunting through the catalog product-by-product.<\/li>\n<li>Payment gateway credentials \u2014 reconnect Stripe\/PayPal\/etc. in FluentCart using the same accounts.<\/li>\n<li>Email templates \u2014 FluentCart has its own notification system.<\/li>\n<li>Order status history \/ WooCommerce order notes.<\/li>\n<li>Tax rate configuration \u2014 set up FluentCart's tax classes and rates directly.<\/li>\n<li>WooCommerce Subscriptions \"requires manual renewal\" fine print beyond collection_method, and any bill-times cap (WooCommerce subscriptions normally run until cancelled, so <code>bill_times<\/code> is imported as 0\/unlimited).<\/li>\n<\/ul>\n\n<p><strong>How it works<\/strong><\/p>\n\n<p>Each step (Customers, Products, Orders, Coupons, Subscriptions, Recount) runs as a series of small AJAX batches. A mapping table (<code>{prefix}pxwfcm_id_map<\/code>) records which WooCommerce ID became which FluentCart ID, so re-running a step skips records already migrated instead of duplicating them. A log table (<code>{prefix}pxwfcm_log<\/code>) records anything skipped or errored for review.<\/p>\n\n<p>Run the steps in order: Customers, Products, Orders, Coupons, Subscriptions, Recount. Orders depend on Customers and Products already being migrated; Subscriptions depend on Orders; Recount depends on everything else.<\/p>\n\n<p>This plugin does not modify WooCommerce data. It only reads from WooCommerce and writes into FluentCart.<\/p>\n\n<p><strong>Maintenance Tools tab<\/strong><\/p>\n\n<p>Repair tools for data already migrated, without re-running the full migration:<\/p>\n\n<ul>\n<li>Fix Prices \u2014 corrects product\/variation prices stored as a plain decimal instead of cents.<\/li>\n<li>Fix Stock \u2014 corrects out-of-stock or unlimited-stock records, including the parent-product manage_stock rollup that FluentCart's purchase check depends on.<\/li>\n<li>Fix Fulfillment Type \u2014 re-applies the Settings tab's fulfillment type to products already migrated.<\/li>\n<li>Fix External\/Affiliate Products \u2014 re-checks External\/Affiliate products for the inactive\/out-of-stock state that keeps them from being accidentally purchased.<\/li>\n<li>Clear Product Mapping (danger zone) \u2014 use after deleting products directly from FluentCart, so re-running Products recreates them instead of skipping them, since the mapping table doesn't otherwise know they were removed.<\/li>\n<\/ul>\n\n<h4>Rehearse first<\/h4>\n\n<p>The Migration tab has a Dry Run toggle \u2014 turn it on and every step simulates a full run, writing nothing to FluentCart, so you can see exactly what would be created, skipped, or warned on. Still test on a staging copy of your site before running for real against production, and take a database backup first regardless \u2014 dry run tells you what <em>would<\/em> happen, it isn't a substitute for a backup.<\/p>\n\n<h4>Requirements<\/h4>\n\n<ul>\n<li>WooCommerce active on the site.<\/li>\n<li>FluentCart installed and active.<\/li>\n<li>WordPress 6.0 or newer.<\/li>\n<li>PHP 7.4 or newer.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Make sure both WooCommerce and FluentCart are installed and active.<\/li>\n<li>Upload the plugin files to the <code>\/wp-content\/plugins\/pxelcode-migration-toolkit-for-fluentcart<\/code> directory, or install the plugin through the WordPress plugins screen directly.<\/li>\n<li>Activate the plugin through the 'Plugins' screen in WordPress.<\/li>\n<li>Go to the plugin's admin page (under the FluentCart menu, or its own top-level menu) and run the Pre-flight Check before migrating anything.<\/li>\n<li>Take a full database backup, then run the migration steps in order.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20modify%20my%20woocommerce%20store%3F\"><h3>Does this modify my WooCommerce store?<\/h3><\/dt>\n<dd><p>No. The plugin only reads from WooCommerce. It writes exclusively into FluentCart's own tables.<\/p><\/dd>\n<dt id=\"can%20i%20re-run%20a%20step%20if%20something%20goes%20wrong%3F\"><h3>Can I re-run a step if something goes wrong?<\/h3><\/dt>\n<dd><p>Yes. Every step is idempotent \u2014 already-migrated records are recognized via the internal ID map and skipped, not duplicated.<\/p><\/dd>\n<dt id=\"is%20there%20a%20dry-run%20mode%3F\"><h3>Is there a dry-run mode?<\/h3><\/dt>\n<dd><p>Yes. Toggle \"Dry run\" on the Migration tab and every step simulates a full run \u2014 same skip\/warning decisions as a real run \u2014 without writing anything to FluentCart. Each step's log entries are prefixed \"[DRY RUN]\" so simulated activity is never confused with a real migration.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20product%20categories%2C%20tags%2C%20and%20downloadable%20files%3F\"><h3>What happens to product categories, tags, and downloadable files?<\/h3><\/dt>\n<dd><p>These are not migrated automatically because FluentCart's data model differs structurally. They need to be re-created\/re-attached manually in FluentCart after migration. For downloadable files, Pre-flight Check's \"Downloadable Files\" report lists every file with its product and Media Library URL so you're not hunting through the catalog by hand.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Fixed: Pre-flight Check could fail outright (\"Request failed\") on stores with a large downloadable-product catalog \u2014 the 1.0.8 \"Downloadable Files\" scan had no bound on how long it could run and no fault isolation from the rest of the report. It's now capped to a bounded number of products per run (re-run after migrating to see the rest on very large catalogs), the request's time limit is raised, and each report section now fails independently \u2014 one section erroring can no longer take down the whole Pre-flight response.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Added: real Dry Run mode on the Migration tab. Every step (Customers, Products, Orders, Coupons, Subscriptions, Recount) can now simulate a full run \u2014 same logic, same skip\/warning decisions \u2014 without writing anything to FluentCart. A visible banner confirms when it's on, and each step's log line is prefixed \"[DRY RUN]\" so simulated activity is never confused with a real one. All actual database writes now funnel through one internal component (PXWFCM_Writer) so live and dry-run mode share identical code paths.<\/li>\n<\/ul>\n\n<h4>1.0.9<\/h4>\n\n<ul>\n<li>Renamed display name from \"PxelCode Migration Toolkit for FluentCart\" to \"Pxel Migration Toolkit for FluentCart\" (plugin header, readme, and on-page heading). Slug\/folder and text domain unchanged \u2014 this is an in-place update, no reinstall needed.<\/li>\n<\/ul>\n\n<h4>1.0.8<\/h4>\n\n<ul>\n<li>Added: Pre-flight Check now includes a \"Downloadable Files\" report \u2014 lists every downloadable product\/variation with its file name and Media Library URL, so files can be re-attached under FluentCart's Downloadable Asset(s) without hunting through the catalog product-by-product. Read-only, same as the rest of Pre-flight \u2014 doesn't touch WooCommerce or FluentCart data.<\/li>\n<\/ul>\n\n<h4>1.0.7<\/h4>\n\n<ul>\n<li>Fixed: variable-product variations with real, in-stock quantities (e.g. 5 in stock) still showed as unlimited stock even after the 1.0.6 fix. FluentCart's purchase check only enforces a variation's stock count when its parent product row is ALSO flagged as stock-managed \u2014 the parent flag was still being set from the raw (and often-off) WooCommerce store setting instead of following the same corrected logic as its variations. Both migration and the \"Fix Stock\" repair tool now roll the correct flag up to the parent.<\/li>\n<li>Fixed: \"WC Migrator\" under FluentCart's own admin menu could 404 and bounce to the dashboard, because our submenu was registered before FluentCart's own top-level menu existed (a well-known WordPress admin_menu timing issue). Now registered at a later priority so FluentCart's menu is guaranteed to exist first. The \"WC \u2192 FluentCart\" top-level menu item (separate from FluentCart's menu) was unaffected and still works either way.<\/li>\n<\/ul>\n\n<h4>1.0.6<\/h4>\n\n<ul>\n<li>Fixed: in-stock variable-product variations with a real WooCommerce quantity (e.g. 5 in stock) still migrated as unlimited stock \u2014 the 1.0.5 fix only forced manage_stock on for out-of-stock items, but managing_stock() itself returns false for every product when the store's global \"Manage stock\" option is off, even when individual products\/variations carry a real quantity. Stock resolution no longer relies on managing_stock() at all \u2014 if WooCommerce has a quantity on record, it's now trusted and carried over.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Fixed: out-of-stock products\/variations migrated as unlimited stock whenever WooCommerce wasn't quantity-tracking them (i.e. \"Manage stock\" off, Stock status set to Out of stock manually) \u2014 FluentCart only enforces out-of-stock when manage_stock is on, so this is now forced for out-of-stock items regardless of WooCommerce's tracking setting.<\/li>\n<li>Fixed: variable products whose variations were entirely out of stock and hidden from the catalog (a common WooCommerce setting) fell through to a \"no variations\" fallback that stored $0 as the price and unlimited stock. Variations are now fetched directly (not filtered by catalog visibility), so out-of-stock variations migrate with their real price and correct stock status.<\/li>\n<li>Added: \"Fix Stock\" maintenance tool to repair products\/variations already migrated before this fix, without re-running the full migration.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Maintenance release.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Renamed from \"Store Migration Toolkit for FluentCart\" (slug store-migration-toolkit-for-fluentcart) to \"PxelCode Migration Toolkit for FluentCart\" (slug pxelcode-migration-toolkit-for-fluentcart) per WordPress.org trademark-naming guidelines \u2014 the display name now leads with a distinctive term instead of a generic descriptive phrase. This is a new slug, not an in-place update: deactivate\/delete the old plugin and install this one.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Security\/compliance hardening: replaced mt_rand() with wp_rand() in UUID generation, escaped an exception message that could carry unescaped output, and guarded set_time_limit() with a function_exists() check.<\/li>\n<li>Documented and justified direct-database-query usage against the plugin's own fixed-name tables to satisfy Plugin Check.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release. Migrates customers, products, orders, coupons, and subscriptions from a WooCommerce store into FluentCart, with a read-only Pre-flight Check to scan for likely problem spots before migrating.<\/li>\n<\/ul>","raw_excerpt":"Migrates customers, products, orders, coupons and subscriptions from a WooCommerce store into FluentCart. Read-only against WooCommerce.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/345069","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=345069"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/esratpopy"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=345069"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=345069"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=345069"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=345069"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=345069"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=345069"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}