Custom Order Statuses
Order statuses of your own, each one saying plainly whether it counts as paid, whether it reduces stock, and what email it sends, with a bulk action in the orders list.
by George Vasiliades · github.com/poseidonas/custom-order-statuses · website
Install
The author publishes release zips, so WP-CLI can install straight from GitHub:
wp plugin install https://github.com/poseidonas/custom-order-statuses/releases/download/v1.0.0/custom-order-statuses.zipDeclares an update source (https://github.com/Poseidonas/custom-order-statuses), so updates arrive through the plugin's own updater.
Readme
Custom Order Statuses
Order statuses of your own, added to the ones WooCommerce ships with. Each one says plainly whether it counts as paid, whether it takes items out of stock, and what email it sends, and each can be offered as a bulk action in the orders list.
- Author: George Vasiliades - https://github.com/Poseidonas
- License: GPL-2.0-or-later
- Requires WordPress 6.7 or newer
- Requires PHP 8.0 or newer
- Requires WooCommerce 9.0 or newer, tested up to 11.0
- Compatible with High-Performance Order Storage and with the cart and checkout blocks
- Settings live in WooCommerce > Order Statuses
What was measured before writing this
Measured on WooCommerce 11.0.1:
| Question | Result |
|---|---|
| How many statuses does the core have? | Eight, with no screen for adding your own |
| Which count as paid? | processing and completed, through the woocommerce_order_is_paid_statuses filter, which is free |
| Which reduce stock? | processing, completed and on-hold, each through its own woocommerce_order_status_{status} action |
| How wide is the status column? | varchar(20) on the HPOS orders table |
That last row is the one that matters, and it is easy to miss. Three of those twenty characters are taken by the wc- prefix WooCommerce adds, leaving seventeen. Verified by writing a longer value straight to the database:
key of 28 characters → stored as [wc-aaaaaaaaaaaaaaaaa], length 20 → CUT
A status whose key is cut is not the status you registered. Orders land in a value that exists nowhere: invisible to the filters in the orders list, missing from reports, and skipped by every email. So the key is limited to seventeen characters here, where you can see it happen, instead of silently in the database.
What you set per status
Name is what you and your customers see. Key is what WooCommerce stores; leave it empty and it is made from the name, as long as the name is written in Latin letters. A Greek or Cyrillic name produces no usable key, so the plugin says so and asks you to fill one in rather than inventing something unreadable.
Counts as paid adds the status to wc_get_is_paid_statuses(). This is what reports, customer totals and $order->is_paid() all read, so leave it off for anything that comes before payment.
Reduces stock hooks the status into the same routine the core uses. WooCommerce marks an order as stock-reduced once, so a status that reduces stock after processing already did will not take the items twice. Verified: an order moved to a stock-reducing status took 3 items out of 100, and moving it on to another status took nothing more.
Email sends to the customer or to the shop, with your own subject, heading and message. Nothing is sent when set to none.
Bulk action offers it in the orders list, on the HPOS screen and the older one alike. Position orders the list on the settings page.
The emails
Each status that sends email registers a proper WC_Email, so it appears in WooCommerce > Settings > Emails alongside the built-in ones, with its own enable switch, subject, heading and format. It uses the plugin's own template inside the standard WooCommerce wrapper, so your message is the message and the order details follow underneath, rather than borrowing the wording of another email.
Write {order_number}, {site_title}, {customer_name} or {status} and they are filled in.
Removing a status
A status that still holds orders is not removed. The list shows how many, linked to those orders, so you can move them somewhere else first. This is deliberate: removing a status while orders sit in it leaves them in a value nothing recognises.
Honest limits
- These are statuses, not a workflow engine. Nothing moves an order automatically from one to another.
- A status added here exists while the plugin is active. Deactivate it and orders sitting in that status keep the value in the database, but WooCommerce no longer knows the name. Bring the plugin back and they read correctly again. This is why removal is blocked while a status is in use.
- Reports built by WooCommerce Analytics read their own settings for which statuses to include. Marking a status as paid covers
is_paid()and the classic reports; the Analytics screens have their own list under WooCommerce settings. - The plugin does not rename or replace the eight core statuses, and refuses a key that matches one.
- Payment gateways decide for themselves which statuses they treat as final. A custom status is not offered to a gateway as a payment destination.
Filters
add_filter( 'icxcnika_cos_statuses', function ( array $statuses ): array {
return $statuses;
} );
icxcnika_cos_statuses receives the defined statuses before they are registered and is the last word on what exists. icxcnika_cos_registry_payload receives the data sent to the installation registry.
Data stored
- Option
icxcnika_cos_statuses(the statuses you defined). - Email settings are stored by WooCommerce itself (
woocommerce_icxcnika_cos_*options), as for any other email. - Option
icxcnika_cos_registry_key(random installation key of 48 characters, created only if installation reporting is active). - Transients
icxcnika_cos_release(cached GitHub release lookup, 12 hours) andicxcnika_cos_flush(one-off rewrite flush marker). - Cron event
icxcnika_cos_registry_ping(weekly, only if installation reporting is active).
Nothing is written to orders beyond their status, which WooCommerce writes.
Installation reporting
On activation, on deactivation and once a week the plugin sends a small JSON message to the author's installation registry: plugin slug, plugin version, home URL, site URL, WordPress version, WooCommerce version, PHP version, locale and whether the site is a multisite. Each report carries a random installation key generated locally on first use. No order, customer or status data is ever sent.
The reporting address is empty by default, which means nothing is sent at all. Add define( 'ICXCNIKA_REGISTRY_DISABLE', true ); to wp-config.php to turn the reporting off, or define( 'ICXCNIKA_REGISTRY_URL', '...' ); to point it elsewhere.
Updates
Updates are delivered from GitHub Releases through the Update URI header of WordPress. The Plugins screen shows View details and allows automatic updates to be enabled, exactly as for a plugin from the directory.
Uninstall
Deleting the plugin removes the option holding your statuses, the installation key, the cached release check and the scheduled report. Orders are not touched, so move any orders out of a custom status before deleting the plugin.
Custom Order Statuses (Ελληνικά)
Δικές σας καταστάσεις παραγγελίας, δίπλα σε αυτές που έρχονται με το WooCommerce. Καθεμιά δηλώνει καθαρά αν μετράει ως πληρωμένη, αν αφαιρεί είδη από το απόθεμα, και τι email στέλνει, και καθεμιά μπορεί να προσφέρεται ως μαζική ενέργεια στη λίστα παραγγελιών.
- Δημιουργός: George Vasiliades - https://github.com/Poseidonas
- Άδεια: GPL-2.0-or-later
- Απαιτεί WordPress 6.7 ή νεότερο
- Απαιτεί PHP 8.0 ή νεότερη
- Απαιτεί WooCommerce 9.0 ή νεότερο, δοκιμασμένο έως 11.0
- Συμβατό με το High-Performance Order Storage και με τα μπλοκ καλαθιού και ταμείου
- Οι ρυθμίσεις βρίσκονται στο WooCommerce > Καταστάσεις παραγγελίας
Τι μετρήθηκε πριν γραφτεί
Μετρήθηκε σε WooCommerce 11.0.1:
| Ερώτημα | Αποτέλεσμα |
|---|---|
| Πόσες καταστάσεις έχει ο πυρήνας; | Οκτώ, χωρίς καμία οθόνη για να προσθέσετε δικές σας |
| Ποιες μετράνε ως πληρωμένες; | Οι processing και completed, μέσω του φίλτρου woocommerce_order_is_paid_statuses, που είναι ελεύθερο |
| Ποιες μειώνουν απόθεμα; | Οι processing, completed και on-hold, καθεμιά μέσω της δικής της ενέργειας woocommerce_order_status_{status} |
| Πόσο πλατιά είναι η στήλη κατάστασης; | varchar(20) στον πίνακα παραγγελιών του HPOS |
Η τελευταία γραμμή είναι αυτή που μετράει, και εύκολα περνά απαρατήρητη. Τρεις από τους είκοσι χαρακτήρες τους πιάνει το πρόθεμα wc- που προσθέτει το WooCommerce, αφήνοντας δεκαεπτά. Επαληθεύτηκε γράφοντας μεγαλύτερη τιμή απευθείας στη βάση:
κλειδί 28 χαρακτήρων → αποθηκεύτηκε ως [wc-aaaaaaaaaaaaaaaaa], μήκος 20 → ΚΟΠΗΚΕ
Μια κατάσταση με κομμένο κλειδί δεν είναι η κατάσταση που καταχωρήσατε. Οι παραγγελίες καταλήγουν σε μια τιμή που δεν υπάρχει πουθενά: αόρατη στα φίλτρα της λίστας παραγγελιών, απούσα από τις αναφορές, και παραλείπεται από κάθε email. Γι' αυτό το κλειδί περιορίζεται στους δεκαεπτά χαρακτήρες εδώ, όπου το βλέπετε να συμβαίνει, αντί σιωπηλά μέσα στη βάση.
Τι ορίζετε ανά κατάσταση
Το Όνομα είναι αυτό που βλέπετε εσείς και οι πελάτες σας. Το Κλειδί είναι αυτό που αποθηκεύει το WooCommerce· αφήστε το κενό και παράγεται από το όνομα, εφόσον το όνομα είναι γραμμένο με λατινικούς χαρακτήρες. Ένα ελληνικό ή κυριλλικό όνομα δεν παράγει χρήσιμο κλειδί, οπότε το πρόσθετο το λέει και ζητά να το συμπληρώσετε, αντί να επινοήσει κάτι δυσανάγνωστο.
Το Μετράει ως πληρωμένη προσθέτει την κατάσταση στο wc_get_is_paid_statuses(). Αυτό διαβάζουν οι αναφορές, τα σύνολα πελατών και το $order->is_paid(), οπότε αφήστε το ανενεργό για ό,τι προηγείται της πληρωμής.
Το Μειώνει απόθεμα συνδέει την κατάσταση με την ίδια ρουτίνα που χρησιμοποιεί ο πυρήνας. Το WooCommerce σημειώνει μια παραγγελία ως μειωμένη σε απόθεμα μία φορά, οπότε μια κατάσταση που μειώνει απόθεμα αφού το έκανε ήδη η processing δεν θα αφαιρέσει τα είδη δεύτερη φορά. Επαληθεύτηκε: παραγγελία που πήγε σε κατάσταση με μείωση αποθέματος αφαίρεσε 3 από τα 100, και η μετακίνησή της σε επόμενη κατάσταση δεν αφαίρεσε τίποτα άλλο.
Το Email στέλνει στον πελάτη ή στο κατάστημα, με δικό σας θέμα, επικεφαλίδα και μήνυμα. Τίποτα δεν στέλνεται όταν είναι ορισμένο σε καμία αποστολή.
Η Μαζική ενέργεια την προσφέρει στη λίστα παραγγελιών, τόσο στην οθόνη HPOS όσο και στην παλαιότερη. Η Θέση ταξινομεί τη λίστα στη σελίδα ρυθμίσεων.
Τα emails
Κάθε κατάσταση που στέλνει email καταχωρεί κανονικό WC_Email, οπότε εμφανίζεται στο WooCommerce > Ρυθμίσεις > Email δίπλα στα ενσωματωμένα, με δικό της διακόπτη ενεργοποίησης, θέμα, επικεφαλίδα και μορφή. Χρησιμοποιεί το δικό του πρότυπο του πρόσθετου μέσα στο κανονικό περίβλημα του WooCommerce, ώστε το μήνυμά σας να είναι το μήνυμα και τα στοιχεία της παραγγελίας να ακολουθούν από κάτω, αντί να δανείζεται τη διατύπωση άλλου email.
Γράψτε {order_number}, {site_title}, {customer_name} ή {status} και συμπληρώνονται.
Αφαίρεση κατάστασης
Μια κατάσταση που έχει ακόμα παραγγελίες δεν αφαιρείται. Η λίστα δείχνει πόσες, με σύνδεσμο σε εκείνες τις παραγγελίες, ώστε να τις μεταφέρετε πρώτα αλλού. Αυτό είναι σκόπιμο: η αφαίρεση κατάστασης ενώ κάθονται παραγγελίες μέσα της τις αφήνει σε τιμή που δεν αναγνωρίζει τίποτα.
Τίμιοι περιορισμοί
- Πρόκειται για καταστάσεις, όχι για μηχανή ροής εργασίας. Τίποτα δεν μετακινεί παραγγελία αυτόματα από τη μία στην άλλη.
- Μια κατάσταση που προστίθεται εδώ υπάρχει όσο το πρόσθετο είναι ενεργό. Απενεργοποιήστε το και οι παραγγελίες που κάθονται σε αυτή κρατούν την τιμή στη βάση, αλλά το WooCommerce δεν ξέρει πια το όνομα. Επαναφέρετε το πρόσθετο και διαβάζονται ξανά σωστά. Γι' αυτό η αφαίρεση εμποδίζεται όσο μια κατάσταση είναι σε χρήση.
- Οι αναφορές του WooCommerce Analytics διαβάζουν δικές τους ρυθμίσεις για το ποιες καταστάσεις περιλαμβάνουν. Η σήμανση μιας κατάστασης ως πληρωμένης καλύπτει το
is_paid()και τις κλασικές αναφορές· οι οθόνες Analytics έχουν δική τους λίστα στις ρυθμίσεις του WooCommerce. - Το πρόσθετο δεν μετονομάζει ούτε αντικαθιστά τις οκτώ καταστάσεις του πυρήνα, και απορρίπτει κλειδί που ταιριάζει με κάποια από αυτές.
- Οι πύλες πληρωμής αποφασίζουν μόνες τους ποιες καταστάσεις θεωρούν τελικές. Μια δική σας κατάσταση δεν προσφέρεται σε πύλη ως προορισμός πληρωμής.
Φίλτρα
add_filter( 'icxcnika_cos_statuses', function ( array $statuses ): array {
return $statuses;
} );
Το icxcnika_cos_statuses δέχεται τις ορισμένες καταστάσεις πριν καταχωρηθούν και έχει τον τελευταίο λόγο για το τι υπάρχει. Το icxcnika_cos_registry_payload δέχεται τα δεδομένα που στέλνονται στο μητρώο εγκαταστάσεων.
Δεδομένα που αποθηκεύονται
- Option
icxcnika_cos_statuses(οι καταστάσεις που ορίσατε). - Οι ρυθμίσεις email αποθηκεύονται από το ίδιο το WooCommerce (options
woocommerce_icxcnika_cos_*), όπως για κάθε άλλο email. - Option
icxcnika_cos_registry_key(τυχαίο κλειδί εγκατάστασης 48 χαρακτήρων, δημιουργείται μόνο αν είναι ενεργή η αναφορά εγκατάστασης). - Transients
icxcnika_cos_release(cache της αναζήτησης έκδοσης στο GitHub, 12 ώρες) καιicxcnika_cos_flush(σημείο εφάπαξ ανανέωσης rewrite). - Cron event
icxcnika_cos_registry_ping(εβδομαδιαίο, μόνο αν είναι ενεργή η αναφορά εγκατάστασης).
Στις παραγγελίες δεν γράφεται τίποτα πέρα από την κατάστασή τους, την οποία γράφει το WooCommerce.
Read the full README on GitHub →
Releases
| Tag | Published | Asset | Downloads |
|---|---|---|---|
| v1.0.0 | Aug 19, 2026 | custom-order-statuses.zip | 1 |