Skip to main content

Request a Quote

Goal​

Replace "add to cart" with "request a quote" for products whose price is negotiated. A visitor collects products in a quote basket, submits a request, exchanges messages with the shop, and receives offered prices. An accepted quote is converted into a real WooCommerce order. It is for trade, wholesale and made-to-order stores.

Tier and entitlement​

FieldValue
TierPremium
Entitlement keyquotes
Admin tabquotes
Module keyquotes
Settings prefixaiowc_qt_

Hooks register only when aiowc_module_enabled_quotes is true and the licence permits the quotes entitlement.

What the code does​

  • A quote basket held per visitor, driven by three admin-ajax actions that are registered for both signed-in and signed-out visitors.
  • A Request a Quote button rendered after the add-to-cart button on the single product page and in the shop loop.
  • Quote requests carrying the customer's email, name, phone, company and notes, plus the requested items.
  • A message thread on each quote, written to by both the customer and the shop.
  • Offered prices set per item by the shop, and a customer-facing accept action.
  • Conversion of an accepted quote into a WooCommerce order through wc_create_order().
  • A Quotes endpoint added to the WooCommerce My Account area, with its own menu item and page title.
  • Six transactional emails sent through wp_mail, driven by the module's own actions rather than the WooCommerce email system.

Quote statuses​

updateStatus() accepts exactly six: pending, replied, accepted, declined, expired and converted. Any other value is rejected.

Settings​

Read through ModuleSettings with the aiowc_qt_ prefix; defaults are QuotesModule::DEFAULTS.

SettingDefaultMeaning
enable_for_gueststrueWhether a signed-out visitor may request a quote
require_loginfalseWhether a request demands an account
quote_validity_days14Days a quote stays valid before the expiry job closes it
notification_emailemptyAddress the shop's copies are sent to
enable_negotiationstrueWhether the message thread is offered
min_quote_amount0Minimum basket value a request must reach
show_on_all_productsfalseWhether the quote button appears on every product rather than a selected set
basket_page_id0Page holding the quote basket shortcode
reminder_days_before3Days before expiry that the reminder is sent

Admin screen​

Admin tab quotes. It lists quotes with status and search filters, opens a quote to read and reply to its message thread, sets offered prices, changes status, converts an accepted quote to an order, and shows the overview figures.

Database schema​

Created by Schema/DatabaseSchema.php at schema version 1.0.0.

TableHolds
{prefix}aiowc_quotesThe request itself: customer details, status, notes and validity
{prefix}aiowc_quote_itemsRequested products, quantities and offered prices
{prefix}aiowc_quote_messagesThe message thread between customer and shop

REST endpoints​

Namespace aiowc/v1. All responses use the shared envelope.

Customer​

MethodPathPurposeRequired argsPermission
POST/quotesSubmit a quote request; also accepts name, phone, company, customer_notesemail, itemsPublic write check
GET/quotes/my-quotesThe customer's own quotes, paginated—Customer
GET/quotes/{id}Read one quoteidCustomer
POST/quotes/{id}/acceptAccept the offered pricesidCustomer
GET/quotes/{id}/messagesRead the threadidCustomer
POST/quotes/{id}/messagesPost a customer messageid, messageCustomer

Shop​

Permission: manage.

MethodPathPurposeRequired args
GET/quotes/adminList quotes, filterable by status and search, paginated—
GET/quotes/overviewAggregate figures for the admin overview—
POST/quotes/{id}/offerSet offered prices for the quote's itemsid, prices
POST/quotes/{id}/replyPost a shop messageid, message
PUT / PATCH / POST/quotes/{id}/statusChange status; optionally record notesid, status
POST/quotes/{id}/convertCreate a WooCommerce order from the quoteid
GET/quotes/settingsRead settings—
PUT / PATCH / POST/quotes/settingsUpdate settings—

WooCommerce and WordPress integration​

Storefront​

HookPriorityEffect
woocommerce_after_add_to_cart_buttondefaultRenders the quote button on the product page
woocommerce_after_shop_loop_item15Renders the quote button in the shop loop
wp_enqueue_scriptsdefaultLoads the module's assets

My Account​

HookPriorityEffect
initdefaultRegisters the quotes account endpoint
woocommerce_account_menu_itemsdefaultAdds the Quotes menu item
woocommerce_account_quotes_endpointdefaultRenders the quotes page
the_title10Supplies the endpoint's page title

Basket​

HookEffect
wp_ajax_aiowc_add_to_quote_basket / wp_ajax_nopriv_…Adds an item to the basket
wp_ajax_aiowc_remove_from_quote_basket / wp_ajax_nopriv_…Removes an item
wp_ajax_aiowc_update_quote_basket / wp_ajax_nopriv_…Updates quantities

Shortcode​

ShortcodePurpose
[aiowc_quote_basket]Renders the quote basket

No block is registered.

Emails and the actions behind them​

The notification service listens to four of the module's own actions and sends through wp_mail.

ActionEmails sent
aiowc_quote_createdShop notification, customer confirmation
aiowc_quote_status_changedAccepted, declined, expired or converted notice to the customer
aiowc_quote_admin_replyReply notice to the customer
aiowc_quote_customer_messageMessage notice to the shop

Background jobs​

All three run on the WordPress cron scheduler.

HookSchedulePurpose
aiowc_raq_check_expirationHourlyExpires quotes past quote_validity_days
aiowc_quote_reminderTwice dailySends the reminder reminder_days_before expiry
aiowc_raq_cleanupDailyRemoves stale quote data

Entitlement limits​

The quotes entitlement gates the module as a whole. min_quote_amount is a shop-configured floor on a request, not a licence limit, and the module caps neither the number of quotes nor the items in one.