-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Canceling the orders that haven't been paid. #11257
Comments
Regarding this input ChannelUpdateInput {
...
expireOrdersAfter: Second
} As you described in #11337 we'll have |
It seems like it requires adding some new field to |
Thanks. Yes, exactly, it should be in OrderSettingsInput. Thanks for catching this! |
We will add new status to |
In type Shop {
...
"""
Default number of minutes stock will be reserved for anonymous checkout or null when stock reservation is disabled.
Added in Saleor 3.1.
Requires one of the following permissions: MANAGE_SETTINGS.
"""
reserveStockDurationAnonymousUser: Int
} I think we should keep it in minutes instead of seconds. Also when we introduce |
Any Staff users shouldn't be able to perform actions like:
|
Thanks @fowczarek for the feedback. I've updated the rfc. |
What I'm trying to achieve
With new payment's transaction flow, there is a possibility to create an order then paid for it. If customer cancels the payment process, we will end up with orders that haven't been paid and allocated stock. We need to have a mechanism to release stock and cancel the orders.
General assumptions
OrderSettings
inChannel
type should include a new fieldexpireOrdersAfter
of typeMinute
.channelCreate
andchannelUpdate
mutations should include a new input fieldexpireOrdersAfter
of typeMinute
.Channel
model should have a new fieldexpire_orders_after
to store the expiration delta. The default value for this field should be None, which means do not expire any orders.MANAGE_ORDERS
orMANAGE_CHANNELS
permissions should be able to updateOrderSettings
(Keep in mind thatMANAGE_ORDERS
can be used only to updateorderSettings
. That means, that user cannot use MANAGE_ORDERS permission on mutation that will updateOrderSettings
and otherChannel
field).unconfirmed
order, and only confirm it when a transaction is attached to the order (but only whenauto-confirm
is active).confirmed
(but only whenauto-confirm
is active).expired order
should be treated in the same way as acanceled order
, that means:expired order
should not be allowedinvoice
forexpired_order
orders_total
fromOrder
should not includeexpired order
expired order
cannot be captured or confirmedexpired orders
celery_beat
to convertunconfirmed
and not paid orders intoexpired orders
.expired orders
will have their stock released andvouchers
will be available again.order_expired
andorder_updated
event.CeleryTask
object should be added as a lock for celery tasks.Order.status
field new value:EXPIRED
.Describe a proposed solution
The proposed solution relays on the changes proposed in #11337.
Staff user will have a possibility to provide the time, that Saleor will use to change the unconfirmed and not paid orders into expired orders. We will release a stock allocation for these orders
API changes
OrderSettings
typeMutation
The
channelCreate
andchannelUpdate
mutations will get new input fields:Permission
MANAGE_ORDERS
orMANAGE_CHANNELS
will be required to updateorderSettings
.orderCreateFromCheckout
- will create unconfirmed order, Saleor will confirm it when transaction will be attached to the order (but only when auto-confirm is active).transactionCreate
- calling for order, should also mark order as confirmed (but only when auto-confirm is active).Changes in the core logic
Order
The expired order should be treated in the same way as cancel order. Any update action on it should not be allowed. (including invoice generate which is available on cancel for unknown reason).
There are voucher that can be used only once. Such voucher must set to be available after cancelling the order
Celery task
We will have a celery task that will be triggered by celery_beat. The main job of this task will be taking a batch of unconfirmed and not paid orders and converting them to expired orders. The stock allocation will be released.
We want to use batches as we have in
delete_expired_checkouts
task. We want to be sure that we’re executing only one task at the same time. We will add the modelCeleryTask
based on https://github.com/saleor/saleor/blob/main/saleor/core/models.py#L115.We will treat the
CeleryTask
object as our lock. Something similar to the celery solution described in cookbook: https://docs.celeryq.dev/en/latest/tutorials/task-cookbook.html#ensuring-a-task-is-only-executed-one-at-a-time. (linking only as an example, we should use DB model in our case).The
CeleryTask
model should have a field for task name, and we should use it to find an ongoing task.We attach a soft limit to the task (https://docs.celeryq.dev/en/stable/userguide/workers.html#time-limits), set it to 30 minutes, and remove the CeleryTask object in case of raised exception, same for expectedly finishing the task.
In case having
CeleryTask
withcreated_at < time.now() - 1 hour
, we will call log.error inside the task.(Reference: Internal link with discussion: https://saleorcommerce.slack.com/archives/C03E6UHTJ6T/p1669801908944829)
DB changes
The
Order.status
field will accept new value:EXPIRED
.The
Channel
model will recieve a new field for storing expiration delta:expire_orders_after
. Default set toNone
-None
means do not expire any ordersWebhooks
We will need to have a new event
order_expired
, that will be triggered when order is marked as expired.Additional actions:
reserveStockDurationAnonymousUser
from int to MinuteThe text was updated successfully, but these errors were encountered: