Skip to content

For Developers โ€‹

Falcon Wholesale is built on the shop's logic hooks, and exposes hooks of its own so a theme or another plugin can change what it does. Register them in a theme's functions.php or a plugin's service provider. A filter returns its first argument, changed or not.


Who is wholesale, and at what price โ€‹

HookTypeArgumentsUse it to
falcon_wholesale_customer_levelfilter?Level $level, ?User $userMake someone wholesale by another rule, or take it away. Return a Level or null.
falcon_wholesale_pricefilter?float $price, array $contextChange the wholesale price: quantity tiers, a price list per customer, rounding. $context holds post_id, variation_id, level, quantity (the cart line's quantity in the cart), retail (['price', 'sale_price']) and source (variation, product, category, level or null). Return null for the retail price.
falcon_wholesale_category_discountfilterfloat $percent, int $postId, Level $levelChange the category discount (0โ€“100).
falcon_wholesale_tiersfilterarray $tiers, int $postId, Level $levelChange the quantity tiers that apply: each ['level' => int, 'min' => int, 'max' => ?int, 'type' => 'percent'|'price', 'value' => float].
falcon_wholesale_tier_labelfilter?string $label, array $tier, int $postId, int $quantityChange how a line's price tier is written ("20+ pcs ยท เงณ30.00 each").
falcon_wholesale_hidden_price_htmlfilterstring $html, $product, string $context, bool $guestChange what replaces a hidden price ($context price) or buy button (cart).
php
// 5% more off from 50 pieces.
add_falcon_filter('falcon_wholesale_price', function ($price, $context) {
    return $price !== null && $context['quantity'] >= 50 ? $price * 0.95 : $price;
});

Ordering rules โ€‹

HookTypeArgumentsUse it to
falcon_wholesale_product_rulesfilterarray $rules, int $postId, Level $levelChange ['min_qty' => ?int, 'qty_step' => ?int, 'max_qty' => ?int] for a product (max_qty defaults to the last tier's "to").
falcon_wholesale_min_orderfilterarray $minimum, Level $level, array $cartChange ['amount' => ?float, 'quantity' => ?int] for an order.

Applications and accounts โ€‹

HookTypeArgumentsWhen
falcon_wholesale_application_fieldsaction?WholesaleCustomer $accountInside the application form. Print extra fields here.
falcon_wholesale_application_rulesfilterarray $rules, Request $requestValidation rules for the form. Add your fields' rules.
falcon_wholesale_application_datafilterarray $data, Request $requestWhat is saved. Put extra fields under $data['meta']. They show on the customer screen.
falcon_wholesale_auto_approvefilterbool $approve, WholesaleCustomer $accountApprove some applications automatically (for example a verified BIN).
falcon_wholesale_application_submittedactionWholesaleCustomer $accountAn application was sent or sent again.
falcon_wholesale_customer_approvedactionWholesaleCustomer $accountAn account was approved.
falcon_wholesale_customer_rejectedactionWholesaleCustomer $account, ?string $reasonAn account was rejected or revoked.
falcon_wholesale_customer_level_changedactionWholesaleCustomer $account, ?int $oldLevelIdAn approved customer moved to another level.
php
// Ask for annual volume on the application.
add_falcon_action('falcon_wholesale_application_fields', function () {
    echo '<label>Annual volume <input name="annual_volume" type="number" required></label>';
});
add_falcon_filter('falcon_wholesale_application_rules', fn ($rules) => $rules + ['annual_volume' => 'required|integer|min:0']);
add_falcon_filter('falcon_wholesale_application_data', function ($data, $request) {
    $data['meta'] = ['annual_volume' => (int) $request->input('annual_volume')];
    return $data;
});

Screens โ€‹

HookTypeArgumentsUse it to
falcon_wholesale_price_notefilterstring $html, $post, array $dataChange or replace the note under the product price. $data holds label, level, savings, rules, variable.
falcon_wholesale_admin_customers_queryactionBuilder $query, Request $requestNarrow the admin customer list (for example an account manager's own customers).
falcon_wholesale_customer_fieldsactionWholesaleCustomer $accountAdd rows (<tr>) to the admin customer form.
falcon_wholesale_customer_savedactionWholesaleCustomer $account, Request $requestSave those rows.

Login, portal and private store โ€‹

HookTypeArgumentsUse it to
falcon_wholesale_portal_tabsfilterarray $tabsAdd a portal tab: [slug, label, lucide icon].
falcon_wholesale_portal_tab_contentactionstring $tab, WholesaleCustomer $accountPrint your tab's content.
falcon_wholesale_reorderedactionOrder $order, int $added, array $skippedAfter "Order again". $skipped holds the names of items that could not be added.
falcon_wholesale_company_updatedactionWholesaleCustomer $account, Request $requestThe customer saved their company details.
falcon_wholesale_login_form_afteractionโ€”Below the wholesale login form.
falcon_wholesale_login_urlfilterstring $url, ?string $redirectToChange where customers are sent to sign in (the login page, with redirect_to).
falcon_wholesale_private_store_allowsfilterbool $allowed, Request $request, string $modeOpen a page to everyone in private store mode, or close one.

Quick order and price import โ€‹

HookTypeArgumentsWhen
falcon_wholesale_quick_orderactionint $added, array $problemsAfter a quick order put lines in the cart.
falcon_wholesale_prices_importedactionarray $resultAfter a price sheet was imported (products, variations, unknown SKUs, errors).

Credit and invoices โ€‹

HookTypeArgumentsUse it to
falcon_wholesale_credit_availablefilter?float $available, WholesaleCustomer $accountChange the credit left (null = no limit).
falcon_wholesale_credit_allows_orderfiltertrue|string $verdict, WholesaleCustomer $account, float $totalAllow or refuse an order on account. A string is the message shown.
falcon_wholesale_credit_chargedactionCreditEntry $charge, Order $orderAn order was charged to the account.
falcon_wholesale_payment_recordedactionCreditEntry $payment, WholesaleCustomer $account, float $amountA payment was recorded. $payment is its first ledger line (a payment spread over several orders makes one line per order).
falcon_wholesale_invoice_datafilterarray $data, Order $orderChange what the invoice or challan shows (seller, footer, dueDate, owedโ€ฆ).

FalconWholesale\Support\Credit has balance(), available(), unpaid(), recordPayment() and adjust().

Emails โ€‹

Every wholesale email uses one layout (resources/views/emails/layout.blade.php): your Shop email header image, or your logo, or your shop name; your theme's primary colour; and the Shop email footer text. It works in the usual email clients and narrows for phones. A theme can override any email view under falcon-wholesale::emails.*.

Quotes, teams, SMS and reports โ€‹

HookTypeArgumentsWhen / use it to
falcon_wholesale_quote_requestedactionQuote $quoteA customer asked for a quote.
falcon_wholesale_quote_pricefilterfloat $price, array $item, Quote $quoteChange a quoted line price (for example rounding).
falcon_wholesale_quote_sentactionQuote $quoteThe shop sent the quote.
falcon_wholesale_quote_acceptedactionQuote $quoteThe customer accepted it (it is in their cart).
falcon_wholesale_quote_declinedactionQuote $quote, string $byDeclined by customer or shop.
falcon_wholesale_member_invited / _joined / _removedactionCompanyMember $memberTeam changes.
falcon_wholesale_send_smsfilter?bool $sent, string $to, string $messageSend through your own provider: return true or false. Leave null to use the HTTP provider.
falcon_wholesale_sms_messagefilterstring $message, string $event, array $contextChange the text (approved, order, payment, reminder, quote, manual, test), after the shop's own words are filled in.
falcon_wholesale_role_added / falcon_wholesale_role_removedactionint $userIdThe Wholesale Customer role was given or taken away.
falcon_wholesale_sms_sent_by_handactionWholesaleCustomer $account, string $message, bool $sentStaff texted a customer from their screen.
falcon_wholesale_reportfilterarray $report, Carbon $from, Carbon $toAdd figures to the report.

B2B checkout, approval, lists and reps โ€‹

HookTypeArgumentsWhen / use it to
falcon_wholesale_tier_quantityfilterint $quantity, int $postId, int $lineQuantity, array $cartThe cart quantity a line's tier is measured against (mix & match).
falcon_wholesale_payment_gatewaysfilterarray $gateways, Level $levelThe payment methods a level is offered, after its hidden ones are removed.
falcon_wholesale_shipping_methodsfilterarray $methods, Level $level, array $cartThe shipping methods a level is offered (free shipping applied).
falcon_wholesale_customer_pricefilter?float $price, int $postId, ?int $variationId, WholesaleCustomer $accountChange or supply a contract price.
falcon_wholesale_customer_price_savedactionWholesaleCustomer $account, int $postId, ?int $variationId, float $priceA contract price was saved.
falcon_wholesale_order_needs_approvalfilter?string $reason, ?CompanyMember $member, float $totalReturn a reason to hold an order for approval, or null.
falcon_wholesale_approval_requestedactionOrder $order, WholesaleCustomer $accountAn order went on hold for approval.
falcon_wholesale_order_approved / _declinedactionOrder $order, WholesaleCustomer $accountThe decision was made.
falcon_wholesale_list_savedactionSavedList $listA cart was saved as a list.
falcon_wholesale_deposit_gatewayfilterarray $gateway, Level $levelThe "Pay a deposit" method's title and text.
falcon_wholesale_deposit_received / falcon_wholesale_balance_receivedactionOrder $orderThe shop confirmed a payment.
falcon_wholesale_spend_discountfilter?array $rule, float $subtotal, Level $levelThe spend discount reached (['over', 'percent']), or null.
falcon_wholesale_tax_exemptfilterbool $exempt, ?WholesaleCustomer $accountDecide whether the shopper pays tax.
falcon_wholesale_rep_commissionfilterfloat $commission, array $orderData, object $repChange a rep's commission on an order.

In code โ€‹

Changes to an account should go through FalconWholesale\Support\Accounts (apply, approve, reject, setLevel), so the actions above fire and the emails go out. FalconWholesale\Support\Customers::currentLevel() tells you the signed-in shopper's level.

Shortcodes โ€‹

See Settings & Tools โ†’ Shortcodes.

Data โ€‹

TableWhat
wholesale_levelsLevels
wholesale_customersOne wholesale account per user: application, status, level
wholesale_product_rulesPer product: price per level and tiers (JSON), minimum quantity, pack size, visibility
wholesale_quotesQuote requests and quotes, with their lines (JSON)
wholesale_company_membersPeople who buy for a company besides its owner, and pending invitations
wholesale_credit_entriesEach customer's account: charges (+), payments, reversals and adjustments (โˆ’)
wholesale_price_indexWhat each level pays per product (min and max), for the price filter and sort
wholesale_category_discountsPer category and level: discount percent
wholesale_mix_categoriesCategories whose products count together for quantity tiers
wholesale_customer_pricesContract prices: account, product, variation (0 = every option), price
wholesale_saved_listsSaved lists: account, who saved it, name, items (JSON), reminder
wholesale_sales_repsSales reps: user, commission percent, whether they are emailed orders

Levels also hold hidden payment and shipping methods, free shipping from, deposit and spend discounts. Company members hold their approval rules (needs_approval, order_limit), and wholesale customers their tax exemption and sales rep. An order's meta records wholesale_approval, wholesale_deposit, wholesale_tax_exempt and wholesale_rep; the PO number is meta.checkout_fields.po_number.

Variation prices are stored on the variation row: shop_product_variations.meta.falcon_wholesale, keyed by level id. Settings are CMS options named wholesale_*.

Released under the MIT License.