Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command to purge expired pending orders. #1217

Merged
merged 9 commits into from
Mar 22, 2014

Conversation

kayue
Copy link
Contributor

@kayue kayue commented Mar 18, 2014

No description provided.

*
* @author Ka-Yue Yeung <kayuey@gmail.com>
*/
interface PurgerInterface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could reuse the interface from CartBundle actually, couldn't you?

@foopang
Copy link
Contributor

foopang commented Mar 18, 2014

@winzou Updated, please have a look.

@winzou
Copy link
Contributor

winzou commented Mar 18, 2014

I'm a bit confused, who is @foopang? :D

@winzou
Copy link
Contributor

winzou commented Mar 18, 2014

@kayue what is this sylius.inventory.holding.duration? I must say i like the standard duration format used here.

@kayue / @foopang please add specs for the purger. And we need to release inventory before deleting order, right?

@foopang
Copy link
Contributor

foopang commented Mar 18, 2014

@winzou I work with @kayue at 101 Media Lab LOL

@kayue
Copy link
Contributor Author

kayue commented Mar 18, 2014

@winzou By release inventory, did you mean those on-hold? It should be done in another command, because it happens a lot earlier.

We release inventory after 15 minutes, and we purge order after 3 hours.

@winzou
Copy link
Contributor

winzou commented Mar 18, 2014

@kayue yes I meant it. Whatever the other command, we need to release inventory units here before the deletion (and if onhold=0 then it will do nothing) to ensure that we don't delete onhold units.

Can you try to add the release command in this PR? Should be quite similar.

You release inventory after 15 minutes only at the end? You told me before that you might have late payments in your solution and couldn't release after only 15min. What has changed since?

@kayue
Copy link
Contributor Author

kayue commented Mar 18, 2014

So we will have two commands:

  • sylius:order:release
    Release on-hold inventory, by checking inventory unit's shipping state (onhold) and updated time.
  • sylius:order:purge
    Remove expired pending orders. Do not remove if order contain on-hold inventory unit.

PayPal could clear payment after 2 weeks, and there is nothing I can do about it. And you just remind me something, I think we cannot delete the order here.. We have to change order state to STATE_ABANDONED, and change it to STATE_CONFIRMED when we receive the payment later. Agree?

@kayue
Copy link
Contributor Author

kayue commented Mar 18, 2014

@winzou Should we combine OrderInterface::STATE_ABANDONED and OrderInterface::STATE_CANCELLED?

Less state is less confusing...

@kayue
Copy link
Contributor Author

kayue commented Mar 18, 2014

@winzou Actually order is soft delete, do we still want to delete them at all? or just change the state is enough?

@winzou
Copy link
Contributor

winzou commented Mar 18, 2014

Indeed we should delete nothing here. Let's just change the state to ABANDONED.
I think we do need 2 separate states (for statistics purposes) so let's keep CANCELLED for human action and ABANDONE for timeout. We will have a way to configure dynamically all these states anyway.

And how do you ensure you have enough inventory if you release them after 15min and receive payment after 2 weeks?

@kayue
Copy link
Contributor Author

kayue commented Mar 18, 2014

@winzou We can't ensure. It will result in backordered.


$queryBuilder
->andWhere($queryBuilder->expr()->lt($this->getAlias().'.updatedAt', ':expiresAt'))
->andWhere($queryBuilder->expr()->eq($this->getAlias().'.state', OrderInterface::STATE_PENDING))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or

->andWhere($this->getAlias().'.state = :state')
->setParameter('state', OrderInterface::STATE_PENDING)

@stloyd stloyd added this to the 1.0.0-BETA1 milestone Mar 18, 2014
@foopang
Copy link
Contributor

foopang commented Mar 19, 2014

@kayue / @winzou Updated, please review.

We do not change order status to cart when releasing orders because it will make the purge orders command useless.

$orders = $this->repository->findExpiredPendingOrders($expiresAt);
foreach ($orders as $order) {
$this->dispatcher->dispatch(SyliusOrderEvents::PRE_RELEASE, new GenericEvent($order));
$this->dispatcher->dispatch(SyliusOrderEvents::POST_RELEASE, new GenericEvent($order));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still can't dispatch this event before the flush.

edit: can not

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put the flush inside the foreach loop?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best way is to loop over $orders twice I think, with the flush between the 2 loops.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, updated.

@pjedrzejewski
Copy link
Member

Nice work @foopang! I think it would be good idea to move the logic of Release command to a separate service, so that it can be used outside of the CLI. What do you think? It should be quite easy!

/**
* Get the order from event and void payment.
*
* @param GenericEvent $event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @throws param.

protected function execute(InputInterface $input, OutputInterface $output)
{
$holdingDuration = $this->getContainer()->getParameter('sylius.inventory.holding.duration');
$expiresAt = new \DateTime(sprintf('-%s', $holdingDuration));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those two lines should go into else after that if ($input->isInteractive()) {} call.

@foopang
Copy link
Contributor

foopang commented Mar 22, 2014

@pjedrzejewski I've moved the logic of Release command to a separate service.

pjedrzejewski pushed a commit that referenced this pull request Mar 22, 2014
Command to purge expired pending orders.
@pjedrzejewski pjedrzejewski merged commit ca1f52a into Sylius:master Mar 22, 2014
@pjedrzejewski
Copy link
Member

@foopang @kayue Thank you guys! 👍 One thing to do later is maybe make the Purger service stateless and pass the $expiresAt as method argument instead of setting it. Now if you use it more than once, you can get unexpected expires at setting from the previous usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Minor issues and PRs improving the current solutions (optimizations, typo fixes, etc.).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants