Changeset 3398377
- Timestamp:
- 11/18/2025 09:51:54 PM (2 months ago)
- Location:
- product-sales-report-for-woocommerce
- Files:
-
- 10 edited
- 1 copied
-
tags/2.0.5 (copied) (copied from product-sales-report-for-woocommerce/trunk)
-
tags/2.0.5/admin/admin.php (modified) (1 diff)
-
tags/2.0.5/hm-product-sales-report.php (modified) (9 diffs)
-
tags/2.0.5/includes/reporters/base.php (modified) (1 diff)
-
tags/2.0.5/includes/reporters/woocommerce.php (modified) (2 diffs)
-
tags/2.0.5/readme.txt (modified) (1 diff)
-
trunk/admin/admin.php (modified) (1 diff)
-
trunk/hm-product-sales-report.php (modified) (9 diffs)
-
trunk/includes/reporters/base.php (modified) (1 diff)
-
trunk/includes/reporters/woocommerce.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
product-sales-report-for-woocommerce/tags/2.0.5/admin/admin.php
r3393922 r3398377 1353 1353 <div class="ninjalytics-settings-box ags-psr-advanced"> 1354 1354 <label class="ninjalytics-settings-label-column"> 1355 <input disabledtype="checkbox" name="report_unfiltered"'.(empty($reportSettings['report_unfiltered']) ? '' : ' checked="checked"').'>1356 <span class="label">Attempt to prevent other plugins or code from changing the export query or output <span class="ninjalytics-pro-badge">Pro</span>'./* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ self::docsLink( 'report-configuration/data-and-display', 'report-unfiltered' ).'</span>1355 <input type="checkbox" name="report_unfiltered"'.(empty($reportSettings['report_unfiltered']) ? '' : ' checked="checked"').'> 1356 <span class="label">Attempt to prevent other plugins or code from changing the export query or output</span> 1357 1357 </label> 1358 './* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ self::docsLink( 'report-configuration/data-and-display', 're move-html' ).'1358 './* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ self::docsLink( 'report-configuration/data-and-display', 'report-unfiltered' ).' 1359 1359 </div> 1360 1360 -
product-sales-report-for-woocommerce/tags/2.0.5/hm-product-sales-report.php
r3393922 r3398377 4 4 * Description: Generates a report on individual WooCommerce products sold during a specified time period. 5 5 * Plugin URI: https://berrypress.com/product/woocommerce/ninjalytics/ 6 * Version: 2.0. 47 * WC tested up to: 10. 26 * Version: 2.0.5 7 * WC tested up to: 10.3 8 8 * WC requires at least: 2.2 9 9 * Author: BerryPress … … 44 44 use Ninjalytics\Reporters\PlatformFeatures; 45 45 46 define('NINJALYTICS_VERSION', '2.0. 4');46 define('NINJALYTICS_VERSION', '2.0.5'); 47 47 48 48 add_filter('default_option_ninjalytics_settings', 'ninjalytics_psr_import'); … … 119 119 'refunds' => 1, 120 120 'adjustments' => 1, 121 'report_unfiltered' => 0, 121 122 'report_title_on' => 0, 122 123 'report_title' => '[preset] - [start] to [end]', … … 188 189 'builtin::discount' => 'Total Discount Amount', 189 190 'builtin::taxes' => 'Taxes' 190 ]; 191 ] 192 + ($reporter->supports(PlatformFeatures::COGS) ? [ 193 'builtin::cogs' => 'Cost of Goods Sold', 194 'builtin::profit' => 'Profit', 195 'builtin::margin' => 'Gross Margin', 196 'builtin::item_cogs' => 'Current COGS per Item', 197 ] : []); 191 198 192 199 foreach (ninjalytics_get_tax_types() as $taxTypeId => $taxType) { … … 356 363 foreach (array( 357 364 'limit_on', 'include_nil', 'include_shipping', 'include_unpublished', 'include_header', 'include_totals', 358 'format_amounts', 'exclude_free', 365 'format_amounts', 'exclude_free', 'report_unfiltered', 359 366 'refunds', 'adjustments', 'report_title_on', 'hm_psr_debug', 'disable_product_grouping', 'intermediate_rounding' 360 367 ) as $checkboxField) { … … 826 833 } 827 834 835 // Remove existing filters if the unfiltered option is on 836 if (!empty($_POST['report_unfiltered'])) { 837 remove_all_filters('woocommerce_reports_get_order_report_data_args'); 838 remove_all_filters('woocommerce_reports_order_statuses'); 839 remove_all_filters('woocommerce_reports_get_order_report_query'); 840 remove_all_filters('woocommerce_reports_get_order_report_data'); 841 } 842 828 843 // Avoid max join size error 829 844 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching … … 858 873 if (!empty($_POST['refunds'])) { 859 874 $refunded_products = ninjalytics_getReportData($wc_report, $baseFields, ($productsFiltered ? $product_ids : null), $start_date, $end_date, true); 860 $sold_products = ninjalytics_process_refunds($sold_products, $refunded_products, array (875 $sold_products = ninjalytics_process_refunds($sold_products, $refunded_products, array_merge(array( 861 876 'quantity', 862 877 'gross', 863 878 'gross_after_discount', 864 879 'taxes' 865 ), (int) $_POST['disable_product_grouping'], ((int) $_POST['disable_product_grouping']) == 2 ? 'product_category' : ''); 880 ), ($wc_report->supports(PlatformFeatures::COGS) ? ['cogs'] : [])), 881 (int) $_POST['disable_product_grouping'], ((int) $_POST['disable_product_grouping']) == 2 ? 'product_category' : ''); 866 882 } 867 883 … … 1159 1175 get_the_time('Y-m-d H:i:s', $productId); 1160 1176 }, $product->_product_ids); 1177 break; 1178 case 'builtin::cogs': 1179 $rowValue = $product->cogs ?? ''; 1180 break; 1181 case 'builtin::profit': 1182 $rowValue = isset($product->cogs) ? ($product->gross_after_discount - $product->cogs) : ''; 1183 break; 1184 case 'builtin::margin': 1185 $rowValue = isset($product->cogs) ? (($product->gross_after_discount - $product->cogs) / $product->gross_after_discount) : ''; 1186 break; 1187 case 'builtin::item_cogs': 1188 $rowValueDelimiter = ', '; 1189 $rowValue = array_map(function($itemId) { 1190 return get_post_meta($itemId, '_cogs_total_value', true); 1191 }, $product->_variation_ids ? $product->_variation_ids : ($product->_product_ids ? $product->_product_ids : [])); 1192 break; 1193 case 'builtin::cogs': 1194 $rowValue = $product->cogs ?? ''; 1195 break; 1196 case 'builtin::item_cogs': 1197 $rowValueDelimiter = ', '; 1198 $rowValue = array_map(function($itemId) { 1199 return get_post_meta($itemId, '_cogs_total_value', true); 1200 }, $product->_variation_ids ? $product->_variation_ids : ($product->_product_ids ? $product->_product_ids : [])); 1161 1201 break; 1162 1202 case 'builtin::line_item_count': … … 1367 1407 $rowValue = get_the_time('Y-m-d H:i:s', $productId); 1368 1408 break; 1409 case 'builtin::item_cogs': 1410 $rowValue = get_post_meta($variationId ? $variationId : $productId, '_cogs_total_value', true); 1411 break; 1369 1412 1370 1413 // hm-export-order-items-pro\hm-export-order-items-pro.php -
product-sales-report-for-woocommerce/tags/2.0.5/includes/reporters/base.php
r3393922 r3398377 14 14 case CHILD_ITEMS; 15 15 case META; 16 case COGS; 16 17 } 17 18 -
product-sales-report-for-woocommerce/tags/2.0.5/includes/reporters/woocommerce.php
r3379586 r3398377 55 55 56 56 public function getPlatformFeatures() { 57 return [PlatformFeatures::CHILD_ITEMS, PlatformFeatures::META, PlatformFeatures::VARIATIONS, PlatformFeatures::SHIPPING, PlatformFeatures::CUSTOMER_USERS ];57 return [PlatformFeatures::CHILD_ITEMS, PlatformFeatures::META, PlatformFeatures::VARIATIONS, PlatformFeatures::SHIPPING, PlatformFeatures::CUSTOMER_USERS, PlatformFeatures::COGS]; 58 58 } 59 59 … … 96 96 } 97 97 98 public function getDataParams($baseFields) { 99 $dataParams = parent::getDataParams($baseFields); 100 101 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a helper function, to be called after nonce is checked as needed 102 $intermediateRounding = !empty( $_POST['intermediate_rounding'] ); 103 104 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a helper function, to be called after nonce is checked as needed 105 if (empty($_POST['export_orders']) || in_array('builtin::cogs', $_POST['fields'] ?? [])) { 106 $dataParams[ '_cogs_value' ] = array( 107 'type' => 'order_item_meta', 108 'order_item_type' => 'line_item', 109 'function' => ($intermediateRounding ? 'PSRSUM' : 'SUM'), 110 'name' => 'cogs', 111 'join_type' => 'LEFT' 112 ); 113 } 114 return $dataParams; 115 } 98 116 99 117 public function getVirtualOrderMeta() { -
product-sales-report-for-woocommerce/tags/2.0.5/readme.txt
r3393922 r3398377 182 182 183 183 == Changelog == 184 185 = 2.0.5, 2025-11-18 = 186 - Add support for Cost of Goods 187 - Add new fields: 188 - Cost of Goods Sold 189 - Profit 190 - Gross Margin 191 - Current COGS per item 184 192 185 193 = 2.0.4, 2025-11-11 = -
product-sales-report-for-woocommerce/trunk/admin/admin.php
r3393922 r3398377 1353 1353 <div class="ninjalytics-settings-box ags-psr-advanced"> 1354 1354 <label class="ninjalytics-settings-label-column"> 1355 <input disabledtype="checkbox" name="report_unfiltered"'.(empty($reportSettings['report_unfiltered']) ? '' : ' checked="checked"').'>1356 <span class="label">Attempt to prevent other plugins or code from changing the export query or output <span class="ninjalytics-pro-badge">Pro</span>'./* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ self::docsLink( 'report-configuration/data-and-display', 'report-unfiltered' ).'</span>1355 <input type="checkbox" name="report_unfiltered"'.(empty($reportSettings['report_unfiltered']) ? '' : ' checked="checked"').'> 1356 <span class="label">Attempt to prevent other plugins or code from changing the export query or output</span> 1357 1357 </label> 1358 './* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ self::docsLink( 'report-configuration/data-and-display', 're move-html' ).'1358 './* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ self::docsLink( 'report-configuration/data-and-display', 'report-unfiltered' ).' 1359 1359 </div> 1360 1360 -
product-sales-report-for-woocommerce/trunk/hm-product-sales-report.php
r3393922 r3398377 4 4 * Description: Generates a report on individual WooCommerce products sold during a specified time period. 5 5 * Plugin URI: https://berrypress.com/product/woocommerce/ninjalytics/ 6 * Version: 2.0. 47 * WC tested up to: 10. 26 * Version: 2.0.5 7 * WC tested up to: 10.3 8 8 * WC requires at least: 2.2 9 9 * Author: BerryPress … … 44 44 use Ninjalytics\Reporters\PlatformFeatures; 45 45 46 define('NINJALYTICS_VERSION', '2.0. 4');46 define('NINJALYTICS_VERSION', '2.0.5'); 47 47 48 48 add_filter('default_option_ninjalytics_settings', 'ninjalytics_psr_import'); … … 119 119 'refunds' => 1, 120 120 'adjustments' => 1, 121 'report_unfiltered' => 0, 121 122 'report_title_on' => 0, 122 123 'report_title' => '[preset] - [start] to [end]', … … 188 189 'builtin::discount' => 'Total Discount Amount', 189 190 'builtin::taxes' => 'Taxes' 190 ]; 191 ] 192 + ($reporter->supports(PlatformFeatures::COGS) ? [ 193 'builtin::cogs' => 'Cost of Goods Sold', 194 'builtin::profit' => 'Profit', 195 'builtin::margin' => 'Gross Margin', 196 'builtin::item_cogs' => 'Current COGS per Item', 197 ] : []); 191 198 192 199 foreach (ninjalytics_get_tax_types() as $taxTypeId => $taxType) { … … 356 363 foreach (array( 357 364 'limit_on', 'include_nil', 'include_shipping', 'include_unpublished', 'include_header', 'include_totals', 358 'format_amounts', 'exclude_free', 365 'format_amounts', 'exclude_free', 'report_unfiltered', 359 366 'refunds', 'adjustments', 'report_title_on', 'hm_psr_debug', 'disable_product_grouping', 'intermediate_rounding' 360 367 ) as $checkboxField) { … … 826 833 } 827 834 835 // Remove existing filters if the unfiltered option is on 836 if (!empty($_POST['report_unfiltered'])) { 837 remove_all_filters('woocommerce_reports_get_order_report_data_args'); 838 remove_all_filters('woocommerce_reports_order_statuses'); 839 remove_all_filters('woocommerce_reports_get_order_report_query'); 840 remove_all_filters('woocommerce_reports_get_order_report_data'); 841 } 842 828 843 // Avoid max join size error 829 844 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching … … 858 873 if (!empty($_POST['refunds'])) { 859 874 $refunded_products = ninjalytics_getReportData($wc_report, $baseFields, ($productsFiltered ? $product_ids : null), $start_date, $end_date, true); 860 $sold_products = ninjalytics_process_refunds($sold_products, $refunded_products, array (875 $sold_products = ninjalytics_process_refunds($sold_products, $refunded_products, array_merge(array( 861 876 'quantity', 862 877 'gross', 863 878 'gross_after_discount', 864 879 'taxes' 865 ), (int) $_POST['disable_product_grouping'], ((int) $_POST['disable_product_grouping']) == 2 ? 'product_category' : ''); 880 ), ($wc_report->supports(PlatformFeatures::COGS) ? ['cogs'] : [])), 881 (int) $_POST['disable_product_grouping'], ((int) $_POST['disable_product_grouping']) == 2 ? 'product_category' : ''); 866 882 } 867 883 … … 1159 1175 get_the_time('Y-m-d H:i:s', $productId); 1160 1176 }, $product->_product_ids); 1177 break; 1178 case 'builtin::cogs': 1179 $rowValue = $product->cogs ?? ''; 1180 break; 1181 case 'builtin::profit': 1182 $rowValue = isset($product->cogs) ? ($product->gross_after_discount - $product->cogs) : ''; 1183 break; 1184 case 'builtin::margin': 1185 $rowValue = isset($product->cogs) ? (($product->gross_after_discount - $product->cogs) / $product->gross_after_discount) : ''; 1186 break; 1187 case 'builtin::item_cogs': 1188 $rowValueDelimiter = ', '; 1189 $rowValue = array_map(function($itemId) { 1190 return get_post_meta($itemId, '_cogs_total_value', true); 1191 }, $product->_variation_ids ? $product->_variation_ids : ($product->_product_ids ? $product->_product_ids : [])); 1192 break; 1193 case 'builtin::cogs': 1194 $rowValue = $product->cogs ?? ''; 1195 break; 1196 case 'builtin::item_cogs': 1197 $rowValueDelimiter = ', '; 1198 $rowValue = array_map(function($itemId) { 1199 return get_post_meta($itemId, '_cogs_total_value', true); 1200 }, $product->_variation_ids ? $product->_variation_ids : ($product->_product_ids ? $product->_product_ids : [])); 1161 1201 break; 1162 1202 case 'builtin::line_item_count': … … 1367 1407 $rowValue = get_the_time('Y-m-d H:i:s', $productId); 1368 1408 break; 1409 case 'builtin::item_cogs': 1410 $rowValue = get_post_meta($variationId ? $variationId : $productId, '_cogs_total_value', true); 1411 break; 1369 1412 1370 1413 // hm-export-order-items-pro\hm-export-order-items-pro.php -
product-sales-report-for-woocommerce/trunk/includes/reporters/base.php
r3393922 r3398377 14 14 case CHILD_ITEMS; 15 15 case META; 16 case COGS; 16 17 } 17 18 -
product-sales-report-for-woocommerce/trunk/includes/reporters/woocommerce.php
r3379586 r3398377 55 55 56 56 public function getPlatformFeatures() { 57 return [PlatformFeatures::CHILD_ITEMS, PlatformFeatures::META, PlatformFeatures::VARIATIONS, PlatformFeatures::SHIPPING, PlatformFeatures::CUSTOMER_USERS ];57 return [PlatformFeatures::CHILD_ITEMS, PlatformFeatures::META, PlatformFeatures::VARIATIONS, PlatformFeatures::SHIPPING, PlatformFeatures::CUSTOMER_USERS, PlatformFeatures::COGS]; 58 58 } 59 59 … … 96 96 } 97 97 98 public function getDataParams($baseFields) { 99 $dataParams = parent::getDataParams($baseFields); 100 101 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a helper function, to be called after nonce is checked as needed 102 $intermediateRounding = !empty( $_POST['intermediate_rounding'] ); 103 104 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a helper function, to be called after nonce is checked as needed 105 if (empty($_POST['export_orders']) || in_array('builtin::cogs', $_POST['fields'] ?? [])) { 106 $dataParams[ '_cogs_value' ] = array( 107 'type' => 'order_item_meta', 108 'order_item_type' => 'line_item', 109 'function' => ($intermediateRounding ? 'PSRSUM' : 'SUM'), 110 'name' => 'cogs', 111 'join_type' => 'LEFT' 112 ); 113 } 114 return $dataParams; 115 } 98 116 99 117 public function getVirtualOrderMeta() { -
product-sales-report-for-woocommerce/trunk/readme.txt
r3393922 r3398377 182 182 183 183 == Changelog == 184 185 = 2.0.5, 2025-11-18 = 186 - Add support for Cost of Goods 187 - Add new fields: 188 - Cost of Goods Sold 189 - Profit 190 - Gross Margin 191 - Current COGS per item 184 192 185 193 = 2.0.4, 2025-11-11 =
Note: See TracChangeset
for help on using the changeset viewer.