=== NuxWP Devis – Quote Requests for WooCommerce ===
Contributors: kais1977
Tags: quote, request a quote, woocommerce, b2b, pdf quote
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.5.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Turn any WooCommerce cart into a quote request: price it, send the PDF, get paid. B2B quotes with thresholds, roles and a "My quotes" tab.

== Description ==

**NuxWP Devis** (*devis* is French for "quote") lets your customers build their cart as usual and, instead of paying, **ask for a quote** — with one button on the cart page.

Most quote plugins replace "Add to cart" and hide prices behind a separate "quote basket". NuxWP Devis does the opposite: the cart stays a cart, and becomes a quote only when the customer wants one. Perfect for B2B shops, wholesalers and any store where large baskets deserve a negotiated price.

= How it works =

1. The customer fills the cart and clicks **Request a quote** on the cart page.
2. A confirmation modal opens — with an optional message — and the request is sent. The cart is emptied, a **PDF quote** is generated, e-mails go out to the customer and to you.
3. In **WooCommerce → Quotes** you review the request, apply **line discounts** and/or a **global discount**, set the expiry date and change the status (*Pending → Quoted → Accepted*). The PDF is regenerated and the customer is notified at every step.
4. In **My Account → My quotes** the customer sees the quote, downloads the PDF and, once accepted, clicks **Accept and pay**: the quote is loaded back into the cart with the negotiated prices, the cart is **locked** (no quantity change, no coupon, no extra product) and goes to checkout.
5. The quote is marked **Ordered** once the order is paid / confirmed. Quotes expire automatically on their expiry date.

= For your customers =

* **Request a quote** button on the cart page — classic cart and **block cart** (WooCommerce Blocks slot)
* Optional **message** with the request
* **My quotes** tab in My Account: list, detail, status, PDF download, customer message
* **Accept and pay** on accepted quotes: frozen negotiated prices, locked cart, one-click checkout
* E-mails at every step: request received, priced, accepted, declined, expired, ordered (responsive HTML, PDF attached)

= For you =

* **WooCommerce → Quotes** dashboard: counters per status, search, filters, pending badge in the menu
* **Line discounts and a global discount**, exact tax computation with the real product tax rates for the customer, single rounding — no phantom cents
* **Expiry date**, status workflow, message to the customer, delete
* **Automatic PDF quote** (zero dependency) with your logo, company details, registration and VAT numbers, footer note
* **Who can request**: any logged-in customer or selected roles
* **Cart button styled from the settings**: filled / outline / text link, colours, hover, size, radius, full width, icon, live preview
* **Texts** settings: rewrite the phrases your customers see (cart, modal, My account, statuses, e-mails) without a translation plugin
* **EN / FR switch** for the admin screen (per user); other languages via translate.wordpress.org or Loco Translate
* HPOS compatible, no theme dependency, no external service, no tracking

= NuxWP Devis Pro (separate add-on) =

This plugin is complete and fully functional on its own. A separate, paid add-on adds: a quote button on **single product pages** and in **product grids**, **product rules** (categories, per-product "Quote" tab, quantity threshold), **out of stock → quote**, **customer file attachments** and an **ERP bridge** (Sage, Odoo, EBP…). Learn more at https://nuxwp.com/nuxwp-devis-pro.

== All settings ==

Everything is in **WooCommerce → Quotes → Settings**.

= Quote requests =

* **Show the "Request a quote" button on the cart page** — on/off. In the block cart the button is placed automatically in the totals area; the `[devisqr_button]` shortcode places it anywhere else.
* **Minimum cart total (incl. tax)** — 0 = no minimum. Computed on the products at catalog price including tax (shipping, fees and coupons are not part of a quote). Below the minimum the button stays locked and shows "From X".
* **Who can request a quote** — *Any logged-in customer* or *Only the selected roles* (role chips). Shop managers and administrators can always request. Guests are sent to the login page.
* **Quote validity (days)** — default 15. Printed on the PDF and in the e-mails; quotes past their date switch to *Expired* automatically (daily) and can no longer be paid.
* **Quote number prefix** — letters and digits, e.g. `QT` → `QT-202610-0001` (sequential per month).
* **Let the customer add a message to the request** — on/off.

= Cart button =

* **Position (classic cart)** — after the cart totals / before "Proceed to checkout" / after "Proceed to checkout" / top of the cart / manual (shortcode only).
* **Alignment** — left / center / right (on phones the cart button is always full width).
* **Button text** — default "Request a quote".
* **Style** — *Look* (filled / outline / text link), *Size* (small / medium / large), *Corner radius*, *Background*, *Text*, *Border*, *Hover background*, *Hover text*, *Full width*, *Show the icon*, with a live preview.

= Texts & translations =

Rewrite the essential phrases without a translation plugin (they apply to what customers see; back-office screens keep the original wording). Each field shows the current wording in grey; type yours to replace it (applies to PHP and JavaScript). Keep the `%s` placeholders where they appear. Groups: *Cart & quote request* (button label, minimum notice, modal title/text/fields/buttons, success message, locked-cart messages, contact link), *My account* (tab title, empty state, PDF button, pay button, back link, team message label), *Status labels*, *E-mails* (the three subjects, greeting, every sentence of the "request received" and status e-mails, button labels, footer line, shop notification title/button).

= E-mails & contact =

* **Notification e-mail(s) for new requests** — one or more addresses, comma-separated. Default: the site admin e-mail.
* **Sender e-mail (From)** — default: the WooCommerce sender address.
* **Contact e-mail shown to customers** — in e-mails and "contact us" links. Default: the site admin e-mail.
* **Contact page URL (optional)** — used for the "contact us" links instead of a mailto link.
* **Send me a test e-mail** — sends the "request received" e-mail with sample data to your own address, using the saved settings. Handy to check your SMTP setup and the rendering of your logo, colour and texts.

E-mails share one sober, responsive template: your logo (the one chosen in Company details & PDF, else the theme logo) or the site name, a thin accent rule, the message, a quote card (number, date, validity), the products and totals, one button, and your company details in the footer. The accent colour (default dark blue) can be changed with the `devisqr_email_accent_color` filter.

= Company details & PDF =

* **Logo (PDF & e-mails)** — PNG, JPEG, WebP, GIF or AVIF from the media library (no SVG); falls back to the theme's site logo. Non-PNG/JPEG files are converted once to PNG in `uploads/devisqr-branding/` so they print on the PDF and display in every e-mail client.
* **Company name, Address, Postcode, City, Phone, E-mail printed on the PDF, Company registration no., VAT number** — empty fields fall back to the site name and the WooCommerce store address.
* **Footer note on the PDF** — default "This document is a quote, not an invoice. Keep it for your records."

= Uninstall =

* **Delete all quotes, PDFs and settings when the plugin is deleted** — off by default. When on, deleting the plugin drops the two tables, the options, the rate-limit transients and the `uploads/devisqr-quotes` folder.

= Admin language =

At the top of **WooCommerce → Quotes**: **EN / FR** switch (per user) and a ↺ button to follow the site language again. The switch changes the admin screen, status labels and menu for this plugin only.

== Shortcodes ==

* `[devisqr_button]` — the cart quote button (respects the minimum, the roles and the locked-cart state). Useful in a block cart layout or a custom cart template.

== Developers ==

Actions: `devisqr_quote_created` (quote_id), `devisqr_quote_status_changed` (quote_id, status, old_status), `devisqr_quote_converted` (quote_id, order), `devisqr_before_delete_quote` (quote).

Filters: `devisqr_settings`, `devisqr_user_can_request` (bool, user), `devisqr_allowed_roles`, `devisqr_min_cart_total`, `devisqr_cart_button_hook` (hook, position), `devisqr_account_endpoint` (default `quotes`), `devisqr_pdf_company_info`, `devisqr_converting_order_statuses` (default processing, completed, on-hold), `devisqr_email_accent_color`, `devisqr_buttons_inline_css`.

REST namespace: `devisqr/v1` — customer routes (`/submit`, `/quotes`, `/quotes/{id}`, `/quotes/{id}/add-to-cart`) require a logged-in user; admin routes (`/admin/*`) require `manage_woocommerce`.

Data: tables `{prefix}devisqr_quotes` and `{prefix}devisqr_quote_items`; option `devisqr_settings`; files in `uploads/devisqr-quotes/` (unguessable names, `.htaccess` protected, served only through nonce-protected links to the owner or shop managers).

== Installation ==

1. Upload the plugin to `/wp-content/plugins/` or install it from the Plugins screen.
2. Activate it. WooCommerce must be active.
3. Go to **WooCommerce → Quotes → Settings**: minimum cart total, who can request, company details, PDF logo, buttons.

== Frequently Asked Questions ==

= Does it hide prices or replace "Add to cart"? =

No. NuxWP Devis keeps your shop working normally. Customers fill their cart and request a quote from the cart page. (Product-page buttons and the out-of-stock quote mode are part of the Pro add-on.)

= Can guests request a quote? =

Quotes are tied to a customer account so they can be followed up, accepted and paid. Guests are invited to log in or register.

= Does it work with the Cart block? =

Yes. The button is rendered inside the block cart's totals area. The `[devisqr_button]` shortcode remains available to place it anywhere else.

= How is the minimum cart total computed? =

On the products in the cart at catalog price, including tax — shipping, fees and coupons are not part of a quote.

= What happens when the customer pays an accepted quote? =

The quote lines are loaded into an empty cart at the negotiated prices (all or nothing: if a product is no longer available in the requested quantity, the customer is asked to contact you). The cart is locked; the order is placed normally; the quote becomes *Ordered* once the order is processing / completed / on hold (filterable). A failed or abandoned payment leaves the quote payable.

= Which languages does the PDF support? =

The built-in PDF generator supports Latin-script languages (English, French, Spanish, German, Italian, Portuguese…). The interface, e-mails and admin are fully translatable; English and French are included.

= Does it work with HPOS? =

Yes. The plugin declares compatibility with WooCommerce High-Performance Order Storage.

= Where are the PDFs stored? =

PDFs are stored in `wp-content/uploads/devisqr-quotes/` with unguessable file names, protected by `.htaccess` (Apache) and only served to the quote owner or shop managers through a nonce-protected link. On Nginx, add `location ~* /uploads/devisqr-quotes/ { deny all; }` to your server block.

= E-mails are not arriving =

The plugin uses `wp_mail()` like WooCommerce. If your site has no SMTP configured, install an SMTP plugin; the "Sender e-mail" setting must be an address your server is allowed to send from.

== Screenshots ==

1. The "Request a quote" button on the cart page
2. Confirmation modal with optional message
3. "My quotes" tab in My Account
4. Quote detail with "Accept and pay"
5. Admin dashboard: counters, filters, search
6. Admin quote detail: line and global discounts, expiry, status
7. Settings: cart button style editor with live preview
8. The generated PDF quote

== Changelog ==

= 1.5.2 =
* Removed the free-form "Custom CSS" field: the cart button is styled through the form fields of the style editor (colours, size, outline, icon).

= 1.5.1 =
* Renamed to NuxWP Devis. The cart button style editor is part of the free plugin. Translations now come from translate.wordpress.org.

= 1.5.0 =
* First public release on WordPress.org.
* Cart → quote request flow (classic cart and Cart block), minimum cart total, allowed roles, validity and automatic expiry, optional customer message.
* PDF quote (zero dependency) with your logo and company details; "My quotes" account tab; accept & pay in one click.
* Admin: quotes list with search and statuses, line editing and global discount, pending badge, EN / FR switch per user.
* E-mails: one sober responsive template, every sentence editable from Settings → Texts & translations, "Send me a test e-mail" button.
* Logo: PNG, JPEG, WebP, GIF or AVIF (converted to PNG for the PDF and e-mails).
