Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion includes/CLI.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ public static function orders( $args, $assoc_args ) {
}
}

$period_keys = array_filter(
array( 'days', 'weeks', 'months' ),
fn( $k ) => ! empty( $assoc_args[ $k ] )
);
if ( count( $period_keys ) > 1 ) {
WP_CLI::error( 'Use only one of --days, --weeks, or --months.' );
}
if ( ! empty( $period_keys ) && ( ! empty( $assoc_args['date-start'] ) || ! empty( $assoc_args['date-end'] ) ) ) {
WP_CLI::error( '--days, --weeks, and --months cannot be combined with --date-start or --date-end.' );
}
foreach ( $period_keys as $key ) {
if ( ! ctype_digit( (string) $assoc_args[ $key ] ) || (int) $assoc_args[ $key ] <= 0 ) {
WP_CLI::error( "--{$key} must be a positive integer." );
}
}

$progress = \WP_CLI\Utils\make_progress_bar( 'Generating orders', $amount );

add_action(
Expand Down Expand Up @@ -369,6 +385,24 @@ function () use ( $progress ) {
'description' => 'Randomize the order date using this as the upper limit. Only works in conjunction with date-start. Format as YYYY-MM-DD.',
'optional' => true,
),
array(
'name' => 'days',
'type' => 'assoc',
'description' => 'Generate orders within the past N days (from today going back). Cannot be combined with --date-start or --date-end.',
'optional' => true,
),
array(
'name' => 'weeks',
'type' => 'assoc',
'description' => 'Generate orders within the past N weeks (from today going back). Cannot be combined with --date-start or --date-end.',
'optional' => true,
),
array(
'name' => 'months',
'type' => 'assoc',
'description' => 'Generate orders within the past N months (from today going back). Cannot be combined with --date-start or --date-end.',
'optional' => true,
),
array(
'name' => 'status',
'type' => 'assoc',
Expand Down Expand Up @@ -401,7 +435,7 @@ function () use ( $progress ) {
'optional' => true,
)
),
'longdesc' => "## EXAMPLES\n\nwc generate orders 10\n\nwc generate orders 50 --date-start=2020-01-01 --date-end=2022-12-31 --status=completed --coupons",
'longdesc' => "## EXAMPLES\n\nwc generate orders 10\n\nwc generate orders 50 --days=21\n\nwc generate orders 100 --weeks=4 --status=completed --refund-ratio=0.2\n\nwc generate orders 200 --months=6 --status=completed\n\nwc generate orders 50 --date-start=2020-01-01 --date-end=2022-12-31 --status=completed --coupons",
) );

WP_CLI::add_command( 'wc generate bookings', array( 'WC\SmoothGenerator\CLI', 'bookings' ), array(
Expand Down
23 changes: 23 additions & 0 deletions includes/Generator/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ class Order extends Generator {
const REFUND_DISTRIBUTION_FULL_RATIO = 0.5;
const REFUND_DISTRIBUTION_PARTIAL_RATIO = 0.25;

/**
* Resolve --days, --weeks, --months into date-start so existing date logic can handle them.
* Has no effect if date-start is already set.
*
* @param array $assoc_args CLI arguments.
* @return array Modified arguments with date-start populated.
*/
protected static function resolve_date_period_args( array $assoc_args ) {
if ( ! empty( $assoc_args['date-start'] ) ) {
return $assoc_args;
}
if ( ! empty( $assoc_args['days'] ) ) {
$assoc_args['date-start'] = date( 'Y-m-d', strtotime( '-' . absint( $assoc_args['days'] ) . ' days' ) );
} elseif ( ! empty( $assoc_args['weeks'] ) ) {
$assoc_args['date-start'] = date( 'Y-m-d', strtotime( '-' . absint( $assoc_args['weeks'] ) . ' weeks' ) );
} elseif ( ! empty( $assoc_args['months'] ) ) {
$assoc_args['date-start'] = date( 'Y-m-d', strtotime( '-' . absint( $assoc_args['months'] ) . ' months' ) );
}
return $assoc_args;
}

/**
* Return a new order.
*
Expand All @@ -63,6 +84,7 @@ class Order extends Generator {
*/
public static function generate( $save = true, $assoc_args = array(), $date = null, $include_coupon = null, $refund_type = null ) {
parent::maybe_initialize_generators();
$assoc_args = self::resolve_date_period_args( $assoc_args );

$order = new \WC_Order();
$customer = self::get_customer();
Expand Down Expand Up @@ -272,6 +294,7 @@ public static function generate( $save = true, $assoc_args = array(), $date = nu
* @return int[]|\WP_Error
*/
public static function batch( $amount, array $args = array() ) {
$args = self::resolve_date_period_args( $args );
$amount = self::validate_batch_amount( $amount );
if ( is_wp_error( $amount ) ) {
error_log( 'Batch generation failed: ' . $amount->get_error_message() );
Expand Down
78 changes: 78 additions & 0 deletions tests/Unit/Generator/OrderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,84 @@ public function test_order_has_currency() {
$this->assertEquals( get_woocommerce_currency(), $currency );
}

/**
* Test order date falls within the past N days when --days is used.
*/
public function test_order_with_days_period() {
$order = Order::generate( true, array( 'days' => 14 ) );

$created_date = $order->get_date_created()->format( 'Y-m-d' );
$start = date( 'Y-m-d', strtotime( '-14 days' ) );
$today = date( 'Y-m-d' );

$this->assertGreaterThanOrEqual( $start, $created_date, 'Order date should be on or after 14 days ago' );
$this->assertLessThanOrEqual( $today, $created_date, 'Order date should be on or before today' );
}

/**
* Test order date falls within the past N weeks when --weeks is used.
*/
public function test_order_with_weeks_period() {
$order = Order::generate( true, array( 'weeks' => 2 ) );

$created_date = $order->get_date_created()->format( 'Y-m-d' );
$start = date( 'Y-m-d', strtotime( '-2 weeks' ) );
$today = date( 'Y-m-d' );

$this->assertGreaterThanOrEqual( $start, $created_date, 'Order date should be on or after 2 weeks ago' );
$this->assertLessThanOrEqual( $today, $created_date, 'Order date should be on or before today' );
}

/**
* Test order date falls within the past N months when --months is used.
*/
public function test_order_with_months_period() {
$order = Order::generate( true, array( 'months' => 1 ) );

$created_date = $order->get_date_created()->format( 'Y-m-d' );
$start = date( 'Y-m-d', strtotime( '-1 month' ) );
$today = date( 'Y-m-d' );

$this->assertGreaterThanOrEqual( $start, $created_date, 'Order date should be on or after 1 month ago' );
$this->assertLessThanOrEqual( $today, $created_date, 'Order date should be on or before today' );
}

/**
* Test all batch orders fall within the past N days when --days is used.
*/
public function test_batch_with_days_period() {
$order_ids = Order::batch( 5, array( 'days' => 30 ) );

$this->assertCount( 5, $order_ids, 'Should generate 5 orders' );

// Upper bound includes a one-day buffer to account for the hour offset added in generate().
$lower = strtotime( '-30 days' );
$upper = time() + DAY_IN_SECONDS;

foreach ( $order_ids as $order_id ) {
$timestamp = wc_get_order( $order_id )->get_date_created()->getTimestamp();
$this->assertGreaterThanOrEqual( $lower, $timestamp, 'Order date should be on or after 30 days ago' );
$this->assertLessThanOrEqual( $upper, $timestamp, 'Order date should not exceed today' );
}
}

/**
* Test that an explicit --date-start takes precedence over --days.
*/
public function test_days_does_not_override_explicit_date_start() {
$order = Order::generate(
true,
array(
'date-start' => '2024-03-01',
'date-end' => '2024-03-01',
'days' => 7,
)
);

$created_date = $order->get_date_created()->format( 'Y-m-d' );
$this->assertEquals( '2024-03-01', $created_date, 'Explicit date-start should take precedence over --days' );
}

/**
* Test refund dates are after order completion.
*/
Expand Down